forked from libre-chip/cpu
unit_base is basically finished, implemented AddSub[I], didn't check any tests yet
This commit is contained in:
parent
3f6e5cc600
commit
3bd5c77a3f
8 changed files with 21311 additions and 23900 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue