2024-02-25 22:24:22 +01:00

464 lines
15 KiB
Rust

use serde::Deserialize;
use stm32_data_macros::EnumDebug;
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 mut 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: 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 {
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();
#[allow(clippy::redundant_field_names)]
Block {
name: name.to_string(),
items: items,
extends: block.extends.clone(),
description: block.description.clone(),
}
})
.collect();
blocks.sort_by_key(|b| b.name.clone());
let mut 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: match &field.bit_offset {
chiptool::ir::BitOffset::Regular(offset) => {
BitOffset::Regular(RegularBitOffset { offset: *offset })
}
chiptool::ir::BitOffset::Cursed(ranges) => {
BitOffset::Cursed(CursedBitOffset { ranges: ranges.clone() })
}
},
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();
#[allow(clippy::redundant_field_names)]
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();
fieldsets.sort_by_key(|f| f.name.clone());
let mut 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();
#[allow(clippy::redundant_field_names)]
Enum {
name: name.strip_prefix("vals::").unwrap().to_owned(),
description: enumm.description.clone(),
bit_size: enumm.bit_size,
variants: variants,
}
})
.collect();
enums.sort_by_key(|e| e.name.clone());
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>,
}
// Notice:
// BlockItem has custom Debug implement,
// when modify the struct, make sure Debug impl reflect the change.
#[derive(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,
}
// Notice:
// Debug implement AFFECT OUTPUT METAPAC, modify with caution
impl std::fmt::Debug for BlockItem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BlockItem")
.field("name", &self.name)
.field("description", &self.description)
.field("array", &self.array)
.field("byte_offset", &format_args!("{:#x}", self.byte_offset))
.field("inner", &self.inner)
.finish()
}
}
#[derive(EnumDebug, 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(EnumDebug, 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: BitOffset,
pub bit_size: u32,
pub array: Option<Array>,
pub enumm: Option<String>,
}
#[derive(EnumDebug, 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(EnumDebug, Eq, PartialEq, Clone, Deserialize)]
pub enum BitOffset {
Regular(RegularBitOffset),
Cursed(CursedBitOffset),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct RegularBitOffset {
pub offset: u32,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct CursedBitOffset {
pub ranges: Vec<core::ops::RangeInclusive<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)]
pub struct Chip {
pub name: String,
pub family: String,
pub line: String,
pub cores: Vec<Core>,
pub memory: Vec<MemoryRegion>,
pub packages: Vec<Package>,
}
// Notice:
// MemoryRegion has custom Debug implement,
// when modify the struct, make sure Debug impl reflect the change.
#[derive(Eq, PartialEq, Clone, Deserialize)]
pub struct MemoryRegion {
pub name: String,
pub kind: MemoryRegionKind,
pub address: u32,
pub size: u32,
pub settings: Option<FlashSettings>,
}
// Notice:
// Debug implement AFFECT OUTPUT METAPAC, modify with caution
impl std::fmt::Debug for MemoryRegion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MemoryRegion")
.field("name", &self.name)
.field("kind", &self.kind)
.field("address", &format_args!("{:#x}", self.address))
.field("size", &self.size)
.field("settings", &self.settings)
.finish()
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct FlashSettings {
pub erase_size: u32,
pub write_size: u32,
pub erase_value: u8,
}
#[derive(EnumDebug, Eq, PartialEq, Clone, Deserialize)]
pub enum MemoryRegionKind {
#[serde(rename = "flash")]
Flash,
#[serde(rename = "ram")]
Ram,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Core {
pub name: String,
pub peripherals: Vec<Peripheral>,
#[serde(default)]
pub nvic_priority_bits: Option<u8>,
pub interrupts: Vec<Interrupt>,
pub dma_channels: Vec<DmaChannel>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Interrupt {
pub name: String,
pub number: u32,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct Package {
pub name: String,
pub package: String,
}
// Notice:
// Peripheral has custom Debug implement,
// when modify struct, make sure Debug impl reflect the change.
#[derive(Eq, PartialEq, Clone, Deserialize)]
pub struct Peripheral {
pub name: String,
pub address: u64,
#[serde(default)]
pub registers: Option<PeripheralRegisters>,
#[serde(default)]
pub rcc: Option<PeripheralRcc>,
#[serde(default)]
pub pins: Vec<PeripheralPin>,
#[serde(default)]
pub dma_channels: Vec<PeripheralDmaChannel>,
#[serde(default)]
pub interrupts: Vec<PeripheralInterrupt>,
}
// Notice:
// Debug implement AFFECT OUTPUT METAPAC, modify with caution
impl std::fmt::Debug for Peripheral {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Peripheral")
.field("name", &self.name)
.field("address", &format_args!("{:#x}", self.address))
.field("registers", &self.registers)
.field("rcc", &self.rcc)
.field("pins", &self.pins)
.field("dma_channels", &self.dma_channels)
.field("interrupts", &self.interrupts)
.finish()
}
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct PeripheralInterrupt {
pub signal: String,
pub interrupt: String,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct PeripheralRcc {
pub bus_clock: String,
pub kernel_clock: PeripheralRccKernelClock,
#[serde(default)]
pub enable: Option<PeripheralRccRegister>,
#[serde(default)]
pub reset: Option<PeripheralRccRegister>,
#[serde(default)]
pub stop_mode: StopMode,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
#[serde(untagged)]
pub enum PeripheralRccKernelClock {
Clock(String),
Mux(PeripheralRccRegister),
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct PeripheralRccRegister {
pub register: String,
pub field: String,
}
#[derive(EnumDebug, Eq, PartialEq, Clone, Deserialize, Default)]
pub enum StopMode {
#[default]
Stop1, // Peripheral prevents chip from entering Stop1
Stop2, // Peripheral prevents chip from entering Stop2
Standby, // Peripheral does not prevent chip from entering Stop
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct PeripheralPin {
pub pin: String,
pub signal: String,
pub af: Option<u8>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct DmaChannel {
pub name: String,
pub dma: String,
pub channel: u32,
pub dmamux: Option<String>,
pub dmamux_channel: Option<u32>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Hash)]
pub struct PeripheralDmaChannel {
pub signal: String,
pub channel: Option<String>,
pub dmamux: Option<String>,
pub dma: Option<String>,
pub request: Option<u32>,
}
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Hash)]
pub struct PeripheralRegisters {
pub kind: String,
pub version: String,
pub block: String,
#[serde(default)]
pub ir: String,
}