metapac: generate ir

This commit is contained in:
xoviat 2023-09-26 20:20:28 -05:00
parent 1595920962
commit 38619f8b99
3 changed files with 355 additions and 1 deletions

View File

@ -1,3 +1,96 @@
pub mod ir {
pub struct IR {
pub blocks: &'static [Block],
pub fieldsets: &'static [FieldSet],
pub enums: &'static [Enum],
}
pub struct Block {
pub name: &'static str,
pub extends: Option<&'static str>,
pub description: Option<&'static str>,
pub items: &'static [BlockItem],
}
pub struct BlockItem {
pub name: &'static str,
pub description: Option<&'static str>,
pub array: Option<Array>,
pub byte_offset: u32,
pub inner: BlockItemInner,
}
pub enum BlockItemInner {
Block(BlockItemBlock),
Register(Register),
}
pub struct Register {
pub access: Access,
pub bit_size: u32,
pub fieldset: Option<&'static str>,
}
pub struct BlockItemBlock {
pub block: &'static str,
}
pub enum Access {
ReadWrite,
Read,
Write,
}
pub struct FieldSet {
pub name: &'static str,
pub extends: Option<&'static str>,
pub description: Option<&'static str>,
pub bit_size: u32,
pub fields: &'static [Field],
}
pub struct Field {
pub name: &'static str,
pub description: Option<&'static str>,
pub bit_offset: u32,
pub bit_size: u32,
pub array: Option<Array>,
pub enumm: Option<&'static str>,
}
pub enum Array {
Regular(RegularArray),
Cursed(CursedArray),
}
pub struct RegularArray {
pub len: u32,
pub stride: u32,
}
pub struct CursedArray {
pub offsets: &'static [u32],
}
pub struct Enum {
pub name: &'static str,
pub description: Option<&'static str>,
pub bit_size: u32,
pub variants: &'static [EnumVariant],
}
pub struct EnumVariant {
pub name: &'static str,
pub description: Option<&'static str>,
pub value: u64,
}
}
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata { pub struct Metadata {
pub name: &'static str, pub name: &'static str,
@ -73,6 +166,7 @@ pub struct PeripheralRcc {
pub clock: &'static str, pub clock: &'static str,
pub enable: Option<PeripheralRccRegister>, pub enable: Option<PeripheralRccRegister>,
pub reset: Option<PeripheralRccRegister>, pub reset: Option<PeripheralRccRegister>,
pub mux: Option<PeripheralRccRegister>,
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]

View File

@ -1,5 +1,226 @@
use serde::Deserialize; use serde::Deserialize;
pub mod ir {
use super::*;
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct IR {
pub blocks: Vec<Block>,
pub fieldsets: Vec<FieldSet>,
pub enums: Vec<Enum>,
}
impl IR {
pub fn from_chiptool(ir: chiptool::ir::IR) -> Self {
let blocks: Vec<Block> = ir
.blocks
.iter()
.map(|(name, block)| {
let items = block
.items
.iter()
.map(|item| BlockItem {
name: item.name.clone(),
description: item.description.clone(),
array: None,
byte_offset: item.byte_offset,
inner: match &item.inner {
chiptool::ir::BlockItemInner::Block(block) => BlockItemInner::Block(BlockItemBlock {
block: block.block.clone(),
}),
chiptool::ir::BlockItemInner::Register(register) => {
BlockItemInner::Register(Register {
access: match register.access {
chiptool::ir::Access::Read => Access::Read,
chiptool::ir::Access::ReadWrite => Access::ReadWrite,
chiptool::ir::Access::Write => Access::Write,
},
bit_size: register.bit_size,
fieldset: register
.fieldset
.as_ref()
.map(|fieldset| fieldset.strip_prefix("regs::").unwrap().to_string()),
})
}
},
})
.collect();
Block {
name: name.to_string(),
items: items,
extends: block.extends.clone(),
description: block.description.clone(),
}
})
.collect();
let fieldsets: Vec<FieldSet> = ir
.fieldsets
.iter()
.map(|(name, fieldset)| {
let fields = fieldset
.fields
.iter()
.map(|field| Field {
name: field.name.clone(),
description: field.description.clone(),
bit_offset: field.bit_offset,
bit_size: field.bit_size,
array: field.array.as_ref().map(|array| match &array {
chiptool::ir::Array::Regular(regular_array) => Array::Regular(RegularArray {
len: regular_array.len,
stride: regular_array.stride,
}),
chiptool::ir::Array::Cursed(cursed_array) => Array::Cursed(CursedArray {
offsets: cursed_array.offsets.clone(),
}),
}),
enumm: field
.enumm
.as_ref()
.map(|fieldset| fieldset.strip_prefix("vals::").unwrap().to_string()),
})
.collect();
FieldSet {
name: name.strip_prefix("regs::").unwrap().to_owned(),
fields: fields,
extends: fieldset.extends.clone(),
description: fieldset.description.clone(),
bit_size: fieldset.bit_size,
}
})
.collect();
let enums: Vec<Enum> = ir
.enums
.iter()
.map(|(name, enumm)| {
let variants = enumm
.variants
.iter()
.map(|variant| EnumVariant {
name: variant.name.clone(),
description: variant.description.clone(),
value: variant.value,
})
.collect();
Enum {
name: name.strip_prefix("vals::").unwrap().to_owned(),
description: enumm.description.clone(),
bit_size: enumm.bit_size,
variants: variants,
}
})
.collect();
Self {
blocks,
fieldsets,
enums,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Block {
pub name: String,
pub extends: Option<String>,
pub description: Option<String>,
pub items: Vec<BlockItem>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct BlockItem {
pub name: String,
pub description: Option<String>,
pub array: Option<Array>,
pub byte_offset: u32,
pub inner: BlockItemInner,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub enum BlockItemInner {
Block(BlockItemBlock),
Register(Register),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Register {
pub access: Access,
pub bit_size: u32,
pub fieldset: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct BlockItemBlock {
pub block: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub enum Access {
ReadWrite,
Read,
Write,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct FieldSet {
pub name: String,
pub extends: Option<String>,
pub description: Option<String>,
pub bit_size: u32,
pub fields: Vec<Field>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Field {
pub name: String,
pub description: Option<String>,
pub bit_offset: u32,
pub bit_size: u32,
pub array: Option<Array>,
pub enumm: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub enum Array {
Regular(RegularArray),
Cursed(CursedArray),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct RegularArray {
pub len: u32,
pub stride: u32,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct CursedArray {
pub offsets: Vec<u32>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Enum {
pub name: String,
pub description: Option<String>,
pub bit_size: u32,
pub variants: Vec<EnumVariant>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct EnumVariant {
pub name: String,
pub description: Option<String>,
pub value: u64,
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)] #[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Chip { pub struct Chip {
pub name: String, pub name: String,

View File

@ -206,7 +206,7 @@ impl Gen {
file file
}); });
let data = format!( let mut data = format!(
"include!(\"../{}\"); "include!(\"../{}\");
pub const METADATA: Metadata = Metadata {{ pub const METADATA: Metadata = Metadata {{
name: {:?}, name: {:?},
@ -226,6 +226,15 @@ impl Gen {
&core.nvic_priority_bits, &core.nvic_priority_bits,
); );
for (module, version) in &peripheral_versions {
writeln!(
&mut data,
"#[path=\"../../registers/{}_{}.rs\"] pub mod {};",
module, version, module
)
.unwrap();
}
let mut file = File::create(chip_dir.join("metadata.rs")).unwrap(); let mut file = File::create(chip_dir.join("metadata.rs")).unwrap();
file.write_all(data.as_bytes()).unwrap(); file.write_all(data.as_bytes()).unwrap();
@ -250,6 +259,7 @@ impl Gen {
pub fn gen(&mut self) { pub fn gen(&mut self) {
fs::create_dir_all(self.opts.out_dir.join("src/peripherals")).unwrap(); fs::create_dir_all(self.opts.out_dir.join("src/peripherals")).unwrap();
fs::create_dir_all(self.opts.out_dir.join("src/registers")).unwrap();
fs::create_dir_all(self.opts.out_dir.join("src/chips")).unwrap(); fs::create_dir_all(self.opts.out_dir.join("src/chips")).unwrap();
let mut chip_core_names: Vec<String> = Vec::new(); let mut chip_core_names: Vec<String> = Vec::new();
@ -318,6 +328,35 @@ impl Gen {
let re = Regex::new("# *! *\\[.*\\]").unwrap(); let re = Regex::new("# *! *\\[.*\\]").unwrap();
let data = re.replace_all(&data, ""); let data = re.replace_all(&data, "");
file.write_all(data.as_bytes()).unwrap(); file.write_all(data.as_bytes()).unwrap();
let ir = crate::data::ir::IR::from_chiptool(ir);
let mut data = String::new();
write!(
&mut data,
"
use crate::metadata::ir::*;
static REGISTERS: IR = {};
",
stringify(&ir)
.replace("Register(", "BlockItemInner::Register(")
.replace("Block(", "BlockItemInner::Block(")
.replace("Regular(", "Array::Regular(")
.replace("Cursed(", "Array::Cursed(")
.replace("Read,", "Access::Read,")
.replace("Write,", "Access::Write,")
.replace("ReadAccess::Write,", "Access::ReadWrite,"),
)
.unwrap();
let mut file = File::create(
self.opts
.out_dir
.join("src/registers")
.join(format!("{}_{}.rs", module, version)),
)
.unwrap();
file.write_all(data.as_bytes()).unwrap();
} }
// Generate Cargo.toml // Generate Cargo.toml