next_pc works afaict

This commit is contained in:
Jacob Lifshay 2025-12-16 23:06:32 -08:00
parent 59da0aec06
commit d5a7d9dd9e
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
3 changed files with 293695 additions and 38183 deletions

View file

@ -326,7 +326,9 @@ impl MockInsn {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct MockMachineState {
reset_at_exit: bool,
call_stack: Vec<u64>,
orig_input: &'static [u8],
input: &'static [u8],
output: Vec<u8>,
regs: MockRegs,
@ -340,16 +342,36 @@ const RESET_PC: u64 = 0;
const EXIT_PC: u64 = u64::from_be_bytes(*b"ExitExit");
impl MockMachineState {
fn new(insns: MockInsns, input: impl AsRef<[u8]>) -> Self {
fn new(insns: MockInsns, input: impl AsRef<[u8]>, reset_at_exit: bool) -> Self {
let input = Interned::into_inner(input.as_ref().intern());
Self {
reset_at_exit,
call_stack: Vec::with_capacity(16),
input: Interned::into_inner(input.as_ref().intern()),
orig_input: input,
input,
output: Vec::with_capacity(16),
regs: MockRegs::new(),
pc: RESET_PC,
insns,
}
}
fn reset(&mut self) {
let Self {
reset_at_exit: _,
call_stack,
orig_input,
input,
output,
regs,
pc,
insns: _,
} = self;
call_stack.clear();
*input = *orig_input;
output.clear();
*regs = MockRegs::new();
*pc = RESET_PC;
}
fn run_one(&mut self, trace: bool) -> RetireSeqEntry {
let orig_pc = self.pc;
let insn = self
@ -420,7 +442,18 @@ impl MockMachineState {
next_pc = target;
}
MockInsn::Ret => next_pc = self.call_stack.pop().unwrap_or(DEMO_ILLEGAL_INSN_TRAP),
MockInsn::ExitSysCall => next_pc = EXIT_PC,
MockInsn::ExitSysCall => {
if self.reset_at_exit {
self.reset();
return RetireSeqEntry {
pc: orig_pc,
cond_br_taken: None,
insn,
};
} else {
next_pc = EXIT_PC;
}
}
MockInsn::Illegal => next_pc = DEMO_ILLEGAL_INSN_TRAP,
}
self.pc = next_pc;
@ -721,7 +754,7 @@ fn test_program_expr_parser() {
#[track_caller]
fn test(expected_output: &str, expected_exit_code: u64, input: &str) {
println!("starting new test case: input={input:?}\n\n");
let mut state = MockMachineState::new(mock_program_expr_parser(), input);
let mut state = MockMachineState::new(mock_program_expr_parser(), input, false);
let exit_code = state.run_until_exit(10000, true).unwrap();
println!("output: {:?}", str::from_utf8(&state.output));
println!("exit code: {exit_code}");
@ -1250,8 +1283,8 @@ fn mock_execute_retire_pipe(
)
.await;
sim.write(
retire_output.next_insn_ids,
retire_output.next_insn_ids.ty().HdlNone(),
retire_output.next_insns,
retire_output.next_insns.ty().HdlNone(),
)
.await;
sim.write(
@ -1294,7 +1327,7 @@ fn mock_execute_retire_pipe(
let config = from_post_decode.config.ty();
let mut state = MockExecuteState::new(
config,
RetireSeq::new(MockMachineState::new(mock_insns, mock_input)),
RetireSeq::new(MockMachineState::new(mock_insns, mock_input, true)),
);
let empty_retire_insn = #[hdl(sim)]
RetireToNextPcInterfacePerInsn::<_> {
@ -1312,22 +1345,32 @@ fn mock_execute_retire_pipe(
let mut sim_queue = queue_debug
.ty()
.new_sim(ExecuteRetirePipeQueueEntry.default_sim());
let mut next_insn_ids = retire_output.next_insn_ids.ty().HdlSome.new_sim(0_hdl_u12);
let mut next_insns = retire_output.next_insns.ty().HdlSome.new_sim(
#[hdl(sim)]
WipDecodedInsn {
fetch_block_id: 0u8,
id: 0_hdl_u12,
pc: 0u64,
predicted_next_pc: 0u64,
size_in_bytes: 0_hdl_u4,
kind: WipDecodedInsnKind.NonBranch(),
},
);
for entry in &state.queue {
ArrayVec::try_push_sim(&mut sim_queue, entry)
.ok()
.expect("queue is known to be small enough");
let _ = ArrayVec::try_push_sim(&mut next_insn_ids, &entry.insn.id);
let _ = ArrayVec::try_push_sim(&mut next_insns, &entry.insn);
}
sim.write(queue_debug, sim_queue).await;
sim.write(
retire_output.next_insn_ids,
retire_output.next_insns,
if state.canceling {
#[hdl(sim)]
(retire_output.next_insn_ids.ty()).HdlNone()
(retire_output.next_insns.ty()).HdlNone()
} else {
#[hdl(sim)]
(retire_output.next_insn_ids.ty()).HdlSome(next_insn_ids)
(retire_output.next_insns.ty()).HdlSome(next_insns)
},
)
.await;
@ -1498,7 +1541,7 @@ fn test_next_pc() {
};
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
for cycle in 0..800 {
for cycle in 0..2000 {
sim.advance_time(SimDuration::from_nanos(500));
println!("clock tick: {cycle}");
sim.write_clock(sim.io().cd.clk, true);