fix queueing errors

This commit is contained in:
Jacob Lifshay 2025-12-15 00:47:53 -08:00
parent 8ab63f3c6a
commit 84e4fde512
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
3 changed files with 20332 additions and 15680 deletions

View file

@ -12,7 +12,11 @@ use cpu::{
unit::UnitKind,
util::array_vec::ArrayVec,
};
use fayalite::{prelude::*, sim::vcd::VcdWriterDecls, util::RcWriter};
use fayalite::{
prelude::*,
sim::vcd::VcdWriterDecls,
util::{DebugAsDisplay, RcWriter},
};
use std::{
cell::Cell,
collections::{BTreeMap, BTreeSet, VecDeque},
@ -565,13 +569,31 @@ impl MockExecuteState {
#[hdl]
fn try_retire(
&mut self,
) -> Option<Result<SimValue<RetireToNextPcInterfacePerInsn<PhantomConst<CpuConfig>>>, String>>
{
) -> Option<(
SimValue<RetireToNextPcInterfacePerInsn<PhantomConst<CpuConfig>>>,
Result<(), String>,
)> {
if self.queue.front()?.cycles_left.as_int() != 0 {
return None;
}
let entry = self.queue.pop_front()?;
Some(self.do_retire(entry))
let id = entry.insn.id.clone();
Some(match self.do_retire(entry) {
Ok(v) => (v, Ok(())),
Err(e) => (
#[hdl(sim)]
RetireToNextPcInterfacePerInsn::<_> {
id,
next_pc: u64::from_be_bytes(*b"ErrError"),
call_stack_op: #[hdl(sim)]
CallStackOp::None(),
cond_br_taken: #[hdl(sim)]
HdlNone(),
config: self.config,
},
Err(e),
),
})
}
fn space_available(&self) -> usize {
EXECUTE_RETIRE_PIPE_QUEUE_SIZE.saturating_sub(self.queue.len())
@ -621,6 +643,11 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
retire_output.ty().inner.data.HdlNone(),
)
.await;
sim.write(
retire_output.next_insn_ids,
retire_output.next_insn_ids.ty().new_sim(0_hdl_u12),
)
.await;
sim.write(
queue_debug,
queue_debug
@ -672,30 +699,21 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
let mut sim_queue = queue_debug
.ty()
.new_sim(ExecuteRetirePipeQueueEntry.default_sim());
let mut next_insn_ids = retire_output.next_insn_ids.ty().new_sim(0_hdl_u12);
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);
}
sim.write(queue_debug, sim_queue).await;
sim.write(retire_output.next_insn_ids, next_insn_ids).await;
let mut retiring = retire_vec_ty.new_sim(&empty_retire_insn);
let mut peek_state = state.clone();
while let Some(peek_retire) = peek_state.try_retire() {
if peek_retire.is_err() && **ArrayVec::len_sim(&retiring) > 0 {
while let Some((peek_retire, result)) = peek_state.try_retire() {
if result.is_err() && **ArrayVec::len_sim(&retiring) > 0 {
break;
}
let peek_retire = peek_retire.unwrap_or_else(|_| {
#[hdl(sim)]
RetireToNextPcInterfacePerInsn::<_> {
id: 0_hdl_u12,
next_pc: u64::from_be_bytes(*b"ErrError"),
call_stack_op: #[hdl(sim)]
CallStackOp::None(),
cond_br_taken: #[hdl(sim)]
HdlNone(),
config,
}
});
let Ok(_) = ArrayVec::try_push_sim(&mut retiring, peek_retire) else {
break;
};
@ -723,11 +741,22 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
)
.await;
sim.wait_for_clock_edge(cd.clk).await;
println!(
"Dump mock execute retire pipe queue: {:#?}",
Vec::from_iter(state.queue.iter().map(|v| {
DebugAsDisplay(format!(
"fid={:#x} id={} pc={:#x}",
v.insn.fetch_block_id.as_int(),
v.insn.id,
v.insn.pc.as_int(),
))
}))
);
if sim.read_past_bool(retire_output.inner.ready, cd.clk).await {
for _ in 0..**ArrayVec::len_sim(&retiring) {
match state.try_retire() {
Some(Ok(_)) => {}
Some(Err(e)) => panic!("retire error: {e}"),
Some((_, Ok(_))) => {}
Some((_, Err(e))) => panic!("retire error: {e}"),
None => unreachable!(),
}
}
@ -737,7 +766,7 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
&mut new_insns,
*sim.read_past(from_post_decode.ready, cd.clk).await,
);
for insn in ArrayVec::elements_sim_ref(&new_insns) {
for insn in dbg!(ArrayVec::elements_sim_ref(&new_insns)) {
state.start(insn, delay_sequence_index);
}
}
@ -803,7 +832,7 @@ fn test_next_pc() {
config.fetch_width = NonZeroUsize::new(2).unwrap();
let m = dut(PhantomConst::new_sized(config));
let mut sim = Simulation::new(m);
let mut writer = RcWriter::default();
let writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
struct DumpVcdOnDrop {
writer: Option<RcWriter>,
@ -823,6 +852,7 @@ fn test_next_pc() {
sim.write_reset(sim.io().cd.rst, true);
for _cycle in 0..300 {
sim.advance_time(SimDuration::from_nanos(500));
println!("clock tick");
sim.write_clock(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, false);