Skip to content

Commit

Permalink
target-specific configuration in settings.yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
romancardenas committed Oct 21, 2024
1 parent b198aec commit f598498
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 98 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ default = ["bin", "json", "yaml"]
bin = ["dep:clap", "dep:env_logger", "serde", "dep:irx-config"]
json = ["dep:serde_json"]
yaml = ["dep:serde_yaml"]
unstable-riscv = ["irx-config/yaml"]
unstable-riscv = []

[dependencies]
clap = { version = "4.0", optional = true }
irx-config = { version = "=3.3.0", features = [
"cmd",
"toml-parser",
"yaml",
], optional = true }
env_logger = { version = "0.11", optional = true }
inflections = "1.1"
Expand Down
57 changes: 8 additions & 49 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub struct Config {
pub field_names_for_enums: bool,
pub base_address_shift: u64,
pub html_url: Option<url::Url>,
#[cfg(feature = "unstable-riscv")]
pub riscv_config: Option<RiscvConfig>,
/// Path to YAML file with chip-specific settings
pub settings: Option<PathBuf>,
}

#[allow(clippy::upper_case_acronyms)]
Expand Down Expand Up @@ -315,56 +315,15 @@ pub enum IdentFormatsTheme {
Legacy,
}

#[cfg(feature = "unstable-riscv")]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvConfig {
pub core_interrupts: Option<Vec<RiscvEnumItem>>,
pub exceptions: Option<Vec<RiscvEnumItem>>,
pub priorities: Option<Vec<RiscvEnumItem>>,
pub harts: Option<Vec<RiscvEnumItem>>,
pub clint: Option<RiscvClintConfig>,
pub plic: Option<RiscvPlicConfig>,
}

#[cfg(feature = "unstable-riscv")]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvEnumItem {
pub name: String,
pub value: usize,
pub description: Option<String>,
}

#[cfg(feature = "unstable-riscv")]
impl RiscvEnumItem {
pub fn description(&self) -> String {
let description = match &self.description {
Some(d) => d,
None => &self.name,
};
format!("{} - {}", self.value, description)
}
}

#[cfg(feature = "unstable-riscv")]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvClintConfig {
pub name: String,
pub freq: Option<usize>,
pub async_delay: bool,
/// Chip-specific settings
pub struct Settings {
#[cfg(feature = "unstable-riscv")]
/// RISC-V specific settings
pub riscv_config: Option<riscv::RiscvConfig>,
}

#[cfg(feature = "unstable-riscv")]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvPlicConfig {
pub name: String,
pub core_interrupt: Option<String>,
pub hart_id: Option<String>,
}
pub mod riscv;
48 changes: 48 additions & 0 deletions src/config/riscv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvConfig {
pub core_interrupts: Vec<RiscvEnumItem>,
pub exceptions: Vec<RiscvEnumItem>,
pub priorities: Vec<RiscvEnumItem>,
pub harts: Vec<RiscvEnumItem>,
pub clint: Option<RiscvClintConfig>,
pub plic: Option<RiscvPlicConfig>,
}

#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvEnumItem {
pub name: String,
pub value: usize,
pub description: Option<String>,
}

impl RiscvEnumItem {
pub fn description(&self) -> String {
let description = match &self.description {
Some(d) => d,
None => &self.name,
};
format!("{} - {}", self.value, description)
}
}

#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvClintConfig {
pub name: String,
pub freq: Option<usize>,
pub async_delay: bool,
}

#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub struct RiscvPlicConfig {
pub name: String,
pub core_interrupt: Option<String>,
pub hart_id: Option<String>,
}
14 changes: 11 additions & 3 deletions src/generate/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::fs::File;
use std::io::Write;
use std::path::Path;

use crate::config::{Config, Target};
use crate::config::{Config, Settings, Target};
use crate::util::{self, ident};
use anyhow::{Context, Result};

Expand All @@ -30,6 +30,14 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
}
};

let _settings = match config.settings.as_ref() {
Some(settings) => {
let file = std::fs::read_to_string(settings).context("could not read settings file")?;
serde_yaml::from_str(&file).context("could not parse settings file")?
}
None => Settings::default(),
};

