prjunnamed_netlist/
parse.rs

1use std::{collections::BTreeMap, fmt::Display, ops::Range, str::FromStr, sync::Arc};
2
3use yap::{one_of, types::WithContext, IntoTokens, TokenLocation, Tokens};
4
5use crate::{
6    create_target, AssignCell, Cell, Const, ControlNet, Design, FlipFlop, Instance, IoBuffer, IoNet, IoValue,
7    MatchCell, Memory, MemoryPortRelation, MemoryReadFlipFlop, MemoryReadPort, MemoryWritePort, MetaItem, Net,
8    ParamValue, Target, TargetCell, Value,
9};
10use crate::metadata::{MetaStringIndex, MetaItemIndex, SourcePosition};
11
12#[derive(Debug)]
13struct Context {
14    design: Design,
15    meta_map: BTreeMap<usize, MetaItemIndex>,
16    def_map: BTreeMap<usize, Value>,        // definition: index -> value
17    use_map: BTreeMap<(usize, usize), Net>, // reference:  index + offset -> void (only if above definition)
18}
19
20impl Context {
21    fn new(target: Option<Arc<dyn Target>>) -> Context {
22        Context {
23            design: Design::with_target(target),
24            meta_map: BTreeMap::new(),
25            def_map: BTreeMap::new(),
26            use_map: BTreeMap::new(),
27        }
28    }
29
30    fn add_meta(&mut self, index: usize, item_index: MetaItemIndex) {
31        assert_eq!(self.meta_map.insert(index, item_index), None, "metadata indices cannot be reused");
32    }
33
34    fn get_meta(&self, index: usize) -> MetaItemIndex {
35        *self.meta_map.get(&index).expect("index should reference a metadata item")
36    }
37
38    fn add_io(&mut self, name: String, width: usize) -> IoValue {
39        self.design.add_io(name, width)
40    }
41
42    fn get_io(&self, name: impl AsRef<str>) -> IoValue {
43        self.design.get_io(name).expect("name should reference an IO")
44    }
45
46    fn get_io1(&self, name: impl AsRef<str>) -> IoNet {
47        let value = self.get_io(name);
48        assert_eq!(value.len(), 1, "IO width should be 1");
49        value[0]
50    }
51
52    fn add_def(&mut self, index: usize, width: usize, value: Value) {
53        assert_eq!(value.len(), width, "cell width should match declaration width");
54        assert_eq!(self.def_map.insert(index, value.clone()), None, "cell indices cannot be reused");
55    }
56
57    fn get_use(&mut self, index: usize, offsets: Range<usize>) -> Value {
58        if let Some(value) = self.def_map.get(&index) {
59            value.slice(offsets)
60        } else {
61            let mut nets = vec![];
62            for offset in offsets {
63                let net = self.use_map.entry((index, offset)).or_insert_with(|| self.design.add_void(1).unwrap_net());
64                nets.push(*net);
65            }
66            Value::from(nets)
67        }
68    }
69
70    fn apply(mut self) -> Design {
71        for ((index, offset), net) in self.use_map.into_iter() {
72            if let Some(output) = self.def_map.get(&index) {
73                if offset < output.len() {
74                    self.design.replace_net(net, output[offset]);
75                } else {
76                    panic!("reference %{}+{} out of bounds for definition %{}:{}", index, offset, index, output.len());
77                }
78            } else {
79                panic!("unresolved reference %{index}")
80            }
81        }
82        self.design.apply();
83        self.design
84    }
85}
86
87fn parse_space(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> bool {
88    t.skip_while(|c| *c == ' ' || *c == '\t') > 0
89}
90
91fn parse_comment(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> bool {
92    if !t.token(';') {
93        return false;
94    }
95    t.skip_while(|c| *c != '\n');
96    true
97}
98
99fn parse_blank(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> bool {
100    let space = parse_space(t);
101    let comment = parse_comment(t);
102    space || comment
103}
104
105#[must_use]
106fn parse_symbol(t: &mut WithContext<impl Tokens<Item = char>, Context>, symbol: char) -> Option<()> {
107    debug_assert!(symbol != '\n', "use parse_newline()");
108    if !t.token(symbol) {
109        return None;
110    }
111    Some(())
112}
113
114#[must_use]
115fn parse_newline(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
116    if one_of!(t;
117        t.token('\n'),
118        t.token('\r') && t.token('\n')
119    ) {
120        Some(())
121    } else {
122        None
123    }
124}
125
126fn parse_decimal<T: FromStr>(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<T> {
127    t.take_while(|c| c.is_ascii_digit() || *c == '-').parse::<T, String>().ok()
128}
129
130fn parse_integer<T: FromStr>(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<T> {
131    parse_symbol(t, '#')?;
132    parse_decimal(t)
133}
134
135fn parse_string_char(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<u8> {
136    match t.next() {
137        Some('"' | '\\') => None,
138        Some(char) if char.is_ascii() => Some(char as u8),
139        _ => None,
140    }
141}
142
143fn parse_string_escape(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<u8> {
144    parse_symbol(t, '\\')?;
145    if let (Some(hi @ ('0'..='9' | 'a'..='f')), Some(lo @ ('0'..='9' | 'a'..='f'))) = (t.next(), t.next()) {
146        u8::from_str_radix(&format!("{hi}{lo}"), 16).ok()
147    } else {
148        None
149    }
150}
151
152fn parse_string(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<String> {
153    parse_symbol(t, '"')?;
154    let bytes = t
155        .many(|t| {
156            one_of!(t;
157                parse_string_char(t),
158                parse_string_escape(t)
159            )
160        })
161        .collect::<Vec<u8>>();
162    parse_symbol(t, '"')?;
163    String::from_utf8(bytes).ok()
164}
165
166fn parse_const(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Const> {
167    t.take_while(|c| *c == 'X' || *c == '0' || *c == '1')
168        .parse::<Const, String>()
169        .ok()
170        .and_then(|value| if !value.is_empty() { Some(value) } else { None })
171}
172
173fn parse_keyword(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<String> {
174    let name: String = t.take_while(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '/')).collect();
175    if name.is_empty() {
176        return None;
177    }
178    Some(name)
179}
180
181fn parse_keyword_eq(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<String> {
182    let keyword = parse_keyword(t)?;
183    parse_blank(t);
184    parse_symbol(t, '=')?;
185    parse_blank(t);
186    Some(keyword)
187}
188
189#[must_use]
190fn parse_keyword_expect(t: &mut WithContext<impl Tokens<Item = char>, Context>, expected: &str) -> Option<()> {
191    let keyword = parse_keyword(t)?;
192    if keyword != expected {
193        return None;
194    }
195    Some(())
196}
197
198#[must_use]
199fn parse_keyword_eq_expect(t: &mut WithContext<impl Tokens<Item = char>, Context>, expected: &str) -> Option<()> {
200    let keyword = parse_keyword_eq(t)?;
201    if keyword != expected {
202        return None;
203    }
204    Some(())
205}
206
207fn parse_metadata_index(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<usize> {
208    parse_symbol(t, '!')?;
209    parse_decimal(t)
210}
211
212fn parse_io_name(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<String> {
213    parse_symbol(t, '&')?;
214    parse_string(t)
215}
216
217fn parse_io_name_size(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, usize)> {
218    let name = parse_io_name(t)?;
219    parse_symbol(t, ':')?;
220    let size = parse_decimal(t)?;
221    Some((name, size))
222}
223
224fn parse_io_name_offset(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, usize)> {
225    let name = parse_io_name(t)?;
226    parse_symbol(t, '+')?;
227    let offset = parse_decimal(t)?;
228    Some((name, offset))
229}
230
231fn parse_io_net(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<IoNet> {
232    one_of!(t;
233        parse_symbol(t, '&').and_then(|()| parse_symbol(t, '_')).map(|()| IoNet::FLOATING),
234        parse_io_name_offset(t).map(|(name, offset)| t.context().get_io(name)[offset]),
235        parse_io_name(t).map(|name| t.context().get_io1(name))
236    )
237}
238
239fn parse_io_value_floating(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<IoValue> {
240    parse_symbol(t, '&')?;
241    parse_symbol(t, '_')?;
242    parse_symbol(t, ':')?;
243    let size = parse_decimal(t)?;
244    Some(IoValue::from_iter(std::iter::repeat_n(IoNet::FLOATING, size)))
245}
246
247fn parse_io_value_concat(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<IoValue> {
248    let mut value = IoValue::new();
249    parse_symbol(t, '[')?;
250    let parts = Vec::from_iter(
251        t.many(|t| {
252            parse_blank(t);
253            parse_io_net(t)
254        })
255        .as_iter(),
256    );
257    for part in parts.into_iter().rev() {
258        value.extend([part]);
259    }
260    parse_blank(t);
261    parse_symbol(t, ']')?;
262    Some(value)
263}
264
265fn parse_io_value(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<IoValue> {
266    one_of!(t;
267        parse_io_value_concat(t),
268        parse_io_value_floating(t),
269        parse_io_name_size(t).and_then(|(name, size)| Some(t.context().get_io(name).slice(..size))),
270        parse_io_net(t).map(IoValue::from),
271    )
272}
273
274fn parse_cell_index(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<usize> {
275    parse_symbol(t, '%')?;
276    parse_decimal(t)
277}
278
279fn parse_cell_index_placeholder(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<usize> {
280    let cell_index = parse_cell_index(t)?;
281    parse_symbol(t, ':')?;
282    parse_symbol(t, '_')?;
283    Some(cell_index)
284}
285
286fn parse_cell_index_width(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(usize, usize)> {
287    let cell_index = parse_cell_index(t)?;
288    parse_symbol(t, ':')?;
289    let width = parse_decimal(t)?;
290    Some((cell_index, width))
291}
292
293fn parse_cell_index_offset_width(
294    t: &mut WithContext<impl Tokens<Item = char>, Context>,
295) -> Option<(usize, usize, usize)> {
296    let cell_index = parse_cell_index(t)?;
297    let offset = if parse_symbol(t, '+').is_some() { parse_decimal(t)? } else { 0 };
298    let width = if parse_symbol(t, ':').is_some() { parse_decimal(t)? } else { 1 };
299    Some((cell_index, offset, width))
300}
301
302fn parse_value_part(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Value> {
303    let value = one_of!(t;
304        parse_const(t).map(Value::from),
305        parse_cell_index_offset_width(t).and_then(|(cell_index, offset, width)| {
306            Some(t.context_mut().get_use(cell_index, offset..offset+width))
307        }),
308    )?;
309    if parse_symbol(t, '*').is_some() {
310        let repeat = parse_decimal(t)?;
311        Some(value.repeat(repeat))
312    } else {
313        Some(value)
314    }
315}
316
317fn parse_value_concat(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Value> {
318    let mut value = Value::new();
319    parse_symbol(t, '[')?;
320    let parts = Vec::from_iter(
321        t.many(|t| {
322            parse_blank(t);
323            parse_value_part(t)
324        })
325        .as_iter(),
326    );
327    for part in parts.into_iter().rev() {
328        value.extend(part);
329    }
330    parse_blank(t);
331    parse_symbol(t, ']')?;
332    Some(value)
333}
334
335fn parse_param_value(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<ParamValue> {
336    one_of!(t;
337        parse_const(t).map(ParamValue::Const),
338        parse_integer(t).map(ParamValue::Int),
339        parse_string(t).map(ParamValue::String)
340    )
341}
342
343fn parse_target_option(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, String)> {
344    parse_blank(t);
345    let name = parse_string(t)?;
346    parse_blank(t);
347    parse_symbol(t, '=')?;
348    parse_blank(t);
349    let value = parse_string(t)?;
350    Some((name, value))
351}
352
353fn parse_target(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
354    parse_keyword_expect(t, "target")?;
355    parse_blank(t);
356    let name = parse_string(t)?;
357    let mut options = BTreeMap::new();
358    while let Some((name, value)) = parse_target_option(t) {
359        if options.insert(name.clone(), value).is_some() {
360            panic!("target option {name} is specified more than once");
361        }
362    }
363    parse_blank(t);
364    parse_newline(t)?;
365    let context = t.context_mut();
366    if !context.design.is_empty() {
367        panic!("target specification must come before any definitions");
368    }
369    context.design = Design::with_target(Some(create_target(&name, options).unwrap()));
370    Some(())
371}
372
373fn parse_metadata_string(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MetaStringIndex> {
374    let string = parse_string(t)?;
375    Some(t.context_mut().design.add_metadata_string(&string).index())
376}
377
378fn parse_metadata_set(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MetaItemIndex> {
379    let mut indices = Vec::new();
380    parse_symbol(t, '{')?;
381    parse_blank(t);
382    while let Some(()) = t.optional(|t| {
383        indices.push(parse_metadata_index(t)?);
384        parse_blank(t);
385        Some(())
386    }) {}
387    parse_symbol(t, '}')?;
388    let ctx = t.context_mut();
389    let items = indices.into_iter().map(|index| ctx.design.ref_metadata_item(ctx.get_meta(index))).collect();
390    Some(ctx.design.add_metadata_item(&MetaItem::Set(items)).index())
391}
392
393fn parse_metadata_position(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<SourcePosition> {
394    parse_symbol(t, '(')?;
395    parse_blank(t);
396    let line = parse_integer(t)?;
397    parse_blank(t);
398    let column = parse_integer(t)?;
399    parse_blank(t);
400    parse_symbol(t, ')')?;
401    Some(SourcePosition { line, column })
402}
403
404fn parse_metadata_source(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MetaItemIndex> {
405    parse_keyword_expect(t, "source")?;
406    parse_blank(t);
407    let file = parse_metadata_string(t)?;
408    parse_blank(t);
409    let start = parse_metadata_position(t)?;
410    parse_blank(t);
411    let end = parse_metadata_position(t)?;
412    let ctx = t.context_mut();
413    let file = ctx.design.ref_metadata_string(file);
414    Some(ctx.design.add_metadata_item(&MetaItem::Source { file, start, end }).index())
415}
416
417fn parse_metadata_scope(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MetaItemIndex> {
418    enum Scope {
419        Named(MetaStringIndex),
420        Indexed(i32),
421    }
422
423    parse_keyword_expect(t, "scope")?;
424    parse_blank(t);
425    let scope = one_of!(t;
426        parse_metadata_string(t).map(Scope::Named),
427        parse_integer(t).map(Scope::Indexed),
428    )?;
429    let parent_index = t.optional(|t| {
430        parse_blank(t);
431        parse_keyword_eq_expect(t, "in")?;
432        parse_metadata_index(t)
433    });
434    let source_index = t.optional(|t| {
435        parse_blank(t);
436        parse_keyword_eq_expect(t, "src")?;
437        parse_metadata_index(t)
438    });
439    let ctx = t.context_mut();
440    let parent_index = parent_index.map(|parent_index| ctx.get_meta(parent_index)).unwrap_or(MetaItemIndex::NONE);
441    let parent = ctx.design.ref_metadata_item(parent_index);
442    let source_index = source_index.map(|source_index| ctx.get_meta(source_index)).unwrap_or(MetaItemIndex::NONE);
443    let source = ctx.design.ref_metadata_item(source_index);
444    match scope {
445        Scope::Named(name_index) => {
446            let name = ctx.design.ref_metadata_string(name_index);
447            Some(ctx.design.add_metadata_item(&MetaItem::NamedScope { name, parent, source }).index())
448        }
449        Scope::Indexed(index) => {
450            Some(ctx.design.add_metadata_item(&MetaItem::IndexedScope { index, parent, source }).index())
451        }
452    }
453}
454
455fn parse_metadata_ident(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MetaItemIndex> {
456    parse_keyword_expect(t, "ident")?;
457    parse_blank(t);
458    let name = parse_metadata_string(t)?;
459    parse_blank(t);
460    parse_keyword_eq_expect(t, "in")?;
461    let scope_index = parse_metadata_index(t)?;
462    let ctx = t.context_mut();
463    let name = ctx.design.ref_metadata_string(name);
464    let scope = ctx.design.ref_metadata_item(ctx.get_meta(scope_index));
465    Some(ctx.design.add_metadata_item(&MetaItem::Ident { name, scope }).index())
466}
467
468fn parse_metadata_attr(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MetaItemIndex> {
469    parse_keyword_expect(t, "attr")?;
470    parse_blank(t);
471    let name = parse_metadata_string(t)?;
472    parse_blank(t);
473    let value = parse_param_value(t)?;
474    let ctx = t.context_mut();
475    let name = ctx.design.ref_metadata_string(name);
476    Some(ctx.design.add_metadata_item(&MetaItem::Attr { name, value }).index())
477}
478
479fn parse_metadata(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
480    let index = parse_metadata_index(t)?;
481    parse_blank(t);
482    parse_symbol(t, '=')?;
483    parse_blank(t);
484    let item_index = one_of!(t;
485        parse_metadata_set(t),
486        parse_metadata_source(t),
487        parse_metadata_scope(t),
488        parse_metadata_ident(t),
489        parse_metadata_attr(t),
490    )?;
491    parse_blank(t);
492    parse_newline(t)?;
493    t.context_mut().add_meta(index, item_index);
494    Some(())
495}
496
497fn parse_io(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<IoValue> {
498    let (name, size) = parse_io_name_size(t)?;
499    parse_blank(t);
500    parse_symbol(t, '=')?;
501    parse_blank(t);
502    parse_keyword_expect(t, "io")?;
503    parse_newline(t)?;
504    let ctx = t.context_mut();
505    let io_value = ctx.add_io(name, size);
506    ctx.design.apply();
507    Some(io_value)
508}
509
510fn parse_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
511    fn parse_metadata_ref(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MetaItemIndex> {
512        let index = parse_metadata_index(t)?;
513        Some(t.context().get_meta(index))
514    }
515
516    fn parse_value_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Value> {
517        parse_blank(t);
518        one_of!(t;
519            parse_value_part(t),
520            parse_value_concat(t)
521        )
522    }
523
524    fn parse_net_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Net> {
525        parse_blank(t);
526        parse_value_part(t).map(|value| {
527            assert_eq!(value.len(), 1, "reference should be a single net");
528            value[0]
529        })
530    }
531
532    fn parse_control_net_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<ControlNet> {
533        parse_blank(t);
534        let negated = parse_symbol(t, '!').is_some();
535        let net = parse_net_arg(t)?;
536        if negated { Some(ControlNet::Neg(net)) } else { Some(ControlNet::Pos(net)) }
537    }
538
539    fn parse_control_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>, name: &str) -> Option<ControlNet> {
540        parse_blank(t);
541        parse_keyword_eq_expect(t, name)?;
542        parse_control_net_arg(t)
543    }
544
545    fn parse_int_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<usize> {
546        parse_blank(t);
547        parse_integer(t)
548    }
549
550    fn parse_string_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<String> {
551        parse_blank(t);
552        parse_string(t)
553    }
554
555    fn parse_dff_reset_control_net_arg(
556        t: &mut WithContext<impl Tokens<Item = char>, Context>,
557        name: &str,
558    ) -> Option<(ControlNet, Option<Const>)> {
559        parse_control_arg(t, name).map(|control_net| {
560            let init_value = t.optional(|t| {
561                parse_blank(t);
562                parse_symbol(t, ',')?;
563                parse_blank(t);
564                parse_const(t)
565            });
566            (control_net, init_value)
567        })
568    }
569
570    fn parse_dff_load_control_net_arg(
571        t: &mut WithContext<impl Tokens<Item = char>, Context>,
572        name: &str,
573    ) -> Option<(ControlNet, Value)> {
574        let cnet = parse_control_arg(t, name)?;
575        parse_blank(t);
576        parse_symbol(t, ',')?;
577        parse_blank(t);
578        let value = parse_value_arg(t)?;
579        Some((cnet, value))
580    }
581
582    fn parse_reset_over_enable_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<bool> {
583        parse_blank(t);
584        one_of!(t;
585            parse_keyword(t).filter(|kw| kw == "rst/en").map(|_| true),
586            parse_keyword(t).filter(|kw| kw == "en/rst").map(|_| false),
587        )
588    }
589
590    fn parse_dff_init_value_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Const> {
591        parse_blank(t);
592        parse_keyword_eq_expect(t, "init")?;
593        parse_const(t)
594    }
595
596    fn parse_instance_param(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, ParamValue)> {
597        parse_keyword_expect(t, "param")?;
598        parse_blank(t);
599        let name = parse_string(t)?;
600        parse_blank(t);
601        parse_symbol(t, '=')?;
602        parse_blank(t);
603        let value = parse_param_value(t)?;
604        Some((name, value))
605    }
606
607    fn parse_instance_input(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, Value)> {
608        parse_keyword_expect(t, "input")?;
609        parse_blank(t);
610        let name = parse_string(t)?;
611        parse_blank(t);
612        parse_symbol(t, '=')?;
613        let value = parse_value_arg(t)?;
614        Some((name, value))
615    }
616
617    fn parse_instance_output(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, usize, usize)> {
618        let (cell_index, width) = parse_cell_index_width(t)?;
619        parse_blank(t);
620        parse_symbol(t, '=')?;
621        parse_blank(t);
622        parse_keyword_expect(t, "output")?;
623        parse_blank(t);
624        let name = parse_string(t)?;
625        Some((name, cell_index, width))
626    }
627
628    fn parse_instance_io(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, IoValue)> {
629        parse_keyword_expect(t, "io")?;
630        parse_blank(t);
631        let name = parse_string(t)?;
632        parse_blank(t);
633        parse_symbol(t, '=')?;
634        parse_blank(t);
635        let io_value = parse_io_value(t)?;
636        Some((name, io_value))
637    }
638
639    fn parse_instance(
640        t: &mut WithContext<impl Tokens<Item = char>, Context>,
641    ) -> Option<(Instance, MetaItemIndex, Value)> {
642        let mut instance = Instance {
643            kind: parse_string(t)?,
644            params: BTreeMap::new(),
645            inputs: BTreeMap::new(),
646            outputs: BTreeMap::new(),
647            ios: BTreeMap::new(),
648        };
649        let mut output = Value::new();
650        parse_blank(t);
651        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
652        parse_blank(t);
653        parse_symbol(t, '{')?;
654        parse_blank(t);
655        parse_newline(t)?;
656        while let Some(()) = t.optional(|t| {
657            parse_blank(t);
658            one_of!(t;
659                parse_instance_param(t).map(|(name, value)|
660                    assert!(instance.params.insert(name, value).is_none(), "duplicate parameter name in instance")),
661                parse_instance_input(t).map(|(name, value)|
662                    assert!(instance.inputs.insert(name, value).is_none(), "duplicate input name in instance")),
663                parse_instance_output(t).map(|(name, index, width)| {
664                    let start = instance.output_len();
665                    assert!(
666                        instance.outputs.insert(name, start..start + width).is_none(),
667                        "duplicate output name in instance"
668                    );
669                    let ctx = t.context_mut();
670                    let value = ctx.design.add_void(width);
671                    ctx.add_def(index, width, value.clone());
672                    output = output.concat(value);
673                }),
674                parse_instance_io(t).map(|(name, io_value)|
675                    assert!(instance.ios.insert(name, io_value).is_none(), "duplicate IO name in instance"))
676            );
677            parse_blank(t);
678            parse_newline(t)?;
679            Some(())
680        }) {}
681        parse_blank(t);
682        parse_symbol(t, '}')?;
683        Some((instance, metadata, output))
684    }
685
686    fn parse_simple_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
687        let (index, width) = parse_cell_index_width(t)?;
688        parse_blank(t);
689        parse_symbol(t, '=')?;
690        parse_blank(t);
691        let keyword = parse_keyword(t)?;
692        let cell = match keyword.as_ref() {
693            "buf" => Cell::Buf(parse_value_arg(t)?),
694            "not" => Cell::Not(parse_value_arg(t)?),
695            "and" => Cell::And(parse_value_arg(t)?, parse_value_arg(t)?),
696            "or" => Cell::Or(parse_value_arg(t)?, parse_value_arg(t)?),
697            "xor" => Cell::Xor(parse_value_arg(t)?, parse_value_arg(t)?),
698            "mux" => Cell::Mux(parse_net_arg(t)?, parse_value_arg(t)?, parse_value_arg(t)?),
699            "adc" => Cell::Adc(parse_value_arg(t)?, parse_value_arg(t)?, parse_net_arg(t)?),
700            "aig" => Cell::Aig(parse_control_net_arg(t)?, parse_control_net_arg(t)?),
701            "eq" => Cell::Eq(parse_value_arg(t)?, parse_value_arg(t)?),
702            "ult" => Cell::ULt(parse_value_arg(t)?, parse_value_arg(t)?),
703            "slt" => Cell::SLt(parse_value_arg(t)?, parse_value_arg(t)?),
704            "shl" => Cell::Shl(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
705            "ushr" => Cell::UShr(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
706            "sshr" => Cell::SShr(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
707            "xshr" => Cell::XShr(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
708            "mul" => Cell::Mul(parse_value_arg(t)?, parse_value_arg(t)?),
709            "udiv" => Cell::UDiv(parse_value_arg(t)?, parse_value_arg(t)?),
710            "umod" => Cell::UMod(parse_value_arg(t)?, parse_value_arg(t)?),
711            "sdiv_trunc" => Cell::SDivTrunc(parse_value_arg(t)?, parse_value_arg(t)?),
712            "sdiv_floor" => Cell::SDivFloor(parse_value_arg(t)?, parse_value_arg(t)?),
713            "smod_trunc" => Cell::SModTrunc(parse_value_arg(t)?, parse_value_arg(t)?),
714            "smod_floor" => Cell::SModFloor(parse_value_arg(t)?, parse_value_arg(t)?),
715            "assign" => {
716                let enable = t
717                    .optional(|t| {
718                        parse_blank(t);
719                        parse_keyword_eq_expect(t, "en")?;
720                        parse_net_arg(t)
721                    })
722                    .unwrap_or(Net::ONE);
723                let value = parse_value_arg(t)?;
724                let update = parse_value_arg(t)?;
725                let offset = t
726                    .optional(|t| {
727                        parse_blank(t);
728                        parse_keyword_eq_expect(t, "at")?;
729                        parse_integer(t)
730                    })
731                    .unwrap_or(0);
732                Cell::Assign(AssignCell { value, enable, update, offset })
733            }
734            "dff" => {
735                let data = t.optional(|t| parse_value_arg(t)).unwrap_or(Value::undef(width));
736                let clock = t.optional(|t| parse_control_arg(t, "clk")).unwrap_or(ControlNet::Pos(Net::ZERO));
737                let (clear, clear_value) = t
738                    .optional(|t| parse_dff_reset_control_net_arg(t, "clr"))
739                    .unwrap_or((ControlNet::Pos(Net::ZERO), None));
740                let (load, load_data) = t
741                    .optional(|t| parse_dff_load_control_net_arg(t, "load"))
742                    .unwrap_or((ControlNet::Pos(Net::ZERO), Value::undef(width)));
743                let (reset, reset_value) = t
744                    .optional(|t| parse_dff_reset_control_net_arg(t, "rst"))
745                    .unwrap_or((ControlNet::Pos(Net::ZERO), None));
746                let enable = t.optional(|t| parse_control_arg(t, "en")).unwrap_or(ControlNet::Pos(Net::ONE));
747                let reset_over_enable = t.optional(|t| parse_reset_over_enable_arg(t)).unwrap_or(false);
748                let init_value = t.optional(|t| parse_dff_init_value_arg(t)).unwrap_or_else(|| Const::undef(width));
749                Cell::Dff(FlipFlop {
750                    data,
751                    clock,
752                    clear,
753                    clear_value: clear_value.unwrap_or_else(|| init_value.clone()),
754                    load,
755                    load_data,
756                    reset,
757                    reset_value: reset_value.unwrap_or_else(|| init_value.clone()),
758                    enable,
759                    reset_over_enable,
760                    init_value,
761                })
762            }
763            "iobuf" => {
764                parse_blank(t);
765                let io = parse_io_value(t)?;
766                parse_blank(t);
767                parse_keyword_eq_expect(t, "o")?;
768                let output = parse_value_arg(t)?;
769                let enable = parse_control_arg(t, "en")?;
770                Cell::IoBuf(IoBuffer { io, output, enable })
771            }
772            "input" => Cell::Input(parse_string_arg(t)?, width),
773            "output" => Cell::Output(parse_string_arg(t)?, parse_value_arg(t)?),
774            "name" => Cell::Name(parse_string_arg(t)?, parse_value_arg(t)?),
775            "debug" => Cell::Debug(parse_string_arg(t)?, parse_value_arg(t)?),
776            _ => return None,
777        };
778        parse_blank(t);
779        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
780        let ctx = t.context_mut();
781        let output = ctx.design.add_cell_with_metadata_index(cell, metadata);
782        assert_eq!(output.len(), width, "cell output width must match declaration width");
783        ctx.add_def(index, width, output);
784        Some(())
785    }
786
787    fn parse_match_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
788        let (index, width) = parse_cell_index_width(t)?;
789        parse_blank(t);
790        parse_symbol(t, '=')?;
791        parse_blank(t);
792        parse_keyword_expect(t, "match")?;
793        parse_blank(t);
794        let enable = t
795            .optional(|t| {
796                parse_blank(t);
797                parse_keyword_eq_expect(t, "en")?;
798                parse_net_arg(t)
799            })
800            .unwrap_or(Net::ONE);
801        let value = parse_value_arg(t)?;
802        let mut patterns = Vec::new();
803        parse_blank(t);
804        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
805        parse_blank(t);
806        parse_symbol(t, '{')?;
807        parse_blank(t);
808        let _ = parse_newline(t);
809        while let Some(()) = t.optional(|t| {
810            parse_blank(t);
811            let mut alternates = Vec::new();
812            if let Some(()) = parse_symbol(t, '(') {
813                while let Some(()) = t.optional(|t| {
814                    parse_blank(t);
815                    alternates.push(parse_const(t)?);
816                    Some(())
817                }) {}
818                parse_blank(t);
819                parse_symbol(t, ')')?;
820            } else {
821                alternates.push(parse_const(t)?);
822            }
823            parse_blank(t);
824            let _ = parse_newline(t);
825            patterns.push(alternates);
826            Some(())
827        }) {}
828        parse_blank(t);
829        parse_symbol(t, '}')?;
830        let ctx = t.context_mut();
831        let output =
832            ctx.design.add_cell_with_metadata_index(Cell::Match(MatchCell { value, enable, patterns }), metadata);
833        assert_eq!(output.len(), width, "cell output width must match declaration width");
834        ctx.add_def(index, width, output);
835        Some(())
836    }
837
838    fn parse_memory_init(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Const> {
839        parse_keyword_expect(t, "init")?;
840        parse_blank(t);
841        let value = parse_const(t)?;
842        let repeats = t
843            .optional(|t| {
844                parse_symbol(t, '*')?;
845                parse_decimal(t)
846            })
847            .unwrap_or(1);
848        Some(value.repeat(repeats))
849    }
850
851    fn parse_memory_write(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MemoryWritePort> {
852        parse_keyword_expect(t, "write")?;
853        parse_blank(t);
854        parse_keyword_eq_expect(t, "addr")?;
855        let addr = parse_value_arg(t)?;
856        parse_blank(t);
857        parse_keyword_eq_expect(t, "data")?;
858        let data = parse_value_arg(t)?;
859        parse_blank(t);
860        let mask = t
861            .optional(|t| {
862                parse_keyword_eq_expect(t, "mask")?;
863                parse_value_arg(t)
864            })
865            .unwrap_or_else(|| Value::ones(data.len()));
866        let clock = parse_control_arg(t, "clk")?;
867        Some(MemoryWritePort { addr, data, mask, clock })
868    }
869
870    fn parse_memory_read(
871        t: &mut WithContext<impl Tokens<Item = char>, Context>,
872    ) -> Option<(MemoryReadPort, usize, usize)> {
873        let (cell_index, width) = parse_cell_index_width(t)?;
874        parse_blank(t);
875        parse_symbol(t, '=')?;
876        parse_blank(t);
877        parse_keyword_expect(t, "read")?;
878        parse_blank(t);
879        parse_keyword_eq_expect(t, "addr")?;
880        let addr = parse_value_arg(t)?;
881        let flip_flop = t.optional(|t| {
882            let clock = parse_control_arg(t, "clk")?;
883            let (clear, clear_value) =
884                t.optional(|t| parse_dff_reset_control_net_arg(t, "clr")).unwrap_or((ControlNet::Pos(Net::ZERO), None));
885            let (reset, reset_value) =
886                t.optional(|t| parse_dff_reset_control_net_arg(t, "rst")).unwrap_or((ControlNet::Pos(Net::ZERO), None));
887            let enable = t.optional(|t| parse_control_arg(t, "en")).unwrap_or(ControlNet::Pos(Net::ONE));
888            let reset_over_enable = t.optional(|t| parse_reset_over_enable_arg(t)).unwrap_or(false);
889            let init_value = t.optional(|t| parse_dff_init_value_arg(t)).unwrap_or_else(|| Const::undef(width));
890            let mut relations = vec![];
891            parse_blank(t);
892            parse_symbol(t, '[')?;
893            while let Some(()) = t.optional(|t| {
894                parse_blank(t);
895                let keyword = parse_keyword(t)?;
896                relations.push(match keyword.as_str() {
897                    "undef" => MemoryPortRelation::Undefined,
898                    "rdfirst" => MemoryPortRelation::ReadBeforeWrite,
899                    "trans" => MemoryPortRelation::Transparent,
900                    _ => return None,
901                });
902                Some(())
903            }) {}
904            parse_blank(t);
905            parse_symbol(t, ']')?;
906            Some(MemoryReadFlipFlop {
907                clock,
908                clear,
909                clear_value: clear_value.unwrap_or_else(|| init_value.clone()),
910                reset,
911                reset_value: reset_value.unwrap_or_else(|| init_value.clone()),
912                enable,
913                reset_over_enable,
914                init_value,
915                relations,
916            })
917        });
918        Some((MemoryReadPort { addr, data_len: width, flip_flop }, cell_index, width))
919    }
920
921    fn parse_memory_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
922        parse_cell_index_placeholder(t)?;
923        parse_blank(t);
924        parse_symbol(t, '=')?;
925        parse_blank(t);
926        parse_keyword_expect(t, "memory")?;
927        parse_blank(t);
928        parse_keyword_eq_expect(t, "depth")?;
929        let memory_depth = parse_integer(t)?;
930        parse_blank(t);
931        parse_keyword_eq_expect(t, "width")?;
932        let memory_width = parse_integer(t)?;
933        parse_blank(t);
934        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
935        parse_blank(t);
936        parse_symbol(t, '{')?;
937        parse_blank(t);
938        parse_newline(t)?;
939        let mut init_value = Const::new();
940        let mut write_ports = Vec::new();
941        let mut read_ports = Vec::new();
942        let mut output = Value::new();
943        while let Some(()) = t.optional(|t| {
944            parse_blank(t);
945            one_of!(t;
946                parse_memory_init(t).map(|value| init_value.extend(value)),
947                parse_memory_write(t).map(|port| write_ports.push(port)),
948                parse_memory_read(t).map(|(port, index, width)| {
949                    read_ports.push(port);
950                    let ctx = t.context_mut();
951                    let value = ctx.design.add_void(width);
952                    ctx.add_def(index, width, value.clone());
953                    output = output.concat(value);
954                }),
955            );
956            parse_blank(t);
957            parse_newline(t)?;
958            Some(())
959        }) {}
960        parse_blank(t);
961        parse_symbol(t, '}')?;
962        let ctx = t.context_mut();
963        ctx.design.replace_value(
964            output,
965            ctx.design.add_cell_with_metadata_index(
966                Cell::Memory(Memory {
967                    depth: memory_depth,
968                    width: memory_width,
969                    init_value: init_value
970                        .concat(Const::undef((memory_depth * memory_width).checked_sub(init_value.len()).unwrap())),
971                    write_ports,
972                    read_ports,
973                }),
974                metadata,
975            ),
976        );
977        Some(())
978    }
979
980    fn parse_target_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
981        let (index, width) = one_of!(t;
982            parse_cell_index_width(t).map(|(index, width)| (index, Some(width))),
983            parse_cell_index_placeholder(t).map(|index| (index, None))
984        )?;
985        parse_blank(t);
986        parse_symbol(t, '=')?;
987        parse_blank(t);
988        parse_keyword_expect(t, "target")?;
989        parse_blank(t);
990        let (instance, metadata, output) = parse_instance(t)?;
991        let target = t.context().design.target().expect("no target specified");
992        let prototype = target.prototype(&instance.kind).expect("no prototype for target cell");
993        let mut target_cell = TargetCell::new(instance.kind.clone(), prototype);
994        for (name, value) in instance.params {
995            let target_param = prototype.get_param(&name).expect("unknown parameter");
996            if !target_param.kind.is_valid(&value) {
997                panic!("invalid value for parameter {name}");
998            }
999            target_cell.params[target_param.index] = value;
1000        }
1001        for (name, value) in instance.inputs {
1002            let target_input = prototype.get_input(&name).expect("unknown input");
1003            if value.len() != target_input.len() {
1004                panic!("width mismatch for input {name}");
1005            }
1006            target_cell.inputs[target_input.range.clone()].copy_from_slice(&value[..]);
1007        }
1008        for (name, value) in instance.ios {
1009            let target_io = prototype.get_io(&name).expect("unknown io");
1010            if value.len() != target_io.len() {
1011                panic!("width mismatch for io {name}");
1012            }
1013            target_cell.ios[target_io.range.clone()].copy_from_slice(&value[..]);
1014        }
1015        let ctx = t.context_mut();
1016        if let Some(width) = width {
1017            // %0:1 = target "SB_LUT" { .. }
1018            if !(instance.outputs.is_empty() && prototype.outputs.len() == 1 && prototype.output_len == width) {
1019                panic!("target instance should have a single implicit output of the right size")
1020            }
1021            ctx.add_def(index, width, ctx.design.add_cell_with_metadata_index(Cell::Target(target_cell), metadata));
1022        } else {
1023            // %0:_ = target "SB_LUT" { %0:1 = output "Y" .. }
1024            let target_cell_output = ctx.design.add_cell_with_metadata_index(Cell::Target(target_cell), metadata);
1025            for (name, range) in instance.outputs {
1026                let target_output = prototype.get_output(&name).expect("unknown output");
1027                if range.len() != target_output.len() {
1028                    panic!("width mismatch for output {name}");
1029                }
1030                ctx.design
1031                    .replace_value(output.slice(range.clone()), target_cell_output.slice(target_output.range.clone()));
1032            }
1033        }
1034        Some(())
1035    }
1036
1037    fn parse_other_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
1038        parse_cell_index_placeholder(t)?;
1039        parse_blank(t);
1040        parse_symbol(t, '=')?;
1041        parse_blank(t);
1042        let (instance, metadata, output) = parse_instance(t)?;
1043        let ctx = t.context_mut();
1044        ctx.design.replace_value(output, ctx.design.add_cell_with_metadata_index(Cell::Other(instance), metadata));
1045        Some(())
1046    }
1047
1048    one_of!(t;
1049        parse_simple_cell(t),
1050        parse_match_cell(t),
1051        parse_memory_cell(t),
1052        parse_target_cell(t),
1053        parse_other_cell(t),
1054    )?;
1055    parse_blank(t);
1056    parse_newline(t)?;
1057    Some(())
1058}
1059
1060fn parse_line(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> bool {
1061    parse_blank(t);
1062    one_of!(t;
1063        parse_target(t).is_some(),
1064        parse_metadata(t).is_some(),
1065        parse_io(t).is_some(),
1066        parse_cell(t).is_some(),
1067        parse_newline(t).is_some()
1068    )
1069}
1070
1071#[derive(Debug)]
1072pub struct ParseError {
1073    source: String,
1074    offset: usize,
1075}
1076
1077impl Display for ParseError {
1078    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1079        write!(f, "failed to parse near offset {}: {:?}", self.offset, &self.source[self.offset..])
1080    }
1081}
1082
1083impl std::error::Error for ParseError {}
1084
1085// Primarily used for testing, since an unregistered target can be provided directly.
1086pub fn parse(target: Option<Arc<dyn Target>>, source: &str) -> Result<Design, ParseError> {
1087    let context = Context::new(target);
1088    let mut tokens = source.into_tokens().with_context(context);
1089    while parse_line(&mut tokens) {}
1090    parse_blank(&mut tokens);
1091    let (mut tokens, context) = tokens.into_parts();
1092    if !tokens.eof() {
1093        return Err(ParseError { source: String::from(source), offset: tokens.location().offset() });
1094    }
1095    Ok(context.apply())
1096}
1097
1098impl FromStr for Design {
1099    type Err = crate::ParseError;
1100
1101    fn from_str(source: &str) -> Result<Self, Self::Err> {
1102        crate::parse(None, source)
1103    }
1104}