1use std::{borrow::Cow, fmt::Display};
2
3use crate::{
4 metadata::MetaItemIndex, Cell, CellRef, Const, ControlNet, Design, IoNet, IoValue, MemoryPortRelation, Net,
5 TargetOutput, Trit, Value,
6};
7
8struct DisplayFn<'a, F: for<'b> Fn(&Design, &mut std::fmt::Formatter<'b>) -> std::fmt::Result>(&'a Design, F);
9
10impl<F: Fn(&Design, &mut std::fmt::Formatter) -> std::fmt::Result> Display for DisplayFn<'_, F> {
11 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
12 self.1(self.0, f)
13 }
14}
15
16impl Design {
17 fn find_cell_output(&self, net: Net) -> Result<(Value, usize, usize), Trit> {
20 if let Some(val) = net.as_const() {
21 return Err(val);
22 }
23 let (cell_ref, offset) = self.find_cell(net);
24 let cell_index = cell_ref.debug_index();
25 match &*cell_ref.get() {
26 Cell::Other(instance) => {
27 for range in instance.outputs.values() {
28 if range.contains(&offset) {
29 return Ok((
30 cell_ref.output().slice(range.clone()),
31 cell_index + range.start,
32 offset - range.start,
33 ));
34 }
35 }
36 unreachable!()
37 }
38 Cell::Target(target_cell) => {
39 let prototype = self.target_prototype(target_cell);
40 for TargetOutput { range, .. } in &prototype.outputs {
41 if range.contains(&offset) {
42 return Ok((
43 cell_ref.output().slice(range.clone()),
44 cell_index + range.start,
45 offset - range.start,
46 ));
47 }
48 }
49 unreachable!()
50 }
51 Cell::Memory(memory) => {
52 let mut port_offset = 0;
53 for port in &memory.read_ports {
54 let port_range = port_offset..port_offset + port.data_len;
55 if port_range.contains(&offset) {
56 return Ok((
57 cell_ref.output().slice(port_range.clone()),
58 cell_index + port_range.start,
59 offset - port_range.start,
60 ));
61 }
62 port_offset += port.data_len;
63 }
64 unreachable!()
65 }
66 _ => Ok((cell_ref.output(), cell_index, offset)),
67 }
68 }
69
70 pub(crate) fn write_string(f: &mut std::fmt::Formatter, str: &str) -> std::fmt::Result {
71 write!(f, "\"")?;
72 for byte in str.as_bytes() {
73 if (byte.is_ascii_graphic() || matches!(byte, b' ' | b'\t')) && ![b'\\', b'"'].contains(byte) {
74 write!(f, "{}", *byte as char)?;
75 } else {
76 assert!(byte.is_ascii());
77 write!(f, "\\{byte:02x}")?;
78 }
79 }
80 write!(f, "\"")?;
81 Ok(())
82 }
83
84 pub(crate) fn write_io_net(&self, f: &mut std::fmt::Formatter, io_net: IoNet) -> std::fmt::Result {
85 if io_net.is_floating() {
86 write!(f, "&_")
87 } else {
88 write!(f, "&")?;
89 match self.find_io(io_net) {
90 Some((name, offset)) => {
91 Design::write_string(f, name)?;
92 if self.get_io(name).unwrap().len() > 1 {
93 write!(f, "+{offset}")?;
94 }
95 Ok(())
96 }
97 None => write!(f, "??"),
98 }
99 }
100 }
101
102 pub(crate) fn write_io_value(&self, f: &mut std::fmt::Formatter, io_value: &IoValue) -> std::fmt::Result {
103 if io_value.is_empty() {
104 write!(f, "[]")
105 } else if io_value.len() == 1 {
106 self.write_io_net(f, io_value[0])
107 } else if io_value.iter().all(IoNet::is_floating) {
108 write!(f, "&_:{}", io_value.len())
109 } else {
110 if let Some((name, _offset)) = self.find_io(io_value[0])
111 && self.get_io(name).unwrap() == *io_value
112 {
113 write!(f, "&")?;
114 Design::write_string(f, name)?;
115 write!(f, ":{}", io_value.len())?;
116 return Ok(());
117 }
118 write!(f, "[")?;
119 for io_net in io_value.iter().rev() {
120 write!(f, " ")?;
121 self.write_io_net(f, io_net)?;
122 }
123 write!(f, " ]")
124 }
125 }
126
127 pub(crate) fn write_net(&self, f: &mut std::fmt::Formatter, net: Net) -> std::fmt::Result {
128 let index = net.as_cell_index();
129 if !self.is_valid_cell_index(index) {
130 return write!(f, "%_{index}");
131 }
132 match self.find_cell_output(net) {
133 Ok((output, index, offset)) => {
134 if output.len() == 1 {
135 write!(f, "%{index}")
136 } else {
137 write!(f, "%{index}+{offset}")
138 }
139 }
140 Err(trit) => write!(f, "{trit}"),
141 }
142 }
143
144 pub(crate) fn write_control_net(&self, f: &mut std::fmt::Formatter, control_net: ControlNet) -> std::fmt::Result {
145 if control_net.is_negative() {
146 write!(f, "!")?;
147 };
148 self.write_net(f, control_net.net())
149 }
150
151 pub(crate) fn write_value(&self, f: &mut std::fmt::Formatter, value: &Value) -> std::fmt::Result {
152 enum Chunk {
153 Slice { cell_index: usize, offset: usize, width: usize, repeat: usize },
154 WholeGrainCell { cell_index: usize, width: usize, repeat: usize },
155 NewNet { net: Net, repeat: usize },
156 Const(Const),
157 }
158 let mut index = 0;
159 let mut chunks = vec![];
160 while index < value.len() {
161 if !self.is_valid_cell_index(value[index].as_cell_index()) {
162 let mut repeat = 1;
165 while index + repeat < value.len() && value[index] == value[index + repeat] {
166 repeat += 1;
167 }
168 chunks.push(Chunk::NewNet { net: value[index], repeat });
169 index += repeat;
170 } else if let Ok((output, index_a, offset_a)) = self.find_cell_output(value[index]) {
171 let count = value[index..]
172 .iter()
173 .enumerate()
174 .take_while(|(addend, net)| {
175 if let Ok((_, index_b, offset_b)) = self.find_cell_output(**net) {
176 index_a == index_b && offset_a + *addend == offset_b
177 } else {
178 false
179 }
180 })
181 .count();
182 assert!(count != 0);
183 let mut repeat = 1;
184 while index + (repeat + 1) * count <= value.len()
185 && value[index..index + count] == value[index + repeat * count..index + (repeat + 1) * count]
186 {
187 repeat += 1;
188 }
189 if offset_a == 0 && output.len() == count {
190 chunks.push(Chunk::WholeGrainCell { cell_index: index_a, width: count, repeat });
191 } else {
192 chunks.push(Chunk::Slice { cell_index: index_a, offset: offset_a, width: count, repeat });
193 }
194 index += count * repeat;
195 } else {
196 let const_value = Const::from_iter(
197 value[index..].iter().take_while(|net| net.as_const().is_some()).map(|net| net.as_const().unwrap()),
198 );
199 assert!(!const_value.is_empty());
200 index += const_value.len();
201 chunks.push(Chunk::Const(const_value));
202 }
203 }
204 if chunks.is_empty() {
205 return write!(f, "[]");
206 }
207 let single_chunk = chunks.len() == 1;
208 if !single_chunk {
209 write!(f, "[")?;
210 }
211 for chunk in chunks.into_iter().rev() {
212 if !single_chunk {
213 write!(f, " ")?;
214 }
215 match chunk {
216 Chunk::Slice { cell_index, offset, width, repeat } => {
217 write!(f, "%{cell_index}+{offset}")?;
218 if width != 1 {
219 write!(f, ":{width}")?;
220 }
221 if repeat != 1 {
222 write!(f, "*{repeat}")?;
223 }
224 }
225 Chunk::WholeGrainCell { cell_index, width, repeat } => {
226 write!(f, "%{cell_index}")?;
227 if width != 1 {
228 write!(f, ":{width}")?;
229 }
230 if repeat != 1 {
231 write!(f, "*{repeat}")?;
232 }
233 }
234 Chunk::Const(const_value) => {
235 write!(f, "{const_value}")?;
236 }
237 Chunk::NewNet { net, repeat } => {
238 self.write_net(f, net)?;
239 if repeat != 1 {
240 write!(f, "*{repeat}")?;
241 }
242 }
243 }
244 }
245 if !single_chunk {
246 write!(f, " ]")?;
247 }
248 Ok(())
249 }
250
251 pub(crate) fn write_cell(
252 &self,
253 f: &mut std::fmt::Formatter,
254 prefix: &str,
255 index: usize,
256 cell: &Cell,
257 metadata: MetaItemIndex,
258 ) -> std::fmt::Result {
259 let newline = &format!("\n{prefix}");
260
261 let write_metadata = |f: &mut std::fmt::Formatter| -> std::fmt::Result {
262 if metadata != MetaItemIndex::NONE { write!(f, " {metadata}") } else { Ok(()) }
263 };
264
265 let write_control = |f: &mut std::fmt::Formatter, name: &str, control_net: ControlNet| -> std::fmt::Result {
266 write!(f, "{name}=")?;
267 self.write_control_net(f, control_net)
268 };
269
270 let write_common = |f: &mut std::fmt::Formatter, name: &str, args: &[&Value]| -> std::fmt::Result {
271 write!(f, "{name}")?;
272 for arg in args {
273 write!(f, " ")?;
274 self.write_value(f, arg)?;
275 }
276 Ok(())
277 };
278
279 let write_shift =
280 |f: &mut std::fmt::Formatter, name: &str, arg1: &Value, arg2: &Value, stride: u32| -> std::fmt::Result {
281 write!(f, "{name} ")?;
282 self.write_value(f, arg1)?;
283 write!(f, " ")?;
284 self.write_value(f, arg2)?;
285 write!(f, " #{stride}")?;
286 Ok(())
287 };
288
289 let write_cell_argument = |f: &mut std::fmt::Formatter, keyword: &str, name: &str| -> std::fmt::Result {
290 write!(f, " {keyword} ")?;
291 Design::write_string(f, name)?;
292 write!(f, " = ")?;
293 Ok(())
294 };
295
296 let single_output = match &cell {
297 Cell::Other(..) => false,
298 Cell::Target(target_cell) if self.target_prototype(target_cell).outputs.len() > 1 => false,
299 Cell::Memory(..) => false,
300 _ => true,
301 };
302 if single_output {
303 write!(f, "{prefix}%{index}:{width} = ", width = cell.output_len())?;
304 } else {
305 write!(f, "{prefix}%{index}:_ = ")?; }
307 match &cell {
308 Cell::Const(trit) => write!(f, "const {trit}")?,
309 Cell::Buf(arg) => write_common(f, "buf", &[arg])?,
310 Cell::Not(arg) => write_common(f, "not", &[arg])?,
311 Cell::And(arg1, arg2) => write_common(f, "and", &[arg1, arg2])?,
312 Cell::Or(arg1, arg2) => write_common(f, "or", &[arg1, arg2])?,
313 Cell::Xor(arg1, arg2) => write_common(f, "xor", &[arg1, arg2])?,
314 Cell::Mux(arg1, arg2, arg3) => {
315 write!(f, "mux ")?;
316 self.write_net(f, *arg1)?;
317 write!(f, " ")?;
318 self.write_value(f, arg2)?;
319 write!(f, " ")?;
320 self.write_value(f, arg3)?;
321 }
322 Cell::Adc(arg1, arg2, arg3) => {
323 write!(f, "adc ")?;
324 self.write_value(f, arg1)?;
325 write!(f, " ")?;
326 self.write_value(f, arg2)?;
327 write!(f, " ")?;
328 self.write_net(f, *arg3)?;
329 }
330 Cell::Aig(arg1, arg2) => {
331 write!(f, "aig ")?;
332 self.write_control_net(f, *arg1)?;
333 write!(f, " ")?;
334 self.write_control_net(f, *arg2)?;
335 }
336
337 Cell::Eq(arg1, arg2) => write_common(f, "eq", &[arg1, arg2])?,
338 Cell::ULt(arg1, arg2) => write_common(f, "ult", &[arg1, arg2])?,
339 Cell::SLt(arg1, arg2) => write_common(f, "slt", &[arg1, arg2])?,
340
341 Cell::Shl(arg1, arg2, stride) => write_shift(f, "shl", arg1, arg2, *stride)?,
342 Cell::UShr(arg1, arg2, stride) => write_shift(f, "ushr", arg1, arg2, *stride)?,
343 Cell::SShr(arg1, arg2, stride) => write_shift(f, "sshr", arg1, arg2, *stride)?,
344 Cell::XShr(arg1, arg2, stride) => write_shift(f, "xshr", arg1, arg2, *stride)?,
345
346 Cell::Mul(arg1, arg2) => write_common(f, "mul", &[arg1, arg2])?,
347 Cell::UDiv(arg1, arg2) => write_common(f, "udiv", &[arg1, arg2])?,
348 Cell::UMod(arg1, arg2) => write_common(f, "umod", &[arg1, arg2])?,
349 Cell::SDivTrunc(arg1, arg2) => write_common(f, "sdiv_trunc", &[arg1, arg2])?,
350 Cell::SDivFloor(arg1, arg2) => write_common(f, "sdiv_floor", &[arg1, arg2])?,
351 Cell::SModTrunc(arg1, arg2) => write_common(f, "smod_trunc", &[arg1, arg2])?,
352 Cell::SModFloor(arg1, arg2) => write_common(f, "smod_floor", &[arg1, arg2])?,
353
354 Cell::Match(match_cell) => {
355 write!(f, "match")?;
356 if match_cell.enable != Net::ONE {
357 write!(f, " en=")?;
358 self.write_net(f, match_cell.enable)?;
359 }
360 write!(f, " ")?;
361 self.write_value(f, &match_cell.value)?;
362 let multiline = match_cell
363 .patterns
364 .iter()
365 .map(|alternates| alternates.iter().map(Const::len).sum::<usize>())
366 .sum::<usize>()
367 > 80;
368 write_metadata(f)?;
369 write!(f, " {{")?;
370 if multiline {
371 write!(f, "{newline}")?;
372 }
373 for alternates in &match_cell.patterns {
374 if multiline {
375 write!(f, " ")?;
376 } else {
377 write!(f, " ")?;
378 }
379 if alternates.len() == 1 {
380 let pattern = &alternates[0];
381 write!(f, "{pattern}")?;
382 } else {
383 write!(f, "(")?;
384 for (index, pattern) in alternates.iter().enumerate() {
385 if index > 0 {
386 write!(f, " ")?;
387 }
388 write!(f, "{pattern}")?;
389 }
390 write!(f, ")")?;
391 }
392 if multiline {
393 write!(f, "{newline}")?;
394 }
395 }
396 if !multiline {
397 write!(f, " ")?;
398 }
399 write!(f, "}}")?;
400 }
401 Cell::Assign(assign_cell) => {
402 write!(f, "assign")?;
403 if assign_cell.enable != Net::ONE {
404 write!(f, " en=")?;
405 self.write_net(f, assign_cell.enable)?;
406 }
407 write!(f, " ")?;
408 self.write_value(f, &assign_cell.value)?;
409 write!(f, " ")?;
410 self.write_value(f, &assign_cell.update)?;
411 if assign_cell.offset != 0 {
412 write!(f, " at=#{}", assign_cell.offset)?;
413 }
414 }
415
416 Cell::Dff(flip_flop) => {
417 write_common(f, "dff", &[&flip_flop.data])?;
418 write_control(f, " clk", flip_flop.clock)?;
419 if flip_flop.has_clear() {
420 write_control(f, " clr", flip_flop.clear)?;
421 if flip_flop.clear_value != flip_flop.init_value {
422 write!(f, ",{}", flip_flop.clear_value)?;
423 }
424 }
425 if flip_flop.has_load() {
426 write_control(f, " load", flip_flop.load)?;
427 write!(f, ",")?;
428 self.write_value(f, &flip_flop.load_data)?;
429 }
430 if flip_flop.has_reset() {
431 write_control(f, " rst", flip_flop.reset)?;
432 if flip_flop.reset_value != flip_flop.init_value {
433 write!(f, ",{}", flip_flop.reset_value)?;
434 }
435 }
436 if flip_flop.has_enable() {
437 write_control(f, " en", flip_flop.enable)?;
438 }
439 if flip_flop.has_reset() && flip_flop.has_enable() {
440 if flip_flop.reset_over_enable {
441 write!(f, " rst/en")?;
442 } else {
443 write!(f, " en/rst")?;
444 }
445 }
446 if flip_flop.has_init_value() {
447 write!(f, " init={}", flip_flop.init_value)?;
448 }
449 }
450 Cell::Memory(memory) => {
451 write!(f, "memory depth=#{} width=#{}", memory.depth, memory.width)?;
452 write_metadata(f)?;
453 write!(f, " {{{newline}")?;
454 for write_port in &memory.write_ports {
455 write!(f, " write addr=")?;
456 self.write_value(f, &write_port.addr)?;
457 write!(f, " data=")?;
458 self.write_value(f, &write_port.data)?;
459 if !write_port.mask.is_ones() {
460 write!(f, " mask=")?;
461 self.write_value(f, &write_port.mask)?;
462 }
463 write_control(f, " clk", write_port.clock)?;
464 write!(f, "{newline}")?;
465 }
466 let mut port_offset = 0;
467 for read_port in &memory.read_ports {
468 write!(f, " %{}:{} = read addr=", index + port_offset, read_port.data_len)?;
469 self.write_value(f, &read_port.addr)?;
470 if let Some(ref flip_flop) = read_port.flip_flop {
471 write_control(f, " clk", flip_flop.clock)?;
472 if flip_flop.has_clear() {
473 write_control(f, " clr", flip_flop.clear)?;
474 if flip_flop.clear_value != flip_flop.init_value {
475 write!(f, ",{}", flip_flop.clear_value)?;
476 }
477 }
478 if flip_flop.has_reset() {
479 write_control(f, " rst", flip_flop.reset)?;
480 if flip_flop.reset_value != flip_flop.init_value {
481 write!(f, ",{}", flip_flop.reset_value)?;
482 }
483 }
484 if flip_flop.has_enable() {
485 write_control(f, " en", flip_flop.enable)?;
486 }
487 if flip_flop.has_reset() && flip_flop.has_enable() {
488 if flip_flop.reset_over_enable {
489 write!(f, " rst/en")?;
490 } else {
491 write!(f, " en/rst")?;
492 }
493 }
494 if flip_flop.has_init_value() {
495 write!(f, " init={}", flip_flop.init_value)?;
496 }
497 write!(f, " [")?;
498 for (index, relation) in flip_flop.relations.iter().enumerate() {
499 match relation {
500 MemoryPortRelation::Undefined => write!(f, "undef")?,
501 MemoryPortRelation::ReadBeforeWrite => write!(f, "rdfirst")?,
502 MemoryPortRelation::Transparent => write!(f, "trans")?,
503 }
504 if index < flip_flop.relations.len() - 1 {
505 write!(f, " ")?;
506 }
507 }
508 write!(f, "]")?;
509 }
510 write!(f, "{newline}")?;
511 port_offset += read_port.data_len;
512 }
513 let mut rows = Vec::new();
514 for index in 0..memory.depth {
515 rows.push(memory.init_value.slice((index * memory.width)..((index + 1) * memory.width)));
516 }
517 let mut index = 0;
518 while index < rows.len() {
519 write!(f, " init {}", rows[index])?;
520 let mut repeats = 1;
521 while rows.get(index) == rows.get(index + repeats) {
522 repeats += 1;
523 }
524 if repeats > 1 {
525 write!(f, "*{repeats}")?;
526 }
527 write!(f, "{newline}")?;
528 index += repeats;
529 }
530 write!(f, "}}")?;
531 }
532 Cell::IoBuf(io_buffer) => {
533 write!(f, "iobuf ")?;
534 self.write_io_value(f, &io_buffer.io)?;
535 write!(f, " o=")?;
536 self.write_value(f, &io_buffer.output)?;
537 write_control(f, " en", io_buffer.enable)?;
538 }
539 Cell::Other(instance) => {
540 Design::write_string(f, instance.kind.as_str())?;
541 write_metadata(f)?;
542 write!(f, " {{{newline}")?;
543 for (name, value) in instance.params.iter() {
544 write_cell_argument(f, "param", name)?;
545 write!(f, "{value}{newline}")?;
546 }
547 for (name, value) in instance.inputs.iter() {
548 write_cell_argument(f, "input", name)?;
549 self.write_value(f, value)?;
550 write!(f, "{newline}")?;
551 }
552 for (name, range) in instance.outputs.iter() {
553 write!(f, " %{}:{} = output ", index + range.start, range.len())?;
554 Design::write_string(f, name)?;
555 write!(f, "{newline}")?;
556 }
557 for (name, value) in instance.ios.iter() {
558 write_cell_argument(f, "io", name)?;
559 self.write_io_value(f, value)?;
560 write!(f, "{newline}")?;
561 }
562 write!(f, "}}")?;
563 }
564 Cell::Target(target_cell) => {
565 write!(f, "target ")?;
566 let prototype = self.target_prototype(target_cell);
567 Design::write_string(f, &target_cell.kind)?;
568 write_metadata(f)?;
569 write!(f, " {{{newline}")?;
570 for (param, value) in prototype.params.iter().zip(target_cell.params.iter()) {
571 write_cell_argument(f, "param", ¶m.name)?;
572 write!(f, "{value}{newline}")?;
573 }
574 for target_input in &prototype.inputs {
575 write_cell_argument(f, "input", &target_input.name)?;
576 self.write_value(f, &target_cell.inputs.slice(target_input.range.clone()))?;
577 write!(f, "{newline}")?;
578 }
579 if prototype.outputs.len() > 1 {
580 for target_output in &prototype.outputs {
581 write!(f, " %{}:{} = output ", index + target_output.range.start, target_output.range.len())?;
582 Design::write_string(f, &target_output.name)?;
583 write!(f, "{newline}")?;
584 }
585 }
586 for target_io in &prototype.ios {
587 write_cell_argument(f, "io", &target_io.name)?;
588 self.write_io_value(f, &target_cell.ios.slice(target_io.range.clone()))?;
589 write!(f, "{newline}")?;
590 }
591 write!(f, "}}")?;
592 }
593
594 Cell::Input(name, _size) => {
595 write!(f, "input ")?;
596 Design::write_string(f, name)?;
597 }
598 Cell::Output(name, value) => {
599 write!(f, "output ")?;
600 Design::write_string(f, name)?;
601 write!(f, " ")?;
602 self.write_value(f, value)?;
603 }
604 Cell::Name(name, value) => {
605 write!(f, "name ")?;
606 Design::write_string(f, name)?;
607 write!(f, " ")?;
608 self.write_value(f, value)?;
609 }
610 Cell::Debug(name, value) => {
611 write!(f, "debug ")?;
612 Design::write_string(f, name)?;
613 write!(f, " ")?;
614 self.write_value(f, value)?;
615 }
616 }
617 match cell {
618 Cell::Match(..) | Cell::Memory(..) | Cell::Other(..) | Cell::Target(..) => (),
619 _ => write_metadata(f)?,
620 }
621 Ok(())
622 }
623
624 pub fn display_net(&self, net: impl Into<Net>) -> impl Display + '_ {
625 let net = net.into();
626 DisplayFn(self, move |design: &Design, f| design.write_net(f, net))
627 }
628
629 pub fn display_control_net(&self, net: impl Into<ControlNet>) -> impl Display + '_ {
630 let net = net.into();
631 DisplayFn(self, move |design: &Design, f| design.write_control_net(f, net))
632 }
633
634 pub fn display_value<'a, 'b: 'a>(&'a self, value: impl Into<Cow<'b, Value>>) -> impl Display + 'a {
635 let value = value.into();
636 DisplayFn(self, move |design: &Design, f| design.write_value(f, &value))
637 }
638
639 pub fn display_cell<'a>(&'a self, cell_ref: CellRef<'a>) -> impl Display + 'a {
640 DisplayFn(self, move |design: &Design, f| {
641 design.write_cell(f, "", cell_ref.debug_index(), &cell_ref.get(), cell_ref.metadata().index())
642 })
643 }
644}