add a procedural implementation of rename_execute_retire #12

Merged
programmerjake merged 24 commits from programmerjake/cpu:rename-execute-retire into master 2026-05-22 06:58:09 +00:00
38 changed files with 615322 additions and 36446 deletions

8
Cargo.lock generated
View file

@ -388,7 +388,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
name = "fayalite"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cf3e6cfc6bc33eebf2d2862c7a1948b9cf40ecac"
dependencies = [
"base64",
"bitvec",
@ -417,7 +417,7 @@ dependencies = [
[[package]]
name = "fayalite-proc-macros"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cf3e6cfc6bc33eebf2d2862c7a1948b9cf40ecac"
dependencies = [
"fayalite-proc-macros-impl",
]
@ -425,7 +425,7 @@ dependencies = [
[[package]]
name = "fayalite-proc-macros-impl"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cf3e6cfc6bc33eebf2d2862c7a1948b9cf40ecac"
dependencies = [
"base16ct 0.2.0",
"num-bigint",
@ -440,7 +440,7 @@ dependencies = [
[[package]]
name = "fayalite-visit-gen"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cf3e6cfc6bc33eebf2d2862c7a1948b9cf40ecac"
dependencies = [
"indexmap",
"prettyplease",

View file

@ -33,3 +33,6 @@ hex-literal.workspace = true
regex = "1.12.2"
sha2.workspace = true
which.workspace = true
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] }

View file

@ -1,13 +1,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
instruction::{CONST_ZERO_UNIT_NUM, MOpTrait, PRegNum, RenamedMOp, UnitNum, UnitOutRegNum},
unit::{
UnitCancelInput, UnitKind, UnitOutputWrite,
unit_base::{UnitForwardingInfo, UnitToRegAlloc},
},
};
use fayalite::prelude::*;
use crate::{instruction::CONST_ZERO_UNIT_NUM, unit::UnitKind};
use fayalite::{expr::HdlPartialOrdImpl, prelude::*};
use serde::{Deserialize, Serialize};
use std::num::NonZeroUsize;
@ -101,54 +95,20 @@ impl CpuConfig {
pub fn unit_num_width(&self) -> usize {
UInt::range(CONST_ZERO_UNIT_NUM..self.non_const_unit_nums().end).width()
}
pub fn unit_num(&self) -> UnitNum<DynSize> {
UnitNum[self.unit_num_width()]
}
pub fn unit_out_reg_num(&self) -> UnitOutRegNum<DynSize> {
UnitOutRegNum[self.out_reg_num_width]
}
pub fn p_reg_num(&self) -> PRegNum<DynSize, DynSize> {
PRegNum[self.unit_num_width()][self.out_reg_num_width]
}
pub fn p_reg_num_width(&self) -> usize {
self.unit_num_width() + self.out_reg_num_width
}
pub fn renamed_mop_in_unit(&self) -> RenamedMOp<UnitOutRegNum<DynSize>, DynSize> {
RenamedMOp[self.unit_out_reg_num()][self.p_reg_num_width()]
}
pub fn unit_output_write(&self) -> UnitOutputWrite<DynSize> {
UnitOutputWrite[self.out_reg_num_width]
}
pub fn unit_output_writes(&self) -> Array<HdlOption<UnitOutputWrite<DynSize>>> {
Array[HdlOption[self.unit_output_write()]][self.non_const_unit_nums().len()]
}
pub fn unit_cancel_input(&self) -> UnitCancelInput<DynSize> {
UnitCancelInput[self.out_reg_num_width]
}
pub fn unit_forwarding_info(&self) -> UnitForwardingInfo<DynSize, DynSize, DynSize> {
UnitForwardingInfo[self.unit_num_width()][self.out_reg_num_width]
[self.non_const_unit_nums().len()]
}
pub fn unit_max_in_flight(&self, unit_index: usize) -> NonZeroUsize {
self.units[unit_index]
.max_in_flight
.unwrap_or(self.default_unit_max_in_flight)
}
pub fn unit_to_reg_alloc<
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
ExtraOut: Type,
>(
&self,
mop_ty: MOp,
extra_out_ty: ExtraOut,
) -> UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> {
assert_eq!(
mop_ty.dest_reg_ty(),
self.unit_out_reg_num(),
"inconsistent types",
);
UnitToRegAlloc[mop_ty][extra_out_ty][self.unit_num_width()][self.out_reg_num_width]
[self.non_const_unit_nums().len()]
/// the maximum of all [`unit_max_in_flight()`][Self::unit_max_in_flight()]
pub fn max_unit_max_in_flight(&self) -> NonZeroUsize {
(0..self.units.len())
.map(|unit_index| self.unit_max_in_flight(unit_index))
.max()
.unwrap_or(self.default_unit_max_in_flight)
}
pub fn fetch_width_in_bytes(&self) -> usize {
1usize
@ -188,6 +148,21 @@ impl CpuConfig {
}
}
#[hdl(get(|c| c.out_reg_num_width))]
pub type CpuConfigOutRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.unit_num_width()))]
pub type CpuConfigUnitNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.p_reg_num_width()))]
pub type CpuConfigPRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| 1 << c.out_reg_num_width))]
pub type CpuConfig2PowOutRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.units.len()))]
pub type CpuConfigUnitCount<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.fetch_width.get()))]
pub type CpuConfigFetchWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
@ -236,6 +211,10 @@ pub type CpuConfigL1ICacheMaxMissesInFlight<C: PhantomConstGet<CpuConfig>> = Dyn
#[hdl(get(|c| c.rob_size.get()))]
pub type CpuConfigRobSize<C: PhantomConstGet<CpuConfig>> = DynSize;
/// the maximum of all [`unit_max_in_flight()`][CpuConfig::unit_max_in_flight()]
#[hdl(get(|c| c.max_unit_max_in_flight().get()))]
pub type CpuConfigMaxUnitMaxInFlight<C: PhantomConstGet<CpuConfig>> = DynSize;
pub trait PhantomConstCpuConfig:
PhantomConstGet<CpuConfig>
+ Into<PhantomConst<CpuConfig>>
@ -243,6 +222,7 @@ pub trait PhantomConstCpuConfig:
+ Type
+ ToSimValue<Type = Self>
+ ToExpr<Type = Self>
+ HdlPartialOrdImpl<Self>
{
}

View file

