forked from libre-chip/cpu
WIP fixing bugs
This commit is contained in:
parent
5e1238b5c7
commit
59da0aec06
3 changed files with 38211 additions and 16198 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -771,7 +771,7 @@ impl FetchPipeQueueEntry {
|
||||||
.rotate_left(32)
|
.rotate_left(32)
|
||||||
.wrapping_mul(0x92B38C197608A6B) // random prime
|
.wrapping_mul(0x92B38C197608A6B) // random prime
|
||||||
.rotate_right(60);
|
.rotate_right(60);
|
||||||
(random % 8) as u8
|
if random % 32 == 0 { 30 } else { 3 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -799,6 +799,12 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
||||||
async |mut sim| {
|
async |mut sim| {
|
||||||
sim.write(from_fetch.fetch.ready, false).await;
|
sim.write(from_fetch.fetch.ready, false).await;
|
||||||
sim.write(from_fetch.cancel.ready, false).await;
|
sim.write(from_fetch.cancel.ready, false).await;
|
||||||
|
sim.write(
|
||||||
|
from_fetch.next_fetch_block_ids,
|
||||||
|
#[hdl(sim)]
|
||||||
|
(from_fetch.next_fetch_block_ids.ty()).HdlNone(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
sim.write(
|
sim.write(
|
||||||
to_post_decode.inner.data,
|
to_post_decode.inner.data,
|
||||||
to_post_decode.ty().inner.data.HdlNone(),
|
to_post_decode.ty().inner.data.HdlNone(),
|
||||||
|
|
@ -840,12 +846,21 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
||||||
let mut next_id = 0u32;
|
let mut next_id = 0u32;
|
||||||
loop {
|
loop {
|
||||||
let mut sim_queue = queue_debug.ty().new_sim(FetchPipeQueueEntry.default_sim());
|
let mut sim_queue = queue_debug.ty().new_sim(FetchPipeQueueEntry.default_sim());
|
||||||
|
let mut next_fetch_block_ids =
|
||||||
|
from_fetch.next_fetch_block_ids.ty().HdlSome.new_sim(0u8);
|
||||||
for entry in &queue {
|
for entry in &queue {
|
||||||
ArrayVec::try_push_sim(&mut sim_queue, entry)
|
ArrayVec::try_push_sim(&mut sim_queue, entry)
|
||||||
.ok()
|
.ok()
|
||||||
.expect("queue is known to be small enough");
|
.expect("queue is known to be small enough");
|
||||||
|
let _ = ArrayVec::try_push_sim(&mut next_fetch_block_ids, &entry.fetch_block_id);
|
||||||
}
|
}
|
||||||
sim.write(queue_debug, sim_queue).await;
|
sim.write(queue_debug, sim_queue).await;
|
||||||
|
sim.write(
|
||||||
|
from_fetch.next_fetch_block_ids,
|
||||||
|
#[hdl(sim)]
|
||||||
|
(from_fetch.next_fetch_block_ids.ty()).HdlSome(next_fetch_block_ids),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
if let Some(front) = queue.front().filter(|v| v.cycles_left.as_int() == 0) {
|
if let Some(front) = queue.front().filter(|v| v.cycles_left.as_int() == 0) {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
let FetchPipeQueueEntry {
|
let FetchPipeQueueEntry {
|
||||||
|
|
@ -874,6 +889,7 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
||||||
fetch_block_id,
|
fetch_block_id,
|
||||||
id: next_id.cast_to_static::<UInt<_>>(),
|
id: next_id.cast_to_static::<UInt<_>>(),
|
||||||
pc,
|
pc,
|
||||||
|
predicted_next_pc: 0u64,
|
||||||
size_in_bytes: insn.byte_len().cast_to_static::<UInt<_>>(),
|
size_in_bytes: insn.byte_len().cast_to_static::<UInt<_>>(),
|
||||||
kind: insn.wip_decoded_insn_kind(),
|
kind: insn.wip_decoded_insn_kind(),
|
||||||
};
|
};
|
||||||
|
|
@ -890,6 +906,7 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
||||||
fetch_block_id,
|
fetch_block_id,
|
||||||
id: next_id.cast_to_static::<UInt<_>>(),
|
id: next_id.cast_to_static::<UInt<_>>(),
|
||||||
pc: start_pc,
|
pc: start_pc,
|
||||||
|
predicted_next_pc: 0u64,
|
||||||
size_in_bytes: 0u8.cast_to_static::<UInt<_>>(),
|
size_in_bytes: 0u8.cast_to_static::<UInt<_>>(),
|
||||||
kind: WipDecodedInsnKind.Interrupt(DEMO_ILLEGAL_INSN_TRAP),
|
kind: WipDecodedInsnKind.Interrupt(DEMO_ILLEGAL_INSN_TRAP),
|
||||||
},
|
},
|
||||||
|
|
@ -917,10 +934,27 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
||||||
.await;
|
.await;
|
||||||
sim.write(from_fetch.cancel.ready, true).await;
|
sim.write(from_fetch.cancel.ready, true).await;
|
||||||
sim.wait_for_clock_edge(cd.clk).await;
|
sim.wait_for_clock_edge(cd.clk).await;
|
||||||
|
println!(
|
||||||
|
"Dump mock fetch decode pipe queue: {:#?}",
|
||||||
|
Vec::from_iter(queue.iter().map(|v| {
|
||||||
|
DebugAsDisplay(format!(
|
||||||
|
"fid={:#x} pc={:#x}",
|
||||||
|
v.fetch_block_id.as_int(),
|
||||||
|
v.start_pc.as_int(),
|
||||||
|
))
|
||||||
|
}))
|
||||||
|
);
|
||||||
if sim.read_past_bool(to_post_decode.inner.ready, cd.clk).await {
|
if sim.read_past_bool(to_post_decode.inner.ready, cd.clk).await {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
if let HdlSome(_) = sim.read_past(to_post_decode.inner.data, cd.clk).await {
|
if let HdlSome(_) = sim.read_past(to_post_decode.inner.data, cd.clk).await {
|
||||||
queue.pop_front();
|
let Some(v) = queue.pop_front() else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
println!(
|
||||||
|
"mock fetch decode pipe queue pop: fid={:#x} pc={:#x}",
|
||||||
|
v.fetch_block_id.as_int(),
|
||||||
|
v.start_pc.as_int(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for entry in &mut queue {
|
for entry in &mut queue {
|
||||||
|
|
@ -935,7 +969,14 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
||||||
{
|
{
|
||||||
// cancel in-progress fetches from newest to oldest
|
// cancel in-progress fetches from newest to oldest
|
||||||
for _ in 0..*in_progress_fetches_to_cancel {
|
for _ in 0..*in_progress_fetches_to_cancel {
|
||||||
let _ = queue.pop_back();
|
let Some(v) = queue.pop_back() else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
println!(
|
||||||
|
"mock fetch decode pipe queue cancel unpush: fid={:#x} pc={:#x}",
|
||||||
|
v.fetch_block_id.as_int(),
|
||||||
|
v.start_pc.as_int(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !sim.read_past_bool(from_fetch.fetch.ready, cd.clk).await {
|
if !sim.read_past_bool(from_fetch.fetch.ready, cd.clk).await {
|
||||||
|
|
@ -949,6 +990,11 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
||||||
start_pc,
|
start_pc,
|
||||||
fetch_block_id,
|
fetch_block_id,
|
||||||
} = &inner;
|
} = &inner;
|
||||||
|
println!(
|
||||||
|
"mock fetch decode pipe queue push: fid={:#x} pc={:#x}",
|
||||||
|
fetch_block_id.as_int(),
|
||||||
|
start_pc.as_int(),
|
||||||
|
);
|
||||||
queue.push_back(
|
queue.push_back(
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
FetchPipeQueueEntry {
|
FetchPipeQueueEntry {
|
||||||
|
|
@ -979,7 +1025,8 @@ impl ExecuteRetirePipeQueueEntry {
|
||||||
WipDecodedInsn {
|
WipDecodedInsn {
|
||||||
fetch_block_id: 0u8,
|
fetch_block_id: 0u8,
|
||||||
id: 0_hdl_u12,
|
id: 0_hdl_u12,
|
||||||
pc: 0xEEEE_EEEE_EEEE_EEEEu64,
|
pc: 0u64,
|
||||||
|
predicted_next_pc: 0u64,
|
||||||
size_in_bytes: 0_hdl_u4,
|
size_in_bytes: 0_hdl_u4,
|
||||||
kind: WipDecodedInsnKind.NonBranch(),
|
kind: WipDecodedInsnKind.NonBranch(),
|
||||||
},
|
},
|
||||||
|
|
@ -996,7 +1043,13 @@ impl ExecuteRetirePipeQueueEntry {
|
||||||
.rotate_left(32)
|
.rotate_left(32)
|
||||||
.wrapping_mul(0x73161B54984B1C21) // random prime
|
.wrapping_mul(0x73161B54984B1C21) // random prime
|
||||||
.rotate_right(60);
|
.rotate_right(60);
|
||||||
(random % 16) as u8
|
const DELAYS: &[u8; 0x20] = &[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, //
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, //
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2, //
|
||||||
|
3, 3, 3, 3, 4, 5, 6, 50, // 50 for simulating a cache miss or something
|
||||||
|
];
|
||||||
|
DELAYS[(random & 0x1F) as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1052,6 +1105,7 @@ impl MockExecuteState {
|
||||||
fetch_block_id: &insn.fetch_block_id,
|
fetch_block_id: &insn.fetch_block_id,
|
||||||
id: &insn.id,
|
id: &insn.id,
|
||||||
pc,
|
pc,
|
||||||
|
predicted_next_pc: &insn.predicted_next_pc,
|
||||||
size_in_bytes: mock_insn.byte_len().cast_to_static::<UInt<4>>(),
|
size_in_bytes: mock_insn.byte_len().cast_to_static::<UInt<4>>(),
|
||||||
kind: mock_insn.wip_decoded_insn_kind(),
|
kind: mock_insn.wip_decoded_insn_kind(),
|
||||||
};
|
};
|
||||||
|
|
@ -1060,16 +1114,14 @@ impl MockExecuteState {
|
||||||
"insn doesn't match expected:\ninsn: {insn:?}\nexpected insn: {expected_insn:?}"
|
"insn doesn't match expected:\ninsn: {insn:?}\nexpected insn: {expected_insn:?}"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(next_insn) = self.queue.front() {
|
if next_pc != insn.predicted_next_pc.as_int() {
|
||||||
if next_pc != next_insn.insn.pc.as_int() {
|
self.canceling = true;
|
||||||
self.canceling = true;
|
if !passive {
|
||||||
if !passive {
|
println!(
|
||||||
println!(
|
"MockExecuteState: starting canceling {} instruction(s): next_pc={next_pc:#x}, mis-predicted next_pc={}",
|
||||||
"MockExecuteState: starting canceling {} instruction(s): next_pc={next_pc:#x}, mis-predicted next_pc={next_insn_pc}",
|
self.queue.len(),
|
||||||
self.queue.len(),
|
insn.predicted_next_pc
|
||||||
next_insn_pc = next_insn.insn.pc
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(
|
Ok(
|
||||||
|
|
@ -1130,6 +1182,10 @@ impl MockExecuteState {
|
||||||
if !self.used_ids.insert(insn.id.clone()) {
|
if !self.used_ids.insert(insn.id.clone()) {
|
||||||
panic!("next_pc gave a duplicate insn id: {insn:?}");
|
panic!("next_pc gave a duplicate insn id: {insn:?}");
|
||||||
}
|
}
|
||||||
|
println!(
|
||||||
|
"MockExecutionState::start fid={} id={} pc={}",
|
||||||
|
insn.fetch_block_id, insn.id, insn.pc
|
||||||
|
);
|
||||||
self.queue.push_back(
|
self.queue.push_back(
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
ExecuteRetirePipeQueueEntry {
|
ExecuteRetirePipeQueueEntry {
|
||||||
|
|
@ -1187,6 +1243,7 @@ fn mock_execute_retire_pipe(
|
||||||
cd,
|
cd,
|
||||||
async |mut sim| {
|
async |mut sim| {
|
||||||
sim.write(from_post_decode.ready, 0usize).await;
|
sim.write(from_post_decode.ready, 0usize).await;
|
||||||
|
sim.write(from_post_decode.cancel.ready, false).await;
|
||||||
sim.write(
|
sim.write(
|
||||||
retire_output.inner.data,
|
retire_output.inner.data,
|
||||||
retire_output.ty().inner.data.HdlNone(),
|
retire_output.ty().inner.data.HdlNone(),
|
||||||
|
|
@ -1310,6 +1367,8 @@ fn mock_execute_retire_pipe(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
sim.write(from_post_decode.cancel.ready, state.canceling)
|
||||||
|
.await;
|
||||||
sim.wait_for_clock_edge(cd.clk).await;
|
sim.wait_for_clock_edge(cd.clk).await;
|
||||||
println!(
|
println!(
|
||||||
"Dump mock execute retire pipe queue: {:#?}",
|
"Dump mock execute retire pipe queue: {:#?}",
|
||||||
|
|
@ -1322,8 +1381,17 @@ fn mock_execute_retire_pipe(
|
||||||
))
|
))
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
if state.canceling {
|
#[hdl(sim)]
|
||||||
state.finish_cancel();
|
if let HdlSome(v) = sim.read_past(from_post_decode.cancel.data, cd.clk).await {
|
||||||
|
#[hdl(sim)]
|
||||||
|
let () = v;
|
||||||
|
if sim
|
||||||
|
.read_past_bool(from_post_decode.cancel.ready, cd.clk)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
assert!(state.canceling);
|
||||||
|
state.finish_cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if sim.read_past_bool(retire_output.inner.ready, cd.clk).await {
|
if sim.read_past_bool(retire_output.inner.ready, cd.clk).await {
|
||||||
for _ in 0..**ArrayVec::len_sim(&retiring) {
|
for _ in 0..**ArrayVec::len_sim(&retiring) {
|
||||||
|
|
@ -1339,7 +1407,7 @@ fn mock_execute_retire_pipe(
|
||||||
&mut new_insns,
|
&mut new_insns,
|
||||||
*sim.read_past(from_post_decode.ready, cd.clk).await,
|
*sim.read_past(from_post_decode.ready, cd.clk).await,
|
||||||
);
|
);
|
||||||
for insn in dbg!(ArrayVec::elements_sim_ref(&new_insns)) {
|
for insn in ArrayVec::elements_sim_ref(&new_insns) {
|
||||||
state.start(insn, delay_sequence_index);
|
state.start(insn, delay_sequence_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1430,9 +1498,9 @@ fn test_next_pc() {
|
||||||
};
|
};
|
||||||
sim.write_clock(sim.io().cd.clk, false);
|
sim.write_clock(sim.io().cd.clk, false);
|
||||||
sim.write_reset(sim.io().cd.rst, true);
|
sim.write_reset(sim.io().cd.rst, true);
|
||||||
for _cycle in 0..500 {
|
for cycle in 0..800 {
|
||||||
sim.advance_time(SimDuration::from_nanos(500));
|
sim.advance_time(SimDuration::from_nanos(500));
|
||||||
println!("clock tick");
|
println!("clock tick: {cycle}");
|
||||||
sim.write_clock(sim.io().cd.clk, true);
|
sim.write_clock(sim.io().cd.clk, true);
|
||||||
sim.advance_time(SimDuration::from_nanos(500));
|
sim.advance_time(SimDuration::from_nanos(500));
|
||||||
sim.write_clock(sim.io().cd.clk, false);
|
sim.write_clock(sim.io().cd.clk, false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue