Skip to content

Commit f598498

Browse files
committed
target-specific configuration in settings.yaml
1 parent b198aec commit f598498

File tree

7 files changed

+97
-98
lines changed

7 files changed

+97
-98
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ default = ["bin", "json", "yaml"]
3535
bin = ["dep:clap", "dep:env_logger", "serde", "dep:irx-config"]
3636
json = ["dep:serde_json"]
3737
yaml = ["dep:serde_yaml"]
38-
unstable-riscv = ["irx-config/yaml"]
38+
unstable-riscv = []
3939

4040
[dependencies]
4141
clap = { version = "4.0", optional = true }
4242
irx-config = { version = "=3.3.0", features = [
4343
"cmd",
4444
"toml-parser",
45+
"yaml",
4546
], optional = true }
4647
env_logger = { version = "0.11", optional = true }
4748
inflections = "1.1"

src/config.rs

+8-49
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ pub struct Config {
3636
pub field_names_for_enums: bool,
3737
pub base_address_shift: u64,
3838
pub html_url: Option<url::Url>,
39-
#[cfg(feature = "unstable-riscv")]
40-
pub riscv_config: Option<RiscvConfig>,
39+
/// Path to YAML file with chip-specific settings
40+
pub settings: Option<PathBuf>,
4141
}
4242

4343
#[allow(clippy::upper_case_acronyms)]
@@ -315,56 +315,15 @@ pub enum IdentFormatsTheme {
315315
Legacy,
316316
}
317317

