fix & clean up MOp definitions and ensure_reg_fields_are_in_the_same_place

This commit is contained in:
Jacob Lifshay 2026-01-22 08:28:02 -08:00
parent 9b8d99e9af
commit e6f876f9af
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
3 changed files with 4561 additions and 5933 deletions

View file

@ -1919,7 +1919,7 @@ common_mop_struct! {
#[hdl(cmp_eq)] #[hdl(cmp_eq)]
pub struct ReadL2RegMOp<DestReg: Type, SrcRegWidth: Size> { pub struct ReadL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
#[common] #[common]
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<0>>, pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<0>>,
} }
} }
@ -1928,7 +1928,7 @@ common_mop_struct! {
#[hdl(cmp_eq)] #[hdl(cmp_eq)]
pub struct WriteL2RegMOp<DestReg: Type, SrcRegWidth: Size> { pub struct WriteL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
#[common] #[common]
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<1>>, pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<1>>,
} }
} }
@ -1946,7 +1946,7 @@ common_mop_struct! {
#[hdl(cmp_eq)] #[hdl(cmp_eq)]
pub struct LoadStoreCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> { pub struct LoadStoreCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
#[common] #[common]
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, SrcCount>, pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, SrcCount>,
} }
} }
@ -1972,8 +1972,8 @@ mop_enum! {
#[impl_mop_into = true] #[impl_mop_into = true]
#[hdl] #[hdl]
pub enum LoadStoreMOp<DestReg: Type, SrcRegWidth: Size> { pub enum LoadStoreMOp<DestReg: Type, SrcRegWidth: Size> {
Load(CommonMOp<ConstUsize<2>, DestReg, SrcRegWidth, ConstUsize<0>>), Load(LoadMOp<DestReg, SrcRegWidth>),
Store(CommonMOp<ConstUsize<2>, DestReg, SrcRegWidth, ConstUsize<1>>), Store(StoreMOp<DestReg, SrcRegWidth>),
} }
} }
@ -1982,7 +1982,7 @@ common_mop_struct! {
#[hdl(cmp_eq)] #[hdl(cmp_eq)]
pub struct MoveRegMOp<DestReg: Type, SrcRegWidth: Size> { pub struct MoveRegMOp<DestReg: Type, SrcRegWidth: Size> {
#[common] #[common]
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<1>>, pub common: CommonMOp<ConstUsize<4>, DestReg, SrcRegWidth, ConstUsize<1>>,
} }
} }
@ -2440,16 +2440,23 @@ mod tests {
#[test] #[test]
fn ensure_reg_fields_are_in_the_same_place() { fn ensure_reg_fields_are_in_the_same_place() {
struct Error {
dest_reg_offset: usize,
prefix_pad: usize,
path: Vec<&'static str>,
loc: SourceLocation,
variant: String,
}
struct Visitor { struct Visitor {
dest_reg_offset: Option<(usize, String)>, dest_reg_offset: Option<(usize, String)>,
max_dest_reg_offset: usize, max_dest_reg_offset: usize,
min_prefix_pad: usize, min_prefix_pad: usize,
errors: Option<String>, errors: Vec<Error>,
} }
impl MOpVariantVisitor<MOp> for Visitor { impl<T: MOpTrait> MOpVariantVisitor<T> for Visitor {
type Break = Infallible; type Break = Infallible;
fn visit_variant< fn visit_variant<
VisitOps: ?Sized + MOpVariantVisitOps<Target = MOp, MOp: CommonMOpTrait>, VisitOps: ?Sized + MOpVariantVisitOps<Target = T, MOp: CommonMOpTrait>,
>( >(
&mut self, &mut self,
visit_ops: &VisitOps, visit_ops: &VisitOps,
@ -2497,15 +2504,13 @@ mod tests {
self.max_dest_reg_offset = self.max_dest_reg_offset.max(dest_reg_offset); self.max_dest_reg_offset = self.max_dest_reg_offset.max(dest_reg_offset);
if let Some((first_dest_reg_offset, _)) = self.dest_reg_offset { if let Some((first_dest_reg_offset, _)) = self.dest_reg_offset {
if first_dest_reg_offset != dest_reg_offset { if first_dest_reg_offset != dest_reg_offset {
writeln!( self.errors.push(Error {
self.errors.get_or_insert_default(), dest_reg_offset,
"dest_reg_offset {dest_reg_offset} doesn't match first \ prefix_pad: <VisitOps::MOp as CommonMOpTrait>::PrefixPad::VALUE,
variant's dest_reg_offset {first_dest_reg_offset}\n\ path: VisitOps::path(),
variant's path: {:?}\n\ loc: VisitOps::MOp::source_location(),
variant: {variant:#?}\n", variant: format!("{variant:#?}"),
VisitOps::path(), });
)
.unwrap();
} }
} else { } else {
self.dest_reg_offset = Some(( self.dest_reg_offset = Some((
@ -2519,28 +2524,54 @@ mod tests {
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
} }
let mut visitor = Visitor { #[track_caller]
dest_reg_offset: None, fn check<T: MOpVisitVariants>(mop: T) {
max_dest_reg_offset: 0, let mut visitor = Visitor {
min_prefix_pad: usize::MAX, dest_reg_offset: None,
errors: None, max_dest_reg_offset: 0,
}; min_prefix_pad: usize::MAX,
let ControlFlow::Continue(()) = MOp::visit_variants(&mut visitor, &MOp); errors: Vec::new(),
let Visitor { };
dest_reg_offset: Some((_, first_variant)), let ControlFlow::Continue(()) = T::visit_variants(&mut visitor, &mop);
max_dest_reg_offset, let Visitor {
min_prefix_pad, dest_reg_offset: Some((_, first_variant)),
errors, max_dest_reg_offset,
} = visitor min_prefix_pad,
else { errors,
panic!("no variants"); } = visitor
}; else {
println!("max_dest_reg_offset: {max_dest_reg_offset}"); panic!("no variants");
println!("min_prefix_pad: {min_prefix_pad}"); };
println!("{first_variant}"); println!("max_dest_reg_offset: {max_dest_reg_offset}");
if let Some(errors) = errors { println!("min_prefix_pad: {min_prefix_pad}");
panic!("{errors}"); println!("{first_variant}");
if !errors.is_empty() {
let mut text = String::new();
for Error {
dest_reg_offset,
prefix_pad,
path,
loc,
variant,
} in errors
{
let expected_dest_reg_offset = max_dest_reg_offset - min_prefix_pad;
let fixed_prefix_pad = expected_dest_reg_offset + prefix_pad - dest_reg_offset;
writeln!(
text,
"at: {loc}\n\
dest_reg_offset {dest_reg_offset} doesn't match expected {expected_dest_reg_offset}\n\
change the prefix pad to: {fixed_prefix_pad}\n\
variant's path: {path:?}\n\
variant: {variant}\n",
)
.unwrap();
}
panic!("{text}");
}
assert_eq!(min_prefix_pad, 0);
} }
assert_eq!(min_prefix_pad, 0); check(MOp);
check(RenamedMOp[UInt[8]][8]);
} }
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff