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>, use_map: BTreeMap<(usize, usize), Net>, }
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 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 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
1085pub 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}