Skip to content

Commit 9b401dc

Browse files
committed
Get really basic file generation working:
1 parent 684741c commit 9b401dc

File tree

4 files changed

+213
-6
lines changed

4 files changed

+213
-6
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ version = "0.1.0"
44
authors = ["Dylan McKay <[email protected]>"]
55

66
[dependencies]
7+
8+
[build-dependencies]
9+
xmltree = "0.4"

build.rs

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
extern crate xmltree;
2+
3+
use std::path::Path;
4+
5+
#[derive(Debug)]
6+
pub struct Device {
7+
pub name: String,
8+
pub variants: Vec<Variant>,
9+
pub address_spaces: Vec<AddressSpace>,
10+
pub modules: Vec<Module>,
11+
}
12+
13+
#[derive(Debug)]
14+
pub struct Variant {
15+
pub name: String,
16+
pub pinout: Option<String>,
17+
pub package: String,
18+
pub temperature_min: i32,
19+
pub temperature_max: i32,
20+
pub voltage_min: f32,
21+
pub voltage_max: f32,
22+
pub speed_max_hz: u64,
23+
}
24+
25+
#[derive(Debug)]
26+
pub struct AddressSpace {
27+
pub name: String,
28+
pub start_address: u32,
29+
pub size: u32,
30+
pub segments: Vec<MemorySegment>,
31+
}
32+
33+
#[derive(Debug)]
34+
pub struct MemorySegment {
35+
pub start_address: u32,
36+
pub size: u32,
37+
pub ty: String,
38+
pub readable: bool,
39+
pub writable: bool,
40+
pub executable: bool,
41+
pub name: String,
42+
pub page_size: u32,
43+
}
44+
45+
#[derive(Debug)]
46+
pub struct Module {
47+
pub name: String,
48+
pub instances: Vec<Instance>,
49+
}
50+
51+
#[derive(Debug)]
52+
pub struct Instance {
53+
pub name: String,
54+
pub signals: Vec<Signal>,
55+
}
56+
57+
#[derive(Debug)]
58+
pub struct Signal {
59+
pub pad: String,
60+
pub index: Option<u8>,
61+
}
62+
63+
fn main() {
64+
let crate_root = Path::new(env!("CARGO_MANIFEST_DIR"));
65+
66+
let devices = pack::load_all(&crate_root.join("packs")).unwrap();
67+
gen::all(&crate_root.join("src").join("gen"), &devices).unwrap();
68+
}
69+
70+
mod gen {
71+
use super::*;
72+
use std::io::prelude::*;
73+
use std::io::{self, Cursor};
74+
use std::fs::{self, File};
75+
use std::path::Path;
76+
77+
pub fn all(path: &Path, devices: &Vec<Device>) -> Result<(), io::Error> {
78+
fs::create_dir_all(path)?;
79+
80+
let device_names: Vec<String> = devices.iter().map(|device| {
81+
let normalised_name = device.name.to_lowercase();
82+
let registers = self::registers(device);
83+
let mut file = File::create(path.join(format!("{}.rs", normalised_name))).unwrap();
84+
writeln!(file, "{}", registers).unwrap();
85+
normalised_name
86+
}).collect();
87+
88+
let mut mod_rs = File::create(path.join("mod.rs"))?;
89+
for device_name in device_names {
90+
writeln!(mod_rs, "pub mod {};", device_name).unwrap();
91+
}
92+
93+
Ok(())
94+
}
95+
96+
pub fn registers(device: &Device) -> String {
97+
let mut b = Cursor::new(Vec::new());
98+
99+
for module in device.modules.iter() {
100+
for instance in module.instances.iter() {
101+
for signal in instance.signals.iter() {
102+
let offset = 2;
103+
let addr = offset + 20;
104+
writeln!(b, "pub const {}: *mut u8 = {} as *mut u8;", signal.pad, addr).unwrap();
105+
}
106+
}
107+
}
108+
109+
String::from_utf8(b.into_inner()).unwrap()
110+
}
111+
}
112+
113+
mod pack {
114+
use super::*;
115+
116+
use std::fs::File;
117+
use std::io::prelude::*;
118+
use std::{io, fs};
119+
use std::path::{Path, PathBuf};
120+
121+
use xmltree::Element;
122+
123+
pub fn load_all(path: &Path) -> Result<Vec<Device>, io::Error> {
124+
let pack_paths = find_packs(&path.join("atmega")).unwrap();
125+
Ok(pack_paths.into_iter().map(|path| self::load(&path).unwrap()).collect())
126+
}
127+
128+
pub fn load(path: &Path) -> Result<Device, io::Error> {
129+
let mut file = File::open(path)?;
130+
let mut body = String::new();
131+
file.read_to_string(&mut body)?;
132+
133+
let root = Element::parse(body.as_bytes()).unwrap();
134+
let device = root.get_child("devices").unwrap().get_child("device").unwrap();
135+
136+
let address_spaces = Vec::new();
137+
138+
let modules: Vec<_> = device.get_child("peripherals").unwrap().children.iter().map(|module| {
139+
let instance = module.get_child("instance").unwrap();
140+
let name = instance.attributes.get("name").unwrap().clone();
141+
142+
let signals = match instance.get_child("signals") {
143+
Some(signals) => signals.children.iter().map(|signal| {
144+
let pad = signal.attributes.get("pad").unwrap().clone();
145+
let index = signal.attributes.get("index").map(|i| i.parse().unwrap());
146+
Signal {
147+
pad: pad,
148+
index: index,
149+
}
150+
}).collect(),
151+
None => Vec::new(),
152+
};
153+
154+
Module {
155+
name: name.clone(),
156+
instances: vec![Instance {
157+
name: name,
158+
signals: signals,
159+
}],
160+
}
161+
}).collect();
162+
163+
// let address_spaces = device.get_child("address-spaces").unwrap().children.iter().map(|addr| {
164+
// AddressSpace {
165+
// name: addr.attributes.get("name").unwrap().clone(),
166+
// start: u32::from_str_radix(addr.attributes.get("id").unknown()).unwrap(),
167+
// }
168+
// }).collect();
169+
170+
let name = device.attributes.get("name").unwrap();
171+
172+
let variants = root.get_child("variants").unwrap().children.iter().map(|variant| {
173+
Variant {
174+
name: variant.attributes.get("ordercode").unwrap().clone(),
175+
temperature_min: variant.attributes.get("tempmin").unwrap().parse().unwrap(),
176+
temperature_max: variant.attributes.get("tempmax").unwrap().parse().unwrap(),
177+
voltage_min: variant.attributes.get("vccmin").unwrap().parse().unwrap(),
178+
voltage_max: variant.attributes.get("vccmax").unwrap().parse().unwrap(),
179+
package: variant.attributes.get("package").unwrap().clone(),
180+
pinout: variant.attributes.get("pinout").map(|p| p.clone()),
181+
speed_max_hz: variant.attributes.get("speedmax").unwrap().parse().unwrap(),
182+
}
183+
}).collect();
184+
185+
Ok(Device {
186+
name: name.clone(),
187+
variants: variants,
188+
address_spaces: address_spaces,
189+
modules: modules,
190+
})
191+
}
192+
193+
fn find_packs(in_dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
194+
let mut paths = Vec::new();
195+
196+
for entry in fs::read_dir(in_dir)? {
197+
let entry = entry?;
198+
if let Some("atdf") = entry.path().extension().map(|s| s.to_str().unwrap()) {
199+
paths.push(entry.path());
200+
}
201+
}
202+
Ok(paths)
203+
}
204+
}
205+

src/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/gen/

src/lib.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
#[cfg(test)]
2-
mod tests {
3-
#[test]
4-
fn it_works() {
5-
}
6-
}
1+
pub use self::gen::*;
2+
3+
mod gen;
4+

0 commit comments

Comments
 (0)