Skip to content

Commit

Permalink
calyx constant op
Browse files Browse the repository at this point in the history
  • Loading branch information
jiahanxie353 committed May 23, 2024
1 parent 1e189d9 commit fc689f7
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 14 deletions.
38 changes: 38 additions & 0 deletions include/circt/Dialect/Calyx/CalyxPrimitives.td
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
//
//===----------------------------------------------------------------------===//

include "mlir/IR/BuiltinAttributeInterfaces.td"

/// Base class for Calyx primitives.
class CalyxPrimitive<string mnemonic, list<Trait> traits = []> :
CalyxCell<mnemonic, traits> {
Expand All @@ -18,6 +20,42 @@ class CalyxPrimitive<string mnemonic, list<Trait> traits = []> :
let skipDefaultBuilders = 1;
}

def ConstantOp: CalyxOp<"constant",
[Pure, ConstantLike, FirstAttrDerivedResultType,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
AllTypesMatch<["value", "result"]>
]> {
let summary = "integer or floating point constant";
let description = [{
The `constant` operation produces an SSA value equal to some integer or
floating-point constant specified by an attribute.

Example:

```
// Integer constant
%1 = calyx.constant 42 : i32

// Floating point constant
%1 = calyx.constant 42.00+e00 : f32
```
}];
let arguments = (ins TypedAttrInterface:$value);

let results = (outs SignlessIntegerOrFloatLike:$result);

let builders = [
/// Build a ConstantOp from a prebuilt attribute.
OpBuilder <(ins "IntegerAttr":$attr)>,

OpBuilder <(ins "FloatAttr":$attr)>
];

let hasFolder = 1;
let assemblyFormat = "attr-dict $value";
let hasVerifier = 1;
}

/// The n-bit, undef op which only provides the out signal
def UndefLibOp: CalyxPrimitive<"undefined", []> {
let summary = "An undefined signal";
Expand Down
21 changes: 15 additions & 6 deletions lib/Conversion/SCFToCalyx/SCFToCalyx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,12 +795,21 @@ LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,

LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,
arith::ConstantOp constOp) const {
/// Move constant operations to the compOp body as hw::ConstantOp's.
APInt value;
calyx::matchConstantOp(constOp, value);
auto hwConstOp = rewriter.replaceOpWithNewOp<hw::ConstantOp>(constOp, value);
hwConstOp->moveAfter(getComponent().getBodyBlock(),
getComponent().getBodyBlock()->begin());
if (isa<IntegerType>(constOp.getType())) {
/// Move constant operations to the compOp body as hw::ConstantOp's.
APInt value;
calyx::matchConstantOp(constOp, value);
auto hwConstOp =
rewriter.replaceOpWithNewOp<hw::ConstantOp>(constOp, value);
hwConstOp->moveAfter(getComponent().getBodyBlock(),
getComponent().getBodyBlock()->begin());
} else {
auto calyxConstOp = rewriter.replaceOpWithNewOp<calyx::ConstantOp>(
constOp, constOp.getType(), constOp.getValueAttr());
calyxConstOp->moveAfter(getComponent().getBodyBlock(),
getComponent().getBodyBlock()->begin());
}

return success();
}

Expand Down
56 changes: 56 additions & 0 deletions lib/Dialect/Calyx/CalyxOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1944,6 +1944,62 @@ ParseResult GroupDoneOp::parse(OpAsmParser &parser, OperationState &result) {
return parseGroupPort(parser, result);
}

//===----------------------------------------------------------------------===//
// ConstantOp
//===----------------------------------------------------------------------===//
void ConstantOp::getAsmResultNames(
function_ref<void(Value, StringRef)> setNameFn) {
auto type = getType();
if (auto intCst = llvm::dyn_cast<IntegerAttr>(getValue())) {
auto intType = llvm::dyn_cast<IntegerType>(type);

// Sugar i1 constants with 'true' and 'false'.
if (intType && intType.getWidth() == 1)
return setNameFn(getResult(), (intCst.getInt() ? "true" : "false"));

// Otherwise, build a complex name with the value and type.
SmallString<32> specialNameBuffer;
llvm::raw_svector_ostream specialName(specialNameBuffer);
specialName << 'c' << intCst.getValue();
if (intType)
specialName << '_' << type;
setNameFn(getResult(), specialName.str());
} else {
setNameFn(getResult(), "cst");
}
}

