forked from libre-chip/cpu
WIP fixing bugs
This commit is contained in:
parent
84e4fde512
commit
d42f010cda
3 changed files with 17859 additions and 14030 deletions
|
|
@ -460,6 +460,7 @@ struct MockExecuteState {
|
|||
queue: VecDeque<SimValue<ExecuteRetirePipeQueueEntry>>,
|
||||
used_ids: BTreeSet<SimValue<UInt<12>>>,
|
||||
retire_seq: RetireSeq,
|
||||
canceling: bool,
|
||||
config: PhantomConst<CpuConfig>,
|
||||
}
|
||||
|
||||
|
|
@ -469,6 +470,7 @@ impl MockExecuteState {
|
|||
queue: VecDeque::new(),
|
||||
used_ids: BTreeSet::new(),
|
||||
retire_seq: RetireSeq::new(),
|
||||
canceling: false,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
|
@ -483,6 +485,7 @@ impl MockExecuteState {
|
|||
fn do_retire(
|
||||
&mut self,
|
||||
entry: SimValue<ExecuteRetirePipeQueueEntry>,
|
||||
passive: bool,
|
||||
) -> Result<SimValue<RetireToNextPcInterfacePerInsn<PhantomConst<CpuConfig>>>, String> {
|
||||
#[hdl(sim)]
|
||||
let ExecuteRetirePipeQueueEntry {
|
||||
|
|
@ -549,6 +552,18 @@ impl MockExecuteState {
|
|||
"insn doesn't match expected:\ninsn: {insn:?}\nexpected insn: {expected_insn:?}"
|
||||
));
|
||||
}
|
||||
if let Some(next_insn) = self.queue.front() {
|
||||
if next_pc != next_insn.insn.pc.as_int() {
|
||||
self.canceling = true;
|
||||
if !passive {
|
||||
println!(
|
||||
"MockExecuteState: starting canceling {} instruction(s): next_pc={next_pc:#x}, mis-predicted next_pc={next_insn_pc}",
|
||||
self.queue.len(),
|
||||
next_insn_pc = next_insn.insn.pc
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(
|
||||
#[hdl(sim)]
|
||||
RetireToNextPcInterfacePerInsn::<_> {
|
||||
|
|
@ -569,16 +584,20 @@ impl MockExecuteState {
|
|||
#[hdl]
|
||||
fn try_retire(
|
||||
&mut self,
|
||||
passive: bool,
|
||||
) -> Option<(
|
||||
SimValue<RetireToNextPcInterfacePerInsn<PhantomConst<CpuConfig>>>,
|
||||
Result<(), String>,
|
||||
)> {
|
||||
if self.canceling {
|
||||
return None;
|
||||
}
|
||||
if self.queue.front()?.cycles_left.as_int() != 0 {
|
||||
return None;
|
||||
}
|
||||
let entry = self.queue.pop_front()?;
|
||||
let id = entry.insn.id.clone();
|
||||
Some(match self.do_retire(entry) {
|
||||
Some(match self.do_retire(entry, passive) {
|
||||
Ok(v) => (v, Ok(())),
|
||||
Err(e) => (
|
||||
#[hdl(sim)]
|
||||
|
|
@ -611,6 +630,16 @@ impl MockExecuteState {
|
|||
},
|
||||
);
|
||||
}
|
||||
#[hdl]
|
||||
fn finish_cancel(&mut self) {
|
||||
println!(
|
||||
"MockExecuteState: finishing canceling {} instruction(s)",
|
||||
self.queue.len(),
|
||||
);
|
||||
self.queue.clear();
|
||||
self.used_ids.clear();
|
||||
self.canceling = false;
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl_module(extern)]
|
||||
|
|
@ -645,7 +674,7 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
|
|||
.await;
|
||||
sim.write(
|
||||
retire_output.next_insn_ids,
|
||||
retire_output.next_insn_ids.ty().new_sim(0_hdl_u12),
|
||||
retire_output.next_insn_ids.ty().HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
|
|
@ -699,7 +728,7 @@ 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);
|
||||
let mut next_insn_ids = retire_output.next_insn_ids.ty().HdlSome.new_sim(0_hdl_u12);
|
||||
for entry in &state.queue {
|
||||
ArrayVec::try_push_sim(&mut sim_queue, entry)
|
||||
.ok()
|
||||
|
|
@ -707,10 +736,20 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
|
|||
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;
|
||||
sim.write(
|
||||
retire_output.next_insn_ids,
|
||||
if state.canceling {
|
||||
#[hdl(sim)]
|
||||
(retire_output.next_insn_ids.ty()).HdlNone()
|
||||
} else {
|
||||
#[hdl(sim)]
|
||||
(retire_output.next_insn_ids.ty()).HdlSome(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, result)) = peek_state.try_retire() {
|
||||
while let Some((peek_retire, result)) = peek_state.try_retire(true) {
|
||||
if result.is_err() && **ArrayVec::len_sim(&retiring) > 0 {
|
||||
break;
|
||||
}
|
||||
|
|
@ -737,7 +776,11 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
|
|||
.await;
|
||||
sim.write(
|
||||
from_post_decode.ready,
|
||||
state.space_available().min(config.get().fetch_width.get()),
|
||||
if state.canceling {
|
||||
0
|
||||
} else {
|
||||
state.space_available().min(config.get().fetch_width.get())
|
||||
},
|
||||
)
|
||||
.await;
|
||||
sim.wait_for_clock_edge(cd.clk).await;
|
||||
|
|
@ -752,9 +795,12 @@ fn mock_execute_retire_pipe(config: PhantomConst<CpuConfig>) {
|
|||
))
|
||||
}))
|
||||
);
|
||||
if state.canceling {
|
||||
state.finish_cancel();
|
||||
}
|
||||
if sim.read_past_bool(retire_output.inner.ready, cd.clk).await {
|
||||
for _ in 0..**ArrayVec::len_sim(&retiring) {
|
||||
match state.try_retire() {
|
||||
match state.try_retire(false) {
|
||||
Some((_, Ok(_))) => {}
|
||||
Some((_, Err(e))) => panic!("retire error: {e}"),
|
||||
None => unreachable!(),
|
||||
|
|
@ -850,7 +896,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..300 {
|
||||
for _cycle in 0..500 {
|
||||
sim.advance_time(SimDuration::from_nanos(500));
|
||||
println!("clock tick");
|
||||
sim.write_clock(sim.io().cd.clk, true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue