diff --git a/coreblocks/cache/icache.py b/coreblocks/cache/icache.py index 08cd51784..d41559f5b 100644 --- a/coreblocks/cache/icache.py +++ b/coreblocks/cache/icache.py @@ -172,8 +172,6 @@ def elaborate(self, platform): with m.If(refill_finish): m.next = "LOOKUP" - accepting_requests = fsm.ongoing("LOOKUP") & ~needs_refill - # Replacement policy way_selector = Signal(self.params.num_of_ways, reset=1) with m.If(refill_finish): @@ -185,6 +183,9 @@ def elaborate(self, platform): m.d.comb += assign(mem_read_addr, prev_mem_read_addr) mem_read_output_valid = Signal() + forwarding_response_now = Signal() + accepting_requests = ~mem_read_output_valid | forwarding_response_now + with Transaction(name="MemRead").body( m, request=fsm.ongoing("LOOKUP") & (mem_read_output_valid | refill_error_saved) ): @@ -194,6 +195,7 @@ def elaborate(self, platform): tag_hit_any = reduce(operator.or_, tag_hit) with m.If(tag_hit_any | refill_error_saved): + m.d.comb += forwarding_response_now.eq(1) self.perf_hits.incr(m, cond=tag_hit_any) mem_out = Signal(self.params.fetch_block_bytes * 8) for i in OneHotSwitchDynamic(m, Cat(tag_hit)): diff --git a/test/cache/test_icache.py b/test/cache/test_icache.py index f53cff894..e8753fa65 100644 --- a/test/cache/test_icache.py +++ b/test/cache/test_icache.py @@ -330,6 +330,8 @@ def setUp(self) -> None: self.refill_requests = deque() self.issued_requests = deque() + self.accept_refill_request = True + self.refill_in_fly = False self.refill_word_cnt = 0 self.refill_addr = 0 @@ -347,7 +349,7 @@ def init_module(self, ways, sets) -> None: self.cp = self.gen_params.icache_params self.m = ICacheTestCircuit(self.gen_params) - @def_method_mock(lambda self: self.m.refiller.start_refill_mock) + @def_method_mock(lambda self: self.m.refiller.start_refill_mock, enable=lambda self: self.accept_refill_request) def start_refill_mock(self, addr): self.refill_requests.append(addr) self.refill_block_cnt = 0 @@ -631,11 +633,21 @@ def cache_process(): # Schedule two requests and then flush yield from self.send_req(0x00000000 + self.cp.line_size_bytes) yield from self.send_req(0x00010000) - yield from self.m.flush_cache.call() - self.mem[0x00010000] = random.randrange(2**self.gen_params.isa.ilen) - # And accept the results + yield from self.m.flush_cache.call_init() + yield + # We cannot flush until there are two pending requests + self.assertFalse((yield from self.m.flush_cache.done())) + yield + yield from self.m.flush_cache.disable() + yield + + # Accept the first response self.assert_resp((yield from self.m.accept_res.call())) + + yield from self.m.flush_cache.call() + + # And accept the second response ensuring that we got old data self.assert_resp((yield from self.m.accept_res.call())) self.expect_refill(0x00000000 + self.cp.line_size_bytes) @@ -753,6 +765,16 @@ def test_random(self): if random.random() < 0.05: self.add_bad_addr(i) + def refiller_ctrl(): + yield Passive() + + while True: + yield from self.random_wait_geom(0.4) + self.accept_refill_request = False + + yield from self.random_wait_geom(0.7) + self.accept_refill_request = True + def sender(): for _ in range(iterations): yield from self.send_req(random.randrange(0, max_addr, 4)) @@ -773,3 +795,4 @@ def receiver(): with self.run_simulation(self.m) as sim: sim.add_sync_process(sender) sim.add_sync_process(receiver) + sim.add_sync_process(refiller_ctrl)