mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-10 01:18:18 +02:00
kraid/isa: Handle field restrictions
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41841>
This commit is contained in:
parent
6f214056ce
commit
c64e968bf8
2 changed files with 87 additions and 9 deletions
|
|
@ -420,6 +420,7 @@ impl InstrEncSrc {
|
|||
struct InstrEncFieldSrc {
|
||||
ident: Ident,
|
||||
field_type: FieldType,
|
||||
field_restrict: Option<Rc<FieldRestrict>>,
|
||||
src_name: String,
|
||||
src_field: SrcField,
|
||||
}
|
||||
|
|
@ -428,6 +429,7 @@ impl InstrEncFieldSrc {
|
|||
fn new(
|
||||
field_name: &str,
|
||||
field_type: FieldType,
|
||||
field_restrict: Option<Rc<FieldRestrict>>,
|
||||
src_name: &str,
|
||||
src_field: SrcField,
|
||||
) -> InstrEncFieldSrc {
|
||||
|
|
@ -436,6 +438,7 @@ impl InstrEncFieldSrc {
|
|||
InstrEncFieldSrc {
|
||||
ident,
|
||||
field_type,
|
||||
field_restrict,
|
||||
src_name,
|
||||
src_field,
|
||||
}
|
||||
|
|
@ -459,6 +462,15 @@ impl InstrEncFieldSrc {
|
|||
});
|
||||
}
|
||||
|
||||
if let Some(restrict) = &self.field_restrict {
|
||||
let err = format!("Unsupported {f_ident} value");
|
||||
ts.extend(quote! {
|
||||
if !#restrict.contains(&#f_ident) {
|
||||
return Err(#err.into());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if matches!(&self.field_type, FieldType::Enum(_)) {
|
||||
ts.extend(quote! {
|
||||
let #f_ident = #f_ident.try_encode(arch)?;
|
||||
|
|
@ -509,6 +521,7 @@ impl InstrEncSources {
|
|||
instr_name: &str,
|
||||
field_name: &str,
|
||||
field_type: &FieldType,
|
||||
field_restrict: &Option<Rc<FieldRestrict>>,
|
||||
sr_control: SrControl,
|
||||
enums: &EnumSet,
|
||||
) -> Option<InstrEncFieldSrc> {
|
||||
|
|
@ -529,6 +542,7 @@ impl InstrEncSources {
|
|||
Some(InstrEncFieldSrc::new(
|
||||
field_name,
|
||||
field_type.clone(),
|
||||
field_restrict.clone(),
|
||||
&src.name,
|
||||
src_field,
|
||||
))
|
||||
|
|
@ -539,6 +553,7 @@ impl InstrEncSources {
|
|||
instr_name: &str,
|
||||
field_name: &str,
|
||||
field_type: &FieldType,
|
||||
field_restrict: &Option<Rc<FieldRestrict>>,
|
||||
sr_control: SrControl,
|
||||
enums: &EnumSet,
|
||||
) -> InstrEncFieldSrc {
|
||||
|
|
@ -557,6 +572,7 @@ impl InstrEncSources {
|
|||
return InstrEncFieldSrc::new(
|
||||
field_name,
|
||||
field_type.clone(),
|
||||
field_restrict.clone(),
|
||||
&src.name,
|
||||
src_field,
|
||||
);
|
||||
|
|
@ -574,6 +590,7 @@ impl InstrEncSources {
|
|||
InstrEncFieldSrc::new(
|
||||
field_name,
|
||||
field_type.clone(),
|
||||
field_restrict.clone(),
|
||||
&src.name,
|
||||
src_field,
|
||||
)
|
||||
|
|
@ -648,11 +665,11 @@ impl InstrEncVariant {
|
|||
continue;
|
||||
}
|
||||
|
||||
let (field_name, field_type) = match field {
|
||||
let (field_name, field_type, restrict) = match field {
|
||||
InstrField::Virtual(f) => {
|
||||
// Virtual fields are always sources since they're used to
|
||||
// calculate computed physical fields.
|
||||
(&f.name, &f.type_)
|
||||
(&f.name, &f.type_, &f.restrict)
|
||||
}
|
||||
InstrField::Physical(f) => {
|
||||
// Physical fields only show up as sources if we can't
|
||||
|
|
@ -660,27 +677,28 @@ impl InstrEncVariant {
|
|||
if f.expr.is_some() {
|
||||
continue;
|
||||
}
|
||||
(&f.name, f.type_.as_ref().unwrap())
|
||||
(&f.name, f.type_.as_ref().unwrap(), &f.restrict)
|
||||
}
|
||||
InstrField::Reserved(_) => continue,
|
||||
};
|
||||
|
||||
fields.push((i, field_name, field_type));
|
||||
fields.push((i, field_name, field_type, restrict));
|
||||
}
|
||||
|
||||
// Add the sources and destinations first
|
||||
for (i, field_name, field_type) in fields.iter().cloned() {
|
||||
for (i, field_name, field_type, restrict) in fields.iter().cloned() {
|
||||
field_srcs[i] = srcs.add_src_for_src_dst_field(
|
||||
&instr.name,
|
||||
field_name,
|
||||
&field_type,
|
||||
restrict,
|
||||
sr_control,
|
||||
enums,
|
||||
);
|
||||
}
|
||||
|
||||
// Add all the other sources
|
||||
for (i, field_name, field_type) in fields.iter().cloned() {
|
||||
for (i, field_name, field_type, restrict) in fields.iter().cloned() {
|
||||
if field_srcs[i].is_some() {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -689,6 +707,7 @@ impl InstrEncVariant {
|
|||
&instr.name,
|
||||
field_name,
|
||||
&field_type,
|
||||
restrict,
|
||||
sr_control,
|
||||
enums,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -63,10 +63,53 @@ impl FieldType {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct FieldRestrict {
|
||||
values: Vec<LiteralEnum>,
|
||||
}
|
||||
|
||||
impl FieldRestrict {
|
||||
fn from_xml_attr(
|
||||
attr: &str,
|
||||
type_: Option<&FieldType>,
|
||||
) -> Result<Rc<FieldRestrict>> {
|
||||
let Some(FieldType::Enum(e)) = type_ else {
|
||||
return Err(err("restrict= requires an enum type"));
|
||||
};
|
||||
|
||||
let mut values = Vec::new();
|
||||
for v_name in attr.split(' ') {
|
||||
if v_name.trim().is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(v) = e.get_value(v_name) else {
|
||||
return Err(err("Invalid enum value in restrict"));
|
||||
};
|
||||
values.push(LiteralEnum {
|
||||
enum_type: e.clone(),
|
||||
value_name: v.name.clone(),
|
||||
value_ident: v.ident.clone(),
|
||||
});
|
||||
}
|
||||
Ok(Rc::new(FieldRestrict { values }))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for FieldRestrict {
|
||||
fn to_tokens(&self, ts: &mut TokenStream2) {
|
||||
let mut values_ts = TokenStream2::new();
|
||||
for i in &self.values {
|
||||
values_ts.extend(quote! { #i, });
|
||||
}
|
||||
ts.extend(quote! { [#values_ts] });
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VirtualField {
|
||||
pub name: String,
|
||||
pub ident: Ident,
|
||||
pub type_: FieldType,
|
||||
pub restrict: Option<Rc<FieldRestrict>>,
|
||||
pub expr: Box<Expr>,
|
||||
}
|
||||
|
||||
|
|
@ -86,13 +129,20 @@ impl VirtualField {
|
|||
let snake_name = to_snake_case(&name);
|
||||
let ident = Ident::new(&snake_name, Span::call_site());
|
||||
|
||||
let type_ = xml
|
||||
let type_name = xml
|
||||
.attrs
|
||||
.get("type")
|
||||
.ok_or(err("Instruction virtual has no type"))?;
|
||||
let type_ = FieldType::from_name(type_name, 32, enums)?;
|
||||
|
||||
let restrict = if let Some(res_attr) = xml.attrs.get("restrict") {
|
||||
Some(FieldRestrict::from_xml_attr(res_attr, Some(&type_))?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let expr = if let Some(exact) = xml.attrs.get("exact") {
|
||||
Box::new(Expr::literal(Some(type_), exact, enums)?)
|
||||
Box::new(Expr::literal(Some(type_name), exact, enums)?)
|
||||
} else {
|
||||
let mut children = xml.children;
|
||||
if children.len() != 1 {
|
||||
|
|
@ -105,7 +155,8 @@ impl VirtualField {
|
|||
Ok(VirtualField {
|
||||
name,
|
||||
ident,
|
||||
type_: FieldType::from_name(type_, 32, enums)?,
|
||||
type_,
|
||||
restrict,
|
||||
expr,
|
||||
})
|
||||
}
|
||||
|
|
@ -152,6 +203,7 @@ pub struct PhysicalField {
|
|||
pub bits: Range<u8>,
|
||||
pub mod_: FieldMod,
|
||||
pub type_: Option<FieldType>,
|
||||
pub restrict: Option<Rc<FieldRestrict>>,
|
||||
pub expr: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +240,12 @@ impl PhysicalField {
|
|||
None => None,
|
||||
};
|
||||
|
||||
let restrict = if let Some(res_attr) = xml.attrs.get("restrict") {
|
||||
Some(FieldRestrict::from_xml_attr(res_attr, type_.as_ref())?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut expr = if let Some(exact) = xml.attrs.get("exact") {
|
||||
Some(Box::new(Expr::literal(
|
||||
type_name.map(String::as_str),
|
||||
|
|
@ -224,6 +282,7 @@ impl PhysicalField {
|
|||
bits,
|
||||
mod_,
|
||||
type_,
|
||||
restrict,
|
||||
expr,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue