Skip to content

Commit 9a34bbb

Browse files
authored
[Calyx] Constant op's actual value is wrapped in the attribute, while the type is always unsigned integer.
* Change calyx constant op so that the actual value is wrapped in the attribute, while the type is always unsigned integer. Make the corresponding change for addf operator so that they also take integer inputs and produce integer results; make the corresponding change for function argument passing to convert floating point args to integer. Finally make the corresponding change for the test code.
1 parent 31cd866 commit 9a34bbb

File tree

8 files changed

+54
-59
lines changed

8 files changed

+54
-59
lines changed

include/circt/Dialect/Calyx/CalyxHelpers.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ calyx::RegisterOp createRegister(Location loc, OpBuilder &builder,
3030
ComponentOp component, size_t width,
3131
Twine prefix);
3232

33-
calyx::RegisterOp createRegister(Location loc, OpBuilder &builder,
34-
ComponentOp component, Type type,
35-
Twine prefix);
36-
3733
/// A helper function to create constants in the HW dialect.
3834
hw::ConstantOp createConstant(Location loc, OpBuilder &builder,
3935
ComponentOp component, size_t width,

include/circt/Dialect/Calyx/CalyxPrimitives.td

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,33 @@ class CalyxPrimitive<string mnemonic, list<Trait> traits = []> :
2121
}
2222