if config.target == Target::Msp430 {
out.extend(quote! {
#![feature(abi_msp430_interrupt)]
Expand Down Expand Up @@ -193,7 +201,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
#[cfg(feature = "unstable-riscv")]
Target::RISCV => {
debug!("Rendering RISC-V specific code");
out.extend(riscv::render(&d.peripherals, device_x, config)?);
out.extend(riscv::render(&d.peripherals, device_x, &_settings)?);
}
_ => {
debug!("Rendering interrupts");
Expand All @@ -215,7 +223,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
continue;
}
#[cfg(feature = "unstable-riscv")]
if config.target == Target::RISCV && riscv::is_riscv_peripheral(p, config) {
if config.target == Target::RISCV && riscv::is_riscv_peripheral(p, &_settings) {
// RISC-V specific peripherals are handled above
continue;
}
Expand Down
37 changes: 19 additions & 18 deletions src/generate/riscv.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::{svd::Peripheral, util, Config};
use crate::{svd::Peripheral, util, Settings};
use anyhow::Result;
use log::debug;
use proc_macro2::TokenStream;
use quote::quote;
use std::{collections::HashMap, fmt::Write, str::FromStr};

pub fn is_riscv_peripheral(p: &Peripheral, c: &Config) -> bool {
pub fn is_riscv_peripheral(p: &Peripheral, s: &Settings) -> bool {
// TODO cleaner implementation of this
match &c.riscv_config {
match &s.riscv_config {
Some(c) => {
c.clint.as_ref().is_some_and(|clint| clint.name == p.name)
|| c.plic.as_ref().is_some_and(|plic| plic.name == p.name)
Expand All @@ -20,16 +20,16 @@ pub fn is_riscv_peripheral(p: &Peripheral, c: &Config) -> bool {
pub fn render(
peripherals: &[Peripheral],
device_x: &mut String,
config: &Config,
settings: &Settings,
) -> Result<TokenStream> {
let mut mod_items = TokenStream::new();

if let Some(c) = config.riscv_config.as_ref() {
if let Some(i) = c.core_interrupts.as_ref() {
if let Some(c) = settings.riscv_config.as_ref() {
if !c.core_interrupts.is_empty() {
debug!("Rendering target-specific core interrupts");
writeln!(device_x, "/* Core interrupt sources and trap handlers */")?;
let mut interrupts = vec![];
for interrupt in i.iter() {
for interrupt in c.core_interrupts.iter() {
let name = TokenStream::from_str(&interrupt.name).unwrap();
let value = TokenStream::from_str(&format!("{}", interrupt.value)).unwrap();
let description = interrupt.description();
Expand Down Expand Up @@ -58,11 +58,11 @@ pub fn render(
mod_items.extend(quote! {pub use riscv::interrupt::Interrupt as CoreInterrupt;});
}

if let Some(e) = c.exceptions.as_ref() {
if !c.exceptions.is_empty() {
debug!("Rendering target-specific exceptions");
writeln!(device_x, "/* Exception sources */")?;
let mut exceptions = vec![];
for exception in e.iter() {
for exception in c.exceptions.iter() {
let name = TokenStream::from_str(&exception.name).unwrap();
let value = TokenStream::from_str(&format!("{}", exception.value)).unwrap();
let description = exception.description();
Expand All @@ -87,9 +87,9 @@ pub fn render(
mod_items.extend(quote! { pub use riscv::interrupt::Exception; });
}

if let Some(p) = c.priorities.as_ref() {
if !c.priorities.is_empty() {
debug!("Rendering target-specific priority levels");
let priorities = p.iter().map(|priority| {
let priorities = c.priorities.iter().map(|priority| {
let name = TokenStream::from_str(&priority.name).unwrap();
let value = TokenStream::from_str(&format!("{}", priority.value)).unwrap();
let description = priority.description();
Expand All @@ -109,9 +109,9 @@ pub fn render(
});
}

if let Some(h) = c.harts.as_ref() {
if !c.harts.is_empty() {
debug!("Rendering target-specific HART IDs");
let harts = h.iter().map(|hart| {
let harts = c.harts.iter().map(|hart| {
let name = TokenStream::from_str(&hart.name).unwrap();
let value = TokenStream::from_str(&format!("{}", hart.value)).unwrap();
let description = hart.description();
Expand Down Expand Up @@ -205,13 +205,14 @@ pub fn render(
}

let mut riscv_peripherals = TokenStream::new();
if let Some(c) = &config.riscv_config {
let harts = match &c.harts {
Some(harts) => harts
if let Some(c) = &settings.riscv_config {
let harts = match c.harts.is_empty() {
true => vec![],
false => c
.harts
.iter()
.map(|h| (TokenStream::from_str(&h.name).unwrap(), h.value))
.collect::<Vec<_>>(),
None => vec![],
};
if let Some(clint) = &c.clint {
let p = peripherals.iter().find(|&p| p.name == clint.name).unwrap();
Expand Down Expand Up @@ -286,7 +287,7 @@ pub fn render(
fn plic_handler() {
let claim = crate::PLIC::#ctx.claim();
if let Some(s) = claim.claim::<ExternalInterrupt>() {
unsafe { _dispatch_core_interrupt(s.number()) }
unsafe { _dispatch_external_interrupt(s.number()) }
claim.complete(s);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ pub mod config;
pub mod generate;
pub mod util;

pub use config::{Config, Target};
pub use config::{Config, Settings, Target};

#[non_exhaustive]
pub struct Generation {
Expand Down
34 changes: 8 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#![recursion_limit = "128"]

use log::{debug, error, info, warn};
#[cfg(feature = "unstable-riscv")]
use svd2rust::config::RiscvConfig;
use svd2rust::config::{IdentFormatError, IdentFormats, IdentFormatsTheme};
use svd2rust::util::IdentFormat;

Expand All @@ -20,8 +18,6 @@ use svd2rust::{
};

fn parse_configs(app: Command) -> Result<Config> {
#[cfg(feature = "unstable-riscv")]
use irx_config::parsers::yaml;
use irx_config::parsers::{cmd, toml};
use irx_config::ConfigBuilder;
let ident_formats = app.clone().get_matches();
Expand All @@ -34,23 +30,11 @@ fn parse_configs(app: Command) -> Result<Config> {
.ignore_missing_file(true)
.build()?,
);
#[cfg(feature = "unstable-riscv")]
let irxconfig = irxconfig.append_parser(
yaml::ParserBuilder::default()
.default_path("riscv.yaml")
.path_option("riscv_cfg")
.ignore_missing_file(true)
.build()?,
);

let irxconfig = irxconfig.load()?;

let mut config: Config = irxconfig.get()?;

#[cfg(feature = "unstable-riscv")]
if let Ok(riscv_config) = irxconfig.get::<RiscvConfig>() {
config.riscv_config = Some(riscv_config);
}

let mut idf = match config.ident_formats_theme {
Some(IdentFormatsTheme::Legacy) => IdentFormats::legacy_theme(),
_ => IdentFormats::default_theme(),
Expand Down Expand Up @@ -116,6 +100,13 @@ fn run() -> Result<()> {
.action(ArgAction::Set)
.value_name("TOML_FILE"),
)
.arg(
Arg::new("settings")
.long("settings")
.help("Target-specific settings YAML file")
.action(ArgAction::Set)
.value_name("YAML_FILE"),
)
.arg(
Arg::new("target")
.long("target")
Expand Down Expand Up @@ -308,15 +299,6 @@ Ignore this option if you are not building your own FPGA based soft-cores."),
env!("CARGO_PKG_VERSION"),
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
));
#[cfg(feature = "unstable-riscv")]
let app = app.arg(
Arg::new("riscv_cfg")
.long("riscv_config")
.help("RISC-V Config YAML file")
.short('r')
.action(ArgAction::Set)
.value_name("YAML_FILE"),
);

let mut config = match parse_configs(app) {
Ok(config) => {
Expand Down

0 comments on commit f598498

Please sign in to comment.