@ -7,8 +7,8 @@ use crate::{
AddSubMOp, BranchMOp, CompareMOp, CompareMode, ConditionMode, LoadMOp, LoadStoreConversion,
LoadStoreWidth, LogicalFlagsMOp, LogicalFlagsMOpImm, LogicalMOp, Lut4, MOp, MOpDestReg,
MOpRegNum, MoveRegMOp, OutputIntegerMode, ReadSpecialMOp, ReadSpecialMOpImm,
ShiftRotateDestLogicOp, ShiftRotateMOp, ShiftRotateMOpImm, ShiftRotateMode, StoreMOp,
power_isa::PowerIsaSprEnum,
ShiftAmountOverflowBehavior, ShiftRotateDestLogicOp, ShiftRotateMOp, ShiftRotateMOpImm,
ShiftRotateMode, StoreMOp, power_isa::PowerIsaSprEnum,
},
powerisa_instructions_xml::{
InstructionBitFieldName, InstructionBitFieldsInner, Instructions, TextLineItem,
@ -604,7 +604,7 @@ impl DecodeState<'_> {
}],
[],
),
MOpRegNum::const_zero().value,
[MOpRegNum::const_zero(); 2],
(li << 2).cast_to_static(),
!aa,
lk,
@ -646,7 +646,7 @@ impl DecodeState<'_> {
#[hdl]
let branch_ctr_reg: MOpRegNum = wire();
let dest = MOpDestReg::new([branch_lr_dest_reg], []);
let src1 = addr_reg.unwrap_or_else(|| MOpRegNum::const_zero()).value;
let src1 = addr_reg.unwrap_or_else(|| MOpRegNum::const_zero());
let imm: Expr<SInt<_>> = (bd.unwrap_or(0_hdl_i14) << 2).cast_to_static();
let invert_src2_eq_zero = !use_eq_for_ctr_compare;
let pc_relative = match aa {
@ -659,7 +659,7 @@ impl DecodeState<'_> {
branch_mop,
BranchMOp::branch_i(
dest,
src1,
[MOpRegNum::const_zero(), src1],
imm.cast_to_static::<SInt<_>>(),
pc_relative,
lk,
@ -671,8 +671,7 @@ impl DecodeState<'_> {
branch_mop,
BranchMOp::branch_ctr(
dest,
src1,
branch_ctr_reg.value,
[MOpRegNum::const_zero(), src1, branch_ctr_reg],
imm,
invert_src2_eq_zero,
pc_relative,
@ -685,7 +684,7 @@ impl DecodeState<'_> {
branch_mop,
BranchMOp::branch_cond_ctr(
dest,
[cr_field.value, src1, branch_ctr_reg.value],
[cr_field, src1, branch_ctr_reg],
imm,
!expected_cr_bit_value,
condition_mode,
@ -713,10 +712,7 @@ impl DecodeState<'_> {
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([MOpRegNum::power_isa_ctr_reg()], []),
[
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::const_zero().value,
],
[MOpRegNum::power_isa_ctr_reg(), MOpRegNum::const_zero()],
(-1).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -789,7 +785,7 @@ impl DecodeState<'_> {
this.output[0],
LogicalFlagsMOp::logical_flags(
MOpDestReg::new([bt_reg], []),
[ba_reg.value, bb_reg.value, bt_reg.value],
[ba_reg, bb_reg, bt_reg],
#[hdl]
LogicalFlagsMOpImm {
src0_start: src0_start.cast_to(LogicalFlagsMOpImm.src0_start),
@ -815,7 +811,7 @@ impl DecodeState<'_> {
this.output[0],
MoveRegMOp::move_reg(
MOpDestReg::new([crf(bf)], []),
[crf(bfa).value],
[crf(bfa)],
0i8.cast_to_static::<SInt<_>>(),
),
);
@ -892,7 +888,7 @@ impl DecodeState<'_> {
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[MOpRegNum::const_zero().value; 2],
[MOpRegNum::const_zero(); 2],
d,
OutputIntegerMode.Full64(),
false,
@ -906,7 +902,7 @@ impl DecodeState<'_> {
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
d,
OutputIntegerMode.Full64(),
false,
@ -918,12 +914,7 @@ impl DecodeState<'_> {
}
connect(
this.output[1],
LoadMOp::load(
MOpDestReg::new([gpr(rt)], []),
[ea_reg.value],
width,
conversion,
),
LoadMOp::load(MOpDestReg::new([gpr(rt)], []), [ea_reg], width, conversion),
);
},
);
@ -939,7 +930,7 @@ impl DecodeState<'_> {
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, gpr(rb).value],
[gpr_or_zero(ra), gpr(rb)],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -950,12 +941,7 @@ impl DecodeState<'_> {
);
connect(
this.output[1],
LoadMOp::load(
MOpDestReg::new([gpr(rt)], []),
[ea_reg.value],
width,
conversion,
),
LoadMOp::load(MOpDestReg::new([gpr(rt)], []), [ea_reg], width, conversion),
);
});
} else if self.arguments == Some("RT,disp(RA)") {
@ -969,7 +955,7 @@ impl DecodeState<'_> {
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
(ds << 2).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -980,12 +966,7 @@ impl DecodeState<'_> {
);
connect(
this.output[1],
LoadMOp::load(
MOpDestReg::new([gpr(rt)], []),
[ea_reg.value],
width,
conversion,
),
LoadMOp::load(MOpDestReg::new([gpr(rt)], []), [ea_reg], width, conversion),
);
});
} else {
@ -1005,7 +986,7 @@ impl DecodeState<'_> {
this.output[0],
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
d.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -1016,12 +997,7 @@ impl DecodeState<'_> {
);
connect(
this.output[1],
LoadMOp::load(
MOpDestReg::new([gpr(rt)], []),
[ea_reg.value],
width,
conversion,
),
LoadMOp::load(MOpDestReg::new([gpr(rt)], []), [ea_reg], width, conversion),
);
});
}
@ -1092,7 +1068,7 @@ impl DecodeState<'_> {
this.output[1],
StoreMOp::store(
MOpDestReg::new([], []),
[ea_reg.value, gpr(rs).value],
[ea_reg, gpr(rs)],
width,
LoadStoreConversion.ZeroExt(),
),
@ -1107,7 +1083,7 @@ impl DecodeState<'_> {
this.output[2],
MoveRegMOp::move_reg(
MOpDestReg::new([gpr(ra)], []),
[ea_reg.value],
[ea_reg],
0.cast_to_static::<SInt<_>>(),
),
);
@ -1126,7 +1102,7 @@ impl DecodeState<'_> {
insn,
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[MOpRegNum::const_zero().value; 2],
[MOpRegNum::const_zero(); 2],
d,
OutputIntegerMode.Full64(),
false,
@ -1140,7 +1116,7 @@ impl DecodeState<'_> {
insn,
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
d,
OutputIntegerMode.Full64(),
false,
@ -1161,7 +1137,7 @@ impl DecodeState<'_> {
insn,
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, gpr(rb).value],
[gpr_or_zero(ra), gpr(rb)],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -1179,7 +1155,7 @@ impl DecodeState<'_> {
insn,
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
(ds << 2).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -1203,7 +1179,7 @@ impl DecodeState<'_> {
insn,
AddSubMOp::add_sub_i(
MOpDestReg::new([ea_reg], []),
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
d.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -1230,7 +1206,7 @@ impl DecodeState<'_> {
AddSubMOp::add_sub_i(
MOpDestReg::new([gpr(rt)], []),
#[hdl]
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
si.cast_to_static(),
OutputIntegerMode.Full64(),
false,
@ -1253,7 +1229,7 @@ impl DecodeState<'_> {
AddSubMOp::add_sub_i(
MOpDestReg::new([gpr(rt)], []),
#[hdl]
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
((si0 << 16) + si1.cast_to(SInt[34])).cast_to_static(),
OutputIntegerMode.Full64(),
false,
@ -1280,7 +1256,7 @@ impl DecodeState<'_> {
AddSubMOp::add_sub_i(
MOpDestReg::new([gpr(rt)], []),
#[hdl]
[gpr_or_zero(ra).value, MOpRegNum::const_zero().value],
[gpr_or_zero(ra), MOpRegNum::const_zero()],
(si << 16).cast_to_static(),
OutputIntegerMode.Full64(),
false,
@ -1307,7 +1283,7 @@ impl DecodeState<'_> {
AddSubMOp::add_sub_i(
MOpDestReg::new([gpr(rt)], []),
#[hdl]
[MOpRegNum::const_zero().value; 2],
[MOpRegNum::const_zero(); 2],
(4i8 + (d << 16)).cast_to_static(),
OutputIntegerMode.Full64(),
false,
@ -1340,7 +1316,7 @@ impl DecodeState<'_> {
],
),
#[hdl]
[gpr(ra).value, gpr(rb).value, MOpRegNum::const_zero().value],
[gpr(ra), gpr(rb), MOpRegNum::const_zero()],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -1371,7 +1347,7 @@ impl DecodeState<'_> {
)],
),
#[hdl]
[gpr(ra).value, MOpRegNum::const_zero().value],
[gpr(ra), MOpRegNum::const_zero()],
si.cast_to_static(),
OutputIntegerMode.Full64(),
false,
@ -1410,7 +1386,7 @@ impl DecodeState<'_> {
],
),
#[hdl]
[gpr(ra).value, gpr(rb).value, MOpRegNum::const_zero().value],
[gpr(ra), gpr(rb), MOpRegNum::const_zero()],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
true,
@ -1440,7 +1416,7 @@ impl DecodeState<'_> {
)],
),
#[hdl]
[gpr(ra).value, MOpRegNum::const_zero().value],
[gpr(ra), MOpRegNum::const_zero()],
si.cast_to_static(),
OutputIntegerMode.Full64(),
true,
@ -1472,7 +1448,7 @@ impl DecodeState<'_> {
],
),
#[hdl]
[gpr(ra).value, gpr(rb).value, MOpRegNum::const_zero().value],
[gpr(ra), gpr(rb), MOpRegNum::const_zero()],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -1505,11 +1481,7 @@ impl DecodeState<'_> {
],
),
#[hdl]
[
gpr(ra).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
gpr(rb).value,
],
[gpr(ra), MOpRegNum::power_isa_xer_ca_ca32_reg(), gpr(rb)],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -1542,11 +1514,7 @@ impl DecodeState<'_> {
],
),
#[hdl]
[
gpr(ra).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
gpr(rb).value,
],
[gpr(ra), MOpRegNum::power_isa_xer_ca_ca32_reg(), gpr(rb)],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
true,
@ -1580,9 +1548,9 @@ impl DecodeState<'_> {
),
#[hdl]
[
gpr(ra).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::const_zero().value,
gpr(ra),
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::const_zero(),
],
if this.mnemonic.contains('m') { -1i8 } else { 0 }
.cast_to_static::<SInt<_>>(),
@ -1617,11 +1585,7 @@ impl DecodeState<'_> {
],
),
#[hdl]
[
gpr(ra).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
],
[gpr(ra), MOpRegNum::const_zero(), MOpRegNum::const_zero()],
0i8.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
true,
@ -1654,9 +1618,8 @@ impl DecodeState<'_> {
this.output[0],
CompareMOp::compare_i(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value],
[gpr(ra)],
si.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
compare_mode,
),
);
@ -1683,9 +1646,7 @@ impl DecodeState<'_> {
this.output[0],
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
[gpr(ra), gpr(rb)],
compare_mode,
),
);
@ -1712,9 +1673,8 @@ impl DecodeState<'_> {
this.output[0],
CompareMOp::compare_i(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value],
[gpr(ra)],
ui.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
compare_mode,
),
);
@ -1741,9 +1701,7 @@ impl DecodeState<'_> {
this.output[0],
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
[gpr(ra), gpr(rb)],
compare_mode,
),
);
@ -1770,9 +1728,7 @@ impl DecodeState<'_> {
this.output[0],
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
[gpr(ra), gpr(rb)],
compare_mode,
),
);
@ -1791,9 +1747,7 @@ impl DecodeState<'_> {
this.output[0],
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
[gpr(ra), gpr(rb)],
CompareMode.CmpEqB(),
),
);
@ -1825,7 +1779,7 @@ impl DecodeState<'_> {
this.mnemonic.contains('.').to_expr(),
)],
),
[gpr(rs).value],
[gpr(rs)],
if this.mnemonic.contains('s') {
(ui << 16).cast_to_static::<SInt<_>>()
} else {
@ -1873,7 +1827,7 @@ impl DecodeState<'_> {
this.output[0],
LogicalMOp::logical(
MOpDestReg::new([gpr(ra)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)]),
[gpr(rs).value, gpr(rb).value],
[gpr(rs), gpr(rb)],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
lut,
@ -1887,7 +1841,7 @@ impl DecodeState<'_> {
this.output[0],
MoveRegMOp::move_reg(
MOpDestReg::new([gpr(ra)], []),
[gpr(rs).value],
[gpr(rs)],
0i8.cast_to_static::<SInt<_>>(),
),
);
@ -1916,7 +1870,7 @@ impl DecodeState<'_> {
this.output[0],
LogicalMOp::logical_i(
MOpDestReg::new([gpr(ra)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)]),
[gpr(rs).value],
[gpr(rs)],
0.cast_to_static::<SInt<_>>(),
output_integer_mode,
Lut4::from_fn(|a, b| a | b),
@ -1994,11 +1948,12 @@ impl DecodeState<'_> {
self.output[0],
ShiftRotateMOp::shift_rotate(
MOpDestReg::new([gpr(ra.0)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc.0)]),
[gpr(rs.0).value, gpr(rs.0).value, gpr(rb.0).value],
[gpr(rs.0), gpr(rs.0), gpr(rb.0)],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlNone(),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
dest_logic_op,
},
OutputIntegerMode.Full64(),
@ -2031,24 +1986,25 @@ impl DecodeState<'_> {
self.rotate_dest_logic_op(msb0_mask_begin, msb0_mask_end, fallback_is_src2);
#[hdl]
let rotate_imm_src2 = wire();
connect(rotate_imm_src2, MOpRegNum::const_zero().value);
connect(rotate_imm_src2, MOpRegNum::const_zero());
// if dest_logic_op is HdlNone, we don't need to read from src2
#[hdl]
if let HdlSome(dest_logic_op) = dest_logic_op {
#[hdl]
if dest_logic_op.fallback_is_src2 {
connect(rotate_imm_src2, gpr(ra.0).value);
connect(rotate_imm_src2, gpr(ra.0));
}
}
connect(
self.output[0],
ShiftRotateMOp::shift_rotate(
MOpDestReg::new([gpr(ra.0)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc.0)]),
[gpr(rs.0).value, gpr(rs.0).value, rotate_imm_src2],
[gpr(rs.0), gpr(rs.0), rotate_imm_src2],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(rotate_amount),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
dest_logic_op,
},
OutputIntegerMode.Full64(),
@ -2194,15 +2150,13 @@ impl DecodeState<'_> {
[gpr(ra), MOpRegNum::power_isa_xer_ca_ca32_reg()],
[(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)],
),
[
gpr(rs).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
],
[gpr(rs), MOpRegNum::const_zero(), MOpRegNum::const_zero()],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(sh.cast_to_static::<UInt<_>>()),
shift_rotate_right: true,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToWidth(),
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
@ -2226,15 +2180,13 @@ impl DecodeState<'_> {
[gpr(ra), MOpRegNum::power_isa_xer_ca_ca32_reg()],
[(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)],
),
[
gpr(rs).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
],
[gpr(rs), MOpRegNum::const_zero(), MOpRegNum::const_zero()],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
shift_rotate_right: true,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToWidth(),
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
@ -2268,14 +2220,16 @@ impl DecodeState<'_> {
[(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)],
),
if !is_signed && is_right_shift {
[MOpRegNum::const_zero().value, gpr(rs).value, gpr(rb).value]
[MOpRegNum::const_zero(), gpr(rs), gpr(rb)]
} else {
[gpr(rs).value, MOpRegNum::const_zero().value, gpr(rb).value]
[gpr(rs), MOpRegNum::const_zero(), gpr(rb)]
},
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlNone(),
shift_rotate_right: is_right_shift,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToTwiceWidth(),
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
@ -2306,15 +2260,13 @@ impl DecodeState<'_> {
this.output[0],
ShiftRotateMOp::shift_rotate(
MOpDestReg::new([gpr(ra)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)]),
[
gpr(rs).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
],
[gpr(rs), MOpRegNum::const_zero(), MOpRegNum::const_zero()],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToWidth(),
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
@ -2340,7 +2292,7 @@ impl DecodeState<'_> {
self.output[0],
MoveRegMOp::move_reg(
MOpDestReg::new([spr], []),
[gpr(reg).value],
[gpr(reg)],
0.cast_to_static::<SInt<_>>(),
),
);
@ -2349,7 +2301,7 @@ impl DecodeState<'_> {
self.output[0],
MoveRegMOp::move_reg(
MOpDestReg::new([gpr(reg)], []),
[spr.value],
[spr],
0.cast_to_static::<SInt<_>>(),
),
);
@ -2365,7 +2317,7 @@ impl DecodeState<'_> {
self.output[0],
ReadSpecialMOp::read_special(
MOpDestReg::new([gpr(reg)], []),
[MOpRegNum::const_zero().value; 0],
[MOpRegNum::const_zero(); 0],
imm,
),
);
@ -2441,9 +2393,9 @@ impl DecodeState<'_> {
LogicalFlagsMOp::logical_flags(
MOpDestReg::new([crf(bf)], []),
[
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_xer_so_ov_ov32_reg().value,
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_xer_so_ov_ov32_reg(),
],
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| {
let mut dest = PRegFlagsPowerISAView::splat(None);

View file

@ -523,7 +523,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
kind,
read_data,
config: _,
} = memory_operation_finish;
} = memory_operation_finish.into_sim_value();
#[hdl(sim)]
match kind {
MemoryOperationFinishKind::Success(success) =>
@ -746,7 +746,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
let NextPcToFetchInterfaceInner {
start_pc,
fetch_block_id,
} = fetch;
} = fetch.into_sim_value();
let entry_ty = FetchQueueEntry[config];
self.queue.push_back(
#[hdl(sim)]
@ -895,7 +895,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
let CacheReadData::<_> {
cache_line_index: read_cache_line_index,
cache_line,
} = cache_read_data;
} = cache_read_data.into_sim_value();
let config = self.config();
for entry in &mut self.queue {
#[hdl(sim)]
@ -1151,8 +1151,6 @@ fn l1_i_cache_impl(config: PhantomConst<CpuConfig>) {
sim.wait_for_clock_edge(cd.clk).await;
}
sim.write(from_next_pc.cancel.ready, true).await;
let memory_interface_start_data_ty = memory_interface.start.data.ty();
let to_decode_fetched_data_ty = to_decode_fetched.data.ty();
let cache_read_data_ty = CacheReadData[config];
let mut state = L1ICacheStateSim::new(state_expr);
loop {
@ -1168,26 +1166,11 @@ fn l1_i_cache_impl(config: PhantomConst<CpuConfig>) {
.await;
sim.write(
memory_interface.start.data,
if let Some(v) = state.clone().try_start_memory_operation() {
#[hdl(sim)]
memory_interface_start_data_ty.HdlSome(v)
} else {
#[hdl(sim)]
memory_interface_start_data_ty.HdlNone()
},
)
.await;
sim.write(
to_decode_fetched.data,
if let Some(v) = state.clone().to_decode_fetched() {
#[hdl(sim)]
to_decode_fetched_data_ty.HdlSome(v)
} else {
#[hdl(sim)]
to_decode_fetched_data_ty.HdlNone()
},
state.clone().try_start_memory_operation(),
)
.await;
sim.write(to_decode_fetched.data, state.clone().to_decode_fetched())
.await;
state.write_debug_state(&mut sim).await;
sim.write(max_cancel_in_fetch, state.queue.len()).await;
state

File diff suppressed because it is too large Load diff

View file

@ -25,89 +25,206 @@ pub struct PowerIsaCrBitNum {
pub bit_in_field: UInt<2>,
}
impl MOpRegNum {
pub const POWER_ISA_LR_REG_NUM: u32 = 1;
#[hdl]
pub fn power_isa_lr_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_LR_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
pub const POWER_ISA_CTR_REG_NUM: u32 = 2;
#[hdl]
pub fn power_isa_ctr_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_CTR_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
pub const POWER_ISA_TAR_REG_NUM: u32 = 3;
#[hdl]
pub fn power_isa_tar_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_TAR_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
macro_rules! suffix_str_with_0_to_31 {
($str:literal) => {
suffix_str_with_0_to_31!(
$str,
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31,
]
)
};
($str:literal, [$($num:literal),* $(,)?]) => {
[$(concat!($str, $num)),*]
};
}
const fn fill_names_range<'a>(dest: &mut [Option<&'a str>], range: Range<u32>, src: &[&'a str]) {
assert!((range.end - range.start) as usize == src.len());
let mut i = 0;
while i < src.len() {
dest[i + range.start as usize] = Some(src[i]);
i += 1;
}
}
macro_rules! power_isa_regs {
(
$(
#[name_str = $name_str:literal, expr_fn = $expr_fn:ident, sim_fn = $sim_fn:ident]
$(#[doc = $($doc:tt)*])*
pub const $REG_NUM:ident: u32 = $reg_num_expr:expr;
)*
$(
#[names_fn = |$names_var:ident| $names_body:expr $(,
reg_num_fn = $reg_num_fn_multi:ident,
expr_fn = $expr_fn_multi:ident($fn_multi_arg:ty),
expr_imm_fn = $expr_imm_fn_multi:ident,
sim_fn = $sim_fn_multi:ident,)?
]
$(#[doc = $($doc_multi:tt)*])*
pub const $REG_NUM_MULTI:ident: Range<u32> = $reg_num_multi_expr:expr;
)*
) => {
impl MOpRegNum {
pub const POWER_ISA_REG_NAMES: &[Option<&str>; 1 << Self::WIDTH] = &{
let mut retval = [None; _];
$(retval[Self::$REG_NUM as usize] = Some($name_str);)*
$({
let $names_var = &mut retval;
$names_body
})*
retval
};
$(
$(#[doc = $($doc)*])*
pub const $REG_NUM: u32 = $reg_num_expr;
$(#[doc = $($doc)*])*
#[hdl]
pub fn $expr_fn() -> Expr<Self> {
#[hdl]
Self {
value: Self::$REG_NUM.cast_to_static::<UInt<_>>(),
}
}
$(#[doc = $($doc)*])*
#[hdl]
pub fn $sim_fn() -> SimValue<Self> {
#[hdl(sim)]
Self {
value: Self::$REG_NUM.cast_to_static::<UInt<_>>(),
}
}
)*
$(
$(#[doc = $($doc_multi)*])*
pub const $REG_NUM_MULTI: Range<u32> = $reg_num_multi_expr;
power_isa_regs! {
@helper_fns
#[names_fn = |$names_var| $names_body $(,
reg_num_fn = $reg_num_fn_multi,
expr_fn = $expr_fn_multi($fn_multi_arg),
expr_imm_fn = $expr_imm_fn_multi,
sim_fn = $sim_fn_multi,)?
]
$(#[doc = $($doc_multi)*])*
pub const $REG_NUM_MULTI: Range<u32> = $reg_num_multi_expr;
}
)*
}
};
(
@helper_fns
#[names_fn = |$names_var:ident| $names_body:expr]
$(#[doc = $($doc_multi:tt)*])*
pub const $REG_NUM_MULTI:ident: Range<u32> = $reg_num_multi_expr:expr;
) => {};
(
@helper_fns
#[
names_fn = |$names_var:ident| $names_body:expr,
reg_num_fn = $reg_num_fn_multi:ident,
expr_fn = $expr_fn_multi:ident($fn_multi_arg:ty),
expr_imm_fn = $expr_imm_fn_multi:ident,
sim_fn = $sim_fn_multi:ident,
]
$(#[doc = $($doc_multi:tt)*])*
pub const $REG_NUM_MULTI:ident: Range<u32> = $reg_num_multi_expr:expr;
) => {
$(#[doc = $($doc_multi)*])*
pub const fn $reg_num_fn_multi(index: usize) -> u32 {
range_u32_nth_or_panic(&Self::$REG_NUM_MULTI, index)
}
$(#[doc = $($doc_multi)*])*
#[hdl]
pub fn $expr_fn_multi(input: Expr<$fn_multi_arg>) -> Expr<Self> {
#[hdl]
Self {
value: (Self::$REG_NUM_MULTI.start + input).cast_to_static::<UInt<_>>(),
}
}
$(#[doc = $($doc_multi)*])*
#[hdl]
pub fn $expr_imm_fn_multi(input: usize) -> Expr<Self> {
#[hdl]
Self {
value: Self::$reg_num_fn_multi(input).cast_to_static::<UInt<_>>(),
}
}
$(#[doc = $($doc_multi)*])*
#[hdl]
pub fn $sim_fn_multi(reg_num: &SimValue<$fn_multi_arg>) -> SimValue<Self> {
#[hdl(sim)]
Self {
value: (Self::$REG_NUM_MULTI.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
};
}
power_isa_regs! {
#[name_str = "lr", expr_fn = power_isa_lr_reg, sim_fn = power_isa_lr_reg_sim]
pub const POWER_ISA_LR_REG_NUM: u32 = 1;
#[name_str = "ctr", expr_fn = power_isa_ctr_reg, sim_fn = power_isa_ctr_reg_sim]
pub const POWER_ISA_CTR_REG_NUM: u32 = 2;
#[name_str = "tar", expr_fn = power_isa_tar_reg, sim_fn = power_isa_tar_reg_sim]
pub const POWER_ISA_TAR_REG_NUM: u32 = 3;
#[name_str = "xer[so,ov,ov32]", expr_fn = power_isa_xer_so_ov_ov32_reg, sim_fn = power_isa_xer_so_ov_ov32_reg_sim]
/// SO, OV, and OV32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
pub const POWER_ISA_XER_SO_OV_OV32_REG_NUM: u32 =
range_u32_nth_or_panic(&Self::FLAG_REG_NUMS, 0);
#[name_str = "xer[ca,ca32]", expr_fn = power_isa_xer_ca_ca32_reg, sim_fn = power_isa_xer_ca_ca32_reg_sim]
/// CA and CA32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
pub const POWER_ISA_XER_CA_CA32_REG_NUM: u32 = 4;
#[name_str = "xer[other]", expr_fn = power_isa_xer_other_reg, sim_fn = power_isa_xer_other_reg_sim]
/// only the XER bits that don't exist in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
pub const POWER_ISA_XER_OTHER_REG_NUM: u32 = 5;
#[name_str = "temp", expr_fn = power_isa_temp_reg, sim_fn = power_isa_temp_reg_sim]
/// used as a temporary for things like computing the effective address before loading/storing memory
pub const POWER_ISA_TEMP_REG_NUM: u32 = 8;
#[hdl]
pub fn power_isa_temp_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_TEMP_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
/// SO, OV, and OV32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
#[hdl]
pub fn power_isa_xer_so_ov_ov32_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_XER_SO_OV_OV32_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
/// CA and CA32 XER bits -- in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
#[hdl]
pub fn power_isa_xer_ca_ca32_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_XER_CA_CA32_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
/// only the XER bits that don't exist in [`PRegValue.flags`]
///
/// [`PRegValue.flags`]: struct@crate::register::PRegValue
#[hdl]
pub fn power_isa_xer_other_reg() -> Expr<Self> {
#[hdl]
Self {
value: Self::POWER_ISA_XER_OTHER_REG_NUM.cast_to_static::<UInt<_>>(),
}
}
#[name_str = "cr0", expr_fn = power_isa_cr_0_reg, sim_fn = power_isa_cr_0_reg_sim]
pub const POWER_ISA_CR_0_REG_NUM: u32 = range_u32_nth_or_panic(&Self::FLAG_REG_NUMS, 1);
#[names_fn = |names| {
fill_names_range(names, Self::POWER_ISA_CR_1_THRU_7_REG_NUMS, &["cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7"]);
}]
pub const POWER_ISA_CR_1_THRU_7_REG_NUMS: Range<u32> = 9..16;
#[
names_fn = |names| {
fill_names_range(names, Self::POWER_ISA_GPR_REG_NUMS, &suffix_str_with_0_to_31!("r"));
},
reg_num_fn = power_isa_gpr_reg_num,
expr_fn = power_isa_gpr_reg(UInt<5>),
expr_imm_fn = power_isa_gpr_reg_imm,
sim_fn = power_isa_gpr_reg_sim,
]
pub const POWER_ISA_GPR_REG_NUMS: Range<u32> = 32..64;
#[
names_fn = |names| {
fill_names_range(names, Self::POWER_ISA_FPR_REG_NUMS, &suffix_str_with_0_to_31!("f"));
},
reg_num_fn = power_isa_fpr_reg_num,
expr_fn = power_isa_fpr_reg(UInt<5>),
expr_imm_fn = power_isa_fpr_reg_imm,
sim_fn = power_isa_fpr_reg_sim,
]
pub const POWER_ISA_FPR_REG_NUMS: Range<u32> = 64..96;
}
impl MOpRegNum {
pub const fn power_isa_cr_reg_num(index: usize) -> u32 {
if index == 0 {
Self::POWER_ISA_CR_0_REG_NUM
@ -148,31 +265,6 @@ impl MOpRegNum {
}
}
pub const POWER_ISA_GPR_REG_NUMS: Range<u32> = 32..64;
pub const fn power_isa_gpr_reg_num(index: usize) -> u32 {
range_u32_nth_or_panic(&Self::POWER_ISA_GPR_REG_NUMS, index)
}
#[hdl]
pub fn power_isa_gpr_reg(reg_num: Expr<UInt<5>>) -> Expr<Self> {
#[hdl]
Self {
value: (Self::POWER_ISA_GPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
#[hdl]
pub fn power_isa_gpr_reg_imm(index: usize) -> Expr<Self> {
#[hdl]
Self {
value: Self::power_isa_gpr_reg_num(index).cast_to_static::<UInt<_>>(),
}
}
#[hdl]
pub fn power_isa_gpr_reg_sim(reg_num: &SimValue<UInt<5>>) -> SimValue<Self> {
#[hdl(sim)]
Self {
value: (Self::POWER_ISA_GPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
pub const fn power_isa_gpr_or_zero_reg_num(index: usize) -> u32 {
if index == 0 {
Self::CONST_ZERO_REG_NUM
@ -192,6 +284,13 @@ impl MOpRegNum {
power_isa_gpr_or_zero_reg
}
#[hdl]
pub fn power_isa_gpr_or_zero_reg_imm(index: usize) -> Expr<Self> {
#[hdl]
Self {
value: Self::power_isa_gpr_or_zero_reg_num(index).cast_to_static::<UInt<_>>(),
}
}
#[hdl]
pub fn power_isa_gpr_or_zero_reg_sim(reg_num: &SimValue<UInt<5>>) -> SimValue<Self> {
#[hdl(sim)]
Self {
@ -201,25 +300,6 @@ impl MOpRegNum {
.cast_to_static::<UInt<_>>(),
}
}
pub const POWER_ISA_FPR_REG_NUMS: Range<u32> = 64..96;
pub const fn power_isa_fpr_reg_num(index: usize) -> u32 {
range_u32_nth_or_panic(&Self::POWER_ISA_FPR_REG_NUMS, index)
}
#[hdl]
pub fn power_isa_fpr_reg(reg_num: Expr<UInt<5>>) -> Expr<Self> {
#[hdl]
Self {
value: (Self::POWER_ISA_FPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
#[hdl]
pub fn power_isa_fpr_reg_sim(reg_num: &SimValue<UInt<5>>) -> SimValue<Self> {
#[hdl(sim)]
Self {
value: (Self::POWER_ISA_FPR_REG_NUMS.start + reg_num).cast_to_static::<UInt<_>>(),
}
}
}
#[hdl(cmp_eq)]

View file

@ -7,7 +7,9 @@ pub mod instruction;
pub mod main_memory_and_io;
pub mod next_pc;
pub mod powerisa_instructions_xml;
#[cfg(todo)]
pub mod reg_alloc;
pub mod register;
pub mod rename_execute_retire;
pub mod unit;
pub mod util;

View file

@ -20,17 +20,16 @@ use crate::{
CpuConfig, CpuConfigFetchWidth, CpuConfigMaxFetchesInFlight, CpuConfigRobSize,
PhantomConstCpuConfig, TwiceCpuConfigFetchWidth,
},
util::array_vec::ArrayVec,
util::{LFSR31, array_vec::ArrayVec},
};
use fayalite::{
expr::HdlPartialEqImpl,
int::{UIntInRange, UIntInRangeInclusive, UIntInRangeInclusiveType, UIntInRangeType},
prelude::*,
sim::value::SimOnlyValueTrait,
ty::StaticType,
util::{DebugAsDisplay, ready_valid::ReadyValid},
};
use std::{borrow::Cow, fmt};
use std::fmt;
pub const FETCH_BLOCK_ID_WIDTH: usize = FetchBlockIdInt::BITS as usize;
type FetchBlockIdInt = u8;
@ -53,7 +52,7 @@ pub struct NextPcToFetchInterface<C: PhantomConstGet<CpuConfig>> {
pub config: C,
}
#[hdl]
#[hdl(cmp_eq)]
/// WIP version of decoded instruction just good enough to represent stuff needed for [`next_pc()`]
/// since the actual instruction definition isn't finalized yet.
/// This will be replaced at a later point.
@ -93,101 +92,6 @@ impl WipDecodedInsnKind {
}
}
// TODO: replace with #[hdl(cmp_eq)] when that's implemented for enums
impl HdlPartialEqImpl<Self> for WipDecodedInsnKind {
#[track_caller]
fn cmp_value_eq(
lhs: Self,
lhs_value: Cow<'_, Self::SimValue>,
rhs: Self,
rhs_value: Cow<'_, Self::SimValue>,
) -> bool {
*Self::cmp_sim_value_eq(
Cow::Owned(SimValue::from_value(lhs, lhs_value.into_owned())),
Cow::Owned(SimValue::from_value(rhs, rhs_value.into_owned())),
)
}
#[hdl]
#[track_caller]
fn cmp_sim_value_eq(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
let clear_unused_bits = |v: Cow<'_, SimValue<Self>>| {
#[hdl(sim)]
match &*v {
Self::NonBranch =>
{
#[hdl(sim)]
Self::NonBranch()
}
Self::Branch(target) =>
{
#[hdl(sim)]
Self::Branch(target)
}
Self::BranchCond(target) =>
{
#[hdl(sim)]
Self::BranchCond(target)
}
Self::IndirectBranch =>
{
#[hdl(sim)]
Self::IndirectBranch()
}
Self::Call(target) =>
{
#[hdl(sim)]
Self::Call(target)
}
Self::CallCond(target) =>
{
#[hdl(sim)]
Self::CallCond(target)
}
Self::IndirectCall =>
{
#[hdl(sim)]
Self::IndirectCall()
}
Self::Ret =>
{
#[hdl(sim)]
Self::Ret()
}
Self::RetCond =>
{
#[hdl(sim)]
Self::RetCond()
}
Self::Interrupt(target) =>
{
#[hdl(sim)]
Self::Interrupt(target)
}
Self::Unknown => v.into_owned(),
}
};
(SimValue::bits(&clear_unused_bits(lhs)) == SimValue::bits(&clear_unused_bits(rhs)))
.to_sim_value()
}
#[track_caller]
fn cmp_sim_value_ne(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
!Self::cmp_sim_value_eq(lhs, rhs)
}
#[track_caller]
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
todo!()
}
}
#[hdl(cmp_eq)]
/// WIP version of decoded instruction just good enough to represent stuff needed for [`next_pc()`]
/// since the actual instruction definition isn't finalized yet.
@ -2781,8 +2685,10 @@ impl<T: SimValueDefault, N: Size> SimValueDefault for ArrayType<T, N> {
}
impl<T: Type> SimValueDefault for HdlOption<T> {
#[hdl]
fn sim_value_default(self) -> SimValue<Self> {
self.HdlNone().to_sim_value_with_type(self)
#[hdl(sim)]
self.HdlNone()
}
}
@ -2911,50 +2817,13 @@ impl ResetSteps for CallStack {
}
}
#[hdl]
#[hdl(cmp_eq)]
enum BTBEntryInsnKind {
Branch,
Call,
Ret,
}
// TODO: replace with #[hdl(cmp_eq)] when that's implemented for enums
impl HdlPartialEqImpl<Self> for BTBEntryInsnKind {
#[track_caller]
fn cmp_value_eq(
lhs: Self,
lhs_value: Cow<'_, Self::SimValue>,
rhs: Self,
rhs_value: Cow<'_, Self::SimValue>,
) -> bool {
*Self::cmp_sim_value_eq(
Cow::Owned(SimValue::from_value(lhs, lhs_value.into_owned())),
Cow::Owned(SimValue::from_value(rhs, rhs_value.into_owned())),
)
}
#[track_caller]
fn cmp_sim_value_eq(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) == SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_sim_value_ne(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) != SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits())
}
}
impl BTBEntryInsnKind {
#[hdl]
fn try_from_decoded_insn_kind(kind: &SimValue<WipDecodedInsnKind>) -> Option<SimValue<Self>> {
@ -2983,7 +2852,7 @@ impl BTBEntryInsnKind {
}
}
#[hdl]
#[hdl(cmp_eq)]
enum BTBEntryAddrKind {
Unconditional,
Indirect,
@ -2991,43 +2860,6 @@ enum BTBEntryAddrKind {
CondNotTaken,
}
// TODO: replace with #[hdl(cmp_eq)] when that's implemented for enums
impl HdlPartialEqImpl<Self> for BTBEntryAddrKind {
#[track_caller]
fn cmp_value_eq(
lhs: Self,
lhs_value: Cow<'_, Self::SimValue>,
rhs: Self,
rhs_value: Cow<'_, Self::SimValue>,
) -> bool {
*Self::cmp_sim_value_eq(
Cow::Owned(SimValue::from_value(lhs, lhs_value.into_owned())),
Cow::Owned(SimValue::from_value(rhs, rhs_value.into_owned())),
)
}
#[track_caller]
fn cmp_sim_value_eq(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) == SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_sim_value_ne(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) != SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits())
}
}
impl BTBEntryAddrKind {
#[hdl]
fn taken(this: &SimValue<Self>) -> bool {
@ -3123,33 +2955,9 @@ impl BTBEntry {
}
}
#[hdl]
struct LFSR31 {
// MSB is always zero, 32 bits makes it easier to manipulate
state: UInt<32>,
}
impl SimValueDefault for LFSR31 {
#[hdl]
fn sim_value_default(self) -> SimValue<Self> {
#[hdl(sim)]
Self { state: 1u32 }
}
}
impl LFSR31 {
fn next(this: &mut SimValue<Self>) -> u32 {
let state = this.state.as_int();
let state = if state == 0 {
1u32
} else {
// a maximal-length 31-bit LFSR
let lsb = ((state >> 30) ^ (state >> 27)) & 1;
let msb = (state << 1) & ((1 << 31) - 1);
lsb | msb
};
*this.state = state.into();
state
Self::new()
}
}
@ -3163,7 +2971,7 @@ impl BranchTargetBuffer {
const LOG2_SIZE: usize = 4;
const SIZE: usize = 1 << Self::LOG2_SIZE;
fn next_index_to_replace(this: &mut SimValue<Self>) -> usize {
LFSR31::next(&mut this.next_index_to_replace_lfsr) as usize % Self::SIZE
LFSR31::next_sim(&mut this.next_index_to_replace_lfsr) as usize % Self::SIZE
}
}

View file

@ -6,9 +6,9 @@ use fayalite::{
expr::CastToImpl,
int::{BoolOrIntType, UIntInRange},
prelude::*,
ty::StaticType,
ty::{SimValueDebug, StaticType},
};
use std::fmt;
use std::{any::Any, fmt};
#[hdl]
pub enum FlagsMode {
@ -47,6 +47,12 @@ pub trait PRegFlagsViewTrait: Type + PRegFlagsViewTraitSealed {
fn from_view_sim<T: ToSimValue>(view: Self::View<T>) -> SimValue<PRegFlags<T::Type>>;
fn view_unused_into_view<T>(unused: ViewUnused<T, PRegFlagsAllUnused>) -> Self::View<T>;
fn view_into_view_unused<T>(view: Self::View<T>) -> ViewUnused<T, PRegFlagsAllUnused>;
fn debug_fmt<'a, T: 'a, F: FnMut(&'a T, bool) -> Option<D>, D: fmt::Debug>(
view: &'a Self::View<T>,
type_name: Option<&str>,
field: F,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result;
}
pub struct ViewUnused<T, V: PRegFlagsViewTrait>(V::UnusedInner<T>);
@ -467,6 +473,34 @@ macro_rules! impl_view_trait {
};
fields.into_view_unused()
}
fn debug_fmt<'a, T: 'a, F: FnMut(&'a T, bool) -> Option<D>, D: fmt::Debug>(
view: &'a Self::View<T>,
type_name: Option<&str>,
mut field: F,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
let $View {
$unused: ViewUnused([$($unused_field,)*]),
$($view_field: $flags_field,)*
} = view;
let mut debug_struct = f.debug_struct(type_name.unwrap_or(stringify!($FlagsMode)));
#[allow(unused_mut)]
let mut any_skipped = false;
$(if let Some(v) = field($flags_field, true) {
debug_struct.field(stringify!($view_field), &v);
} else {
any_skipped = true;
})*
$(if let Some(v) = field($unused_field, false) {
debug_struct.field(stringify!($unused_field), &v);
})*
if any_skipped {
debug_struct.finish_non_exhaustive()
} else {
debug_struct.finish()
}
}
}
};
}
@ -739,6 +773,46 @@ impl<T: Type> PRegFlags<T> {
pub fn splat_sim(v: impl ToSimValue<Type = T>) -> SimValue<Self> {
Self::from_fields_sim(ViewUnused::splat(v.into_sim_value()))
}
#[hdl]
pub fn debug_fmt<V: PRegFlagsViewTrait>(
this: &SimValue<Self>,
type_name: Option<&str>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
if let Some(this) = <dyn Any>::downcast_ref::<SimValue<PRegFlags>>(this) {
V::debug_fmt(
&PRegFlags::view_sim_ref::<V>(this),
type_name,
|v, _| v.then_some(*v),
f,
)
} else {
V::debug_fmt(
&PRegFlags::view_sim_ref::<V>(this),
type_name,
|v, _| Some(*v),
f,
)
}
}
#[hdl]
pub fn debug_fmt_mode(
this: &SimValue<Self>,
short_name: bool,
mode: &SimValue<FlagsMode>,
) -> impl fmt::Debug {
fmt::from_fn(move |f| {
#[hdl(sim)]
match mode {
FlagsMode::PowerISA(_) => {
Self::debug_fmt::<PRegFlagsPowerISA>(this, short_name.then_some("Pwr"), f)
}
FlagsMode::X86(_) => {
Self::debug_fmt::<PRegFlagsX86>(this, short_name.then_some("X86"), f)
}
}
})
}
}
impl PRegFlags<UIntInRange<0, { PRegFlags::FLAG_COUNT }>> {
@ -762,7 +836,7 @@ impl PRegFlags {
pub const FLAG_COUNT: usize = PRegFlagsAllUnused::UNUSED_INNER_LEN;
}
#[hdl(cmp_eq)]
#[hdl(cmp_eq, custom_debug(sim))]
/// Unit output register's value -- a combination of an integer/fp register
/// and flags register and CR field.
///
@ -773,6 +847,15 @@ pub struct PRegValue {
pub flags: PRegFlags,
}
impl SimValueDebug for PRegValue {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(&Self::debug_fmt::<PRegFlagsPowerISA>(value, Some("Pwr")), f)
}
}
impl PRegValue {
#[hdl]
pub fn zeroed() -> Expr<Self> {
@ -782,4 +865,47 @@ impl PRegValue {
flags: PRegFlags::zeroed(),
}
}
#[hdl]
pub fn zeroed_sim() -> SimValue<Self> {
#[hdl(sim)]
Self {
int_fp: 0u64,
flags: PRegFlags::zeroed_sim(),
}
}
#[hdl]
pub fn debug_fmt<V: PRegFlagsViewTrait>(
this: &<Self as Type>::SimValue,
flags_type_name: Option<&str>,
) -> impl fmt::Debug {
fmt::from_fn(move |f| {
#[hdl(sim)]
let Self { int_fp, flags } = this;
f.debug_struct("PRegValue")
.field("int_fp", int_fp)
.field(
"flags",
&fmt::from_fn(|f| PRegFlags::debug_fmt::<V>(flags, flags_type_name, f)),
)
.finish()
})
}
#[hdl]
pub fn debug_fmt_mode(
this: &SimValue<Self>,
flags_short_name: bool,
mode: &SimValue<FlagsMode>,
) -> impl fmt::Debug {
fmt::from_fn(move |f| {
#[hdl(sim)]
let Self { int_fp, flags } = this;
f.debug_struct("PRegValue")
.field("int_fp", int_fp)
.field(
"flags",
&PRegFlags::debug_fmt_mode(flags, flags_short_name, mode),
)
.finish()
})
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,311 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
config::{CpuConfig, CpuConfig2PowOutRegNumWidth, CpuConfigUnitCount, PhantomConstCpuConfig},
instruction::{L2RegNum, MOpRegNum, PRegNum, UnitNum, UnitOutRegNum},
rename_execute_retire::L2RegFileLen,
};
use fayalite::{int::UIntInRangeInclusiveType, prelude::*};
#[hdl(no_static)]
pub(crate) struct RenameTableEntry<C: PhantomConstGet<CpuConfig>> {
pub(crate) l1: HdlOption<PRegNum<C>>,
pub(crate) l2: HdlOption<L2RegNum>,
}
impl<C: PhantomConstCpuConfig> RenameTableEntry<C> {
#[hdl]
pub(crate) fn const_zero(self) -> SimValue<Self> {
#[hdl(sim)]
Self {
l1: #[hdl(sim)]
(self.l1).HdlSome(self.l1.HdlSome.const_zero()),
l2: #[hdl(sim)]
HdlNone(),
}
}
}
/// make arrays dynamically-sized to avoid putting large types on the stack
#[hdl(get(|c| 1 << MOpRegNum::WIDTH))]
type MOpRegCount<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(no_static)]
pub(crate) struct RenameTableDebugState<C: PhantomConstGet<CpuConfig>> {
entries: ArrayType<TraceAsString<RenameTableEntry<C>>, MOpRegCount<C>>,
l1_ref_counts: ArrayType<
ArrayType<
UIntInRangeInclusiveType<ConstUsize<0>, MOpRegCount<C>>,
CpuConfig2PowOutRegNumWidth<C>,
>,
CpuConfigUnitCount<C>,
>,
l2_ref_counts:
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, MOpRegCount<C>>, L2RegFileLen<C>>,
config: C,
}
#[derive(Debug)]
pub(crate) struct RenameTable<C: PhantomConstCpuConfig> {
entries: Box<[SimValue<TraceAsString<RenameTableEntry<C>>>; 1 << MOpRegNum::WIDTH]>,
l1_ref_counts: Box<[Box<[usize]>]>,
l2_ref_counts: Box<[usize]>,
config: C,
}
impl<C: PhantomConstCpuConfig> Clone for RenameTable<C> {
fn clone(&self) -> Self {
Self {
entries: self.entries.clone(),
config: self.config.clone(),
l1_ref_counts: self.l1_ref_counts.clone(),
l2_ref_counts: self.l2_ref_counts.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
let Self {
entries,
l1_ref_counts,
l2_ref_counts,
config,
} = self;
entries.clone_from(&source.entries);
l1_ref_counts.clone_from(&source.l1_ref_counts);
l2_ref_counts.clone_from(&source.l2_ref_counts);
*config = source.config;
}
}
#[derive(Debug, Clone)]
pub(crate) enum RenameTableUpdate<C: PhantomConstCpuConfig> {
Write {
unrenamed_reg_num: u32,
new: SimValue<TraceAsString<RenameTableEntry<C>>>,
},
UpdateForReadL2Reg {
dest: SimValue<PRegNum<C>>,
src: SimValue<L2RegNum>,
},
UpdateForWriteL2Reg {
dest: SimValue<L2RegNum>,
src: SimValue<PRegNum<C>>,
},
DropAllL2RegFileOutputs,
}
impl<C: PhantomConstCpuConfig> RenameTable<C> {
pub(crate) fn new(config: C) -> Self {
let entries: Box<[SimValue<TraceAsString<RenameTableEntry<C>>>; 1 << MOpRegNum::WIDTH]> =
vec![
RenameTableEntry[config].const_zero().into_trace_as_string();
1 << MOpRegNum::WIDTH
]
.try_into()
.expect("size is known to match");
Self {
entries,
l1_ref_counts: vec![
vec![0; CpuConfig2PowOutRegNumWidth[config]].into_boxed_slice();
CpuConfigUnitCount[config]
]
.into_boxed_slice(),
l2_ref_counts: vec![0; L2RegFileLen[config]].into_boxed_slice(),
config,
}
}
pub(crate) fn entries(
&self,
) -> &[SimValue<TraceAsString<RenameTableEntry<C>>>; 1 << MOpRegNum::WIDTH] {
&self.entries
}
#[hdl]
pub(crate) fn to_debug_state(&self) -> SimValue<RenameTableDebugState<C>> {
let Self {
entries,
l1_ref_counts,
l2_ref_counts,
config,
} = self;
let ty = RenameTableDebugState[*config];
#[hdl(sim)]
RenameTableDebugState::<_> {
entries: entries.to_sim_value_with_type(ty.entries),
l1_ref_counts: l1_ref_counts.to_sim_value_with_type(ty.l1_ref_counts),
l2_ref_counts: l2_ref_counts.to_sim_value_with_type(ty.l2_ref_counts),
config,
}
}
#[hdl]
pub(crate) fn l1_ref_counts(&self) -> &[Box<[usize]>] {
let mut expected = vec![
vec![0usize; CpuConfig2PowOutRegNumWidth[self.config]]
.into_boxed_slice();
CpuConfigUnitCount[self.config]
];
for entry in self.entries.iter() {
#[hdl(sim)]
let RenameTableEntry::<_> { l1, l2: _ } = entry.inner();
#[hdl(sim)]
if let HdlSome(l1) = l1 {
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
expected[unit_index][UnitOutRegNum::value_sim(&l1.unit_out_reg)] += 1;
}
}
}
assert_eq!(*expected, *self.l1_ref_counts);
&self.l1_ref_counts
}
#[hdl]
pub(crate) fn l2_ref_counts(&self) -> &[usize] {
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
for entry in self.entries.iter() {
#[hdl(sim)]
let RenameTableEntry::<_> { l1: _, l2 } = entry.inner();
#[hdl(sim)]
if let HdlSome(l2) = l2 {
expected[L2RegNum::value_sim(l2)] += 1
}
}
assert_eq!(*expected, *self.l2_ref_counts);
&self.l2_ref_counts
}
#[hdl]
pub(crate) fn update<'a>(&mut self, update: &RenameTableUpdate<C>, rename_table_name: &str) {
let mut update_entry =
|entry: &mut SimValue<TraceAsString<RenameTableEntry<C>>>,
new: SimValue<TraceAsString<RenameTableEntry<C>>>| {
#[hdl(sim)]
let RenameTableEntry::<_> { l1, l2 } = entry.inner();
#[hdl(sim)]
if let HdlSome(l1) = l1 {
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
let ref_count = &mut self.l1_ref_counts[unit_index]
[UnitOutRegNum::value_sim(&l1.unit_out_reg)];
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
unreachable!("{rename_table_name}: l1 ref count went negative: {l1:?}")
});
}
}
#[hdl(sim)]
if let HdlSome(l2) = l2 {
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
unreachable!("{rename_table_name}: l2 ref count went negative: {l2:?}")
});
}
#[hdl(sim)]
let RenameTableEntry::<_> { l1, l2 } = new.inner();
#[hdl(sim)]
if let HdlSome(l1) = l1 {
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
let ref_count = &mut self.l1_ref_counts[unit_index]
[UnitOutRegNum::value_sim(&l1.unit_out_reg)];
*ref_count += 1;
assert!(
*ref_count <= 1 << MOpRegNum::WIDTH,
"{rename_table_name}: l1 ref count overflowed: {l1:?}",
);
}
}
#[hdl(sim)]
if let HdlSome(l2) = l2 {
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
*ref_count += 1;
assert!(
*ref_count <= 1 << MOpRegNum::WIDTH,
"{rename_table_name}: l2 ref count overflowed: {l2:?}",
);
}
*entry = new;
};
match update {
RenameTableUpdate::Write {
unrenamed_reg_num,
new,
} => {
if *unrenamed_reg_num == MOpRegNum::CONST_ZERO_REG_NUM {
// writing to const zero reg does nothing
return;
}
println!("{rename_table_name}: Write: {unrenamed_reg_num:#x} <- {new:?}");
update_entry(&mut self.entries[*unrenamed_reg_num as usize], new.clone());
}
RenameTableUpdate::UpdateForReadL2Reg { dest, src } => {
let new = #[hdl(sim)]
RenameTableEntry::<_> {
l1: #[hdl(sim)]
(HdlOption[dest.ty()]).HdlSome(dest),
l2: #[hdl(sim)]
HdlSome(src),
};
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
#[hdl(sim)]
if let HdlSome(l2) = &entry.inner().l2 {
if L2RegNum::value_sim(l2) == L2RegNum::value_sim(src) {
println!(
"{rename_table_name}: UpdateForReadL2Reg: {unrenamed_reg_num:#x} \
updating from {entry:?} to {new:?}",
);
#[hdl(sim)]
if let HdlSome(_) = &entry.inner().l1 {
unreachable!("l1 should be HdlNone: {entry:?}");
}
update_entry(entry, new.to_trace_as_string());
}
}
}
}
RenameTableUpdate::UpdateForWriteL2Reg { dest, src } => {
let new = #[hdl(sim)]
RenameTableEntry::<_> {
l1: #[hdl(sim)]
(HdlOption[src.ty()]).HdlNone(),
l2: #[hdl(sim)]
HdlSome(dest),
};
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
#[hdl(sim)]
if let HdlSome(l1) = &entry.inner().l1 {
if l1 == src {
println!(
"{rename_table_name}: UpdateForWriteL2Reg: {unrenamed_reg_num:#x} \
updating from {entry:?} to {new:?}",
);
#[hdl(sim)]
if let HdlSome(_) = &entry.inner().l2 {
unreachable!("l2 should be HdlNone: {entry:?}");
}
update_entry(entry, new.to_trace_as_string());
}
}
}
}
RenameTableUpdate::DropAllL2RegFileOutputs => {
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
#[hdl(sim)]
if let HdlSome(_) = &entry.inner().l1 {
#[hdl(sim)]
if let HdlSome(_) = &entry.inner().l2 {
let mut new = entry.inner().clone();
new.l1 = #[hdl(sim)]
(new.l1.ty()).HdlNone();
println!(
"{rename_table_name}: DropAllL2RegFileOutputs: {unrenamed_reg_num:#x} \
updating from {entry:?} to {new:?}",
);
update_entry(entry, new.to_trace_as_string());
}
}
}
}
}
}
#[hdl]
pub(crate) fn used_unit_out_reg_count(&self, unit_index: usize) -> usize {
self.l1_ref_counts()[unit_index]
.iter()
.filter(|ref_count| **ref_count != 0)
.count()
}
}

View file

@ -0,0 +1,564 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
config::{
CpuConfig, CpuConfig2PowOutRegNumWidth, CpuConfigRobSize, CpuConfigUnitCount,
PhantomConstCpuConfig,
},
instruction::{
COMMON_MOP_SRC_LEN, L2RegNum, L2RegisterFileMOp, MOp, MOpTrait, PRegNum, UnitNum,
UnitOutRegNum,
},
next_pc::SimValueDefault,
rename_execute_retire::{
L2RegFileLen, MOpId, MOpInUnitState, MOpInstance, NextPcPredictorOp, RenamedMOp,
UnitCausedCancel, rename_table::RenameTableUpdate, zeroed,
},
util::array_vec::ArrayVec,
};
use fayalite::{
int::{UIntInRangeInclusiveType, UIntInRangeType},
prelude::*,
ty::StaticType,
};
use std::{collections::VecDeque, mem};
#[hdl]
type SimOnlyMOpInUnitState = SimOnly<MOpInUnitState>;
#[hdl(no_static)]
struct RobEntryDebugState<C: PhantomConstGet<CpuConfig>> {
/// See [`RobEntry::is_register_fence`]
is_register_fence: Bool,
/// See [`RobEntry::is_register_fence`]
done_waiting_for_register_fences: Bool,
mop: MOpInstance<RenamedMOp<C>>,
unit_index: UIntInRangeType<ConstUsize<0>, CpuConfigUnitCount<C>>,
mop_in_unit_state: SimOnlyMOpInUnitState,
is_speculative: Bool,
all_prior_mops_finished_and_or_caused_cancel: Bool,
output: HdlOption<NextPcPredictorOp<C>>,
caused_cancel: HdlOption<UnitCausedCancel<C>>,
}
impl<C: PhantomConstCpuConfig> SimValueDefault for RobEntryDebugState<C> {
#[hdl]
fn sim_value_default(self) -> SimValue<Self> {
let Self {
mop,
is_register_fence: _,
done_waiting_for_register_fences: _,
unit_index,
mop_in_unit_state: _,
is_speculative: _,
all_prior_mops_finished_and_or_caused_cancel: _,
output,
caused_cancel,
} = self;
#[hdl(sim)]
Self {
mop: zeroed(mop),
is_register_fence: false,
done_waiting_for_register_fences: false,
unit_index: zeroed(unit_index),
mop_in_unit_state: SimOnlyValue::default(),
is_speculative: false,
all_prior_mops_finished_and_or_caused_cancel: false,
output: #[hdl(sim)]
output.HdlNone(),
caused_cancel: #[hdl(sim)]
caused_cancel.HdlNone(),
}
}
}
#[derive(Debug)]
pub(crate) struct RobEntry<C: PhantomConstCpuConfig> {
/// Block this and all later µOps until all prior µOps are finished and didn't cause a cancel.
/// Not to be confused with memory fences.
pub(crate) is_register_fence: bool,
/// See [`Self::is_register_fence`]
pub(crate) done_waiting_for_register_fences: bool,
pub(crate) mop: SimValue<MOpInstance<RenamedMOp<C>>>,
pub(crate) unit_index: usize,
pub(crate) mop_in_unit_state: MOpInUnitState,
pub(crate) is_speculative: bool,
pub(crate) all_prior_mops_finished_and_or_caused_cancel: bool,
pub(crate) output: Option<SimValue<NextPcPredictorOp<C>>>,
pub(crate) caused_cancel: Option<SimValue<UnitCausedCancel<C>>>,
}
impl<C: PhantomConstCpuConfig> RobEntry<C> {
pub(crate) fn new(
mop: SimValue<MOpInstance<RenamedMOp<C>>>,
unit_index: usize,
is_register_fence: bool,
) -> Self {
Self {
mop,
is_register_fence,
done_waiting_for_register_fences: false,
unit_index,
mop_in_unit_state: MOpInUnitState::NotYetEnqueued,
is_speculative: true,
all_prior_mops_finished_and_or_caused_cancel: false,
output: None,
caused_cancel: None,
}
}
fn dest_reg(&self) -> Option<&SimValue<PRegNum<C>>> {
let dest_reg = MOpTrait::dest_reg_sim_ref(self.mop.mop.inner());
let unit_index = UnitNum::index_sim(&dest_reg.unit_num)?;
assert_eq!(unit_index, self.unit_index);
Some(dest_reg)
}
fn unit_out_reg(&self) -> Option<&SimValue<UnitOutRegNum<C>>> {
Some(&self.dest_reg()?.unit_out_reg)
}
pub(crate) fn unit_out_reg_index(&self) -> Option<usize> {
Some(UnitOutRegNum::value_sim(self.unit_out_reg()?))
}
#[hdl]
fn debug_state(&self, config: C) -> SimValue<RobEntryDebugState<C>> {
let Self {
is_register_fence,
done_waiting_for_register_fences,
mop,
unit_index,
mop_in_unit_state,
is_speculative,
all_prior_mops_finished_and_or_caused_cancel,
output,
caused_cancel,
} = self;
let ret_ty = RobEntryDebugState[config];
#[hdl(sim)]
RobEntryDebugState::<C> {
is_register_fence,
done_waiting_for_register_fences,
mop,
unit_index: unit_index.into_sim_value_with_type(ret_ty.unit_index),
mop_in_unit_state: SimOnlyValue::new(*mop_in_unit_state),
is_speculative,
all_prior_mops_finished_and_or_caused_cancel,
output: output.into_sim_value_with_type(ret_ty.output),
caused_cancel: caused_cancel.into_sim_value_with_type(ret_ty.caused_cancel),
}
}
#[hdl]
fn for_each_reg<S>(
&self,
mut shared_state: S,
mut l1_reg: impl FnMut(&mut S, &SimValue<PRegNum<C>>),
mut l2_reg: impl FnMut(&mut S, &SimValue<L2RegNum>),
) {
l1_reg(
&mut shared_state,
MOpTrait::dest_reg_sim_ref(self.mop.mop.inner()),
);
MOpTrait::for_each_src_reg_sim_ref(self.mop.mop.inner(), &mut |l1, _| {
l1_reg(&mut shared_state, l1);
});
#[hdl(sim)]
if let RenamedMOp::<_>::TransformedMove(mop) = self.mop.mop.inner() {
#[hdl(sim)]
match mop {
L2RegisterFileMOp::<_, _>::ReadL2Reg(v) => {
l2_reg(&mut shared_state, &v.common.imm);
}
L2RegisterFileMOp::<_, _>::WriteL2Reg(v) => {
l2_reg(&mut shared_state, &v.common.imm);
}
}
}
}
}
#[hdl]
struct RobEntriesDebugState {
unrenamed: MOpInstance<MOp>,
/// number of renamed &micro;Ops that this unrenamed &micro;Op corresponds to
renamed_entries_len: UInt<8>,
}
impl SimValueDefault for RobEntriesDebugState {
#[hdl]
fn sim_value_default(self) -> SimValue<Self> {
let Self {
unrenamed,
renamed_entries_len,
} = self;
#[hdl(sim)]
Self {
unrenamed: zeroed(unrenamed),
renamed_entries_len: renamed_entries_len.sim_value_default(),
}
}
}
#[derive(Debug)]
struct RobEntries<C: PhantomConstCpuConfig> {
unrenamed: SimValue<MOpInstance<MOp>>,
rename_table_updates: Vec<RenameTableUpdate<C>>,
renamed_entries: VecDeque<RobEntry<C>>,
}
impl<C: PhantomConstCpuConfig> RobEntries<C> {
#[hdl]
fn debug_state(&self) -> SimValue<RobEntriesDebugState> {
let Self {
unrenamed,
rename_table_updates: _,
renamed_entries,
} = self;
#[hdl(sim)]
RobEntriesDebugState {
unrenamed,
renamed_entries_len: u8::try_from(renamed_entries.len())
.expect("renamed_entries.len() should fit in u8"),
}
}
}
#[hdl(get(|c| c.rob_size.get() * (1 + COMMON_MOP_SRC_LEN)))]
type L1RegMaxRefCount<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(no_static)]
pub(crate) struct ReorderBufferDebugState<C: PhantomConstGet<CpuConfig>> {
next_renamed_mop_id: MOpId,
entries: ArrayVec<RobEntriesDebugState, CpuConfigRobSize<C>>,
incomplete_back_entry: HdlOption<RobEntriesDebugState>,
renamed: ArrayVec<RobEntryDebugState<C>, CpuConfigRobSize<C>>,
l1_reg_ref_counts: ArrayType<
ArrayType<
UIntInRangeInclusiveType<ConstUsize<0>, L1RegMaxRefCount<C>>,
CpuConfig2PowOutRegNumWidth<C>,
>,
CpuConfigUnitCount<C>,
>,
l2_reg_ref_counts:
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, CpuConfigRobSize<C>>, L2RegFileLen<C>>,
config: C,
}
impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
#[hdl]
fn sim_value_default(self) -> SimValue<Self> {
let Self {
next_renamed_mop_id,
entries,
incomplete_back_entry,
renamed,
l1_reg_ref_counts,
l2_reg_ref_counts,
config,
} = self;
#[hdl(sim)]
Self {
next_renamed_mop_id: next_renamed_mop_id.sim_value_default(),
entries: entries.sim_value_default(),
incomplete_back_entry: incomplete_back_entry.sim_value_default(),
renamed: renamed.sim_value_default(),
l1_reg_ref_counts: zeroed(l1_reg_ref_counts),
l2_reg_ref_counts: zeroed(l2_reg_ref_counts),
config,
}
}
}
#[derive(Debug)]
pub(crate) struct ReorderBuffer<C: PhantomConstCpuConfig> {
next_renamed_mop_id: SimValue<MOpId>,
entries: VecDeque<RobEntries<C>>,
incomplete_back_entry: Option<RobEntries<C>>,
l1_reg_ref_counts: Box<[Box<[usize]>]>,
l2_reg_ref_counts: Box<[usize]>,
config: C,
}
impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
pub(crate) fn new(config: C) -> Self {
Self {
next_renamed_mop_id: MOpId.zero().into_sim_value(),
entries: VecDeque::new(),
incomplete_back_entry: None,
l1_reg_ref_counts: vec![
vec![0; CpuConfig2PowOutRegNumWidth[config]].into_boxed_slice();
CpuConfigUnitCount[config]
]
.into_boxed_slice(),
l2_reg_ref_counts: vec![0; L2RegNum.l2_reg_count()].into_boxed_slice(),
config,
}
}
#[hdl]
pub(crate) fn l1_reg_ref_counts(&self) -> &[Box<[usize]>] {
let mut expected = vec![
vec![0usize; CpuConfig2PowOutRegNumWidth[self.config]]
.into_boxed_slice();
CpuConfigUnitCount[self.config]
];
for entry in self.renamed() {
entry.for_each_reg(
(),
|(), l1| {
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
expected[unit_index][UnitOutRegNum::value_sim(&l1.unit_out_reg)] += 1
}
},
|(), _l2| {},
);
}
assert_eq!(*expected, *self.l1_reg_ref_counts);
&self.l1_reg_ref_counts
}
#[hdl]
pub(crate) fn l2_reg_ref_counts(&self) -> &[usize] {
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
for entry in self.renamed() {
entry.for_each_reg(
(),
|(), _l1| {},
|(), l2| expected[L2RegNum::value_sim(l2)] += 1,
);
}
assert_eq!(*expected, *self.l2_reg_ref_counts);
&self.l2_reg_ref_counts
}
#[hdl]
pub(crate) fn debug_state(&self) -> SimValue<ReorderBufferDebugState<C>> {
let Self {
next_renamed_mop_id,
entries,
incomplete_back_entry,
l1_reg_ref_counts,
l2_reg_ref_counts,
config,
} = self;
let ty = ReorderBufferDebugState[*config];
#[hdl(sim)]
ReorderBufferDebugState::<_> {
next_renamed_mop_id,
entries: ty
.entries
.from_iter_sim(
zeroed(StaticType::TYPE),
entries.iter().map(RobEntries::debug_state),
)
.expect("known to fit"),
incomplete_back_entry: incomplete_back_entry.as_ref().map(|v| v.debug_state()),
renamed: ty
.renamed
.from_iter_sim(
ty.renamed.element().sim_value_default(),
self.renamed().map(|v| v.debug_state(*config)),
)
.ok()
.expect("known to fit"),
l1_reg_ref_counts: l1_reg_ref_counts.to_sim_value_with_type(ty.l1_reg_ref_counts),
l2_reg_ref_counts: l2_reg_ref_counts.to_sim_value_with_type(ty.l2_reg_ref_counts),
config,
}
}
pub(crate) fn unrenamed_len(&self) -> usize {
self.entries.len()
}
pub(crate) fn unrenamed(
&self,
) -> impl DoubleEndedIterator<Item = &SimValue<MOpInstance<MOp>>> + Clone {
self.entries.iter().map(|v| &v.unrenamed)
}
fn retire_groups_unrenamed_ranges(
&self,
) -> impl Clone + Iterator<Item = std::ops::Range<usize>> {
let mut next_group_start = 0;
self.entries
.iter()
.enumerate()
.filter_map(move |(index, entry)| {
if *entry.unrenamed.is_last_mop_in_insn {
let group_start = next_group_start;
next_group_start = index + 1;
Some(group_start..next_group_start)
} else {
None
}
})
}
pub(crate) fn retire_groups(
&self,
) -> impl Clone + Iterator<Item: DoubleEndedIterator<Item = &VecDeque<RobEntry<C>>> + Clone>
{
self.retire_groups_unrenamed_ranges().map(|range| {
self.entries
.range(range)
.map(|entries| &entries.renamed_entries)
})
}
pub(crate) fn renamed_len(&self) -> usize {
let Self {
next_renamed_mop_id: _,
entries,
incomplete_back_entry,
l1_reg_ref_counts: _,
l2_reg_ref_counts: _,
config: _,
} = self;
entries
.iter()
.chain(incomplete_back_entry)
.map(|entries| entries.renamed_entries.len())
.sum()
}
pub(crate) fn renamed(&self) -> impl DoubleEndedIterator<Item = &RobEntry<C>> + Clone {
let Self {
next_renamed_mop_id: _,
entries,
incomplete_back_entry,
l1_reg_ref_counts: _,
l2_reg_ref_counts: _,
config: _,
} = self;
entries
.iter()
.chain(incomplete_back_entry)
.flat_map(|entries| &entries.renamed_entries)
}
pub(crate) fn renamed_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut RobEntry<C>> {
let Self {
next_renamed_mop_id: _,
entries,
incomplete_back_entry,
l1_reg_ref_counts: _,
l2_reg_ref_counts: _,
config: _,
} = self;
entries
.iter_mut()
.chain(incomplete_back_entry)
.flat_map(|entries| &mut entries.renamed_entries)
}
fn try_renamed_by_id_mut(&mut self, id: &SimValue<MOpId>) -> Option<&mut RobEntry<C>> {
self.renamed_mut().find(|v| v.mop.id == *id)
}
pub(crate) fn renamed_by_id_mut(&mut self, id: &SimValue<MOpId>) -> &mut RobEntry<C> {
match self.try_renamed_by_id_mut(id) {
Some(v) => v,
None => panic!("MOpId not found: {id:?}"),
}
}
pub(crate) fn renamed_push_back_with_new_id(
&mut self,
unrenamed: &SimValue<MOpInstance<MOp>>,
mut renamed: RobEntry<C>,
) -> &SimValue<MOpId> {
let replacement_id = self
.next_renamed_mop_id
.as_int()
.wrapping_add(1)
.into_sim_value();
renamed.mop.id = mem::replace(&mut self.next_renamed_mop_id, replacement_id);
println!("renamed_push_back_with_new_id: {:?}", renamed.mop);
renamed.for_each_reg(
(),
|(), l1| {
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
self.l1_reg_ref_counts[unit_index]
[UnitOutRegNum::value_sim(&l1.unit_out_reg)] += 1;
}
},
|(), l2| self.l2_reg_ref_counts[L2RegNum::value_sim(l2)] += 1,
);
let renamed_entries = &mut self
.incomplete_back_entry
.get_or_insert_with(|| RobEntries {
unrenamed: unrenamed.clone(),
rename_table_updates: Vec::new(),
renamed_entries: VecDeque::new(),
})
.renamed_entries;
renamed_entries.push_back(renamed);
&renamed_entries.back().expect("just pushed").mop.id
}
pub(crate) fn has_incomplete_back_entry(&self) -> bool {
self.incomplete_back_entry.is_some()
}
pub(crate) fn finished_unrenamed_push_back(&mut self, unrenamed: &SimValue<MOpInstance<MOp>>) {
let entry = self
.incomplete_back_entry
.take()
.unwrap_or_else(|| RobEntries {
unrenamed: unrenamed.clone(),
rename_table_updates: Vec::new(),
renamed_entries: VecDeque::new(),
});
self.entries.push_back(entry);
}
pub(crate) fn clear(&mut self) {
let Self {
next_renamed_mop_id: _,
entries,
incomplete_back_entry,
l1_reg_ref_counts,
l2_reg_ref_counts,
config: _,
} = self;
entries.clear();
l2_reg_ref_counts.fill(0);
for i in l1_reg_ref_counts {
i.fill(0);
}
*incomplete_back_entry = None;
}
pub(crate) fn unrenamed_back_append_rename_table_update(
&mut self,
unrenamed: &SimValue<MOpInstance<MOp>>,
update: RenameTableUpdate<C>,
) {
self.incomplete_back_entry
.get_or_insert_with(|| RobEntries {
unrenamed: unrenamed.clone(),
rename_table_updates: Vec::new(),
renamed_entries: VecDeque::new(),
})
.rename_table_updates
.push(update);
}
pub(crate) fn all_mops_are_finished_and_or_caused_cancel(&self) -> bool {
self.renamed().next().is_none_or(|entry| {
entry.all_prior_mops_finished_and_or_caused_cancel
&& entry.mop_in_unit_state.is_finished_and_or_caused_cancel()
})
}
pub(crate) fn entries_pop_front(
&mut self,
) -> Option<(Vec<RenameTableUpdate<C>>, VecDeque<RobEntry<C>>)> {
let RobEntries {
unrenamed: _,
rename_table_updates,
renamed_entries,
} = self.entries.pop_front()?;
for entry in &renamed_entries {
entry.for_each_reg(
(),
|(), l1| {
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
let ref_count = &mut self.l1_reg_ref_counts[unit_index]
[UnitOutRegNum::value_sim(&l1.unit_out_reg)];
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
unreachable!("ReorderBuffer: l1 ref count went negative: {l1:?}")
});
}
},
|(), l2| {
let ref_count = &mut self.l2_reg_ref_counts[L2RegNum::value_sim(l2)];
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
unreachable!("ReorderBuffer: l2 ref count went negative: {l2:?}")
});
},
);
}
Some((rename_table_updates, renamed_entries))
}
}

