Skip to content

Commit

Permalink
Add external-to-ref pass (#1952)
Browse files Browse the repository at this point in the history
* Compiling external-to-ref. TBD if correct

* Allow `ref` in toplevel components

* update runt tests allowing ref in main and external-to-ref pass

* remove some comments from external_to_ref

* update for nested external-to-ref

* rustfmt

* remove old main-ref-cell well-formedness test

* add doc comments and remove todos from external_to_ref
  • Loading branch information
nathanielnrn authored Mar 3, 2024
1 parent 4cf9f99 commit f99a966
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 38 deletions.
2 changes: 1 addition & 1 deletion calyx-ir/src/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ impl Cell {
}

///Set the external field
pub(super) fn set_reference(&mut self, reference: bool) -> bool {
pub fn set_reference(&mut self, reference: bool) -> bool {
self.reference = reference;
self.reference
}
Expand Down
13 changes: 7 additions & 6 deletions calyx-opt/src/default_passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use crate::passes::{
CompileInvoke, CompileRepeat, CompileStatic, CompileStaticInterface,
CompileSync, CompileSyncWithoutSyncReg, ComponentInliner, DataPathInfer,
DeadAssignmentRemoval, DeadCellRemoval, DeadGroupRemoval, DefaultAssigns,
DiscoverExternal, Externalize, GoInsertion, GroupToInvoke, GroupToSeq,
HoleInliner, InferShare, LowerGuards, MergeAssign, Papercut, ParToSeq,
RegisterUnsharing, RemoveIds, ResetInsertion, SimplifyStaticGuards,
SimplifyWithControl, StaticInference, StaticInliner, StaticPromotion,
SynthesisPapercut, TopDownCompileControl, UnrollBounded, WellFormed,
WireInliner, WrapMain,
DiscoverExternal, ExternalToRef, Externalize, GoInsertion, GroupToInvoke,
GroupToSeq, HoleInliner, InferShare, LowerGuards, MergeAssign, Papercut,
ParToSeq, RegisterUnsharing, RemoveIds, ResetInsertion,
SimplifyStaticGuards, SimplifyWithControl, StaticInference, StaticInliner,
StaticPromotion, SynthesisPapercut, TopDownCompileControl, UnrollBounded,
WellFormed, WireInliner, WrapMain,
};
use crate::traversal::Named;
use crate::{pass_manager::PassManager, register_alias};
Expand Down Expand Up @@ -74,6 +74,7 @@ impl PassManager {
pm.register_pass::<LowerGuards>()?;
pm.register_pass::<HoleInliner>()?;
pm.register_pass::<RemoveIds>()?;
pm.register_pass::<ExternalToRef>()?;

register_alias!(pm, "validate", [WellFormed, Papercut, Canonicalize]);
register_alias!(
Expand Down
50 changes: 50 additions & 0 deletions calyx-opt/src/passes/external_to_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::traversal::{Action, ConstructVisitor, Named, VisResult, Visitor};
use calyx_ir::{self as ir, GetAttributes, LibrarySignatures};
use calyx_utils::CalyxResult;

/// Turns memory cell primitives with the `@external(1)` attribute into
/// `ref` memory cells without the `@external` attribute.
pub struct ExternalToRef;

impl Named for ExternalToRef {
fn name() -> &'static str {
"external-to-ref"
}

fn description() -> &'static str {
"Turn memory cells marked with `@external(1) into `ref` memory cells."
}
}

impl ConstructVisitor for ExternalToRef {
fn from(_ctx: &ir::Context) -> CalyxResult<Self>
where
Self: Sized,
{
let external_to_ref = ExternalToRef;
Ok(external_to_ref)
}

fn clear_data(&mut self) {}
}

impl Visitor for ExternalToRef {
fn start(
&mut self,
comp: &mut ir::Component,
_ctx: &LibrarySignatures,
_comps: &[ir::Component],
) -> VisResult {
// Iterate over each cell in the component
for cell in comp.cells.iter() {
let mut cell_ref = cell.borrow_mut();
if cell_ref.get_attributes().has(ir::BoolAttr::External) {
// Change the cell type to `ref` and remove the external attribute
cell_ref.get_mut_attributes().remove(ir::BoolAttr::External);
cell_ref.set_reference(true);
}
}
// Continue visiting other nodes in the AST
Ok(Action::Continue)
}
}
2 changes: 2 additions & 0 deletions calyx-opt/src/passes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod dead_assignment_removal;
mod dead_cell_removal;
mod dead_group_removal;
mod dump_ports;
mod external_to_ref;
mod externalize;
mod go_insertion;
mod group_to_invoke;
Expand Down Expand Up @@ -59,6 +60,7 @@ pub use dead_assignment_removal::DeadAssignmentRemoval;
pub use dead_cell_removal::DeadCellRemoval;
pub use dead_group_removal::DeadGroupRemoval;
pub use discover_external::DiscoverExternal;
pub use external_to_ref::ExternalToRef;
pub use externalize::Externalize;
pub use go_insertion::GoInsertion;
pub use group_to_invoke::GroupToInvoke;
Expand Down
12 changes: 0 additions & 12 deletions calyx-opt/src/passes/well_formed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,6 @@ impl ConstructVisitor for WellFormed {

let mut ref_cell_types = HashMap::new();
for comp in ctx.components.iter() {
// Main component cannot use `ref` cells
if comp.name == ctx.entrypoint {
for cell in comp.cells.iter() {
if cell.borrow().is_reference() {
return Err(Error::malformed_structure(
"ref cells are not allowed for main component",
)
.with_pos(cell.borrow().get_attributes()));
}
}
}

// Non-main components cannot use @external attribute
let cellmap: LinkedHashMap<ir::Id, CellType> = comp
.cells
Expand Down
52 changes: 52 additions & 0 deletions tests/passes/external-to-ref.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import "primitives/core.futil";
import "primitives/memories/seq.futil";
component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) {
cells {
ref A = seq_mem_d1(32, 16, 4);
B = seq_mem_d1(32, 16, 4);
ref state = std_reg(32);
ref my_module = module();
}
wires {
group wr_A {
A.write_en = 1'd1;
A.content_en = 1'd1;
A.write_data = 32'd5;
wr_A[done] = A.done;
}
group wr_B {
B.write_en = 1'd1;
B.content_en = 1'd1;
B.write_data = 32'd4;
wr_B[done] = B.done;
}
group read_A {
A.content_en = 1'd1;
A.write_en = 1'd0;
read_A[done] = A.done;
}
}
control {
seq {
par {
wr_A;
wr_B;
}
read_A;
}
}
}
component module(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) {
cells {
ref C = seq_mem_d1(32, 16, 4);
}
wires {
group wr_C {
C.write_en = 1'd1;
C.content_en = 1'd1;
C.write_data = 32'd6;
wr_C[done] = C.done;
}
}
control {}
}
56 changes: 56 additions & 0 deletions tests/passes/external-to-ref.futil
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// -p external-to-ref

import "primitives/core.futil";
import "primitives/memories/seq.futil";

component main() -> () {
cells {
@external(1) A = seq_mem_d1(32, 16, 4);
B = seq_mem_d1(32, 16, 4);
@external(1) state = std_reg(32);
@external(1) my_module = module();

}
wires {
group wr_A {
A.write_en = 1'b1;
A.content_en = 1'b1;
A.write_data = 32'd5;
wr_A[done] = A.done;
}

group wr_B {
B.write_en = 1'b1;
B.content_en=1'b1;
B.write_data = 32'd4;
wr_B[done] = B.done;
}

group read_A {
A.content_en = 1'b1;
A.write_en = 1'b0;
read_A[done] = A.done;
}
}
control {
seq{
par{wr_A; wr_B;}
read_A;
}
}
}

component module() -> () {
cells {
@external(1) C = seq_mem_d1(32,16,4);
}
wires {
group wr_C {
C.write_en = 1'b1;
C.content_en = 1'b1;
C.write_data= 32'd6;
wr_C[done] = C.done;
}
}
control {}
}
4 changes: 0 additions & 4 deletions tests/passes/well-formed/main-ref-cell.expect

This file was deleted.

15 changes: 0 additions & 15 deletions tests/passes/well-formed/main-ref-cell.futil

This file was deleted.

0 comments on commit f99a966

Please sign in to comment.