start adding ROB
This commit is contained in:
parent
4ff75313e7
commit
6c91d1b0b0
crates/cpu
|
@ -35,6 +35,7 @@ pub struct CpuConfig {
|
|||
pub fetch_width: NonZeroUsize,
|
||||
/// default value for [`UnitConfig::max_in_flight`]
|
||||
pub default_unit_max_in_flight: NonZeroUsize,
|
||||
pub rob_size: NonZeroUsize,
|
||||
}
|
||||
|
||||
impl CpuConfig {
|
||||
|
@ -51,12 +52,13 @@ impl CpuConfig {
|
|||
};
|
||||
v
|
||||
};
|
||||
pub fn new(units: Vec<UnitConfig>) -> Self {
|
||||
pub fn new(units: Vec<UnitConfig>, rob_size: NonZeroUsize) -> Self {
|
||||
Self {
|
||||
units,
|
||||
out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH,
|
||||
fetch_width: Self::DEFAULT_FETCH_WIDTH,
|
||||
default_unit_max_in_flight: Self::DEFAULT_UNIT_MAX_IN_FLIGHT,
|
||||
rob_size,
|
||||
}
|
||||
}
|
||||
pub fn non_const_unit_nums(&self) -> std::ops::Range<usize> {
|
||||
|
|
|
@ -7,8 +7,9 @@ use crate::{
|
|||
COMMON_MOP_SRC_LEN,
|
||||
},
|
||||
unit::{
|
||||
unit_base::UnitInput, GlobalState, TrapData, UnitOutput, UnitOutputWrite, UnitResult,
|
||||
UnitResultCompleted, UnitTrait,
|
||||
unit_base::{UnitForwardingInfo, UnitInput},
|
||||
GlobalState, TrapData, UnitOutput, UnitOutputWrite, UnitResult, UnitResultCompleted,
|
||||
UnitTrait,
|
||||
},
|
||||
util::tree_reduce::tree_reduce_with_state,
|
||||
};
|
||||
|
@ -48,6 +49,145 @@ pub struct FetchDecodeInterface<FetchWidth: Size> {
|
|||
pub fetch_decode_special_op: ReadyValid<FetchDecodeSpecialOp>,
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
struct ROBRenamedInsn<UnitNumWidth: Size, OutRegNumWidth: Size> {
|
||||
mop_dest: MOpDestReg,
|
||||
p_dest: PRegNum<UnitNumWidth, OutRegNumWidth>,
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
struct ROBEntry<UnitNumWidth: Size, OutRegNumWidth: Size> {
|
||||
renamed_insn: ROBRenamedInsn<UnitNumWidth, OutRegNumWidth>,
|
||||
dest_written: Bool,
|
||||
}
|
||||
|
||||
#[hdl_module]
|
||||
fn rob(config: &CpuConfig) {
|
||||
#[hdl]
|
||||
let cd: ClockDomain = m.input();
|
||||
#[hdl]
|
||||
let renamed_insns_in: Array<ReadyValid<ROBRenamedInsn<DynSize, DynSize>>> = m.input(
|
||||
Array[ReadyValid[ROBRenamedInsn[config.unit_num_width()][config.out_reg_num_width]]]
|
||||
[config.fetch_width.get()],
|
||||
);
|
||||
#[hdl]
|
||||
let unit_forwarding_info: UnitForwardingInfo<DynSize, DynSize, DynSize> =
|
||||
m.input(config.unit_forwarding_info());
|
||||
|
||||
let rob_entry_ty = ROBEntry[config.unit_num_width()][config.out_reg_num_width];
|
||||
#[hdl]
|
||||
let rob = reg_builder()
|
||||
.clock_domain(cd)
|
||||
.no_reset(Array[rob_entry_ty][config.rob_size.get()]);
|
||||
#[hdl]
|
||||
let rob_valid_start = reg_builder()
|
||||
.clock_domain(cd)
|
||||
.reset(UInt::range(0..config.rob_size.get()).zero());
|
||||
#[hdl]
|
||||
let rob_valid_end = reg_builder()
|
||||
.clock_domain(cd)
|
||||
.reset(UInt::range(0..config.rob_size.get()).zero());
|
||||
#[hdl]
|
||||
let free_space = wire(UInt::range_inclusive(0..=config.rob_size.get()));
|
||||
#[hdl]
|
||||
if rob_valid_end.cmp_lt(rob_valid_start) {
|
||||
// rob_valid_end wrapped around but start didn't
|
||||
connect_any(
|
||||
free_space,
|
||||
rob_valid_end + config.rob_size.get() - rob_valid_start,
|
||||
);
|
||||
} else {
|
||||
connect_any(free_space, rob_valid_end - rob_valid_start);
|
||||
}
|
||||
|
||||
struct IndexAndRange {
|
||||
index: Expr<UInt>,
|
||||
range: std::ops::Range<usize>,
|
||||
}
|
||||
|
||||
let mut next_write_index = IndexAndRange {
|
||||
index: rob_valid_end,
|
||||
range: 0..config.rob_size.get(),
|
||||
};
|
||||
for fetch_index in 0..config.fetch_width.get() {
|
||||
let write_index = next_write_index;
|
||||
let next_write_index_range = write_index.range.start..write_index.range.end + 1;
|
||||
next_write_index = IndexAndRange {
|
||||
index: wire_with_loc(
|
||||
&format!("next_write_index_{fetch_index}"),
|
||||
SourceLocation::caller(),
|
||||
UInt::range(next_write_index_range.clone()),
|
||||
),
|
||||
range: next_write_index_range,
|
||||
};
|
||||
connect(
|
||||
renamed_insns_in[fetch_index].ready,
|
||||
fetch_index.cmp_lt(free_space),
|
||||
);
|
||||
#[hdl]
|
||||
if let HdlSome(renamed_insn) = ReadyValid::firing_data(renamed_insns_in[fetch_index]) {
|
||||
for i in write_index.range.clone() {
|
||||
#[hdl]
|
||||
if write_index.index.cmp_eq(i) {
|
||||
connect(
|
||||
rob[i % config.rob_size.get()],
|
||||
#[hdl]
|
||||
ROBEntry {
|
||||
renamed_insn,
|
||||
dest_written: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: optimize write_index chain better
|
||||
connect_any(
|
||||
next_write_index.index,
|
||||
write_index.index
|
||||
+ ReadyValid::firing(renamed_insns_in[fetch_index]).cast_to_static::<UInt<1>>(),
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
config.rob_size >= config.fetch_width,
|
||||
"rob_size ({}) is too small for fetch_width = {} -- next_write_index would overflow",
|
||||
config.rob_size,
|
||||
config.fetch_width,
|
||||
);
|
||||
#[hdl]
|
||||
if next_write_index.index.cmp_lt(config.rob_size.get()) {
|
||||
connect_any(rob_valid_end, next_write_index.index);
|
||||
} else {
|
||||
connect_any(
|
||||
rob_valid_end,
|
||||
next_write_index.index - config.rob_size.get(),
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: optimize better, O(rob_size * unit_count) is too big here
|
||||
for rob_index in 0..config.rob_size.get() {
|
||||
for unit_index in 0..config.non_const_unit_nums().len() {
|
||||
#[hdl]
|
||||
if let HdlSome(unit_output_write) = unit_forwarding_info.unit_output_writes[unit_index]
|
||||
{
|
||||
#[hdl]
|
||||
let UnitOutputWrite::<_> {
|
||||
which: unit_out_reg,
|
||||
value: _,
|
||||
} = unit_output_write;
|
||||
let p_reg_num = #[hdl]
|
||||
PRegNum::<_, _> {
|
||||
unit_num: config.unit_num().from_index(unit_index),
|
||||
unit_out_reg,
|
||||
};
|
||||
#[hdl]
|
||||
if rob[rob_index].renamed_insn.p_dest.cmp_eq(p_reg_num) {
|
||||
connect(rob[rob_index].dest_written, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl_module]
|
||||
/// combination register allocator, register renaming, unit selection, and retire handling
|
||||
pub fn reg_alloc(config: &CpuConfig) {
|
||||
|
@ -65,6 +205,10 @@ pub fn reg_alloc(config: &CpuConfig) {
|
|||
);
|
||||
// TODO: finish
|
||||
|
||||
#[hdl]
|
||||
let rob = instance(rob(config));
|
||||
connect(rob.cd, cd);
|
||||
|
||||
let mut rename_table_mems = BTreeMap::<RenameTableName, MemBuilder<_>>::new();
|
||||
|
||||
for reg_kind in MOpDestReg::REG_KINDS {
|
||||
|
@ -94,10 +238,25 @@ pub fn reg_alloc(config: &CpuConfig) {
|
|||
#[hdl]
|
||||
let renamed_mops_out_reg = wire(Array[HdlOption[config.p_reg_num()]][config.fetch_width.get()]);
|
||||
for fetch_index in 0..config.fetch_width.get() {
|
||||
// TODO: finish
|
||||
connect(
|
||||
rob.renamed_insns_in[fetch_index].data,
|
||||
Expr::ty(rob).renamed_insns_in.element().data.HdlNone(),
|
||||
);
|
||||
// TODO: finish
|
||||
connect(
|
||||
fetch_decode_interface.decoded_insns[fetch_index].ready,
|
||||
true,
|
||||
);
|
||||
for prev_fetch_index in 0..fetch_index {
|
||||
#[hdl]
|
||||
if !fetch_decode_interface.decoded_insns[prev_fetch_index].ready {
|
||||
connect(
|
||||
fetch_decode_interface.decoded_insns[fetch_index].ready,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
connect(
|
||||
available_units[fetch_index],
|
||||
repeat(false, config.units.len()),
|
||||
|
@ -316,6 +475,7 @@ pub fn reg_alloc(config: &CpuConfig) {
|
|||
);
|
||||
#[hdl]
|
||||
let unit_forwarding_info = wire(config.unit_forwarding_info());
|
||||
connect(rob.unit_forwarding_info, unit_forwarding_info);
|
||||
for (unit_index, unit_config) in config.units.iter().enumerate() {
|
||||
let dyn_unit = unit_config.kind.unit(config, unit_index);
|
||||
let unit = instance_with_loc(
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,10 +21,13 @@ use std::num::NonZeroUsize;
|
|||
#[test]
|
||||
fn test_reg_alloc() {
|
||||
let _n = SourceLocation::normalize_files_for_tests();
|
||||
let mut config = CpuConfig::new(vec![
|
||||
UnitConfig::new(UnitKind::AluBranch),
|
||||
UnitConfig::new(UnitKind::AluBranch),
|
||||
]);
|
||||
let mut config = CpuConfig::new(
|
||||
vec![
|
||||
UnitConfig::new(UnitKind::AluBranch),
|
||||
UnitConfig::new(UnitKind::AluBranch),
|
||||
],
|
||||
NonZeroUsize::new(20).unwrap(),
|
||||
);
|
||||
config.fetch_width = NonZeroUsize::new(2).unwrap();
|
||||
let m = reg_alloc(&config);
|
||||
let mut sim = Simulation::new(m);
|
||||
|
|
Loading…
Reference in a new issue