View file

@ -0,0 +1,207 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{config::CpuConfig, rename_execute_retire::ExecuteToUnitInterface};
use fayalite::{
bundle::{BundleField, BundleType, NoBuilder},
expr::ops::FieldAccess,
intern::{Intern, Interned, Memoize},
prelude::*,
ty::{
OpaqueSimValue, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten,
SimValueDebug,
},
};
use std::{fmt, marker::PhantomData, ops::Index};
/// a bundle with fields of type [`ExecuteToUnitInterface<C>`] for each unit
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ExecuteToUnitInterfaces<C: Type + PhantomConstGet<CpuConfig>> {
bundle_ty: Bundle,
config: C,
}
impl<C: Type + PhantomConstGet<CpuConfig>> fmt::Debug for ExecuteToUnitInterfaces<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("ExecuteToUnitInterfaces ")?;
let fields = self.bundle_ty.fields();
let field_offsets = self.bundle_ty.field_offsets();
f.debug_set()
.entries(
fields.iter().enumerate().map(|(index, field)| {
field.fmt_debug_in_struct(field_offsets[index].bit_width)
}),
)
.finish()
}
}
const CONFIG_FIELD_NAME: &str = "config";
impl<C: Type + PhantomConstGet<CpuConfig>> ExecuteToUnitInterfaces<C> {
pub fn new(config: C) -> Self {
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
struct MyMemoize<C>(PhantomData<C>);
impl<C: Type + PhantomConstGet<CpuConfig>> Memoize for MyMemoize<C> {
type Input = C;
type InputOwned = C;
type Output = ExecuteToUnitInterfaces<C>;
fn inner(self, &config: &Self::Input) -> Self::Output {
let unit_ty = ExecuteToUnitInterface[config].canonical();
let bundle_ty = Bundle::new(
(0..config.get().units.len())
.map(|unit_index| BundleField {
name: format!(
"u{unit_index}_{:?}",
config.get().units[unit_index].kind,
)
.intern_deref(),
flipped: false,
ty: unit_ty,
})
.chain([BundleField {
name: CONFIG_FIELD_NAME.intern(),
flipped: false,
ty: config.canonical(),
}])
.collect(),
);
ExecuteToUnitInterfaces { bundle_ty, config }
}
}
MyMemoize(PhantomData).get_owned(config)
}
pub fn bundle_ty(self) -> Bundle {
self.bundle_ty
}
pub fn config(self) -> C {
self.config
}
#[track_caller]
pub fn unit_field_name(self, unit_index: usize) -> Interned<str> {
assert!(unit_index < self.config.get().units.len());
self.bundle_ty.fields()[unit_index].name
}
pub fn unit_fields(
this: impl ToExpr<Type = Self>,
) -> Interned<[Expr<ExecuteToUnitInterface<C>>]> {
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
struct MyMemoize<C>(PhantomData<C>);
impl<C: Type + PhantomConstGet<CpuConfig>> Memoize for MyMemoize<C> {
type Input = Expr<ExecuteToUnitInterfaces<C>>;
type InputOwned = Expr<ExecuteToUnitInterfaces<C>>;
type Output = Interned<[Expr<ExecuteToUnitInterface<C>>]>;
fn inner(self, this: &Self::Input) -> Self::Output {
let bundle = Expr::as_bundle(*this);
(0..this.ty().config.get().units.len())
.map(|unit_index| FieldAccess::new_by_index(bundle, unit_index).to_expr())
.collect()
}
}
MyMemoize(PhantomData).get_owned(this.to_expr())
}
}
#[doc(hidden)]
pub struct ExecuteToUnitInterfacesWithoutGenerics(());
#[expect(non_upper_case_globals)]
pub const ExecuteToUnitInterfaces: ExecuteToUnitInterfacesWithoutGenerics =
ExecuteToUnitInterfacesWithoutGenerics(());
impl<C: Type + PhantomConstGet<CpuConfig>> Index<C> for ExecuteToUnitInterfacesWithoutGenerics {
type Output = ExecuteToUnitInterfaces<C>;
fn index(&self, config: C) -> &Self::Output {
Interned::into_inner(ExecuteToUnitInterfaces::new(config).intern())
}
}
impl<C: Type + PhantomConstGet<CpuConfig>> SimValueDebug for ExecuteToUnitInterfaces<C> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<C: Type + PhantomConstGet<CpuConfig>> Type for ExecuteToUnitInterfaces<C> {
type BaseType = Bundle;
type MaskType = Bundle;
type SimValue = OpaqueSimValue;
type MatchVariant = <Bundle as Type>::MatchVariant;
type MatchActiveScope = <Bundle as Type>::MatchActiveScope;
type MatchVariantAndInactiveScope = <Bundle as Type>::MatchVariantAndInactiveScope;
type MatchVariantsIter = <Bundle as Type>::MatchVariantsIter;
fn match_variants(
this: Expr<Self>,
source_location: SourceLocation,
) -> Self::MatchVariantsIter {
Type::match_variants(Expr::as_bundle(this), source_location)
}
fn mask_type(&self) -> Self::MaskType {
self.bundle_ty.mask_type()
}
fn canonical(&self) -> CanonicalType {
self.bundle_ty.canonical()
}
fn from_canonical(canonical_type: CanonicalType) -> Self {
let bundle_ty = Bundle::from_canonical(canonical_type);
let config = if let Some(BundleField {
name,
flipped: false,
ty,
}) = bundle_ty.fields().last()
&& **name == *CONFIG_FIELD_NAME
{
C::from_canonical(*ty)
} else {
panic!(
"ExecuteToUnitInterfaces must have `{}` field",
CONFIG_FIELD_NAME
);
};
let retval = Self::new(config);
assert_eq!(bundle_ty, retval.bundle_ty);
retval
}
fn source_location() -> SourceLocation {
SourceLocation::caller()
}
fn sim_value_from_opaque(&self, opaque: OpaqueSimValueSlice<'_>) -> Self::SimValue {
<Bundle as Type>::sim_value_from_opaque(&self.bundle_ty, opaque)
}
fn sim_value_clone_from_opaque(
&self,
value: &mut Self::SimValue,
opaque: OpaqueSimValueSlice<'_>,
) {
<Bundle as Type>::sim_value_clone_from_opaque(&self.bundle_ty, value, opaque)
}
fn sim_value_to_opaque<'w>(
&self,
value: &Self::SimValue,
writer: OpaqueSimValueWriter<'w>,
) -> OpaqueSimValueWritten<'w> {
<Bundle as Type>::sim_value_to_opaque(&self.bundle_ty, value, writer)
}
}
impl<C: Type + PhantomConstGet<CpuConfig>> BundleType for ExecuteToUnitInterfaces<C> {
type Builder = NoBuilder;
fn fields(&self) -> Interned<[BundleField]> {
self.bundle_ty.fields()
}
}

