Skip to content

[WIP] Adding encode functions to SVD elements #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c2a13da
Split out endian + added encode function
ryankurte Aug 8, 2017
9c7f2fb
Split access, added encode and tests
ryankurte Aug 8, 2017
c252c1a
Split usage, added encode and tests
ryankurte Aug 8, 2017
2d36b81
Whoops, added files
ryankurte Aug 8, 2017
eea653b
Added encoding to enumerated values
ryankurte Aug 8, 2017
b3d4ba4
Split Defaults + added encode_children function
ryankurte Aug 12, 2017
ee4a8a1
Splitting writeconstraint/writeconstraintrange.
ryankurte Aug 13, 2017
ceb577c
Bitranges, yeeeeaah
ryankurte Aug 16, 2017
2abbdfd
Interrupt module
ryankurte Aug 17, 2017
0eebd41
Split field and register, haven't implemented encode or tests yet.
ryankurte Aug 22, 2017
8e248d5
Registerinfo tests
ryankurte Aug 22, 2017
87b078e
Playing with lossless uint encoding/decoding type
ryankurte Aug 22, 2017
89094bb
Playing with lossless uint encoding/decoding type
ryankurte Aug 22, 2017
ed68e57
Almost there -big sigh-
ryankurte Aug 22, 2017
e543875
Reformatted (with 120 linewidth)
ryankurte Aug 22, 2017
821e11c
Working on e2e tests to make sure encoding works /ok/
ryankurte Aug 29, 2017
6607684
Working on e2e import/export tests
ryankurte Sep 12, 2017
05b9e77
Input/output processing looking pretty close to matching, some differ…
ryankurte Sep 12, 2017
93df472
Added notes on normalising files
ryankurte Sep 12, 2017
ed018a6
Normalising example files, added script to help.
ryankurte Sep 12, 2017
268dea2
Removed examples from repo, should drop LOC lots
ryankurte Sep 12, 2017
d564bd4
Mostly merged
ryankurte Sep 21, 2017
480c796
Refactored out try! macro and renamed to avoid confusion with rust st…
ryankurte Sep 21, 2017
cdbb797
Fixed PartialEq error, moved _extensible to pub(crate)
ryankurte Sep 23, 2017
6638c7b
Cleaning up unused imports etc.
ryankurte Sep 25, 2017
dd34c72
Cleaning up glob imports
ryankurte Sep 25, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ array_layout = "Block"
fn_args_layout = "Block"
fn_call_style = "Block"
generics_indent = "Block"
max_width = 80
max_width = 120
where_style = "Rfc"
write_mode = "overwrite"
Empty file added examples/.keep
Empty file.
21 changes: 21 additions & 0 deletions examples/normalise.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

#End to end tests require some normalisation of files to correct for varying formatting by vendors (because the output format is static).

# Normalise hexadecimal case:
gsed -i 's|\(0x[0-9a-fA-F]*\)|\L\1|g' $1

# Normalise hexadecimal lengths
gsed -i 's|>0x[0]\{1,2\}\([0-9a-f]\{1,2\}\)<|>0x\1<|g' $1

# Swap ST resets to full register width
gsed -i 's|<resetValue>0x00</resetValue>|<resetValue>0x00000000</resetValue>|g' $1

# Swap register sizes from hex to dec
gsed -i 's|<size>0x20</size>|<size>32</size>|g' $1

# Remove displayName props because we don't care
gsed -i 's|\(\s*<displayName>[a-zA-Z0-9]*</displayName>[\r\n]*\)||g' $1

# Remove empty descriptions
gsed -i 's|<description/>||g' $1
85 changes: 85 additions & 0 deletions src/access.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

use std::collections::HashMap;

use xmltree::Element;

use helpers::{ParseElem, EncodeElem};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Access {
ReadOnly,
ReadWrite,
ReadWriteOnce,
WriteOnce,
WriteOnly,
}

