Skip to content

Commit

Permalink
eDSL integrations for pipelined operations (#2141)
Browse files Browse the repository at this point in the history
Added eDSL `op_use` and `op_store_in_reg` functionality for non-combinational binary operations, and implicit combinational checking.
  • Loading branch information
KabirSamsi committed Jun 18, 2024
1 parent 04add67 commit 76cc300
Showing 1 changed file with 67 additions and 3 deletions.
70 changes: 67 additions & 3 deletions calyx-py/calyx/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,8 @@ def binary_use(self, left, right, cell, groupname=None):
with self.comb_group(groupname) as comb_group:
cell.left = left
cell.right = right
if not cell.is_comb():
cell.go = HI
return CellAndGroup(cell, comb_group)

def binary_use_names(self, cellname, leftname, rightname, groupname=None):
Expand Down Expand Up @@ -718,6 +720,16 @@ def not_use(self, input, cellname=None, width=None):
width = self.try_infer_width(width, input, input)
return self.unary_use(input, self.not_(width, cellname))

def mult_use(self, left, right, signed=False, cellname=None, width=None):
"""Inserts wiring into `self` to compute `left` * `right`."""
width = self.try_infer_width(width, left, right)
return self.binary_use(left, right, self.mult_pipe(width, cellname, signed))

def div_use(self, left, right, signed=False, cellname=None, width=None):
"""Inserts wiring into `self` to compute `left` * `right`."""
width = self.try_infer_width(width, left, right)
return self.binary_use(left, right, self.div_pipe(width, cellname, signed))

def bitwise_flip_reg(self, reg, cellname=None):
"""Inserts wiring into `self` to bitwise-flip the contents of `reg`
and put the result back into `reg`.
Expand Down Expand Up @@ -885,18 +897,25 @@ def op_store_in_reg(
right,
cellname,
width,
ans_reg=None,
ans_reg=None
):
"""Inserts wiring into `self` to perform `reg := left op right`,
where `op_cell`, a Cell that performs some `op`, is provided.
"""

is_comb = op_cell.is_comb()
ans_reg = ans_reg or self.reg(width, f"reg_{cellname}")
with self.group(f"{cellname}_group") as op_group:
op_cell.left = left
op_cell.right = right
ans_reg.write_en = 1
ans_reg.in_ = op_cell.out

if not is_comb:
op_cell.go = HI

ans_reg.write_en = 1 if is_comb else op_cell.done @ 1
ans_reg.in_ = op_cell.out if is_comb else op_cell.done @ op_cell.out
op_group.done = ans_reg.done

return op_group, ans_reg

def add_store_in_reg(
Expand Down Expand Up @@ -955,6 +974,35 @@ def neq_store_in_reg(
cell = self.neq(width, cellname, signed)
return self.op_store_in_reg(cell, left, right, cell.name, 1, ans_reg)

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

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


def infer_width(self, expr) -> int:
"""Infer the width of an expression."""
if isinstance(expr, int): # We can't infer the width of an integer.
Expand Down Expand Up @@ -1342,6 +1390,22 @@ def is_primitive(self, prim_name) -> bool:
and self._cell.comp.id == prim_name
)

def is_comb(self) -> bool:
return self._cell.comp.id in (
"std_add",
"std_sub",
"std_lt",
"std_le",
"std_ge",
"std_gt",
"std_eq",
"std_neq",
"std_sgt",
"std_slt",
"std_fp_sgt",
"std_fp_slt",
)

def is_comb_mem_d1(self) -> bool:
"""Check if the cell is a StdMemD1 cell."""
return self.is_primitive("comb_mem_d1")
Expand Down

0 comments on commit 76cc300

Please sign in to comment.