[ExportSystemC] Add support for NewOp, DeleteOp, and DestructorOp (#3893)

This commit is contained in:
Martin Erhart 2022-10-04 22:21:50 +02:00 committed by GitHub
parent d8d7d332d0
commit b23acdac32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 133 additions and 24 deletions

View File

@ -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>">>
}
}

View File

@ -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>();
}

View File

@ -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