From 1595920962e1b7d20cea4f552a4fb73a823449bc Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 25 Sep 2023 19:26:46 -0500 Subject: [PATCH 1/3] rcc: pipe through sel mux --- stm32-data-gen/src/rcc.rs | 21 +++++++++++++++++++++ stm32-data-serde/src/lib.rs | 8 ++++++++ stm32-metapac-gen/src/data.rs | 2 ++ 3 files changed, 31 insertions(+) diff --git a/stm32-data-gen/src/rcc.rs b/stm32-data-gen/src/rcc.rs index 7316c3d..cf81c4e 100644 --- a/stm32-data-gen/src/rcc.rs +++ b/stm32-data-gen/src/rcc.rs @@ -14,6 +14,24 @@ impl PeripheralToClock { for (rcc_name, ir) in ®isters.registers { if let Some(rcc_name) = rcc_name.strip_prefix("rcc_") { + let mut family_muxes = HashMap::new(); + for (reg, body) in &ir.fieldsets { + let key = format!("fieldset/{reg}"); + if let Some(_) = regex!(r"^fieldset/CCIPR\d?$").captures(&key) { + for field in &body.fields { + if let Some(peri) = field.name.strip_suffix("SEL") { + family_muxes.insert( + peri.to_string(), + stm32_data_serde::chip::core::peripheral::rcc::Mux { + register: reg.clone(), + field: field.name.clone(), + }, + ); + } + } + } + } + let mut family_clocks = HashMap::new(); for (reg, body) in &ir.fieldsets { let key = format!("fieldset/{reg}"); @@ -49,6 +67,8 @@ impl PeripheralToClock { } } + let mux = family_muxes.get(peri).map(|peri| peri.clone()); + let res = stm32_data_serde::chip::core::peripheral::Rcc { clock: peri_clock, enable: stm32_data_serde::chip::core::peripheral::rcc::Enable { @@ -56,6 +76,7 @@ impl PeripheralToClock { field: field.name.clone(), }, reset, + mux, }; family_clocks.insert(peri.to_string(), res); diff --git a/stm32-data-serde/src/lib.rs b/stm32-data-serde/src/lib.rs index dd44b07..323f80a 100644 --- a/stm32-data-serde/src/lib.rs +++ b/stm32-data-serde/src/lib.rs @@ -103,6 +103,8 @@ pub mod chip { pub enable: rcc::Enable, #[serde(skip_serializing_if = "Option::is_none")] pub reset: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mux: Option, } pub mod rcc { @@ -119,6 +121,12 @@ pub mod chip { pub register: String, pub field: String, } + + #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)] + pub struct Mux { + pub register: String, + pub field: String, + } } #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)] diff --git a/stm32-metapac-gen/src/data.rs b/stm32-metapac-gen/src/data.rs index 38e85d6..db6f972 100644 --- a/stm32-metapac-gen/src/data.rs +++ b/stm32-metapac-gen/src/data.rs @@ -85,6 +85,8 @@ pub struct PeripheralRcc { pub enable: Option, #[serde(default)] pub reset: Option, + #[serde(default)] + pub mux: Option, } #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] From 38619f8b99daf77086f66f2c0f0cc3d8bf9f99f1 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 26 Sep 2023 20:20:28 -0500 Subject: [PATCH 2/3] 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 From 23f9d9b23629618ad8519a68481afb97301340e7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 29 Sep 2023 18:21:03 -0500 Subject: [PATCH 3/3] metapac: allow runtime inspection of ir types --- stm32-metapac-gen/res/src/metadata.rs | 15 +++++++++++ stm32-metapac-gen/src/data.rs | 12 ++++++++- stm32-metapac-gen/src/lib.rs | 37 ++++++++++++++++----------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/stm32-metapac-gen/res/src/metadata.rs b/stm32-metapac-gen/res/src/metadata.rs index def01e8..e468451 100644 --- a/stm32-metapac-gen/res/src/metadata.rs +++ b/stm32-metapac-gen/res/src/metadata.rs @@ -1,10 +1,12 @@ pub mod ir { + #[derive(Debug, Eq, PartialEq, Clone)] pub struct IR { pub blocks: &'static [Block], pub fieldsets: &'static [FieldSet], pub enums: &'static [Enum], } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct Block { pub name: &'static str, pub extends: Option<&'static str>, @@ -13,6 +15,7 @@ pub mod ir { pub items: &'static [BlockItem], } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct BlockItem { pub name: &'static str, pub description: Option<&'static str>, @@ -23,27 +26,32 @@ pub mod ir { pub inner: BlockItemInner, } + #[derive(Debug, Eq, PartialEq, Clone)] pub enum BlockItemInner { Block(BlockItemBlock), Register(Register), } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct Register { pub access: Access, pub bit_size: u32, pub fieldset: Option<&'static str>, } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct BlockItemBlock { pub block: &'static str, } + #[derive(Debug, Eq, PartialEq, Clone)] pub enum Access { ReadWrite, Read, Write, } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct FieldSet { pub name: &'static str, pub extends: Option<&'static str>, @@ -53,6 +61,7 @@ pub mod ir { pub fields: &'static [Field], } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct Field { pub name: &'static str, pub description: Option<&'static str>, @@ -63,20 +72,24 @@ pub mod ir { pub enumm: Option<&'static str>, } + #[derive(Debug, Eq, PartialEq, Clone)] pub enum Array { Regular(RegularArray), Cursed(CursedArray), } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct RegularArray { pub len: u32, pub stride: u32, } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct CursedArray { pub offsets: &'static [u32], } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct Enum { pub name: &'static str, pub description: Option<&'static str>, @@ -84,6 +97,7 @@ pub mod ir { pub variants: &'static [EnumVariant], } + #[derive(Debug, Eq, PartialEq, Clone)] pub struct EnumVariant { pub name: &'static str, pub description: Option<&'static str>, @@ -153,6 +167,7 @@ pub struct PeripheralRegisters { pub kind: &'static str, pub version: &'static str, pub block: &'static str, + pub ir: &'static ir::IR, } #[derive(Debug, Eq, PartialEq, Clone)] diff --git a/stm32-metapac-gen/src/data.rs b/stm32-metapac-gen/src/data.rs index 73c8922..dc90da7 100644 --- a/stm32-metapac-gen/src/data.rs +++ b/stm32-metapac-gen/src/data.rs @@ -22,7 +22,15 @@ pub mod ir { .map(|item| BlockItem { name: item.name.clone(), description: item.description.clone(), - array: None, + array: item.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(), + }), + }), byte_offset: item.byte_offset, inner: match &item.inner { chiptool::ir::BlockItemInner::Block(block) => BlockItemInner::Block(BlockItemBlock { @@ -346,4 +354,6 @@ pub struct PeripheralRegisters { pub kind: String, pub version: String, pub block: String, + #[serde(default)] + pub ir: String, } diff --git a/stm32-metapac-gen/src/lib.rs b/stm32-metapac-gen/src/lib.rs index 0152e38..69db85f 100644 --- a/stm32-metapac-gen/src/lib.rs +++ b/stm32-metapac-gen/src/lib.rs @@ -186,9 +186,9 @@ impl Gen { write!( &mut data, " - const PERIPHERALS: &'static [Peripheral] = {}; - const INTERRUPTS: &'static [Interrupt] = {}; - const DMA_CHANNELS: &'static [DmaChannel] = {}; + pub(crate) static PERIPHERALS: &'static [Peripheral] = {}; + pub(crate) static INTERRUPTS: &'static [Interrupt] = {}; + pub(crate) static DMA_CHANNELS: &'static [DmaChannel] = {}; ", stringify(&core.peripherals), stringify(&core.interrupts), @@ -199,6 +199,18 @@ impl Gen { let out_dir = self.opts.out_dir.clone(); let n = self.metadata_dedup.len(); let deduped_file = self.metadata_dedup.entry(data.clone()).or_insert_with(|| { + let ir_regex = Regex::new("\":ir_for:([a-z0-9]+):\"").unwrap(); + let mut data = ir_regex.replace_all(&data, "&$1::REGISTERS").to_string(); + + for (module, version) in &peripheral_versions { + writeln!( + &mut data, + "#[path=\"../registers/{}_{}.rs\"] pub mod {};", + module, version, module + ) + .unwrap(); + } + let file = format!("metadata_{:04}.rs", n); let path = out_dir.join("src/chips").join(&file); fs::write(path, data).unwrap(); @@ -206,9 +218,9 @@ impl Gen { file }); - let mut data = format!( + let data = format!( "include!(\"../{}\"); - pub const METADATA: Metadata = Metadata {{ + pub static METADATA: Metadata = Metadata {{ name: {:?}, family: {:?}, line: {:?}, @@ -226,15 +238,6 @@ 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(); @@ -278,6 +281,10 @@ impl Gen { for irq in &mut p.interrupts { irq.interrupt = irq.interrupt.to_ascii_uppercase(); } + + if let Some(registers) = &mut p.registers { + registers.ir = format!(":ir_for:{}:", registers.kind); + } } } @@ -336,7 +343,7 @@ impl Gen { &mut data, " use crate::metadata::ir::*; - static REGISTERS: IR = {}; + pub(crate) static REGISTERS: IR = {}; ", stringify(&ir) .replace("Register(", "BlockItemInner::Register(")