Skip to content

Commit

Permalink
eDSL: Infer more widths, require fewer cell names (#2001)
Browse files Browse the repository at this point in the history
* Infer more bitwidths

* Require fewer cell names

* Reorder parameters

* Less verbose const
  • Loading branch information
anshumanmohan authored Apr 13, 2024
1 parent 4ecb674 commit 33b05e7
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 67 deletions.
73 changes: 53 additions & 20 deletions calyx-py/calyx/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def __init__(
self.prog = prog
self.component: ast.Component = ast.Component(
name,
attributes = [],
attributes=[],
inputs=[],
outputs=[],
structs=cells,
Expand Down Expand Up @@ -114,8 +114,7 @@ def output(self, name: str, size: int) -> ExprBuilder:
return self.this()[name]

def attribute(self, name: str, value: int) -> None:
"""Declare an attribute on the component.
"""
"""Declare an attribute on the component."""
self.component.attributes.append(ast.CompAttribute(name, value))

def this(self) -> ThisBuilder:
Expand Down Expand Up @@ -649,7 +648,15 @@ def mem_load_to_mem(self, mem, i, ans, j, groupname=None):
load_grp.done = ans.done
return load_grp

def op_store_in_reg(self, op_cell, left, right, cellname, width, ans_reg=None):
def op_store_in_reg(
self,
op_cell,
left,
right,
cellname,
width,
ans_reg=None,
):
"""Inserts wiring into `self` to perform `reg := left op right`,
where `op_cell`, a Cell that performs some `op`, is provided.
"""
Expand All @@ -663,34 +670,60 @@ def op_store_in_reg(self, op_cell, left, right, cellname, width, ans_reg=None):
return op_group, ans_reg

def add_store_in_reg(
self, left, right, cellname, width, ans_reg=None, signed=False
self,
left,
right,
ans_reg=None,
cellname=None,
width=None,
signed=False,
):
"""Inserts wiring into `self` to perform `reg := left + right`."""
return self.op_store_in_reg(
self.add(width, cellname, signed), left, right, cellname, width, ans_reg
)
width = width or self.try_infer_width(width, left, right)
cell = self.add(width, cellname, signed)
return self.op_store_in_reg(cell, left, right, cell.name, width, ans_reg)

def sub_store_in_reg(
self, left, right, cellname, width, ans_reg=None, signed=False
self,
left,
right,
ans_reg=None,
cellname=None,
width=None,
signed=False,
):
"""Inserts wiring into `self` to perform `reg := left - right`."""
return self.op_store_in_reg(
self.sub(width, cellname, signed), left, right, cellname, width, ans_reg
)
width = width or self.try_infer_width(width, left, right)
cell = self.sub(width, cellname, signed)
return self.op_store_in_reg(cell, left, right, cell.name, width, ans_reg)

def eq_store_in_reg(self, left, right, cellname, width, ans_reg=None, signed=False):
def eq_store_in_reg(
self,
left,
right,
ans_reg=None,
cellname=None,
width=None,
signed=False,
):
"""Inserts wiring into `self` to perform `reg := left == right`."""
return self.op_store_in_reg(
self.eq(width, cellname, signed), left, right, cellname, 1, ans_reg
)
width = width or self.try_infer_width(width, left, right)
cell = self.eq(width, cellname, signed)
return self.op_store_in_reg(cell, left, right, cell.name, 1, ans_reg)

def neq_store_in_reg(
self, left, right, cellname, width, ans_reg=None, signed=False
self,
left,
right,
ans_reg=None,
cellname=None,
width=None,
signed=False,
):
"""Inserts wiring into `self` to perform `reg := left != right`."""
return self.op_store_in_reg(
self.neq(width, cellname, signed), left, right, cellname, 1, ans_reg
)
width = width or self.try_infer_width(width, left, right)
cell = self.neq(width, cellname, signed)
return self.op_store_in_reg(cell, left, right, cell.name, 1, ans_reg)

def infer_width(self, expr) -> int:
"""Infer the width of an expression."""
Expand Down
86 changes: 45 additions & 41 deletions calyx-py/calyx/queue_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,30 +82,30 @@ def insert_runner(prog, queue, name, stats_component=None):
not_err = runner.not_use(err.out)

# Wiring that raises `err` iff `i = MAX_CMDS`.
check_if_out_of_cmds, _ = runner.eq_store_in_reg(
i.out, cb.const(32, queue_util.MAX_CMDS), "i_eq_MAX_CMDS", 32, err
)
check_if_out_of_cmds, _ = runner.eq_store_in_reg(i.out, queue_util.MAX_CMDS, err)

runner.control += [
read_cmd,
write_cmd_to_reg, # `cmd := commands[i]`
read_value,
write_value_to_reg, # `value := values[i]`
cb.invoke( # Invoke the queue.
queue,
in_cmd=cmd.out,
in_value=value.out,
ref_ans=ans,
ref_err=err,
ref_stats=stats,
)
if stats_component
else cb.invoke( # Invoke the queue.
queue,
in_cmd=cmd.out,
in_value=value.out,
ref_ans=ans,
ref_err=err,
(
cb.invoke( # Invoke the queue.
queue,
in_cmd=cmd.out,
in_value=value.out,
ref_ans=ans,
ref_err=err,
ref_stats=stats,
)
if stats_component
else cb.invoke( # Invoke the queue.
queue,
in_cmd=cmd.out,
in_value=value.out,
ref_ans=ans,
ref_err=err,
)
),
# We're back from the invoke, and it's time for some post-mortem analysis.
cb.if_with(
Expand Down Expand Up @@ -162,35 +162,39 @@ def insert_main(prog, queue, controller=None, stats_component=None):
not_err, # While the dataplane component has not errored out.
[
lower_has_ans, # Lower the has-ans flag.
cb.invoke( # Invoke the dataplane component.
dataplane,
ref_commands=commands,
ref_values=values,
ref_has_ans=has_ans,
ref_component_ans=dataplane_ans,
ref_component_err=dataplane_err,
ref_stats_runner=stats,
)
if stats_component
else cb.invoke( # Invoke the dataplane component.
dataplane,
ref_commands=commands,
ref_values=values,
ref_has_ans=has_ans,
ref_component_ans=dataplane_ans,
ref_component_err=dataplane_err,
(
cb.invoke( # Invoke the dataplane component.
dataplane,
ref_commands=commands,
ref_values=values,
ref_has_ans=has_ans,
ref_component_ans=dataplane_ans,
ref_component_err=dataplane_err,
ref_stats_runner=stats,
)
if stats_component
else cb.invoke( # Invoke the dataplane component.
dataplane,
ref_commands=commands,
ref_values=values,
ref_has_ans=has_ans,
ref_component_ans=dataplane_ans,
ref_component_err=dataplane_err,
)
),
# If the dataplane component has a nonzero answer,
# write it to the answer-list and increment the index `j`.
cb.if_(
has_ans.out,
cb.if_with(ans_neq_0, [write_ans, incr_j]),
),
cb.invoke( # Invoke the controller component.
controller,
ref_stats_controller=stats,
)
if controller
else ast.Empty,
(
cb.invoke( # Invoke the controller component.
controller,
ref_stats_controller=stats,
)
if controller
else ast.Empty
),
],
)
6 changes: 3 additions & 3 deletions calyx-py/test/correctness/arbiter_6.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ def add_wrap2(prog):
unchanged = wrap.reg_store(j_mod_4, j, "j_unchanged")

# Wiring to perform j-4 and j-8. Either of these will store the result in `j_mod_4`.
j_minus_4, j_mod_4 = wrap.sub_store_in_reg(j, 4, "j_minus_4", 32, j_mod_4)
j_minus_8, j_mod_4 = wrap.sub_store_in_reg(j, 8, "j_minus_8", 32, j_mod_4)
j_minus_4, j_mod_4 = wrap.sub_store_in_reg(j, 4, j_mod_4)
j_minus_8, j_mod_4 = wrap.sub_store_in_reg(j, 8, j_mod_4)

load_from_mems = [
# Add wiring to load the value `j_mod_4` from all of the memory cells.
Expand Down Expand Up @@ -121,7 +121,7 @@ def add_wrap3(prog):
unchanged = wrap.reg_store(j_mod_4, j, "j_unchanged")

# Wiring to perform j-4 and store the result in `j_mod_4`.
subcell, j_mod_4 = wrap.sub_store_in_reg(j, 4, "j_minus_4", 32, j_mod_4)
subcell, j_mod_4 = wrap.sub_store_in_reg(j, 4, j_mod_4)

emit_from_mems = [
wrap.mem_load_to_mem(mems[i], j_mod_4.out, ans, 0, f"load_from_mem{i}")
Expand Down
6 changes: 3 additions & 3 deletions calyx-py/test/correctness/reduction_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def add_tree(prog):
# Into the component `tree`, add the wiring for three adder groups that will
# use the tree to perform their additions.
# These need to be orchestrated in the control below.
add_l0_l1, left = tree.add_store_in_reg(leaf0, leaf1, "add_l0_l1", 32)
add_l2_l3, right = tree.add_store_in_reg(leaf2, leaf3, "add_l2_l3", 32)
add_l_r_nodes, root = tree.add_store_in_reg(left.out, right.out, "add_l_r", 32)
add_l0_l1, left = tree.add_store_in_reg(leaf0, leaf1)
add_l2_l3, right = tree.add_store_in_reg(leaf2, leaf3)
add_l_r_nodes, root = tree.add_store_in_reg(left.out, right.out)

# Continuously output the value of the root register.
# It is the invoker's responsibility to ensure that the tree is done
Expand Down

0 comments on commit 33b05e7

Please sign in to comment.