LogicalResult ConstantOp::verify() {
auto type = getType();
// The value's type must match the return type.
if (getValue().getType() != type) {
return emitOpError() << "value type " << getValue().getType()
<< " must match return type: " << type;
}
// Integer values must be signless.
if (llvm::isa<IntegerType>(type) &&
!llvm::cast<IntegerType>(type).isSignless())
return emitOpError("integer return type must be signless");
// Any float or elements attribute are acceptable.
if (!llvm::isa<IntegerAttr, FloatAttr>(getValue())) {
return emitOpError("value must be an integer or float attribute");
}

return success();
}

OpFoldResult calyx::ConstantOp::fold(FoldAdaptor adaptor) {
return getValueAttr();
}

void calyx::ConstantOp::build(OpBuilder &builder, OperationState &state,
FloatAttr attr) {
state.addAttribute("value", attr);
SmallVector<Type> types;
types.push_back(attr.getType()); // Out
state.addTypes(types);
}

//===----------------------------------------------------------------------===//
// RegisterOp
//===----------------------------------------------------------------------===//
Expand Down
16 changes: 8 additions & 8 deletions lib/Dialect/Calyx/Transforms/CalyxLoweringUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,10 +657,10 @@ void InlineCombGroups::recurseInlineCombGroups(
// LateSSAReplacement)
if (isa<BlockArgument>(src) ||
isa<calyx::RegisterOp, calyx::MemoryOp, calyx::SeqMemoryOp,
hw::ConstantOp, mlir::arith::ConstantOp, calyx::MultPipeLibOp,
calyx::DivUPipeLibOp, calyx::DivSPipeLibOp, calyx::RemSPipeLibOp,
calyx::RemUPipeLibOp, mlir::scf::WhileOp, calyx::InstanceOp>(
src.getDefiningOp()))
calyx::ConstantOp, hw::ConstantOp, mlir::arith::ConstantOp,
calyx::MultPipeLibOp, calyx::DivUPipeLibOp, calyx::DivSPipeLibOp,
calyx::RemSPipeLibOp, calyx::RemUPipeLibOp, mlir::scf::WhileOp,
calyx::InstanceOp>(src.getDefiningOp()))
continue;

auto srcCombGroup = dyn_cast<calyx::CombGroupOp>(
Expand Down Expand Up @@ -753,11 +753,11 @@ BuildReturnRegs::partiallyLowerFuncToComp(mlir::func::FuncOp funcOp,

for (auto argType : enumerate(funcOp.getResultTypes())) {
auto convArgType = calyx::convIndexType(rewriter, argType.value());
assert(isa<IntegerType>(convArgType) && "unsupported return type");
unsigned width = convArgType.getIntOrFloatBitWidth();
assert((isa<IntegerType>(convArgType) || isa<FloatType>(convArgType)) &&
"unsupported return type");
std::string name = "ret_arg" + std::to_string(argType.index());
auto reg =
createRegister(funcOp.getLoc(), rewriter, getComponent(), width, name);
auto reg = createRegister(funcOp.getLoc(), rewriter, getComponent(),
convArgType, name);
getState().addReturnReg(reg, argType.index());

rewriter.setInsertionPointToStart(
Expand Down
24 changes: 24 additions & 0 deletions test/Conversion/SCFToCalyx/convert_simple.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,27 @@ module {
return %0, %1 : i8, i8
}
}

// -----

// Test integer and floating point constant

// CHECK: calyx.group @ret_assign_0 {
// CHECK-DAG: calyx.assign %ret_arg0_reg.in = %in0 : f32
// CHECK-DAG: calyx.assign %ret_arg0_reg.write_en = %true : i1
// CHECK-DAG: calyx.assign %ret_arg1_reg.in = %c42_i32 : i32
// CHECK-DAG: calyx.assign %ret_arg1_reg.write_en = %true : i1
// CHECK-DAG: calyx.assign %ret_arg2_reg.in = %cst : f32
// CHECK-DAG: calyx.assign %ret_arg2_reg.write_en = %true : i1
// CHECK-DAG: %0 = comb.and %ret_arg2_reg.done, %ret_arg1_reg.done, %ret_arg0_reg.done : i1
// CHECK-DAG: calyx.group_done %0 ? %true : i1
// CHECK-DAG: }

module {
func.func @main(%arg0 : f32) -> (f32, i32, f32) {
%0 = arith.constant 42 : i32
%1 = arith.constant 4.2e+1 : f32

return %arg0, %0, %1 : f32, i32, f32
}
}

0 comments on commit fc689f7

Please sign in to comment.