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_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 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 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
1069pub 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}