Skip to content

Commit f4376aa

Browse files
authored
Merge pull request #265 from romancardenas/master
Add `riscv` section for RISC-V targets
2 parents 8194739 + ddc3d99 commit f4376aa

20 files changed

+827
-0
lines changed

svd-encoder/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## Unreleased
99

10+
- Add `riscv` element for configuration parameters related to RISC-V targets.
11+
You must use the `unstable-riscv` feature to enable this exeperimental element.
1012
- Bump MSRV to 1.65.0
1113

1214
## [v0.14.3] - 2023-11-15

svd-encoder/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ rust-version = "1.65.0"
1111
version = "0.14.4"
1212
readme = "README.md"
1313

14+
[features]
15+
unstable-riscv = ["svd-rs/unstable-riscv"]
16+
1417
[dependencies]
1518
convert_case = "0.6.0"
1619
svd-rs = { version = "0.14.7", path = "../svd-rs" }

svd-encoder/src/device.rs

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ impl Encode for Device {
3434
elem.children.push(new_node("licenseText", v.clone()));
3535
}
3636

37+
#[cfg(feature = "unstable-riscv")]
38+
if let Some(v) = &self.riscv {
39+
elem.children
40+
.push(XMLNode::Element(v.encode_with_config(config)?));
41+
}
42+
3743
if let Some(v) = &self.cpu {
3844
elem.children
3945
.push(XMLNode::Element(v.encode_with_config(config)?));

svd-encoder/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,7 @@ mod readaction;
103103
mod register;
104104
mod registercluster;
105105
mod registerproperties;
106+
#[cfg(feature = "unstable-riscv")]
107+
mod riscv;
106108
mod usage;
107109
mod writeconstraint;

svd-encoder/src/riscv.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use super::{new_node, Config, Element, Encode, EncodeError, XMLNode};
2+
use crate::svd::riscv::{Hart, Priority, Riscv};
3+
4+
impl Encode for Riscv {
5+
type Error = EncodeError;
6+
7+
fn encode_with_config(&self, config: &Config) -> Result<Element, EncodeError> {
8+
let mut elem = Element::new("riscv");
9+
10+
if !self.core_interrupts.is_empty() {
11+
let mut interrupts = Element::new("coreInterrupts");
12+
for interrupt in &self.core_interrupts {
13+
interrupts
14+
.children
15+
.push(interrupt.encode_node_with_config(config)?);
16+
}
17+
elem.children.push(XMLNode::Element(interrupts));
18+
}
19+
if !self.priorities.is_empty() {
20+
let mut priorities = Element::new("priorities");
21+
for priority in &self.priorities {
22+
priorities
23+
.children
24+
.push(priority.encode_node_with_config(config)?);
25+
}
26+
elem.children.push(XMLNode::Element(priorities));
27+
}
28+
if !self.harts.is_empty() {
29+
let mut harts = Element::new("harts");
30+
for hart in &self.harts {
31+
harts.children.push(hart.encode_node_with_config(config)?);
32+
}
33+
elem.children.push(XMLNode::Element(harts));
34+
}
35+
36+
Ok(elem)
37+
}
38+
}
39+
40+
impl Encode for Priority {
41+
type Error = EncodeError;
42+
43+
fn encode_with_config(&self, _config: &Config) -> Result<Element, EncodeError> {
44+
let mut children = vec![new_node("name", self.name.clone())];
45+
if let Some(desc) = &self.description {
46+
children.push(new_node("description", desc.clone()));
47+
}
48+
children.push(new_node("value", format!("{}", self.value)));
49+
50+
let mut elem = Element::new("priority");
51+
elem.children = children;
52+
Ok(elem)
53+
}
54+
}
55+
56+
impl Encode for Hart {
57+
type Error = EncodeError;
58+
59+
fn encode_with_config(&self, _config: &Config) -> Result<Element, EncodeError> {
60+
let mut children = vec![new_node("name", self.name.clone())];
61+
if let Some(desc) = &self.description {
62+
children.push(new_node("description", desc.clone()));
63+
}
64+
children.push(new_node("value", format!("{}", self.value)));
65+
66+
let mut elem = Element::new("hart");
67+
elem.children = children;
68+
Ok(elem)
69+
}
70+
}

svd-parser/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## Unreleased
99

10+
- Add `riscv` element for configuration parameters related to RISC-V targets.
11+
You must use the `unstable-riscv` feature to enable this exeperimental element.
1012
- Bump MSRV to 1.65.0
1113

1214
## [v0.14.5] - 2024-01-03

svd-parser/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ readme = "README.md"
1717
[features]
1818
derive-from = ["svd-rs/derive-from"]
1919
expand = ["derive-from"]
20+
unstable-riscv = ["svd-rs/unstable-riscv"]
2021

2122
[dependencies]
2223
svd-rs = { version = "0.14.7", path = "../svd-rs" }

svd-parser/src/device.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use super::*;
2+
#[cfg(feature = "unstable-riscv")]
3+
use crate::svd::riscv::Riscv;
24
use crate::svd::{cpu::Cpu, peripheral::Peripheral, registerproperties::RegisterProperties};
35

46
/// Parses a SVD file
@@ -31,6 +33,10 @@ impl Parse for Device {
3133
.collect();
3234
ps?
3335
});
36+
#[cfg(feature = "unstable-riscv")]
37+
if let Some(riscv) = optional::<Riscv>("riscv", tree, config)? {
38+
device = device.riscv(riscv);
39+
}
3440
if let Some(version) = tree.get_child_text_opt("version")? {
3541
device = device.version(version)
3642
}

