mirror of https://github.com/llvm/circt.git
[ExportSystemC] Add support for NewOp, DeleteOp, and DestructorOp (#3893)
This commit is contained in:
parent
d8d7d332d0
commit
b23acdac32
|
@ -3,6 +3,7 @@
|
|||
// RUN: clang-tidy --extra-arg=-frtti %t.cpp
|
||||
|
||||
emitc.include <"systemc.h">
|
||||
emitc.include <"tuple">
|
||||
|
||||
systemc.module @submodule (%in0: !systemc.in<!systemc.uint<32>>, %in1: !systemc.in<!systemc.uint<32>>, %out0: !systemc.out<!systemc.uint<32>>) {}
|
||||
|
||||
|
@ -79,3 +80,21 @@ systemc.module @emitcEmission () {
|
|||
%somePtr = systemc.cpp.variable %6 : !emitc.ptr<!emitc.opaque<"int">>
|
||||
}
|
||||
}
|
||||
|
||||
systemc.module @CppEmission () {
|
||||
systemc.cpp.destructor {
|
||||
%0 = systemc.cpp.new() : () -> !emitc.ptr<!emitc.opaque<"submodule">>
|
||||
systemc.cpp.delete %0 : !emitc.ptr<!emitc.opaque<"submodule">>
|
||||
|
||||
%1 = systemc.cpp.new() : () -> !emitc.ptr<!emitc.opaque<"int[5]">>
|
||||
%2 = emitc.cast %1 : !emitc.ptr<!emitc.opaque<"int[5]">> to !emitc.ptr<!emitc.opaque<"int">>
|
||||
%arr = systemc.cpp.variable %2 : !emitc.ptr<!emitc.opaque<"int">>
|
||||
systemc.cpp.delete %arr : !emitc.ptr<!emitc.opaque<"int">>
|
||||
|
||||
%3 = hw.constant 1 : i32
|
||||
%4 = hw.constant 2 : i32
|
||||
%5 = systemc.cpp.new(%3, %4) : (i32, i32) -> !emitc.ptr<!emitc.opaque<"std::tuple<uint32_t, uint32_t>">>
|
||||
%tup = systemc.cpp.variable %5 : !emitc.ptr<!emitc.opaque<"std::tuple<uint32_t, uint32_t>">>
|
||||
systemc.cpp.delete %tup : !emitc.ptr<!emitc.opaque<"std::tuple<uint32_t, uint32_t>">>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,32 @@ struct SignalReadEmitter : OpEmissionPattern<SignalReadOp> {
|
|||
}
|
||||
};
|
||||
|
||||
/// Emit a systemc.cpp.new operation.
|
||||
struct NewEmitter : OpEmissionPattern<NewOp> {
|
||||
using OpEmissionPattern::OpEmissionPattern;
|
||||
|
||||
MatchResult matchInlinable(Value value) override {
|
||||
if (value.getDefiningOp<NewOp>())
|
||||
return Precedence::NEW;
|
||||
return {};
|
||||
}
|
||||
|
||||
void emitInlined(Value value, EmissionPrinter &p) override {
|
||||
p << "new ";
|
||||
p.emitType(value.getType().cast<mlir::emitc::PointerType>().getPointee());
|
||||
|
||||
auto newOp = value.getDefiningOp<NewOp>();
|
||||
if (newOp.getArgs().empty())
|
||||
return;
|
||||
|
||||
p << "(";
|
||||
llvm::interleaveComma(newOp.getArgs(), p, [&](Value arg) {
|
||||
p.getInlinable(arg).emitWithParensOnLowerPrecedence(Precedence::COMMA);
|
||||
});
|
||||
p << ")";
|
||||
}
|
||||
};
|
||||
|
||||
/// Emit a systemc.ctor operation by using the SC_CTOR macro.
|
||||
struct CtorEmitter : OpEmissionPattern<CtorOp> {
|
||||
using OpEmissionPattern::OpEmissionPattern;
|
||||
|
@ -104,6 +130,23 @@ struct CtorEmitter : OpEmissionPattern<CtorOp> {
|
|||
}
|
||||
};
|
||||
|
||||
/// Emit a systemc.cpp.destructor operation.
|
||||
struct DestructorEmitter : OpEmissionPattern<DestructorOp> {
|
||||
using OpEmissionPattern::OpEmissionPattern;
|
||||
|
||||
void emitStatement(DestructorOp op, EmissionPrinter &p) override {
|
||||
// Emit a new line before the destructor to ensure an empty line for better
|
||||
// readability.
|
||||
// TODO: the 'override' keyword is hardcoded here because the destructor can
|
||||
// only be inside a class inheriting from 'sc_module', if we ever support
|
||||
// custom classes the override should probably be a unitAttr on the
|
||||
// destructor operation.
|
||||
p << "\n~" << op->getParentOfType<SCModuleOp>().getModuleName()
|
||||
<< "() override ";
|
||||
p.emitRegion(op.getBody());
|
||||
}
|
||||
};
|
||||
|
||||
/// Emit a systemc.func operation.
|
||||
struct SCFuncEmitter : OpEmissionPattern<SCFuncOp> {
|
||||
using OpEmissionPattern::OpEmissionPattern;
|
||||
|
@ -148,6 +191,18 @@ struct ThreadEmitter : OpEmissionPattern<ThreadOp> {
|
|||
}
|
||||
};
|
||||
|
||||
/// Emit a systemc.cpp.delete operation.
|
||||
struct DeleteEmitter : OpEmissionPattern<DeleteOp> {
|
||||
using OpEmissionPattern::OpEmissionPattern;
|
||||
|
||||
void emitStatement(DeleteOp op, EmissionPrinter &p) override {
|
||||
p << "delete ";
|
||||
p.getInlinable(op.getPointer())
|
||||
.emitWithParensOnLowerPrecedence(Precedence::DELETE);
|
||||
p << ";\n";
|
||||
}
|
||||
};
|
||||
|
||||
/// Emit a systemc.signal operation.
|
||||
struct SignalEmitter : OpEmissionPattern<SignalOp> {
|
||||
using OpEmissionPattern::OpEmissionPattern;
|
||||
|
@ -295,10 +350,15 @@ struct DynIntegerTypeEmitter : public TypeEmissionPattern<Ty> {
|
|||
|
||||
void circt::ExportSystemC::populateSystemCOpEmitters(
|
||||
OpEmissionPatternSet &patterns, MLIRContext *context) {
|
||||
patterns.add<SCModuleEmitter, SignalWriteEmitter, SignalReadEmitter,
|
||||
CtorEmitter, SCFuncEmitter, MethodEmitter, ThreadEmitter,
|
||||
SignalEmitter, InstanceDeclEmitter, BindPortEmitter,
|
||||
AssignEmitter, VariableEmitter>(context);
|
||||
patterns.add<SCModuleEmitter, CtorEmitter, SCFuncEmitter, MethodEmitter,
|
||||
ThreadEmitter,
|
||||
// Signal and port related emitters
|
||||
SignalWriteEmitter, SignalReadEmitter, SignalEmitter,
|
||||
// Instance-related emitters
|
||||
InstanceDeclEmitter, BindPortEmitter,
|
||||
// CPP-level operation emitters
|
||||
AssignEmitter, VariableEmitter, NewEmitter, DestructorEmitter,
|
||||
DeleteEmitter>(context);
|
||||
}
|
||||
|
||||
void circt::ExportSystemC::populateSystemCTypeEmitters(
|
||||
|
@ -308,24 +368,21 @@ void circt::ExportSystemC::populateSystemCTypeEmitters(
|
|||
static constexpr const char out[] = "sc_out";
|
||||
static constexpr const char signal[] = "sc_signal";
|
||||
|
||||
// clang-format off
|
||||
patterns.add<SignalTypeEmitter<InputType, in>,
|
||||
SignalTypeEmitter<InOutType, inout>,
|
||||
SignalTypeEmitter<OutputType, out>,
|
||||
SignalTypeEmitter<SignalType, signal>,
|
||||
IntegerTypeEmitter<IntType>,
|
||||
IntegerTypeEmitter<UIntType>,
|
||||
IntegerTypeEmitter<BigIntType>,
|
||||
IntegerTypeEmitter<BigUIntType>,
|
||||
IntegerTypeEmitter<BitVectorType>,
|
||||
IntegerTypeEmitter<LogicVectorType>,
|
||||
DynIntegerTypeEmitter<IntBaseType>,
|
||||
DynIntegerTypeEmitter<UIntBaseType>,
|
||||
DynIntegerTypeEmitter<SignedType>,
|
||||
DynIntegerTypeEmitter<UnsignedType>,
|
||||
DynIntegerTypeEmitter<BitVectorBaseType>,
|
||||
DynIntegerTypeEmitter<LogicVectorBaseType>,
|
||||
DynIntegerTypeEmitter<LogicType>,
|
||||
ModuleTypeEmitter>();
|
||||
// clang-format on
|
||||
patterns.add<
|
||||
// Port and signal types
|
||||
SignalTypeEmitter<InputType, in>, SignalTypeEmitter<InOutType, inout>,
|
||||
SignalTypeEmitter<OutputType, out>, SignalTypeEmitter<SignalType, signal>,
|
||||
// SystemC integers with statically known bit-width
|
||||
IntegerTypeEmitter<IntType>, IntegerTypeEmitter<UIntType>,
|
||||
IntegerTypeEmitter<BigIntType>, IntegerTypeEmitter<BigUIntType>,
|
||||
// SystemC integers without statically known bit-width
|
||||
DynIntegerTypeEmitter<IntBaseType>, DynIntegerTypeEmitter<UIntBaseType>,
|
||||
DynIntegerTypeEmitter<SignedType>, DynIntegerTypeEmitter<UnsignedType>,
|
||||
// Vector types with statically known bit-width
|
||||
IntegerTypeEmitter<BitVectorType>, IntegerTypeEmitter<LogicVectorType>,
|
||||
// Vector types without statically known bit-width
|
||||
DynIntegerTypeEmitter<BitVectorBaseType>,
|
||||
DynIntegerTypeEmitter<LogicVectorBaseType>,
|
||||
// Misc types
|
||||
DynIntegerTypeEmitter<LogicType>, ModuleTypeEmitter>();
|
||||
}
|
||||
|
|
|
@ -199,4 +199,37 @@ systemc.module @emitcEmission () {
|
|||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: SC_MODULE(CppEmission)
|
||||
systemc.module @CppEmission () {
|
||||
// CHECK-EMPTY:
|
||||
|
||||
// Test: systemc.cpp.destructor
|
||||
// CHECK-NEXT: ~CppEmission() override {
|
||||
systemc.cpp.destructor {
|
||||
// Test: systemc.cpp.new w/o arguments
|
||||
// CHECK-NEXT: submodule* v0 = new submodule;
|
||||
%0 = systemc.cpp.new() : () -> !emitc.ptr<!emitc.opaque<"submodule">>
|
||||
%v0 = systemc.cpp.variable %0 : !emitc.ptr<!emitc.opaque<"submodule">>
|
||||
|
||||
// Test: systemc.cpp.new with arguments, w/o parens due to precedence
|
||||
// CHECK-NEXT: std::tuple<uint32_t, uint32_t>* v1 = new std::tuple<uint32_t, uint32_t>(1, 2);
|
||||
%3 = hw.constant 1 : i32
|
||||
%4 = hw.constant 2 : i32
|
||||
%5 = systemc.cpp.new(%3, %4) : (i32, i32) -> !emitc.ptr<!emitc.opaque<"std::tuple<uint32_t, uint32_t>">>
|
||||
%v1 = systemc.cpp.variable %5 : !emitc.ptr<!emitc.opaque<"std::tuple<uint32_t, uint32_t>">>
|
||||
|
||||
// Test: systemc.cpp.new w arguments, with parens due to precedence
|
||||
// TODO: there is currently no appropriate inlinable operation implemented with lower precedence
|
||||
|
||||
// Test: systemc.cpp.delete w/o parens due to precedence
|
||||
// CHECK-NEXT: delete v0;
|
||||
systemc.cpp.delete %v0 : !emitc.ptr<!emitc.opaque<"submodule">>
|
||||
|
||||
// Test: systemc.cpp.delete with parens due to precedence
|
||||
// TODO: there is currently no appropriate inlinable operation implemented with lower precedence
|
||||
|
||||
// CHECK-NEXT: }
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: #endif // STDOUT_H
|
||||
|
|
Loading…
Reference in New Issue