Skip to content

Commit

Permalink
Fix Calyx backend issue with emitting signed binops (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark1626 committed Apr 9, 2024
1 parent 9eae400 commit 164c2dd
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 10 deletions.
110 changes: 110 additions & 0 deletions file-tests/should-futil/emit-signed-op.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import "primitives/core.futil";
import "primitives/memories/seq.futil";
import "primitives/binary_operators.futil";
component main() -> () {
cells {
@external(1) a = seq_mem_d1(10,128,8);
a_read0_0 = std_reg(10);
a_read1_0 = std_reg(10);
add0 = std_sadd(10);
add1 = std_sadd(8);
and0 = std_and(10);
@external(1) b = seq_mem_d1(10,128,8);
b_read0_0 = std_reg(10);
b_read1_0 = std_reg(10);
@external(1) c = seq_mem_d1(10,128,8);
const0 = std_const(8,0);
const1 = std_const(8,1);
@external(1) d = seq_mem_d1(10,128,8);
i0 = std_reg(8);
}
wires {
group let0<"promotable"=1> {
i0.in = const0.out;
i0.write_en = 1'd1;
let0[done] = i0.done;
}
group let1<"promotable"=2> {
a_read0_0.in = a.read_data;
a_read0_0.write_en = a.done;
let1[done] = a_read0_0.done;
a.content_en = 1'd1;
a.addr0 = i0.out;
}
group let2<"promotable"=2> {
b_read0_0.in = b.read_data;
b_read0_0.write_en = b.done;
let2[done] = b_read0_0.done;
b.content_en = 1'd1;
b.addr0 = i0.out;
}
group let3<"promotable"=2> {
a_read1_0.in = a.read_data;
a_read1_0.write_en = a.done;
let3[done] = a_read1_0.done;
a.content_en = 1'd1;
a.addr0 = i0.out;
}
group let4<"promotable"=2> {
b_read1_0.in = b.read_data;
b_read1_0.write_en = b.done;
let4[done] = b_read1_0.done;
b.content_en = 1'd1;
b.addr0 = i0.out;
}
group upd0<"promotable"=1> {
c.content_en = 1'd1;
c.addr0 = i0.out;
c.write_en = 1'd1;
and0.left = a_read0_0.out;
and0.right = b_read0_0.out;
c.write_data = and0.out;
upd0[done] = c.done;
}
group upd1<"promotable"=1> {
d.content_en = 1'd1;
d.addr0 = i0.out;
d.write_en = 1'd1;
add0.left = a_read1_0.out;
add0.right = b_read1_0.out;
d.write_data = add0.out;
upd1[done] = d.done;
}
group upd2<"promotable"=1> {
i0.write_en = 1'd1;
add1.left = i0.out;
add1.right = const1.out;
i0.in = add1.out;
upd2[done] = i0.done;
}
}
control {
seq {
@pos(0) let0;
repeat 128 {
seq {
par {
@pos(1) let1;
@pos(2) let2;
}
par {
@pos(3) upd0;
@pos(4) let3;
@pos(5) let4;
}
@pos(6) upd1;
@pos(0) upd2;
}
}
}
}
}
metadata #{
0: for (let i:bit<8>=0..128) {
1: c[i] := a[i] & b[i]; // This should not be emit signed Calyx primitive
2: c[i] := a[i] & b[i]; // This should not be emit signed Calyx primitive
3: c[i] := a[i] & b[i]; // This should not be emit signed Calyx primitive
4: d[i] := a[i] + b[i]; // This should emit a signed Calyx primitive
5: d[i] := a[i] + b[i]; // This should emit a signed Calyx primitive
6: d[i] := a[i] + b[i]; // This should emit a signed Calyx primitive
}#
9 changes: 9 additions & 0 deletions file-tests/should-futil/emit-signed-op.fuse
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
decl a: bit<10>[128];
decl b: bit<10>[128];
decl c: bit<10>[128];
decl d: bit<10>[128];

for (let i:bit<8>=0..128) {
c[i] := a[i] & b[i]; // This should not be emit signed Calyx primitive
d[i] := a[i] + b[i]; // This should emit a signed Calyx primitive
}
8 changes: 4 additions & 4 deletions src/main/scala/backends/calyx/Backend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ private class CalyxBackendHelper {
/** `emitBinop` is a helper function to generate the structure for `e1 binop
* e2`. The return type is described in `emitExpr`.
*/
def emitBinop(compName: String, e1: Expr, e2: Expr)(implicit
def emitBinop(compName: String, op: BOp, e1: Expr, e2: Expr)(implicit
store: Store
): EmitOutput = {
val e1Out = emitExpr(e1)
Expand Down Expand Up @@ -286,7 +286,7 @@ private class CalyxBackendHelper {

bitsForType(e1.typ, e1.pos) match {
case (e1Bits, None) => {
val isSigned = signed(e1.typ)
val isSigned = signed(e1.typ, op)
val binOp = Stdlib.binop(s"$compName", e1Bits, isSigned)
val comp = Cell(genName(compName), binOp, false, List())
val struct = List(
Expand All @@ -309,7 +309,7 @@ private class CalyxBackendHelper {
val (e2Bits, Some(intBit2)) = bitsForType(e2.typ, e2.pos): @unchecked
val fracBit1 = e1Bits - intBit1
val fracBit2 = e2Bits - intBit2
val isSigned = signed(e1.typ)
val isSigned = signed(e1.typ, op)
assertOrThrow(
fracBit1 == fracBit2 && intBit1 == intBit2,
NotImplemented(
Expand Down Expand Up @@ -487,7 +487,7 @@ private class CalyxBackendHelper {
"out_remainder",
None
)
case _ => emitBinop(compName, e1, e2)
case _ => emitBinop(compName, op, e1, e2)
}
}
case EVar(id) =>
Expand Down
14 changes: 8 additions & 6 deletions src/main/scala/backends/calyx/Helpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ object Helpers:

/** Returns true if the given int or fixed point is signed
*/
def signed(typ: Option[Type]) =
typ match
case Some(TSizedInt(_, un)) => un == false
case Some(TFixed(_, _, un)) => un == false
case _ => false

def signed(typ: Option[Type], op: BOp) =
op match
case _@NumOp(_, _) =>
typ match
case Some(TSizedInt(_, un)) => un == false
case Some(TFixed(_, _, un)) => un == false
case _ => false
case _ => false // bit

0 comments on commit 164c2dd

Please sign in to comment.