diff --git a/rowhammer_tester/gateware/payload_executor.py b/rowhammer_tester/gateware/payload_executor.py index 0638052ec..ccce97b46 100644 --- a/rowhammer_tester/gateware/payload_executor.py +++ b/rowhammer_tester/gateware/payload_executor.py @@ -386,6 +386,7 @@ class Fetcher(Module): """ def __init__(self, mem_addr, stall, jump, jump_offset, pipeline_delay=2): + self.reset_pc = Signal() self.program_counter = Signal.like(mem_addr, reset=0) self.program_counter_old = Signal.like(mem_addr, reset=0) self.next_addr = Signal.like(mem_addr) @@ -407,7 +408,11 @@ def __init__(self, mem_addr, stall, jump, jump_offset, pipeline_delay=2): ~stall, self.program_counter.eq(self.next_addr), self.program_counter_old.eq(self.program_counter), - ) + ).Elif( + self.reset_pc, + self.program_counter.eq(0), + self.program_counter_old.eq(0), + ), ] @@ -592,6 +597,7 @@ def __init__( "READY", self.stall.eq(1), self.ready.eq(1), + self.fetcher.reset_pc.eq(1), If( self.start, NextValue(dfi_switch.wants_dfi, 1), diff --git a/tests/test_payload_executor.py b/tests/test_payload_executor.py index 43c4ce121..62c994335 100644 --- a/tests/test_payload_executor.py +++ b/tests/test_payload_executor.py @@ -1386,6 +1386,7 @@ def generator(dut, payload): yield dut.payload_executor.start.eq(1) yield yield dut.payload_executor.start.eq(0) + yield for instr in payload: while (yield dut.payload_executor.stall): @@ -1421,6 +1422,51 @@ def generator(dut, payload): op_codes = [OpCode.ACT, OpCode.READ, OpCode.PRE, OpCode.REF] self.assert_history(dut.dfi_history, op_codes) + def test_multiple_runs(self): + def run_payload(dut): + def generator(dut): + yield dut.dfii._control.fields.mode_2n.eq(0) + yield dut.dfii._control.fields.reset_n.eq(1) + yield dut.payload_executor.start.eq(1) + yield + yield dut.payload_executor.start.eq(0) + yield + while not (yield dut.payload_executor.ready): + yield + + self.assertEqual((yield dut.payload_executor.fetcher.reset_pc), 1) + yield + self.assertEqual((yield dut.payload_executor.fetcher.program_counter), 0) + yield + self.assertEqual((yield dut.payload_executor.fetcher.program_counter_old), 0) + yield dut.payload_executor.start.eq(1) + yield + yield dut.payload_executor.start.eq(0) + yield + while not (yield dut.payload_executor.ready): + yield + + run_simulation( + dut, + [generator(dut), *dut.get_generators()], + vcd_name="test_multiple_runs.vcd", + ) + + encoder = Encoder(bankbits=5) + payload = ( + encoder(OpCode.ACT, timeslice=10, address=encoder.address(bank=1, row=100)) + + encoder(OpCode.READ, timeslice=3, address=encoder.address(bank=1, col=13)) + + encoder(OpCode.PRE, timeslice=10, address=encoder.address(bank=1)) + + encoder(OpCode.REF, timeslice=15) + ) + + dut = PayloadExecutorDDR5DUT(payload) + run_payload(dut) + + # compare DFI history to what payload should yield + op_codes = [OpCode.ACT, OpCode.READ, OpCode.PRE, OpCode.REF] * 2 + self.assert_history(dut.dfi_history, op_codes) + def test_instruction_fetch_jump(self): def run_payload(dut, encoder, payload): def generator(dut, _encoder, payload): @@ -1487,14 +1533,13 @@ def generator(dut, _encoder, payload): yield dut.payload_executor.start.eq(0) # Wait for first instruction - while (not (yield dut.payload_executor.executing)): + while not (yield dut.payload_executor.executing): yield for _ in range(dut.payload_executor.PIPELINE_DELAY): yield idx = 0 while idx < len(payload): - # Compare fetched instruction to expected instr = payload[idx] instruction_encoded = encoder(instr) @@ -1515,10 +1560,9 @@ def generator(dut, _encoder, payload): idx += 1 # Idle for timeslice-1 cycles if not hasattr(instr, "jump"): - for _ in range(max(instr.timeslice-1, 0)): + for _ in range(max(instr.timeslice - 1, 0)): yield - while not (yield dut.payload_executor.ready): yield