View file

@ -0,0 +1,41 @@
%% SPDX-License-Identifier: LGPL-3.0-or-later
%% See Notices.txt for copyright information
stateDiagram-v2
direction LR
state "Inputs not ready<br/>Speculative<br/>Can cause cancel" as inr_s_c
state "Inputs not ready<br/>Speculative" as inr_s
state "Inputs ready<br/>Speculative<br/>Can cause cancel" as ir_s_c
state "Inputs ready<br/>Speculative" as ir_s
state "Inputs ready<br/>Can cause cancel" as ir_c
state "Inputs ready" as ir
state "Output ready<br/>Speculative<br/>Can cause cancel" as or_s_c
state "Output ready<br/>Can cause cancel" as or_c
state "Output ready<br/>Speculative" as or_s
state "Output ready" as or
[*] --> inr_s_c: Enqueue
inr_s_c --> inr_s: Can't cause cancel
ir_s_c --> ir_s: Can't cause cancel
ir_c --> ir: Can't cause cancel
or_s_c --> or_s: Can't cause cancel
or_c --> or: Can't cause cancel
ir_s_c --> ir_c: No longer speculative
ir_s --> ir: No longer speculative
or_s_c --> or_c: No longer speculative
or_s --> or: No longer speculative
inr_s_c --> ir_s_c: Inputs ready
inr_s --> ir_s: Inputs ready
ir_s_c --> or_s_c: Output Ready
ir_c --> or_c: Output Ready
ir_s --> or_s: Output Ready
ir --> or: Output Ready
or_s_c --> [*]: Finish
or_c --> [*]: Finish
or_s --> [*]: Finish
or --> [*]: Finish

