forked from libre-chip/cpu
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
|
#[hdl]
|
||||||
PRegValue::zeroed().to_trace_as_string()
|
let LogicalMOp::<_, _, _> { alu_common, lut } = mop;
|
||||||
|
#[hdl]
|
||||||
|
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]
|
#[hdl]
|
||||||
fn logical_i<C: PhantomConstCpuConfig>(
|
match output_integer_mode {
|
||||||
global_state: Expr<GlobalState>,
|
OutputIntegerMode::Full64 => connect_output(64, false),
|
||||||
pc: Expr<UInt<64>>,
|
OutputIntegerMode::DupLow32 => {
|
||||||
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, ConstUsize<1>>>,
|
connect(x86_sf, logical_result.int_fp[31]);
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
let v = lut4_output.cast_to_static::<UInt<32>>();
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
connect_any(logical_result.int_fp, v | (v << 32));
|
||||||
#[hdl]
|
}
|
||||||
let GlobalState { flags_mode } = global_state;
|
OutputIntegerMode::ZeroExt32 => connect_output(32, false),
|
||||||
// TODO: finish
|
OutputIntegerMode::SignExt32 => connect_output(32, true),
|
||||||
PRegValue::zeroed().to_trace_as_string()
|
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