Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Builder: optional names for cells #1664

Merged
merged 29 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
93140dd
Make FIFO use new eq
anshumanmohan Aug 15, 2023
8d66d43
Tidying
anshumanmohan Aug 15, 2023
b317c80
Arbiter works
anshumanmohan Aug 15, 2023
95616c6
Pifo and Pifotrer work
anshumanmohan Aug 15, 2023
7a3d87d
Merge branch 'master' into builder-gensym
anshumanmohan Aug 16, 2023
7969855
Drop optional names for other eq cell uses
anshumanmohan Aug 16, 2023
9b32d40
Optional name for neq cells
anshumanmohan Aug 16, 2023
9f4d90e
Optional name for lt cells
anshumanmohan Aug 16, 2023
c6d37ae
Allow a buncha other cells to make names automatically
anshumanmohan Aug 16, 2023
05b5672
pipe change through to builder_util
anshumanmohan Aug 16, 2023
b0b42b9
Catch up all programs to new name-optional regime
anshumanmohan Aug 16, 2023
dd657cf
Fix in MrXL
anshumanmohan Aug 16, 2023
4ab5866
Fixes in systolic
anshumanmohan Aug 16, 2023
1dd5fb6
More auto-names
anshumanmohan Aug 16, 2023
9d210cd
assert that names must be strings
anshumanmohan Aug 16, 2023
278f86a
Fixes in systolic and mrxl
anshumanmohan Aug 16, 2023
63146f3
Merge branch 'master' into builder-gensym
anshumanmohan Aug 17, 2023
3dc2a8d
User helpers to make cells
anshumanmohan Aug 17, 2023
42fa744
Catch clashes and retry
anshumanmohan Aug 17, 2023
ce09c22
Merge branch 'master' into builder-gensym
anshumanmohan Aug 17, 2023
333d492
no more op_op_number
anshumanmohan Aug 18, 2023
83ead71
Add a few type annotations
anshumanmohan Aug 18, 2023
dae7dad
rename helpers to binary and logic
anshumanmohan Aug 18, 2023
5698b68
backticks in docstrings
anshumanmohan Aug 18, 2023
4af3645
More backticks
anshumanmohan Aug 18, 2023
251da7a
Back docstrings
anshumanmohan Aug 18, 2023
47ff914
Revert overzealous backticking
anshumanmohan Aug 18, 2023
ef5a256
No more randomness
anshumanmohan Aug 18, 2023
aeb87a0
Merge branch 'master' into builder-gensym
anshumanmohan Aug 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 52 additions & 28 deletions calyx-py/calyx/builder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import threading
import random
from typing import Dict, Union, Optional, List
from . import py_ast as ast

