@@ -9,6 +9,132 @@ use xml::attribute::OwnedAttribute;
99use crate :: parse_error:: * ;
1010use 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+
12138fn 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