impl ParseElem for Access {
fn parse(tree: &Element) -> Access {
let text = try_get_child!(tree.text.as_ref());

match &text[..] {
"read-only" => Access::ReadOnly,
"read-write" => Access::ReadWrite,
"read-writeOnce" => Access::ReadWriteOnce,
"write-only" => Access::WriteOnly,
"writeOnce" => Access::WriteOnce,
_ => panic!("unknown access variant: {}", text),
}
}
}

impl EncodeElem for Access {
fn encode(&self) -> Element {
let text = match *self {
Access::ReadOnly => String::from("read-only"),
Access::ReadWrite => String::from("read-write"),
Access::ReadWriteOnce => String::from("read-writeOnce"),
Access::WriteOnly => String::from("write-only"),
Access::WriteOnce => String::from("writeOnce"),
};

Element {
name: String::from("access"),
attributes: HashMap::new(),
children: Vec::new(),
text: Some(text),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn decode_encode() {
let types = vec![
(Access::ReadOnly, String::from("<access>read-only</access>")),
(
Access::ReadWrite,
String::from("<access>read-write</access>")
),
(
Access::ReadWriteOnce,
String::from("<access>read-writeOnce</access>")
),
(
Access::WriteOnly,
String::from("<access>write-only</access>")
),
(
Access::WriteOnce,
String::from("<access>writeOnce</access>")
),
];

for (a, s) in types {
let tree1 = &try_get_child!(Element::parse(s.as_bytes()));
let access = Access::parse(tree1);
assert_eq!(access, a, "Parsing `{}` expected `{:?}`", s, a);
let tree2 = &access.encode();
assert_eq!(tree1, tree2, "Encoding {:?} expected {}", a, s);
}
}
}
73 changes: 73 additions & 0 deletions src/addressblock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

use std::collections::HashMap;

use xmltree::Element;

use elementext::ElementExt;
use helpers::{ParseElem, EncodeElem, new_element};
use parse;

#[derive(Clone, Debug, PartialEq)]
pub struct AddressBlock {
pub offset: u32,
pub size: u32,
pub usage: String,
}

impl ParseElem for AddressBlock {
fn parse(tree: &Element) -> AddressBlock {
AddressBlock {
offset: try_get_child!(parse::u32(try_get_child!(tree.get_child("offset")))),
size: try_get_child!(parse::u32(try_get_child!(tree.get_child("size")))),
usage: try_get_child!(tree.get_child_text("usage")),
}
}
}

impl EncodeElem for AddressBlock {
fn encode(&self) -> Element {
Element {
name: String::from("addressBlock"),
attributes: HashMap::new(),
children: vec![
new_element("offset", Some(format!("{}", self.offset))),
new_element("size", Some(format!("0x{:08.x}", self.size))),
new_element("usage", Some(self.usage.clone())),
],
text: None,
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn decode_encode() {
let types = vec![
(
AddressBlock {
offset: 0,
size: 0x00000800,
usage: String::from("registers"),
},
String::from(
"<addressBlock>
<offset>0</offset>
<size>0x00000800</size>
<usage>registers</usage>
</addressBlock>",
)
),
];

for (a, s) in types {
let tree1 = &try_get_child!(Element::parse(s.as_bytes()));
let v = AddressBlock::parse(tree1);
assert_eq!(v, a, "Parsing `{}` expected `{:?}`", s, a);
let tree2 = &v.encode();
assert_eq!(tree1, tree2, "Encoding {:?} expected {}", a, s);
}
}
}
146 changes: 146 additions & 0 deletions src/bitrange.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@

use xmltree::Element;

use helpers::{ParseElem, EncodeChildren, new_element};
use parse;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BitRangeType {
BitRange,
OffsetWidth,
MsbLsb,
}

// TODO: reimplement equality
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct BitRange {
pub offset: u32,
pub width: u32,
pub range_type: BitRangeType,
}

impl ParseElem for BitRange {
fn parse(tree: &Element) -> BitRange {
let (end, start, range_type): (u32, u32, BitRangeType) = if let Some(range) = tree.get_child("bitRange") {
let text = try_get_child!(range.text.as_ref());

assert!(text.starts_with('['));
assert!(text.ends_with(']'));

let mut parts = text[1..text.len() - 1].split(':');

(
try_get_child!(try_get_child!(parts.next()).parse()),
try_get_child!(try_get_child!(parts.next()).parse()),
BitRangeType::BitRange,
)
} else if let (Some(lsb), Some(msb)) = (tree.get_child("lsb"), tree.get_child("msb")) {
(
try_get_child!(parse::u32(msb)),
try_get_child!(parse::u32(lsb)),
BitRangeType::MsbLsb,
)
} else {
return BitRange {
offset: try_get_child!(parse::u32(try_get_child!(tree.get_child("bitOffset")))),
width: try_get_child!(parse::u32(try_get_child!(tree.get_child("bitWidth")))),
range_type: BitRangeType::OffsetWidth,
};
};

BitRange {
offset: start,
width: end - start + 1,
range_type: range_type,
}
}
}


impl EncodeChildren for BitRange {
fn encode_children(&self) -> Vec<Element> {
match self.range_type {
BitRangeType::BitRange => {
vec![
new_element(
"bitRange",
Some(format!(
"[{}:{}]",
self.offset + self.width - 1,
self.offset
))
),
]
}
BitRangeType::MsbLsb => {
vec![
new_element("lsb", Some(format!("{}", self.offset))),
new_element("msb", Some(format!("{}", self.offset + self.width - 1))),
]
}
BitRangeType::OffsetWidth => {
vec![
new_element("bitOffset", Some(format!("{}", self.offset))),
new_element("bitWidth", Some(format!("{}", self.width))),
]
}
}
}
}


#[cfg(test)]
mod tests {
use super::*;

#[test]
fn decode_encode() {
let types = vec![
(
BitRange {
offset: 16,
width: 4,
range_type: BitRangeType::BitRange,
},
String::from(
"
<fake><bitRange>[19:16]</bitRange></fake>
",
)
),
(
BitRange {
offset: 16,
width: 4,
range_type: BitRangeType::OffsetWidth,
},
String::from(
"
<fake><bitOffset>16</bitOffset><bitWidth>4</bitWidth></fake>
",
)
),
(
BitRange {
offset: 16,
width: 4,
range_type: BitRangeType::MsbLsb,
},
String::from(
"
<fake><lsb>16</lsb><msb>19</msb></fake>
",
)
),
];

for (a, s) in types {
let tree1 = &try_get_child!(Element::parse(s.as_bytes()));
let value = BitRange::parse(tree1);
assert_eq!(value, a, "Parsing `{}` expected `{:?}`", s, a);
let mut tree2 = new_element("fake", None);
tree2.children = value.encode_children();
assert_eq!(tree1, &tree2, "Encoding {:?} expected {}", a, s);
}
}
}
56 changes: 56 additions & 0 deletions src/cluster.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

use std::ops::Deref;
use std::collections::hash_map::*;

use xmltree::Element;

use helpers::{ParseElem, EncodeElem};
use clusterinfo::ClusterInfo;
use registerclusterarrayinfo::RegisterClusterArrayInfo;

#[derive(Clone, Debug, PartialEq)]
pub enum Cluster {
Single(ClusterInfo),
Array(ClusterInfo, RegisterClusterArrayInfo),
}

impl ParseElem for Cluster {
fn parse(tree: &Element) -> Cluster {
assert_eq!(tree.name, "cluster");

let info = ClusterInfo::parse(tree);

if tree.get_child("dimIncrement").is_some() {
let array_info = RegisterClusterArrayInfo::parse(tree);
assert!(info.name.contains("%s"));
if let Some(ref indices) = array_info.dim_index {
assert_eq!(array_info.dim as usize, indices.len())
}
Cluster::Array(info, array_info)
} else {
Cluster::Single(info)
}
}
}

impl EncodeElem for Cluster {
fn encode(&self) -> Element {
Element {
name: String::from("cluster"),
attributes: HashMap::new(),
children: Vec::new(),
text: None,
}
}
}

impl Deref for Cluster {
type Target = ClusterInfo;

fn deref(&self) -> &ClusterInfo {
match *self {
Cluster::Single(ref info) => info,
Cluster::Array(ref info, _) => info,
}
}
}
Loading