Skip to content

Commit

Permalink
Remove @externalized attribute and update @data documentation (#2023
Browse files Browse the repository at this point in the history
)

* remove externalized

* remove externalize

* udpate docs

* added docs

* small changes

* clarification
  • Loading branch information
calebmkim authored Apr 27, 2024
1 parent d6be860 commit 54f481c
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 23 deletions.
6 changes: 2 additions & 4 deletions calyx-backend/src/verilog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ fn emit_guard_disjoint_check(
/// 1. The port is marked with `@data`
/// 2. The port's cell parent is marked with `@data`
fn is_data_port(pr: &RRC<ir::Port>) -> bool {
assert_eq!(ir::Direction::Input, pr.borrow().direction);
let port = pr.borrow();
if !port.attributes.has(ir::BoolAttr::Data) {
return false;
Expand All @@ -501,10 +502,7 @@ fn is_data_port(pr: &RRC<ir::Port>) -> bool {
let cell = cr.borrow();
// For cell.is_this() ports that were externalized, we already checked
// that the parent cell had the `@data` attribute.
if cell.attributes.has(ir::BoolAttr::Data)
|| (cell.is_this()
& port.attributes.has(ir::BoolAttr::Externalized))
{
if cell.attributes.has(ir::BoolAttr::Data) || cell.is_this() {
return true;
}
}
Expand Down
3 changes: 0 additions & 3 deletions calyx-frontend/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@ pub enum BoolAttr {
#[strum(serialize = "promoted")]
/// denotes a static component or control promoted from dynamic
Promoted,
#[strum(serialize = "externalized")]
/// Denotes a port that has been externalized (i.e., dumped into signature)
Externalized,
}
impl From<BoolAttr> for Attribute {
fn from(attr: BoolAttr) -> Self {
Expand Down
7 changes: 4 additions & 3 deletions calyx-opt/src/passes/dump_ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,17 @@ where
for port_ref in ports_inline {
let canon = port_ref.borrow().canonical();
let port = port_ref.borrow();
// We might want to insert
let mut new_port_attrs =
// We might want to insert the @data attribute for optimization purposes.
// But to do this, we have to make sure that the cell is marked @data
// as well.
let new_port_attrs =
if is_data_cell & port.attributes.has(ir::BoolAttr::Data) {
let mut attrs = ir::Attributes::default();
attrs.insert(ir::BoolAttr::Data, 1);
attrs
} else {
ir::Attributes::default()
};
new_port_attrs.insert(ir::BoolAttr::Externalized, 1);

let new_port = ir::rrc(ir::Port {
name: component.generate_name(format_port_name(&canon)),
Expand Down
36 changes: 33 additions & 3 deletions docs/lang/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,18 +199,48 @@ When we have following two conditions:
1. An input port is marked with `@data` in the component definitions, and
2. The cell instance is marked as `@data`

The backend generate `'x` as the default value for the assignment to the port instead of `'0`. Additionally, if the port has exactly one assignment, the backend removes the guard entirely and produces a continuous assignment.
The backend generates `'x` as the default value for the assignment to the port instead of `'0`. Additionally, if the port has exactly one assignment, the backend removes the guard entirely and produces a continuous assignment.

This represents the optimization:
```
in = g ? out : 'x
cells {
@data cell = cell_component();
}
wires {
cell.in = g ? out : 'x
}
```
into:
```
in = out;
// cells are same as before
wires {
cell.in = out;
}
```
Since the value `'x` can be replaced with anything.
(Currently Calyx does not support assignments of the form `rhs = guard ? lhs1: lhs2`,
so the syntax isn't 100% accurate.
This optimization happens when translating from Calyx to Verilog.
At some point we may want to make this optimization happen during a Calyx pass.)

`@data` can also appear on the output ports of a Calyx component.
This represents when we want to optimize assignments to the port _within a Calyx component_.
Consider the following example:
```
component main() ->(...@data out_write_data: 32....) {
...
wires {
out_write_data = g ? out : 'x // we want to optimize to out_write_data = out
}
}
```
Note that we are trying to perform this optimization _within the component_, i.e.,
`out_write_data` is a port on the signature of the component itself, not an instance.
Also note that in this case, `@data` appears on the _output_ port of the component's signature.
When `@data` appears on an output port of a Calyx component, it means that assignments
to this port _within_ the component will get the "default to `'x`" semantics and optimizations.
Note that there is no requirement of having the "cell instance is marked as `@data`",
as before.

[datapath-components]: https://github.com/calyxir/calyx/issues/1169
[builder]: https://docs.rs/calyx-ir/latest/calyx_ir/struct.Builder.html
Expand Down
2 changes: 1 addition & 1 deletion tests/passes/compile-invoke/invoke-ref.expect
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "primitives/compile.futil";
component foo(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized r_out: 32, @externalized r_done: 1) -> (@done done: 1, @externalized r_in: 32, @externalized r_write_en: 1) {
component foo(@go go: 1, @clk clk: 1, @reset reset: 1, r_out: 32, r_done: 1) -> (@done done: 1, r_in: 32, r_write_en: 1) {
cells {
}
wires {
Expand Down
4 changes: 2 additions & 2 deletions tests/passes/compile-invoke/ref-chain.expect
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) {
}
}
}
component incr(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized value_out: 32, @externalized value_done: 1) -> (@done done: 1, @externalized value_in: 32, @externalized value_write_en: 1) {
component incr(@go go: 1, @clk clk: 1, @reset reset: 1, value_out: 32, value_done: 1) -> (@done done: 1, value_in: 32, value_write_en: 1) {
cells {
ih = incr_helper();
}
Expand All @@ -40,7 +40,7 @@ component incr(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized value_out:
}
}
}
component incr_helper(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized value_out: 32, @externalized value_done: 1) -> (@done done: 1, @externalized value_in: 32, @externalized value_write_en: 1) {
component incr_helper(@go go: 1, @clk clk: 1, @reset reset: 1, value_out: 32, value_done: 1) -> (@done done: 1, value_in: 32, value_write_en: 1) {
cells {
incr_value = std_add(32);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/passes/compile-invoke/ref-invoke.expect
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "primitives/compile.futil";
component foo(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized m_out: 32, @externalized m_done: 1) -> (@done done: 1, @externalized m_in: 32, @externalized m_write_en: 1) {
component foo(@go go: 1, @clk clk: 1, @reset reset: 1, m_out: 32, m_done: 1) -> (@done done: 1, m_in: 32, m_write_en: 1) {
cells {
r = std_reg(32);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/passes/compile-invoke/ref.expect
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "primitives/compile.futil";
component foo(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized r_out: 32, @externalized r_done: 1) -> (@done done: 1, @externalized r_in: 32, @externalized r_write_en: 1) {
component foo(@go go: 1, @clk clk: 1, @reset reset: 1, r_out: 32, r_done: 1) -> (@done done: 1, r_in: 32, r_write_en: 1) {
cells {
}
wires {
Expand Down
2 changes: 1 addition & 1 deletion tests/passes/compile-invoke/static-ref.expect
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "primitives/core.futil";
import "primitives/memories/comb.futil";
static<2> component add_one(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized out_read_data: 32, @externalized out_done: 1) -> (@done done: 1, @externalized out_addr0: 1, @externalized out_write_data: 32, @externalized out_write_en: 1) {
static<2> component add_one(@go go: 1, @clk clk: 1, @reset reset: 1, out_read_data: 32, out_done: 1) -> (@done done: 1, out_addr0: 1, out_write_data: 32, out_write_en: 1) {
cells {
add = std_add(32);
r = std_reg(32);
Expand Down
6 changes: 3 additions & 3 deletions tests/passes/externalize.expect
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import "primitives/core.futil";
import "primitives/memories/comb.futil";
component main(@go go: 1, @clk clk: 1, @reset reset: 1, @externalized A_read_data: 32, @externalized A_done: 1) -> (@done done: 1, @externalized A_addr0: 4, @externalized A_write_data: 32, @externalized A_write_en: 1, @externalized A_clk: 1, @externalized A_reset: 1) {
component main(@go go: 1, @clk clk: 1, @reset reset: 1, A_read_data: 32, A_done: 1) -> (@done done: 1, A_addr0: 4, @data A_write_data: 32, A_write_en: 1, A_clk: 1, A_reset: 1) {
cells {
B = comb_mem_d1(32, 16, 4);
state = std_reg(32);
@data B = comb_mem_d1(32, 16, 4);
@data state = std_reg(32);
}
wires {
group wr_A {
Expand Down
2 changes: 1 addition & 1 deletion tests/passes/externalize.futil
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// -p externalize
// -p infer-data-path -p externalize

import "primitives/core.futil";
import "primitives/memories/comb.futil";
Expand Down

0 comments on commit 54f481c

Please sign in to comment.