View file

@ -2,11 +2,11 @@
// See Notices.txt for copyright information
use crate::{
config::CpuConfig,
config::{CpuConfig, PhantomConstCpuConfig},
instruction::{
AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait,
MOpVariantVisitOps, MOpVariantVisitor, MOpVisitVariants, RenamedMOp, UnitOutRegNum,
mop_enum,
MOpVariantVisitOps, MOpVariantVisitor, MOpVisitVariants, PRegNum, RenamedMOp,
UnitOutRegNum, mop_enum,
},
register::{FlagsMode, PRegValue},
unit::unit_base::UnitToRegAlloc,
@ -26,13 +26,13 @@ macro_rules! all_units {
(
#[hdl_unit_kind = $HdlUnitKind:ident]
#[unit_kind = $UnitKind:ident]
#[hdl]
#[hdl(custom_debug(sim))]
$(#[$enum_meta:meta])*
$vis:vis enum $UnitMOpEnum:ident<$DestReg:ident: Type, $SrcRegWidth:ident: Size, #[MOp(get_ty = $transformed_move_op_get_ty:expr)] $TransformedMoveOp:ident: Type> {
$vis:vis enum $UnitMOpEnum:ident<$DestReg:ident: Type, $SrcReg:ident: Type, #[MOp(get_ty = $transformed_move_op_get_ty:expr)] $TransformedMoveOp:ident: Type> {
$(
$(#[transformed_move $($transformed_move:tt)*])?
#[create_dyn_unit_fn = $create_dyn_unit_fn:expr]
#[extract = $extract:ident]
#[extract($extract:ident, $extract_sim:ident, $extract_sim_ref:ident, $extract_sim_mut:ident)]
$(#[$variant_meta:meta])*
$Unit:ident($Op:ty),
)*
@ -48,7 +48,7 @@ macro_rules! all_units {
}
impl $UnitKind {
pub fn unit(self, config: &CpuConfig, unit_index: usize) -> DynUnit {
pub fn unit(self, config: PhantomConst<CpuConfig>, unit_index: usize) -> DynUnit {
match self {
$($UnitKind::$Unit => $create_dyn_unit_fn(config, unit_index),)*
}
@ -83,15 +83,15 @@ macro_rules! all_units {
mop_enum! {
#[impl_mop_into = false]
#[hdl]
#[hdl(custom_debug(sim))]
$(#[$enum_meta])*
$vis enum $UnitMOpEnum<
$DestReg: Type,
$SrcRegWidth: Size,
$SrcReg: Type,
#[MOp(get_ty = $transformed_move_op_get_ty)] $TransformedMoveOp: Type,
#[MOpVisitVariants] [
$TransformedMoveOp: MOpVisitVariants<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
$($Op: MOpVisitVariants<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,)*
$TransformedMoveOp: MOpVisitVariants<DestReg = $DestReg, SrcReg = $SrcReg>,
$($Op: MOpVisitVariants<DestReg = $DestReg, SrcReg = $SrcReg>,)*
]
> {
$(
@ -101,7 +101,7 @@ macro_rules! all_units {
}
}
impl<$DestReg: Type, $SrcRegWidth: Size, $TransformedMoveOp: Type> $UnitMOpEnum<$DestReg, $SrcRegWidth, $TransformedMoveOp> {
impl<$DestReg: Type, $SrcReg: Type, $TransformedMoveOp: Type> $UnitMOpEnum<$DestReg, $SrcReg, $TransformedMoveOp> {
#[hdl]
$vis fn kind(expr: impl ToExpr<Type = Self>) -> Expr<$HdlUnitKind> {
#[hdl]
@ -112,6 +112,15 @@ macro_rules! all_units {
}
unit_kind
}
#[hdl]
$vis fn kind_sim(expr: &SimValue<Self>) -> UnitKind {
#![allow(unreachable_patterns)]
#[hdl(sim)]
match expr {
$(Self::$Unit(_) => $UnitKind::$Unit,)*
_ => unreachable!(),
}
}
$(
#[hdl]
$vis fn $extract(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<$Op>> {
@ -126,19 +135,47 @@ macro_rules! all_units {
}
$extract
}
#[hdl]
$vis fn $extract_sim(expr: impl ToSimValue<Type = Self>) -> Option<SimValue<$Op>> {
let expr = expr.into_sim_value();
#[hdl(sim)]
if let Self::$Unit(v) = expr {
Some(v)
} else {
None
}
}
#[hdl]
$vis fn $extract_sim_ref(expr: &SimValue<Self>) -> Option<&SimValue<$Op>> {
#[hdl(sim)]
if let Self::$Unit(v) = expr {
Some(v)
} else {
None
}
}
#[hdl]
$vis fn $extract_sim_mut(expr: &mut SimValue<Self>) -> Option<&mut SimValue<$Op>> {
#[hdl(sim)]
if let Self::$Unit(v) = expr {
Some(v)
} else {
None
}
}
)*
$vis fn with_transformed_move_op_ty<T>(self, new_transformed_move_op_ty: T) -> $UnitMOpEnum<$DestReg, $SrcRegWidth, T>
$vis fn with_transformed_move_op_ty<T>(self, new_transformed_move_op_ty: T) -> $UnitMOpEnum<$DestReg, $SrcReg, T>
where
T: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
T: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
{
$UnitMOpEnum[self.dest_reg_ty()][self.src_reg_width()][new_transformed_move_op_ty]
$UnitMOpEnum[self.dest_reg_ty()][self.src_reg_ty()][new_transformed_move_op_ty]
}
}
all_units! {
@split_by_transformed_move
$vis enum $UnitMOpEnum<$DestReg: Type, $SrcRegWidth: Size, $TransformedMoveOp: Type> {
$vis enum $UnitMOpEnum<$DestReg: Type, $SrcReg: Type, $TransformedMoveOp: Type> {
$(
$(#[transformed_move $($transformed_move)*])?
$Unit($Op),
@ -163,23 +200,23 @@ macro_rules! all_units {
};
(
@split_by_transformed_move
$vis:vis enum $UnitMOpEnum:ident<$DestReg:ident: Type, $SrcRegWidth:ident: Size, $TransformedMoveOp:ident: Type> {
$vis:vis enum $UnitMOpEnum:ident<$DestReg:ident: Type, $SrcReg:ident: Type, $TransformedMoveOp:ident: Type> {
$($BeforeUnit:ident($BeforeOp:ty),)*
#[transformed_move]
$TransformedMove:ident($TransformedMoveOp2:ty),
$($AfterUnit:ident($AfterOp:ty),)*
}
) => {
impl<$DestReg: Type, $SrcRegWidth: Size, $TransformedMoveOp: Type> $UnitMOpEnum<$DestReg, $SrcRegWidth, $TransformedMoveOp> {
impl<$DestReg: Type, $SrcReg: Type, $TransformedMoveOp: Type> $UnitMOpEnum<$DestReg, $SrcReg, $TransformedMoveOp> {
#[hdl]
$vis fn try_with_transformed_move_op<T>(
this: impl ToExpr<Type = Self>,
new_transformed_move_op_ty: T,
connect_transformed_move_op: impl FnOnce(Expr<HdlOption<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>>, Expr<$TransformedMoveOp>),
) -> Expr<HdlOption<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>>
connect_transformed_move_op: impl FnOnce(Expr<HdlOption<$UnitMOpEnum<$DestReg, $SrcReg, T>>>, Expr<$TransformedMoveOp>),
) -> Expr<HdlOption<$UnitMOpEnum<$DestReg, $SrcReg, T>>>
where
T: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
T: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
{
let this = this.to_expr();
let new_ty = this.ty().with_transformed_move_op_ty(new_transformed_move_op_ty);
@ -196,12 +233,51 @@ macro_rules! all_units {
}
with_transformed_move_op
}
#[hdl]
$vis fn try_with_transformed_move_op_sim<T, E>(
this: impl ToSimValue<Type = Self>,
new_transformed_move_op_ty: T,
f: impl FnOnce(SimValue<$TransformedMoveOp>) -> Result<SimValue<$UnitMOpEnum<$DestReg, $SrcReg, T>>, E>,
) -> Result<SimValue<$UnitMOpEnum<$DestReg, $SrcReg, T>>, E>
where
T: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
{
#![allow(unreachable_patterns)]
let this = this.into_sim_value();
let new_ty = this.ty().with_transformed_move_op_ty(new_transformed_move_op_ty);
#[hdl(sim)]
match this {
$(Self::$BeforeUnit(unit) => Ok(
#[hdl(sim)]
new_ty.$BeforeUnit(unit)
),)*
Self::$TransformedMove(unit) => f(unit),
$(Self::$AfterUnit(unit) => Ok(
#[hdl(sim)]
new_ty.$AfterUnit(unit)
),)*
_ => unreachable!(),
}
}
$vis fn with_transformed_move_op_sim<T>(
this: impl ToSimValue<Type = Self>,
new_transformed_move_op_ty: T,
f: impl FnOnce(SimValue<$TransformedMoveOp>) -> SimValue<$UnitMOpEnum<$DestReg, $SrcReg, T>>,
) -> SimValue<$UnitMOpEnum<$DestReg, $SrcReg, T>>
where
T: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcReg = $SrcReg>,
{
let Ok::<_, std::convert::Infallible>(retval) = Self::try_with_transformed_move_op_sim(this, new_transformed_move_op_ty, move |v| Ok(f(v)));
retval
}
}
const _: () = {
#[hdl]
type $DestReg = MOpDestReg;
type $SrcRegWidth = ConstUsize<{ MOpRegNum::WIDTH }>;
type $SrcReg = MOpRegNum;
$(impl MOpInto<MOp> for $BeforeOp {
fn mop_into_ty(self) -> MOp {
@ -222,21 +298,21 @@ macro_rules! all_units {
})*
};
$(impl<$DestReg: Type, $SrcRegWidth: Size> MOpInto<RenamedMOp<$DestReg, $SrcRegWidth>> for $BeforeOp {
fn mop_into_ty(self) -> RenamedMOp<$DestReg, $SrcRegWidth> {
RenamedMOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_width(self)]
$(impl<$DestReg: Type, $SrcReg: Type> MOpInto<RenamedMOp<$DestReg, $SrcReg>> for $BeforeOp {
fn mop_into_ty(self) -> RenamedMOp<$DestReg, $SrcReg> {
RenamedMOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_ty(self)]
}
fn mop_into(this: Expr<Self>) -> Expr<RenamedMOp<$DestReg, $SrcRegWidth>> {
MOpInto::<RenamedMOp<$DestReg, $SrcRegWidth>>::mop_into_ty(this.ty()).$BeforeUnit(this)
fn mop_into(this: Expr<Self>) -> Expr<RenamedMOp<$DestReg, $SrcReg>> {
MOpInto::<RenamedMOp<$DestReg, $SrcReg>>::mop_into_ty(this.ty()).$BeforeUnit(this)
}
})*
$(impl<$DestReg: Type, $SrcRegWidth: Size> MOpInto<RenamedMOp<$DestReg, $SrcRegWidth>> for $AfterOp {
fn mop_into_ty(self) -> RenamedMOp<$DestReg, $SrcRegWidth> {
RenamedMOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_width(self)]
$(impl<$DestReg: Type, $SrcReg: Type> MOpInto<RenamedMOp<$DestReg, $SrcReg>> for $AfterOp {
fn mop_into_ty(self) -> RenamedMOp<$DestReg, $SrcReg> {
RenamedMOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_ty(self)]
}
fn mop_into(this: Expr<Self>) -> Expr<RenamedMOp<$DestReg, $SrcRegWidth>> {
MOpInto::<RenamedMOp<$DestReg, $SrcRegWidth>>::mop_into_ty(this.ty()).$AfterUnit(this)
fn mop_into(this: Expr<Self>) -> Expr<RenamedMOp<$DestReg, $SrcReg>> {
MOpInto::<RenamedMOp<$DestReg, $SrcReg>>::mop_into_ty(this.ty()).$AfterUnit(this)
}
})*
};
@ -245,24 +321,24 @@ macro_rules! all_units {
all_units! {
#[hdl_unit_kind = HdlUnitKind]
#[unit_kind = UnitKind]
#[hdl]
#[hdl(custom_debug(sim))]
pub enum UnitMOp<
DestReg: Type,
SrcRegWidth: Size,
#[MOp(get_ty = |this: UnitMOp<DestReg, SrcRegWidth, TransformedMoveOp>, new_dest_reg, new_src_reg_width| {
this.TransformedMove.mapped_ty(new_dest_reg, new_src_reg_width)
SrcReg: Type,
#[MOp(get_ty = |this: UnitMOp<DestReg, SrcReg, TransformedMoveOp>, new_dest_reg, new_src_reg| {
this.TransformedMove.mapped_ty(new_dest_reg, new_src_reg)
})] TransformedMoveOp: Type
> {
#[create_dyn_unit_fn = |config, unit_index| alu_branch::AluBranch::new(config, unit_index).to_dyn()]
#[extract = alu_branch_mop]
AluBranch(AluBranchMOp<DestReg, SrcRegWidth>),
#[extract(alu_branch_mop, alu_branch_mop_sim, alu_branch_mop_sim_ref, alu_branch_mop_sim_mut)]
AluBranch(AluBranchMOp<DestReg, SrcReg>),
#[transformed_move]
#[create_dyn_unit_fn = |config, unit_index| todo!()]
#[extract = transformed_move_mop]
#[extract(transformed_move_mop, transformed_move_mop_sim, transformed_move_mop_sim_ref, transformed_move_mop_sim_mut)]
TransformedMove(TransformedMoveOp),
#[create_dyn_unit_fn = |config, unit_index| todo!()]
#[extract = load_store_mop]
LoadStore(LoadStoreMOp<DestReg, SrcRegWidth>),
#[extract(load_store_mop, load_store_mop_sim, load_store_mop_sim_ref, load_store_mop_sim_mut)]
LoadStore(LoadStoreMOp<DestReg, SrcReg>),
}
}
@ -277,9 +353,9 @@ pub struct UnitResultCompleted<ExtraOut> {
pub extra_out: ExtraOut,
}
#[hdl(cmp_eq)]
pub struct UnitOutputWrite<OutRegNumWidth: Size> {
pub which: UnitOutRegNum<OutRegNumWidth>,
#[hdl(cmp_eq, no_static)]
pub struct UnitOutputWrite<C: PhantomConstGet<CpuConfig>> {
pub which: UnitOutRegNum<C>,
pub value: PRegValue,
}
@ -300,21 +376,21 @@ impl<ExtraOut: Type> UnitResult<ExtraOut> {
}
}
#[hdl]
pub struct UnitOutput<OutRegNumWidth: Size, ExtraOut> {
pub which: UnitOutRegNum<OutRegNumWidth>,
#[hdl(no_static)]
pub struct UnitOutput<C: PhantomConstGet<CpuConfig>, ExtraOut> {
pub which: UnitOutRegNum<C>,
pub result: UnitResult<ExtraOut>,
}
impl<OutRegNumWidth: Size, ExtraOut: Type> UnitOutput<OutRegNumWidth, ExtraOut> {
impl<C: PhantomConstCpuConfig, ExtraOut: Type> UnitOutput<C, ExtraOut> {
pub fn extra_out_ty(self) -> ExtraOut {
self.result.extra_out_ty()
}
}
#[hdl(cmp_eq)]
pub struct UnitCancelInput<OutRegNumWidth: Size> {
pub which: UnitOutRegNum<OutRegNumWidth>,
#[hdl(cmp_eq, no_static)]
pub struct UnitCancelInput<C: PhantomConstGet<CpuConfig>> {
pub which: UnitOutRegNum<C>,
}
pub trait UnitTrait:
@ -332,7 +408,9 @@ pub trait UnitTrait:
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
mop: Expr<
RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
>,
) -> Expr<HdlOption<Self::MOp>>;
fn module(&self) -> Interned<Module<Self::Type>>;
@ -340,7 +418,7 @@ pub trait UnitTrait:
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>>;
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>>;
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
@ -390,7 +468,9 @@ impl UnitTrait for DynUnit {
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
mop: Expr<
RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
>,
) -> Expr<HdlOption<Self::MOp>> {
self.unit.extract_mop(mop)
}
@ -402,7 +482,7 @@ impl UnitTrait for DynUnit {
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
self.unit.unit_to_reg_alloc(this)
}
@ -445,7 +525,9 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
mop: Expr<
RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
>,
) -> Expr<HdlOption<Self::MOp>> {
Expr::from_enum(Expr::as_enum(self.0.extract_mop(mop)))
}
@ -457,7 +539,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
Expr::from_bundle(Expr::as_bundle(
self.0.unit_to_reg_alloc(Expr::from_bundle(this)),
))

View file

@ -5,8 +5,8 @@ use crate::{
config::CpuConfig,
instruction::{
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOpDefaultImm,
CompareMOp, LogicalFlagsMOp, LogicalMOp, MOpTrait, OutputIntegerMode, ReadSpecialMOp,
RenamedMOp, ShiftRotateMOp, UnitOutRegNum,
CompareMOp, LogicalFlagsMOp, LogicalMOp, MOpTrait, OutputIntegerMode, PRegNum,
ReadSpecialMOp, RenamedMOp, ShiftRotateMOp, UnitOutRegNum,
},
register::{
FlagsMode, PRegFlagsPowerISA, PRegFlagsPowerISAView, PRegFlagsViewTrait, PRegFlagsX86,
@ -19,16 +19,19 @@ use crate::{
},
};
use fayalite::{
intern::{Intern, Interned},
module::wire_with_loc,
prelude::*,
util::ready_valid::ReadyValid,
intern::Interned, module::wire_with_loc, prelude::*, util::ready_valid::ReadyValid,
};
use std::{collections::HashMap, ops::RangeTo};
#[hdl]
fn add_sub<SrcCount: KnownSize>(
mop: Expr<AddSubMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
mop: Expr<
AddSubMOp<
UnitOutRegNum<PhantomConst<CpuConfig>>,
PRegNum<PhantomConst<CpuConfig>>,
SrcCount,
>,
>,
pc: Expr<UInt<64>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
@ -245,7 +248,9 @@ fn add_sub<SrcCount: KnownSize>(
#[hdl]
fn logical_flags(
mop: Expr<LogicalFlagsMOp<UnitOutRegNum<DynSize>, DynSize>>,
mop: Expr<
LogicalFlagsMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -259,7 +264,13 @@ fn logical_flags(
#[hdl]
fn logical(
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<2>>>,
mop: Expr<
LogicalMOp<
UnitOutRegNum<PhantomConst<CpuConfig>>,
PRegNum<PhantomConst<CpuConfig>>,
ConstUsize<2>,
>,
>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -273,7 +284,13 @@ fn logical(
#[hdl]
fn logical_i(
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<1>>>,
mop: Expr<
LogicalMOp<
UnitOutRegNum<PhantomConst<CpuConfig>>,
PRegNum<PhantomConst<CpuConfig>>,
ConstUsize<1>,
>,
>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -287,7 +304,9 @@ fn logical_i(
#[hdl]
fn shift_rotate(
mop: Expr<ShiftRotateMOp<UnitOutRegNum<DynSize>, DynSize>>,
mop: Expr<
ShiftRotateMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -301,7 +320,13 @@ fn shift_rotate(
#[hdl]
fn compare<SrcCount: KnownSize>(
mop: Expr<CompareMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
mop: Expr<
CompareMOp<
UnitOutRegNum<PhantomConst<CpuConfig>>,
PRegNum<PhantomConst<CpuConfig>>,
SrcCount,
>,
>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -315,7 +340,13 @@ fn compare<SrcCount: KnownSize>(
#[hdl]
fn branch<SrcCount: KnownSize>(
mop: Expr<BranchMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
mop: Expr<
BranchMOp<
UnitOutRegNum<PhantomConst<CpuConfig>>,
PRegNum<PhantomConst<CpuConfig>>,
SrcCount,
>,
>,
pc: Expr<UInt<64>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
@ -330,7 +361,9 @@ fn branch<SrcCount: KnownSize>(
#[hdl]
fn read_special(
mop: Expr<ReadSpecialMOp<UnitOutRegNum<DynSize>, DynSize>>,
mop: Expr<
ReadSpecialMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
>,
pc: Expr<UInt<64>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
@ -344,20 +377,15 @@ fn read_special(
}
#[hdl_module]
pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
#[hdl]
let cd: ClockDomain = m.input();
#[hdl]
let unit_to_reg_alloc: UnitToRegAlloc<
AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>,
PhantomConst<CpuConfig>,
AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
(),
DynSize,
DynSize,
DynSize,
> = m.output(config.unit_to_reg_alloc(
AluBranchMOp[config.unit_out_reg_num()][config.p_reg_num_width()],
(),
));
> = m.output(UnitToRegAlloc[config][AluBranchMOp[UnitOutRegNum[config]][PRegNum[config]]][()]);
#[hdl]
let global_state: GlobalState = m.input();
@ -375,10 +403,11 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
#[hdl]
if let HdlSome(execute_start) = ReadyValid::firing_data(unit_base.execute_start) {
#[hdl]
let ExecuteStart::<_> {
let ExecuteStart::<_, _> {
mop,
pc,
src_values,
config: _,
} = execute_start;
#[hdl]
match mop {
@ -580,14 +609,14 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AluBranch {
config: Interned<CpuConfig>,
config: PhantomConst<CpuConfig>,
module: Interned<Module<alu_branch>>,
}
impl AluBranch {
pub fn new(config: &CpuConfig, unit_index: usize) -> Self {
pub fn new(config: PhantomConst<CpuConfig>, unit_index: usize) -> Self {
Self {
config: config.intern(),
config,
module: alu_branch(config, unit_index),
}
}
@ -596,7 +625,8 @@ impl AluBranch {
impl UnitTrait for AluBranch {
type Type = alu_branch;
type ExtraOut = ();
type MOp = AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>;
type MOp =
AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>;
fn ty(&self) -> Self::Type {
self.module.io_ty()
@ -616,7 +646,9 @@ impl UnitTrait for AluBranch {
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
mop: Expr<
RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, PRegNum<PhantomConst<CpuConfig>>>,
>,
) -> Expr<HdlOption<Self::MOp>> {
UnitMOp::alu_branch_mop(mop)
}
@ -628,7 +660,7 @@ impl UnitTrait for AluBranch {
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
this.unit_to_reg_alloc
}

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information
use crate::{
config::CpuConfig,
config::{CpuConfig, CpuConfigUnitCount, PhantomConstCpuConfig},
instruction::{COMMON_MOP_SRC_LEN, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
register::PRegValue,
unit::{UnitCancelInput, UnitOutput, UnitOutputWrite},
@ -15,13 +15,11 @@ use fayalite::{
ty::StaticType,
util::ready_valid::ReadyValid,
};
use std::marker::PhantomData;
#[hdl]
pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>,
pub _phantom: PhantomData<UnitNumWidth>,
#[hdl(no_static)]
pub struct UnitForwardingInfo<C: PhantomConstGet<CpuConfig>> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<C>>, CpuConfigUnitCount<C>>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<C>>, CpuConfigUnitCount<C>>,
}
#[hdl]
@ -30,26 +28,18 @@ pub struct UnitInput<MOp: Type> {
pub pc: UInt<64>,
}
#[hdl]
pub struct UnitToRegAlloc<
MOp: Type,
ExtraOut: Type,
UnitNumWidth: Size,
OutRegNumWidth: Size,
UnitCount: Size,
> {
#[hdl(no_static)]
pub struct UnitToRegAlloc<C: PhantomConstGet<CpuConfig>, MOp: Type, ExtraOut: Type> {
#[hdl(flip)]
pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>,
pub unit_forwarding_info: UnitForwardingInfo<C>,
#[hdl(flip)]
pub input: ReadyValid<UnitInput<MOp>>,
#[hdl(flip)]
pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>,
pub output: HdlOption<UnitOutput<OutRegNumWidth, ExtraOut>>,
pub cancel_input: HdlOption<UnitCancelInput<C>>,
pub output: HdlOption<UnitOutput<C, ExtraOut>>,
}
impl<MOp: Type, ExtraOut: Type, UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size>
UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount>
{
impl<C: PhantomConstCpuConfig, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp, ExtraOut> {
pub fn mop_ty(self) -> MOp {
self.input.data.HdlSome.mop
}
@ -58,16 +48,20 @@ impl<MOp: Type, ExtraOut: Type, UnitNumWidth: Size, OutRegNumWidth: Size, UnitCo
}
}
#[hdl]
pub struct ExecuteStart<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>> {
#[hdl(no_static)]
pub struct ExecuteStart<
C: PhantomConstGet<CpuConfig>,
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<C>>,
> {
pub mop: MOp,
pub pc: UInt<64>,
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
pub config: C,
}
#[hdl]
pub struct ExecuteEnd<OutRegNumWidth: Size, ExtraOut> {
pub unit_output: UnitOutput<OutRegNumWidth, ExtraOut>,
#[hdl(no_static)]
pub struct ExecuteEnd<C: PhantomConstGet<CpuConfig>, ExtraOut> {
pub unit_output: UnitOutput<C, ExtraOut>,
}
#[hdl]
@ -240,10 +234,14 @@ impl InFlightOpsSummary<DynSize> {
#[hdl_module]
pub fn unit_base<
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
MOp: Type
+ MOpTrait<
DestReg = UnitOutRegNum<PhantomConst<CpuConfig>>,
SrcReg = PRegNum<PhantomConst<CpuConfig>>,
>,
ExtraOut: Type,
>(
config: &CpuConfig,
config: PhantomConst<CpuConfig>,
unit_index: usize,
mop_ty: MOp,
extra_out_ty: ExtraOut,
@ -251,17 +249,18 @@ pub fn unit_base<
#[hdl]
let cd: ClockDomain = m.input();
#[hdl]
let unit_to_reg_alloc: UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> =
m.output(config.unit_to_reg_alloc(mop_ty, extra_out_ty));
let unit_to_reg_alloc: UnitToRegAlloc<PhantomConst<CpuConfig>, MOp, ExtraOut> =
m.output(UnitToRegAlloc[config][mop_ty][extra_out_ty]);
#[hdl]
let execute_start: ReadyValid<ExecuteStart<MOp>> = m.output(ReadyValid[ExecuteStart[mop_ty]]);
let execute_start: ReadyValid<ExecuteStart<PhantomConst<CpuConfig>, MOp>> =
m.output(ReadyValid[ExecuteStart[config][mop_ty]]);
#[hdl]
let execute_end: HdlOption<ExecuteEnd<DynSize, ExtraOut>> =
m.input(HdlOption[ExecuteEnd[config.out_reg_num_width][extra_out_ty]]);
let execute_end: HdlOption<ExecuteEnd<PhantomConst<CpuConfig>, ExtraOut>> =
m.input(HdlOption[ExecuteEnd[config][extra_out_ty]]);
connect(execute_start.data, execute_start.ty().data.HdlNone());
let max_in_flight = config.unit_max_in_flight(unit_index).get();
let max_in_flight = config.get().unit_max_in_flight(unit_index).get();
let in_flight_op_ty = InFlightOp[mop_ty];
#[hdl]
let in_flight_ops = reg_builder()
@ -279,16 +278,15 @@ pub fn unit_base<
);
#[hdl]
let UnitForwardingInfo::<_, _, _> {
let UnitForwardingInfo::<_> {
unit_output_writes,
unit_reg_frees,
_phantom: _,
} = unit_to_reg_alloc.unit_forwarding_info;
#[hdl]
let read_src_regs = wire(mop_ty.src_regs_ty());
connect(
read_src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
repeat(PRegNum[config].const_zero(), ConstUsize),
);
#[hdl]
let read_src_values = wire();
@ -297,7 +295,7 @@ pub fn unit_base<
let input_src_regs = wire(mop_ty.src_regs_ty());
connect(
input_src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
repeat(PRegNum[config].const_zero(), ConstUsize),
);
#[hdl]
let input_src_regs_valid = wire();
@ -309,7 +307,7 @@ pub fn unit_base<
Bool,
SourceLocation::caller(),
);
mem.depth(1 << config.out_reg_num_width);
mem.depth(1 << config.get().out_reg_num_width);
mem
})
.collect();
@ -319,11 +317,11 @@ pub fn unit_base<
PRegValue,
SourceLocation::caller(),
);
unit_output_regs.depth(1 << config.out_reg_num_width);
unit_output_regs.depth(1 << config.get().out_reg_num_width);
for src_index in 0..COMMON_MOP_SRC_LEN {
let read_port = unit_output_regs.new_read_port();
let p_reg_num = read_src_regs[src_index].cast_bits_to(config.p_reg_num());
let p_reg_num = read_src_regs[src_index];
connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
connect(read_port.en, false);
connect(read_port.clk, cd.clk);
@ -336,7 +334,7 @@ pub fn unit_base<
for src_index in 0..COMMON_MOP_SRC_LEN {
let read_port = unit_output_regs_valid[unit_index].new_read_port();
let p_reg_num = input_src_regs[src_index].cast_bits_to(config.p_reg_num());
let p_reg_num = input_src_regs[src_index];
connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
connect(read_port.en, false);
connect(read_port.clk, cd.clk);
@ -367,13 +365,13 @@ pub fn unit_base<
connect_any(ready_write_port.addr, unit_output_write.which.value);
connect(ready_write_port.en, true);
let p_reg_num = #[hdl]
PRegNum::<_, _> {
unit_num: config.unit_num().from_index(unit_index),
PRegNum::<_> {
unit_num: UnitNum[config].from_index(unit_index),
unit_out_reg: unit_output_write.which,
};
for src_index in 0..COMMON_MOP_SRC_LEN {
#[hdl]
if input_src_regs[src_index].cmp_eq(p_reg_num.cast_to_bits()) {
if input_src_regs[src_index].cmp_eq(p_reg_num) {
connect(input_src_regs_valid[src_index], true);
}
}
@ -399,10 +397,11 @@ pub fn unit_base<
execute_start.data,
HdlSome(
#[hdl]
ExecuteStart::<_> {
ExecuteStart::<_, _> {
mop: in_flight_op.mop,
pc: in_flight_op.pc,
src_values: read_src_values,
config,
},
),
);
@ -425,7 +424,7 @@ pub fn unit_base<
let input_mop_src_regs = wire(mop_ty.src_regs_ty());
connect(
input_mop_src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
repeat(PRegNum[config].const_zero(), ConstUsize),
);
MOp::connect_src_regs(mop, input_mop_src_regs);
let src_ready_flags = wire_with_loc(
@ -495,10 +494,7 @@ pub fn unit_base<
SourceLocation::caller(),
mop_ty.src_regs_ty(),
);
connect(
src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
);
connect(src_regs, repeat(PRegNum[config].const_zero(), ConstUsize));
MOp::connect_src_regs(mop, src_regs);
#[hdl]
@ -521,13 +517,13 @@ pub fn unit_base<
value: _,
} = unit_output_write;
let p_reg_num = #[hdl]
PRegNum::<_, _> {
unit_num: config.unit_num().from_index(unit_index),
PRegNum::<_> {
unit_num: UnitNum[config].from_index(unit_index),
unit_out_reg,
};
for src_index in 0..COMMON_MOP_SRC_LEN {
#[hdl]
if p_reg_num.cast_to_bits().cmp_eq(src_regs[src_index]) {
if p_reg_num.cmp_eq(src_regs[src_index]) {
connect(
in_flight_op_next_src_ready_flags[in_flight_op_index][src_index],
true,

View file

@ -280,3 +280,33 @@ impl<T: Type, N: Size> Rotate<usize> for SimValue<ArrayType<T, N>> {
retval
}
}
#[hdl]
pub struct LFSR31 {
// MSB is always zero, 32 bits makes it easier to manipulate
state: UInt<32>,
}
impl LFSR31 {
#[hdl]
pub fn new() -> SimValue<Self> {
#[hdl(sim)]
Self { state: 1u32 }
}
}
impl LFSR31 {
pub fn next_sim(this: &mut SimValue<Self>) -> u32 {
let state = this.state.as_int();
let state = if state == 0 {
1u32
} else {
// a maximal-length 31-bit LFSR
let lsb = ((state >> 30) ^ (state >> 27)) & 1;
let msb = (state << 1) & ((1 << 31) - 1);
lsb | msb
};
*this.state = state.into();
state
}
}

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

File diff suppressed because it is too large Load diff

View file

@ -1163,13 +1163,7 @@ impl MockExecuteState {
id: &insn.id,
next_pc,
call_stack_op: mock_insn.call_stack_op(pc),
cond_br_taken: if let Some(cond_br_taken) = cond_br_taken {
#[hdl(sim)]
HdlSome(cond_br_taken)
} else {
#[hdl(sim)]
HdlNone()
},
cond_br_taken,
config: self.config,
},
)

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
#![cfg(todo)]
use cpu::{
config::{CpuConfig, UnitConfig},

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -152,16 +152,7 @@ fn test_decode_insn() {
} in test_cases::test_cases()
{
sim.write(sim.io().first_input, first_input);
sim.write(
sim.io().second_input,
if let Some(v) = second_input {
#[hdl(sim)]
HdlSome(v)
} else {
#[hdl(sim)]
HdlNone()
},
);
sim.write(sim.io().second_input, second_input);
sim.advance_time(SimDuration::from_micros(1));
let second_input_used = sim.read_bool(sim.io().second_input_used);
let is_illegal = sim.read_bool(sim.io().is_illegal);

View file

@ -15,7 +15,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_i(
MOpDestReg::new_sim(&[], &[]),
MOpRegNum::const_zero().value,
[MOpRegNum::const_zero(); 2],
0x345678.cast_to_static::<SInt<_>>(),
true,
false,
@ -28,7 +28,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_i(
MOpDestReg::new_sim(&[], &[]),
MOpRegNum::const_zero().value,
[MOpRegNum::const_zero(); 2],
0x345678.cast_to_static::<SInt<_>>(),
false,
false,
@ -41,7 +41,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
MOpRegNum::const_zero().value,
[MOpRegNum::const_zero(); 2],
0x345678.cast_to_static::<SInt<_>>(),
true,
true,
@ -54,7 +54,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
MOpRegNum::const_zero().value,
[MOpRegNum::const_zero(); 2],
0x345678.cast_to_static::<SInt<_>>(),
false,
true,
@ -74,10 +74,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
[
AddSubMOp::add_sub_i::<MOp>(
MOpDestReg::new([MOpRegNum::power_isa_ctr_reg()], []),
[
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::const_zero().value,
],
[MOpRegNum::power_isa_ctr_reg(), MOpRegNum::const_zero()],
(-1).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -143,9 +140,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
@ -163,9 +160,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
@ -183,9 +180,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
@ -203,9 +200,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
@ -223,9 +220,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(2).value,
MOpRegNum::power_isa_cr_reg_imm(2),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
@ -243,9 +240,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
@ -264,9 +261,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
@ -285,9 +282,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
false,
@ -305,9 +302,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::power_isa_ctr_reg().value,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
false,
@ -326,9 +323,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
BranchMOp::branch_cond_ctr(
$dest,
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
$src1,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero(),
],
$imm.cast_to_static::<SInt<_>>(),
false,
@ -346,8 +343,11 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_ctr(
$dest,
$src1,
MOpRegNum::power_isa_ctr_reg().value,
[
MOpRegNum::const_zero(),
$src1,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
true,
$pc_relative,
@ -361,8 +361,11 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_ctr(
$dest,
$src1,
MOpRegNum::power_isa_ctr_reg().value,
[
MOpRegNum::const_zero(),
$src1,
MOpRegNum::power_isa_ctr_reg(),
],
$imm.cast_to_static::<SInt<_>>(),
false,
$pc_relative,
@ -377,7 +380,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_i(
$dest,
$src1,
[MOpRegNum::const_zero(), $src1],
$imm.cast_to_static::<SInt<_>>(),
$pc_relative,
$lk,
@ -392,7 +395,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
asm_last_arg = "0x1234";
imm = 0x1234;
encoding = 0x40001234;
src1 = MOpRegNum::const_zero().value;
src1 = MOpRegNum::const_zero();
pc_relative = true;
is_ret = false;
}
@ -402,7 +405,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
asm_last_arg = "0x1234";
imm = 0x1234;
encoding = 0x40001236;
src1 = MOpRegNum::const_zero().value;
src1 = MOpRegNum::const_zero();
pc_relative = false;
is_ret = false;
}
@ -412,7 +415,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
asm_last_arg = "0";
imm = 0;
encoding = 0x4c000020;
src1 = MOpRegNum::power_isa_lr_reg().value;
src1 = MOpRegNum::power_isa_lr_reg();
pc_relative = false;
is_ret = true;
}
@ -422,7 +425,7 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
asm_last_arg = "0";
imm = 0;
encoding = 0x4c000420;
src1 = MOpRegNum::power_isa_ctr_reg().value;
src1 = MOpRegNum::power_isa_ctr_reg();
pc_relative = false;
is_ret = false;
}
@ -434,8 +437,11 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
None,
BranchMOp::branch_ctr(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
MOpRegNum::power_isa_tar_reg().value,
MOpRegNum::power_isa_ctr_reg().value,
[
MOpRegNum::const_zero(),
MOpRegNum::power_isa_tar_reg(),
MOpRegNum::power_isa_ctr_reg(),
],
0.cast_to_static::<SInt<_>>(),
false,
false,

View file

@ -23,9 +23,9 @@ pub fn test_cases_book_i_2_5_condition_register(retval: &mut Vec<TestCase>) {
LogicalFlagsMOp::logical_flags(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_cr_reg_imm(1).value,
MOpRegNum::power_isa_cr_reg_imm(5).value,
MOpRegNum::power_isa_cr_reg_imm(3).value,
MOpRegNum::power_isa_cr_reg_imm(1),
MOpRegNum::power_isa_cr_reg_imm(5),
MOpRegNum::power_isa_cr_reg_imm(3),
],
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| {
let mut dest = src2.map(|v| Some(v.into()));
@ -42,9 +42,9 @@ pub fn test_cases_book_i_2_5_condition_register(retval: &mut Vec<TestCase>) {
LogicalFlagsMOp::logical_flags(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]),
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_cr_reg_imm(0),
],
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| {
let mut dest = src2.map(|v| Some(v.into()));
@ -61,9 +61,9 @@ pub fn test_cases_book_i_2_5_condition_register(retval: &mut Vec<TestCase>) {
LogicalFlagsMOp::logical_flags(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]),
[
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0).value,
MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_cr_reg_imm(0),
],
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| {
let mut dest = src2.map(|v| Some(v.into()));
@ -91,7 +91,7 @@ pub fn test_cases_book_i_2_5_condition_register(retval: &mut Vec<TestCase>) {
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num($dest)], &[]),
[MOpRegNum::power_isa_cr_reg_imm($src).value],
[MOpRegNum::power_isa_cr_reg_imm($src)],
0i8.cast_to_static::<SInt<_>>(),
),
));

View file

@ -13,10 +13,7 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
None,
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::const_zero().value,
],
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
0x1234.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -31,10 +28,7 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
Some(0x38646789),
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::const_zero().value,
],
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
0x123456789i64.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -49,7 +43,7 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
Some(0x38606789),
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero().value, MOpRegNum::const_zero().value],
[MOpRegNum::const_zero(), MOpRegNum::const_zero()],
0x123456789i64.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -64,10 +58,7 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
None,
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::const_zero().value,
],
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
0x12340000.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -82,7 +73,7 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
None,
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero().value; _],
[MOpRegNum::const_zero(); _],
0x12340004.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -101,9 +92,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
MOpRegNum::const_zero(),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -125,10 +116,7 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::const_zero().value,
],
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
0x1234.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
@ -147,9 +135,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
MOpRegNum::const_zero(),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -171,10 +159,7 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
],
&[],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::const_zero().value,
],
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
0x1234.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
true,
@ -196,9 +181,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
MOpRegNum::const_zero(),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -221,9 +206,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
MOpRegNum::const_zero(),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -246,9 +231,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -271,9 +256,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -296,9 +281,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::const_zero(),
],
(-1i8).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -321,9 +306,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::const_zero(),
],
(-1i8).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -346,9 +331,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::const_zero(),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -371,9 +356,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::const_zero(),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -393,9 +378,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information
use crate::test_cases::{TestCase, insn_single};
use cpu::instruction::{CompareMOp, CompareMode, MOpDestReg, MOpRegNum, OutputIntegerMode};
use cpu::instruction::{CompareMOp, CompareMode, MOpDestReg, MOpRegNum};
use fayalite::prelude::*;
/// covers instructions in PowerISA v3.1C Book I 3.3.10 Fixed-Point Compare Instructions
@ -13,9 +13,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
None,
CompareMOp::compare_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
[MOpRegNum::power_isa_gpr_reg_imm(4)],
0x1234.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S32(),
),
));
@ -25,9 +24,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
None,
CompareMOp::compare_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
[MOpRegNum::power_isa_gpr_reg_imm(4)],
(0x89abu16 as i16).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S64(),
),
));
@ -38,11 +36,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S32(),
),
));
@ -53,11 +49,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S64(),
),
));
@ -67,9 +61,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
None,
CompareMOp::compare_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
[MOpRegNum::power_isa_gpr_reg_imm(4)],
0x1234.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U32(),
),
));
@ -79,9 +72,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
None,
CompareMOp::compare_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
[MOpRegNum::power_isa_gpr_reg_imm(4)],
0x89ab.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U64(),
),
));
@ -92,11 +84,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U32(),
),
));
@ -107,11 +97,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U64(),
),
));
@ -122,11 +110,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.CmpRBOne(),
),
));
@ -137,11 +123,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.CmpRBTwo(),
),
));
@ -152,11 +136,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
MOpRegNum::power_isa_gpr_reg_imm(4),
MOpRegNum::power_isa_gpr_reg_imm(5),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.CmpEqB(),
),
));

View file

@ -26,11 +26,11 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
if $r != 0 || $ra == 0 {
MOpRegNum::const_zero().value
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra).value
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::const_zero().value,
MOpRegNum::const_zero(),
],
($disp as i64).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -41,7 +41,7 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
),
LoadMOp::load(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[MOpRegNum::power_isa_temp_reg().value],
[MOpRegNum::power_isa_temp_reg()],
LoadStoreWidth.$width(),
LoadStoreConversion.$conversion(),
),
@ -65,11 +65,11 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
if $ra == 0 {
MOpRegNum::const_zero().value
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra).value
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::const_zero().value,
MOpRegNum::const_zero(),
],
($disp as i64).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -80,7 +80,7 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
),
LoadMOp::load(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[MOpRegNum::power_isa_temp_reg().value],
[MOpRegNum::power_isa_temp_reg()],
LoadStoreWidth.$width(),
LoadStoreConversion.$conversion(),
),
@ -103,8 +103,8 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::const_zero(),
],
($disp as i64).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -115,7 +115,7 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
),
LoadMOp::load(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm($ra).value],
[MOpRegNum::power_isa_gpr_reg_imm($ra)],
LoadStoreWidth.$width(),
LoadStoreConversion.$conversion(),
),
@ -139,11 +139,11 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
if $ra == 0 {
MOpRegNum::const_zero().value
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra).value
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::power_isa_gpr_reg_imm($rb).value,
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -154,7 +154,7 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
),
LoadMOp::load(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[MOpRegNum::power_isa_temp_reg().value],
[MOpRegNum::power_isa_temp_reg()],
LoadStoreWidth.$width(),
LoadStoreConversion.$conversion(),
),
@ -177,8 +177,8 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra).value,
MOpRegNum::power_isa_gpr_reg_imm($rb).value,
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -189,7 +189,7 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
),
LoadMOp::load(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm($ra).value],
[MOpRegNum::power_isa_gpr_reg_imm($ra)],
LoadStoreWidth.$width(),
LoadStoreConversion.$conversion(),
),

View file

@ -34,7 +34,7 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
&[]
},
),
[MOpRegNum::power_isa_gpr_reg_imm($src).value],
[MOpRegNum::power_isa_gpr_reg_imm($src)],
(($imm as u32) << if $mnemonic.contains('s') { 16 } else { 0 })
.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -108,8 +108,8 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
},
),
[
MOpRegNum::power_isa_gpr_reg_imm($src0).value,
MOpRegNum::power_isa_gpr_reg_imm($src1).value,
MOpRegNum::power_isa_gpr_reg_imm($src0),
MOpRegNum::power_isa_gpr_reg_imm($src1),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -159,7 +159,7 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
[MOpRegNum::power_isa_gpr_reg_imm(4)],
0.cast_to_static::<SInt<_>>(),
),
));
@ -232,7 +232,7 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
&[]
},
),
[MOpRegNum::power_isa_gpr_reg_imm($src).value],
[MOpRegNum::power_isa_gpr_reg_imm($src)],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.$OutputIntegerMode(),
Lut4::from_fn(|a, b| a | b),

