Skip to content

Commit 787473f

Browse files
committed
proof of concept: using config parameters only
1 parent eac74d5 commit 787473f

File tree

3 files changed

+138
-145
lines changed

3 files changed

+138
-145
lines changed

src/config.rs

+45-3
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ pub struct Config {
3737
pub base_address_shift: u64,
3838
pub html_url: Option<url::Url>,
3939
#[cfg(feature = "unstable-riscv")]
40-
pub use_riscv_peripheral: bool,
41-
#[cfg(feature = "unstable-riscv")]
42-
pub riscv_clint_freq: Option<u64>,
40+
pub riscv_config: Option<RiscvConfig>,
4341
}
4442

4543
#[allow(clippy::upper_case_acronyms)]
@@ -316,3 +314,47 @@ impl DerefMut for IdentFormats {
316314
pub enum IdentFormatsTheme {
317315
Legacy,
318316
}
317+
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<String>,
329+
}
330+
331+
#[cfg(feature = "unstable-riscv")]
332+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
333+
#[derive(Clone, PartialEq, Eq, Debug, Default)]
334+
#[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,
360+
}

src/generate/device.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
193193
#[cfg(feature = "unstable-riscv")]
194194
Target::RISCV => {
195195
debug!("Rendering RISC-V specific code");
196-
out.extend(riscv::render(
197-
d.riscv.as_ref(),
198-
&d.peripherals,
199-
device_x,
200-
config,
201-
)?);
196+
out.extend(riscv::render(&d.peripherals, device_x, config)?);
202197
}
203198
_ => {
204199
debug!("Rendering interrupts");
@@ -220,10 +215,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
220215
continue;
221216
}
222217
#[cfg(feature = "unstable-riscv")]
223-
if config.target == Target::RISCV
224-
&& config.use_riscv_peripheral
225-
&& riscv::is_riscv_peripheral(p)
226-
{
218+
if config.target == Target::RISCV && riscv::is_riscv_peripheral(p, config) {
227219
// RISC-V specific peripherals are handled above
228220
continue;
229221
}

src/generate/riscv.rs

+91-132
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,38 @@
1-
use crate::{
2-
svd::{Peripheral, Riscv},
3-
util, Config,
4-
};
1+
use crate::{svd::Peripheral, util, Config};
52
use anyhow::Result;
63
use log::debug;
74
use proc_macro2::TokenStream;
85
use quote::quote;
96
use std::{collections::HashMap, fmt::Write, str::FromStr};
107

11-
pub fn is_riscv_peripheral(p: &Peripheral) -> bool {
12-
["PLIC", "CLINT"].contains(&p.name.to_uppercase().as_ref())
8+
pub fn is_riscv_peripheral(p: &Peripheral, c: &Config) -> bool {
9+
// TODO cleaner implementation of this
10+
match &c.riscv_config {
11+
Some(c) => {
12+
c.clint.as_ref().is_some_and(|clint| clint.name == p.name)
13+
|| c.plic.as_ref().is_some_and(|plic| plic == &p.name)
14+
}
15+
_ => false,
16+
}
1317
}
1418

1519
/// Whole RISC-V generation
1620
pub fn render(
17-
r: Option<&Riscv>,
1821
peripherals: &[Peripheral],
1922
device_x: &mut String,
2023
config: &Config,
2124
) -> Result<TokenStream> {
2225
let mut mod_items = TokenStream::new();
2326

24-
if let Some(r) = r {
25-
if !r.core_interrupts.is_empty() {
27+
if let Some(c) = config.riscv_config.as_ref() {
28+
if let Some(i) = c.core_interrupts.as_ref() {
2629
debug!("Rendering target-specific core interrupts");
2730
writeln!(device_x, "/* Core interrupt sources and trap handlers */")?;
2831
let mut interrupts = vec![];
29-
for i in r.core_interrupts.iter() {
30-
let name = TokenStream::from_str(&i.name).unwrap();
31-
let value = TokenStream::from_str(&format!("{}", i.value)).unwrap();
32-
let description = format!(
33-
"{} - {}",
34-
i.value,
35-
i.description
36-
.as_ref()
37-
.map(|s| util::respace(s))
38-
.as_ref()
39-
.map(|s| util::escape_special_chars(s))
40-
.unwrap_or_else(|| i.name.clone())
41-
);
32+
for interrupt in i.iter() {
33+
let name = TokenStream::from_str(&interrupt.name).unwrap();
34+
let value = TokenStream::from_str(&format!("{}", interrupt.value)).unwrap();
35+
let description = interrupt.description();
4236

4337
writeln!(device_x, "PROVIDE({name} = DefaultHandler);")?;
4438
writeln!(
@@ -64,23 +58,14 @@ pub fn render(
6458
mod_items.extend(quote! {pub use riscv::interrupt::Interrupt as CoreInterrupt;});
6559
}
6660

67-
if !r.exceptions.is_empty() {
61+
if let Some(e) = c.exceptions.as_ref() {
6862
debug!("Rendering target-specific exceptions");
6963
writeln!(device_x, "/* Exception sources */")?;
7064
let mut exceptions = vec![];
71-
for e in r.exceptions.iter() {
72-
let name = TokenStream::from_str(&e.name).unwrap();
73-
let value = TokenStream::from_str(&format!("{}", e.value)).unwrap();
74-
let description = format!(
75-
"{} - {}",
76-
e.value,
77-
e.description
78-
.as_ref()
79-
.map(|s| util::respace(s))
80-
.as_ref()
81-
.map(|s| util::escape_special_chars(s))
82-
.unwrap_or_else(|| e.name.clone())
83-
);
65+
for exception in e.iter() {
66+
let name = TokenStream::from_str(&exception.name).unwrap();
67+
let value = TokenStream::from_str(&format!("{}", exception.value)).unwrap();
68+
let description = exception.description();
8469

8570
writeln!(device_x, "PROVIDE({name} = ExceptionHandler);")?;
8671

@@ -102,21 +87,12 @@ pub fn render(
10287
mod_items.extend(quote! { pub use riscv::interrupt::Exception; });
10388
}
10489

105-
if !r.priorities.is_empty() {
90+
if let Some(p) = c.priorities.as_ref() {
10691
debug!("Rendering target-specific priority levels");
107-
let priorities = r.priorities.iter().map(|p| {
108-
let name = TokenStream::from_str(&p.name).unwrap();
109-
let value = TokenStream::from_str(&format!("{}", p.value)).unwrap();
110-
let description = format!(
111-
"{} - {}",
112-
p.value,
113-
p.description
114-
.as_ref()
115-
.map(|s| util::respace(s))
116-
.as_ref()
117-
.map(|s| util::escape_special_chars(s))
118-
.unwrap_or_else(|| p.name.clone())
119-
);
92+
let priorities = p.iter().map(|priority| {
93+
let name = TokenStream::from_str(&priority.name).unwrap();
94+
let value = TokenStream::from_str(&format!("{}", priority.value)).unwrap();
95+
let description = priority.description();
12096

12197
quote! {
12298
#[doc = #description]
@@ -133,21 +109,12 @@ pub fn render(
133109
});
134110
}
135111

136-
if !r.harts.is_empty() {
112+
if let Some(h) = c.harts.as_ref() {
137113
debug!("Rendering target-specific HART IDs");
138-
let harts = r.harts.iter().map(|h| {
139-
let name = TokenStream::from_str(&h.name).unwrap();
140-
let value = TokenStream::from_str(&format!("{}", h.value)).unwrap();
141-
let description = format!(
142-
"{} - {}",
143-
h.value,
144-
h.description
145-
.as_ref()
146-
.map(|s| util::respace(s))
147-
.as_ref()
148-
.map(|s| util::escape_special_chars(s))
149-
.unwrap_or_else(|| h.name.clone())
150-
);
114+
let harts = h.iter().map(|hart| {
115+
let name = TokenStream::from_str(&hart.name).unwrap();
116+
let value = TokenStream::from_str(&format!("{}", hart.value)).unwrap();
117+
let description = hart.description();
151118

152119
quote! {
153120
#[doc = #description]
@@ -238,80 +205,72 @@ pub fn render(
238205
}
239206

240207
let mut riscv_peripherals = TokenStream::new();
241-
if config.use_riscv_peripheral {
242-
let harts = match r {
243-
Some(r) => r
244-
.harts
208+
if let Some(c) = &config.riscv_config {
209+
let harts = match &c.harts {
210+
Some(harts) => harts
245211
.iter()
246-
.map(|h| {
247-
let name = TokenStream::from_str(&h.name).unwrap();
248-
let value = h.value;
249-
(name, value)
250-
})
212+
.map(|h| (TokenStream::from_str(&h.name).unwrap(), h.value))
251213
.collect::<Vec<_>>(),
252214
None => vec![],
253215
};
254-
for p in peripherals.iter() {
255-
match p.name.to_uppercase().as_ref() {
256-
"PLIC" => {
257-
let base =
258-
TokenStream::from_str(&format!("base 0x{:X},", p.base_address)).unwrap();
259-
let ctxs = harts
260-
.iter()
261-
.map(|(name, value)| {
262-
let ctx_name = TokenStream::from_str(&format!("ctx{value}")).unwrap();
263-
let doc = format!("[{value}](crate::interrupt::Hart::{name})");
264-
quote! {#ctx_name = (crate::interrupt::Hart::#name, #doc)}
265-
})
266-
.collect::<Vec<_>>();
267-
let ctxs = match ctxs.len() {
268-
0 => quote! {},
269-
_ => quote! {ctxs [ #(#ctxs),* ],},
270-
};
216+
if let Some(clint) = &c.clint {
217+
let p = peripherals.iter().find(|&p| p.name == clint.name).unwrap();
218+
let base = TokenStream::from_str(&format!("base 0x{:X},", p.base_address)).unwrap();
219+
let freq = match clint.freq {
220+
Some(clk) => match clint.async_delay {
221+
true => TokenStream::from_str(&format!("freq {clk}, async_delay,")).unwrap(),
222+
false => TokenStream::from_str(&format!("freq {clk},")).unwrap(),
223+
},
224+
None => quote! {},
225+
};
226+
let mtimecmps = harts
227+
.iter()
228+
.map(|(name, value)| {
229+
let mtimecmp_name = TokenStream::from_str(&format!("mtimecmp{value}")).unwrap();
230+
let doc = format!("[{value}](crate::interrupt::Hart::{name})");
231+
quote! {#mtimecmp_name = (crate::interrupt::Hart::#name, #doc)}
232+
})
233+
.collect::<Vec<_>>();
234+
let mtimecmps = match mtimecmps.len() {
235+
0 => quote! {},
236+
_ => quote! {mtimecmps [ #(#mtimecmps),* ],},
237+
};
238+
let msips = harts
239+
.iter()
240+
.map(|(name, value)| {
241+
let msip_name = TokenStream::from_str(&format!("msip{value}")).unwrap();
242+
let doc = format!("[{value}](crate::interrupt::Hart::{name})");
243+
quote! {#msip_name = (crate::interrupt::Hart::#name, #doc)}
244+
})
245+
.collect::<Vec<_>>();
246+
let msips = match msips.len() {
247+
0 => quote! {},
248+
_ => quote! {msips [ #(#msips),* ],},
249+
};
271250

272-
riscv_peripherals.extend(quote! {
273-
riscv_peripheral::plic_codegen!(#base #ctxs);
274-
});
275-
}
276-
"CLINT" => {
277-
let base =
278-
TokenStream::from_str(&format!("base 0x{:X},", p.base_address)).unwrap();
279-
let freq = match config.riscv_clint_freq {
280-
Some(clk) => TokenStream::from_str(&format!("freq {clk},")).unwrap(),
281-
None => quote! {},
282-
};
283-
let mtimecmps = harts
284-
.iter()
285-
.map(|(name, value)| {
286-
let mtimecmp_name =
287-
TokenStream::from_str(&format!("mtimecmp{value}")).unwrap();
288-
let doc = format!("[{value}](crate::interrupt::Hart::{name})");
289-
quote! {#mtimecmp_name = (crate::interrupt::Hart::#name, #doc)}
290-
})
291-
.collect::<Vec<_>>();
292-
let mtimecmps = match mtimecmps.len() {
293-
0 => quote! {},
294-
_ => quote! {mtimecmps [ #(#mtimecmps),* ],},
295-
};
296-
let msips = harts
297-
.iter()
298-
.map(|(name, value)| {
299-
let msip_name = TokenStream::from_str(&format!("msip{value}")).unwrap();
300-
let doc = format!("[{value}](crate::interrupt::Hart::{name})");
301-
quote! {#msip_name = (crate::interrupt::Hart::#name, #doc)}
302-
})
303-
.collect::<Vec<_>>();
304-
let msips = match msips.len() {
305-
0 => quote! {},
306-
_ => quote! {msips [ #(#msips),* ],},
307-
};
251+
riscv_peripherals.extend(quote! {
252+
riscv_peripheral::clint_codegen!(#base #freq #mtimecmps #msips);
253+
});
254+
}
255+
if let Some(plic) = &c.plic {
256+
let p = peripherals.iter().find(|&p| &p.name == plic).unwrap();
257+
let base = TokenStream::from_str(&format!("base 0x{:X},", p.base_address)).unwrap();
258+
let ctxs = harts
259+
.iter()
260+
.map(|(name, value)| {
261+
let ctx_name = TokenStream::from_str(&format!("ctx{value}")).unwrap();
262+
let doc = format!("[{value}](crate::interrupt::Hart::{name})");
263+
quote! {#ctx_name = (crate::interrupt::Hart::#name, #doc)}
264+
})
265+
.collect::<Vec<_>>();
266+
let ctxs = match ctxs.len() {
267+
0 => quote! {},
268+
_ => quote! {ctxs [ #(#ctxs),* ],},
269+
};
308270

309-
riscv_peripherals.extend(quote! {
310-
riscv_peripheral::clint_codegen!(#base #freq #mtimecmps #msips);
311-
});
312-
}
313-
_ => {}
314-
}
271+
riscv_peripherals.extend(quote! {
272+
riscv_peripheral::plic_codegen!(#base #ctxs);
273+
});
315274
}
316275
}
317276

0 commit comments

Comments
 (0)