svd-parser/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ mod readaction;
211211
mod register;
212212
mod registercluster;
213213
mod registerproperties;
214+
#[cfg(feature = "unstable-riscv")]
215+
mod riscv;
214216
mod usage;
215217
mod writeconstraint;
216218

svd-parser/src/riscv.rs

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use super::*;
2+
use crate::svd::riscv::{Hart, Interrupt, Priority, Riscv};
3+
4+
impl Parse for Riscv {
5+
type Object = Self;
6+
type Error = SVDErrorAt;
7+
type Config = Config;
8+
9+
fn parse(tree: &Node, config: &Config) -> Result<Self, Self::Error> {
10+
if !tree.has_tag_name("riscv") {
11+
return Err(SVDError::NotExpectedTag("riscv".to_string()).at(tree.id()));
12+
}
13+
14+
let mut builder = Riscv::builder();
15+
16+
if let Some(interrupts) = tree.get_child("coreInterrupts") {
17+
let interrupts: Result<Vec<_>, _> = interrupts
18+
.children()
19+
.filter(|t| t.is_element() && t.has_tag_name("interrupt"))
20+
.map(|i| Interrupt::parse(&i, config))
21+
.collect();
22+
builder = builder.core_interrupts(interrupts?);
23+
}
24+
25+
if let Some(priorities) = tree.get_child("priorities") {
26+
let priorities: Result<Vec<_>, _> = priorities
27+
.children()
28+
.filter(|t| t.is_element() && t.has_tag_name("priority"))
29+
.map(|i| Priority::parse(&i, config))
30+
.collect();
31+
builder = builder.priorities(priorities?);
32+
};
33+
34+
if let Some(harts) = tree.get_child("harts") {
35+
let harts: Result<Vec<_>, _> = harts
36+
.children()
37+
.filter(|t| t.is_element() && t.has_tag_name("hart"))
38+
.map(|i| Hart::parse(&i, config))
39+
.collect();
40+
builder = builder.harts(harts?);
41+
};
42+
43+
builder
44+
.build(config.validate_level)
45+
.map_err(|e| SVDError::from(e).at(tree.id()))
46+
}
47+
}
48+
49+
impl Parse for Priority {
50+
type Object = Self;
51+
type Error = SVDErrorAt;
52+
type Config = Config;
53+
54+
fn parse(tree: &Node, config: &Config) -> Result<Self, Self::Error> {
55+
if !tree.has_tag_name("priority") {
56+
return Err(SVDError::NotExpectedTag("priority".to_string()).at(tree.id()));
57+
}
58+
59+
Priority::builder()
60+
.name(tree.get_child_text("name")?)
61+
.description(tree.get_child_text_opt("description")?)
62+
.value(tree.get_child_u32("value")?)
63+
.build(config.validate_level)
64+
.map_err(|e| SVDError::from(e).at(tree.id()))
65+
}
66+
}
67+
68+
impl Parse for Hart {
69+
type Object = Self;
70+
type Error = SVDErrorAt;
71+
type Config = Config;
72+
73+
fn parse(tree: &Node, config: &Config) -> Result<Self, Self::Error> {
74+
if !tree.has_tag_name("hart") {
75+
return Err(SVDError::NotExpectedTag("hart".to_string()).at(tree.id()));
76+
}
77+
78+
Hart::builder()
79+
.name(tree.get_child_text("name")?)
80+
.description(tree.get_child_text_opt("description")?)
81+
.value(tree.get_child_u32("value")?)
82+
.build(config.validate_level)
83+
.map_err(|e| SVDError::from(e).at(tree.id()))
84+
}
85+
}

