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_digit(10) || *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_reset_over_enable_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<bool> {
571        parse_blank(t);
572        one_of!(t;
573            parse_keyword(t).filter(|kw| kw == "rst/en").map(|_| true),
574            parse_keyword(t).filter(|kw| kw == "en/rst").map(|_| false),
575        )
576    }
577
578    fn parse_dff_init_value_arg(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Const> {
579        parse_blank(t);
580        parse_keyword_eq_expect(t, "init")?;
581        parse_const(t)
582    }
583
584    fn parse_instance_param(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, ParamValue)> {
585        parse_keyword_expect(t, "param")?;
586        parse_blank(t);
587        let name = parse_string(t)?;
588        parse_blank(t);
589        parse_symbol(t, '=')?;
590        parse_blank(t);
591        let value = parse_param_value(t)?;
592        Some((name, value))
593    }
594
595    fn parse_instance_input(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, Value)> {
596        parse_keyword_expect(t, "input")?;
597        parse_blank(t);
598        let name = parse_string(t)?;
599        parse_blank(t);
600        parse_symbol(t, '=')?;
601        let value = parse_value_arg(t)?;
602        Some((name, value))
603    }
604
605    fn parse_instance_output(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, usize, usize)> {
606        let (cell_index, width) = parse_cell_index_width(t)?;
607        parse_blank(t);
608        parse_symbol(t, '=')?;
609        parse_blank(t);
610        parse_keyword_expect(t, "output")?;
611        parse_blank(t);
612        let name = parse_string(t)?;
613        Some((name, cell_index, width))
614    }
615
616    fn parse_instance_io(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<(String, IoValue)> {
617        parse_keyword_expect(t, "io")?;
618        parse_blank(t);
619        let name = parse_string(t)?;
620        parse_blank(t);
621        parse_symbol(t, '=')?;
622        parse_blank(t);
623        let io_value = parse_io_value(t)?;
624        Some((name, io_value))
625    }
626
627    fn parse_instance(
628        t: &mut WithContext<impl Tokens<Item = char>, Context>,
629    ) -> Option<(Instance, MetaItemIndex, Value)> {
630        let mut instance = Instance {
631            kind: parse_string(t)?,
632            params: BTreeMap::new(),
633            inputs: BTreeMap::new(),
634            outputs: BTreeMap::new(),
635            ios: BTreeMap::new(),
636        };
637        let mut output = Value::new();
638        parse_blank(t);
639        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
640        parse_blank(t);
641        parse_symbol(t, '{')?;
642        parse_blank(t);
643        parse_newline(t)?;
644        while let Some(()) = t.optional(|t| {
645            parse_blank(t);
646            one_of!(t;
647                parse_instance_param(t).map(|(name, value)|
648                    assert!(instance.params.insert(name, value).is_none(), "duplicate parameter name in instance")),
649                parse_instance_input(t).map(|(name, value)|
650                    assert!(instance.inputs.insert(name, value).is_none(), "duplicate input name in instance")),
651                parse_instance_output(t).map(|(name, index, width)| {
652                    let start = instance.output_len();
653                    assert!(
654                        instance.outputs.insert(name, start..start + width).is_none(),
655                        "duplicate output name in instance"
656                    );
657                    let ctx = t.context_mut();
658                    let value = ctx.design.add_void(width);
659                    ctx.add_def(index, width, value.clone());
660                    output = output.concat(value);
661                }),
662                parse_instance_io(t).map(|(name, io_value)|
663                    assert!(instance.ios.insert(name, io_value).is_none(), "duplicate IO name in instance"))
664            );
665            parse_blank(t);
666            parse_newline(t)?;
667            Some(())
668        }) {}
669        parse_blank(t);
670        parse_symbol(t, '}')?;
671        Some((instance, metadata, output))
672    }
673
674    fn parse_simple_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
675        let (index, width) = parse_cell_index_width(t)?;
676        parse_blank(t);
677        parse_symbol(t, '=')?;
678        parse_blank(t);
679        let keyword = parse_keyword(t)?;
680        let cell = match keyword.as_ref() {
681            "buf" => Cell::Buf(parse_value_arg(t)?),
682            "not" => Cell::Not(parse_value_arg(t)?),
683            "and" => Cell::And(parse_value_arg(t)?, parse_value_arg(t)?),
684            "or" => Cell::Or(parse_value_arg(t)?, parse_value_arg(t)?),
685            "xor" => Cell::Xor(parse_value_arg(t)?, parse_value_arg(t)?),
686            "mux" => Cell::Mux(parse_net_arg(t)?, parse_value_arg(t)?, parse_value_arg(t)?),
687            "adc" => Cell::Adc(parse_value_arg(t)?, parse_value_arg(t)?, parse_net_arg(t)?),
688            "aig" => Cell::Aig(parse_control_net_arg(t)?, parse_control_net_arg(t)?),
689            "eq" => Cell::Eq(parse_value_arg(t)?, parse_value_arg(t)?),
690            "ult" => Cell::ULt(parse_value_arg(t)?, parse_value_arg(t)?),
691            "slt" => Cell::SLt(parse_value_arg(t)?, parse_value_arg(t)?),
692            "shl" => Cell::Shl(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
693            "ushr" => Cell::UShr(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
694            "sshr" => Cell::SShr(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
695            "xshr" => Cell::XShr(parse_value_arg(t)?, parse_value_arg(t)?, parse_int_arg(t)? as u32),
696            "mul" => Cell::Mul(parse_value_arg(t)?, parse_value_arg(t)?),
697            "udiv" => Cell::UDiv(parse_value_arg(t)?, parse_value_arg(t)?),
698            "umod" => Cell::UMod(parse_value_arg(t)?, parse_value_arg(t)?),
699            "sdiv_trunc" => Cell::SDivTrunc(parse_value_arg(t)?, parse_value_arg(t)?),
700            "sdiv_floor" => Cell::SDivFloor(parse_value_arg(t)?, parse_value_arg(t)?),
701            "smod_trunc" => Cell::SModTrunc(parse_value_arg(t)?, parse_value_arg(t)?),
702            "smod_floor" => Cell::SModFloor(parse_value_arg(t)?, parse_value_arg(t)?),
703            "assign" => {
704                let enable = t
705                    .optional(|t| {
706                        parse_blank(t);
707                        parse_keyword_eq_expect(t, "en")?;
708                        parse_net_arg(t)
709                    })
710                    .unwrap_or(Net::ONE);
711                let value = parse_value_arg(t)?;
712                let update = parse_value_arg(t)?;
713                let offset = t
714                    .optional(|t| {
715                        parse_blank(t);
716                        parse_keyword_eq_expect(t, "at")?;
717                        parse_integer(t)
718                    })
719                    .unwrap_or(0);
720                Cell::Assign(AssignCell { value, enable, update, offset })
721            }
722            "dff" => {
723                let data = parse_value_arg(t)?;
724                let clock = parse_control_arg(t, "clk")?;
725                let (clear, clear_value) = t
726                    .optional(|t| parse_dff_reset_control_net_arg(t, "clr"))
727                    .unwrap_or((ControlNet::Pos(Net::ZERO), None));
728                let (reset, reset_value) = t
729                    .optional(|t| parse_dff_reset_control_net_arg(t, "rst"))
730                    .unwrap_or((ControlNet::Pos(Net::ZERO), None));
731                let enable = t.optional(|t| parse_control_arg(t, "en")).unwrap_or(ControlNet::Pos(Net::ONE));
732                let reset_over_enable = t.optional(|t| parse_reset_over_enable_arg(t)).unwrap_or(false);
733                let init_value =
734                    t.optional(|t| parse_dff_init_value_arg(t)).unwrap_or_else(|| Const::undef(data.len()));
735                Cell::Dff(FlipFlop {
736                    data,
737                    clock,
738                    clear,
739                    clear_value: clear_value.unwrap_or_else(|| init_value.clone()),
740                    reset,
741                    reset_value: reset_value.unwrap_or_else(|| init_value.clone()),
742                    enable,
743                    reset_over_enable,
744                    init_value,
745                })
746            }
747            "iobuf" => {
748                parse_blank(t);
749                let io = parse_io_value(t)?;
750                parse_blank(t);
751                parse_keyword_eq_expect(t, "o")?;
752                let output = parse_value_arg(t)?;
753                let enable = parse_control_arg(t, "en")?;
754                Cell::IoBuf(IoBuffer { io, output, enable })
755            }
756            "input" => Cell::Input(parse_string_arg(t)?, width),
757            "output" => Cell::Output(parse_string_arg(t)?, parse_value_arg(t)?),
758            "name" => Cell::Name(parse_string_arg(t)?, parse_value_arg(t)?),
759            "debug" => Cell::Debug(parse_string_arg(t)?, parse_value_arg(t)?),
760            _ => return None,
761        };
762        parse_blank(t);
763        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
764        let ctx = t.context_mut();
765        let output = ctx.design.add_cell_with_metadata_index(cell, metadata);
766        assert_eq!(output.len(), width, "cell output width must match declaration width");
767        ctx.add_def(index, width, output);
768        Some(())
769    }
770
771    fn parse_match_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
772        let (index, width) = parse_cell_index_width(t)?;
773        parse_blank(t);
774        parse_symbol(t, '=')?;
775        parse_blank(t);
776        parse_keyword_expect(t, "match")?;
777        parse_blank(t);
778        let enable = t
779            .optional(|t| {
780                parse_blank(t);
781                parse_keyword_eq_expect(t, "en")?;
782                parse_net_arg(t)
783            })
784            .unwrap_or(Net::ONE);
785        let value = parse_value_arg(t)?;
786        let mut patterns = Vec::new();
787        parse_blank(t);
788        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
789        parse_blank(t);
790        parse_symbol(t, '{')?;
791        parse_blank(t);
792        let _ = parse_newline(t);
793        while let Some(()) = t.optional(|t| {
794            parse_blank(t);
795            let mut alternates = Vec::new();
796            if let Some(()) = parse_symbol(t, '(') {
797                while let Some(()) = t.optional(|t| {
798                    parse_blank(t);
799                    alternates.push(parse_const(t)?);
800                    Some(())
801                }) {}
802                parse_blank(t);
803                parse_symbol(t, ')')?;
804            } else {
805                alternates.push(parse_const(t)?);
806            }
807            parse_blank(t);
808            let _ = parse_newline(t);
809            patterns.push(alternates);
810            Some(())
811        }) {}
812        parse_blank(t);
813        parse_symbol(t, '}')?;
814        let ctx = t.context_mut();
815        let output =
816            ctx.design.add_cell_with_metadata_index(Cell::Match(MatchCell { value, enable, patterns }), metadata);
817        assert_eq!(output.len(), width, "cell output width must match declaration width");
818        ctx.add_def(index, width, output);
819        Some(())
820    }
821
822    fn parse_memory_init(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<Const> {
823        parse_keyword_expect(t, "init")?;
824        parse_blank(t);
825        let value = parse_const(t)?;
826        let repeats = t
827            .optional(|t| {
828                parse_symbol(t, '*')?;
829                parse_decimal(t)
830            })
831            .unwrap_or(1);
832        Some(value.repeat(repeats))
833    }
834
835    fn parse_memory_write(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<MemoryWritePort> {
836        parse_keyword_expect(t, "write")?;
837        parse_blank(t);
838        parse_keyword_eq_expect(t, "addr")?;
839        let addr = parse_value_arg(t)?;
840        parse_blank(t);
841        parse_keyword_eq_expect(t, "data")?;
842        let data = parse_value_arg(t)?;
843        parse_blank(t);
844        let mask = t
845            .optional(|t| {
846                parse_keyword_eq_expect(t, "mask")?;
847                parse_value_arg(t)
848            })
849            .unwrap_or_else(|| Value::ones(data.len()));
850        let clock = parse_control_arg(t, "clk")?;
851        Some(MemoryWritePort { addr, data, mask, clock })
852    }
853
854    fn parse_memory_read(
855        t: &mut WithContext<impl Tokens<Item = char>, Context>,
856    ) -> Option<(MemoryReadPort, usize, usize)> {
857        let (cell_index, width) = parse_cell_index_width(t)?;
858        parse_blank(t);
859        parse_symbol(t, '=')?;
860        parse_blank(t);
861        parse_keyword_expect(t, "read")?;
862        parse_blank(t);
863        parse_keyword_eq_expect(t, "addr")?;
864        let addr = parse_value_arg(t)?;
865        let flip_flop = t.optional(|t| {
866            let clock = parse_control_arg(t, "clk")?;
867            let (clear, clear_value) =
868                t.optional(|t| parse_dff_reset_control_net_arg(t, "clr")).unwrap_or((ControlNet::Pos(Net::ZERO), None));
869            let (reset, reset_value) =
870                t.optional(|t| parse_dff_reset_control_net_arg(t, "rst")).unwrap_or((ControlNet::Pos(Net::ZERO), None));
871            let enable = t.optional(|t| parse_control_arg(t, "en")).unwrap_or(ControlNet::Pos(Net::ONE));
872            let reset_over_enable = t.optional(|t| parse_reset_over_enable_arg(t)).unwrap_or(false);
873            let init_value = t.optional(|t| parse_dff_init_value_arg(t)).unwrap_or_else(|| Const::undef(width));
874            let mut relations = vec![];
875            parse_blank(t);
876            parse_symbol(t, '[')?;
877            while let Some(()) = t.optional(|t| {
878                parse_blank(t);
879                let keyword = parse_keyword(t)?;
880                relations.push(match keyword.as_str() {
881                    "undef" => MemoryPortRelation::Undefined,
882                    "rdfirst" => MemoryPortRelation::ReadBeforeWrite,
883                    "trans" => MemoryPortRelation::Transparent,
884                    _ => return None,
885                });
886                Some(())
887            }) {}
888            parse_blank(t);
889            parse_symbol(t, ']')?;
890            Some(MemoryReadFlipFlop {
891                clock,
892                clear,
893                clear_value: clear_value.unwrap_or_else(|| init_value.clone()),
894                reset,
895                reset_value: reset_value.unwrap_or_else(|| init_value.clone()),
896                enable,
897                reset_over_enable,
898                init_value,
899                relations,
900            })
901        });
902        Some((MemoryReadPort { addr, data_len: width, flip_flop }, cell_index, width))
903    }
904
905    fn parse_memory_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
906        parse_cell_index_placeholder(t)?;
907        parse_blank(t);
908        parse_symbol(t, '=')?;
909        parse_blank(t);
910        parse_keyword_expect(t, "memory")?;
911        parse_blank(t);
912        parse_keyword_eq_expect(t, "depth")?;
913        let memory_depth = parse_integer(t)?;
914        parse_blank(t);
915        parse_keyword_eq_expect(t, "width")?;
916        let memory_width = parse_integer(t)?;
917        parse_blank(t);
918        let metadata = parse_metadata_ref(t).unwrap_or(MetaItemIndex::NONE);
919        parse_blank(t);
920        parse_symbol(t, '{')?;
921        parse_blank(t);
922        parse_newline(t)?;
923        let mut init_value = Const::new();
924        let mut write_ports = Vec::new();
925        let mut read_ports = Vec::new();
926        let mut output = Value::new();
927        while let Some(()) = t.optional(|t| {
928            parse_blank(t);
929            one_of!(t;
930                parse_memory_init(t).map(|value| init_value.extend(value)),
931                parse_memory_write(t).map(|port| write_ports.push(port)),
932                parse_memory_read(t).map(|(port, index, width)| {
933                    read_ports.push(port);
934                    let ctx = t.context_mut();
935                    let value = ctx.design.add_void(width);
936                    ctx.add_def(index, width, value.clone());
937                    output = output.concat(value);
938                }),
939            );
940            parse_blank(t);
941            parse_newline(t)?;
942            Some(())
943        }) {}
944        parse_blank(t);
945        parse_symbol(t, '}')?;
946        let ctx = t.context_mut();
947        ctx.design.replace_value(
948            output,
949            ctx.design.add_cell_with_metadata_index(
950                Cell::Memory(Memory {
951                    depth: memory_depth,
952                    width: memory_width,
953                    init_value: init_value
954                        .concat(Const::undef((memory_depth * memory_width).checked_sub(init_value.len()).unwrap())),
955                    write_ports,
956                    read_ports,
957                }),
958                metadata,
959            ),
960        );
961        Some(())
962    }
963
964    fn parse_target_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
965        let (index, width) = one_of!(t;
966            parse_cell_index_width(t).map(|(index, width)| (index, Some(width))),
967            parse_cell_index_placeholder(t).map(|index| (index, None))
968        )?;
969        parse_blank(t);
970        parse_symbol(t, '=')?;
971        parse_blank(t);
972        parse_keyword_expect(t, "target")?;
973        parse_blank(t);
974        let (instance, metadata, output) = parse_instance(t)?;
975        let target = t.context().design.target().expect("no target specified");
976        let prototype = target.prototype(&instance.kind).expect("no prototype for target cell");
977        let mut target_cell = TargetCell::new(instance.kind.clone(), prototype);
978        for (name, value) in instance.params {
979            let target_param = prototype.get_param(&name).expect("unknown parameter");
980            if !target_param.kind.is_valid(&value) {
981                panic!("invalid value for parameter {name}");
982            }
983            target_cell.params[target_param.index] = value;
984        }
985        for (name, value) in instance.inputs {
986            let target_input = prototype.get_input(&name).expect("unknown input");
987            if value.len() != target_input.len() {
988                panic!("width mismatch for input {name}");
989            }
990            target_cell.inputs[target_input.range.clone()].copy_from_slice(&value[..]);
991        }
992        for (name, value) in instance.ios {
993            let target_io = prototype.get_io(&name).expect("unknown io");
994            if value.len() != target_io.len() {
995                panic!("width mismatch for io {name}");
996            }
997            target_cell.ios[target_io.range.clone()].copy_from_slice(&value[..]);
998        }
999        let ctx = t.context_mut();
1000        if let Some(width) = width {
1001            // %0:1 = target "SB_LUT" { .. }
1002            if !(instance.outputs.is_empty() && prototype.outputs.len() == 1 && prototype.output_len == width) {
1003                panic!("target instance should have a single implicit output of the right size")
1004            }
1005            ctx.add_def(index, width, ctx.design.add_cell_with_metadata_index(Cell::Target(target_cell), metadata));
1006        } else {
1007            // %0:_ = target "SB_LUT" { %0:1 = output "Y" .. }
1008            let target_cell_output = ctx.design.add_cell_with_metadata_index(Cell::Target(target_cell), metadata);
1009            for (name, range) in instance.outputs {
1010                let target_output = prototype.get_output(&name).expect("unknown output");
1011                if range.len() != target_output.len() {
1012                    panic!("width mismatch for output {name}");
1013                }
1014                ctx.design
1015                    .replace_value(output.slice(range.clone()), target_cell_output.slice(target_output.range.clone()));
1016            }
1017        }
1018        Some(())
1019    }
1020
1021    fn parse_other_cell(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> Option<()> {
1022        parse_cell_index_placeholder(t)?;
1023        parse_blank(t);
1024        parse_symbol(t, '=')?;
1025        parse_blank(t);
1026        let (instance, metadata, output) = parse_instance(t)?;
1027        let ctx = t.context_mut();
1028        ctx.design.replace_value(output, ctx.design.add_cell_with_metadata_index(Cell::Other(instance), metadata));
1029        Some(())
1030    }
1031
1032    one_of!(t;
1033        parse_simple_cell(t),
1034        parse_match_cell(t),
1035        parse_memory_cell(t),
1036        parse_target_cell(t),
1037        parse_other_cell(t),
1038    )?;
1039    parse_blank(t);
1040    parse_newline(t)?;
1041    Some(())
1042}
1043
1044fn parse_line(t: &mut WithContext<impl Tokens<Item = char>, Context>) -> bool {
1045    parse_blank(t);
1046    one_of!(t;
1047        parse_target(t).is_some(),
1048        parse_metadata(t).is_some(),
1049        parse_io(t).is_some(),
1050        parse_cell(t).is_some(),
1051        parse_newline(t).is_some()
1052    )
1053}
1054
1055#[derive(Debug)]
1056pub struct ParseError {
1057    source: String,
1058    offset: usize,
1059}
1060
1061impl Display for ParseError {
1062    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1063        write!(f, "failed to parse near offset {}: {:?}", self.offset, &self.source[self.offset..])
1064    }
1065}
1066
1067impl std::error::Error for ParseError {}
1068
1069// Primarily used for testing, since an unregistered target can be provided directly.
1070pub fn parse(target: Option<Arc<dyn Target>>, source: &str) -> Result<Design, ParseError> {
1071    let context = Context::new(target);
1072    let mut tokens = source.into_tokens().with_context(context);
1073    while parse_line(&mut tokens) {}
1074    parse_blank(&mut tokens);
1075    let (mut tokens, context) = tokens.into_parts();
1076    if !tokens.eof() {
1077        return Err(ParseError { source: String::from(source), offset: tokens.location().offset() });
1078    }
1079    Ok(context.apply())
1080}
1081
1082impl FromStr for Design {
1083    type Err = crate::ParseError;
1084
1085    fn from_str(source: &str) -> Result<Self, Self::Err> {
1086        crate::parse(None, source)
1087    }
1088}