unit::alu_branch: implement for LogicalMOp
This commit is contained in:
parent
b25448a275
commit
42056ce6b5
5 changed files with 2378 additions and 1229 deletions
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
instruction::{
|
instruction::{
|
||||||
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
||||||
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
||||||
OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateDestLogicOp, ShiftRotateMOp,
|
Lut4, OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateDestLogicOp, ShiftRotateMOp,
|
||||||
ShiftRotateMOpImm, ShiftRotateMode,
|
ShiftRotateMOpImm, ShiftRotateMode,
|
||||||
},
|
},
|
||||||
next_pc::CallStackOp,
|
next_pc::CallStackOp,
|
||||||
|
|
@ -254,29 +254,122 @@ fn logical_flags<C: PhantomConstCpuConfig>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn logical<C: PhantomConstCpuConfig>(
|
fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
global_state: Expr<GlobalState>,
|
global_state: Expr<GlobalState>,
|
||||||
pc: Expr<UInt<64>>,
|
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
||||||
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, ConstUsize<2>>>,
|
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
) -> Expr<TraceAsString<PRegValue>> {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
// TODO: finish
|
|
||||||
PRegValue::zeroed().to_trace_as_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
fn logical_i<C: PhantomConstCpuConfig>(
|
|
||||||
global_state: Expr<GlobalState>,
|
|
||||||
pc: Expr<UInt<64>>,
|
|
||||||
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, ConstUsize<1>>>,
|
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let LogicalMOp::<_, _, _> { alu_common, lut } = mop;
|
||||||
// TODO: finish
|
#[hdl]
|
||||||
PRegValue::zeroed().to_trace_as_string()
|
let AluCommonMOp::<_, _, _, _> {
|
||||||
|
common,
|
||||||
|
output_integer_mode,
|
||||||
|
} = alu_common;
|
||||||
|
let (lhs, rhs) = match SrcCount::VALUE {
|
||||||
|
1 => (
|
||||||
|
src_values[0],
|
||||||
|
Expr::into_trace_as_string(
|
||||||
|
#[hdl]
|
||||||
|
PRegValue {
|
||||||
|
int_fp: CommonMOpDefaultImm::as_sint_dyn(common.imm)
|
||||||
|
.cast_to_static::<UInt<64>>(),
|
||||||
|
flags: PRegFlags::zeroed(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 => (src_values[0], src_values[1]),
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
#[hdl]
|
||||||
|
let lut4_output = wire();
|
||||||
|
connect(lut4_output, Lut4::output(lut, lhs.int_fp, rhs.int_fp));
|
||||||
|
#[hdl]
|
||||||
|
let logical_result: TraceAsString<PRegValue> = wire();
|
||||||
|
#[hdl]
|
||||||
|
let x86_sf = wire();
|
||||||
|
#[hdl]
|
||||||
|
match flags_mode {
|
||||||
|
FlagsMode::PowerISA(_) => {
|
||||||
|
let PRegFlagsPowerISAView {
|
||||||
|
unused,
|
||||||
|
xer_ca,
|
||||||
|
xer_ca32,
|
||||||
|
xer_ov,
|
||||||
|
xer_ov32,
|
||||||
|
cr_lt,
|
||||||
|
cr_gt,
|
||||||
|
cr_eq,
|
||||||
|
so,
|
||||||
|
} = PRegFlags::view::<PRegFlagsPowerISA>(logical_result.flags);
|
||||||
|
unused.clear();
|
||||||
|
connect(xer_ca, false);
|
||||||
|
connect(xer_ca32, false);
|
||||||
|
connect(xer_ov, false);
|
||||||
|
connect(xer_ov32, false);
|
||||||
|
let signed_result = logical_result.int_fp.cast_to_static::<SInt<64>>();
|
||||||
|
connect(cr_lt, signed_result.cmp_lt(0i64));
|
||||||
|
connect(cr_eq, signed_result.cmp_eq(0i64));
|
||||||
|
connect(cr_gt, !(cr_lt | cr_eq));
|
||||||
|
connect(so, false); // TODO: need to set from the global SO
|
||||||
|
}
|
||||||
|
FlagsMode::X86(_) => {
|
||||||
|
let PRegFlagsX86View {
|
||||||
|
unused,
|
||||||
|
cf,
|
||||||
|
zf,
|
||||||
|
sf,
|
||||||
|
of,
|
||||||
|
af,
|
||||||
|
pf,
|
||||||
|
df,
|
||||||
|
} = PRegFlags::view::<PRegFlagsX86>(logical_result.flags);
|
||||||
|
unused.clear();
|
||||||
|
connect(cf, false);
|
||||||
|
connect(zf, logical_result.int_fp.cmp_eq(0u64));
|
||||||
|
connect(sf, x86_sf);
|
||||||
|
connect(of, false);
|
||||||
|
connect(af, false);
|
||||||
|
connect(pf, logical_result.int_fp[..8].parity_even());
|
||||||
|
connect(df, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let connect_output = |width, signed| {
|
||||||
|
connect(x86_sf, logical_result.int_fp[width - 1]);
|
||||||
|
if signed {
|
||||||
|
connect(
|
||||||
|
logical_result.int_fp,
|
||||||
|
lut4_output
|
||||||
|
.cast_to(SInt[width])
|
||||||
|
.cast_to_static::<UInt<64>>(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
connect(
|
||||||
|
logical_result.int_fp,
|
||||||
|
lut4_output
|
||||||
|
.cast_to(UInt[width])
|
||||||
|
.cast_to_static::<UInt<64>>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#[hdl]
|
||||||
|
match output_integer_mode {
|
||||||
|
OutputIntegerMode::Full64 => connect_output(64, false),
|
||||||
|
OutputIntegerMode::DupLow32 => {
|
||||||
|
connect(x86_sf, logical_result.int_fp[31]);
|
||||||
|
let v = lut4_output.cast_to_static::<UInt<32>>();
|
||||||
|
connect_any(logical_result.int_fp, v | (v << 32));
|
||||||
|
}
|
||||||
|
OutputIntegerMode::ZeroExt32 => connect_output(32, false),
|
||||||
|
OutputIntegerMode::SignExt32 => connect_output(32, true),
|
||||||
|
OutputIntegerMode::ZeroExt16 => connect_output(16, false),
|
||||||
|
OutputIntegerMode::SignExt16 => connect_output(16, true),
|
||||||
|
OutputIntegerMode::ZeroExt8 => connect_output(8, false),
|
||||||
|
OutputIntegerMode::SignExt8 => connect_output(8, true),
|
||||||
|
}
|
||||||
|
logical_result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -897,16 +990,10 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
|
||||||
connect(dest_value, logical_flags(global_state, mop, src_values));
|
connect(dest_value, logical_flags(global_state, mop, src_values));
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::Logical(mop) => {
|
AluBranchMOp::<_, _>::Logical(mop) => {
|
||||||
connect(
|
connect(dest_value, logical(global_state, mop, src_values));
|
||||||
dest_value,
|
|
||||||
logical(global_state, mop_instance.pc, mop, src_values),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::LogicalI(mop) => {
|
AluBranchMOp::<_, _>::LogicalI(mop) => {
|
||||||
connect(
|
connect(dest_value, logical(global_state, mop, src_values));
|
||||||
dest_value,
|
|
||||||
logical_i(global_state, mop_instance.pc, mop, src_values),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::ShiftRotate(mop) => {
|
AluBranchMOp::<_, _>::ShiftRotate(mop) => {
|
||||||
connect(dest_value, shift_rotate(global_state, mop, src_values));
|
connect(dest_value, shift_rotate(global_state, mop, src_values));
|
||||||
|
|
@ -1022,7 +1109,7 @@ impl UnitTrait for AluBranch {
|
||||||
self.module
|
self.module
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
|
fn cd(&self, _this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
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
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue