Skip to content

Commit

Permalink
support calyx constant op reflecting the new change
Browse files Browse the repository at this point in the history
  • Loading branch information
jiahanxie353 committed Oct 30, 2024
1 parent 0a86887 commit 0bee621
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 41 deletions.
12 changes: 5 additions & 7 deletions include/circt/Dialect/Calyx/CalyxPrimitives.td
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ class CalyxPrimitive<string mnemonic, list<Trait> traits = []> :
let skipDefaultBuilders = 1;
}

def ConstantOp: CalyxOp<"constant",
[Pure, ConstantLike, FirstAttrDerivedResultType,
def ConstantOp: CalyxPrimitive<"constant",
[ConstantLike, FirstAttrDerivedResultType,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
AllTypesMatch<["value", "result"]>
AllTypesMatch<["value", "out"]>
]> {
let summary = "integer or floating point constant";
let description = [{
Expand All @@ -42,13 +42,11 @@ def ConstantOp: CalyxOp<"constant",
}];
let arguments = (ins TypedAttrInterface:$value);

let results = (outs SignlessIntegerOrFloatLike:$result);
let results = (outs SignlessIntegerOrFloatLike:$out);

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

OpBuilder <(ins "FloatAttr":$attr)>
OpBuilder <(ins "StringRef":$sym_name, "TypedAttr":$attr)>,
];

let hasFolder = 1;
Expand Down
6 changes: 4 additions & 2 deletions lib/Conversion/SCFToCalyx/SCFToCalyx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -900,10 +900,12 @@ LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,
hwConstOp->moveAfter(getComponent().getBodyBlock(),
getComponent().getBodyBlock()->begin());
} else {
auto calyxConstOp = rewriter.replaceOpWithNewOp<calyx::ConstantOp>(
constOp, constOp.getType(), constOp.getValueAttr());
std::string name = getState<ComponentLoweringState>().getUniqueName("cst");
auto calyxConstOp = rewriter.create<calyx::ConstantOp>(
constOp.getLoc(), name, constOp.getValueAttr());
calyxConstOp->moveAfter(getComponent().getBodyBlock(),
getComponent().getBodyBlock()->begin());
rewriter.replaceAllUsesWith(constOp, calyxConstOp.getOut());
}

return success();
Expand Down
14 changes: 13 additions & 1 deletion lib/Dialect/Calyx/CalyxOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2002,13 +2002,25 @@ OpFoldResult calyx::ConstantOp::fold(FoldAdaptor adaptor) {
}

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

SmallVector<StringRef> ConstantOp::portNames() { return {"out"}; }

SmallVector<Direction> ConstantOp::portDirections() { return {Output}; }

SmallVector<DictionaryAttr> ConstantOp::portAttributes() {
return {DictionaryAttr::get(getContext())};
}

bool ConstantOp::isCombinational() { return true; }

