Skip to content

Commit 361317f

Browse files
Merge pull request #50 from AlexandreSinger/feature-parse-arch
[Parse] Added Segment Connectivity
2 parents 924c858 + e7ebefa commit 361317f

File tree

2 files changed

+277
-2
lines changed

2 files changed

+277
-2
lines changed

fpga_arch_parser/src/arch.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,17 @@ pub enum SegmentResourceType {
334334
General,
335335
}
336336

337+
pub enum SegmentSwitchPoints {
338+
Unidir {
339+
mux_inc: String,
340+
mux_dec: String,
341+
},
342+
Bidir {
343+
wire_switch: String,
344+
opin_switch: String,
345+
},
346+
}
347+
337348
pub struct Segment {
338349
pub axis: SegmentAxis,
339350
pub name: String,
@@ -343,6 +354,9 @@ pub struct Segment {
343354
pub freq: f32,
344355
pub r_metal: f32,
345356
pub c_metal: f32,
357+
pub sb_pattern: Vec<bool>,
358+
pub cb_pattern: Vec<bool>,
359+
pub switch_points: SegmentSwitchPoints,
346360
}
347361

348362
pub struct PackPattern {

fpga_arch_parser/src/parse_segment_list.rs

Lines changed: 263 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,132 @@ use xml::attribute::OwnedAttribute;
99
use crate::parse_error::*;
1010
use crate::arch::*;
1111

12+
fn parse_pattern_int_list(text: &str,
13+
parser: &EventReader<BufReader<File>>) -> Result<Vec<bool>, FPGAArchParseError> {
14+
let mut list: Vec<bool> = Vec::new();
15+
16+
for v in text.split_whitespace() {
17+
let point_val: i32 = match v.parse() {
18+
Ok(val) => val,
19+
Err(e) => return Err(FPGAArchParseError::InvalidTag(format!("Pattern int list parse error: {e}"), parser.position())),
20+
};
21+
match point_val {
22+
0 => list.push(false),
23+
1 => list.push(true),
24+
_ => return Err(FPGAArchParseError::InvalidTag(format!("Pattern int list expected to only have 0s and 1s. Found: {point_val}"), parser.position())),
25+
}
26+
}
27+
28+
Ok(list)
29+
}
30+
31+
fn parse_segment_pattern(name: &OwnedName,
32+
attributes: &[OwnedAttribute],
33+
parser: &mut EventReader<BufReader<File>>) -> Result<Vec<bool>, FPGAArchParseError> {
34+
assert!(name.to_string() == "sb" || name.to_string() == "cb");
35+
36+
let mut block_type: Option<String> = None;
37+
for a in attributes {
38+
match a.name.to_string().as_ref() {
39+
"type" => {
40+
block_type = match block_type {
41+
None => Some(a.value.clone()),
42+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
43+
}
44+
}
45+
_ => return Err(FPGAArchParseError::UnknownAttribute(a.to_string(), parser.position())),
46+
}
47+
}
48+
let block_type = match block_type {
49+
Some(n) => n,
50+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("type".to_string(), parser.position())),
51+
};
52+
if block_type != "pattern" {
53+
return Err(FPGAArchParseError::AttributeParseError(format!("{name} type must be pattern"), parser.position()));
54+
}
55+
56+
let mut pattern: Option<Vec<bool>> = None;
57+
loop {
58+
match parser.next() {
59+
Ok(XmlEvent::Characters(text)) => {
60+
pattern = match pattern {
61+
None => Some(parse_pattern_int_list(&text, parser)?),
62+
Some(_) => return Err(FPGAArchParseError::InvalidTag("Duplicate characters within sb.".to_string(), parser.position())),
63+
}
64+
},
65+
Ok(XmlEvent::EndElement { name: end_name }) => {
66+
if end_name.to_string() == name.to_string() {
67+
break;
68+
} else {
69+
return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position()));
70+
}
71+
},
72+
Ok(XmlEvent::StartElement { name, .. }) => {
73+
return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position()));
74+
},
75+
Ok(XmlEvent::EndDocument) => {
76+
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
77+
},
78+
Err(e) => {
79+
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
80+
},
81+
_ => {},
82+
};
83+
}
84+
let pattern = match pattern {
85+
Some(p) => p,
86+
None => return Err(FPGAArchParseError::InvalidTag("Missing pattern int list".to_string(), parser.position())),
87+
};
88+
89+
Ok(pattern)
90+
}
91+
92+
fn parse_segment_switch_point_descriptor(name: &OwnedName,
93+
attributes: &[OwnedAttribute],
94+
parser: &mut EventReader<BufReader<File>>) -> Result<String, FPGAArchParseError> {
95+
96+
let mut desc_name: Option<String> = None;
97+
for a in attributes {
98+
match a.name.to_string().as_ref() {
99+
"name" => {
100+
desc_name = match desc_name {
101+
None => Some(a.value.clone()),
102+
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
103+
}
104+
},
105+
_ => return Err(FPGAArchParseError::UnknownAttribute(a.to_string(), parser.position())),
106+
}
107+
}
108+
let desc_name = match desc_name {
109+
Some(n) => n,
110+
None => return Err(FPGAArchParseError::MissingRequiredAttribute("name".to_string(), parser.position())),
111+
};
112+
113+
loop {
114+
match parser.next() {
115+
Ok(XmlEvent::EndElement { name: end_name }) => {
116+
if end_name.to_string() == name.to_string() {
117+
break;
118+
} else {
119+
return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position()));
120+
}
121+
},
122+
Ok(XmlEvent::StartElement { name, .. }) => {
123+
return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position()));
124+
},
125+
Ok(XmlEvent::EndDocument) => {
126+
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
127+
},
128+
Err(e) => {
129+
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
130+
},
131+
_ => {},
132+
};
133+
}
134+
135+
Ok(desc_name)
136+
}
137+
12138
fn parse_segment(name: &OwnedName,
13139
attributes: &[OwnedAttribute],
14140
parser: &mut EventReader<BufReader<File>>) -> Result<Segment, FPGAArchParseError> {
@@ -132,8 +258,140 @@ fn parse_segment(name: &OwnedName,
132258

133259
let res_type = res_type.unwrap_or(SegmentResourceType::General);
134260

135-
// TODO: Need to parse the mux, sb, and cb tags. For now just ignore.
136-
let _ = parser.skip();
261+
let mut sb_pattern: Option<Vec<bool>> = None;
262+
let mut cb_pattern: Option<Vec<bool>> = None;
263+
let mut mux: Option<String> = None;
264+
let mut mux_inc: Option<String> = None;
265+
let mut mux_dec: Option<String> = None;
266+
let mut wire_switch: Option<String> = None;
267+
let mut opin_switch: Option<String> = None;
268+
loop {
269+
match parser.next() {
270+
Ok(XmlEvent::StartElement { name, attributes, .. }) => {
271+
match name.to_string().as_str() {
272+
"sb" => {
273+
sb_pattern = match sb_pattern {
274+
None => Some(parse_segment_pattern(&name, &attributes, parser)?),
275+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
276+
};
277+
},
278+
"cb" => {
279+
cb_pattern = match cb_pattern {
280+
None => Some(parse_segment_pattern(&name, &attributes, parser)?),
281+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
282+
};
283+
},
284+
"mux" => {
285+
mux = match mux {
286+
None => Some(parse_segment_switch_point_descriptor(&name, &attributes, parser)?),
287+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
288+
}
289+
},
290+
"mux_inc" => {
291+
mux_inc = match mux_inc {
292+
None => Some(parse_segment_switch_point_descriptor(&name, &attributes, parser)?),
293+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
294+
}
295+
},
296+
"mux_dec" => {
297+
mux_dec = match mux_dec {
298+
None => Some(parse_segment_switch_point_descriptor(&name, &attributes, parser)?),
299+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
300+
}
301+
},
302+
"wire_switch" => {
303+
wire_switch = match wire_switch {
304+
None => Some(parse_segment_switch_point_descriptor(&name, &attributes, parser)?),
305+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
306+
}
307+
},
308+
"opin_switch" => {
309+
opin_switch = match opin_switch {
310+
None => Some(parse_segment_switch_point_descriptor(&name, &attributes, parser)?),
311+
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
312+
}
313+
},
314+
_ => return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position())),
315+
};
316+
},
317+
Ok(XmlEvent::EndElement { name }) => {
318+
match name.to_string().as_str() {
319+
"segment" => break,
320+
_ => return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position())),
321+
}
322+
},
323+
Ok(XmlEvent::EndDocument) => {
324+
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
325+
},
326+
Err(e) => {
327+
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
328+
},
329+
_ => {},
330+
}
331+
};
332+
let sb_pattern = match sb_pattern {
333+
Some(p) => {
334+
if p.len() as i32 != length + 1 {
335+
return Err(FPGAArchParseError::InvalidTag("For a length L wire there must be L+1 entries separated by spaces for <sb>".to_string(), parser.position()));
336+
} else {
337+
p
338+
}
339+
},
340+
None => return Err(FPGAArchParseError::MissingRequiredTag("<sb>".to_string())),
341+
};
342+
let cb_pattern = match cb_pattern {
343+
Some(p) => {
344+
if p.len() as i32 != length {
345+
return Err(FPGAArchParseError::InvalidTag("For a length L wire there must be L entries separated by spaces for <cb>".to_string(), parser.position()));
346+
} else {
347+
p
348+
}
349+
},
350+
None => return Err(FPGAArchParseError::MissingRequiredTag("<sb>".to_string())),
351+
};
352+
let switch_points = match segment_type {
353+
SegmentType::Unidir => {
354+
match mux {
355+
Some(mux_name) => {
356+
if mux_inc.is_some() || mux_dec.is_some() {
357+
return Err(FPGAArchParseError::InvalidTag("For unidirectional segments, either <mux> tag or both <mux_inc> and <mux_dec> should be defined in the architecture file.".to_string(), parser.position()));
358+
}
359+
SegmentSwitchPoints::Unidir{
360+
mux_inc: mux_name.clone(),
361+
mux_dec: mux_name,
362+
}
363+
},
364+
None => {
365+
let mux_inc = match mux_inc {
366+
Some(m) => m,
367+
None => return Err(FPGAArchParseError::InvalidTag("For unidirectional segments, either <mux> tag or both <mux_inc> and <mux_dec> should be defined in the architecture file.".to_string(), parser.position())),
368+
};
369+
let mux_dec = match mux_dec {
370+
Some(m) => m,
371+
None => return Err(FPGAArchParseError::InvalidTag("For unidirectional segments, either <mux> tag or both <mux_inc> and <mux_dec> should be defined in the architecture file.".to_string(), parser.position())),
372+
};
373+
SegmentSwitchPoints::Unidir{
374+
mux_inc,
375+
mux_dec,
376+
}
377+
}
378+
}
379+
},
380+
SegmentType::Bidir => {
381+
let wire_switch = match wire_switch {
382+
Some(w) => w,
383+
None => return Err(FPGAArchParseError::MissingRequiredTag("<wire_switch>".to_string())),
384+
};
385+
let opin_switch = match opin_switch {
386+
Some(w) => w,
387+
None => return Err(FPGAArchParseError::MissingRequiredTag("<opin_switch>".to_string())),
388+
};
389+
SegmentSwitchPoints::Bidir {
390+
wire_switch,
391+
opin_switch,
392+
}
393+
},
394+
};
137395

138396
Ok(Segment {
139397
name,
@@ -144,6 +402,9 @@ fn parse_segment(name: &OwnedName,
144402
freq,
145403
r_metal,
146404
c_metal,
405+
sb_pattern,
406+
cb_pattern,
407+
switch_points,
147408
})
148409
}
149410

0 commit comments

Comments
 (0)