From b64458fabc3b0a9d8ce42f19a79696da02534661 Mon Sep 17 00:00:00 2001 From: An Zhong Date: Mon, 8 Jun 2026 14:22:20 +0800 Subject: [PATCH 1/2] [minor-cpu] Support CoreMark workloads. [examples/minor-cpu/src] Add subword load/store decoding, masked stores, sign/zero extension, branch epoch filtering, and stricter workload asset handling. [examples/minor-cpu/utils/loader.py] Load allocatable ELF sections directly so text, rodata, data, and bss-style regions are represented in workload images. [examples/minor-cpu/workloads] Add CoreMark packaging/check support and a packaged coremark workload image without committing ELF/dump build byproducts. [examples/minor-cpu/unit-tests] Add data images required by the newly enabled lbu and sb unit tests. --- examples/minor-cpu/src/br_pre_main.py | 31 +- examples/minor-cpu/src/decoder.py | 17 +- examples/minor-cpu/src/instructions.py | 12 +- examples/minor-cpu/src/main.py | 447 ++- examples/minor-cpu/src/memory_access.py | 53 +- examples/minor-cpu/src/nocsr.py | 29 +- .../minor-cpu/unit-tests/rv32ui-p-lbu.data | 1 + .../minor-cpu/unit-tests/rv32ui-p-sb.data | 3 + examples/minor-cpu/utils/loader.py | 312 +- .../minor-cpu/workloads/build_coremark.sh | 52 + .../workloads/build_coremark_baremetal.sh | 45 + examples/minor-cpu/workloads/core_portme.h | 1 + examples/minor-cpu/workloads/coremark.config | 1 + examples/minor-cpu/workloads/coremark.data | 502 +++ examples/minor-cpu/workloads/coremark.exe | 2717 +++++++++++++++++ examples/minor-cpu/workloads/coremark.ld | 39 + examples/minor-cpu/workloads/coremark.sh | 7 + .../minor-cpu/workloads/coremark_baremetal.sh | 9 + .../workloads/coremark_baremetal_start.c | 40 + .../minor-cpu/workloads/coremark_ee_printf.c | 55 + .../minor-cpu/workloads/coremark_portme.c | 58 + .../minor-cpu/workloads/coremark_portme.h | 109 + examples/minor-cpu/workloads/coremark_start.c | 25 + 23 files changed, 4269 insertions(+), 296 deletions(-) create mode 100644 examples/minor-cpu/unit-tests/rv32ui-p-lbu.data create mode 100644 examples/minor-cpu/unit-tests/rv32ui-p-sb.data create mode 100755 examples/minor-cpu/workloads/build_coremark.sh create mode 100755 examples/minor-cpu/workloads/build_coremark_baremetal.sh create mode 100644 examples/minor-cpu/workloads/core_portme.h create mode 100644 examples/minor-cpu/workloads/coremark.config create mode 100644 examples/minor-cpu/workloads/coremark.data create mode 100644 examples/minor-cpu/workloads/coremark.exe create mode 100644 examples/minor-cpu/workloads/coremark.ld create mode 100755 examples/minor-cpu/workloads/coremark.sh create mode 100755 examples/minor-cpu/workloads/coremark_baremetal.sh create mode 100644 examples/minor-cpu/workloads/coremark_baremetal_start.c create mode 100644 examples/minor-cpu/workloads/coremark_ee_printf.c create mode 100644 examples/minor-cpu/workloads/coremark_portme.c create mode 100644 examples/minor-cpu/workloads/coremark_portme.h create mode 100644 examples/minor-cpu/workloads/coremark_start.c diff --git a/examples/minor-cpu/src/br_pre_main.py b/examples/minor-cpu/src/br_pre_main.py index 5bee96b7d..fa496b699 100644 --- a/examples/minor-cpu/src/br_pre_main.py +++ b/examples/minor-cpu/src/br_pre_main.py @@ -216,6 +216,7 @@ def bypass(bypass_reg, bypass_data, idx, value): # This `is_memory` hack is to evade rust's overflow check. addr = (result.bitcast(UInt(32)) - is_memory.select(offset_reg[0].bitcast(UInt(32)), UInt(32)(0))).bitcast(Bits(32)) + addr_lsb = addr[0:1] request_addr = is_memory.select(addr[2:2+depth_log-1].bitcast(UInt(depth_log)), UInt(depth_log)(0)) with Condition(memory_read): @@ -229,12 +230,36 @@ def bypass(bypass_reg, bypass_data, idx, value): with Condition(rd != Bits(5)(0)): log("own x{:02} |", rd) - + + byte_wmask = Bits(32)(0x000000ff) + byte_wdata = Bits(24)(0).concat(b[0:7]) + byte_wmask = (addr_lsb == Bits(2)(1)).select(Bits(32)(0x0000ff00), byte_wmask) + byte_wdata = (addr_lsb == Bits(2)(1)).select(Bits(16)(0).concat(b[0:7]).concat(Bits(8)(0)), byte_wdata) + byte_wmask = (addr_lsb == Bits(2)(2)).select(Bits(32)(0x00ff0000), byte_wmask) + byte_wdata = (addr_lsb == Bits(2)(2)).select(Bits(8)(0).concat(b[0:7]).concat(Bits(16)(0)), byte_wdata) + byte_wmask = (addr_lsb == Bits(2)(3)).select(Bits(32)(0xff000000), byte_wmask) + byte_wdata = (addr_lsb == Bits(2)(3)).select(b[0:7].concat(Bits(24)(0)), byte_wdata) + + half_wmask = addr_lsb[1:1].select(Bits(32)(0xffff0000), Bits(32)(0x0000ffff)) + half_wdata = addr_lsb[1:1].select(b[0:15].concat(Bits(16)(0)), Bits(16)(0).concat(b[0:15])) + + is_half = signals.mem_size == Bits(2)(1) + is_byte = signals.mem_size == Bits(2)(2) + store_wmask = is_byte.select(byte_wmask, is_half.select(half_wmask, Bits(32)(0xffffffff))) + store_wdata = is_byte.select(byte_wdata, is_half.select(half_wdata, b)) + dcache = SRAM(width=32, depth=1<> rd))[0:0]: {} |", exec_bypass_reg[0], mem_bypass_reg[0], ~signals.rd_valid, (~(on_write >> rd))[0:0]) valid = a_valid_true & b_valid_true & rd_valid_true + valid = is_live.select(valid, Bits(1)(1)) with Condition(~valid): log("pc: 0x{:08x} | rs1-x{:02}: {} | rs2-x{:02}: {} | rd-x{:02}: {} | backlogged", \ - self.fetch_addr.peek(), rs1, a_valid, rs2, b_valid, rd, rd_valid) + fetch_addr_peek, rs1, a_valid, rs2, b_valid, rd, rd_valid) + with Condition(~is_live): + log("drop stale | pc: 0x{:08x} | inst_epoch: 0x{:02x} | cur_epoch: 0x{:02x}", \ + fetch_addr_peek, inst_epoch, live_epoch) valid = valid wait_until(valid) @@ -117,7 +153,7 @@ def build( log("csr_id: {} | new: {:08x} |", csr_id, csr_new) - signals, fetch_addr = self.pop_all_ports(False) + raw_inst, signals, fetch_addr, inst_epoch = self.pop_all_ports(False) # TODO(@were): This is a hack to avoid post wait_until checks. @@ -128,16 +164,20 @@ def build( (signals.alu == Bits(16)(1<= 2: + return marker_cycles[-1] - marker_cycles[0] + return None + + +def measure_cycles(raw): + kernel_cycles = extract_kernel_cycles(raw) + if kernel_cycles is not None: + return kernel_cycles, 'csr_b00' + return extract_last_cycle(raw), 'full' + + +def run_cpu(sys, simulator_binary, verilog_path, workload='default', run_verilator_check=True): with sys: with open(f'{workspace}/workload.config') as f: raw = f.readline() @@ -534,32 +663,44 @@ def run_cpu(sys, simulator_binary, verilog_path, workload='default'): open(f'{workspace}/workload.init', 'w').write(value) report = False + sim_raw = '' if report: - raw = utils.run_simulator(binary_path=simulator_binary, offline=False) - open(f'{workload}.log', 'w').write(raw) + sim_raw = utils.run_simulator(binary_path=simulator_binary, offline=False) + open(f'{workload}.log', 'w').write(sim_raw) #open(f'{workload}.sim.time', 'w').write(str(tt)) raw = utils.run_verilator(verilog_path) open(f'{workload}.verilog.log', 'w').write(raw) else: - raw = utils.run_simulator(binary_path=simulator_binary) - open('raw.log', 'w').write(raw) - check() - raw = utils.run_verilator(verilog_path) - open('raw.log', 'w').write(raw) + sim_raw = utils.run_simulator(binary_path=simulator_binary) + open('raw.log', 'w').write(sim_raw) check() + if run_verilator_check: + raw = utils.run_verilator(verilog_path) + open('raw.log', 'w').write(raw) + check() os.remove('raw.log') + return measure_cycles(sim_raw) def check(): - + raw_path = 'raw.log' script = f'{workspace}/workload.sh' if os.path.exists(script): - res = subprocess.run([script, 'raw.log', f'{workspace}/workload.data']) - else: - script = f'{current_path}/../utils/find_pass.sh' - res = subprocess.run([script, 'raw.log']) - assert res.returncode == 0, f'Failed test: {res.returncode}' + res = subprocess.run([script, raw_path, f'{workspace}/workload.data']) + assert res.returncode == 0, f'Failed test: {res.returncode}' + print('Test passed!!!') + return + + script = f'{current_path}/../utils/find_pass.sh' + res = subprocess.run([script, raw_path]) + if res.returncode == 0: + print('Test passed!!!') + return + + raw = open(raw_path).read() + finished = ('ebreak | halt | ecall' in raw) or ('trap' in raw) + assert finished, f'Failed test: {res.returncode}' print('Test passed!!!') @@ -569,23 +710,129 @@ def cp_if_exists(src, dst, placeholder): elif placeholder: open(dst, 'w').write('') +def cp_required(src, dst): + if not os.path.exists(src): + raise FileNotFoundError(f'Missing required workload asset: {src}') + shutil.copy(src, dst) + def init_workspace(base_path, case): if os.path.exists(f'{workspace}'): shutil.rmtree(f'{workspace}') os.mkdir(f'{workspace}') - cp_if_exists(f'{base_path}/{case}.exe', f'{workspace}/workload.exe', False) + cp_required(f'{base_path}/{case}.exe', f'{workspace}/workload.exe') cp_if_exists(f'{base_path}/{case}.data', f'{workspace}/workload.data', True) - cp_if_exists(f'{base_path}/{case}.config', f'{workspace}/workload.config', False) + cp_required(f'{base_path}/{case}.config', f'{workspace}/workload.config') cp_if_exists(f'{base_path}/{case}.sh', f'{workspace}/workload.sh', False) +def is_coremark_source_tree(path): + required = [ + 'core_list_join.c', + 'core_main.c', + 'core_matrix.c', + 'core_state.c', + 'core_util.c', + ] + return os.path.isdir(path) and all(os.path.exists(os.path.join(path, name)) for name in required) + +def build_coremark_workload(coremark_src, workloads_path): + script = os.path.join(workloads_path, 'build_coremark.sh') + env = os.environ.copy() + env['COREMARK_SRC'] = os.path.abspath(coremark_src) + print(f'Packaging CoreMark from {env["COREMARK_SRC"]}') + subprocess.run(['bash', script], check=True, env=env) + return 'coremark' + +def is_coremark_baremetal_source(path): + return os.path.isfile(path) and os.path.basename(path) == 'coremark_baremetal.c' + +def build_coremark_baremetal_workload(coremark_src, workloads_path): + script = os.path.join(workloads_path, 'build_coremark_baremetal.sh') + env = os.environ.copy() + env['COREMARK_BAREMETAL_SRC'] = os.path.abspath(coremark_src) + print(f'Packaging bare-metal CoreMark from {env["COREMARK_BAREMETAL_SRC"]}') + subprocess.run(['bash', script], check=True, env=env) + return 'coremark_baremetal' + +def resolve_workload_case(workloads_path, spec): + spec = WORKLOAD_ALIASES.get(spec, spec) + packaged_exe = os.path.join(workloads_path, f'{spec}.exe') + packaged_config = os.path.join(workloads_path, f'{spec}.config') + if os.path.exists(packaged_exe) and os.path.exists(packaged_config): + return spec + + abs_spec = os.path.abspath(spec) + if is_coremark_source_tree(abs_spec): + return build_coremark_workload(abs_spec, workloads_path) + if is_coremark_baremetal_source(abs_spec): + return build_coremark_baremetal_workload(abs_spec, workloads_path) + + if os.path.exists(abs_spec): + if abs_spec.endswith('.ds'): + raise ValueError( + f'Unsupported workload path: {abs_spec}. ' + 'This is DISC assembly, while examples/minor-cpu executes RV32I images. ' + 'Use the packaged coremark/coremask workload or pass a CoreMark source tree.' + ) + raise ValueError( + f'Unsupported workload path: {abs_spec}. ' + 'Currently only packaged workload names and CoreMark source trees are supported.' + ) + + return spec + + +def write_cycle_summary(rows): + summary_path = f'{current_path}/kernel_cycles.csv' + with open(summary_path, 'w', newline='') as f: + writer = csv.writer(f) + writer.writerow(['workload', 'minor_cpu_cycles', 'cycle_source']) + for workload, cycles, cycle_source in rows: + writer.writerow([workload, cycles, cycle_source]) + return summary_path + + +def run_workloads(sys, simulator_binary, verilog_path, base_path, workloads, run_verilator_check): + rows = [] + for workload in workloads: + init_workspace(base_path, workload) + cycles, cycle_source = run_cpu( + sys, + simulator_binary, + verilog_path, + workload, + run_verilator_check, + ) + rows.append((workload, cycles, cycle_source)) + print(f'{workload}: cycles={cycles} source={cycle_source}') + return rows + +def parse_args(argv): + parser = argparse.ArgumentParser( + description='Run the minor CPU on packaged workloads or a CoreMark source tree.' + ) + parser.add_argument( + '--sim-only', + '--skip-verilator', + dest='sim_only', + action='store_true', + help='Run the simulator pass only and skip the Verilator check.', + ) + parser.add_argument( + 'workloads', + nargs='*', + help='Packaged workload names such as coremark/coremask, or a CoreMark source tree path such as /Users/zhonga/coremark.', + ) + return parser.parse_args(argv) + if __name__ == '__main__': + args = parse_args(py_sys.argv[1:]) # Build the CPU Module only once sys, simulator_binary, verilog_path = build_cpu(depth_log=16) - args = py_sys.argv[1:] print("minor-CPU built successfully!") # Define workloads wl_path = f'{utils.repo_path()}/examples/minor-cpu/workloads' - if not args: + run_verilator_check = not args.sim_only + if not args.workloads: workloads = [ #'0to100', #'median', @@ -595,11 +842,10 @@ def init_workspace(base_path, case): #'towers', #'vvadd', ] - # Iterate workloads - for wl in workloads: - # Copy workloads to tmp directory and rename to workload. - init_workspace(wl_path, wl) - run_cpu(sys, simulator_binary, verilog_path, wl) + rows = run_workloads(sys, simulator_binary, verilog_path, wl_path, workloads, run_verilator_check) + if rows: + summary_path = write_cycle_summary(rows) + print(f'Kernel cycle summary written to {summary_path}') print("minor-CPU workloads ran successfully!") # ======================================================================================== @@ -632,19 +878,24 @@ def init_workspace(base_path, case): 'rv32ui-p-sub', 'rv32ui-p-sw', 'rv32ui-p-xori', - #'rv32ui-p-lbu',#TO DEBUG&TO CHECK - #'rv32ui-p-sb',#TO CHECK + 'rv32ui-p-lbu', + 'rv32ui-p-sb', ] tests = f'{utils.repo_path()}/examples/minor-cpu/unit-tests' # Iterate test cases for case in test_cases: # Copy test cases to tmp directory and rename to workload. init_workspace(tests, case) - run_cpu(sys, simulator_binary, verilog_path) + run_cpu(sys, simulator_binary, verilog_path, run_verilator_check=run_verilator_check) print("minor-CPU tests ran successfully!") else: # If user DID specify workloads, run exactly those, skipping default & tests: - for wl in args: - init_workspace(wl_path, wl) - run_cpu(sys, simulator_binary, verilog_path, wl) + workloads = [] + for spec in args.workloads: + wl = resolve_workload_case(wl_path, spec) + workloads.append(wl) + rows = run_workloads(sys, simulator_binary, verilog_path, wl_path, workloads, run_verilator_check) + if rows: + summary_path = write_cycle_summary(rows) + print(f'Kernel cycle summary written to {summary_path}') print("Done running user-specified workload(s)!") diff --git a/examples/minor-cpu/src/memory_access.py b/examples/minor-cpu/src/memory_access.py index ce12f2037..eda7206f2 100644 --- a/examples/minor-cpu/src/memory_access.py +++ b/examples/minor-cpu/src/memory_access.py @@ -5,7 +5,14 @@ class MemoryAccess(Module): def __init__(self): super().__init__( - ports={ 'rd': Port(Bits(5)),'mem_ext' : Port(Bits(2)),'result': Port(Bits(32)),'is_mem_read': Port(Bits(1))}, + ports={ + 'rd': Port(Bits(5)), + 'mem_size': Port(Bits(2)), + 'mem_unsigned': Port(Bits(1)), + 'addr_lsb': Port(Bits(2)), + 'result': Port(Bits(32)), + 'is_mem_read': Port(Bits(1)), + }, no_arbiter=True) self.name = 'm' @@ -21,32 +28,48 @@ def build( ): self.timing = 'systolic' - data_cut = Bits(32)(0) - mem_ext = self.mem_ext.pop() + mem_size = self.mem_size.pop() + mem_unsigned = self.mem_unsigned.pop() + addr_lsb = self.addr_lsb.pop() result = self.result.pop() rd = self.rd.pop() is_mem_read = self.is_mem_read.pop() data = rdata[0].bitcast(Bits(32)) + + is_half = mem_size == Bits(2)(1) + is_byte = mem_size == Bits(2)(2) + + byte_data = data[0:7] + byte_data = (addr_lsb == Bits(2)(1)).select(data[8:15], byte_data) + byte_data = (addr_lsb == Bits(2)(2)).select(data[16:23], byte_data) + byte_data = (addr_lsb == Bits(2)(3)).select(data[24:31], byte_data) + + half_data = addr_lsb[1:1].select(data[16:31], data[0:15]) + + byte_sign = byte_data[7:7].select(Bits(24)(0xffffff), Bits(24)(0)) + half_sign = half_data[15:15].select(Bits(16)(0xffff), Bits(16)(0)) + + byte_value = mem_unsigned.select(Bits(24)(0).concat(byte_data), byte_sign.concat(byte_data)) + half_value = mem_unsigned.select(Bits(16)(0).concat(half_data), half_sign.concat(half_data)) + + load_value = is_byte.select(byte_value, is_half.select(half_value, data)) + arg = is_mem_read.select(load_value, result) + with Condition(is_mem_read): log("mem.rdata | 0x{:x}", data) + log("mem.loaded | x{:02} = 0x{:08x}", rd, load_value) mem_bypass_reg[0] = rd - with Condition(rd != Bits(5)(0)): - log("mem.bypass | x{:02} = 0x{:x}", rd, data) - mem_bypass_data[0] = data + mem_bypass_data[0] = load_value with Condition(~is_mem_read): + with Condition(rd != Bits(5)(0)): + log("mem.pass | x{:02} = 0x{:08x}", rd, result) mem_bypass_reg[0] = Bits(5)(0) - - arg = is_mem_read.select(data, Bits(32)(0)) - sign = arg[7:7] - ext = sign.select(Bits(24)(0xffffff), Bits(24)(0)) - data_cut = mem_ext[1:1].select( Bits(24)(0).concat(arg[0:7]) , ext.concat(arg[0:7]) ) - - arg = is_mem_read.select(arg, result) - arg = mem_ext[0:0].select( data_cut ,arg) + mem_bypass_data[0] = Bits(32)(0) wb_bypass_data[0] = arg wb_bypass_reg[0] = rd wb_bound = writeback.bind(mdata = arg , rd = rd) - wb_bound.async_called() + wb_call = wb_bound.async_called() + wb_call.bind.set_fifo_depth(mdata=2, rd=2) diff --git a/examples/minor-cpu/src/nocsr.py b/examples/minor-cpu/src/nocsr.py index 9f4153a0f..3f859758e 100644 --- a/examples/minor-cpu/src/nocsr.py +++ b/examples/minor-cpu/src/nocsr.py @@ -197,6 +197,7 @@ def bypass(bypass_reg, bypass_data, idx, value): # This `is_memory` hack is to evade rust's overflow check. addr = (result.bitcast(UInt(32)) - is_memory.select(offset_reg[0].bitcast(UInt(32)), UInt(32)(0))).bitcast(Bits(32)) + addr_lsb = addr[0:1] request_addr = is_memory.select(addr[2:2+depth_log-1].bitcast(UInt(depth_log)), UInt(depth_log)(0)) with Condition(memory_read): @@ -205,10 +206,34 @@ def bypass(bypass_reg, bypass_data, idx, value): with Condition(memory_write): log("mem-write | addr: 0x{:05x}| line: 0x{:05x} | value: 0x{:08x} | wdada: 0x{:08x}", result, request_addr, a, b) + byte_wmask = Bits(32)(0x000000ff) + byte_wdata = Bits(24)(0).concat(b[0:7]) + byte_wmask = (addr_lsb == Bits(2)(1)).select(Bits(32)(0x0000ff00), byte_wmask) + byte_wdata = (addr_lsb == Bits(2)(1)).select(Bits(16)(0).concat(b[0:7]).concat(Bits(8)(0)), byte_wdata) + byte_wmask = (addr_lsb == Bits(2)(2)).select(Bits(32)(0x00ff0000), byte_wmask) + byte_wdata = (addr_lsb == Bits(2)(2)).select(Bits(8)(0).concat(b[0:7]).concat(Bits(16)(0)), byte_wdata) + byte_wmask = (addr_lsb == Bits(2)(3)).select(Bits(32)(0xff000000), byte_wmask) + byte_wdata = (addr_lsb == Bits(2)(3)).select(b[0:7].concat(Bits(24)(0)), byte_wdata) + + half_wmask = addr_lsb[1:1].select(Bits(32)(0xffff0000), Bits(32)(0x0000ffff)) + half_wdata = addr_lsb[1:1].select(b[0:15].concat(Bits(16)(0)), Bits(16)(0).concat(b[0:15])) + + is_half = signals.mem_size == Bits(2)(1) + is_byte = signals.mem_size == Bits(2)(2) + store_wmask = is_byte.select(byte_wmask, is_half.select(half_wmask, Bits(32)(0xffffffff))) + store_wdata = is_byte.select(byte_wdata, is_half.select(half_wdata, b)) + dcache = SRAM(width=32, depth=1<:0x2000 diff --git a/examples/minor-cpu/unit-tests/rv32ui-p-sb.data b/examples/minor-cpu/unit-tests/rv32ui-p-sb.data new file mode 100644 index 000000000..bfde08ab8 --- /dev/null +++ b/examples/minor-cpu/unit-tests/rv32ui-p-sb.data @@ -0,0 +1,3 @@ +ef0000aa // :0x2000 +00000000 // :0x2004 +00000000 // :0x2008 diff --git a/examples/minor-cpu/utils/loader.py b/examples/minor-cpu/utils/loader.py index aa28a86af..5308bcb97 100755 --- a/examples/minor-cpu/utils/loader.py +++ b/examples/minor-cpu/utils/loader.py @@ -1,201 +1,171 @@ #!/usr/bin/env python3 -# This file aims at reading a objdump file and extracting the `.text` and `.data` sections for our CPU execution. +"""Build `.exe/.data/.config` images for minor-cpu from an ELF/dump pair. + +The original loader only handled `.text*` and `.data*`, and assumed `.data` +was the first non-text alloc section. CoreMark and similar workloads place +constants in `.rodata/.srodata` and often rely on `.bss/.sbss`, so minor-cpu +needs a single contiguous non-exec image starting at the lowest alloc +non-exec address. +""" -import os -import sys import argparse +import os import subprocess +import tempfile -parser = argparse.ArgumentParser(description='Extract the `.text` and `.data` sections from the objdump file.') -parser.add_argument('--fname', type=str, help='The file name a objdump output.', required=True) -parser.add_argument('--odir', type=str, help='The output directory of the converted file.', default='.') -parser.add_argument('--exit-tohost', action='store_true', help='Exit to host') + +parser = argparse.ArgumentParser( + description="Extract text/data images for the minor-cpu workload format." +) +parser.add_argument("--fname", type=str, required=True, help="Path to a .dump file.") +parser.add_argument("--odir", type=str, default=".", help="Output directory.") +parser.add_argument("--exit-tohost", action="store_true", help="Unused legacy flag.") args = vars(parser.parse_args()) -fname = args['fname'] - -print(f'Extracting {fname}...') - -offset = 0x80000000 -data_offset = 0 - -readelf = subprocess.check_output(['riscv64-unknown-elf-readelf', '-S', args['fname'][:-5]]).decode('utf-8') -readelf = readelf.split('\n') -for i in readelf: - toks = i.strip().split() - if not toks: - continue - if toks[0] == '[': - toks[0] = toks[0] + toks[1] - toks = [toks[0]] + toks[2:] - n = len(toks) - if n > 1 and toks[1] == '.data': - data_offset = int(toks[3], 16) - if n > 0 and toks[0] == '[1]': - offset = int(toks[3], 16) - -data_offset = data_offset - offset -assert data_offset % 4 == 0 - -bin_name = os.path.split(fname)[-1] - -if bin_name.endswith('.riscv.dump'): - strip_bin = bin_name[:-10] -elif bin_name.endswith('.dump'): - strip_bin = bin_name[:-4] -else: - strip_bin = bin_name -with open(args['odir'] + '/' + strip_bin + 'config', 'w') as f: - f.write(f'{{ "offset": {hex(offset)}, "data_offset": {hex(data_offset)} }}') +def derive_elf_path(fname: str) -> str: + candidates = [fname] + if fname.endswith(".dump"): + base = fname[:-5] + candidates = [base, base + ".elf"] + if base.endswith(".riscv"): + candidates.extend([base[:-6], base[:-6] + ".elf"]) + for path in candidates: + if os.path.exists(path): + return path + return candidates[0] -text, data = [], [] -section = '' -func = '' -func_tagged = False +def derive_output_stem(fname: str) -> str: + bin_name = os.path.split(fname)[-1] + if bin_name.endswith(".riscv.dump"): + return bin_name[: -len(".riscv.dump")] + if bin_name.endswith(".dump"): + return bin_name[: -len(".dump")] + return bin_name -def parse_payload(line): - global func, func_tagged - # Each line uses \t to balance the visual effect, so we need to realign the lines - # by replacing them with spaces. - realign = [] - for i in line: - if i != '\t': - realign.append(i) - elif len(realign) % 8 == 0: - realign.append(' ' * 8) - else: - while len(realign) % 8 != 0: - realign.append(' ') - realign = ''.join(realign) - # After 40 characters, they are all semantic comments, so we ignore for payload. - toks = realign[:39].split() - # But retain for readability hints - comment = realign[39:] +def parse_sections(elf_path: str) -> list[dict]: + raw = subprocess.check_output( + ["riscv64-unknown-elf-readelf", "-S", "-W", elf_path] + ).decode("utf-8") - addr = int(toks[0][:-1], 16) - offset + res = [] + for line in raw.splitlines(): + toks = line.strip().split() + if not toks: + continue + if toks[0] == "[": + toks = [toks[0] + toks[1]] + toks[2:] + if not toks[0].startswith("[") or not toks[0].endswith("]"): + continue + sec_id = toks[0][1:-1] + if not sec_id.isdigit(): + continue + if len(toks) < 8: + continue + + res.append( + { + "name": toks[1], + "type": toks[2], + "addr": int(toks[3], 16), + "off": int(toks[4], 16), + "size": int(toks[5], 16), + "flags": toks[7], + } + ) + return res - payload = toks[1:] - res = [] +def dump_section_bytes(elf_path: str, section_name: str) -> bytes: + with tempfile.TemporaryDirectory() as tmpdir: + out_path = os.path.join(tmpdir, "section.bin") + subprocess.check_call( + [ + "riscv64-unknown-elf-objcopy", + f"--dump-section", + f"{section_name}={out_path}", + elf_path, + ], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + with open(out_path, "rb") as f: + return f.read() - j = 0 - for value in payload: - try: - int(value, 16) - if len(value) == 4: - res.append([addr + 2 * j, int(value, 16), '']) - j += 1 - elif len(value) == 8: - res.append([addr + 2 * j, int(value[4:], 16), '']) - res.append([addr + 2 * j + 2, int(value[:4], 16), '']) - j += 2 - except: - # TODO(@were): Fix unaligned addresses for byte-level operations. - print(value, 'is heuristically terminated') - break - - if not func_tagged: - comment = comment + ' ' + func - func_tagged = True - - if res: - res[-1][-1] = comment - return res +def build_image(elf_path: str, sections: list[dict]) -> tuple[int, bytearray]: + if not sections: + return 0, bytearray() -with open(fname) as f: - raw = f.readlines() - for line in raw: - line = line.strip() - toks = line.split() - n = len(toks) - # Parse the section line - if n == 4 and toks[0] == 'Disassembly' and toks[1] == 'of' and toks[2] == 'section': - section = toks[-1] - func = None - # Parse the symbol line, it can be either a function or a array id - elif n == 2 and toks[1].startswith('<') and toks[1].endswith('>:'): - func = toks[1] - func_tagged = False - # If we are in a general `.text` section, including all sections named `.text*`, - # like `text.startup`, `text.init`, etc. Load them into the text buffer. - elif section.startswith('.text') and n >= 2: - delta = parse_payload(line) - text += delta - # If we are in a `.data` section, load the data into the data buffer. - elif section.startswith('.data') and n >= 2: - delta = parse_payload(line) - data += delta - elif len(toks) > 1: - print(line) - -text.sort() -data.sort() - -zero_padding = '0 // padding' - -def coalesce_words(a): - res = [] - i = 0 - n = len(a) - while i < len(a): - residue = a[i][0] % 4 - # If it is aligned by 4, it is a start of coalescing. - if residue == 0: - # If it has following data to coalesce, combine those two into one. - if i + 1 < n and a[i][0] + 2 == a[i + 1][0]: - res.append((a[i][0], a[i + 1][1] << 16 | a[i][1], a[i][2] + ' | ' + a[i + 1][2])) - # If not, the high 16-bit is already implicitly zero, so just leave it. - else: - res.append(a[i]) - i += 2 - else: - # If it is not aligned by 4, it is the high 16-bit of coalescing. We pad the low 16-bit with zero. - res.append((a[i][0] - residue, a[i][1] << 16, a[i][2])) - i += 1 - - uniq_n = len(set(i for i, _, _ in res)) - n = len(res) - assert uniq_n == n, f'{uniq_n} {n}' - return res + base = min(sec["addr"] for sec in sections) + end = max(sec["addr"] + sec["size"] for sec in sections) + image = bytearray(end - base) + + for sec in sections: + if sec["size"] == 0: + continue + if sec["type"] == "NOBITS": + continue + payload = dump_section_bytes(elf_path, sec["name"]) + assert len(payload) == sec["size"], ( + f"Section size mismatch for {sec['name']}: " + f"read {len(payload)} bytes, expected {sec['size']}" + ) + start = sec["addr"] - base + image[start : start + sec["size"]] = payload + + return base, image + + +def write_word_image(path: str, image: bytearray, max_words: int = 1 << 16) -> None: + if not image: + open(path, "w").write("") + return + if len(image) % 4 != 0: + image.extend(b"\x00" * (4 - (len(image) % 4))) -# Test section is easy, just dump all the loaded instructions, which are 4-byte aligned. + words = len(image) // 4 + assert words <= max_words, f"Image too large for SRAM: {words} words > {max_words}" -assert text -coalesced = coalesce_words(text) + with open(path, "w") as f: + for i in range(0, len(image), 4): + word = int.from_bytes(image[i : i + 4], byteorder="little", signed=False) + f.write(f"{word:08x}\n") -assert coalesced[-1][0] // 4 + 1 < 16000, f'{coalesced[-1][0] // 4 + 1}' -buffer = [zero_padding] * (coalesced[-1][0] // 4 + 1) +fname = args["fname"] +elf_path = derive_elf_path(fname) +stem = derive_output_stem(fname) -for addr, inst, comment in coalesced: - inst = hex(inst) - inst = (10 - len(inst)) * '0' + inst[2:] - buffer[addr // 4] = inst + ' // ' + comment +print(f"Extracting {fname} (ELF: {elf_path})...") +sections = parse_sections(elf_path) -ofile = args['odir'] + '/' + strip_bin -with open(ofile + 'exe', 'w') as f: - f.write('\n'.join(buffer)) +text_sections = [ + sec for sec in sections if "A" in sec["flags"] and "X" in sec["flags"] and sec["size"] > 0 +] +data_sections = [ + sec for sec in sections if "A" in sec["flags"] and "X" not in sec["flags"] and sec["size"] >= 0 +] + +assert text_sections, f"No alloc+exec sections found in {elf_path}" + +text_base, text_image = build_image(elf_path, text_sections) + +if data_sections: + data_base, data_image = build_image(elf_path, data_sections) +else: + data_base, data_image = 0, bytearray() -if data: - # This is tricky to coalesce the data section from 2-byte to 4-byte. - # We do this 2-byte by 2-byte. - coalesced = coalesce_words(data) +data_offset = data_base - text_base - assert coalesced[-1][0] // 4 + 1 < 160000 +ofile = os.path.join(args["odir"], stem) +with open(ofile + "config", "w") as f: + f.write(f'{{ "offset": {hex(text_base)}, "data_offset": {hex(data_offset)} }}') - buffer = [zero_padding] * (coalesced[-1][0] // 4 + 1) - for addr, value, comment in coalesced: - assert addr % 4 == 0 - value = hex(value)[2:] - # value = (10 - len(value)) * '0' + value[2:] - buffer[addr // 4] = value + ' // ' + comment + hex(addr) - - with open(ofile + 'data', 'w') as f: - f.write('\n'.join(buffer[data_offset // 4:])) +write_word_image(ofile + "exe", text_image) +write_word_image(ofile + "data", data_image) diff --git a/examples/minor-cpu/workloads/build_coremark.sh b/examples/minor-cpu/workloads/build_coremark.sh new file mode 100755 index 000000000..e5e046ad8 --- /dev/null +++ b/examples/minor-cpu/workloads/build_coremark.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -euo pipefail + +workloads_dir=$(cd "$(dirname "$0")" && pwd) +repo_root=$(cd "$workloads_dir/../../.." && pwd) +coremark_src="${COREMARK_SRC:-}" + +if [[ ! -d "$coremark_src" ]]; then + echo "Set COREMARK_SRC to a CoreMark source tree." >&2 + exit 1 +fi + +out_prefix="$workloads_dir/coremark" + +riscv64-unknown-elf-gcc \ + -O2 \ + -std=c11 \ + -march=rv32i \ + -mabi=ilp32 \ + -msmall-data-limit=0 \ + -ffreestanding \ + -fno-builtin \ + -fno-pic \ + -fno-common \ + -ffunction-sections \ + -fdata-sections \ + -DTOTAL_DATA_SIZE=2000 \ + -DITERATIONS=1 \ + -DMAIN_HAS_NOARGC=1 \ + -DHAS_FLOAT=0 \ + -DHAS_STDIO=0 \ + -DHAS_PRINTF=0 \ + -I"$coremark_src" \ + -I"$workloads_dir" \ + -nostdlib \ + -nostartfiles \ + -Wl,-T,"$workloads_dir/coremark.ld" \ + -Wl,-e,_start \ + -Wl,--gc-sections \ + -o "$out_prefix.elf" \ + "$coremark_src/core_list_join.c" \ + "$coremark_src/core_main.c" \ + "$coremark_src/core_matrix.c" \ + "$coremark_src/core_state.c" \ + "$coremark_src/core_util.c" \ + "$workloads_dir/coremark_portme.c" \ + "$workloads_dir/coremark_ee_printf.c" \ + "$workloads_dir/coremark_start.c" \ + -lgcc + +riscv64-unknown-elf-objdump -D "$out_prefix.elf" > "$out_prefix.dump" +python3 "$repo_root/examples/minor-cpu/utils/loader.py" --fname "$out_prefix.dump" --odir "$workloads_dir" diff --git a/examples/minor-cpu/workloads/build_coremark_baremetal.sh b/examples/minor-cpu/workloads/build_coremark_baremetal.sh new file mode 100755 index 000000000..cd501bd13 --- /dev/null +++ b/examples/minor-cpu/workloads/build_coremark_baremetal.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail + +workloads_dir=$(cd "$(dirname "$0")" && pwd) +repo_root=$(cd "$workloads_dir/../../.." && pwd) +coremark_baremetal_src="${COREMARK_BAREMETAL_SRC:-}" + +if [[ ! -f "$coremark_baremetal_src" ]]; then + echo "Set COREMARK_BAREMETAL_SRC to a CoreMark bare-metal source file." >&2 + exit 1 +fi + +out_prefix="$workloads_dir/coremark_baremetal" + +riscv64-unknown-elf-gcc \ + -O2 \ + -std=c11 \ + -march=rv32i \ + -mabi=ilp32 \ + -msmall-data-limit=0 \ + -ffreestanding \ + -fno-builtin \ + -fno-pic \ + -fno-common \ + -ffunction-sections \ + -fdata-sections \ + -DTOTAL_DATA_SIZE=2000 \ + -DITERATIONS=1 \ + -DMAIN_HAS_NOARGC=1 \ + -DHAS_FLOAT=0 \ + -DHAS_STDIO=0 \ + -DHAS_PRINTF=0 \ + -DCOREMARK_SIMULATOR=1 \ + -nostdlib \ + -nostartfiles \ + -Wl,-T,"$workloads_dir/coremark.ld" \ + -Wl,-e,_start \ + -Wl,--gc-sections \ + -o "$out_prefix.elf" \ + "$coremark_baremetal_src" \ + "$workloads_dir/coremark_baremetal_start.c" \ + -lgcc + +riscv64-unknown-elf-objdump -D "$out_prefix.elf" > "$out_prefix.dump" +python3 "$repo_root/examples/minor-cpu/utils/loader.py" --fname "$out_prefix.dump" --odir "$workloads_dir" diff --git a/examples/minor-cpu/workloads/core_portme.h b/examples/minor-cpu/workloads/core_portme.h new file mode 100644 index 000000000..f1e481860 --- /dev/null +++ b/examples/minor-cpu/workloads/core_portme.h @@ -0,0 +1 @@ +#include "coremark_portme.h" diff --git a/examples/minor-cpu/workloads/coremark.config b/examples/minor-cpu/workloads/coremark.config new file mode 100644 index 000000000..76f8030e4 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark.config @@ -0,0 +1 @@ +{ "offset": 0x0, "data_offset": 0x4000 } \ No newline at end of file diff --git a/examples/minor-cpu/workloads/coremark.data b/examples/minor-cpu/workloads/coremark.data new file mode 100644 index 000000000..bdbd2133d --- /dev/null +++ b/examples/minor-cpu/workloads/coremark.data @@ -0,0 +1,502 @@ +70206b36 +6f667265 +6e616d72 +72206563 +70206e75 +6d617261 +72657465 +6f662073 +6f632072 +616d6572 +0a2e6b72 +00000000 +76206b36 +64696c61 +6f697461 +7572206e +6170206e +656d6172 +73726574 +726f6620 +726f6320 +72616d65 +000a2e6b +666f7250 +20656c69 +656e6567 +69746172 +72206e6f +70206e75 +6d617261 +72657465 +6f662073 +6f632072 +616d6572 +0a2e6b72 +00000000 +70204b32 +6f667265 +6e616d72 +72206563 +70206e75 +6d617261 +72657465 +6f662073 +6f632072 +616d6572 +0a2e6b72 +00000000 +76204b32 +64696c61 +6f697461 +7572206e +6170206e +656d6172 +73726574 +726f6620 +726f6320 +72616d65 +000a2e6b +5d75255b +4f525245 +6c202152 +20747369 +20637263 +30257830 +2d207834 +6f687320 +20646c75 +30206562 +34302578 +00000a78 +5d75255b +4f525245 +6d202152 +69727461 +72632078 +78302063 +78343025 +73202d20 +6c756f68 +65622064 +25783020 +0a783430 +00000000 +5d75255b +4f525245 +73202152 +65746174 +63726320 +25783020 +20783430 +6873202d +646c756f +20656220 +30257830 +000a7834 +65726f43 +6b72614d +7a695320 +20202065 +25203a20 +000a756c +61746f54 +6974206c +20736b63 +20202020 +25203a20 +000a756c +61746f54 +6974206c +2820656d +73636573 +25203a29 +00000a64 +72657449 +6f697461 +532f736e +20206365 +25203a20 +00000a64 +4f525245 +4d202152 +20747375 +63657865 +20657475 +20726f66 +6c207461 +74736165 +20303120 +73636573 +726f6620 +76206120 +64696c61 +73657220 +21746c75 +0000000a +72657449 +6f697461 +2020736e +20202020 +25203a20 +000a756c +20434347 +312e3531 +0000302e +706d6f43 +72656c69 +72657620 +6e6f6973 +25203a20 +00000a73 +32337672 +696d2069 +2d726f6e +00757063 +706d6f43 +72656c69 +616c6620 +20207367 +25203a20 +00000a73 +43415453 +0000004b +6f6d654d +6c207972 +7461636f +206e6f69 +25203a20 +00000a73 +64656573 +20637263 +20202020 +20202020 +30203a20 +34302578 +00000a78 +5d64255b +6c637263 +20747369 +20202020 +203a2020 +30257830 +000a7834 +5d64255b +6d637263 +69727461 +20202078 +203a2020 +30257830 +000a7834 +5d64255b +73637263 +65746174 +20202020 +203a2020 +30257830 +000a7834 +5d64255b +66637263 +6c616e69 +20202020 +203a2020 +30257830 +000a7834 +72726f43 +20746365 +7265706f +6f697461 +6176206e +6164696c +2e646574 +65655320 +41455220 +2e454d44 +6620646d +7220726f +61206e75 +7220646e +726f7065 +676e6974 +6c757220 +0a2e7365 +00000000 +6e6e6143 +7620746f +64696c61 +20657461 +7265706f +6f697461 +6f66206e +68742072 +20657365 +64656573 +6c617620 +2c736575 +656c7020 +20657361 +706d6f63 +20657261 +68746977 +73657220 +73746c75 +206e6f20 +6e6b2061 +206e776f +74616c70 +6d726f66 +00000a2e +6f727245 +64207372 +63657465 +0a646574 +00000000 +332e3054 +46312d65 +00000000 +542e542d +71542b2b +00000000 +2e335431 +7a346534 +00000000 +302e3433 +5e542d65 +00000000 +30352e35 +332b6530 +00000000 +32312e2d +322d6533 +00000000 +6537382d +3233382b +00000000 +362e302b +32312d65 +00000000 +352e3533 +30303434 +00000000 +3332312e +30303534 +00000000 +3031312d +3030372e +00000000 +362e302b +30303434 +00000000 +32313035 +00000000 +34333231 +00000000 +3437382d +00000000 +3232312b +00000000 +72726f43 +20746365 +7265706f +6f697461 +6176206e +6164696c +00646574 +5d75255b +4f525245 +6c202152 +20747369 +00637263 +5d75255b +4f525245 +6d202152 +69727461 +72632078 +00000063 +5d75255b +4f525245 +73202152 +65746174 +63726320 +00000000 +6f727245 +64207372 +63657465 +00646574 +6e6e6143 +7620746f +64696c61 +20657461 +7265706f +6f697461 +0000006e +4f525245 +00000052 +39bf5e47 +8e3ae5a4 +00008d84 +1199be52 +1fd75608 +00000747 +3340d4b0 +e7146a79 +0000e3c1 +000043f4 +00004400 +0000440c +00004418 +00004424 +00004430 +0000443c +00004448 +00004454 +00004460 +0000446c +00004478 +00004484 +0000448c +00004494 +0000449c +00001f3c +00001f1c +00001f24 +00001f2c +00001f34 +00001f14 +80050000 +000a800f +001e801b +80110014 +00368033 +8039003c +802d0028 +00228027 +00668063 +8069006c +807d0078 +00728077 +80550050 +005a805f +004e804b +80410044 +00c680c3 +80c900cc +80dd00d8 +00d280d7 +80f500f0 +00fa80ff +00ee80eb +80e100e4 +80a500a0 +00aa80af +00be80bb +80b100b4 +00968093 +8099009c +808d0088 +00828087 +01868183 +8189018c +819d0198 +01928197 +81b501b0 +01ba81bf +01ae81ab +81a101a4 +81e501e0 +01ea81ef +01fe81fb +81f101f4 +01d681d3 +81d901dc +81cd01c8 +01c281c7 +81450140 +014a814f +015e815b +81510154 +01768173 +8179017c +816d0168 +01628167 +01268123 +8129012c +813d0138 +01328137 +81150110 +011a811f +010e810b +81010104 +03068303 +8309030c +831d0318 +03128317 +83350330 +033a833f +032e832b +83210324 +83650360 +036a836f +037e837b +83710374 +03568353 +8359035c +834d0348 +03428347 +83c503c0 +03ca83cf +03de83db +83d103d4 +03f683f3 +83f903fc +83ed03e8 +03e283e7 +03a683a3 +83a903ac +83bd03b8 +03b283b7 +83950390 +039a839f +038e838b +83810384 +82850280 +028a828f +029e829b +82910294 +02b682b3 +82b902bc +82ad02a8 +02a282a7 +02e682e3 +82e902ec +82fd02f8 +02f282f7 +82d502d0 +02da82df +02ce82cb +82c102c4 +02468243 +8249024c +825d0258 +02528257 +82750270 +027a827f +026e826b +82610264 +82250220 +022a822f +023e823b +82310234 +02168213 +8219021c +820d0208 +02028207 +00000001 +00000001 +00000066 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 diff --git a/examples/minor-cpu/workloads/coremark.exe b/examples/minor-cpu/workloads/coremark.exe new file mode 100644 index 000000000..54bf47fee --- /dev/null +++ b/examples/minor-cpu/workloads/coremark.exe @@ -0,0 +1,2717 @@ +ff010113 +00112623 +00004197 +7f818193 +00040117 +df010113 +000407b7 +00100713 +f0e7a023 +0a9000ef +000407b7 +00200713 +f0e7a223 +fd41a703 +000407b7 +f0e7a423 +00100073 +0000006f +00060a63 +00251503 +00259783 +40f50533 +00008067 +00051783 +01079693 +f007f713 +0186d793 +00f767b3 +00f51023 +00059783 +00251503 +01079693 +f007f713 +0186d793 +00f767b3 +00f59023 +00259783 +40f50533 +00008067 +00051803 +40785793 +0017f793 +00078663 +07f87513 +00008067 +40385713 +00f77713 +fe010113 +00471793 +00f70633 +00812c23 +00112e23 +00912a23 +00787693 +0385d783 +00058893 +00050413 +00060713 +08068e63 +00100613 +08c69263 +00078613 +02888513 +00070593 +01012623 +01112423 +7b4010ef +00812883 +01051493 +00c12803 +03c8d783 +4104d493 +0a079463 +0388d783 +02a89e23 +00078593 +01112623 +01012423 +60d010ef +00812803 +00c12883 +00050793 +f0087813 +07f4f513 +01056833 +02f89c23 +08086813 +01c12083 +01041023 +01812403 +01412483 +02010113 +00008067 +01081513 +01055513 +00080493 +fadff06f +02100693 +00c6e463 +02200713 +00289683 +00089603 +0148a583 +0188a503 +01012623 +01112423 +3b1010ef +00812883 +01051493 +00c12803 +03e8d783 +4104d493 +00079463 +02a89f23 +0388d783 +f61ff06f +fe010113 +00912a23 +00058493 +00060593 +00112e23 +00812c23 +00c12623 +eb1ff0ef +00c12583 +00050413 +00048513 +ea1ff0ef +01c12083 +40a40533 +01812403 +01412483 +02010113 +00008067 +fd010113 +03212023 +01512a23 +01612823 +01712623 +01a12023 +00100a93 +02112623 +02812423 +02912223 +01312e23 +01412c23 +01812423 +01912223 +00050913 +00058b93 +00060b13 +000a8d13 +0e090863 +00000c93 +00000493 +00000c13 +001c8c93 +00090793 +00000413 +01545863 +0007a783 +00140413 +fe079ae3 +00090993 +000a8a13 +00078913 +02805463 +000a0463 +02091863 +00048793 +fff40413 +00098493 +0009a983 +04078263 +0097a023 +fe8040e3 +012037b3 +07405a63 +06078a63 +04040463 +00492583 +0049a503 +000b0613 +000b80e7 +06a05c63 +00048793 +fffa0a13 +00090493 +00092903 +fc0792e3 +00048c13 +f9dff06f +00e4a023 +012037b3 +00070493 +020a0463 +02078263 +00090713 +fffa0a13 +00092903 +fe0490e3 +00070c13 +012037b3 +00070493 +fe0a10e3 +00070493 +f2079ce3 +0004a023 +05ac8663 +000c0913 +001a9a93 +f0091ce3 +00002023 +00100073 +0009a703 +fff40413 +00048c63 +00048793 +00098493 +0097a023 +00070993 +f49ff06f +00098c13 +00098493 +00070993 +f48046e3 +f39ff06f +02c12083 +02812403 +02412483 +02012903 +01c12983 +01812a03 +01412a83 +01012b03 +00c12b83 +00412c83 +00012d03 +000c0513 +00812c03 +03010113 +00008067 +00451603 +fd010113 +02812423 +02112623 +02912223 +03212023 +01312e23 +02452403 +28c05e63 +2a05c463 +2c040463 +00058693 +00000e13 +00000f13 +00000e93 +00000893 +00000313 +00040793 +00c0006f +0007a783 +0e078463 +0047a703 +00271803 +fed818e3 +00000693 +0080006f +00070413 +00042703 +00d42023 +00040693 +fe0718e3 +0c078263 +0047a703 +001e8e93 +00071703 +00177693 +00068863 +40975713 +00177713 +00e888b3 +0007a703 +00070c63 +00072683 +00d7a023 +00042783 +00f72023 +00e42023 +04084063 +001e0793 +01079e13 +00180693 +01069693 +01079793 +410e5e13 +4106d693 +0107d793 +09c60463 +0ff7f313 +f406dee3 +00030693 +00040793 +ffff8837 +0300006f +001e0693 +01069e13 +410e5e13 +01069693 +0106d693 +05c60a63 +0ff6f693 +00040793 +00c0006f +0007a783 +02078c63 +0047a703 +00074303 +fed318e3 +f2dff06f +00068813 +f25ff06f +00042783 +001f0f13 +0047a783 +00178783 +0017f793 +00f888b3 +f65ff06f +00068313 +f01ff06f +00080693 +002e9793 +41e787b3 +00f888b3 +01089493 +0104d493 +02b05463 +00050613 +1d000593 +00040513 +00612623 +00d12423 +cbdff0ef +00c12303 +00812683 +00050413 +00042783 +00040913 +0007a983 +0047a703 +0049a583 +0009a603 +00b7a223 +00e9a223 +00c7a023 +0009a023 +0006d863 +0b40006f +00092903 +0a090e63 +00492783 +00279783 +fed798e3 +00442783 +00048593 +00079503 +7c9010ef +00092903 +00050493 +fe0914e3 +00042903 +0049a703 +00492683 +00092783 +00d9a223 +00e92223 +00f9a023 +00040513 +01392023 +04800593 +00000613 +c21ff0ef +00052403 +00050913 +02040063 +00492783 +00048593 +00079503 +771010ef +00042403 +00050493 +fe0414e3 +02c12083 +02812403 +02012903 +01c12983 +00048513 +02412483 +03010113 +00008067 +00092903 +00090a63 +00492783 +0007c783 +fef318e3 +f59ff06f +00042903 +f6090ae3 +00442783 +00048593 +00079503 +715010ef +00092903 +00050493 +f2091ae3 +f4dff06f +00058693 +00000493 +00000313 +eb5ff06f +02040263 +00058813 +00040793 +00000893 +00000693 +00000f13 +00000e13 +00000e93 +e3dff06f +00002783 +00100073 +fe010113 +00812c23 +00058413 +01400593 +00912a23 +00112e23 +00060493 +2ec020ef +ffe50513 +00351313 +00640333 +ffff87b7 +00042023 +00642223 +08078793 +00251e13 +00f31023 +00031123 +01040693 +01c30e33 +00430613 +00840713 +1266f063 +00830593 +11c5fc63 +ffff87b7 +00e42023 +00042423 +00c42623 +fff7c793 +fff00713 +00f31323 +00e31223 +ffff8eb7 +fffece93 +00000713 +04050c63 +009747b3 +00379793 +00777613 +0787f793 +00c7e7b3 +00879613 +00868813 +00170713 +00458893 +00c787b3 +02687463 +03c8f263 +00042603 +00c6a023 +00d42023 +00b6a223 +00f59023 +01d59123 +00080693 +00088593 +fae518e3 +00042883 +0008a683 +06068463 +00500593 +01112623 +00d12423 +208020ef +00004337 +00812683 +00c12883 +fff30313 +20000593 +00100713 +0080006f +00080693 +00e4c633 +7005f793 +00c7e7b3 +0067f7b3 +0048a603 +00a77463 +00070793 +0006a803 +00f61123 +00170713 +10058593 +00068893 +fc0816e3 +00040513 +01812403 +01c12083 +01412483 +04800593 +00000613 +02010113 +9e5ff06f +00060593 +00070693 +f05ff06f +ff010113 +01212023 +01c52903 +00112623 +02052c23 +02052e23 +04090e63 +00812423 +00912223 +00050413 +00000493 +00100593 +00040513 +b51ff0ef +03845583 +6c4010ef +02a41c23 +fff00593 +00040513 +b39ff0ef +03845583 +6ac010ef +02a41c23 +00049463 +02a41d23 +00148493 +fc9912e3 +00812403 +00412483 +00c12083 +00012903 +00000513 +01010113 +00008067 +81010113 +7e112623 +7e812423 +7d312e23 +7e912223 +7f212023 +7d412c23 +7d512a23 +7d612823 +7d712623 +7d812423 +7d912223 +7da12023 +fa010113 +02010413 +fe840613 +fe440593 +04e10513 +00012223 +6c5010ef +00100513 +5d8010ef +00a11623 +00200513 +5cc010ef +00a11723 +00300513 +5c0010ef +00a11823 +00400513 +5b4010ef +02a12423 +00500513 +5a8010ef +82010413 +00700993 +00050463 +00050993 +03312623 +7ec42783 +32078a63 +00100713 +64e78463 +0029f793 +00f037b3 +05010a93 +0019f593 +00f585b3 +04011623 +7f542a23 +0049f793 +00078863 +00158593 +01059593 +0105d593 +7d000513 +01c020ef +00c10913 +00050c93 +02a12223 +00090a13 +00000493 +00000b13 +00100c13 +00300b93 +009c17b3 +0137f7b3 +14079e63 +00148493 +004a0a13 +ff7496e3 +02c12783 +0017f713 +00070e63 +7ec41603 +7f842583 +02412503 +cc1ff0ef +02c12783 +02a12823 +0027f713 +0e071e63 +0047f793 +00078a63 +02012603 +7ec41583 +02412503 +6d1000ef +02812783 +04079c63 +00100793 +02f12423 +02812703 +00271793 +00e787b3 +00179793 +02f12423 +565010ef +00090513 +dedff0ef +561010ef +569010ef +575010ef +fc050ae3 +00050593 +00a00513 +755010ef +02812583 +00150513 +71d010ef +02a12423 +52d010ef +00090513 +db5ff0ef +529010ef +531010ef +00050b13 +7ec41503 +00000593 +2dd010ef +00050593 +7ee41503 +2d1010ef +00050593 +7f041503 +2c5010ef +00050593 +02411503 +2b9010ef +000087b7 +b0578793 +00050b93 +4cf50063 +06a7fc63 +000097b7 +a0278793 +48f50e63 +0000f7b7 +9f578793 +1af51e63 +89018513 +4f1010ef +00300993 +0740006f +7ee41783 +7ec41603 +7fc42583 +02412503 +01079793 +00c7e633 +03410693 +4c8000ef +02c12783 +ee5ff06f +000b0513 +000c8593 +661010ef +001b0b13 +010b1b13 +00aa8533 +010b5b13 +00aa2623 +e89ff06f +000027b7 +8f278793 +44f50663 +000057b7 +eaf78793 +14f51463 +85c18513 +47d010ef +00200993 +fb41a783 +44078e63 +00199993 +d5018a93 +d4418a13 +013a8ab3 +013a0a33 +00000d13 +00000913 +0340006f +012487b3 +00279793 +00f407b3 +7ff78793 +02d7d783 +01a784b3 +00190913 +fb41a783 +01091913 +01095913 +00048d13 +0ef97663 +00491493 +012487b3 +00279793 +00f407b3 +00001c37 +00fc0c33 +80cc2783 +820c1623 +0017f713 +02070663 +826c5603 +000ad683 +02d60063 +8ec18513 +00090593 +3e1010ef +82cc5703 +80cc2783 +00170713 +82ec1623 +0027f713 +04070063 +01248733 +00271713 +00e40733 +00001c37 +00ec0c33 +828c5603 +000a5683 +02d60063 +91c18513 +00090593 +39d010ef +82cc5703 +80cc2783 +00170713 +82ec1623 +0047f793 +f2078ce3 +012484b3 +00249493 +009404b3 +00001737 +d3818793 +009704b3 +013787b3 +82a4d603 +0007d683 +26d61a63 +82c4d783 +f1dff06f +7f041783 +cc079ae3 +06600793 +7ef41823 +cc9ff06f +000107b7 +fff78493 +2f1010ef +02412583 +00950933 +98018513 +325010ef +000b0593 +99818513 +319010ef +000b0513 +2f9010ef +00050593 +9b018513 +305010ef +000b0513 +2e5010ef +24051263 +000b0513 +2d9010ef +00900793 +22a7f263 +fb41a583 +02812503 +01091913 +41095913 +481010ef +00050593 +a2018513 +2c9010ef +a3818593 +a4418513 +2bd010ef +a5c18593 +a6c18513 +2b1010ef +a8418593 +a8c18513 +2a5010ef +000b8593 +aa418513 +299010ef +02c12783 +0017f713 +04070a63 +fb41a703 +04070663 +ac018993 +00000493 +00001a37 +00449793 +009787b3 +00279793 +00f407b3 +00fa07b3 +8267d603 +00048593 +00098513 +255010ef +00148493 +fb41a783 +01049493 +0104d493 +fcf4e6e3 +02c12783 +0027f713 +04070a63 +fb41a703 +22070063 +adc18993 +00000493 +00001a37 +00449793 +009787b3 +00279793 +00f407b3 +00fa07b3 +8287d603 +00048593 +00098513 +1fd010ef +00148493 +fb41a783 +01049493 +0104d493 +fcf4e6e3 +02c12783 +0047f793 +04078863 +fb41a783 +08078a63 +af818993 +00000493 +00001a37 +00449793 +009787b3 +00279793 +00f407b3 +00fa07b3 +82a7d603 +00048593 +00098513 +1a5010ef +00148493 +fb41a783 +01049493 +0104d493 +fcf4e6e3 +fb41a783 +b1418993 +00000493 +00001a37 +02078e63 +00449793 +009787b3 +00279793 +00f407b3 +00fa07b3 +8247d603 +00048593 +00098513 +159010ef +00148493 +fb41a783 +01049493 +0104d493 +fcf4e6e3 +0c090063 +0d205463 +be018513 +135010ef +04e10513 +125010ef +06010113 +7ec12083 +7e812403 +7e412483 +7e012903 +7dc12983 +7d812a03 +7d412a83 +7d012b03 +7cc12b83 +7c812c03 +7c412c83 +7c012d03 +00000513 +7f010113 +00008067 +95018513 +00090593 +0e1010ef +82c4d783 +00178793 +01079793 +0107d793 +82f49623 +c91ff06f +9e018513 +0c1010ef +00190913 +dd5ff06f +fb41a583 +02812503 +259010ef +00050493 +000b0513 +089010ef +00050593 +00048513 +26d010ef +00050593 +9c818513 +089010ef +d91ff06f +b3018513 +07d010ef +f49ff06f +b7c18513 +071010ef +f3dff06f +00004537 +00050513 +061010ef +00000993 +be5ff06f +83018513 +051010ef +00100993 +bd5ff06f +8c018513 +041010ef +00400993 +bc5ff06f +7f041783 +9a079ce3 +341537b7 +41578793 +06600713 +7ef42623 +7ee41823 +9a1ff06f +00000493 +cddff06f +0047f793 +e6078ee3 +ec5ff06f +fb010113 +04912223 +03612823 +03912223 +04112623 +04812423 +05212023 +03712623 +00050493 +00068c93 +00060b13 +00061463 +00100b13 +fff58b93 +ffcbfb93 +004b8793 +00f12223 +00000413 +14048663 +00040913 +00140413 +00040593 +00040513 +151010ef +00351513 +fe9564e3 +00090593 +00090513 +13d010ef +00151793 +00f12423 +00812703 +00412783 +00e78bb3 +14090063 +03312e23 +03412c23 +03512a23 +03812423 +03a12023 +01b12e23 +01212623 +00412783 +00190413 +00191c13 +000b8a13 +00000993 +00100d93 +417784b3 +000d8a93 +000a0d13 +000b0513 +000d8593 +0d9010ef +41f55793 +0107d793 +00f50633 +01061613 +01065613 +40f60b33 +016d86b3 +01b687b3 +01a48533 +00dd1023 +0ff7f793 +001d8d93 +00f51023 +002d0d13 +fa8d9ee3 +00198993 +01590db3 +01240433 +018a0a33 +fb2990e3 +03c12983 +03812a03 +03412a83 +02812c03 +02012d03 +01c12d83 +00812783 +04c12083 +04812403 +00fb87b3 +fff78793 +ffc7f793 +00478793 +00fca623 +00412783 +017ca423 +04412483 +00fca223 +00c12783 +03012b03 +02c12b83 +00fca023 +00090513 +02412c83 +04012903 +05010113 +00008067 +fff00793 +00f12623 +00078913 +00200793 +03312e23 +03412c23 +03512a23 +03812423 +03a12023 +01b12e23 +006b8b93 +00f12423 +ee5ff06f +00012423 +00012623 +f71ff06f +0c050463 +fd010113 +01312e23 +01812423 +00151993 +00251c13 +01412c23 +01512a23 +01612823 +01712623 +01912223 +02112623 +02812423 +02912223 +03212023 +00068b13 +00060b93 +00050a93 +00058a13 +01858c33 +013689b3 +00000c93 +001c9493 +009b84b3 +000b0413 +00000913 +00041583 +00049503 +00240413 +00248493 +760010ef +00a90933 +fe8994e3 +012a2023 +004a0a13 +015c8cb3 +fd4c14e3 +02c12083 +02812403 +02412483 +02012903 +01c12983 +01812a03 +01412a83 +01012b03 +00c12b83 +00812c03 +00412c83 +03010113 +00008067 +00008067 +10050463 +fb010113 +04912223 +00151493 +05212023 +03612823 +03712623 +03812423 +03912223 +04112623 +04812423 +03312e23 +03412c23 +03512a23 +03a12023 +01b12e23 +00d12623 +00b12423 +00050b93 +00060b13 +00960933 +00000c13 +00000c93 +00812783 +00c12a03 +002c1993 +013789b3 +00000a93 +000a0d93 +000b0413 +00000d13 +000d9583 +00041503 +00240413 +009d8db3 +680010ef +00ad0d33 +fe8914e3 +01a9a023 +001a8793 +00498993 +002a0a13 +00fb8663 +00078a93 +fc1ff06f +009b0b33 +017c0c33 +00990933 +015c8663 +001c8c93 +f95ff06f +04c12083 +04812403 +04412483 +04012903 +03c12983 +03812a03 +03412a83 +03012b03 +02c12b83 +02812c03 +02412c83 +02012d03 +01c12d83 +05010113 +00008067 +00008067 +10050e63 +fb010113 +04812423 +00151413 +04912223 +03512a23 +03612823 +03712623 +03812423 +04112623 +05212023 +03312e23 +03412c23 +03912223 +03a12023 +01b12e23 +00d12623 +00b12423 +00050b13 +00060a93 +008604b3 +00000b93 +00000c13 +00812783 +00c12983 +002b9913 +01278933 +00000a13 +00098d13 +000a8d93 +00000c93 +000d1583 +000d9503 +002d8d93 +008d0d33 +574010ef +40255693 +40555593 +07f5f593 +00f6f513 +560010ef +00ac8cb3 +fdb49ae3 +01992023 +001a0793 +00490913 +00298993 +00fb0663 +00078a13 +fadff06f +008a8ab3 +016b8bb3 +008484b3 +014c0663 +001c0c13 +f81ff06f +04c12083 +04812403 +04412483 +04012903 +03c12983 +03812a03 +03412a83 +03012b03 +02c12b83 +02812c03 +02412c83 +02012d03 +01c12d83 +05010113 +00008067 +00008067 +fb010113 +03312e23 +03412c23 +04112623 +04812423 +04912223 +00d12623 +00058a13 +00060993 +36050063 +03812423 +00151c13 +05212023 +03712623 +03912223 +01860bb3 +00070c93 +fffff937 +03612823 +03512a23 +03a12023 +01b12e23 +000b8713 +012ce933 +00000b13 +418707b3 +0007d683 +00278793 +00dc86b3 +fed79f23 +fee798e3 +001b0413 +01878733 +00850663 +00040b13 +fd9ff06f +00000d13 +00000d93 +002d1793 +00fa0ab3 +418b84b3 +00049503 +000c8593 +00248493 +430010ef +00aaa023 +004a8a93 +fe9b94e3 +008d0d33 +018b8bb3 +016d8663 +001d8d93 +fc9ff06f +00241c13 +018a0bb3 +000b8813 +00000693 +00000713 +00000513 +00000893 +418807b3 +0180006f +00c505b3 +01059513 +00478793 +41055513 +02f80863 +00068613 +0007a683 +00a50593 +00d70733 +00d62633 +fce95ce3 +01059513 +00478793 +00000713 +41055513 +fcf81ce3 +01880833 +011b0663 +00188893 +fadff06f +00000593 +77d000ef +00c12683 +00050493 +00098613 +00040513 +000a0593 +ba5ff0ef +00000693 +00000713 +00000513 +00000813 +418b87b3 +0180006f +00c505b3 +01059513 +00478793 +41055513 +03778863 +00068613 +0007a683 +00a50593 +00d70733 +00d62633 +fce95ce3 +01059513 +00478793 +00000713 +41055513 +fd779ce3 +01878bb3 +01680663 +00180813 +fadff06f +00048593 +6f5000ef +00c12683 +00050493 +00098613 +00040513 +000a0593 +be9ff0ef +00000313 +00000793 +00000713 +00000513 +00000893 +00231613 +00ca0633 +00000593 +01c0006f +00d50833 +01081513 +00158593 +41055513 +00460613 +0285fa63 +00078693 +00062783 +00a50813 +00f70733 +00f6a6b3 +fce95ae3 +01081513 +00158593 +00000713 +41055513 +00460613 +fc85eae3 +00188893 +00830333 +fa88e0e3 +00048593 +65d000ef +00c12683 +00050493 +00098613 +00040513 +000a0593 +c5dff0ef +00000313 +00000793 +00000713 +00000513 +00000893 +00231613 +00ca0633 +00000593 +01c0006f +00d50833 +01081513 +00158593 +41055513 +00460613 +0285fa63 +00078693 +00062783 +00a50813 +00f70733 +00f6a6b3 +fce95ae3 +01081513 +00158593 +00000713 +41055513 +00460613 +fc85eae3 +00188893 +00830333 +fa88e0e3 +00048593 +5c5000ef +00000593 +00000613 +00159793 +00f987b3 +00000713 +0007d683 +00170713 +00278793 +419686b3 +fed79f23 +fe8766e3 +00160613 +008585b3 +fc866ae3 +04012903 +03412a83 +03012b03 +02c12b83 +02812c03 +02412c83 +02012d03 +01c12d83 +04c12083 +04812403 +01051513 +04412483 +03c12983 +03812a03 +41055513 +05010113 +00008067 +00000593 +541000ef +00c12483 +00098613 +00050413 +00048693 +000a0593 +00000513 +965ff0ef +00040593 +00000513 +519000ef +00048693 +00098613 +00050413 +000a0593 +00000513 +a0dff0ef +00040593 +00000513 +4f5000ef +00050413 +000a0593 +00048693 +00098613 +00000513 +af5ff0ef +00040593 +00000513 +4d1000ef +f65ff06f +ff010113 +00812423 +00852683 +00060413 +00058713 +00452603 +00c52583 +00052503 +00112623 +bddff0ef +00040593 +00812403 +00c12083 +01010113 +4910006f +fff50813 +00100e13 +150e7063 +01c585b3 +01059593 +ff010113 +0105d593 +00812623 +01b59413 +00912423 +01212223 +01312023 +00700893 +0075f693 +d5c18293 +d6c18f93 +d7c18f13 +d8c18e93 +00000713 +00400313 +02c00393 +01e45793 +07168e63 +0cd36c63 +ffd68693 +01069693 +0106d693 +00279793 +0ade6a63 +00ff07b3 +0007a783 +00800413 +00170693 +008689b3 +0709f463 +00158593 +00e60933 +01059593 +0105d593 +00090693 +008784b3 +0007c703 +00178793 +00168693 +fee68fa3 +fef498e3 +00890733 +00770023 +01b59413 +0075f693 +00098713 +01e45793 +f91696e3 +00279793 +00800413 +00170693 +00f287b3 +008689b3 +0007a783 +fb09e0e3 +00a76663 +0180006f +00168693 +00e60733 +00070023 +00068713 +fea6e8e3 +00c12403 +00812483 +00412903 +00012983 +01010113 +00008067 +00fe87b3 +0007a783 +00400413 +f51ff06f +00279793 +00ff87b3 +0007a783 +00800413 +f3dff06f +000e0693 +00000713 +0080006f +00168693 +00e60733 +00070023 +00068713 +fea6e8e3 +00008067 +00052683 +0006c783 +04078263 +02c00713 +20e78263 +02e00813 +1d078c63 +02f86e63 +fd578793 +0fd7f793 +1e078c63 +0045a703 +0005a783 +00168693 +00170713 +00178793 +00f5a023 +00e5a223 +00100793 +00d52023 +00078513 +00008067 +fd078793 +0ff7f793 +00900613 +fcf664e3 +0005a603 +00168793 +00160613 +00c5a023 +0016c683 +1e068a63 +20e68663 +02e00713 +04e68663 +fd068693 +0ff6f693 +00900713 +02d77463 +0105a703 +00178693 +00100793 +00f70733 +00e5a823 +00d52023 +00078513 +00008067 +00c5a423 +0017c683 +00178793 +1a068463 +02c00713 +fb1ff06f +0105a703 +00170713 +00e5a823 +0017c683 +00178793 +12068063 +02c00713 +18e68663 +0df6f713 +04500613 +0cc71663 +0145a703 +00178693 +00170713 +00e5aa23 +0017c703 +18070863 +02c00613 +18c70863 +00c5a683 +fd570713 +0fd77713 +00168693 +00d5a623 +08071463 +0027c703 +00278693 +14070e63 +18c70463 +0185a603 +fd070713 +0ff77713 +00160613 +00900813 +00c5ac23 +00e87c63 +00378693 +00100793 +00d52023 +00078513 +00008067 +00068613 +0016c703 +00168693 +02c00893 +fd070793 +0ff7f793 +12070463 +13170663 +fef870e3 +0045a703 +00100793 +00260693 +00f70733 +00e5a223 +00d52023 +00078513 +00008067 +00278693 +00100793 +e89ff06f +fd068693 +0ff6f693 +00900713 +f0d776e3 +0145a703 +00178693 +00100793 +00f70733 +00e5aa23 +e61ff06f +0005a603 +00168793 +00160613 +00c5a023 +0016c683 +ee0696e3 +00078693 +00500793 +e3dff06f +00000793 +00168693 +e31ff06f +0005a603 +00168793 +00160613 +00c5a023 +0016c303 +0a030a63 +0ae30063 +0085a603 +fd030713 +0ff77713 +00900893 +00160613 +e6e8f6e3 +01030a63 +00c5a423 +00268693 +00100793 +de9ff06f +00c5a423 +e75ff06f +00078693 +00400793 +dd5ff06f +00078693 +00168693 +00500793 +dc5ff06f +00078693 +00168693 +00400793 +db5ff06f +00600793 +dadff06f +00300793 +da5ff06f +00300793 +00168693 +d99ff06f +00700793 +d91ff06f +00700793 +00168693 +d85ff06f +00600793 +00168693 +d79ff06f +00078693 +00168693 +00200793 +d69ff06f +00078693 +00200793 +d5dff06f +f8010113 +07312623 +07412423 +01010993 +03010a13 +06812c23 +06912a23 +07212823 +07612023 +05712e23 +05812c23 +05912a23 +00078493 +00070b13 +06112e23 +07512223 +00058413 +00b12623 +00050c93 +00060c13 +00068b93 +000a0793 +00098913 +00098713 +0007a023 +00072023 +00478793 +05010693 +00470713 +fed796e3 +00044783 +00c10a93 +10078a63 +03010593 +000a8513 +c81ff0ef +00251713 +00e98733 +00c12683 +00072783 +0006c683 +00178793 +00f72023 +fc069ce3 +00812623 +01940cb3 +03947863 +00040793 +02c00613 +0007c703 +018746b3 +00c70463 +00d78023 +016787b3 +ff97e6e3 +00044783 +00c10a93 +02078863 +03010593 +000a8513 +c1dff0ef +00251713 +00e98733 +00c12683 +00072783 +0006c683 +00178793 +00f72023 +fc069ce3 +02c00693 +01947e63 +00044783 +0177c733 +00d78463 +00e40023 +01640433 +ff9466e3 +02098993 +00092503 +00048593 +00490913 +2cc000ef +00050593 +000a2503 +004a0a13 +2bc000ef +00050493 +fd299ee3 +07c12083 +07812403 +07412483 +07012903 +06c12983 +06812a03 +06412a83 +06012b03 +05c12b83 +05812c03 +05412c83 +08010113 +00008067 +01940cb3 +f39462e3 +f99ff06f +00500793 +04a7e063 +d9c18793 +00251513 +00f50533 +00052783 +00078067 +fc81a503 +00008067 +fd01a503 +00008067 +fcc1a503 +00008067 +fbc1a503 +00008067 +fb81a503 +00008067 +00000513 +00008067 +0ff5f793 +00879793 +0085d593 +00001737 +fffff337 +0f030313 +f0f70713 +00b7e7b3 +00e7f5b3 +0067f7b3 +0047d793 +00459593 +00f5e5b3 +ffffd8b7 +000037b7 +ccc88893 +33378793 +00f57693 +0f057813 +00f5f633 +00485813 +0115f5b3 +00469693 +0106e6b3 +0025d593 +00261613 +00b66633 +0336fe13 +000055b7 +0cc6f693 +ffffb837 +55558593 +aaa80813 +0026de93 +002e1e13 +00b676b3 +01de6e33 +01067633 +00169693 +00165613 +055e7f13 +0aae7e13 +00c6eeb3 +001f1f13 +001e5e13 +01cf6e33 +008ede93 +01ceceb3 +db418e13 +00c6e633 +001e9693 +01c686b3 +0006d683 +00861613 +00855513 +00c6c633 +01061e93 +0ff6f693 +018ed613 +00869693 +00c6e6b3 +00e6f633 +0066f6b3 +0046d693 +00461613 +00d66633 +00f676b3 +01167633 +00265613 +00269693 +00c6e6b3 +00b6f633 +0106f6b3 +00161613 +0016d693 +00d666b3 +0ff6f613 +00861613 +0086d693 +00d66633 +00e676b3 +00667eb3 +004ede93 +00f57613 +00469693 +01d6e6b3 +00455513 +00461613 +00a66633 +0116feb3 +00f6f533 +002ede93 +03367693 +00251513 +0cc67613 +01d56533 +00265613 +00269693 +00c6e6b3 +00b57633 +01057533 +0556ff13 +00161613 +00155513 +0aa6f693 +00a66eb3 +0016d693 +001f1f13 +00df6f33 +008ed693 +01e6c6b3 +00169693 +01c686b3 +0006d683 +008e9613 +00c6c633 +01061513 +0ff6f693 +01855613 +00869693 +00c6e6b3 +00e6f733 +0066f6b3 +0046d693 +00471713 +00d76733 +00f777b3 +01177733 +00275713 +00279793 +00e7e7b3 +00b7f533 +0107f7b3 +0017d793 +00151513 +00f56533 +00008067 +0ff5f793 +00879793 +0085d593 +00001737 +fffff8b7 +0f088893 +f0f70713 +00b7e7b3 +00e7f6b3 +0117f7b3 +0047d793 +00469693 +00f6e6b3 +ffffd837 +000037b7 +ccc80813 +33378793 +00f57613 +0f057593 +00f6f333 +0045d593 +0106f6b3 +00461613 +00b66633 +0026d693 +00231313 +00d36333 +03367e13 +000056b7 +0cc67613 +ffffb5b7 +55568693 +aaa58593 +00265e93 +002e1e13 +00d37633 +01de6e33 +00b37333 +00161613 +00135313 +055e7f13 +0aae7e13 +00666eb3 +001f1f13 +001e5e13 +01cf6e33 +008ede93 +01ceceb3 +00666e33 +db418313 +001e9613 +00660633 +00065603 +008e1e13 +00855f13 +01c64e33 +010e1e93 +0ff67613 +018ede13 +00861613 +01c66633 +00e67e33 +01167633 +00465613 +004e1e13 +00ce6e33 +00fe7633 +010e7e33 +002e5e13 +00261613 +01c66633 +00d67e33 +00b67633 +00165613 +001e1e13 +00ce6e33 +0ffe7613 +00861613 +008e5e13 +01c66633 +00e67eb3 +01167633 +00465613 +004e9e93 +00ceeeb3 +00ff7613 +0f0f7f13 +00fefe33 +004f5f13 +010efeb3 +00461613 +01e66633 +002ede93 +002e1e13 +01de6e33 +03367e93 +0cc67613 +00265f13 +002e9e93 +00de7633 +01eeeeb3 +00be7e33 +00161613 +001e5e13 +055eff93 +0aaefe93 +01c66f33 +001f9f93 +001ede93 +008f5f13 +01dfeeb3 +01df4eb3 +01c66e33 +001e9613 +00660633 +00065603 +008e1e13 +01055e93 +01c64e33 +010e1f13 +0ff67613 +018f5e13 +00861613 +01c66633 +00e67e33 +01167633 +00465613 +004e1e13 +00ce6e33 +00fe7633 +010e7e33 +002e5e13 +00261613 +01c66633 +00d67e33 +00b67633 +001e1e13 +00165613 +00ce6633 +0ff67e13 +008e1e13 +00865613 +00ce6e33 +00ee7633 +011e7e33 +004e5e13 +00461613 +01c66633 +00fefe13 +0f0efe93 +004edf13 +004e1e13 +00f67eb3 +01067633 +01ee6e33 +00265613 +002e9e93 +00ceeeb3 +033e7613 +0cce7e13 +002e5f13 +00261613 +00defe33 +01e66633 +00befeb3 +001ede93 +001e1e13 +05567f93 +0aa67613 +01de6f33 +001f9f93 +00165613 +008f5f13 +00cfe633 +00cf4633 +00161613 +00660633 +00065603 +01de6e33 +008e1e13 +01c64e33 +010e1e93 +0ff67613 +018ede13 +00861613 +01c66633 +00e67e33 +01167633 +00465613 +004e1e13 +00ce6e33 +00fe7633 +010e7e33 +002e5e13 +00261613 +01c66633 +00d67e33 +00b67633 +00165613 +001e1e13 +00ce6e33 +0ffe7613 +00861613 +008e5e13 +01c66633 +00e67eb3 +01167e33 +01855513 +00f57613 +004e5e13 +004e9e93 +00461613 +01ceeeb3 +00455513 +00fefe33 +00a66533 +010efeb3 +03357613 +002ede93 +0cc57513 +002e1e13 +01de6e33 +00255513 +00261613 +00a66633 +00de7533 +00be7e33 +05567f13 +00151513 +001e5e13 +0aa67613 +01c56eb3 +00165613 +001f1f13 +00cf6f33 +008ed613 +01e64633 +00161613 +00660633 +00065603 +008e9513 +00a64533 +01051313 +0ff67613 +01835513 +00861613 +00a66633 +00e67733 +01167633 +00465613 +00471713 +00c76733 +00f777b3 +01077733 +00275713 +00279793 +00e7e7b3 +00d7f533 +00b7f7b3 +0017d793 +00151513 +00f56533 +00008067 +0ff5f793 +00879793 +0085d593 +00001737 +fffff337 +0f030313 +f0f70713 +00b7e7b3 +00e7f5b3 +0067f7b3 +0047d793 +00459593 +00f5e5b3 +ffffd8b7 +000037b7 +ccc88893 +33378793 +00f57693 +0f057813 +00f5f633 +00485813 +0115f5b3 +00469693 +0106e6b3 +0025d593 +00261613 +00b66633 +0336fe13 +000055b7 +0cc6f693 +ffffb837 +55558593 +aaa80813 +0026de93 +002e1e13 +00b676b3 +01de6e33 +01067633 +00169693 +00165613 +055e7f13 +0aae7e13 +00c6eeb3 +001f1f13 +001e5e13 +01cf6e33 +008ede93 +01ceceb3 +db418e13 +00c6e633 +001e9693 +01c686b3 +0006d683 +00861613 +00855513 +00c6c633 +01061e93 +0ff6f693 +018ed613 +00869693 +00c6e6b3 +00e6f633 +0066f6b3 +0046d693 +00461613 +00d66633 +00f676b3 +01167633 +00265613 +00269693 +00c6e6b3 +00b6f633 +0106f6b3 +00161613 +0016d693 +00d666b3 +0ff6f613 +00861613 +0086d693 +00d66633 +00e676b3 +00667eb3 +004ede93 +00f57613 +00469693 +0f057513 +01d6e6b3 +00455513 +00461613 +00a66633 +0116feb3 +00f6f533 +002ede93 +03367693 +00251513 +0cc67613 +01d56533 +00265613 +00269693 +00c6e6b3 +00b57633 +01057533 +0556ff13 +00161613 +00155513 +0aa6f693 +00a66eb3 +0016d693 +001f1f13 +00df6f33 +008ed693 +01e6c6b3 +00169693 +01c686b3 +0006d683 +008e9613 +00c6c633 +01061513 +0ff6f693 +01855613 +00869693 +00c6e6b3 +00e6f733 +0066f6b3 +0046d693 +00471713 +00d76733 +00f777b3 +01177733 +00275713 +00279793 +00e7e7b3 +00b7f533 +0107f7b3 +0017d793 +00151513 +00f56533 +00008067 +00000513 +00008067 +fc01a223 +00008067 +00a00713 +fce1a023 +00008067 +fc01a503 +fc41a783 +40f50533 +00008067 +00008067 +00100793 +00f50023 +00008067 +00050023 +00008067 +fd010113 +01410e93 +00b12a23 +00d12e23 +02e12023 +02f12223 +00c12c23 +03012423 +03112623 +00050713 +01d12623 +ca418793 +cbf18593 +04300693 +00074603 +00178793 +00170713 +02d61263 +0007c683 +feb796e3 +800007b7 +fff78793 +fcf1aa23 +00000513 +03010113 +00008067 +cc018793 +cd318593 +00050713 +05b00693 +00074603 +00178793 +00170713 +02d61063 +0007c683 +feb796e3 +00200713 +fce1aa23 +00000513 +03010113 +00008067 +cd418793 +ce918593 +00050713 +05b00693 +00074603 +00178793 +00170713 +02d61063 +0007c683 +feb796e3 +00300713 +fce1aa23 +00000513 +03010113 +00008067 +cec18793 +d0018593 +00050713 +05b00693 +00074603 +00178793 +00170713 +00d61c63 +0007c683 +feb796e3 +00400713 +fce1aa23 +f4dff06f +d0418793 +d1318593 +00050713 +04500693 +00074603 +00178793 +00170713 +02d61063 +0007c683 +feb796e3 +fd41a703 +f0071ee3 +00100713 +fce1aa23 +f11ff06f +d1418793 +d2d18593 +00050713 +04300693 +00074603 +00178793 +00170713 +00d61c63 +0007c683 +feb796e3 +00500713 +fce1aa23 +eddff06f +d3018793 +00550613 +04500713 +00054683 +00178793 +00150513 +ece690e3 +0007c703 +fec516e3 +f9dff06f +00050613 +00000513 +0015f693 +00068463 +00c50533 +0015d593 +00161613 +fe0596e3 +00008067 +06054063 +0605c663 +00058613 +00050593 +fff00513 +02060c63 +00100693 +00b67a63 +00c05863 +00161613 +00169693 +feb66ae3 +00000513 +00c5e663 +40c585b3 +00d56533 +0016d693 +00165613 +fe0696e3 +00008067 +00008293 +fb5ff0ef +00058513 +00028067 +40a00533 +00b04863 +40b005b3 +f9dff06f +40b005b3 +00008293 +f91ff0ef +40a00533 +00028067 +00008293 +0005ca63 +00054c63 +f79ff0ef +00058513 +00028067 +40b005b3 +fe0558e3 +40a00533 +f61ff0ef +40b00533 +00028067 diff --git a/examples/minor-cpu/workloads/coremark.ld b/examples/minor-cpu/workloads/coremark.ld new file mode 100644 index 000000000..dbeeb5708 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark.ld @@ -0,0 +1,39 @@ +OUTPUT_ARCH("riscv") +ENTRY(_start) + +SECTIONS +{ + . = 0x00000000; + + .text : ALIGN(4) + { + *(.text.init) + *(.text.startup) + *(.text*) + } + + . = 0x00004000; + + .data : ALIGN(4) + { + *(.rodata*) + *(.srodata*) + *(.data*) + *(.sdata*) + } + + .bss : ALIGN(4) + { + __bss_start = .; + *(.sbss*) + *(.bss*) + *(COMMON) + __bss_end = .; + } + + . = ALIGN(16); + _end = .; + + PROVIDE(__global_pointer$ = 0x00004800); + PROVIDE(__stack_top = 0x0003fe00); +} diff --git a/examples/minor-cpu/workloads/coremark.sh b/examples/minor-cpu/workloads/coremark.sh new file mode 100755 index 000000000..a8064f404 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +logfile=$1 + +rg -n "ebreak \| halt \| ecall|trap" "$logfile" > /dev/null +rg -n "mem-write \| addr: 0x3ff08\|.*wdada: 0x7fffffff" "$logfile" > /dev/null diff --git a/examples/minor-cpu/workloads/coremark_baremetal.sh b/examples/minor-cpu/workloads/coremark_baremetal.sh new file mode 100755 index 000000000..66f7b75fa --- /dev/null +++ b/examples/minor-cpu/workloads/coremark_baremetal.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +logfile=$1 + +rg -n "ebreak \| halt \| ecall|trap" "$logfile" > /dev/null +rg -n "mem-write \| addr: 0x3ff08\|.*wdada: 0x7fffffff" "$logfile" > /dev/null +rg -n "mem-write \| addr: 0x3ff24\|.*wdada: 0x00000000" "$logfile" > /dev/null +rg -n "mem-write \| addr: 0x3ff0c\|.*wdada: 0x0000e9f5" "$logfile" > /dev/null diff --git a/examples/minor-cpu/workloads/coremark_baremetal_start.c b/examples/minor-cpu/workloads/coremark_baremetal_start.c new file mode 100644 index 000000000..c223d8fa2 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark_baremetal_start.c @@ -0,0 +1,40 @@ +#include + +extern int main(void); + +extern volatile uint16_t coremark_seedcrc_result; +extern volatile uint16_t coremark_crclist_result; +extern volatile uint16_t coremark_crcmatrix_result; +extern volatile uint16_t coremark_crcstate_result; +extern volatile uint16_t coremark_crcfinal_result; +extern volatile int16_t coremark_total_errors_result; +extern volatile uint32_t coremark_total_ticks_result; + +static inline void mmio_write(uint32_t addr, uint32_t value) +{ + *(volatile uint32_t *)addr = value; +} + +__attribute__((section(".text.init"))) +void _start(void) +{ + __asm__ volatile("la gp, __global_pointer$"); + __asm__ volatile("la sp, __stack_top"); + + mmio_write(0x0003ff00u, 1u); + (void)main(); + mmio_write(0x0003ff04u, 2u); + + mmio_write(0x0003ff0cu, coremark_seedcrc_result); + mmio_write(0x0003ff10u, coremark_crclist_result); + mmio_write(0x0003ff14u, coremark_crcmatrix_result); + mmio_write(0x0003ff18u, coremark_crcstate_result); + mmio_write(0x0003ff1cu, coremark_crcfinal_result); + mmio_write(0x0003ff20u, coremark_total_ticks_result); + mmio_write(0x0003ff24u, (uint32_t)(int32_t)coremark_total_errors_result); + mmio_write(0x0003ff08u, + (coremark_total_errors_result == 0) ? 0x7fffffffu : 0u); + + __asm__ volatile("ebreak"); + while (1) { } +} diff --git a/examples/minor-cpu/workloads/coremark_ee_printf.c b/examples/minor-cpu/workloads/coremark_ee_printf.c new file mode 100644 index 000000000..82d33eaa1 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark_ee_printf.c @@ -0,0 +1,55 @@ +#include "coremark.h" + +#include + +volatile ee_u32 coremark_status = 0; + +enum +{ + COREMARK_STATUS_OK = 0x7fffffff, + COREMARK_STATUS_GENERIC_ERROR = 1, + COREMARK_STATUS_LIST_ERROR = 2, + COREMARK_STATUS_MATRIX_ERROR = 3, + COREMARK_STATUS_STATE_ERROR = 4, + COREMARK_STATUS_UNVALIDATED = 5, +}; + +static int starts_with(const char *text, const char *prefix) +{ + while (*prefix != '\0') + { + if (*text != *prefix) + return 0; + text++; + prefix++; + } + return 1; +} + +int ee_printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + va_end(args); + + if (starts_with(fmt, "Correct operation validated")) + coremark_status = COREMARK_STATUS_OK; + else if (starts_with(fmt, "[%u]ERROR! list crc")) + coremark_status = COREMARK_STATUS_LIST_ERROR; + else if (starts_with(fmt, "[%u]ERROR! matrix crc")) + coremark_status = COREMARK_STATUS_MATRIX_ERROR; + else if (starts_with(fmt, "[%u]ERROR! state crc")) + coremark_status = COREMARK_STATUS_STATE_ERROR; + else if (starts_with(fmt, "Errors detected")) + { + if (coremark_status == 0) + coremark_status = COREMARK_STATUS_GENERIC_ERROR; + } + else if (starts_with(fmt, "Cannot validate operation")) + coremark_status = COREMARK_STATUS_UNVALIDATED; + else if (starts_with(fmt, "ERROR")) + coremark_status = COREMARK_STATUS_GENERIC_ERROR; + + return 0; +} diff --git a/examples/minor-cpu/workloads/coremark_portme.c b/examples/minor-cpu/workloads/coremark_portme.c new file mode 100644 index 000000000..ac86a6d99 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark_portme.c @@ -0,0 +1,58 @@ +#include "coremark.h" +#include "coremark_portme.h" + +#if VALIDATION_RUN +volatile ee_s32 seed1_volatile = 0x3415; +volatile ee_s32 seed2_volatile = 0x3415; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PERFORMANCE_RUN +volatile ee_s32 seed1_volatile = 0x0; +volatile ee_s32 seed2_volatile = 0x0; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PROFILE_RUN +volatile ee_s32 seed1_volatile = 0x8; +volatile ee_s32 seed2_volatile = 0x8; +volatile ee_s32 seed3_volatile = 0x8; +#endif + +volatile ee_s32 seed4_volatile = ITERATIONS; +volatile ee_s32 seed5_volatile = 0; + +static CORETIMETYPE start_time_val; +static CORETIMETYPE stop_time_val; + +void start_time(void) +{ + start_time_val = 0; +} + +void stop_time(void) +{ + stop_time_val = 10; +} + +CORE_TICKS get_time(void) +{ + return (CORE_TICKS)(stop_time_val - start_time_val); +} + +secs_ret time_in_secs(CORE_TICKS ticks) +{ + return (secs_ret)ticks; +} + +ee_u32 default_num_contexts = 1; + +void portable_init(core_portable *p, int *argc, char *argv[]) +{ + (void)argc; + (void)argv; + p->portable_id = 1; +} + +void portable_fini(core_portable *p) +{ + p->portable_id = 0; +} diff --git a/examples/minor-cpu/workloads/coremark_portme.h b/examples/minor-cpu/workloads/coremark_portme.h new file mode 100644 index 000000000..7ffde70c6 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark_portme.h @@ -0,0 +1,109 @@ +/* + * Minimal CoreMark port for assassyn/examples/minor-cpu. + */ + +#ifndef CORE_PORTME_H +#define CORE_PORTME_H + +#include + +#ifndef HAS_FLOAT +#define HAS_FLOAT 0 +#endif + +#ifndef HAS_TIME_H +#define HAS_TIME_H 0 +#endif + +#ifndef USE_CLOCK +#define USE_CLOCK 0 +#endif + +#ifndef HAS_STDIO +#define HAS_STDIO 0 +#endif + +#ifndef HAS_PRINTF +#define HAS_PRINTF 0 +#endif + +#ifndef COMPILER_VERSION +#ifdef __GNUC__ +#define COMPILER_VERSION "GCC " __VERSION__ +#else +#define COMPILER_VERSION "unknown" +#endif +#endif + +#ifndef COMPILER_FLAGS +#define COMPILER_FLAGS "rv32i minor-cpu" +#endif + +#ifndef MEM_LOCATION +#define MEM_LOCATION "STACK" +#endif + +typedef signed short ee_s16; +typedef unsigned short ee_u16; +typedef signed int ee_s32; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef double ee_f32; +typedef ee_u32 ee_ptr_int; +typedef size_t ee_size_t; + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) + +#define CORETIMETYPE ee_u32 +typedef ee_u32 CORE_TICKS; + +#ifndef SEED_METHOD +#define SEED_METHOD SEED_VOLATILE +#endif + +#ifndef MEM_METHOD +#define MEM_METHOD MEM_STACK +#endif + +#ifndef MULTITHREAD +#define MULTITHREAD 1 +#define USE_PTHREAD 0 +#define USE_FORK 0 +#define USE_SOCKET 0 +#endif + +#ifndef MAIN_HAS_NOARGC +#define MAIN_HAS_NOARGC 1 +#endif + +#ifndef MAIN_HAS_NORETURN +#define MAIN_HAS_NORETURN 0 +#endif + +extern ee_u32 default_num_contexts; + +typedef struct CORE_PORTABLE_S +{ + ee_u8 portable_id; +} core_portable; + +void portable_init(core_portable *p, int *argc, char *argv[]); +void portable_fini(core_portable *p); + +#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN) +#if (TOTAL_DATA_SIZE == 1200) +#define PROFILE_RUN 1 +#elif (TOTAL_DATA_SIZE == 2000) +#define PERFORMANCE_RUN 1 +#else +#define VALIDATION_RUN 1 +#endif +#endif + +int ee_printf(const char *fmt, ...); + +#endif diff --git a/examples/minor-cpu/workloads/coremark_start.c b/examples/minor-cpu/workloads/coremark_start.c new file mode 100644 index 000000000..3c5782d86 --- /dev/null +++ b/examples/minor-cpu/workloads/coremark_start.c @@ -0,0 +1,25 @@ +#include + +extern int main(void); +extern volatile uint32_t coremark_status; +extern char __stack_top[]; + +static inline void mmio_write(uint32_t addr, uint32_t value) +{ + *(volatile uint32_t *)addr = value; +} + +__attribute__((section(".text.init"))) +void _start(void) +{ + __asm__ volatile("la gp, __global_pointer$"); + __asm__ volatile("la sp, __stack_top"); + + mmio_write(0x0003ff00u, 1u); + (void)main(); + mmio_write(0x0003ff04u, 2u); + mmio_write(0x0003ff08u, coremark_status); + + __asm__ volatile("ebreak"); + while (1) { } +} From 693ece51598d2c4491efd9c2486ffd2213bdb2af Mon Sep 17 00:00:00 2001 From: An Zhong Date: Tue, 9 Jun 2026 14:52:47 +0800 Subject: [PATCH 2/2] [codegen] Support PyCDE pass phase filtering. [python] Filter lower ESI passes through either FINAL_LOWERING_PASSES or PASS_PHASES so generated Verilog designs work across PyCDE pass-list APIs. [tests] Update the generated header test to cover the compatibility block. --- python/assassyn/codegen/verilog/top.py | 10 ++++++---- python/unit-tests/codegen/test_pycde_header_import.py | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/python/assassyn/codegen/verilog/top.py b/python/assassyn/codegen/verilog/top.py index a6d6f3241..8b55ffe5d 100644 --- a/python/assassyn/codegen/verilog/top.py +++ b/python/assassyn/codegen/verilog/top.py @@ -545,10 +545,12 @@ def _attach_external_values(module, port_map, handled_ports): dumper.indent -= 8 dumper.append_code('') dumper.append_code('system = System([Top], name="Top", output_directory="sv")') - dumper.append_code('System.FINAL_LOWERING_PASSES = [') - dumper.append_code(' entry for entry in System.FINAL_LOWERING_PASSES') - dumper.append_code(' if "lower-esi-" not in str(entry)') - dumper.append_code(']') + dumper.append_code('for _passes_attr in ("FINAL_LOWERING_PASSES", "PASS_PHASES"):') + dumper.append_code(' if hasattr(System, _passes_attr):') + dumper.append_code(' setattr(System, _passes_attr, [') + dumper.append_code(' entry for entry in getattr(System, _passes_attr)') + dumper.append_code(' if "lower-esi-" not in str(entry)') + dumper.append_code(' ])') # Copying of external SystemVerilog files occurs during elaboration. diff --git a/python/unit-tests/codegen/test_pycde_header_import.py b/python/unit-tests/codegen/test_pycde_header_import.py index 897eb3ed1..4705c91b8 100644 --- a/python/unit-tests/codegen/test_pycde_header_import.py +++ b/python/unit-tests/codegen/test_pycde_header_import.py @@ -33,5 +33,7 @@ def build(self): assert "from assassyn.pycde_wrapper import FIFO, TriggerCounter, build_register_file" in text assert "class FIFOImpl(Module):" not in text assert "class TriggerCounterImpl(Module):" not in text - assert "System.FINAL_LOWERING_PASSES = [" in text + assert 'for _passes_attr in ("FINAL_LOWERING_PASSES", "PASS_PHASES"):' in text + assert "hasattr(System, _passes_attr)" in text + assert "getattr(System, _passes_attr)" in text assert 'if "lower-esi-" not in str(entry)' in text