new(CodeGen): for Block

This commit is contained in:
Wataru Otsubo 2025-01-31 03:26:42 +09:00
parent dfd28782dd
commit 6b5b5e0234
5 changed files with 90 additions and 25 deletions

7
Cargo.lock generated
View file

@ -79,6 +79,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"env_logger",
"heck",
"log",
"proc-macro2",
"quote",
@ -109,6 +110,12 @@ dependencies = [
"log",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "humantime"
version = "2.1.0"

View file

@ -14,6 +14,7 @@ path = "src/lib.rs"
[dependencies]
anyhow = "1.0.95"
env_logger = "0.11.6"
heck = "0.5"
log = "0.4"
proc-macro2 = "1.0.93"
quote = "1.0"

View file

@ -1,6 +1,10 @@
//! Generate register interface rust code from types in [`crate::types`].
use crate::types::{Block, Module, ModuleBlockElements};
use crate::{
type_traits::GetName,
types::{Block, Module, ModuleBlockElements},
};
use heck::{ToSnakeCase, ToUpperCamelCase};
use proc_macro2::TokenStream;
use quote::quote;
@ -40,43 +44,65 @@ impl CodeGen for ModuleBlockElements {
impl CodeGen for Block {
fn generate_register_interface(self) -> proc_macro2::TokenStream {
let name = self.name;
let snake_case_name = self.name.to_snake_case();
let upper_camel_name = self.name.to_upper_camel_case();
let addr = format!("0x{:x}", self.addr);
let desc = self.desc.unwrap_or("".to_string());
let accessor_methods = {
let mut out = TokenStream::new();
for child_name in self.elements.iter().map(|e| e.get_name()) {
let snake_case_name = child_name.to_snake_case();
let upper_camel_name = child_name.to_upper_camel_case();
out.extend(quote! {
pub fn #snake_case_name(&self) -> #snake_case_name::#upper_camel_name {
#snake_case_name::#upper_camel_name::new(self.mem_ptr)
}
});
}
out
};
let child_mods = {
let mut out = TokenStream::new();
for child_mod in self.elements.into_iter() {
let module = child_mod.generate_register_interface();
out.extend(module);
}
out
};
quote! {
pub mod #name {
pub mod #snake_case_name {
#[doc = #desc]
use std::marker::PhantomData;
use super::RegisterInterface;
pub mod control;
pub mod status;
pub(crate) const SLR0_OFFSET: usize = 0x0000;
pub(crate) const SLR0_SIZE: usize = 0x4000;
#child_mods
const OFFSET: usize = #addr;
//pub(crate) const SIZE: usize = 0x4000;
/// Access to SLR0.
pub struct Slr0<'a> {
pub struct #upper_camel_name<'a> {
mem_ptr: *mut u32,
_marker: PhantomData<&'a mut RegisterInterface>,
}
impl Slr0<'_> {
pub(crate) fn new(ptr: *mut u32) -> Self {
Slr0 {
mem_ptr: ptr,
impl #upper_camel_name<'_> {
pub(crate) fn new(parent_ptr: *mut u32) -> Self {
#upper_camel_name {
mem_ptr: unsafe { parent_ptr.add(OFFSET) },
_marker: PhantomData,
}
}
pub fn control(&self) -> control::Control {
control::Control::new(unsafe { self.mem_ptr.add(control::OFFSET) })
}
pub fn status(&self) -> status::Status {
status::Status::new(unsafe { self.mem_ptr.add(status::OFFSET) })
}
#accessor_methods
}
}
}

View file

@ -1,6 +1,7 @@
//! Root document [`types::Module::from_xml_dom`]
pub mod types;
pub mod type_traits;
pub mod parser;
pub mod converter;
pub mod generator;

30
src/type_traits.rs Normal file
View file

@ -0,0 +1,30 @@
//! Util traits to get info from types in [`crate::types`].
use crate::types::{Block, ModuleBlockElements, Register};
pub(crate) trait GetName {
fn get_name(&self) -> String;
}
impl GetName for ModuleBlockElements {
fn get_name(&self) -> String {
match self {
ModuleBlockElements::Block(block) => block.get_name(),
ModuleBlockElements::Register(register) => register.get_name(),
ModuleBlockElements::Memory(memory) => todo!(),
ModuleBlockElements::Fifo(fifo) => todo!(),
}
}
}
impl GetName for Block {
fn get_name(&self) -> String {
self.name.clone()
}
}
impl GetName for Register {
fn get_name(&self) -> String {
self.name.clone()
}
}