diff --git a/coreblocks/params/layouts.py b/coreblocks/params/layouts.py index f6c5ba590..abec94fda 100644 --- a/coreblocks/params/layouts.py +++ b/coreblocks/params/layouts.py @@ -594,3 +594,8 @@ def __init__(self, gen_params: GenParams): ] self.report = self.get + + +class CoreInstructionCounterLayouts: + def __init__(self, gen_params: GenParams): + self.decrement = [("empty", 1)] diff --git a/coreblocks/stages/retirement.py b/coreblocks/stages/retirement.py index de465143c..38b8591f4 100644 --- a/coreblocks/stages/retirement.py +++ b/coreblocks/stages/retirement.py @@ -54,6 +54,7 @@ def elaborate(self, platform): fields = self.gen_params.get(CommonLayoutFields) m.submodules.frat_fix = frat_fix = Forwarder([fields.rl_dst, fields.rp_dst]) + m.submodules.fetch_continue_fwd = fetch_continue_fwd = Forwarder([fields.pc]) with Transaction().body(m): # TODO: do we prefer single precommit call per instruction? @@ -108,8 +109,8 @@ def elaborate(self, platform): # Resume core operation from exception handler # mtvec without mode is [mxlen-1:2], mode is two last bits. Only direct mode is supported - resume_pc = m_csr.mtvec.value & ~(0b11) - self.fetch_continue(m, {"from_pc": 0, "next_pc": resume_pc}) # TODO: add from_pc valid + resume_pc = m_csr.mtvec.read(m) & ~(0b11) + fetch_continue_fwd.write(m, pc=resume_pc) m.d.sync += side_fx.eq(1) @@ -117,4 +118,8 @@ def elaborate(self, platform): data = frat_fix.read(m) self.rename(m, rl_s1=0, rl_s2=0, rl_dst=data["rl_dst"], rp_dst=data["rp_dst"]) + with Transaction().body(m): + pc = fetch_continue_fwd.read(m).pc + self.fetch_continue(m, from_pc=0, next_pc=pc, resume_from_exception=1) + return m diff --git a/coreblocks/structs_common/instr_counter.py b/coreblocks/structs_common/instr_counter.py index 709548858..5717329d6 100644 --- a/coreblocks/structs_common/instr_counter.py +++ b/coreblocks/structs_common/instr_counter.py @@ -1,13 +1,18 @@ from amaranth import * from coreblocks.params.genparams import GenParams -from coreblocks.params.layouts import FetchLayouts +from coreblocks.params.layouts import CoreInstructionCounterLayouts, FetchLayouts from transactron.core import Method, TModule, def_method class CoreInstructionCounter(Elaboratable): + """ + Counts instructions currently processed in core. + Used in exception handling, to wait for core flush to finsh. + """ + def __init__(self, gp: GenParams): self.increment = Method(i=gp.get(FetchLayouts).raw_instr) - self.decrement = Method(o=[("empty", 1)]) + self.decrement = Method(o=gp.get(CoreInstructionCounterLayouts).decrement) self.count = Signal(gp.rob_entries_bits + 1) diff --git a/test/stages/test_retirement.py b/test/stages/test_retirement.py index 30687a77c..9c50142f8 100644 --- a/test/stages/test_retirement.py +++ b/test/stages/test_retirement.py @@ -1,4 +1,4 @@ -from coreblocks.params.layouts import ExceptionRegisterLayouts +from coreblocks.params.layouts import CoreInstructionCounterLayouts, ExceptionRegisterLayouts, FetchLayouts from coreblocks.stages.retirement import * from coreblocks.structs_common.csr_generic import GenericCSRRegisters @@ -24,6 +24,8 @@ def elaborate(self, platform): lsu_layouts = self.gen_params.get(LSULayouts) scheduler_layouts = self.gen_params.get(SchedulerLayouts) exception_layouts = self.gen_params.get(ExceptionRegisterLayouts) + fetch_layouts = self.gen_params.get(FetchLayouts) + core_instr_counter_layouts = self.gen_params.get(CoreInstructionCounterLayouts) m.submodules.r_rat = self.rat = RRAT(gen_params=self.gen_params) m.submodules.f_rat = self.frat = FRAT(gen_params=self.gen_params) @@ -43,6 +45,14 @@ def elaborate(self, platform): m.submodules.generic_csr = self.generic_csr = GenericCSRRegisters(self.gen_params) self.gen_params.get(DependencyManager).add_dependency(GenericCSRRegistersKey(), self.generic_csr) + m.submodules.mock_fetch_stall = self.mock_fetch_stall = TestbenchIO(Adapter()) + m.submodules.mock_fetch_continue = self.mock_fetch_continue = TestbenchIO( + Adapter(i=fetch_layouts.branch_verify) + ) + m.submodules.mock_instr_decrement = self.mock_instr_decrement = TestbenchIO( + Adapter(o=core_instr_counter_layouts.decrement) + ) + m.submodules.retirement = self.retirement = Retirement( self.gen_params, rob_retire=self.mock_rob_retire.adapter.iface, @@ -53,6 +63,9 @@ def elaborate(self, platform): precommit=self.mock_precommit.adapter.iface, exception_cause_get=self.mock_exception_cause.adapter.iface, frat_rename=self.frat.rename, + fetch_stall=self.mock_fetch_stall.adapter.iface, + fetch_continue=self.mock_fetch_continue.adapter.iface, + instr_decrement=self.mock_instr_decrement.adapter.iface, ) m.submodules.free_rf_fifo_adapter = self.free_rf_adapter = TestbenchIO(AdapterTrans(self.free_rf.read)) @@ -93,6 +106,8 @@ def setUp(self): def test_rand(self): retc = RetirementTestCircuit(self.gen_params) + yield from retc.mock_fetch_stall.enable() + @def_method_mock(lambda: retc.mock_rob_retire, enable=lambda: bool(self.submit_q), sched_prio=1) def retire_process(): return self.submit_q.popleft()