svd-rs/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## Unreleased
99

10+
- Add `riscv` element for configuration parameters related to RISC-V targets.
11+
You must use the `unstable-riscv` feature to enable this exeperimental element.
1012
- Add `DataType`
1113

1214
## [v0.14.8] - 2024-02-13

svd-rs/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ readme = "README.md"
1515

1616
[features]
1717
derive-from = []
18+
unstable-riscv = []
1819

1920
[dependencies]
2021
thiserror = "1.0.31"

svd-rs/src/device.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(feature = "unstable-riscv")]
2+
use super::Riscv;
13
use super::{
24
BuildError, Cpu, Description, EmptyToNone, Name, Peripheral, RegisterProperties, SvdError,
35
ValidateLevel,
@@ -105,6 +107,14 @@ pub struct Device {
105107
/// Specify the compliant CMSIS-SVD schema version
106108
#[cfg_attr(feature = "serde", serde(skip, default = "default_schema_version"))]
107109
pub schema_version: String,
110+
111+
/// Describe the processor included in the device
112+
#[cfg_attr(
113+
feature = "serde",
114+
serde(default, skip_serializing_if = "Option::is_none")
115+
)]
116+
#[cfg(feature = "unstable-riscv")]
117+
pub riscv: Option<Riscv>,
108118
}
109119

110120
fn default_xmlns_xs() -> String {
@@ -130,6 +140,8 @@ pub struct DeviceBuilder {
130140
version: Option<String>,
131141
description: Option<String>,
132142
license_text: Option<String>,
143+
#[cfg(feature = "unstable-riscv")]
144+
riscv: Option<Riscv>,
133145
cpu: Option<Cpu>,
134146
header_system_filename: Option<String>,
135147
header_definitions_prefix: Option<String>,
@@ -152,6 +164,8 @@ impl From<Device> for DeviceBuilder {
152164
version: Some(d.version),
153165
description: Some(d.description),
154166
license_text: d.license_text,
167+
#[cfg(feature = "unstable-riscv")]
168+
riscv: d.riscv,
155169
cpu: d.cpu,
156170
header_system_filename: d.header_system_filename,
157171
header_definitions_prefix: d.header_definitions_prefix,
@@ -202,6 +216,12 @@ impl DeviceBuilder {
202216
self.license_text = value;
203217
self
204218
}
219+
/// Set the riscv of the device.
220+
#[cfg(feature = "unstable-riscv")]
221+
pub fn riscv(mut self, value: Riscv) -> Self {
222+
self.riscv = Some(value);
223+
self
224+
}
205225
/// Set the cpu of the device.
206226
pub fn cpu(mut self, value: Option<Cpu>) -> Self {
207227
self.cpu = value;
@@ -283,6 +303,8 @@ impl DeviceBuilder {
283303
})
284304
.ok_or_else(|| BuildError::Uninitialized("description".to_string()))?,
285305
license_text: self.license_text,
306+
#[cfg(feature = "unstable-riscv")]
307+
riscv: self.riscv,
286308
cpu: self.cpu,
287309
header_system_filename: self.header_system_filename,
288310
header_definitions_prefix: self.header_definitions_prefix,
@@ -341,6 +363,10 @@ impl Device {
341363
if builder.license_text.is_some() {
342364
self.license_text = builder.license_text.empty_to_none();
343365
}
366+
#[cfg(feature = "unstable-riscv")]
367+
if builder.riscv.is_some() {
368+
self.riscv = builder.riscv;
369+
}
344370
if builder.cpu.is_some() {
345371
self.cpu = builder.cpu;
346372
}

svd-rs/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ pub use self::protection::Protection;
9494
pub mod datatype;
9595
pub use self::datatype::DataType;
9696

97+
/// Custom objects for the RISC-V ecosystem
98+
#[cfg(feature = "unstable-riscv")]
99+
pub mod riscv;
100+
#[cfg(feature = "unstable-riscv")]
101+
pub use self::riscv::Riscv;
102+
97103
/// Level of validation
98104
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
99105
pub enum ValidateLevel {

0 commit comments

Comments
 (0)