View file

@ -3,8 +3,8 @@
use crate::test_cases::{TestCase, insn_single};
use cpu::instruction::{
MOpDestReg, MOpRegNum, OutputIntegerMode, ShiftRotateDestLogicOp, ShiftRotateMOp,
ShiftRotateMOpImm, ShiftRotateMode,
MOpDestReg, MOpRegNum, OutputIntegerMode, ShiftAmountOverflowBehavior, ShiftRotateDestLogicOp,
ShiftRotateMOp, ShiftRotateMOpImm, ShiftRotateMode,
};
use fayalite::prelude::*;
@ -18,6 +18,11 @@ fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
HdlNone()
},
shift_rotate_right: shift_right,
shift_amount_overflow_behavior: if amount.is_some() {
ShiftAmountOverflowBehavior.WrapToWidth()
} else {
ShiftAmountOverflowBehavior.WrapToTwiceWidth()
},
dest_logic_op: HdlNone(),
}
}
@ -30,14 +35,9 @@ fn rotate_imm(
) -> SimValue<ShiftRotateMOpImm> {
#[hdl(sim)]
ShiftRotateMOpImm {
shift_rotate_amount: if let Some(amount) = amount {
#[hdl(sim)]
HdlSome(amount.cast_to_static::<UInt<_>>())
} else {
#[hdl(sim)]
HdlNone()
},
shift_rotate_amount: amount.map(|amount| amount.cast_to_static::<UInt<_>>()),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
dest_logic_op: if let Some((rotated_output_start, rotated_output_len)) =
rotated_output_start_and_len
{
@ -101,9 +101,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
src2.value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($src),
src2,
],
&imm,
OutputIntegerMode.Full64(),
@ -127,9 +127,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
src2.value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($src),
src2,
],
imm,
OutputIntegerMode.Full64(),
@ -162,9 +162,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
rotate_imm(None, $rotated_output_start_and_len, false),
OutputIntegerMode.Full64(),
@ -188,9 +188,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
rotate_imm(None, $rotated_output_start_and_len, false),
OutputIntegerMode.Full64(),
@ -745,9 +745,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, false),
OutputIntegerMode.Full64(),
@ -772,9 +772,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, false),
OutputIntegerMode.Full64(),
@ -804,9 +804,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
OutputIntegerMode.Full64(),
@ -831,9 +831,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
OutputIntegerMode.Full64(),
@ -869,9 +869,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
&[],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
OutputIntegerMode.Full64(),
@ -899,9 +899,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
OutputIntegerMode.Full64(),
@ -937,9 +937,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
&[],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), true),
OutputIntegerMode.Full64(),
@ -967,9 +967,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), true),
OutputIntegerMode.Full64(),
@ -1078,9 +1078,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), false),
OutputIntegerMode.Full64(),
@ -1105,9 +1105,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), false),
OutputIntegerMode.Full64(),

