forked from libre-chip/cpu
unit::alu_branch: convert *MOp functions to hdl_module
This commit is contained in:
parent
42056ce6b5
commit
a3898e8c13
5 changed files with 155663 additions and 115637 deletions
|
|
@ -26,13 +26,20 @@ use fayalite::{
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, ops::RangeTo};
|
use std::{collections::HashMap, ops::RangeTo};
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn add_sub<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
fn add_sub<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
|
||||||
global_state: Expr<GlobalState>,
|
#[hdl]
|
||||||
pc: Expr<UInt<64>>,
|
let global_state: GlobalState = m.input();
|
||||||
mop: Expr<AddSubMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
#[hdl]
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
let pc: UInt<64> = m.input();
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
#[hdl]
|
||||||
|
let mop: TraceAsString<AddSubMOp<PRegNum<C>, PRegNum<C>, SrcCount>> =
|
||||||
|
m.input(TraceAsString[AddSubMOp[PRegNum[config]][PRegNum[config]][SrcCount::SIZE]]);
|
||||||
|
#[hdl]
|
||||||
|
let src_values: Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }> = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let output: TraceAsString<PRegValue> = m.output();
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -42,7 +49,7 @@ fn add_sub<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
src1_is_carry_in,
|
src1_is_carry_in,
|
||||||
invert_carry_in,
|
invert_carry_in,
|
||||||
add_pc,
|
add_pc,
|
||||||
} = mop;
|
} = *mop;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let AluCommonMOp::<_, _, _, _> {
|
let AluCommonMOp::<_, _, _, _> {
|
||||||
common,
|
common,
|
||||||
|
|
@ -111,8 +118,7 @@ fn add_sub<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
#[hdl]
|
let int_fp = output.int_fp;
|
||||||
let int_fp: UInt<64> = wire();
|
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let x86_cf = wire();
|
let x86_cf = wire();
|
||||||
|
|
@ -201,12 +207,10 @@ fn add_sub<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let flags = wire();
|
|
||||||
#[hdl]
|
|
||||||
match flags_mode {
|
match flags_mode {
|
||||||
FlagsMode::PowerISA(_) => {
|
FlagsMode::PowerISA(_) => {
|
||||||
connect(
|
connect(
|
||||||
flags,
|
output.flags,
|
||||||
PRegFlagsPowerISA::from_view(PRegFlagsPowerISAView {
|
PRegFlagsPowerISA::from_view(PRegFlagsPowerISAView {
|
||||||
unused: ViewUnused::splat(false.to_expr()),
|
unused: ViewUnused::splat(false.to_expr()),
|
||||||
xer_ca: pwr_ca,
|
xer_ca: pwr_ca,
|
||||||
|
|
@ -222,7 +226,7 @@ fn add_sub<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
}
|
}
|
||||||
FlagsMode::X86(_) => {
|
FlagsMode::X86(_) => {
|
||||||
connect(
|
connect(
|
||||||
flags,
|
output.flags,
|
||||||
PRegFlagsX86::from_view(PRegFlagsX86View {
|
PRegFlagsX86::from_view(PRegFlagsX86View {
|
||||||
unused: ViewUnused::splat(false.to_expr()),
|
unused: ViewUnused::splat(false.to_expr()),
|
||||||
cf: x86_cf,
|
cf: x86_cf,
|
||||||
|
|
@ -237,32 +241,44 @@ fn add_sub<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let retval = #[hdl]
|
|
||||||
PRegValue { int_fp, flags };
|
|
||||||
retval.to_trace_as_string()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn logical_flags<C: PhantomConstCpuConfig>(
|
fn logical_flags<C: Type + PhantomConstCpuConfig>(config: C) {
|
||||||
global_state: Expr<GlobalState>,
|
#[hdl]
|
||||||
mop: Expr<LogicalFlagsMOp<PRegNum<C>, PRegNum<C>>>,
|
let global_state: GlobalState = m.input();
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
#[hdl]
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
let mop: TraceAsString<LogicalFlagsMOp<PRegNum<C>, PRegNum<C>>> =
|
||||||
|
m.input(TraceAsString[LogicalFlagsMOp[PRegNum[config]][PRegNum[config]]]);
|
||||||
|
#[hdl]
|
||||||
|
let src_values: Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }> = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let output: TraceAsString<PRegValue> = m.output();
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode: _ } = global_state;
|
let GlobalState { flags_mode: _ } = global_state;
|
||||||
LogicalFlagsMOp::operation(mop, src_values.map(|v| *v)).to_trace_as_string()
|
connect(
|
||||||
|
output,
|
||||||
|
LogicalFlagsMOp::operation(*mop, src_values.map(|v| *v)).to_trace_as_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
fn logical<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
|
||||||
global_state: Expr<GlobalState>,
|
#[hdl]
|
||||||
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
let global_state: GlobalState = m.input();
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
#[hdl]
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
let mop: TraceAsString<LogicalMOp<PRegNum<C>, PRegNum<C>, SrcCount>> =
|
||||||
|
m.input(TraceAsString[LogicalMOp[PRegNum[config]][PRegNum[config]][SrcCount::SIZE]]);
|
||||||
|
#[hdl]
|
||||||
|
let src_values: Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }> = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let output: TraceAsString<PRegValue> = m.output();
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let LogicalMOp::<_, _, _> { alu_common, lut } = mop;
|
let LogicalMOp::<_, _, _> { alu_common, lut } = *mop;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let AluCommonMOp::<_, _, _, _> {
|
let AluCommonMOp::<_, _, _, _> {
|
||||||
common,
|
common,
|
||||||
|
|
@ -287,8 +303,6 @@ fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
let lut4_output = wire();
|
let lut4_output = wire();
|
||||||
connect(lut4_output, Lut4::output(lut, lhs.int_fp, rhs.int_fp));
|
connect(lut4_output, Lut4::output(lut, lhs.int_fp, rhs.int_fp));
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let logical_result: TraceAsString<PRegValue> = wire();
|
|
||||||
#[hdl]
|
|
||||||
let x86_sf = wire();
|
let x86_sf = wire();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
match flags_mode {
|
match flags_mode {
|
||||||
|
|
@ -303,13 +317,13 @@ fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
cr_gt,
|
cr_gt,
|
||||||
cr_eq,
|
cr_eq,
|
||||||
so,
|
so,
|
||||||
} = PRegFlags::view::<PRegFlagsPowerISA>(logical_result.flags);
|
} = PRegFlags::view::<PRegFlagsPowerISA>(output.flags);
|
||||||
unused.clear();
|
unused.clear();
|
||||||
connect(xer_ca, false);
|
connect(xer_ca, false);
|
||||||
connect(xer_ca32, false);
|
connect(xer_ca32, false);
|
||||||
connect(xer_ov, false);
|
connect(xer_ov, false);
|
||||||
connect(xer_ov32, false);
|
connect(xer_ov32, false);
|
||||||
let signed_result = logical_result.int_fp.cast_to_static::<SInt<64>>();
|
let signed_result = output.int_fp.cast_to_static::<SInt<64>>();
|
||||||
connect(cr_lt, signed_result.cmp_lt(0i64));
|
connect(cr_lt, signed_result.cmp_lt(0i64));
|
||||||
connect(cr_eq, signed_result.cmp_eq(0i64));
|
connect(cr_eq, signed_result.cmp_eq(0i64));
|
||||||
connect(cr_gt, !(cr_lt | cr_eq));
|
connect(cr_gt, !(cr_lt | cr_eq));
|
||||||
|
|
@ -325,29 +339,29 @@ fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
af,
|
af,
|
||||||
pf,
|
pf,
|
||||||
df,
|
df,
|
||||||
} = PRegFlags::view::<PRegFlagsX86>(logical_result.flags);
|
} = PRegFlags::view::<PRegFlagsX86>(output.flags);
|
||||||
unused.clear();
|
unused.clear();
|
||||||
connect(cf, false);
|
connect(cf, false);
|
||||||
connect(zf, logical_result.int_fp.cmp_eq(0u64));
|
connect(zf, output.int_fp.cmp_eq(0u64));
|
||||||
connect(sf, x86_sf);
|
connect(sf, x86_sf);
|
||||||
connect(of, false);
|
connect(of, false);
|
||||||
connect(af, false);
|
connect(af, false);
|
||||||
connect(pf, logical_result.int_fp[..8].parity_even());
|
connect(pf, output.int_fp[..8].parity_even());
|
||||||
connect(df, false);
|
connect(df, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let connect_output = |width, signed| {
|
let connect_output = |width, signed| {
|
||||||
connect(x86_sf, logical_result.int_fp[width - 1]);
|
connect(x86_sf, output.int_fp[width - 1]);
|
||||||
if signed {
|
if signed {
|
||||||
connect(
|
connect(
|
||||||
logical_result.int_fp,
|
output.int_fp,
|
||||||
lut4_output
|
lut4_output
|
||||||
.cast_to(SInt[width])
|
.cast_to(SInt[width])
|
||||||
.cast_to_static::<UInt<64>>(),
|
.cast_to_static::<UInt<64>>(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
connect(
|
connect(
|
||||||
logical_result.int_fp,
|
output.int_fp,
|
||||||
lut4_output
|
lut4_output
|
||||||
.cast_to(UInt[width])
|
.cast_to(UInt[width])
|
||||||
.cast_to_static::<UInt<64>>(),
|
.cast_to_static::<UInt<64>>(),
|
||||||
|
|
@ -358,9 +372,9 @@ fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
match output_integer_mode {
|
match output_integer_mode {
|
||||||
OutputIntegerMode::Full64 => connect_output(64, false),
|
OutputIntegerMode::Full64 => connect_output(64, false),
|
||||||
OutputIntegerMode::DupLow32 => {
|
OutputIntegerMode::DupLow32 => {
|
||||||
connect(x86_sf, logical_result.int_fp[31]);
|
connect(x86_sf, output.int_fp[31]);
|
||||||
let v = lut4_output.cast_to_static::<UInt<32>>();
|
let v = lut4_output.cast_to_static::<UInt<32>>();
|
||||||
connect_any(logical_result.int_fp, v | (v << 32));
|
connect_any(output.int_fp, v | (v << 32));
|
||||||
}
|
}
|
||||||
OutputIntegerMode::ZeroExt32 => connect_output(32, false),
|
OutputIntegerMode::ZeroExt32 => connect_output(32, false),
|
||||||
OutputIntegerMode::SignExt32 => connect_output(32, true),
|
OutputIntegerMode::SignExt32 => connect_output(32, true),
|
||||||
|
|
@ -369,7 +383,6 @@ fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
OutputIntegerMode::ZeroExt8 => connect_output(8, false),
|
OutputIntegerMode::ZeroExt8 => connect_output(8, false),
|
||||||
OutputIntegerMode::SignExt8 => connect_output(8, true),
|
OutputIntegerMode::SignExt8 => connect_output(8, true),
|
||||||
}
|
}
|
||||||
logical_result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -438,16 +451,22 @@ fn funnel_shift<W: Size, A: Size>(
|
||||||
funnel_shift_retval
|
funnel_shift_retval
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn shift_rotate<C: PhantomConstCpuConfig>(
|
fn shift_rotate<C: Type + PhantomConstCpuConfig>(config: C) {
|
||||||
global_state: Expr<GlobalState>,
|
#[hdl]
|
||||||
mop: Expr<ShiftRotateMOp<PRegNum<C>, PRegNum<C>>>,
|
let global_state: GlobalState = m.input();
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
#[hdl]
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
let mop: TraceAsString<ShiftRotateMOp<PRegNum<C>, PRegNum<C>>> =
|
||||||
|
m.input(TraceAsString[ShiftRotateMOp[PRegNum[config]][PRegNum[config]]]);
|
||||||
|
#[hdl]
|
||||||
|
let src_values: Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }> = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let output: TraceAsString<PRegValue> = m.output();
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let ShiftRotateMOp::<_, _> { alu_common, mode } = mop;
|
let ShiftRotateMOp::<_, _> { alu_common, mode } = *mop;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let AluCommonMOp::<_, _, _, _> {
|
let AluCommonMOp::<_, _, _, _> {
|
||||||
common,
|
common,
|
||||||
|
|
@ -561,8 +580,7 @@ fn shift_rotate<C: PhantomConstCpuConfig>(
|
||||||
} else {
|
} else {
|
||||||
connect(masked, shifted_rotated);
|
connect(masked, shifted_rotated);
|
||||||
}
|
}
|
||||||
#[hdl]
|
let int_fp = output.int_fp;
|
||||||
let int_fp: UInt<64> = wire();
|
|
||||||
fn connect_int_fp_cast<T: IntType + StaticType>(int_fp: Expr<UInt<64>>, masked: Expr<UInt<64>>)
|
fn connect_int_fp_cast<T: IntType + StaticType>(int_fp: Expr<UInt<64>>, masked: Expr<UInt<64>>)
|
||||||
where
|
where
|
||||||
UInt<64>: CastToImpl<T>,
|
UInt<64>: CastToImpl<T>,
|
||||||
|
|
@ -587,27 +605,28 @@ fn shift_rotate<C: PhantomConstCpuConfig>(
|
||||||
OutputIntegerMode::ZeroExt8 => connect_int_fp_cast::<UInt<8>>(int_fp, masked),
|
OutputIntegerMode::ZeroExt8 => connect_int_fp_cast::<UInt<8>>(int_fp, masked),
|
||||||
OutputIntegerMode::SignExt8 => connect_int_fp_cast::<SInt<8>>(int_fp, masked),
|
OutputIntegerMode::SignExt8 => connect_int_fp_cast::<SInt<8>>(int_fp, masked),
|
||||||
}
|
}
|
||||||
let retval = #[hdl]
|
connect(output.flags, PRegFlags::zeroed()); // TODO: compute flags
|
||||||
PRegValue {
|
|
||||||
int_fp,
|
|
||||||
flags: PRegFlags::zeroed(), // TODO: compute flags
|
|
||||||
};
|
|
||||||
retval.into_trace_as_string()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
fn compare<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
|
||||||
global_state: Expr<GlobalState>,
|
#[hdl]
|
||||||
mop: Expr<CompareMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
let global_state: GlobalState = m.input();
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
#[hdl]
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
let mop: TraceAsString<CompareMOp<PRegNum<C>, PRegNum<C>, SrcCount>> =
|
||||||
|
m.input(TraceAsString[CompareMOp[PRegNum[config]][PRegNum[config]][SrcCount::SIZE]]);
|
||||||
|
#[hdl]
|
||||||
|
let src_values: Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }> = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let output: TraceAsString<PRegValue> = m.output();
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let CompareMOp::<_, _, _> {
|
let CompareMOp::<_, _, _> {
|
||||||
common,
|
common,
|
||||||
compare_mode,
|
compare_mode,
|
||||||
} = mop;
|
} = *mop;
|
||||||
let config = common.dest.unit_num.config.ty();
|
let config = common.dest.unit_num.config.ty();
|
||||||
let (lhs, rhs) = match SrcCount::VALUE {
|
let (lhs, rhs) = match SrcCount::VALUE {
|
||||||
1 => (
|
1 => (
|
||||||
|
|
@ -624,9 +643,7 @@ fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
2 => (src_values[0], src_values[1]),
|
2 => (src_values[0], src_values[1]),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
#[hdl]
|
connect(output, PRegValue::zeroed().to_trace_as_string());
|
||||||
let compare_result = wire();
|
|
||||||
connect(compare_result, PRegValue::zeroed().to_trace_as_string());
|
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let lhs_casted: SInt<65> = wire();
|
let lhs_casted: SInt<65> = wire();
|
||||||
|
|
@ -640,25 +657,37 @@ fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let x86_flags = wire();
|
let x86_flags = wire();
|
||||||
let zero_reg = PRegNum[config].const_zero();
|
let zero_reg = PRegNum[config].const_zero();
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
let add_sub_for_flags = instance(add_sub(config));
|
||||||
|
#[hdl]
|
||||||
|
let add_sub::<_, _> {
|
||||||
|
global_state: add_sub_for_flags_global_state,
|
||||||
|
pc: add_sub_for_flags_pc,
|
||||||
|
mop: add_sub_for_flags_mop,
|
||||||
|
src_values: add_sub_for_flags_src_values,
|
||||||
|
output: add_sub_for_flags_output,
|
||||||
|
} = add_sub_for_flags;
|
||||||
|
connect(add_sub_for_flags_global_state, global_state);
|
||||||
|
connect(add_sub_for_flags_pc, 0u64);
|
||||||
connect(
|
connect(
|
||||||
x86_flags,
|
*add_sub_for_flags_mop,
|
||||||
add_sub(
|
AddSubMOp::add_sub_i(
|
||||||
global_state,
|
zero_reg,
|
||||||
0u64.to_expr(),
|
repeat(zero_reg, ConstUsize),
|
||||||
AddSubMOp::add_sub_i(
|
0.cast_to_static::<SInt<_>>(),
|
||||||
zero_reg,
|
x86_sub_mode,
|
||||||
repeat(zero_reg, ConstUsize),
|
true,
|
||||||
0.cast_to_static::<SInt<_>>(),
|
false,
|
||||||
x86_sub_mode,
|
true,
|
||||||
true,
|
false,
|
||||||
false,
|
),
|
||||||
true,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
[rhs, lhs, PRegValue::zeroed().to_trace_as_string()].to_expr(),
|
|
||||||
)
|
|
||||||
.flags,
|
|
||||||
);
|
);
|
||||||
|
connect(
|
||||||
|
add_sub_for_flags_src_values,
|
||||||
|
[rhs, lhs, PRegValue::zeroed().to_trace_as_string()],
|
||||||
|
);
|
||||||
|
connect(x86_flags, add_sub_for_flags_output.flags);
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let power_isa_flags = wire();
|
let power_isa_flags = wire();
|
||||||
|
|
@ -690,8 +719,8 @@ fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
connect(rhs_casted, do_cast(rhs.int_fp));
|
connect(rhs_casted, do_cast(rhs.int_fp));
|
||||||
#[hdl]
|
#[hdl]
|
||||||
match flags_mode {
|
match flags_mode {
|
||||||
FlagsMode::PowerISA(_) => connect(compare_result.flags, power_isa_flags),
|
FlagsMode::PowerISA(_) => connect(output.flags, power_isa_flags),
|
||||||
FlagsMode::X86(_) => connect(compare_result.flags, x86_flags),
|
FlagsMode::X86(_) => connect(output.flags, x86_flags),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -717,24 +746,31 @@ fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compare_result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn branch<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
fn branch<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
|
||||||
global_state: Expr<GlobalState>,
|
#[hdl]
|
||||||
pc: Expr<UInt<64>>,
|
let global_state: GlobalState = m.input();
|
||||||
fallthrough_pc: Expr<UInt<64>>,
|
#[hdl]
|
||||||
predicted_next_pc: Expr<UInt<64>>,
|
let pc: UInt<64> = m.input();
|
||||||
mop: Expr<BranchMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
#[hdl]
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
let fallthrough_pc: UInt<64> = m.input();
|
||||||
config: C,
|
#[hdl]
|
||||||
) -> (
|
let predicted_next_pc: UInt<64> = m.input();
|
||||||
Expr<TraceAsString<PRegValue>>,
|
#[hdl]
|
||||||
Expr<NextPcPredictorOp<C>>,
|
let mop: TraceAsString<BranchMOp<PRegNum<C>, PRegNum<C>, SrcCount>> =
|
||||||
Expr<HdlOption<UnitCausedCancel<C>>>,
|
m.input(TraceAsString[BranchMOp[PRegNum[config]][PRegNum[config]][SrcCount::SIZE]]);
|
||||||
) {
|
#[hdl]
|
||||||
|
let src_values: Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }> = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let output: TraceAsString<PRegValue> = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let predictor_op: NextPcPredictorOp<C> = m.output(NextPcPredictorOp[config]);
|
||||||
|
#[hdl]
|
||||||
|
let caused_cancel: HdlOption<UnitCausedCancel<C>> =
|
||||||
|
m.output(HdlOption[UnitCausedCancel[config]]);
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -746,7 +782,7 @@ fn branch<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
pc_relative,
|
pc_relative,
|
||||||
is_call,
|
is_call,
|
||||||
is_ret,
|
is_ret,
|
||||||
} = mop;
|
} = *mop;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let CommonMOp::<_, _, _, _, _> {
|
let CommonMOp::<_, _, _, _, _> {
|
||||||
prefix_pad: _,
|
prefix_pad: _,
|
||||||
|
|
@ -850,11 +886,9 @@ fn branch<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
connect(next_pc, fallthrough_pc);
|
connect(next_pc, fallthrough_pc);
|
||||||
};
|
};
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let cancel = wire(HdlOption[UnitCausedCancel[config]]);
|
|
||||||
#[hdl]
|
|
||||||
if next_pc.cmp_ne(predicted_next_pc) {
|
if next_pc.cmp_ne(predicted_next_pc) {
|
||||||
connect(
|
connect(
|
||||||
cancel,
|
caused_cancel,
|
||||||
HdlSome(
|
HdlSome(
|
||||||
#[hdl]
|
#[hdl]
|
||||||
UnitCausedCancel::<C> {
|
UnitCausedCancel::<C> {
|
||||||
|
|
@ -865,13 +899,16 @@ fn branch<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
connect(cancel, cancel.ty().HdlNone());
|
connect(caused_cancel, caused_cancel.ty().HdlNone());
|
||||||
};
|
|
||||||
let fallthrough_pc_value = #[hdl]
|
|
||||||
PRegValue {
|
|
||||||
int_fp: fallthrough_pc,
|
|
||||||
flags: PRegFlags::zeroed_sim(),
|
|
||||||
};
|
};
|
||||||
|
connect(
|
||||||
|
*output,
|
||||||
|
#[hdl]
|
||||||
|
PRegValue {
|
||||||
|
int_fp: fallthrough_pc,
|
||||||
|
flags: PRegFlags::zeroed_sim(),
|
||||||
|
},
|
||||||
|
);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let call_stack_op = wire();
|
let call_stack_op = wire();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -890,29 +927,33 @@ fn branch<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
} else {
|
} else {
|
||||||
connect(cond_br_taken_opt, HdlNone());
|
connect(cond_br_taken_opt, HdlNone());
|
||||||
}
|
}
|
||||||
(
|
connect(
|
||||||
fallthrough_pc_value.into_trace_as_string(),
|
predictor_op,
|
||||||
#[hdl]
|
#[hdl]
|
||||||
NextPcPredictorOp::<_> {
|
NextPcPredictorOp::<_> {
|
||||||
call_stack_op,
|
call_stack_op,
|
||||||
cond_br_taken: cond_br_taken_opt,
|
cond_br_taken: cond_br_taken_opt,
|
||||||
config,
|
config,
|
||||||
},
|
},
|
||||||
cancel,
|
);
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn read_special<C: PhantomConstCpuConfig>(
|
fn read_special<C: Type + PhantomConstCpuConfig>(config: C) {
|
||||||
global_state: Expr<GlobalState>,
|
#[hdl]
|
||||||
pc: Expr<UInt<64>>,
|
let global_state: GlobalState = m.input();
|
||||||
mop: Expr<ReadSpecialMOp<PRegNum<C>, PRegNum<C>>>,
|
#[hdl]
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
let mop: TraceAsString<ReadSpecialMOp<PRegNum<C>, PRegNum<C>>> =
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
m.input(TraceAsString[ReadSpecialMOp[PRegNum[config]][PRegNum[config]]]);
|
||||||
|
#[hdl]
|
||||||
|
let src_values: Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }> = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let output: TraceAsString<PRegValue> = m.output();
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
// TODO: finish
|
// TODO: finish
|
||||||
PRegValue::zeroed().to_trace_as_string()
|
connect(*output, PRegValue::zeroed());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
|
|
@ -975,68 +1016,193 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
match mop {
|
match mop {
|
||||||
AluBranchMOp::<_, _>::AddSub(mop) => {
|
AluBranchMOp::<_, _>::AddSub(mop) => {
|
||||||
connect(
|
#[hdl]
|
||||||
dest_value,
|
let add_sub = instance(add_sub(config));
|
||||||
add_sub(global_state, mop_instance.pc, mop, src_values),
|
#[hdl]
|
||||||
);
|
let add_sub::<_, _> {
|
||||||
|
global_state: global_state_,
|
||||||
|
pc,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = add_sub;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(pc, mop_instance.pc);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::AddSubI(mop) => {
|
AluBranchMOp::<_, _>::AddSubI(mop) => {
|
||||||
connect(
|
#[hdl]
|
||||||
dest_value,
|
let add_sub_i = instance(add_sub(config));
|
||||||
add_sub(global_state, mop_instance.pc, mop, src_values),
|
#[hdl]
|
||||||
);
|
let add_sub::<_, _> {
|
||||||
|
global_state: global_state_,
|
||||||
|
pc,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = add_sub_i;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(pc, mop_instance.pc);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::LogicalFlags(mop) => {
|
AluBranchMOp::<_, _>::LogicalFlags(mop) => {
|
||||||
connect(dest_value, logical_flags(global_state, mop, src_values));
|
#[hdl]
|
||||||
|
let logical_flags = instance(logical_flags(config));
|
||||||
|
#[hdl]
|
||||||
|
let logical_flags::<_> {
|
||||||
|
global_state: global_state_,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = logical_flags;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::Logical(mop) => {
|
AluBranchMOp::<_, _>::Logical(mop) => {
|
||||||
connect(dest_value, logical(global_state, mop, src_values));
|
#[hdl]
|
||||||
|
let logical = instance(logical(config));
|
||||||
|
#[hdl]
|
||||||
|
let logical::<_, _> {
|
||||||
|
global_state: global_state_,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = logical;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::LogicalI(mop) => {
|
AluBranchMOp::<_, _>::LogicalI(mop) => {
|
||||||
connect(dest_value, logical(global_state, mop, src_values));
|
#[hdl]
|
||||||
|
let logical_i = instance(logical(config));
|
||||||
|
#[hdl]
|
||||||
|
let logical::<_, _> {
|
||||||
|
global_state: global_state_,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = logical_i;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::ShiftRotate(mop) => {
|
AluBranchMOp::<_, _>::ShiftRotate(mop) => {
|
||||||
connect(dest_value, shift_rotate(global_state, mop, src_values));
|
#[hdl]
|
||||||
|
let shift_rotate = instance(shift_rotate(config));
|
||||||
|
#[hdl]
|
||||||
|
let shift_rotate::<_> {
|
||||||
|
global_state: global_state_,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = shift_rotate;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::Compare(mop) => {
|
AluBranchMOp::<_, _>::Compare(mop) => {
|
||||||
connect(dest_value, compare(global_state, mop, src_values));
|
#[hdl]
|
||||||
|
let compare = instance(compare(config));
|
||||||
|
#[hdl]
|
||||||
|
let compare::<_, _> {
|
||||||
|
global_state: global_state_,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = compare;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::CompareI(mop) => {
|
AluBranchMOp::<_, _>::CompareI(mop) => {
|
||||||
connect(dest_value, compare(global_state, mop, src_values));
|
#[hdl]
|
||||||
|
let compare_i = instance(compare(config));
|
||||||
|
#[hdl]
|
||||||
|
let compare::<_, _> {
|
||||||
|
global_state: global_state_,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = compare_i;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::Branch(mop) => {
|
AluBranchMOp::<_, _>::Branch(mop) => {
|
||||||
let (dest_value_, predictor_op_, caused_cancel_) = branch(
|
#[hdl]
|
||||||
global_state,
|
let branch = instance(branch(config));
|
||||||
mop_instance.pc,
|
#[hdl]
|
||||||
fallthrough_pc,
|
let branch::<_, _> {
|
||||||
mop_instance.predicted_next_pc,
|
global_state: global_state_,
|
||||||
mop,
|
pc: pc_,
|
||||||
src_values,
|
fallthrough_pc: fallthrough_pc_,
|
||||||
config,
|
predicted_next_pc,
|
||||||
);
|
mop: mop_,
|
||||||
connect(dest_value, dest_value_);
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
predictor_op: predictor_op_,
|
||||||
|
caused_cancel: caused_cancel_,
|
||||||
|
} = branch;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(pc_, mop_instance.pc);
|
||||||
|
connect(fallthrough_pc_, fallthrough_pc);
|
||||||
|
connect(predicted_next_pc, mop_instance.predicted_next_pc);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
connect(predictor_op, predictor_op_);
|
connect(predictor_op, predictor_op_);
|
||||||
connect(caused_cancel, caused_cancel_);
|
connect(caused_cancel, caused_cancel_);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::BranchI(mop) => {
|
AluBranchMOp::<_, _>::BranchI(mop) => {
|
||||||
let (dest_value_, predictor_op_, caused_cancel_) = branch(
|
#[hdl]
|
||||||
global_state,
|
let branch_i = instance(branch(config));
|
||||||
mop_instance.pc,
|
#[hdl]
|
||||||
fallthrough_pc,
|
let branch::<_, _> {
|
||||||
mop_instance.predicted_next_pc,
|
global_state: global_state_,
|
||||||
mop,
|
pc: pc_,
|
||||||
src_values,
|
fallthrough_pc: fallthrough_pc_,
|
||||||
config,
|
predicted_next_pc,
|
||||||
);
|
mop: mop_,
|
||||||
connect(dest_value, dest_value_);
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
predictor_op: predictor_op_,
|
||||||
|
caused_cancel: caused_cancel_,
|
||||||
|
} = branch_i;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(pc_, mop_instance.pc);
|
||||||
|
connect(fallthrough_pc_, fallthrough_pc);
|
||||||
|
connect(predicted_next_pc, mop_instance.predicted_next_pc);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
connect(predictor_op, predictor_op_);
|
connect(predictor_op, predictor_op_);
|
||||||
connect(caused_cancel, caused_cancel_);
|
connect(caused_cancel, caused_cancel_);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::ReadSpecial(mop) => {
|
AluBranchMOp::<_, _>::ReadSpecial(mop) => {
|
||||||
connect(
|
#[hdl]
|
||||||
dest_value,
|
let read_special = instance(read_special(config));
|
||||||
read_special(global_state, mop_instance.pc, mop, src_values),
|
#[hdl]
|
||||||
);
|
let read_special::<_> {
|
||||||
|
global_state: global_state_,
|
||||||
|
mop: mop_,
|
||||||
|
src_values: src_values_,
|
||||||
|
output,
|
||||||
|
} = read_special;
|
||||||
|
connect(global_state_, global_state);
|
||||||
|
connect(*mop_, mop);
|
||||||
|
connect(src_values_, src_values);
|
||||||
|
connect(dest_value, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connect(
|
connect(
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
83979
crates/cpu/tests/expected/rename_execute_retire_head_n1_real.vcd
generated
83979
crates/cpu/tests/expected/rename_execute_retire_head_n1_real.vcd
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue