unit_base is basically finished, implemented AddSub[I], didn't check any tests yet

This commit is contained in:
Jacob Lifshay 2025-02-20 20:24:14 -08:00
parent 3f6e5cc600
commit 3bd5c77a3f
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
8 changed files with 21311 additions and 23900 deletions

View file

@ -6,7 +6,10 @@ use crate::{
MOp, MOpDestReg, MOpRegNum, MOpTrait, PRegNum, RenameTableName, UnitOutRegNum,
COMMON_MOP_SRC_LEN,
},
unit::{unit_base::UnitForwardingInfo, TrapData, UnitTrait},
unit::{
unit_base::UnitInput, GlobalState, TrapData, UnitOutput, UnitOutputWrite, UnitResult,
UnitResultCompleted, UnitTrait,
},
util::tree_reduce::tree_reduce_with_state,
};
use fayalite::{
@ -17,7 +20,6 @@ use fayalite::{
};
use std::{
collections::{BTreeMap, VecDeque},
marker::PhantomData,
num::NonZeroUsize,
};
@ -54,6 +56,8 @@ pub fn reg_alloc(config: &CpuConfig) {
#[hdl]
let fetch_decode_interface: FetchDecodeInterface<DynSize> =
m.input(FetchDecodeInterface[config.fetch_width.get()]);
#[hdl]
let global_state: GlobalState = m.input();
// TODO: propagate traps, branch mis-predictions, and special ops
connect(
fetch_decode_interface.fetch_decode_special_op.data,
@ -85,7 +89,8 @@ pub fn reg_alloc(config: &CpuConfig) {
let selected_unit_indexes =
wire(Array[HdlOption[UInt[config.unit_num_width()]]][config.fetch_width.get()]);
#[hdl]
let renamed_mops = wire(Array[HdlOption[config.unit_mop_in_unit()]][config.fetch_width.get()]);
let renamed_mops =
wire(Array[HdlOption[UnitInput[config.unit_mop_in_unit()]]][config.fetch_width.get()]);
#[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() {
@ -196,19 +201,25 @@ pub fn reg_alloc(config: &CpuConfig) {
let dest_reg = MOpTrait::dest_reg(decoded_insn.mop);
connect(
renamed_mops[fetch_index],
HdlSome(MOpTrait::map_regs(
decoded_insn.mop,
renamed_mop_out_reg.unit_out_reg,
config.p_reg_num_width(),
&mut |src_reg, src_index| {
connect(
rename_table_read_ports[src_index].addr,
#[hdl]
MOpRegNum { value: src_reg },
);
rename_table_read_ports[src_index].data.cast_to_bits()
HdlSome(
#[hdl]
UnitInput::<_> {
mop: MOpTrait::map_regs(
decoded_insn.mop,
renamed_mop_out_reg.unit_out_reg,
config.p_reg_num_width(),
&mut |src_reg, src_index| {
connect(
rename_table_read_ports[src_index].addr,
#[hdl]
MOpRegNum { value: src_reg },
);
rename_table_read_ports[src_index].data.cast_to_bits()
},
),
pc: decoded_insn.pc,
},
)),
),
);
for (reg, reg_kind) in MOpDestReg::regs(dest_reg)
.into_iter()
@ -303,6 +314,8 @@ pub fn reg_alloc(config: &CpuConfig) {
config.fetch_width.get(),
),
);
#[hdl]
let unit_forwarding_info = wire(config.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(
@ -311,6 +324,7 @@ pub fn reg_alloc(config: &CpuConfig) {
SourceLocation::caller(),
);
connect(dyn_unit.cd(unit), cd);
connect(dyn_unit.global_state(unit), global_state);
let unit_to_reg_alloc = dyn_unit.unit_to_reg_alloc(unit);
// TODO: handle assigning multiple instructions to a unit at a time
let assign_to_unit_at_once = NonZeroUsize::new(1).unwrap();
@ -333,8 +347,8 @@ pub fn reg_alloc(config: &CpuConfig) {
);
connect(unit_free_regs_tracker.alloc_out[0].ready, false);
connect(
unit_to_reg_alloc.input_insn.data,
Expr::ty(unit_to_reg_alloc.input_insn).data.HdlNone(),
unit_to_reg_alloc.input.data,
Expr::ty(unit_to_reg_alloc.input).data.HdlNone(),
);
for fetch_index in 0..config.fetch_width.get() {
#[hdl]
@ -343,7 +357,7 @@ pub fn reg_alloc(config: &CpuConfig) {
connect(available_units[fetch_index][unit_index], false);
}
#[hdl]
if !unit_to_reg_alloc.input_insn.ready {
if !unit_to_reg_alloc.input.ready {
// must come after to override connects in loops above
connect(available_units[fetch_index][unit_index], false);
}
@ -354,13 +368,21 @@ pub fn reg_alloc(config: &CpuConfig) {
connect(unit_free_regs_tracker.alloc_out[0].ready, true);
#[hdl]
if let HdlSome(renamed_mop) =
HdlOption::and_then(renamed_mops[fetch_index], |v| dyn_unit.extract_mop(v))
HdlOption::and_then(renamed_mops[fetch_index], |v| {
#[hdl]
let UnitInput::<_> { mop, pc } = v;
let mop = dyn_unit.extract_mop(mop);
HdlOption::map(mop, |mop| {
#[hdl]
UnitInput::<_> { mop, pc }
})
})
{
connect(unit_to_reg_alloc.input_insn.data, HdlSome(renamed_mop));
connect(unit_to_reg_alloc.input.data, HdlSome(renamed_mop));
} else {
connect(
unit_to_reg_alloc.input_insn.data,
HdlSome(Expr::ty(unit_to_reg_alloc.input_insn).data.HdlSome.uninit()),
unit_to_reg_alloc.input.data,
HdlSome(Expr::ty(unit_to_reg_alloc.input).data.HdlSome.uninit()),
);
// FIXME: add hdl_assert(cd.clk, false.to_expr(), "");
}
@ -385,18 +407,37 @@ pub fn reg_alloc(config: &CpuConfig) {
}
}
}
// TODO: connect outputs to other units
connect(unit_to_reg_alloc.unit_forwarding_info, unit_forwarding_info);
connect(
unit_to_reg_alloc.unit_forwarding_info,
#[hdl]
UnitForwardingInfo::<_, _, _> {
unit_output_writes: repeat(
HdlOption[config.unit_output_write()].HdlNone(),
config.units.len(),
),
_phantom: PhantomData,
},
unit_forwarding_info.unit_output_writes[unit_index],
Expr::ty(unit_forwarding_info)
.unit_output_writes
.element()
.HdlNone(),
);
#[hdl]
if let HdlSome(output) = unit_to_reg_alloc.output {
#[hdl]
let UnitOutput::<_, _> { which, result } = output;
#[hdl]
match result {
UnitResult::<_>::Completed(completed) => {
#[hdl]
let UnitResultCompleted::<_> { value, extra_out } = completed;
connect(
unit_forwarding_info.unit_output_writes[unit_index],
HdlSome(
#[hdl]
UnitOutputWrite::<_> { which, value },
),
);
// TODO: handle extra_out
}
UnitResult::<_>::Trap(trap_data) => {
// TODO: handle traps
}
}
}
// TODO: handle cancellation
connect(
unit_to_reg_alloc.cancel_input,