View file

@ -25,11 +25,11 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
if $r != 0 || $ra == 0 {
MOpRegNum::const_zero().value
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra).value
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::const_zero().value,
MOpRegNum::const_zero(),
],
($disp as i64).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -41,8 +41,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg().value,
MOpRegNum::power_isa_gpr_reg_imm($rs).value,
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
@ -66,11 +66,11 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
if $ra == 0 {
MOpRegNum::const_zero().value
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra).value
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::const_zero().value,
MOpRegNum::const_zero(),
],
($disp as i64).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -82,8 +82,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg().value,
MOpRegNum::power_isa_gpr_reg_imm($rs).value,
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
@ -107,8 +107,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::const_zero(),
],
($disp as i64).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -120,15 +120,15 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg().value,
MOpRegNum::power_isa_gpr_reg_imm($rs).value,
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
),
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[MOpRegNum::power_isa_temp_reg().value],
[MOpRegNum::power_isa_temp_reg()],
0.cast_to_static::<SInt<_>>(),
),
],
@ -142,8 +142,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra).value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::const_zero(),
],
($disp as i64).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -155,8 +155,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra).value,
MOpRegNum::power_isa_gpr_reg_imm($rs).value,
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
@ -181,11 +181,11 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
if $ra == 0 {
MOpRegNum::const_zero().value
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra).value
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::power_isa_gpr_reg_imm($rb).value,
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -197,8 +197,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg().value,
MOpRegNum::power_isa_gpr_reg_imm($rs).value,
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
@ -222,8 +222,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra).value,
MOpRegNum::power_isa_gpr_reg_imm($rb).value,
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -235,15 +235,15 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg().value,
MOpRegNum::power_isa_gpr_reg_imm($rs).value,
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
),
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[MOpRegNum::power_isa_temp_reg().value],
[MOpRegNum::power_isa_temp_reg()],
0.cast_to_static::<SInt<_>>(),
),
],
@ -258,11 +258,11 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[
if $ra == 0 {
MOpRegNum::const_zero().value
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra).value
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::power_isa_gpr_reg_imm($rb).value,
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
@ -274,8 +274,8 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra).value,
MOpRegNum::power_isa_gpr_reg_imm($rs).value,
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),