2323
def ConstantOp: CalyxPrimitive<"constant",
24-
[ConstantLike, FirstAttrDerivedResultType,
25-
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
26-
AllTypesMatch<["value", "out"]>
24+
[ConstantLike, DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
2725
]> {
28-
let summary = "integer or floating point constant";
26+
let summary = "constant capable of representing an integer or floating point value";
2927
let description = [{
30-
The `constant` operation produces an SSA value equal to some integer or
31-
floating-point constant specified by an attribute.
28+
The `constant` operation is a wrapper around bit vectors with fixed-size number of bits.
29+
Specific value and intended type should be specified via attribute only.
3230

3331
Example:
3432

3533
```
3634
// Integer constant
37-
%1 = calyx.constant 42 : i32
35+
%1 = calyx.constant <42 : i32> : i32
3836

3937
// Floating point constant
40-
%1 = calyx.constant 42.00+e00 : f32
38+
%1 = calyx.constant <4.2 : f32> : i32
4139
```
4240
}];
43-
let arguments = (ins TypedAttrInterface:$value);
41+
let arguments = (ins SymbolNameAttr:$sym_name, TypedAttrInterface:$value);
4442

45-
let results = (outs SignlessIntegerOrFloatLike:$out);
43+
let results = (outs AnySignlessInteger:$out);
4644

4745
let builders = [
48-
/// Build a ConstantOp from a prebuilt attribute.
49-
OpBuilder <(ins "StringRef":$sym_name, "TypedAttr":$attr)>,
46+
OpBuilder <(ins "StringRef":$sym_name, "Attribute":$attr, "Type":$type)>,
5047
];
5148

5249
let hasFolder = 1;
53-
let assemblyFormat = "attr-dict $value";
50+
let assemblyFormat = "$sym_name ` ` `<` $value `>` attr-dict `:` qualified(type($out))";
5451
let hasVerifier = 1;
5552
}
5653

@@ -340,7 +337,7 @@ class ArithBinaryFloatingPointLibraryOp<string mnemonic> : ArithBinaryLibraryOp<
340337

341338
def AddFNOp : ArithBinaryFloatingPointLibraryOp<"addFN"> {
342339
let results = (outs I1:$clk, I1:$reset, I1:$go, I1:$control, I1:$subOp,
343-
AnyFloat:$left, AnyFloat:$right, AnySignlessInteger:$roundingMode, AnyFloat:$out,
340+
AnySignlessInteger:$left, AnySignlessInteger:$right, AnySignlessInteger:$roundingMode, AnySignlessInteger:$out,
344341
AnySignlessInteger:$exceptionalFlags, I1:$done);
345342

346343
let extraClassDefinition = [{
@@ -352,11 +349,11 @@ def AddFNOp : ArithBinaryFloatingPointLibraryOp<"addFN"> {
352349

353350
SmallVector<Direction> $cppClass::portDirections() {
354351
return {Input, Input, Input, Input, Input, Input, Input, Input, Output, Output, Output};
355-
}
352+
}
356353

357354
void $cppClass::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
358355
getCellAsmResultNames(setNameFn, *this, this->portNames());
359-
}
356+
}
360357

361358
bool $cppClass::isCombinational() { return false; }
362359

lib/Conversion/SCFToCalyx/SCFToCalyx.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ class BuildOpGroups : public calyx::FuncOpPartialLoweringPattern {
414414
// Pass the result from the Operation to the Calyx primitive.
415415
op.getResult().replaceAllUsesWith(out);
416416
auto reg = createRegister(
417-
op.getLoc(), rewriter, getComponent(), width,
417+
op.getLoc(), rewriter, getComponent(), width.getIntOrFloatBitWidth(),
418418
getState<ComponentLoweringState>().getUniqueName(opName));
419419
// Operation pipelines are not combinational, so a GroupOp is required.
420420
auto group = createGroupForOp<calyx::GroupOp>(rewriter, op);
@@ -687,9 +687,10 @@ LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,
687687
LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,
688688
AddFOp addf) const {
689689
Location loc = addf.getLoc();
690-
Type width = addf.getResult().getType();
691690
IntegerType one = rewriter.getI1Type(), three = rewriter.getIntegerType(3),
692-
five = rewriter.getIntegerType(5);
691+
five = rewriter.getIntegerType(5),
692+
width = rewriter.getIntegerType(
693+
addf.getType().getIntOrFloatBitWidth());
693694
auto addFN =
694695
getState<ComponentLoweringState>()
695696
.getNewLibraryOpInstance<calyx::AddFNOp>(
@@ -935,8 +936,11 @@ LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,
935936
getComponent().getBodyBlock()->begin());
936937
} else {
937938
std::string name = getState<ComponentLoweringState>().getUniqueName("cst");
939+
auto floatAttr = cast<FloatAttr>(constOp.getValueAttr());
940+
auto intType =
941+
rewriter.getIntegerType(floatAttr.getType().getIntOrFloatBitWidth());
938942
auto calyxConstOp = rewriter.create<calyx::ConstantOp>(
939-
constOp.getLoc(), name, constOp.getValueAttr());
943+
constOp.getLoc(), name, floatAttr, intType);
940944
calyxConstOp->moveAfter(getComponent().getBodyBlock(),
941945
getComponent().getBodyBlock()->begin());
942946
rewriter.replaceAllUsesWith(constOp, calyxConstOp.getOut());
@@ -1215,6 +1219,7 @@ struct FuncOpConversion : public calyx::FuncOpPartialLoweringPattern {
12151219
else
12161220
resName = "out" + std::to_string(res.index());
12171221
funcOpResultMapping[res.index()] = outPorts.size();
1222+
12181223
outPorts.push_back(calyx::PortInfo{
12191224
rewriter.getStringAttr(resName),
12201225
calyx::convIndexType(rewriter, res.value()), calyx::Direction::Output,

lib/Dialect/Calyx/CalyxOps.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,10 +1980,13 @@ void ConstantOp::getAsmResultNames(
19801980

19811981
LogicalResult ConstantOp::verify() {
19821982
auto type = getType();
1983-
// The value's type must match the return type.
1984-
if (auto valType = getValue().getType(); valType != type) {
1985-
return emitOpError() << "value type " << valType
1986-
<< " must match return type: " << type;
1983+
assert(isa<IntegerType>(type) && "must be an IntegerType");
1984+
// The value's bit width must match the return type bitwidth.
1985+
if (auto valTyBitWidth = getValue().getType().getIntOrFloatBitWidth();
1986+
valTyBitWidth != type.getIntOrFloatBitWidth()) {
1987+
return emitOpError() << "value type bit width" << valTyBitWidth
1988+
<< " must match return type: "
1989+
<< type.getIntOrFloatBitWidth();
19871990
}
19881991
// Integer values must be signless.
19891992
if (llvm::isa<IntegerType>(type) &&
@@ -2002,12 +2005,12 @@ OpFoldResult calyx::ConstantOp::fold(FoldAdaptor adaptor) {
20022005
}
20032006

20042007
void calyx::ConstantOp::build(OpBuilder &builder, OperationState &state,
2005-
StringRef symName, TypedAttr attr) {
2008+
StringRef symName, Attribute attr, Type type) {
20062009
state.addAttribute(SymbolTable::getSymbolAttrName(),
20072010
builder.getStringAttr(symName));
20082011
state.addAttribute("value", attr);
20092012
SmallVector<Type> types;
2010-
types.push_back(attr.getType()); // Out
2013+
types.push_back(type); // Out
20112014
state.addTypes(types);
20122015
}
20132016

lib/Dialect/Calyx/Transforms/CalyxHelpers.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,6 @@ calyx::RegisterOp createRegister(Location loc, OpBuilder &builder,
2727
return builder.create<RegisterOp>(loc, (prefix + "_reg").str(), width);
2828
}
2929

30-
calyx::RegisterOp createRegister(Location loc, OpBuilder &builder,
31-
ComponentOp component, Type type,
32-
Twine prefix) {
33-
OpBuilder::InsertionGuard guard(builder);
34-
builder.setInsertionPointToStart(component.getBodyBlock());
35-
return builder.create<RegisterOp>(loc, (prefix + "_reg").str(), type);
36-
}
37-
3830
hw::ConstantOp createConstant(Location loc, OpBuilder &builder,
3931
ComponentOp component, size_t width,
4032
size_t value) {

lib/Dialect/Calyx/Transforms/CalyxLoweringUtils.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ Value getComponentOutput(calyx::ComponentOp compOp, unsigned outPortIdx) {
139139
Type convIndexType(OpBuilder &builder, Type type) {
140140
if (type.isIndex())
141141
return builder.getI32Type();
142+
if (type.isIntOrFloat() && !type.isInteger())
143+
return builder.getIntegerType(type.getIntOrFloatBitWidth());
142144
return type;
143145
}
144146

@@ -768,7 +770,7 @@ BuildReturnRegs::partiallyLowerFuncToComp(mlir::func::FuncOp funcOp,
768770
"unsupported return type");
769771
std::string name = "ret_arg" + std::to_string(argType.index());
770772
auto reg = createRegister(funcOp.getLoc(), rewriter, getComponent(),
771-
convArgType, name);
773+
convArgType.getIntOrFloatBitWidth(), name);
772774
getState().addReturnReg(reg, argType.index());
773775

774776
rewriter.setInsertionPointToStart(

test/Conversion/SCFToCalyx/convert_simple.mlir

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,11 @@ module {
215215
// Test integer and floating point constant
216216

217217
// CHECK: calyx.group @ret_assign_0 {
218-
// CHECK-DAG: calyx.assign %ret_arg0_reg.in = %in0 : f32
218+
// CHECK-DAG: calyx.assign %ret_arg0_reg.in = %in0 : i32
219219
// CHECK-DAG: calyx.assign %ret_arg0_reg.write_en = %true : i1
220220
// CHECK-DAG: calyx.assign %ret_arg1_reg.in = %c42_i32 : i32
221221
// CHECK-DAG: calyx.assign %ret_arg1_reg.write_en = %true : i1
222-
// CHECK-DAG: calyx.assign %ret_arg2_reg.in = %cst : f32
222+
// CHECK-DAG: calyx.assign %ret_arg2_reg.in = %cst : i32
223223
// CHECK-DAG: calyx.assign %ret_arg2_reg.write_en = %true : i1
224224
// CHECK-DAG: %0 = comb.and %ret_arg2_reg.done, %ret_arg1_reg.done, %ret_arg0_reg.done : i1
225225
// CHECK-DAG: calyx.group_done %0 ? %true : i1
@@ -239,9 +239,9 @@ module {
239239
// Test floating point add
240240

241241
// CHECK: calyx.group @bb0_0 {
242-
// CHECK-DAG: calyx.assign %std_addFN_0.left = %in0 : f32
243-
// CHECK-DAG: calyx.assign %std_addFN_0.right = %cst : f32
244-
// CHECK-DAG: calyx.assign %addf_0_reg.in = %std_addFN_0.out : f32
242+
// CHECK-DAG: calyx.assign %std_addFN_0.left = %in0 : i32
243+
// CHECK-DAG: calyx.assign %std_addFN_0.right = %cst : i32
244+
// CHECK-DAG: calyx.assign %addf_0_reg.in = %std_addFN_0.out : i32
245245
// CHECK-DAG: calyx.assign %addf_0_reg.write_en = %std_addFN_0.done : i1
246246
// CHECK-DAG: %0 = comb.xor %std_addFN_0.done, %true : i1
247247
// CHECK-DAG: calyx.assign %std_addFN_0.go = %0 ? %true : i1

test/Dialect/Calyx/emit.mlir

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,15 @@ module attributes {calyx.entrypoint = "main"} {
245245
// -----
246246

247247
module attributes {calyx.entrypoint = "main"} {
248-
calyx.component @main(%clk: i1 {clk}, %reset: i1 {reset}, %go: i1 {go}) -> (%out0: i32, %out1: f32, %done: i1 {done}) {
248+
calyx.component @main(%clk: i1 {clk}, %reset: i1 {reset}, %go: i1 {go}) -> (%out0: i32, %out1: i32, %done: i1 {done}) {
249249
// CHECK: cst_0 = std_float_const(0, 32, 4.200000);
250250
%c42_i32 = hw.constant 42 : i32
251-
%cst = calyx.constant {sym_name = "cst_0"} 4.200000e+00 : f32
251+
%cst = calyx.constant @cst_0 <4.200000e+00 : f32> : i32
252252
%true = hw.constant true
253-
%ret_arg1_reg.in, %ret_arg1_reg.write_en, %ret_arg1_reg.clk, %ret_arg1_reg.reset, %ret_arg1_reg.out, %ret_arg1_reg.done = calyx.register @ret_arg1_reg : f32, i1, i1, i1, f32, i1
253+
%ret_arg1_reg.in, %ret_arg1_reg.write_en, %ret_arg1_reg.clk, %ret_arg1_reg.reset, %ret_arg1_reg.out, %ret_arg1_reg.done = calyx.register @ret_arg1_reg : i32, i1, i1, i1, i32, i1
254254
%ret_arg0_reg.in, %ret_arg0_reg.write_en, %ret_arg0_reg.clk, %ret_arg0_reg.reset, %ret_arg0_reg.out, %ret_arg0_reg.done = calyx.register @ret_arg0_reg : i32, i1, i1, i1, i32, i1
255255
calyx.wires {
256-
calyx.assign %out1 = %ret_arg1_reg.out : f32
256+
calyx.assign %out1 = %ret_arg1_reg.out : i32
257257
calyx.assign %out0 = %ret_arg0_reg.out : i32
258258

259259
// CHECK-LABEL: group ret_assign_0 {
@@ -266,7 +266,7 @@ module attributes {calyx.entrypoint = "main"} {
266266
calyx.group @ret_assign_0 {
267267
calyx.assign %ret_arg0_reg.in = %c42_i32 : i32
268268
calyx.assign %ret_arg0_reg.write_en = %true : i1
269-
calyx.assign %ret_arg1_reg.in = %cst : f32
269+
calyx.assign %ret_arg1_reg.in = %cst : i32
270270
calyx.assign %ret_arg1_reg.write_en = %true : i1
271271
%0 = comb.and %ret_arg1_reg.done, %ret_arg0_reg.done : i1
272272
calyx.group_done %0 ? %true : i1
@@ -285,16 +285,16 @@ module attributes {calyx.entrypoint = "main"} {
285285

286286
module attributes {calyx.entrypoint = "main"} {
287287
// CHECK: import "primitives/float/addFN.futil";
288-
calyx.component @main(%in0: f32, %clk: i1 {clk}, %reset: i1 {reset}, %go: i1 {go}) -> (%out0: f32, %done: i1 {done}) {
288+
calyx.component @main(%in0: i32, %clk: i1 {clk}, %reset: i1 {reset}, %go: i1 {go}) -> (%out0: i32, %done: i1 {done}) {
289289
// CHECK: std_addFN_0 = std_addFN(8, 24, 32);
290-
%cst = calyx.constant {sym_name = "cst_0"} 4.200000e+00 : f32
290+
%cst = calyx.constant @cst_0 <4.200000e+00 : f32> : i32
291291
%true = hw.constant true
292292
%false = hw.constant false
293-
%addf_0_reg.in, %addf_0_reg.write_en, %addf_0_reg.clk, %addf_0_reg.reset, %addf_0_reg.out, %addf_0_reg.done = calyx.register @addf_0_reg : f32, i1, i1, i1, f32, i1
294-
%std_addFN_0.clk, %std_addFN_0.reset, %std_addFN_0.go, %std_addFN_0.control, %std_addFN_0.subOp, %std_addFN_0.left, %std_addFN_0.right, %std_addFN_0.roundingMode, %std_addFN_0.out, %std_addFN_0.exceptionalFlags, %std_addFN_0.done = calyx.std_addFN @std_addFN_0 : i1, i1, i1, i1, i1, f32, f32, i3, f32, i5, i1
295-
%ret_arg0_reg.in, %ret_arg0_reg.write_en, %ret_arg0_reg.clk, %ret_arg0_reg.reset, %ret_arg0_reg.out, %ret_arg0_reg.done = calyx.register @ret_arg0_reg : f32, i1, i1, i1, f32, i1
293+
%addf_0_reg.in, %addf_0_reg.write_en, %addf_0_reg.clk, %addf_0_reg.reset, %addf_0_reg.out, %addf_0_reg.done = calyx.register @addf_0_reg : i32, i1, i1, i1, i32, i1
294+
%std_addFN_0.clk, %std_addFN_0.reset, %std_addFN_0.go, %std_addFN_0.control, %std_addFN_0.subOp, %std_addFN_0.left, %std_addFN_0.right, %std_addFN_0.roundingMode, %std_addFN_0.out, %std_addFN_0.exceptionalFlags, %std_addFN_0.done = calyx.std_addFN @std_addFN_0 : i1, i1, i1, i1, i1, i32, i32, i3, i32, i5, i1
295+
%ret_arg0_reg.in, %ret_arg0_reg.write_en, %ret_arg0_reg.clk, %ret_arg0_reg.reset, %ret_arg0_reg.out, %ret_arg0_reg.done = calyx.register @ret_arg0_reg : i32, i1, i1, i1, i32, i1
296296
calyx.wires {
297-
calyx.assign %out0 = %ret_arg0_reg.out : f32
297+
calyx.assign %out0 = %ret_arg0_reg.out : i32
298298

299299
// CHECK-LABEL: group bb0_0 {
300300
// CHECK-NEXT: std_addFN_0.left = in0;
@@ -306,17 +306,17 @@ module attributes {calyx.entrypoint = "main"} {
306306
// CHECK-NEXT: bb0_0[done] = addf_0_reg.done;
307307
// CHECK-NEXT: }
308308
calyx.group @bb0_0 {
309-
calyx.assign %std_addFN_0.left = %in0 : f32
310-
calyx.assign %std_addFN_0.right = %cst : f32
311-
calyx.assign %addf_0_reg.in = %std_addFN_0.out : f32
309+
calyx.assign %std_addFN_0.left = %in0 : i32
310+
calyx.assign %std_addFN_0.right = %cst : i32
311+
calyx.assign %addf_0_reg.in = %std_addFN_0.out : i32
312312
calyx.assign %addf_0_reg.write_en = %std_addFN_0.done : i1
313313
%0 = comb.xor %std_addFN_0.done, %true : i1
314314
calyx.assign %std_addFN_0.go = %0 ? %true : i1
315315
calyx.assign %std_addFN_0.subOp = %false : i1
316316
calyx.group_done %addf_0_reg.done : i1
317317
}
318318
calyx.group @ret_assign_0 {
319-
calyx.assign %ret_arg0_reg.in = %std_addFN_0.out : f32
319+
calyx.assign %ret_arg0_reg.in = %std_addFN_0.out : i32
320320
calyx.assign %ret_arg0_reg.write_en = %true : i1
321321
calyx.group_done %ret_arg0_reg.done : i1
322322
}

0 commit comments

Comments
 (0)