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