calyx_opt/passes/
default_assigns.rs1use crate::analysis::AssignmentAnalysis;
2use crate::traversal::{Action, ConstructVisitor, Named, VisResult, Visitor};
3use calyx_ir::{self as ir, LibrarySignatures};
4use calyx_utils::{CalyxResult, Error};
5use itertools::Itertools;
6use std::collections::HashMap;
7
8pub struct DefaultAssigns {
10 data_ports: HashMap<ir::Id, Vec<ir::Id>>,
12}
13
14impl Named for DefaultAssigns {
15 fn name() -> &'static str {
16 "default-assigns"
17 }
18
19 fn description() -> &'static str {
20 "adds default assignments to all non-`@data` ports of an instance."
21 }
22}
23
24impl ConstructVisitor for DefaultAssigns {
25 fn from(ctx: &ir::Context) -> CalyxResult<Self>
26 where
27 Self: Sized,
28 {
29 let data_ports = ctx
30 .lib
31 .signatures()
32 .map(|sig| {
33 let ports = sig.signature.iter().filter_map(|p| {
34 if p.direction == ir::Direction::Input
35 && !p.attributes.has(ir::BoolAttr::Data)
36 && !p.attributes.has(ir::BoolAttr::Clk)
37 && !p.attributes.has(ir::BoolAttr::Reset)
38 {
39 Some(p.name())
40 } else {
41 None
42 }
43 });
44 (sig.name, ports.collect())
45 })
46 .collect();
47 Ok(Self { data_ports })
48 }
49
50 fn clear_data(&mut self) {
51 }
53}
54
55impl Visitor for DefaultAssigns {
56 fn start(
57 &mut self,
58 comp: &mut ir::Component,
59 sigs: &LibrarySignatures,
60 _comps: &[ir::Component],
61 ) -> VisResult {
62 if !comp.is_structural() {
63 return Err(Error::pass_assumption(
64 Self::name(),
65 format!("component {} is not purely structural", comp.name),
66 ));
67 }
68
69 let writes = comp
71 .continuous_assignments
72 .iter()
73 .analysis()
74 .writes()
75 .group_by_cell();
76
77 let mut assigns = Vec::new();
78
79 let mt = vec![];
80 let cells = comp.cells.iter().cloned().collect_vec();
81 let mut builder = ir::Builder::new(comp, sigs);
82
83 for cr in &cells {
84 let cell = cr.borrow();
85 let Some(typ) = cell.type_name() else {
86 continue;
87 };
88 let Some(required) = self.data_ports.get(&typ) else {
89 continue;
90 };
91
92 let cell_writes = writes
94 .get(&cell.name())
95 .unwrap_or(&mt)
96 .iter()
97 .map(|p| {
98 let p = p.borrow();
99 p.name
100 })
101 .collect_vec();
102
103 assigns.extend(
104 required.iter().filter(|p| !cell_writes.contains(p)).map(
105 |name| {
106 let port = cell.get(name);
107 let zero = builder.add_constant(0, port.borrow().width);
108 let assign: ir::Assignment<ir::Nothing> = builder
109 .build_assignment(
110 cell.get(name),
111 zero.borrow().get("out"),
112 ir::Guard::True,
113 );
114 log::info!(
115 "Adding {}",
116 ir::Printer::assignment_to_str(&assign)
117 );
118 assign
119 },
120 ),
121 );
122 }
123
124 comp.continuous_assignments.extend(assigns);
125
126 Ok(Action::Stop)
128 }
129}