Skip to content

Commit ae22b05

Browse files
Merge pull request #48 from AlexandreSinger/feature-parse-arch
[Parse] Added Switch List Parsing
2 parents e00ed08 + cdd8a21 commit ae22b05

File tree

4 files changed

+377
-5
lines changed

4 files changed

+377
-5
lines changed

fpga_arch_parser/src/arch.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,36 @@ pub struct DeviceInfo {
286286
// TODO: default_fc
287287
}
288288

289-
pub struct Switch {
289+
pub enum SwitchType {
290+
Mux,
291+
Tristate,
292+
PassGate,
293+
Short,
294+
Buffer,
295+
}
296+
297+
pub enum SwitchBufSize {
298+
Auto,
299+
Val(f32),
300+
}
290301

302+
pub struct SwitchTDel {
303+
pub num_inputs: i32,
304+
pub delay: f32,
305+
}
306+
307+
pub struct Switch {
308+
pub sw_type: SwitchType,
309+
pub name: String,
310+
pub resistance: f32,
311+
pub c_in: f32,
312+
pub c_out: f32,
313+
pub c_internal: Option<f32>,
314+
pub t_del: Option<f32>,
315+
pub buf_size: SwitchBufSize,
316+
pub mux_trans_size: Option<f32>,
317+
pub power_buf_size: Option<i32>,
318+
pub t_del_tags: Vec<SwitchTDel>,
291319
}
292320

293321
pub enum SegmentAxis {

fpga_arch_parser/src/lib.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod parse_port;
1313
mod parse_tiles;
1414
mod parse_layouts;
1515
mod parse_device;
16+
mod parse_switch_list;
1617
mod parse_segment_list;
1718
mod parse_complex_block_list;
1819

@@ -23,6 +24,7 @@ use crate::parse_port::parse_port;
2324
use crate::parse_tiles::parse_tiles;
2425
use crate::parse_layouts::parse_layouts;
2526
use crate::parse_device::parse_device;
27+
use crate::parse_switch_list::parse_switch_list;
2628
use crate::parse_segment_list::parse_segment_list;
2729
use crate::parse_complex_block_list::parse_complex_block_list;
2830

@@ -37,6 +39,7 @@ fn parse_architecture(name: &OwnedName,
3739
let mut tiles: Option<Vec<Tile>> = None;
3840
let mut layouts: Option<Vec<Layout>> = None;
3941
let mut device: Option<DeviceInfo> = None;
42+
let mut switch_list: Option<Vec<Switch>> = None;
4043
let mut segment_list: Option<Vec<Segment>> = None;
4144
let mut complex_block_list: Option<Vec<PBType>> = None;
4245

@@ -67,8 +70,10 @@ fn parse_architecture(name: &OwnedName,
6770
}
6871
},
6972
"switchlist" => {
70-
// TODO: Implement.
71-
let _ = parser.skip();
73+
switch_list = match switch_list {
74+
None => Some(parse_switch_list(&name, &attributes, parser)?),
75+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
76+
}
7277
},
7378
"segmentlist" => {
7479
segment_list = match segment_list {
@@ -134,6 +139,10 @@ fn parse_architecture(name: &OwnedName,
134139
Some(d) => d,
135140
None => return Err(FPGAArchParseError::MissingRequiredTag("<device>".to_string())),
136141
};
142+
let switch_list = match switch_list {
143+
Some(s) => s,
144+
None => return Err(FPGAArchParseError::MissingRequiredTag("<switchlist>".to_string())),
145+
};
137146
let segment_list = match segment_list {
138147
Some(s) => s,
139148
None => return Err(FPGAArchParseError::MissingRequiredTag("<segmentlist>".to_string())),
@@ -148,7 +157,7 @@ fn parse_architecture(name: &OwnedName,
148157
tiles,
149158
layouts,
150159
device,
151-
switch_list: Vec::new(),
160+
switch_list,
152161
segment_list,
153162
complex_block_list,
154163
})
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
use std::fs::File;
2+
use std::io::BufReader;
3+
4+
use xml::common::Position;
5+
use xml::reader::{EventReader, XmlEvent};
6+
use xml::name::OwnedName;
7+
use xml::attribute::OwnedAttribute;
8+
9+
use crate::parse_error::*;
10+
use crate::arch::*;
11+
12+
fn parse_switch_t_del(name: &OwnedName,
13+
attributes: &[OwnedAttribute],
14+
parser: &mut EventReader<BufReader<File>>) -> Result<SwitchTDel, FPGAArchParseError> {
15+
assert!(name.to_string() == "Tdel");
16+
17+
let mut num_inputs: Option<i32> = None;
18+
let mut delay: Option<f32> = None;
19+
20+
for a in attributes {
21+
match a.name.to_string().as_ref() {
22+
"num_inputs" => {
23+
num_inputs = match num_inputs {
24+
None => match a.value.parse() {
25+
Ok(v) => Some(v),
26+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
27+
},
28+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
29+
}
30+
},
31+
"delay" => {
32+
delay = match delay {
33+
None => match a.value.parse() {
34+
Ok(v) => Some(v),
35+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
36+
},
37+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
38+
}
39+
},
40+
_ => return Err(FPGAArchParseError::UnknownAttribute(a.to_string(), parser.position())),
41+
}
42+
}
43+
let num_inputs = match num_inputs {
44+
Some(p) => p,
45+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("num_inputs".to_string(), parser.position())),
46+
};
47+
let delay = match delay {
48+
Some(p) => p,
49+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("delay".to_string(), parser.position())),
50+
};
51+
52+
loop {
53+
match parser.next() {
54+
Ok(XmlEvent::StartElement { name, .. }) => {
55+
return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position()));
56+
},
57+
Ok(XmlEvent::EndElement { name }) => {
58+
match name.to_string().as_str() {
59+
"Tdel" => break,
60+
_ => return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position())),
61+
}
62+
},
63+
Ok(XmlEvent::EndDocument) => {
64+
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
65+
},
66+
Err(e) => {
67+
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
68+
},
69+
_ => {},
70+
};
71+
}
72+
73+
Ok(SwitchTDel {
74+
num_inputs,
75+
delay,
76+
})
77+
}
78+
79+
fn parse_switch(name: &OwnedName,
80+
attributes: &[OwnedAttribute],
81+
parser: &mut EventReader<BufReader<File>>) -> Result<Switch, FPGAArchParseError> {
82+
assert!(name.to_string() == "switch");
83+
84+
let mut sw_type: Option<SwitchType> = None;
85+
let mut sw_name: Option<String> = None;
86+
let mut resistance: Option<f32> = None;
87+
let mut c_in: Option<f32> = None;
88+
let mut c_out: Option<f32> = None;
89+
let mut c_internal: Option<f32> = None;
90+
let mut t_del: Option<f32> = None;
91+
let mut buf_size: Option<SwitchBufSize> = None;
92+
let mut mux_trans_size: Option<f32> = None;
93+
let mut power_buf_size: Option<i32> = None;
94+
95+
for a in attributes {
96+
match a.name.to_string().as_ref() {
97+
"type" => {
98+
sw_type = match sw_type {
99+
None => match a.value.to_string().as_ref() {
100+
"mux" => Some(SwitchType::Mux),
101+
"tristate" => Some(SwitchType::Tristate),
102+
"pass_gate" => Some(SwitchType::PassGate),
103+
"short" => Some(SwitchType::Short),
104+
"buffer" => Some(SwitchType::Buffer),
105+
_ => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: Unknown switch type."), parser.position())),
106+
},
107+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
108+
}
109+
},
110+
"name" => {
111+
sw_name = match sw_name {
112+
None => Some(a.value.clone()),
113+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
114+
}
115+
},
116+
"R" => {
117+
resistance = match resistance {
118+
None => match a.value.parse() {
119+
Ok(v) => Some(v),
120+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
121+
},
122+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
123+
}
124+
},
125+
"Cin" => {
126+
c_in = match c_in {
127+
None => match a.value.parse() {
128+
Ok(v) => Some(v),
129+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
130+
},
131+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
132+
}
133+
},
134+
"Cout" => {
135+
c_out = match c_out {
136+
None => match a.value.parse() {
137+
Ok(v) => Some(v),
138+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
139+
},
140+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
141+
}
142+
},
143+
"Cinternal" => {
144+
c_internal = match c_internal {
145+
None => match a.value.parse() {
146+
Ok(v) => Some(v),
147+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
148+
},
149+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
150+
}
151+
},
152+
"Tdel" => {
153+
t_del = match t_del {
154+
None => match a.value.parse() {
155+
Ok(v) => Some(v),
156+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
157+
},
158+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
159+
}
160+
},
161+
"buf_size" => {
162+
buf_size = match buf_size {
163+
None => match a.value.as_ref() {
164+
"auto" => Some(SwitchBufSize::Auto),
165+
_ => match a.value.parse() {
166+
Ok(v) => Some(SwitchBufSize::Val(v)),
167+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
168+
},
169+
},
170+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
171+
}
172+
},
173+
"mux_trans_size" => {
174+
mux_trans_size = match mux_trans_size {
175+
None => match a.value.parse() {
176+
Ok(v) => Some(v),
177+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
178+
},
179+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
180+
}
181+
},
182+
"power_buf_size" => {
183+
power_buf_size = match power_buf_size {
184+
None => match a.value.parse() {
185+
Ok(v) => Some(v),
186+
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
187+
},
188+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
189+
}
190+
},
191+
_ => return Err(FPGAArchParseError::UnknownAttribute(a.to_string(), parser.position())),
192+
};
193+
}
194+
195+
let sw_type = match sw_type {
196+
Some(p) => p,
197+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("type".to_string(), parser.position())),
198+
};
199+
let sw_name = match sw_name {
200+
Some(p) => p,
201+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("name".to_string(), parser.position())),
202+
};
203+
let resistance = match resistance {
204+
Some(p) => p,
205+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("R".to_string(), parser.position())),
206+
};
207+
let c_in = match c_in {
208+
Some(p) => p,
209+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("Cin".to_string(), parser.position())),
210+
};
211+
let c_out = match c_out {
212+
Some(p) => p,
213+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("Cout".to_string(), parser.position())),
214+
};
215+
let buf_size = buf_size.unwrap_or(SwitchBufSize::Auto);
216+
217+
let mut t_del_tags: Vec<SwitchTDel> = Vec::new();
218+
loop {
219+
match parser.next() {
220+
Ok(XmlEvent::StartElement { name, .. }) => {
221+
match name.to_string().as_str() {
222+
"Tdel" => {
223+
t_del_tags.push(parse_switch_t_del(&name, &attributes, parser)?);
224+
},
225+
_ => return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position())),
226+
};
227+
},
228+
Ok(XmlEvent::EndElement { name }) => {
229+
match name.to_string().as_str() {
230+
"switch" => break,
231+
_ => return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position())),
232+
}
233+
},
234+
Ok(XmlEvent::EndDocument) => {
235+
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
236+
},
237+
Err(e) => {
238+
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
239+
},
240+
_ => {},
241+
};
242+
}
243+
244+
Ok(Switch {
245+
sw_type,
246+
name: sw_name,
247+
resistance,
248+
c_in,
249+
c_out,
250+
c_internal,
251+
t_del,
252+
buf_size,
253+
mux_trans_size,
254+
power_buf_size,
255+
t_del_tags,
256+
})
257+
}
258+
259+
pub fn parse_switch_list(name: &OwnedName,
260+
attributes: &[OwnedAttribute],
261+
parser: &mut EventReader<BufReader<File>>) -> Result<Vec<Switch>, FPGAArchParseError> {
262+
assert!(name.to_string() == "switchlist");
263+
if !attributes.is_empty() {
264+
return Err(FPGAArchParseError::UnknownAttribute(String::from("Expected to be empty"), parser.position()));
265+
}
266+
267+
let mut switch_list: Vec<Switch> = Vec::new();
268+
loop {
269+
match parser.next() {
270+
Ok(XmlEvent::StartElement { name, attributes, .. }) => {
271+
match name.to_string().as_str() {
272+
"switch" => {
273+
switch_list.push(parse_switch(&name, &attributes, parser)?);
274+
},
275+
_ => return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position())),
276+
};
277+
},
278+
Ok(XmlEvent::EndElement { name }) => {
279+
match name.to_string().as_str() {
280+
"switchlist" => break,
281+
_ => return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position())),
282+
}
283+
},
284+
Ok(XmlEvent::EndDocument) => {
285+
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
286+
},
287+
Err(e) => {
288+
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
289+
},
290+
_ => {},
291+
}
292+
};
293+
294+
// TODO: It is not clear what should happen if the switch list is empty.
295+
// Should confirm with the documentation.
296+
297+
Ok(switch_list)
298+
}

0 commit comments

Comments
 (0)