forked from libre-chip/cpu
next_pc works afaict
This commit is contained in:
parent
59da0aec06
commit
d5a7d9dd9e
3 changed files with 293695 additions and 38183 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue