From 38619f8b99daf77086f66f2c0f0cc3d8bf9f99f1 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 26 Sep 2023 20:20:28 -0500 Subject: [PATCH] metapac: generate ir --- stm32-metapac-gen/res/src/metadata.rs | 94 +++++++++++ stm32-metapac-gen/src/data.rs | 221 ++++++++++++++++++++++++++ stm32-metapac-gen/src/lib.rs | 41 ++++- 3 files changed, 355 insertions(+), 1 deletion(-) diff --git a/stm32-metapac-gen/res/src/metadata.rs b/stm32-metapac-gen/res/src/metadata.rs index 2342765..def01e8 100644 --- a/stm32-metapac-gen/res/src/metadata.rs +++ b/stm32-metapac-gen/res/src/metadata.rs @@ -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, + 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, + 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)] pub struct Metadata { pub name: &'static str, @@ -73,6 +166,7 @@ pub struct PeripheralRcc { pub clock: &'static str, pub enable: Option, pub reset: Option, + pub mux: Option, } #[derive(Debug, Eq, PartialEq, Clone)] diff --git a/stm32-metapac-gen/src/data.rs b/stm32-metapac-gen/src/data.rs index db6f972..73c8922 100644 --- a/stm32-metapac-gen/src/data.rs +++ b/stm32-metapac-gen/src/data.rs @@ -1,5 +1,226 @@ use serde::Deserialize; +pub mod ir { + use super::*; + + #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] + pub struct IR { + pub blocks: Vec, + pub fieldsets: Vec
, + pub enums: Vec, + } + + impl IR { + pub fn from_chiptool(ir: chiptool::ir::IR) -> Self { + let blocks: Vec = 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
= 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 = 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, + + pub description: Option, + pub items: Vec, + } + + #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] + pub struct BlockItem { + pub name: String, + pub description: Option, + + pub array: Option, + 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, + } + + #[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, + + pub description: Option, + pub bit_size: u32, + pub fields: Vec, + } + + #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] + pub struct Field { + pub name: String, + pub description: Option, + + pub bit_offset: u32, + pub bit_size: u32, + pub array: Option, + pub enumm: Option, + } + + #[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, + } + + #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] + pub struct Enum { + pub name: String, + pub description: Option, + pub bit_size: u32, + pub variants: Vec, + } + + #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] + pub struct EnumVariant { + pub name: String, + pub description: Option, + pub value: u64, + } +} + #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] pub struct Chip { pub name: String, diff --git a/stm32-metapac-gen/src/lib.rs b/stm32-metapac-gen/src/lib.rs index 913a165..0152e38 100644 --- a/stm32-metapac-gen/src/lib.rs +++ b/stm32-metapac-gen/src/lib.rs @@ -206,7 +206,7 @@ impl Gen { file }); - let data = format!( + let mut data = format!( "include!(\"../{}\"); pub const METADATA: Metadata = Metadata {{ name: {:?}, @@ -226,6 +226,15 @@ impl Gen { &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(); file.write_all(data.as_bytes()).unwrap(); @@ -250,6 +259,7 @@ impl Gen { 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/registers")).unwrap(); fs::create_dir_all(self.opts.out_dir.join("src/chips")).unwrap(); let mut chip_core_names: Vec = Vec::new(); @@ -318,6 +328,35 @@ impl Gen { let re = Regex::new("# *! *\\[.*\\]").unwrap(); let data = re.replace_all(&data, ""); 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