Skip to content

Commit

Permalink
impld wire inliner wrt fsm compilation
Browse files Browse the repository at this point in the history
- need to instantiate wire for start/done signals for FSM
- right now, they can't be translated easily to verilog i don't think; they will probably need primitive std_wire instantiations to map easily to verilog logic variables, right?
  • Loading branch information
parthsarkar17 committed Nov 19, 2024
1 parent 15cc16d commit b2a0e3a
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 29 deletions.
3 changes: 2 additions & 1 deletion calyx-ir/src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ impl Printer {
if !matches!(&*assign.guard, ir::Guard::True) {
write!(f, "{} ? ", Self::guard_str(&assign.guard.clone()))?;
}

write!(f, "{};", Self::port_to_str(&assign.src.borrow()))
}

Expand Down Expand Up @@ -459,7 +460,7 @@ impl Printer {
writeln!(f, "{{")?;
for assign in assigns {
Self::write_assignment(assign, indent_level + 4, f)?;
writeln!(f)?;
writeln!(f, "")?;

Check failure on line 463 in calyx-ir/src/printer.rs

View workflow job for this annotation

GitHub Actions / Check Formatting

empty string literal in `writeln!`
}
write!(f, "{}", " ".repeat(indent_level + 2))?;
write!(f, "}} => ")?;
Expand Down
100 changes: 72 additions & 28 deletions calyx-opt/src/passes/wire_inliner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,63 +22,86 @@ impl Named for WireInliner {
}
}

fn rewrite_assign(map: &HoleMapping, assign: &mut ir::Assignment<Nothing>) {
let rewrite = |port: &RRC<ir::Port>| -> Option<RRC<ir::Cell>> {
if let ir::PortParent::Group(g) = &port.borrow().parent {
let (go, done) = &map[&g.upgrade().borrow().name()];
let cell = if port.borrow().name == "go" { go } else { done };
Some(Rc::clone(cell))
} else {
None
}
};
fn rewrite(map: &HoleMapping, port: &RRC<ir::Port>) -> Option<RRC<ir::Cell>> {
if let ir::PortParent::Group(g) = &port.borrow().parent {
let (go, done) = &map[&g.upgrade().borrow().name()];
let cell = if port.borrow().name == "go" { go } else { done };
Some(Rc::clone(cell))
} else {
None
}
}

if let Some(cell) = rewrite(&assign.dst) {
fn rewrite_assign(map: &HoleMapping, assign: &mut ir::Assignment<Nothing>) {
if let Some(cell) = rewrite(map, &assign.dst) {
assign.dst = cell.borrow().get("in");
}
if let Some(cell) = rewrite(&assign.src) {
if let Some(cell) = rewrite(map, &assign.src) {
assign.src = cell.borrow().get("out");
}
assign.guard.for_each(&mut |port| {
rewrite(&port).map(|cell| ir::Guard::port(cell.borrow().get("out")))
rewrite(map, &port)
.map(|cell| ir::Guard::port(cell.borrow().get("out")))
});
}

fn rewrite_guard(map: &HoleMapping, guard: &mut ir::Guard<Nothing>) {
match guard {
ir::Guard::True | ir::Guard::Info(_) => (),
// update the port of a port guard to read from appropriate
// group wire, if it is dependent on a group's port in the first place
ir::Guard::Port(p) => {
if let Some(cell) = rewrite(map, p) {
guard.update(|_| ir::Guard::port(cell.borrow().get("out")));
}
}
// update the ports of a port-comparison guard to read from appropriate
// group wire, if these are dependent on groups' ports in the first place
ir::Guard::CompOp(_, p1, p2) => {
if let Some(cell) = rewrite(map, p1) {
let _ = std::mem::replace(p1, cell.borrow().get("out"));
}
if let Some(cell) = rewrite(map, p2) {
let _ = std::mem::replace(p2, cell.borrow().get("out"));
}
}
ir::Guard::Not(b) => {
rewrite_guard(map, &mut *b);
}
ir::Guard::And(b1, b2) | ir::Guard::Or(b1, b2) => {
rewrite_guard(map, &mut *b1);
rewrite_guard(map, &mut *b2);
}
}
}

impl Visitor for WireInliner {
fn start(
&mut self,
comp: &mut ir::Component,
sigs: &LibrarySignatures,
_comps: &[ir::Component],
) -> VisResult {
// trigger start of component FSM based on component's go signal
// trigger done of component based on FSM's done signal
let control_ref = Rc::clone(&comp.control);
let control = control_ref.borrow();
// Don't compile if the control program is empty
// if let ir::Control::Empty(..) = &*control {
// return Ok(Action::Stop);
// }

match &*control {
ir::Control::Enable(data) => {
ir::Control::FSMEnable(fsm_en) => {
let this = Rc::clone(&comp.signature);
let mut builder = ir::Builder::new(comp, sigs);
let group = &data.group;
let comp_fsm = &fsm_en.fsm;
let this_go_port = this
.borrow()
.find_unique_with_attr(ir::NumAttr::Go)?
.unwrap();
let this_done_port = this
.borrow()
.find_unique_with_attr(ir::NumAttr::Done)?
.unwrap();

structure!(builder;
let one = constant(1, 1);
);
let group_done = guard!(group[this_done_port.borrow().name]);
let fsm_done = guard!(comp_fsm["done"]);
let assigns = build_assignments!(builder;
group["go"] = ? this[this_go_port.borrow().name];
this["done"] = group_done ? one["out"];
comp_fsm["start"] = ? this[this_go_port.borrow().name];
this["done"] = fsm_done ? one["out"];
);
comp.continuous_assignments.extend(assigns);
}
Expand Down Expand Up @@ -127,6 +150,27 @@ impl Visitor for WireInliner {
gr.borrow_mut().assignments = assigns;
});

comp.get_fsms_mut().iter_mut().for_each(|fsm| {
// rewrite all assignments at each state within every fsm
for assigns_at_state in fsm.borrow_mut().assignments.iter_mut() {
for asgn in assigns_at_state.iter_mut() {
rewrite_assign(&hole_map, asgn);
}
}
// rewrite all guards in transitions that depend on group port values
for trans_at_state in fsm.borrow_mut().transitions.iter_mut() {
if let ir::Transition::Conditional(cond_trans_at_state) =
trans_at_state
{
for (cond_trans, _) in cond_trans_at_state {
rewrite_guard(&hole_map, cond_trans)
}
}
}
});

// rewrite all transitions as well

comp.continuous_assignments
.iter_mut()
.for_each(|assign| rewrite_assign(&hole_map, assign));
Expand Down

0 comments on commit b2a0e3a

Please sign in to comment.