Expand Down Expand Up @@ -71,6 +72,14 @@ def __init__(
for cell in cells:
self.index[cell.id.name] = CellBuilder(cell)
self.continuous = GroupBuilder(None, self)
random.seed(4)

def generate_name(self, prefix: str) -> str:
"""Generate a unique name with the given prefix."""
while True:
name = f"{prefix}_{random.randint(0, 2**32)}"
if name not in self.index:
return name
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved

def input(self, name: str, size: int) -> ExprBuilder:
"""Declare an input port on the component.
Expand Down Expand Up @@ -268,53 +277,64 @@ def seq_mem_d1(
name, ast.Stdlib.seq_mem_d1(bitwidth, len, idx_size), is_external, is_ref
)

def add(self, name: str, size: int, signed=False) -> CellBuilder:
"""Generate a StdAdd cell."""
def binary_op_helper(
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
self,
operation: str,
size: int,
name=None,
signed=False,
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
) -> CellBuilder:
"""Generate a binary cell of the kind specified in {operation}."""
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("add", size, signed))
name = name or f"{operation}_{self.generate_name(operation)}"
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
assert isinstance(name, str)
return self.cell(name, ast.Stdlib.op(operation, size, signed))

def sub(self, name: str, size: int, signed=False):
def add(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdAdd cell."""
return self.binary_op_helper("add", size, name, signed)

def sub(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdSub cell."""
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("sub", size, signed))
return self.binary_op_helper("sub", size, name, signed)

def gt(self, name: str, size: int, signed=False):
def gt(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdGt cell."""
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("gt", size, signed))
return self.binary_op_helper("gt", size, name, signed)

def lt(self, name: str, size: int, signed=False):
def lt(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdLt cell."""
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("lt", size, signed))
return self.binary_op_helper("lt", size, name, signed)

def eq(self, name: str, size: int, signed=False):
def eq(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdEq cell."""
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("eq", size, signed))
return self.binary_op_helper("eq", size, name, signed)

def neq(self, name: str, size: int, signed=False):
def neq(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdNeq cell."""
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("neq", size, signed))
return self.binary_op_helper("neq", size, name, signed)

def ge(self, name: str, size: int, signed=False):
def ge(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdGe cell."""
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("ge", size, signed))
return self.binary_op_helper("ge", size, name, signed)

def le(self, name: str, size: int, signed=False):
def le(self, size: int, name=None, signed=False) -> CellBuilder:
"""Generate a StdLe cell."""
self.prog.import_("primitives/binary_operators.futil")
return self.cell(name, ast.Stdlib.op("le", size, signed))
return self.binary_op_helper("le", size, name, signed)

def logical_op_helper(self, operation, size: int, name=None) -> CellBuilder:
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
"""Generate a logical operator cell, of the flavor specified in {operation}."""
name = name or f"{operation}_{self.generate_name(operation)}"
assert isinstance(name, str)
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
return self.cell(name, ast.Stdlib.op(operation, size, False))

def and_(self, name: str, size: int) -> CellBuilder:
def and_(self, size: int, name=None) -> CellBuilder:
"""Generate a StdAnd cell."""
return self.cell(name, ast.Stdlib.op("and", size, False))
return self.logical_op_helper("and", size, name)

def not_(self, name: str, size: int) -> CellBuilder:
def not_(self, size: int, name=None) -> CellBuilder:
"""Generate a StdNot cell."""
return self.cell(name, ast.Stdlib.op("not", size, False))
return self.logical_op_helper("not", size, name)

def pipelined_mult(self, name: str) -> CellBuilder:
"""Generate a pipelined multiplier."""
Expand Down Expand Up @@ -632,6 +652,10 @@ def is_seq_mem_d1(self) -> bool:
"""Check if the cell is a SeqMemD1 cell."""
return self.is_primitive("seq_mem_d1")

def name(self) -> str:
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
"""Get the name of the cell."""
return self._cell.id.name

@classmethod
def unwrap_id(cls, obj):
if isinstance(obj, cls):
Expand Down
58 changes: 26 additions & 32 deletions calyx-py/calyx/builder_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
import calyx.builder as cb


def insert_comb_group(comp: cb.ComponentBuilder, left, right, cell, groupname):
def insert_comb_group(comp: cb.ComponentBuilder, left, right, cell, groupname=None):
"""Accepts a cell that performs some computation on values {left} and {right}.
Creates a combinational group {groupname} that wires up the cell with these ports.
Creates a combinational group that wires up the cell with these ports.
Returns the cell and the combintational group.
"""
groupname = groupname or f"{cell.name()}_group"
with comp.comb_group(groupname) as comb_group:
cell.left = left
cell.right = right
return cell, comb_group


def insert_eq(comp: cb.ComponentBuilder, left, right, cellname, width):
def insert_eq(comp: cb.ComponentBuilder, left, right, width, cellname=None):
"""Inserts wiring into component {comp} to check if {left} == {right}.

<cellname> = std_eq(<width>);
Expand All @@ -25,11 +26,10 @@ def insert_eq(comp: cb.ComponentBuilder, left, right, cellname, width):

Returns handles to the cell and the combinational group.
"""
eq_cell = comp.eq(cellname, width)
return insert_comb_group(comp, left, right, eq_cell, f"{cellname}_group")
return insert_comb_group(comp, left, right, comp.eq(width, cellname))


def insert_neq(comp: cb.ComponentBuilder, left, right, cellname, width):
def insert_neq(comp: cb.ComponentBuilder, left, right, width, cellname=None):
"""Inserts wiring into component {comp} to check if {left} != {right}.

<cellname> = std_neq(<width>);
Expand All @@ -41,11 +41,10 @@ def insert_neq(comp: cb.ComponentBuilder, left, right, cellname, width):

Returns handles to the cell and the combinational group.
"""
neq_cell = comp.neq(cellname, width)
return insert_comb_group(comp, left, right, neq_cell, f"{cellname}_group")
return insert_comb_group(comp, left, right, comp.neq(width, cellname))


def insert_lt(comp: cb.ComponentBuilder, left, right, cellname, width):
def insert_lt(comp: cb.ComponentBuilder, left, right, width, cellname=None):
"""Inserts wiring into component {comp} to check if {left} < {right}.

<cellname> = std_lt(<width>);
Expand All @@ -57,11 +56,10 @@ def insert_lt(comp: cb.ComponentBuilder, left, right, cellname, width):

Returns handles to the cell and the combinational group.
"""
lt_cell = comp.lt(cellname, width)
return insert_comb_group(comp, left, right, lt_cell, f"{cellname}_group")
return insert_comb_group(comp, left, right, comp.lt(width, cellname))


def insert_le(comp: cb.ComponentBuilder, left, right, cellname, width):
def insert_le(comp: cb.ComponentBuilder, left, right, width, cellname=None):
"""Inserts wiring into component {comp} to check if {left} <= {right}.

<cellname> = std_le(<width>);
Expand All @@ -73,11 +71,10 @@ def insert_le(comp: cb.ComponentBuilder, left, right, cellname, width):

Returns handles to the cell and the combinational group.
"""
le_cell = comp.le(cellname, width)
return insert_comb_group(comp, left, right, le_cell, f"{cellname}_group")
return insert_comb_group(comp, left, right, comp.le(width, cellname))


def insert_gt(comp: cb.ComponentBuilder, left, right, cellname, width):
def insert_gt(comp: cb.ComponentBuilder, left, right, width, cellname=None):
"""Inserts wiring into component {comp} to check if {left} > {right}.

<cellname> = std_gt(<width>);
Expand All @@ -89,14 +86,13 @@ def insert_gt(comp: cb.ComponentBuilder, left, right, cellname, width):

Returns handles to the cell and the combinational group.
"""
gt_cell = comp.gt(cellname, width)
return insert_comb_group(comp, left, right, gt_cell, f"{cellname}_group")
return insert_comb_group(comp, left, right, comp.gt(width, cellname))


def insert_add(comp: cb.ComponentBuilder, left, right, cellname, width):
"""Inserts wiring into component {comp} to compute {left} + {right}.
def insert_add(comp: cb.ComponentBuilder, left, right, width, cellname=None):
"""Inserts wiring into component {comp} to check if {left} > {right}.

<cellname> = std_add(<width>);
<cellname> = std_gt(<width>);
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
...
comb group <cellname>_group {
<cellname>.left = <left>;
Expand All @@ -105,14 +101,13 @@ def insert_add(comp: cb.ComponentBuilder, left, right, cellname, width):

Returns handles to the cell and the combinational group.
"""
add_cell = comp.add(cellname, width)
return insert_comb_group(comp, left, right, add_cell, f"{cellname}_group")
return insert_comb_group(comp, left, right, comp.add(width, cellname))


def insert_sub(comp: cb.ComponentBuilder, left, right, cellname, width):
"""Inserts wiring into component {comp} to compute {left} - {right}.
def insert_sub(comp: cb.ComponentBuilder, left, right, width, cellname=None):
"""Inserts wiring into component {comp} to check if {left} > {right}.

<cellname> = std_sub(<width>);
<cellname> = std_gt(<width>);
anshumanmohan marked this conversation as resolved.
Show resolved Hide resolved
...
comb group <cellname>_group {
<cellname>.left = <left>;
Expand All @@ -121,16 +116,15 @@ def insert_sub(comp: cb.ComponentBuilder, left, right, cellname, width):

Returns handles to the cell and the combinational group.
"""
sub_cell = comp.sub(cellname, width)
return insert_comb_group(comp, left, right, sub_cell, f"{cellname}_group")
return insert_comb_group(comp, left, right, comp.sub(width, cellname))


def insert_bitwise_flip_reg(comp: cb.ComponentBuilder, reg, cellname, width):
"""Inserts wiring into component {comp} to bitwise-flip the contents of {reg}.

Returns a handle to the group that does this.
"""
not_cell = comp.not_(cellname, width)
not_cell = comp.not_(width, cellname)
with comp.group(f"{cellname}_group") as not_group:
not_cell.in_ = reg.out
reg.write_en = 1
Expand All @@ -147,7 +141,7 @@ def insert_incr(comp: cb.ComponentBuilder, reg, cellname, val=1):
4. Then puts the answer of the computation back into {reg}.
5. Returns the group that does this.
"""
add_cell = comp.add(cellname, 32)
add_cell = comp.add(32, cellname)
with comp.group(f"{cellname}_group") as incr_group:
add_cell.left = reg.out
add_cell.right = cb.const(32, val)
Expand All @@ -165,7 +159,7 @@ def insert_decr(comp: cb.ComponentBuilder, reg, cellname, val=1):
4. Then puts the answer of the computation back into {reg}.
5. Returns the group that does this.
"""
sub_cell = comp.sub(cellname, 32)
sub_cell = comp.sub(32, cellname)
with comp.group(f"{cellname}_group") as decr_group:
sub_cell.left = reg.out
sub_cell.right = cb.const(32, val)
Expand Down Expand Up @@ -303,7 +297,7 @@ def insert_add_store_in_reg(
4. Then puts the answer of the computation into {ans_reg}.
4. Returns the summing group and the register.
"""
add_cell = comp.add(cellname, 32)
add_cell = comp.add(32, cellname)
ans_reg = ans_reg or comp.reg(f"reg_{cellname}", 32)
with comp.group(f"{cellname}_group") as adder_group:
add_cell.left = left
Expand All @@ -330,7 +324,7 @@ def insert_sub_store_in_reg(
4. Then puts the answer of the computation into {ans_reg}.
4. Returns the subtracting group and the register.
"""
sub_cell = comp.sub(cellname, width)
sub_cell = comp.sub(width, cellname)
ans_reg = ans_reg or comp.reg(f"reg_{cellname}", width)
with comp.group(f"{cellname}_group") as sub_group:
sub_cell.left = left
Expand Down
8 changes: 3 additions & 5 deletions calyx-py/calyx/queue_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ def insert_raise_err_if_i_eq_max_cmds(prog):
i = raise_err_if_i_eq_max_cmds.input("i", 32)
err = raise_err_if_i_eq_max_cmds.reg("err", 1, is_ref=True)

i_eq_max_cmds = util.insert_eq(
raise_err_if_i_eq_max_cmds, i, MAX_CMDS, "i_eq_MAX_CMDS", 32
)
i_eq_max_cmds = util.insert_eq(raise_err_if_i_eq_max_cmds, i, MAX_CMDS, 32)
raise_err = util.insert_reg_store(raise_err_if_i_eq_max_cmds, err, 1, "raise_err")

raise_err_if_i_eq_max_cmds.control += [
Expand Down Expand Up @@ -92,8 +90,8 @@ def insert_main(prog, queue):

incr_i = util.insert_incr(main, i, "incr_i") # i++
incr_j = util.insert_incr(main, j, "incr_j") # j++
err_eq_0 = util.insert_eq(main, err.out, 0, "err_eq_0", 1) # is `err` flag down?
cmd_le_1 = util.insert_le(main, cmd.out, 1, "cmd_le_1", 2) # cmd <= 1
err_eq_0 = util.insert_eq(main, err.out, 0, 1) # is `err` flag down?
cmd_le_1 = util.insert_le(main, cmd.out, 1, 2) # cmd <= 1

read_cmd = util.mem_read_seq_d1(main, commands, i.out, "read_cmd_phase1")
write_cmd_to_reg = util.mem_write_seq_d1_to_reg(
Expand Down
2 changes: 1 addition & 1 deletion calyx-py/test/builder_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def add_main_component(prog):
lhs = main.reg("lhs", 32)
rhs = main.reg("rhs", 32)
sum = main.reg("sum", 32)
add = main.add("add", 32)
add = main.add(32, "add")
# ANCHOR_END: cells

# ANCHOR: bare
Expand Down
16 changes: 8 additions & 8 deletions calyx-py/test/correctness/arbiter_6.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def add_wrap2(prog):
j_mod_4 = wrap.reg("j_mod_4", 32)

# Additional cells and groups to compute equality and lt
i_eq_0_cell, i_eq_0_grp = util.insert_eq(wrap, i, 0, "i_eq_0", 32)
i_eq_1_cell, i_eq_1_group = util.insert_eq(wrap, i, 1, "i_eq_1", 32)
j_lt_4_cell, j_lt_4_group = util.insert_lt(wrap, j, 4, "j_lt_4", 32)
j_lt_8_cell, j_lt_8_group = util.insert_lt(wrap, j, 8, "j_lt_8", 32)
i_eq_0_cell, i_eq_0_grp = util.insert_eq(wrap, i, 0, 32)
i_eq_1_cell, i_eq_1_group = util.insert_eq(wrap, i, 1, 32)
j_lt_4_cell, j_lt_4_group = util.insert_lt(wrap, j, 4, 32)
j_lt_8_cell, j_lt_8_group = util.insert_lt(wrap, j, 8, 32)

# Load `j` unchanged into `j_mod_4`.
unchanged = util.insert_reg_store(wrap, j_mod_4, j, "j_unchanged")
Expand Down Expand Up @@ -126,10 +126,10 @@ def add_wrap3(prog):
j_mod_4 = wrap.reg("j_mod_4", 32)

# Additional cells to compute equality, and lt
i_eq_0_cell, i_eq_0_group = util.insert_eq(wrap, i, 0, "i_eq_0", 32)
i_eq_1_cell, i_eq_1_group = util.insert_eq(wrap, i, 1, "i_eq_1", 32)
i_eq_2_cell, i_eq_2_group = util.insert_eq(wrap, i, 2, "i_eq_2", 32)
j_lt_4_cell, j_lt_4_group = util.insert_lt(wrap, j, 4, "j_lt_4", 32)
i_eq_0_cell, i_eq_0_group = util.insert_eq(wrap, i, 0, 32)
i_eq_1_cell, i_eq_1_group = util.insert_eq(wrap, i, 1, 32)
i_eq_2_cell, i_eq_2_group = util.insert_eq(wrap, i, 2, 32)
j_lt_4_cell, j_lt_4_group = util.insert_lt(wrap, j, 4, 32)

# Load `j` unchanged into `j_mod_4`.
unchanged = util.insert_reg_store(wrap, j_mod_4, j, "j_unchanged")
Expand Down
24 changes: 9 additions & 15 deletions calyx-py/test/correctness/fifo.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,15 @@ def insert_fifo(prog, name):

len = fifo.reg("len", 32) # The length of the FIFO.

# Cells and groups to compute equality.
cmd_eq_0 = util.insert_eq(fifo, cmd, 0, "cmd_eq_0", 2)
cmd_eq_1 = util.insert_eq(fifo, cmd, 1, "cmd_eq_1", 2)
cmd_eq_2 = util.insert_eq(fifo, cmd, 2, "cmd_eq_2", 2)

write_eq_max_queue_len = util.insert_eq(
fifo, write.out, MAX_QUEUE_LEN, "write_eq_MAX_QUEUE_LEN", 32
)
read_eq_max_queue_len = util.insert_eq(
fifo, read.out, MAX_QUEUE_LEN, "read_eq_MAX_QUEUE_LEN", 32
)
len_eq_0 = util.insert_eq(fifo, len.out, 0, "len_eq_0", 32)
len_eq_max_queue_len = util.insert_eq(
fifo, len.out, MAX_QUEUE_LEN, "len_eq_MAX_QUEUE_LEN", 32
)
# Cells and groups to compute equality
cmd_eq_0 = util.insert_eq(fifo, cmd, 0, 2)
cmd_eq_1 = util.insert_eq(fifo, cmd, 1, 2)
cmd_eq_2 = util.insert_eq(fifo, cmd, 2, 2)

write_eq_max_queue_len = util.insert_eq(fifo, write.out, MAX_QUEUE_LEN, 32)
read_eq_max_queue_len = util.insert_eq(fifo, read.out, MAX_QUEUE_LEN, 32)
len_eq_0 = util.insert_eq(fifo, len.out, 0, 32)
len_eq_max_queue_len = util.insert_eq(fifo, len.out, MAX_QUEUE_LEN, 32)

# Cells and groups to increment read and write registers
write_incr = util.insert_incr(fifo, write, "write_incr") # write++
Expand Down
Loading