View file

@ -30,9 +30,9 @@ pub fn test_cases_book_i_3_3_19_move_to_from_system_register(retval: &mut Vec<Te
LogicalFlagsMOp::logical_flags(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[
MOpRegNum::power_isa_xer_ca_ca32_reg().value,
MOpRegNum::const_zero().value,
MOpRegNum::power_isa_xer_so_ov_ov32_reg().value,
MOpRegNum::power_isa_xer_ca_ca32_reg(),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_xer_so_ov_ov32_reg(),
],
mcrxrx_imm(),
Lut4::from_fn(|a, b| a | b),
@ -48,7 +48,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_lr_reg().value],
[MOpRegNum::power_isa_lr_reg()],
0.cast_to_static::<SInt<_>>(),
),
));
@ -58,7 +58,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(3).value],
[MOpRegNum::power_isa_gpr_reg_imm(3)],
0.cast_to_static::<SInt<_>>(),
),
));
@ -68,7 +68,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_ctr_reg().value],
[MOpRegNum::power_isa_ctr_reg()],
0.cast_to_static::<SInt<_>>(),
),
));
@ -78,7 +78,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_CTR_REG_NUM], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(3).value],
[MOpRegNum::power_isa_gpr_reg_imm(3)],
0.cast_to_static::<SInt<_>>(),
),
));
@ -88,7 +88,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_tar_reg().value],
[MOpRegNum::power_isa_tar_reg()],
0.cast_to_static::<SInt<_>>(),
),
));
@ -98,7 +98,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TAR_REG_NUM], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(3).value],
[MOpRegNum::power_isa_gpr_reg_imm(3)],
0.cast_to_static::<SInt<_>>(),
),
));
@ -109,7 +109,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
ReadSpecialMOp::read_special(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero().value; 0],
[MOpRegNum::const_zero(); 0],
ReadSpecialMOpImm.PowerIsaTimeBase(),
),
));
@ -120,7 +120,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
ReadSpecialMOp::read_special(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero().value; 0],
[MOpRegNum::const_zero(); 0],
ReadSpecialMOpImm.PowerIsaTimeBaseU(),
),
));
@ -131,7 +131,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
ReadSpecialMOp::read_special(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero().value; 0],
[MOpRegNum::const_zero(); 0],
ReadSpecialMOpImm.PowerIsaTimeBase(),
),
));
@ -142,7 +142,7 @@ pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<T
None,
ReadSpecialMOp::read_special(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero().value; 0],
[MOpRegNum::const_zero(); 0],
ReadSpecialMOpImm.PowerIsaTimeBaseU(),
),
));