Skip to content

Commit

Permalink
Merge branch 'main' into dynamic-axi
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanielnrn authored Jun 15, 2024
2 parents a3acbe3 + 02d64d5 commit f00bda0
Show file tree
Hide file tree
Showing 44 changed files with 844 additions and 260 deletions.
46 changes: 39 additions & 7 deletions calyx-py/calyx/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,10 @@ def comb_mem_d2(
"""Generate a StdMemD2 cell."""
self.prog.import_("primitives/memories/comb.futil")
return self.cell(
name, ast.Stdlib.comb_mem_d2(bitwidth, len0, len1, idx_size0, idx_size1), is_external, is_ref
name,
ast.Stdlib.comb_mem_d2(bitwidth, len0, len1, idx_size0, idx_size1),
is_external,
is_ref,
)

def seq_mem_d1(
Expand Down Expand Up @@ -446,7 +449,10 @@ def seq_mem_d2(
"""Generate a SeqMemD2 cell."""
self.prog.import_("primitives/memories/seq.futil")
return self.cell(
name, ast.Stdlib.seq_mem_d2(bitwidth, len0, len1, idx_size0, idx_size1), is_external, is_ref
name,
ast.Stdlib.seq_mem_d2(bitwidth, len0, len1, idx_size0, idx_size1),
is_external,
is_ref,
)

def binary(
Expand Down Expand Up @@ -793,7 +799,7 @@ def reg_store(self, reg, val, groupname=None):

def mem_load_d1(self, mem, i, reg, groupname):
"""Inserts wiring into `self` to perform `reg := mem[i]`,
where `mem` is a seq_d1 memory or a comb_mem_d1 memory
where `mem` is a seq_d1 memory or a comb_mem_d1 memory
"""
assert mem.is_seq_mem_d1() or mem.is_comb_mem_d1()
is_comb = mem.is_comb_mem_d1()
Expand All @@ -811,7 +817,7 @@ def mem_load_d1(self, mem, i, reg, groupname):

def mem_load_d2(self, mem, i, j, reg, groupname):
"""Inserts wiring into `self` to perform `reg := mem[i]`,
where `mem` is a seq_d2 memory or a comb_mem_d2 memory
where `mem` is a seq_d2 memory or a comb_mem_d2 memory
"""
assert mem.is_seq_mem_d2() or mem.is_comb_mem_d2()
is_comb = mem.is_comb_mem_d2()
Expand All @@ -830,7 +836,7 @@ def mem_load_d2(self, mem, i, j, reg, groupname):

def mem_store_d1(self, mem, i, val, groupname):
"""Inserts wiring into `self` to perform `mem[i] := val`,
where `mem` is a seq_d1 memory or a comb_mem_d1 memory
where `mem` is a seq_d1 memory or a comb_mem_d1 memory
"""
assert mem.is_seq_mem_d1() or mem.is_comb_mem_d1()
is_comb = mem.is_comb_mem_d1()
Expand All @@ -845,7 +851,7 @@ def mem_store_d1(self, mem, i, val, groupname):

def mem_store_d2(self, mem, i, j, val, groupname):
"""Inserts wiring into `self` to perform `mem[i] := val`,
where `mem` is a seq_d2 memory or a comb_mem_d2 memory
where `mem` is a seq_d2 memory or a comb_mem_d2 memory
"""
assert mem.is_seq_mem_d2() or mem.is_comb_mem_d2()
is_comb = mem.is_comb_mem_d2()
Expand Down Expand Up @@ -1098,14 +1104,24 @@ def invoke(cell: CellBuilder, **kwargs) -> ast.Invoke:
The keyword arguments should have the form `in_*`, `out_*`, or `ref_*`, where
`*` is the name of an input port, output port, or ref cell on the invoked cell.
"""

def try_infer_width(x):
width = cell.infer_width(x)
if not width:
raise WidthInferenceError(
f"Could not infer width of input '{x}' when invoking cell '{cell.name}'. "
"Consider using `const(width, value)` instead of `value`."
)
return width

return ast.Invoke(
cell._cell.id,
[
(
k[3:],
(
(
const(cell.infer_width(k[3:]), v).expr
const(try_infer_width(k[3:]), v).expr
if isinstance(v, int)
else ExprBuilder.unwrap(v)
)
Expand Down Expand Up @@ -1225,6 +1241,22 @@ def __ne__(self, other: ExprBuilder):
"""Construct an inequality comparison with ==."""
return ExprBuilder(ast.Neq(self.expr, other.expr))

def __lt__(self, other: ExprBuilder):
"""Construct a less-than comparison with <."""
return ExprBuilder(ast.Lt(self.expr, other.expr))

def __le__(self, other: ExprBuilder):
"""Construct a less-than-or-equal comparison with <."""
return ExprBuilder(ast.Lte(self.expr, other.expr))

def __gt__(self, other: ExprBuilder):
"""Construct a greater-than comparison with <."""
return ExprBuilder(ast.Gt(self.expr, other.expr))

def __ge__(self, other: ExprBuilder):
"""Construct a greater-than-or-equal comparison with <."""
return ExprBuilder(ast.Gte(self.expr, other.expr))

@property
def name(self):
"""Get the name of the expression."""
Expand Down
42 changes: 26 additions & 16 deletions calyx-py/calyx/gen_exp.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,17 @@ def generate_fp_pow_component(
)

# groups
with comp.group("init") as init:
with comp.group("init_pow") as init_pow:
pow.in_ = FixedPoint(
"1.0", width, int_width, is_signed=is_signed
).unsigned_integer()
pow.write_en = 1
init_pow.done = pow.done

with comp.group("init_count") as init_count:
count.in_ = 0
count.write_en = 1
init.done = (pow.done & count.done) @ 1
init_count.done = count.done

with comp.group("execute_mul") as execute_mul:
mul.left = comp.this().base
Expand All @@ -73,7 +76,10 @@ def generate_fp_pow_component(
with comp.continuous:
comp.this().out = pow.out

comp.control += [init, while_with(cond, par(execute_mul, incr_count))]
comp.control += [
par(init_pow, init_count),
while_with(cond, par(execute_mul, incr_count)),
]

return comp.component

Expand Down Expand Up @@ -312,18 +318,20 @@ def generate_groups(
int_x = comp.get_cell("int_x")
frac_x = comp.get_cell("frac_x")
one = comp.get_cell("one")
with comp.group("split_bits") as split_bits:
with comp.group("split_bits_int_x") as split_bits_int_x:
and0.left = input.out
and0.right = const(width, 2**width - 2**frac_width)
rsh.left = and0.out
rsh.right = const(width, frac_width)
int_x.write_en = 1
int_x.in_ = rsh.out
split_bits_int_x.done = int_x.done
with comp.group("split_bits_frac_x") as split_bits_frac_x:
and1.left = input.out
and1.right = const(width, (2**frac_width) - 1)
int_x.write_en = 1
frac_x.write_en = 1
int_x.in_ = rsh.out
frac_x.in_ = and1.out
split_bits.done = (int_x.done & frac_x.done) @ 1
split_bits_frac_x.done = frac_x.done

if is_signed:
mult_pipe = comp.get_cell("mult_pipe1")
Expand Down Expand Up @@ -411,7 +419,8 @@ def generate_control(comp: ComponentBuilder, degree: int, is_signed: bool):
if is_signed:
lt = comp.get_cell("lt")
init = comp.get_group("init")
split_bits = comp.get_group("split_bits")
split_bits_int_x = comp.get_group("split_bits_int_x")
split_bits_frac_x = comp.get_group("split_bits_frac_x")

# TODO (griffin): This is a hack to avoid inserting empty seqs. Maybe worth
# moving into the add method of ControlBuilder?
Expand All @@ -430,7 +439,7 @@ def generate_control(comp: ComponentBuilder, degree: int, is_signed: bool):
if is_signed
else []
),
split_bits,
par(split_bits_int_x, split_bits_frac_x),
pow_invokes,
consume_pow,
mult_by_reciprocal,
Expand Down Expand Up @@ -695,9 +704,9 @@ def build_base_not_e(degree, width, int_width, is_signed) -> Program:
main = builder.component("main")
base_reg = main.reg(width, "base_reg")
exp_reg = main.reg(width, "exp_reg")
x = main.comb_mem_d1("x", width, 1, 1, is_external=True)
b = main.comb_mem_d1("b", width, 1, 1, is_external=True)
ret = main.comb_mem_d1("ret", width, 1, 1, is_external=True)
x = main.seq_mem_d1("x", width, 1, 1, is_external=True)
b = main.seq_mem_d1("b", width, 1, 1, is_external=True)
ret = main.seq_mem_d1("ret", width, 1, 1, is_external=True)
f = main.comp_instance("f", "fp_pow_full")

read_base = main.mem_load_d1(b, 0, base_reg, "read_base")
Expand Down Expand Up @@ -731,14 +740,15 @@ def build_base_is_e(degree, width, int_width, is_signed) -> Program:
main = builder.component("main")

t = main.reg(width, "t")
x = main.comb_mem_d1("x", width, 1, 1, is_external=True)
ret = main.comb_mem_d1("ret", width, 1, 1, is_external=True)
x = main.seq_mem_d1("x", width, 1, 1, is_external=True)
ret = main.seq_mem_d1("ret", width, 1, 1, is_external=True)
e = main.comp_instance("e", "exp")

with main.group("init") as init:
x.addr0 = 0
t.in_ = x.read_data
t.write_en = 1
x.content_en = 1
t.in_ = x.done @ x.read_data
t.write_en = x.done @ 1
init.done = t.done

write_to_memory = main.mem_store_d1(ret, 0, e.out, "write_to_memory")
Expand Down
36 changes: 36 additions & 0 deletions calyx-py/calyx/py_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,42 @@ def doc(self) -> str:
return f"({self.left.doc()} != {self.right.doc()})"


@dataclass
class Lt(GuardExpr):
left: GuardExpr
right: GuardExpr

def doc(self) -> str:
return f"({self.left.doc()} < {self.right.doc()})"


@dataclass
class Lte(GuardExpr):
left: GuardExpr
right: GuardExpr

def doc(self) -> str:
return f"({self.left.doc()} <= {self.right.doc()})"


@dataclass
class Gt(GuardExpr):
left: GuardExpr
right: GuardExpr

def doc(self) -> str:
return f"({self.left.doc()} > {self.right.doc()})"


@dataclass
class Gte(GuardExpr):
left: GuardExpr
right: GuardExpr

def doc(self) -> str:
return f"({self.left.doc()} >= {self.right.doc()})"


# Control
@dataclass
class Control(Emittable):
Expand Down
12 changes: 12 additions & 0 deletions calyx-py/test/correctness/guards.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"mem": {
"data": [
0
],
"format": {
"numeric_type": "bitnum",
"is_signed": false,
"width": 32
}
}
}
5 changes: 5 additions & 0 deletions calyx-py/test/correctness/guards.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"mem": [
42
]
}
39 changes: 39 additions & 0 deletions calyx-py/test/correctness/guards.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# pylint: disable=import-error
import calyx.builder as cb


def insert_main_component(prog):
"""Insert the main component into the program.
This component will invoke the `muler`, `abs_diff`, `mux`, and `map` components.
"""

comp = prog.component("main")

mem = comp.seq_mem_d1("mem", 32, 1, 32, is_external=True)

mul = comp.mult_pipe(32)
zero = cb.const(32, 0)
one = cb.const(32, 1)

with comp.group("well-guarded_group") as wgg:
mul.left = zero @ 4 # This will never be executed
mul.left = (one <= zero) @ 5 # This will never be executed
mul.left = ~zero @ 6 # This will work
mul.right = (zero | one) @ 7 # This will work
mul.right = (zero & one) @ 8 # This will never be executed
mul.go = cb.HI
wgg.done = mul.done

put_ans_in_mem = comp.mem_store_d1(mem, 0, mul.out, "store")

comp.control += [wgg, put_ans_in_mem]


def build():
prog = cb.Builder()
insert_main_component(prog)
return prog.program


if __name__ == "__main__":
build().emit()
9 changes: 6 additions & 3 deletions calyx-py/test/correctness/queues/sdn.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,18 @@ def insert_controller(prog, name, stats_component):
count_0 = controller.reg(32)
count_1 = controller.reg(32)

with controller.group("get_data_locally") as get_data_locally:
with controller.group("get_data_locally_count0") as get_data_locally_count0:
count_0.in_ = stats.count_0
count_0.write_en = 1
get_data_locally_count0.done = count_0.done

with controller.group("get_data_locally_count1") as get_data_locally_count1:
count_1.in_ = stats.count_1
count_1.write_en = 1
get_data_locally.done = (count_0.done & count_1.done) @ 1
get_data_locally_count1.done = count_1.done

# The main logic.
controller.control += get_data_locally
controller.control += cb.par(get_data_locally_count0, get_data_locally_count1)
# Great, now I have the data around locally.

return controller
Expand Down
10 changes: 7 additions & 3 deletions calyx-py/test/correctness/tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,23 @@ def insert_main(prog):
mem1.content_en = cb.HI
run_tuplify.done = mem1.done

with comp.group("run_untuplify") as run_untuplify:
with comp.group("run_untuplify_fst") as run_untuplify_fst:
untuplify.tup = cb.const(64, 17179869186)
mem2.addr0 = cb.const(1, 0)
mem2.write_en = cb.HI
mem2.write_data = untuplify.fst
mem2.content_en = cb.HI
run_untuplify_fst.done = mem2.done

with comp.group("run_untuplify_snd") as run_untuplify_snd:
untuplify.tup = cb.const(64, 17179869186)
mem3.addr0 = cb.const(1, 0)
mem3.write_en = cb.HI
mem3.write_data = untuplify.snd
mem3.content_en = cb.HI
run_untuplify.done = (mem2.done & mem3.done) @ cb.HI
run_untuplify_snd.done = mem3.done

comp.control += cb.par(run_tuplify, run_untuplify)
comp.control += cb.par(run_tuplify, run_untuplify_fst, run_untuplify_snd)

return comp

Expand Down
Loading

0 comments on commit f00bda0

Please sign in to comment.