318-
#[cfg(feature = "unstable-riscv")]
319-
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
320-
#[derive(Clone, PartialEq, Eq, Debug, Default)]
321-
#[non_exhaustive]
322-
pub struct RiscvConfig {
323-
pub core_interrupts: Option<Vec<RiscvEnumItem>>,
324-
pub exceptions: Option<Vec<RiscvEnumItem>>,
325-
pub priorities: Option<Vec<RiscvEnumItem>>,
326-
pub harts: Option<Vec<RiscvEnumItem>>,
327-
pub clint: Option<RiscvClintConfig>,
328-
pub plic: Option<RiscvPlicConfig>,
329-
}
330-
331-
#[cfg(feature = "unstable-riscv")]
332318
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
333319
#[derive(Clone, PartialEq, Eq, Debug, Default)]
334320
#[non_exhaustive]
335-
pub struct RiscvEnumItem {
336-
pub name: String,
337-
pub value: usize,
338-
pub description: Option<String>,
339-
}
340-
341-
#[cfg(feature = "unstable-riscv")]
342-
impl RiscvEnumItem {
343-
pub fn description(&self) -> String {
344-
let description = match &self.description {
345-
Some(d) => d,
346-
None => &self.name,
347-
};
348-
format!("{} - {}", self.value, description)
349-
}
350-
}
351-
352-
#[cfg(feature = "unstable-riscv")]
353-
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
354-
#[derive(Clone, PartialEq, Eq, Debug, Default)]
355-
#[non_exhaustive]
356-
pub struct RiscvClintConfig {
357-
pub name: String,
358-
pub freq: Option<usize>,
359-
pub async_delay: bool,
321+
/// Chip-specific settings
322+
pub struct Settings {
323+
#[cfg(feature = "unstable-riscv")]
324+
/// RISC-V specific settings
325+
pub riscv_config: Option<riscv::RiscvConfig>,
360326
}
361327

362328
#[cfg(feature = "unstable-riscv")]
363-
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
364-
#[derive(Clone, PartialEq, Eq, Debug, Default)]
365-
#[non_exhaustive]
366-
pub struct RiscvPlicConfig {
367-
pub name: String,
368-
pub core_interrupt: Option<String>,
369-
pub hart_id: Option<String>,
370-
}
329+
pub mod riscv;

src/config/riscv.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
2+
#[derive(Clone, PartialEq, Eq, Debug, Default)]
3+
#[non_exhaustive]
4+
pub struct RiscvConfig {
5+
pub core_interrupts: Vec<RiscvEnumItem>,
6+
pub exceptions: Vec<RiscvEnumItem>,
7+
pub priorities: Vec<RiscvEnumItem>,
8+
pub harts: Vec<RiscvEnumItem>,
9+
pub clint: Option<RiscvClintConfig>,
10+
pub plic: Option<RiscvPlicConfig>,
11+
}
12+
13+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
14+
#[derive(Clone, PartialEq, Eq, Debug, Default)]
15+
#[non_exhaustive]
16+
pub struct RiscvEnumItem {
17+
pub name: String,
18+
pub value: usize,
19+
pub description: Option<String>,
20+
}
21+
22+
impl RiscvEnumItem {
23+
pub fn description(&self) -> String {
24+
let description = match &self.description {
25+
Some(d) => d,
26+
None => &self.name,
27+
};
28+
format!("{} - {}", self.value, description)
29+
}
30+
}
31+
32+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
33+
#[derive(Clone, PartialEq, Eq, Debug, Default)]
34+
#[non_exhaustive]
35+
pub struct RiscvClintConfig {
36+
pub name: String,
37+
pub freq: Option<usize>,
38+
pub async_delay: bool,
39+
}
40+
41+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
42+
#[derive(Clone, PartialEq, Eq, Debug, Default)]
43+
#[non_exhaustive]
44+
pub struct RiscvPlicConfig {
45+
pub name: String,
46+
pub core_interrupt: Option<String>,
47+
pub hart_id: Option<String>,
48+
}

src/generate/device.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::fs::File;
77
use std::io::Write;
88
use std::path::Path;
99

10-
use crate::config::{Config, Target};
10+
use crate::config::{Config, Settings, Target};
1111
use crate::util::{self, ident};
1212
use anyhow::{Context, Result};
1313

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

33+
let _settings = match config.settings.as_ref() {
34+
Some(settings) => {
35+
let file = std::fs::read_to_string(settings).context("could not read settings file")?;
36+
serde_yaml::from_str(&file).context("could not parse settings file")?
37+
}
38+
None => Settings::default(),
39+
};
40+
3341
if config.target == Target::Msp430 {
3442
out.extend(quote! {
3543
#![feature(abi_msp430_interrupt)]
@@ -193,7 +201,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
193201
#[cfg(feature = "unstable-riscv")]
194202
Target::RISCV => {
195203
debug!("Rendering RISC-V specific code");
196-
out.extend(riscv::render(&d.peripherals, device_x, config)?);
204+
out.extend(riscv::render(&d.peripherals, device_x, &_settings)?);
197205
}
198206
_ => {
199207
debug!("Rendering interrupts");
@@ -215,7 +223,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
215223
continue;
216224
}
217225
#[cfg(feature = "unstable-riscv")]
218-
if config.target == Target::RISCV && riscv::is_riscv_peripheral(p, config) {
226+
if config.target == Target::RISCV && riscv::is_riscv_peripheral(p, &_settings) {
219227
// RISC-V specific peripherals are handled above
220228
continue;
221229
}

src/generate/riscv.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use crate::{svd::Peripheral, util, Config};
1+
use crate::{svd::Peripheral, util, Settings};
22
use anyhow::Result;
33
use log::debug;
44
use proc_macro2::TokenStream;
55
use quote::quote;
66
use std::{collections::HashMap, fmt::Write, str::FromStr};
77

8-
pub fn is_riscv_peripheral(p: &Peripheral, c: &Config) -> bool {
8+
pub fn is_riscv_peripheral(p: &Peripheral, s: &Settings) -> bool {
99
// TODO cleaner implementation of this
10-
match &c.riscv_config {
10+
match &s.riscv_config {
1111
Some(c) => {
1212
c.clint.as_ref().is_some_and(|clint| clint.name == p.name)
1313
|| c.plic.as_ref().is_some_and(|plic| plic.name == p.name)
@@ -20,16 +20,16 @@ pub fn is_riscv_peripheral(p: &Peripheral, c: &Config) -> bool {
2020
pub fn render(
2121
peripherals: &[Peripheral],
2222
device_x: &mut String,
23-
config: &Config,
23+
settings: &Settings,
2424
) -> Result<TokenStream> {
2525
let mut mod_items = TokenStream::new();
2626

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

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

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

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

207207
let mut riscv_peripherals = TokenStream::new();
208-
if let Some(c) = &config.riscv_config {
209-
let harts = match &c.harts {
210-
Some(harts) => harts
208+
if let Some(c) = &settings.riscv_config {
209+
let harts = match c.harts.is_empty() {
210+
true => vec![],
211+
false => c
212+
.harts
211213
.iter()
212214
.map(|h| (TokenStream::from_str(&h.name).unwrap(), h.value))
213215
.collect::<Vec<_>>(),
214-
None => vec![],
215216
};
216217
if let Some(clint) = &c.clint {
217218
let p = peripherals.iter().find(|&p| p.name == clint.name).unwrap();
@@ -286,7 +287,7 @@ pub fn render(
286287
fn plic_handler() {
287288
let claim = crate::PLIC::#ctx.claim();
288289
if let Some(s) = claim.claim::<ExternalInterrupt>() {
289-
unsafe { _dispatch_core_interrupt(s.number()) }
290+
unsafe { _dispatch_external_interrupt(s.number()) }
290291
claim.complete(s);
291292
}
292293
}

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ pub mod config;
597597
pub mod generate;
598598
pub mod util;
599599

600-
pub use config::{Config, Target};
600+
pub use config::{Config, Settings, Target};
601601

602602
#[non_exhaustive]
603603
pub struct Generation {

src/main.rs

+8-26
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#![recursion_limit = "128"]
22

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

@@ -20,8 +18,6 @@ use svd2rust::{
2018
};
2119

2220
fn parse_configs(app: Command) -> Result<Config> {
23-
#[cfg(feature = "unstable-riscv")]
24-
use irx_config::parsers::yaml;
2521
use irx_config::parsers::{cmd, toml};
2622
use irx_config::ConfigBuilder;
2723
let ident_formats = app.clone().get_matches();
@@ -34,23 +30,11 @@ fn parse_configs(app: Command) -> Result<Config> {
3430
.ignore_missing_file(true)
3531
.build()?,
3632
);
37-
#[cfg(feature = "unstable-riscv")]
38-
let irxconfig = irxconfig.append_parser(
39-
yaml::ParserBuilder::default()
40-
.default_path("riscv.yaml")
41-
.path_option("riscv_cfg")
42-
.ignore_missing_file(true)
43-
.build()?,
44-
);
33+
4534
let irxconfig = irxconfig.load()?;
4635

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

49-
#[cfg(feature = "unstable-riscv")]
50-
if let Ok(riscv_config) = irxconfig.get::<RiscvConfig>() {
51-
config.riscv_config = Some(riscv_config);
52-
}
53-
5438
let mut idf = match config.ident_formats_theme {
5539
Some(IdentFormatsTheme::Legacy) => IdentFormats::legacy_theme(),
5640
_ => IdentFormats::default_theme(),
@@ -116,6 +100,13 @@ fn run() -> Result<()> {
116100
.action(ArgAction::Set)
117101
.value_name("TOML_FILE"),
118102
)
103+
.arg(
104+
Arg::new("settings")
105+
.long("settings")
106+
.help("Target-specific settings YAML file")
107+
.action(ArgAction::Set)
108+
.value_name("YAML_FILE"),
109+
)
119110
.arg(
120111
Arg::new("target")
121112
.long("target")
@@ -308,15 +299,6 @@ Ignore this option if you are not building your own FPGA based soft-cores."),
308299
env!("CARGO_PKG_VERSION"),
309300
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
310301
));
311-
#[cfg(feature = "unstable-riscv")]
312-
let app = app.arg(
313-
Arg::new("riscv_cfg")
314-
.long("riscv_config")
315-
.help("RISC-V Config YAML file")
316-
.short('r')
317-
.action(ArgAction::Set)
318-
.value_name("YAML_FILE"),
319-
);
320302

321303
let mut config = match parse_configs(app) {
322304
Ok(config) => {

0 commit comments

Comments
 (0)