//===----------------------------------------------------------------------===//
// RegisterOp
//===----------------------------------------------------------------------===//
Expand Down
47 changes: 23 additions & 24 deletions lib/Dialect/Calyx/Export/CalyxEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ struct ImportTracker {
static constexpr std::string_view sMemories = "memories/seq";
return {sMemories};
})
.Case<ConstantOp>([&](auto op) -> FailureOr<StringRef> {
static constexpr std::string_view sFloat = "float";
return {sFloat};
})
.Default([&](auto op) {
auto diag = op->emitOpError() << "not supported for emission";
return diag;
Expand Down Expand Up @@ -255,6 +259,9 @@ struct Emitter {
// Invoke emission
void emitInvoke(InvokeOp invoke);

// Floating point Constant emission
void emitConstant(ConstantOp constant);

// Emits a library primitive with template parameters based on all in- and
// output ports.
// e.g.:
Expand Down Expand Up @@ -481,19 +488,6 @@ struct Emitter {
emitValue(op.getInputs()[0], /*isIndented=*/false);
})
.Case<CycleOp>([&](auto op) { emitCycleValue(op); })
.Case<calyx::ConstantOp>([&](auto op) {
TypedAttr attr = op.getValueAttr();
if (auto fltAttr = dyn_cast<FloatAttr>(attr)) {
APFloat value = fltAttr.getValue();
auto type = cast<FloatType>(fltAttr.getType());
double floatValue = value.convertToFloat();
uint32_t bitPattern = floatToIEEE754(floatValue);
std::bitset<sizeof(float) * CHAR_BIT> bits(bitPattern);
(isIndented ? indent() : os)
<< std::to_string(value.getSizeInBits(type.getFloatSemantics()))
<< apostrophe() << "d" << bits.to_string();
}
})
.Default(
[&](auto op) { emitOpError(op, "not supported for emission"); });
}
Expand Down Expand Up @@ -609,15 +603,6 @@ struct Emitter {
/// Current level of indentation. See `indent()` and
/// `addIndent()`/`reduceIndent()`.
unsigned currentIndent = 0;

uint32_t floatToIEEE754(float f) {
union {
float input;
uint32_t output;
} data;
data.input = f;
return data.output;
}
};

} // end anonymous namespace
Expand Down Expand Up @@ -661,8 +646,8 @@ void Emitter::emitComponent(ComponentInterface op) {
.Case<RegisterOp>([&](auto op) { emitRegister(op); })
.Case<MemoryOp>([&](auto op) { emitMemory(op); })
.Case<SeqMemoryOp>([&](auto op) { emitSeqMemory(op); })
.Case<hw::ConstantOp, calyx::ConstantOp>(
[&](auto op) { /*Do nothing*/ })
.Case<hw::ConstantOp>([&](auto op) { /*Do nothing*/ })
.Case<calyx::ConstantOp>([&](auto op) { emitConstant(op); })
.Case<SliceLibOp, PadLibOp, ExtSILibOp>(
[&](auto op) { emitLibraryPrimTypedByAllPorts(op); })
.Case<LtLibOp, GtLibOp, EqLibOp, NeqLibOp, GeLibOp, LeLibOp, SltLibOp,
Expand Down Expand Up @@ -924,6 +909,20 @@ void Emitter::emitInvoke(InvokeOp invoke) {
os << RParen() << semicolonEndL();
}

void Emitter::emitConstant(ConstantOp constantOp) {
TypedAttr attr = constantOp.getValueAttr();
assert(isa<FloatAttr>(attr) && "must be a floating point constant");
auto fltAttr = cast<FloatAttr>(attr);
APFloat value = fltAttr.getValue();
auto type = cast<FloatType>(fltAttr.getType());
double doubleValue = value.convertToDouble();
auto floatBits = value.getSizeInBits(type.getFloatSemantics());
indent() << constantOp.getName().str() << space() << equals() << space()
<< "std_float_const";
os << LParen() << "0" /* IEEE754 */ << comma() << floatBits << comma()
<< std::to_string(doubleValue) << RParen() << semicolonEndL();
}

/// Calling getName() on a calyx operation will return "calyx.${opname}". This
/// function returns whatever is left after the first '.' in the string,
/// removing the 'calyx' prefix.
Expand Down
16 changes: 9 additions & 7 deletions test/Dialect/Calyx/emit.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,9 @@ module attributes {calyx.entrypoint = "main"} {

module attributes {calyx.entrypoint = "main"} {
calyx.component @main(%clk: i1 {clk}, %reset: i1 {reset}, %go: i1 {go}) -> (%out0: i32, %out1: f32, %done: i1 {done}) {
// CHECK: cst_0 = std_float_const(0, 32, 4.200000);
%c42_i32 = hw.constant 42 : i32
%cst = calyx.constant 4.200000e+00 : f32
%cst = calyx.constant {sym_name = "cst_0"} 4.200000e+00 : f32
%true = hw.constant true
%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
%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
Expand All @@ -256,12 +257,12 @@ module attributes {calyx.entrypoint = "main"} {
calyx.assign %out0 = %ret_arg0_reg.out : i32

// CHECK-LABEL: group ret_assign_0 {
// CHECK-NEXT: ret_arg0_reg.in = 32'd42;
// CHECK-NEXT: ret_arg0_reg.write_en = 1'd1;
// CHECK-NEXT: ret_arg1_reg.in = 32'd01000000100001100110011001100110;
// CHECK-NEXT: ret_arg1_reg.write_en = 1'd1;
// CHECK-NEXT: ret_assign_0[done] = (ret_arg1_reg.done & ret_arg0_reg.done) ? 1'd1;
// CHECK-NEXT: }
// CHECK-NEXT: ret_arg0_reg.in = 32'd42;
// CHECK-NEXT: ret_arg0_reg.write_en = 1'd1;
// CHECK-NEXT: ret_arg1_reg.in = cst_0.out;
// CHECK-NEXT: ret_arg1_reg.write_en = 1'd1;
// CHECK-NEXT: ret_assign_0[done] = (ret_arg1_reg.done & ret_arg0_reg.done) ? 1'd1;
// CHECK-NEXT: }
calyx.group @ret_assign_0 {
calyx.assign %ret_arg0_reg.in = %c42_i32 : i32
calyx.assign %ret_arg0_reg.write_en = %true : i1
Expand All @@ -278,3 +279,4 @@ module attributes {calyx.entrypoint = "main"} {
}
} {toplevel}
}

0 comments on commit 0bee621

Please sign in to comment.