From 6a0e1ab42b86f95038c4716309115c761e6842ff Mon Sep 17 00:00:00 2001 From: Marek Materzok Date: Wed, 27 Nov 2024 10:04:10 +0100 Subject: [PATCH 1/3] Use async memorybank --- coreblocks/core_structs/rf.py | 20 +++++++------------- requirements.txt | 2 +- test/test_core.py | 23 ++++++++++++----------- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/coreblocks/core_structs/rf.py b/coreblocks/core_structs/rf.py index e22e97f98..b65504ff6 100644 --- a/coreblocks/core_structs/rf.py +++ b/coreblocks/core_structs/rf.py @@ -1,9 +1,9 @@ from amaranth import * -import amaranth.lib.memory as memory from transactron import Method, Transaction, def_method, TModule from coreblocks.interface.layouts import RFLayouts from coreblocks.params import GenParams from transactron.lib.metrics import HwExpHistogram, TaggedLatencyMeasurer +from transactron.lib.storage import AsyncMemoryBank from transactron.utils.amaranth_ext.functions import popcount __all__ = ["RegisterFile"] @@ -14,7 +14,9 @@ def __init__(self, *, gen_params: GenParams): self.gen_params = gen_params layouts = gen_params.get(RFLayouts) self.read_layout = layouts.rf_read_out - self.entries = memory.Memory(shape=gen_params.isa.xlen, depth=2**gen_params.phys_regs_bits, init=[]) + self.entries = AsyncMemoryBank( + data_layout=[("data", gen_params.isa.xlen)], elem_count=2**gen_params.phys_regs_bits, read_ports=2 + ) self.valids = Array(Signal(init=k == 0) for k in range(2**gen_params.phys_regs_bits)) self.read1 = Method(i=layouts.rf_read_in, o=layouts.rf_read_out) @@ -43,17 +45,12 @@ def elaborate(self, platform): being_written = Signal(self.gen_params.phys_regs_bits) written_value = Signal(self.gen_params.isa.xlen) - write_port = self.entries.write_port() - read_port_1 = self.entries.read_port(domain="comb") - read_port_2 = self.entries.read_port(domain="comb") - @def_method(m, self.read1) def _(reg_id: Value): forward = Signal() m.d.av_comb += forward.eq((being_written == reg_id) & (reg_id != 0)) - m.d.av_comb += read_port_1.addr.eq(reg_id) return { - "reg_val": Mux(forward, written_value, read_port_1.data), + "reg_val": Mux(forward, written_value, self.entries.read[0](m, addr=reg_id).data), "valid": Mux(forward, 1, self.valids[reg_id]), } @@ -61,9 +58,8 @@ def _(reg_id: Value): def _(reg_id: Value): forward = Signal() m.d.av_comb += forward.eq((being_written == reg_id) & (reg_id != 0)) - m.d.av_comb += read_port_2.addr.eq(reg_id) return { - "reg_val": Mux(forward, written_value, read_port_2.data), + "reg_val": Mux(forward, written_value, self.entries.read[1](m, addr=reg_id).data), "valid": Mux(forward, 1, self.valids[reg_id]), } @@ -72,10 +68,8 @@ def _(reg_id: Value, reg_val: Value): zero_reg = reg_id == 0 m.d.comb += being_written.eq(reg_id) m.d.av_comb += written_value.eq(reg_val) - m.d.av_comb += write_port.addr.eq(reg_id) - m.d.av_comb += write_port.data.eq(reg_val) with m.If(~(zero_reg)): - m.d.comb += write_port.en.eq(1) + self.entries.write(m, addr=reg_id, data={"data": reg_val}) m.d.sync += self.valids[reg_id].eq(1) self.perf_rf_valid_time.start(m, slot=reg_id) diff --git a/requirements.txt b/requirements.txt index 19b874c8c..09401a88a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ amaranth-stubs @ git+https://github.com/kuznia-rdzeni/amaranth-stubs.git@edb302b001433edf4c8568190adc9bd0c0039f45 -transactron @ git+https://github.com/kuznia-rdzeni/transactron.git@972047b7bfac3d2e193a428de35c976f9b17c51a +transactron @ git+https://github.com/kuznia-rdzeni/transactron.git@82aceee58db05498ffd8c4dd515bcb834bb0cf88 amaranth-yosys==0.40.0.0.post100 amaranth==0.5.3 dataclasses-json==0.6.3 diff --git a/test/test_core.py b/test/test_core.py index 92dba973e..0914e293c 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -3,11 +3,12 @@ from amaranth import * from amaranth.lib.wiring import connect from amaranth_types import ValueLike +from transactron.lib import AdapterTrans from transactron.testing.tick_count import TicksKey from transactron.utils import align_to_power_of_two -from transactron.testing import TestCaseWithSimulator, ProcessContext, TestbenchContext +from transactron.testing import TestCaseWithSimulator, ProcessContext, TestbenchContext, TestbenchIO from coreblocks.arch.isa_consts import PrivilegeLevel from coreblocks.core import Core @@ -55,6 +56,7 @@ def elaborate(self, platform): m.submodules.wb_mem_slave = self.wb_mem_slave m.submodules.wb_mem_slave_data = self.wb_mem_slave_data m.submodules.c = self.core + m.submodules.rf_read = self.rf_read = TestbenchIO(AdapterTrans(self.core.RF.read1)) connect(m, self.core.wb_instr, self.wb_mem_slave.bus) connect(m, self.core.wb_data, self.wb_mem_slave_data.bus) @@ -69,9 +71,8 @@ class TestCoreBase(TestCaseWithSimulator): def get_phys_reg_rrat(self, sim: TestbenchContext, reg_id): return sim.get(self.m.core.RRAT.entries[reg_id]) - def get_arch_reg_val(self, sim: TestbenchContext, reg_id): - # TODO: better stubs for memory, remove ignore - return sim.get(self.m.core.RF.entries.data[(self.get_phys_reg_rrat(sim, reg_id))]) # type: ignore + async def get_arch_reg_val(self, sim: TestbenchContext, reg_id): + return (await self.m.rf_read.call(sim, reg_id=self.get_phys_reg_rrat(sim, reg_id))).reg_val class TestCoreAsmSourceBase(TestCoreBase): @@ -161,7 +162,7 @@ async def run_and_check(self, sim: TestbenchContext): await self.tick(sim, self.cycle_count) for reg_id, val in self.expected_regvals.items(): - assert self.get_arch_reg_val(sim, reg_id) == val + assert (await self.get_arch_reg_val(sim, reg_id)) == val def test_asm_source(self): self.gen_params = GenParams(self.configuration) @@ -276,23 +277,23 @@ async def do_interrupt(): if early_interrupt: # wait until interrupts are cleared, so it won't be missed await sim.tick().until(self.m.core.interrupt_controller.mip.value == 0) - assert self.get_arch_reg_val(sim, 30) == int_count + assert (await self.get_arch_reg_val(sim, 30)) == int_count int_count += await do_interrupt() else: await sim.tick().until(self.m.core.interrupt_controller.mip.value == 0) - assert self.get_arch_reg_val(sim, 30) == int_count + assert (await self.get_arch_reg_val(sim, 30)) == int_count handler_count += 1 # wait until ISR returns await sim.tick().until(self.m.core.interrupt_controller.mstatus_mie.value != 0) - assert self.get_arch_reg_val(sim, 30) == int_count - assert self.get_arch_reg_val(sim, 27) == handler_count + assert (await self.get_arch_reg_val(sim, 30)) == int_count + assert (await self.get_arch_reg_val(sim, 27)) == handler_count for reg_id, val in self.expected_regvals.items(): - assert self.get_arch_reg_val(sim, reg_id) == val + assert (await self.get_arch_reg_val(sim, reg_id)) == val def test_interrupted_prog(self): bin_src = self.prepare_source(self.source_file) @@ -358,7 +359,7 @@ async def wait_or_timeout(cond: ValueLike, pred: Callable[[Any], bool]): await self.random_wait(sim, 5) for reg_id, val in self.expected_regvals.items(): - assert self.get_arch_reg_val(sim, reg_id) == val + assert (await self.get_arch_reg_val(sim, reg_id)) == val def test_interrupted_prog(self): bin_src = self.prepare_source(self.source_file) From 79d0c718ec4214af2b58599d93b8e364b6c826c4 Mon Sep 17 00:00:00 2001 From: Marek Materzok Date: Wed, 27 Nov 2024 12:00:17 +0100 Subject: [PATCH 2/3] Synchronous regfile --- coreblocks/core.py | 6 ++- coreblocks/core_structs/rf.py | 31 +++++++++++----- coreblocks/scheduler/scheduler.py | 57 +++++++++++++++++++++-------- requirements.txt | 2 +- test/scheduler/test_rs_selection.py | 15 +++++++- test/scheduler/test_scheduler.py | 6 ++- test/test_core.py | 23 ++++++------ 7 files changed, 97 insertions(+), 43 deletions(-) diff --git a/coreblocks/core.py b/coreblocks/core.py index 207821d24..fbf96ce09 100644 --- a/coreblocks/core.py +++ b/coreblocks/core.py @@ -132,8 +132,10 @@ def elaborate(self, platform): get_free_reg=free_rf_fifo.read, rat_rename=frat.rename, rob_put=rob.put, - rf_read1=rf.read1, - rf_read2=rf.read2, + rf_read_req1=rf.read_req1, + rf_read_req2=rf.read_req2, + rf_read_resp1=rf.read_resp1, + rf_read_resp2=rf.read_resp2, reservation_stations=self.func_blocks_unifier.rs_blocks, gen_params=self.gen_params, ) diff --git a/coreblocks/core_structs/rf.py b/coreblocks/core_structs/rf.py index b65504ff6..a1c3ca027 100644 --- a/coreblocks/core_structs/rf.py +++ b/coreblocks/core_structs/rf.py @@ -3,7 +3,7 @@ from coreblocks.interface.layouts import RFLayouts from coreblocks.params import GenParams from transactron.lib.metrics import HwExpHistogram, TaggedLatencyMeasurer -from transactron.lib.storage import AsyncMemoryBank +from transactron.lib.storage import MemoryBank from transactron.utils.amaranth_ext.functions import popcount __all__ = ["RegisterFile"] @@ -14,13 +14,18 @@ def __init__(self, *, gen_params: GenParams): self.gen_params = gen_params layouts = gen_params.get(RFLayouts) self.read_layout = layouts.rf_read_out - self.entries = AsyncMemoryBank( - data_layout=[("data", gen_params.isa.xlen)], elem_count=2**gen_params.phys_regs_bits, read_ports=2 + self.entries = MemoryBank( + data_layout=[("data", gen_params.isa.xlen)], + elem_count=2**gen_params.phys_regs_bits, + read_ports=2, + transparent=True, ) self.valids = Array(Signal(init=k == 0) for k in range(2**gen_params.phys_regs_bits)) - self.read1 = Method(i=layouts.rf_read_in, o=layouts.rf_read_out) - self.read2 = Method(i=layouts.rf_read_in, o=layouts.rf_read_out) + self.read_req1 = Method(i=layouts.rf_read_in) + self.read_req2 = Method(i=layouts.rf_read_in) + self.read_resp1 = Method(i=layouts.rf_read_in, o=layouts.rf_read_out) + self.read_resp2 = Method(i=layouts.rf_read_in, o=layouts.rf_read_out) self.write = Method(i=layouts.rf_write) self.free = Method(i=layouts.rf_free) @@ -45,21 +50,29 @@ def elaborate(self, platform): being_written = Signal(self.gen_params.phys_regs_bits) written_value = Signal(self.gen_params.isa.xlen) - @def_method(m, self.read1) + @def_method(m, self.read_req1) + def _(reg_id: Value): + self.entries.read_req[0](m, addr=reg_id) + + @def_method(m, self.read_req2) + def _(reg_id: Value): + self.entries.read_req[1](m, addr=reg_id) + + @def_method(m, self.read_resp1) def _(reg_id: Value): forward = Signal() m.d.av_comb += forward.eq((being_written == reg_id) & (reg_id != 0)) return { - "reg_val": Mux(forward, written_value, self.entries.read[0](m, addr=reg_id).data), + "reg_val": Mux(forward, written_value, self.entries.read_resp[0](m).data), "valid": Mux(forward, 1, self.valids[reg_id]), } - @def_method(m, self.read2) + @def_method(m, self.read_resp2) def _(reg_id: Value): forward = Signal() m.d.av_comb += forward.eq((being_written == reg_id) & (reg_id != 0)) return { - "reg_val": Mux(forward, written_value, self.entries.read[1](m, addr=reg_id).data), + "reg_val": Mux(forward, written_value, self.entries.read_resp[1](m).data), "valid": Mux(forward, 1, self.valids[reg_id]), } diff --git a/coreblocks/scheduler/scheduler.py b/coreblocks/scheduler/scheduler.py index 4b9b03439..4ca4ba2c4 100644 --- a/coreblocks/scheduler/scheduler.py +++ b/coreblocks/scheduler/scheduler.py @@ -187,6 +187,8 @@ def __init__( get_instr: Method, push_instr: Method, rs_select: Sequence[tuple[Method, set[OpType]]], + rf_read_req1: Method, + rf_read_req2: Method, gen_params: GenParams ): """ @@ -202,6 +204,12 @@ def __init__( - A method used for allocating an entry in the RS. Uses `RSLayouts.select_out`. - A set of `OpType`\\s that can be handled by this RS. + rf_read_req1: Method + Method used for requesting value of first source register and information if it is valid. + Uses `RFLayouts.rf_read_out`. + rf_read_req2: Method + Method used for requesting value of second source register and information if it is valid. + Uses `RFLayouts.rf_read_out`. gen_params: GenParams Core generation parameters. """ @@ -214,6 +222,8 @@ def __init__( self.get_instr = get_instr self.rs_select = rs_select self.push_instr = push_instr + self.rf_read_req1 = rf_read_req1 + self.rf_read_req2 = rf_read_req2 def decode_optype_set(self, optypes: set[OpType]) -> int: res = 0x0 @@ -242,6 +252,9 @@ def elaborate(self, platform): self.push_instr(m, data_out) + self.rf_read_req1(m, instr.regs_p.rp_s1) + self.rf_read_req2(m, instr.regs_p.rp_s2) + return m @@ -258,8 +271,8 @@ def __init__( *, get_instr: Method, rs_insert: Sequence[Method], - rf_read1: Method, - rf_read2: Method, + rf_read_resp1: Method, + rf_read_resp2: Method, gen_params: GenParams ): """ @@ -270,10 +283,10 @@ def __init__( rs_insert: Sequence[Method] Sequence of methods used for pushing an instruction into the RS. Ordering of this list determines the ID of a specific RS. They use `RSLayouts.insert_in` - rf_read1: Method + rf_read_resp1: Method Method used for getting value of first source register and information if it is valid. Uses `RFLayouts.rf_read_out` and `RFLayouts.rf_read_in`. - rf_read2: Method + rf_read_resp2: Method Method used for getting value of second source register and information if it is valid. Uses `RFLayouts.rf_read_out` and `RFLayouts.rf_read_in`. gen_params: GenParams @@ -283,8 +296,8 @@ def __init__( self.get_instr = get_instr self.rs_insert = rs_insert - self.rf_read1 = rf_read1 - self.rf_read2 = rf_read2 + self.rf_read_resp1 = rf_read_resp1 + self.rf_read_resp2 = rf_read_resp2 def elaborate(self, platform): m = TModule() @@ -293,8 +306,8 @@ def elaborate(self, platform): # therefore we can use single transaction here. with Transaction().body(m): instr = self.get_instr(m) - source1 = self.rf_read1(m, reg_id=instr.regs_p.rp_s1) - source2 = self.rf_read2(m, reg_id=instr.regs_p.rp_s2) + source1 = self.rf_read_resp1(m, reg_id=instr.regs_p.rp_s1) + source2 = self.rf_read_resp2(m, reg_id=instr.regs_p.rp_s2) # when core is flushed, rp_dst are discarded. # source operands may never become ready, skip waiting for them in any in RSes/FBs. @@ -357,8 +370,10 @@ def __init__( get_free_reg: Method, rat_rename: Method, rob_put: Method, - rf_read1: Method, - rf_read2: Method, + rf_read_req1: Method, + rf_read_req2: Method, + rf_read_resp1: Method, + rf_read_resp2: Method, reservation_stations: Sequence[tuple[FuncBlock, set[OpType]]], gen_params: GenParams ): @@ -375,10 +390,16 @@ def __init__( and `RATLayouts.rat_rename_out`. rob_put: Method Method used for getting a free entry in ROB. Uses `ROBLayouts.data_layout`. - rf_read1: Method + rf_read_req1: Method + Method used for requesting value of first source register and information if it is valid. + Uses `RFLayouts.rf_read_out`. + rf_read_req2: Method + Method used for requesting value of second source register and information if it is valid. + Uses `RFLayouts.rf_read_out`. + rf_read_resp1: Method Method used for getting value of first source register and information if it is valid. Uses `RFLayouts.rf_read_out` and `RFLayouts.rf_read_in`. - rf_read2: Method + rf_read_resp2: Method Method used for getting value of second source register and information if it is valid. Uses `RFLayouts.rf_read_out` and `RFLayouts.rf_read_in`. reservation_stations: Sequence[FuncBlock] @@ -392,8 +413,10 @@ def __init__( self.get_free_reg = get_free_reg self.rat_rename = rat_rename self.rob_put = rob_put - self.rf_read1 = rf_read1 - self.rf_read2 = rf_read2 + self.rf_read_req1 = rf_read_req1 + self.rf_read_req2 = rf_read_req2 + self.rf_read_resp1 = rf_read_resp1 + self.rf_read_resp2 = rf_read_resp2 self.rs = reservation_stations def elaborate(self, platform): @@ -429,13 +452,15 @@ def elaborate(self, platform): get_instr=reg_alloc_out_buf.read, rs_select=[(rs.select, optypes) for rs, optypes in self.rs], push_instr=rs_select_out_buf.write, + rf_read_req1=self.rf_read_req1, + rf_read_req2=self.rf_read_req2, ) m.submodules.rs_insertion = RSInsertion( get_instr=rs_select_out_buf.read, rs_insert=[rs.insert for rs, _ in self.rs], - rf_read1=self.rf_read1, - rf_read2=self.rf_read2, + rf_read_resp1=self.rf_read_resp1, + rf_read_resp2=self.rf_read_resp2, gen_params=self.gen_params, ) diff --git a/requirements.txt b/requirements.txt index 09401a88a..2a56d7ffc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ amaranth-stubs @ git+https://github.com/kuznia-rdzeni/amaranth-stubs.git@edb302b001433edf4c8568190adc9bd0c0039f45 -transactron @ git+https://github.com/kuznia-rdzeni/transactron.git@82aceee58db05498ffd8c4dd515bcb834bb0cf88 +transactron @ git+https://github.com/kuznia-rdzeni/transactron.git@e38f872b1875a6ca460a7d173e1bf2072c22ddcc amaranth-yosys==0.40.0.0.post100 amaranth==0.5.3 dataclasses-json==0.6.3 diff --git a/test/scheduler/test_rs_selection.py b/test/scheduler/test_rs_selection.py index 9a7e7d48b..deb7d9be6 100644 --- a/test/scheduler/test_rs_selection.py +++ b/test/scheduler/test_rs_selection.py @@ -4,7 +4,7 @@ from amaranth import * from coreblocks.params import GenParams -from coreblocks.interface.layouts import RSLayouts, SchedulerLayouts +from coreblocks.interface.layouts import RFLayouts, RSLayouts, SchedulerLayouts from coreblocks.arch import Funct3, Funct7 from coreblocks.arch import OpType from coreblocks.params.configurations import test_core_config @@ -26,6 +26,7 @@ def elaborate(self, platform): m = Module() rs_layouts = self.gen_params.get(RSLayouts, rs_entries_bits=self.gen_params.max_rs_entries_bits) + rf_layouts = self.gen_params.get(RFLayouts) scheduler_layouts = self.gen_params.get(SchedulerLayouts) # data structures @@ -37,6 +38,8 @@ def elaborate(self, platform): m.submodules.instr_out = self.instr_out = TestbenchIO(AdapterTrans(out_fifo.read)) m.submodules.rs1_alloc = self.rs1_alloc = TestbenchIO(Adapter(o=rs_layouts.rs.select_out)) m.submodules.rs2_alloc = self.rs2_alloc = TestbenchIO(Adapter(o=rs_layouts.rs.select_out)) + m.submodules.rf_read_req1 = self.rf_read_req1 = TestbenchIO(Adapter(i=rf_layouts.rf_read_in)) + m.submodules.rf_read_req2 = self.rf_read_req2 = TestbenchIO(Adapter(i=rf_layouts.rf_read_in)) # rs selector m.submodules.selector = self.selector = RSSelection( @@ -44,6 +47,8 @@ def elaborate(self, platform): get_instr=instr_fifo.read, rs_select=[(self.rs1_alloc.adapter.iface, _rs1_optypes), (self.rs2_alloc.adapter.iface, _rs2_optypes)], push_instr=out_fifo.write, + rf_read_req1=self.rf_read_req1.adapter.iface, + rf_read_req2=self.rf_read_req2.adapter.iface, ) return m @@ -114,6 +119,14 @@ def eff(): return process() + @def_method_mock(lambda self: self.m.rf_read_req1) + def rf_read_req1_mock(self, reg_id): + pass + + @def_method_mock(lambda self: self.m.rf_read_req2) + def rf_read_req2_mock(self, reg_id): + pass + def create_output_process(self, instr_count: int, random_wait: int = 0): async def process(sim: TestbenchContext): for _ in range(instr_count): diff --git a/test/scheduler/test_scheduler.py b/test/scheduler/test_scheduler.py index 9c54c043b..1489ef2b5 100644 --- a/test/scheduler/test_scheduler.py +++ b/test/scheduler/test_scheduler.py @@ -99,8 +99,10 @@ def elaborate(self, platform): get_free_reg=free_rf_fifo.read, rat_rename=rat.rename, rob_put=self.rob.put, - rf_read1=self.rf.read1, - rf_read2=self.rf.read2, + rf_read_req1=self.rf.read_req1, + rf_read_req2=self.rf.read_req2, + rf_read_resp1=self.rf.read_resp1, + rf_read_resp2=self.rf.read_resp2, reservation_stations=rs_blocks, gen_params=self.gen_params, ) diff --git a/test/test_core.py b/test/test_core.py index 0914e293c..d56350fd2 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -3,12 +3,11 @@ from amaranth import * from amaranth.lib.wiring import connect from amaranth_types import ValueLike -from transactron.lib import AdapterTrans from transactron.testing.tick_count import TicksKey from transactron.utils import align_to_power_of_two -from transactron.testing import TestCaseWithSimulator, ProcessContext, TestbenchContext, TestbenchIO +from transactron.testing import TestCaseWithSimulator, ProcessContext, TestbenchContext from coreblocks.arch.isa_consts import PrivilegeLevel from coreblocks.core import Core @@ -56,7 +55,6 @@ def elaborate(self, platform): m.submodules.wb_mem_slave = self.wb_mem_slave m.submodules.wb_mem_slave_data = self.wb_mem_slave_data m.submodules.c = self.core - m.submodules.rf_read = self.rf_read = TestbenchIO(AdapterTrans(self.core.RF.read1)) connect(m, self.core.wb_instr, self.wb_mem_slave.bus) connect(m, self.core.wb_data, self.wb_mem_slave_data.bus) @@ -71,8 +69,9 @@ class TestCoreBase(TestCaseWithSimulator): def get_phys_reg_rrat(self, sim: TestbenchContext, reg_id): return sim.get(self.m.core.RRAT.entries[reg_id]) - async def get_arch_reg_val(self, sim: TestbenchContext, reg_id): - return (await self.m.rf_read.call(sim, reg_id=self.get_phys_reg_rrat(sim, reg_id))).reg_val + def get_arch_reg_val(self, sim: TestbenchContext, reg_id): + # TODO: better stubs for memory, remove ignore + return sim.get(self.m.core.RF.entries.mem.data[(self.get_phys_reg_rrat(sim, reg_id))]) # type: ignore class TestCoreAsmSourceBase(TestCoreBase): @@ -162,7 +161,7 @@ async def run_and_check(self, sim: TestbenchContext): await self.tick(sim, self.cycle_count) for reg_id, val in self.expected_regvals.items(): - assert (await self.get_arch_reg_val(sim, reg_id)) == val + assert self.get_arch_reg_val(sim, reg_id) == val def test_asm_source(self): self.gen_params = GenParams(self.configuration) @@ -277,23 +276,23 @@ async def do_interrupt(): if early_interrupt: # wait until interrupts are cleared, so it won't be missed await sim.tick().until(self.m.core.interrupt_controller.mip.value == 0) - assert (await self.get_arch_reg_val(sim, 30)) == int_count + assert self.get_arch_reg_val(sim, 30) == int_count int_count += await do_interrupt() else: await sim.tick().until(self.m.core.interrupt_controller.mip.value == 0) - assert (await self.get_arch_reg_val(sim, 30)) == int_count + assert self.get_arch_reg_val(sim, 30) == int_count handler_count += 1 # wait until ISR returns await sim.tick().until(self.m.core.interrupt_controller.mstatus_mie.value != 0) - assert (await self.get_arch_reg_val(sim, 30)) == int_count - assert (await self.get_arch_reg_val(sim, 27)) == handler_count + assert self.get_arch_reg_val(sim, 30) == int_count + assert self.get_arch_reg_val(sim, 27) == handler_count for reg_id, val in self.expected_regvals.items(): - assert (await self.get_arch_reg_val(sim, reg_id)) == val + assert self.get_arch_reg_val(sim, reg_id) == val def test_interrupted_prog(self): bin_src = self.prepare_source(self.source_file) @@ -359,7 +358,7 @@ async def wait_or_timeout(cond: ValueLike, pred: Callable[[Any], bool]): await self.random_wait(sim, 5) for reg_id, val in self.expected_regvals.items(): - assert (await self.get_arch_reg_val(sim, reg_id)) == val + assert self.get_arch_reg_val(sim, reg_id) == val def test_interrupted_prog(self): bin_src = self.prepare_source(self.source_file) From f7af481bc043b6e698fb55fbb9fadf2735287f6c Mon Sep 17 00:00:00 2001 From: Marek Materzok Date: Fri, 29 Nov 2024 12:26:11 +0100 Subject: [PATCH 3/3] Update Transactron --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2a56d7ffc..d83ef49e2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ amaranth-stubs @ git+https://github.com/kuznia-rdzeni/amaranth-stubs.git@edb302b001433edf4c8568190adc9bd0c0039f45 -transactron @ git+https://github.com/kuznia-rdzeni/transactron.git@e38f872b1875a6ca460a7d173e1bf2072c22ddcc +transactron @ git+https://github.com/kuznia-rdzeni/transactron.git@08fd4baa5bdea7617ace0ab0a9348bda623c4017 amaranth-yosys==0.40.0.0.post100 amaranth==0.5.3 dataclasses-json==0.6.3