wrote out all of next_pc and tests/next_pc
This commit is contained in:
parent
cfd04469ce
commit
c87a1b8e1e
4 changed files with 1871 additions and 703 deletions
|
|
@ -163,3 +163,15 @@ pub type CpuConfigFetchWidthInBytes<C: PhantomConstGet<CpuConfig>> = DynSize;
|
||||||
|
|
||||||
#[hdl(get(|c| c.rob_size.get()))]
|
#[hdl(get(|c| c.rob_size.get()))]
|
||||||
pub type CpuConfigRobSize<C: PhantomConstGet<CpuConfig>> = DynSize;
|
pub type CpuConfigRobSize<C: PhantomConstGet<CpuConfig>> = DynSize;
|
||||||
|
|
||||||
|
pub trait PhantomConstCpuConfig:
|
||||||
|
PhantomConstGet<CpuConfig>
|
||||||
|
+ Into<PhantomConst<CpuConfig>>
|
||||||
|
+ From<PhantomConst<CpuConfig>>
|
||||||
|
+ Type
|
||||||
|
+ ToSimValue<Type = Self>
|
||||||
|
+ ToExpr<Type = Self>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhantomConstCpuConfig for PhantomConst<CpuConfig> {}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -190,6 +190,35 @@ impl<T: Type, N: Size> ArrayVec<T, N> {
|
||||||
mapped_array_vec
|
mapped_array_vec
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
pub fn map_sim<U: Type>(
|
||||||
|
this: impl ToSimValue<Type = Self>,
|
||||||
|
uninit_element: impl ToSimValue<Type = U>,
|
||||||
|
mut f: impl FnMut(usize, SimValue<T>) -> SimValue<U>,
|
||||||
|
) -> SimValue<ArrayVec<U, N>> {
|
||||||
|
let this = this.into_sim_value();
|
||||||
|
let uninit_element = uninit_element.into_sim_value();
|
||||||
|
let ty = this.ty().mapped_ty(uninit_element.ty());
|
||||||
|
#[hdl(sim)]
|
||||||
|
let Self { elements, len } = this;
|
||||||
|
#[hdl(sim)]
|
||||||
|
ArrayVec::<_, _> {
|
||||||
|
elements: SimValue::from_array_elements(
|
||||||
|
ty.elements,
|
||||||
|
SimValue::into_value(elements)
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, element)| {
|
||||||
|
if index < *len {
|
||||||
|
f(index, element)
|
||||||
|
} else {
|
||||||
|
uninit_element.clone()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
len,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[hdl]
|
||||||
pub fn as_array_of_options(this: impl ToExpr<Type = Self>) -> Expr<ArrayType<HdlOption<T>, N>> {
|
pub fn as_array_of_options(this: impl ToExpr<Type = Self>) -> Expr<ArrayType<HdlOption<T>, N>> {
|
||||||
let this = this.to_expr();
|
let this = this.to_expr();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -217,3 +246,34 @@ where
|
||||||
<ArrayType<T, N> as ExprIndex<Idx>>::expr_index(&this.elements, index)
|
<ArrayType<T, N> as ExprIndex<Idx>>::expr_index(&this.elements, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ArrayVec<T, ConstUsize<1>> {
|
||||||
|
#[hdl]
|
||||||
|
pub fn from_opt_sim(
|
||||||
|
opt: impl ToSimValue<Type = HdlOption<T>>,
|
||||||
|
uninit_element: impl ToSimValueWithType<T>,
|
||||||
|
) -> SimValue<Self> {
|
||||||
|
let opt = opt.into_sim_value();
|
||||||
|
let ty = ArrayVec[opt.ty().HdlSome][ConstUsize];
|
||||||
|
#[hdl(sim)]
|
||||||
|
match opt {
|
||||||
|
HdlSome(v) => ty.new_full_sim([v]),
|
||||||
|
HdlNone => ty.new_sim(uninit_element),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[hdl]
|
||||||
|
pub fn into_opt_sim(this: impl ToSimValue<Type = Self>) -> SimValue<HdlOption<T>> {
|
||||||
|
let this = this.into_sim_value();
|
||||||
|
#[hdl(sim)]
|
||||||
|
let Self { elements, len } = this;
|
||||||
|
let [element] = SimValue::into_value(elements);
|
||||||
|
let ty = HdlOption[element.ty()];
|
||||||
|
if *len == 0 {
|
||||||
|
#[hdl(sim)]
|
||||||
|
ty.HdlNone()
|
||||||
|
} else {
|
||||||
|
#[hdl(sim)]
|
||||||
|
ty.HdlSome(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ const DEMO_ILLEGAL_INSN_TRAP: u64 = 0xFF000000u64;
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
struct FetchPipeQueueEntry {
|
struct FetchPipeQueueEntry {
|
||||||
fetch_pc: UInt<64>,
|
start_pc: UInt<64>,
|
||||||
cycles_left: UInt<8>,
|
cycles_left: UInt<8>,
|
||||||
fetch_block_id: UInt<{ FETCH_BLOCK_ID_WIDTH }>,
|
fetch_block_id: UInt<{ FETCH_BLOCK_ID_WIDTH }>,
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +88,7 @@ impl FetchPipeQueueEntry {
|
||||||
fn default_sim(self) -> SimValue<Self> {
|
fn default_sim(self) -> SimValue<Self> {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
FetchPipeQueueEntry {
|
FetchPipeQueueEntry {
|
||||||
fetch_pc: 0u64,
|
start_pc: 0u64,
|
||||||
cycles_left: 0u8,
|
cycles_left: 0u8,
|
||||||
fetch_block_id: 0u8,
|
fetch_block_id: 0u8,
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +129,8 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>) {
|
||||||
sim.resettable(
|
sim.resettable(
|
||||||
cd,
|
cd,
|
||||||
async |mut sim| {
|
async |mut sim| {
|
||||||
sim.write(from_fetch.inner.ready, false).await;
|
sim.write(from_fetch.fetch.ready, false).await;
|
||||||
|
sim.write(from_fetch.cancel.ready, false).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(),
|
||||||
|
|
@ -179,21 +180,21 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>) {
|
||||||
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 {
|
||||||
fetch_pc,
|
start_pc,
|
||||||
cycles_left: _,
|
cycles_left: _,
|
||||||
fetch_block_id,
|
fetch_block_id,
|
||||||
} = front;
|
} = front;
|
||||||
let fetch_pc = fetch_pc.as_int();
|
let start_pc = start_pc.as_int();
|
||||||
let fetch_end =
|
let end_pc =
|
||||||
(fetch_pc + 1).next_multiple_of(config.get().fetch_width_in_bytes() as u64);
|
(start_pc + 1).next_multiple_of(config.get().fetch_width_in_bytes() as u64);
|
||||||
let insns = to_post_decode.ty().inner.data.HdlSome.insns;
|
let insns = to_post_decode.ty().inner.data.HdlSome.insns;
|
||||||
let zeroed_insn = UInt[insns.element().canonical().bit_width()]
|
let zeroed_insn = UInt[insns.element().canonical().bit_width()]
|
||||||
.zero()
|
.zero()
|
||||||
.cast_bits_to(insns.element());
|
.cast_bits_to(insns.element());
|
||||||
let mut insns = insns.new_sim(zeroed_insn);
|
let mut insns = insns.new_sim(zeroed_insn);
|
||||||
let mut expected_pc = fetch_pc;
|
let mut expected_pc = start_pc;
|
||||||
// TODO: handle instructions that go past the end of a fetch block
|
// TODO: handle instructions that go past the end of a fetch block
|
||||||
for (pc, insn) in mock_insns.fetch_block(fetch_pc..fetch_end) {
|
for (pc, insn) in mock_insns.fetch_block(start_pc..end_pc) {
|
||||||
let next_pc = pc + insn.byte_len();
|
let next_pc = pc + insn.byte_len();
|
||||||
if pc != expected_pc {
|
if pc != expected_pc {
|
||||||
break;
|
break;
|
||||||
|
|
@ -226,7 +227,7 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>) {
|
||||||
WipDecodedInsn {
|
WipDecodedInsn {
|
||||||
fetch_block_id,
|
fetch_block_id,
|
||||||
id: next_id.cast_to_static::<UInt<_>>(),
|
id: next_id.cast_to_static::<UInt<_>>(),
|
||||||
pc: fetch_pc,
|
pc: start_pc,
|
||||||
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),
|
||||||
},
|
},
|
||||||
|
|
@ -250,8 +251,9 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>) {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
sim.write(from_fetch.inner.ready, queue.len() < FETCH_PIPE_QUEUE_SIZE)
|
sim.write(from_fetch.fetch.ready, queue.len() < FETCH_PIPE_QUEUE_SIZE)
|
||||||
.await;
|
.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;
|
||||||
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)]
|
||||||
|
|
@ -264,25 +266,31 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>) {
|
||||||
entry.cycles_left = (entry.cycles_left.as_int() - 1u8).to_sim_value();
|
entry.cycles_left = (entry.cycles_left.as_int() - 1u8).to_sim_value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !sim.read_past_bool(from_fetch.inner.ready, cd.clk).await {
|
// handle cancels before pushing new fetch op
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
if let HdlSome(inner) = sim.read_past(from_fetch.inner.data, cd.clk).await {
|
if let HdlSome(in_progress_fetches_to_cancel) =
|
||||||
#[hdl(sim)]
|
sim.read_past(from_fetch.cancel.data, cd.clk).await
|
||||||
let NextPcToFetchInterfaceInner {
|
{
|
||||||
next_fetch_pc,
|
|
||||||
fetch_block_id,
|
|
||||||
in_progress_fetches_to_cancel,
|
|
||||||
} = &inner;
|
|
||||||
// cancel in-progress fetches from newest to oldest
|
// cancel in-progress fetches from newest to oldest
|
||||||
for _ in 0..in_progress_fetches_to_cancel.as_int() {
|
for _ in 0..*in_progress_fetches_to_cancel {
|
||||||
let _ = queue.pop_back();
|
let _ = queue.pop_back();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !sim.read_past_bool(from_fetch.fetch.ready, cd.clk).await {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// handle pushing new fetch op after handling cancels
|
||||||
|
#[hdl(sim)]
|
||||||
|
if let HdlSome(inner) = sim.read_past(from_fetch.fetch.data, cd.clk).await {
|
||||||
|
#[hdl(sim)]
|
||||||
|
let NextPcToFetchInterfaceInner {
|
||||||
|
start_pc,
|
||||||
|
fetch_block_id,
|
||||||
|
} = &inner;
|
||||||
queue.push_back(
|
queue.push_back(
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
FetchPipeQueueEntry {
|
FetchPipeQueueEntry {
|
||||||
fetch_pc: next_fetch_pc,
|
start_pc,
|
||||||
cycles_left: FetchPipeQueueEntry::get_next_delay(delay_sequence_index),
|
cycles_left: FetchPipeQueueEntry::get_next_delay(delay_sequence_index),
|
||||||
fetch_block_id,
|
fetch_block_id,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue