forked from libre-chip/cpu
fix queueing errors
This commit is contained in:
parent
8ab63f3c6a
commit
84e4fde512
3 changed files with 20332 additions and 15680 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue