14#include "../EmissionPrinter.h"
32 if (isa<BlockArgument>(value) &&
33 value.getParentRegion()->getParentOfType<SCModuleOp>())
39 auto module = value.getParentRegion()->getParentOfType<SCModuleOp>();
40 for (
size_t i = 0, e = module.getNumArguments(); i < e; ++i) {
41 if (module.getArgument(i) == value) {
42 p << cast<StringAttr>(module.getPortNames()[i]).getValue();
51 p <<
"\nSC_MODULE(" <<
module.getModuleName() << ") ";
52 auto scope = p.
getOstream().scope(
"{\n",
"};\n");
53 for (
size_t i = 0, e = module.getNumArguments(); i < e; ++i) {
54 p.
emitType(module.getArgument(i).getType());
56 auto portName = cast<StringAttr>(module.getPortNames()[i]).getValue();
57 p <<
" " << portName <<
";\n";
83 if (value.getDefiningOp<SignalReadOp>())
99 if (value.getDefiningOp<NewOp>())
106 p.
emitType(cast<mlir::emitc::PointerType>(value.getType()).getPointee());
108 auto newOp = value.getDefiningOp<NewOp>();
109 if (newOp.getArgs().empty())
113 llvm::interleaveComma(newOp.getArgs(), p, [&](Value arg) {
114 p.getInlinable(arg).emitWithParensOnLowerPrecedence(Precedence::COMMA);
127 p <<
"\nSC_CTOR(" << op->getParentOfType<SCModuleOp>().getModuleName()
144 p <<
"\n~" << op->getParentOfType<SCModuleOp>().getModuleName()
155 if (value.getDefiningOp<SCFuncOp>())
161 p << value.getDefiningOp<SCFuncOp>().
getName();
167 p <<
"\nvoid " << op.getName() <<
"() ";
188 if (op.getSensitivities().empty())
191 p <<
"sensitive << ";
193 op.getSensitivities(), p,
194 [&](Value sensitive) {
195 p.getInlinable(sensitive).emitWithParensOnLowerPrecedence(
231 if (llvm::isa_and_nonnull<SignalOp>(value.getDefiningOp()))
237 p << value.getDefiningOp<SignalOp>().
getName();
241 p.
emitType(op.getSignal().getType());
247 p <<
"SC_NAMED(" << op.getName() <<
");\n";
251 p << op.getName() <<
";\n";
260 if (value.getDefiningOp<InstanceDeclOp>())
266 p << value.getDefiningOp<InstanceDeclOp>().
getName();
271 p <<
" " << op.getName() <<
";\n";
285 p <<
"." << op.getPortName() <<
"(";
296 if (value.getDefiningOp<MemberAccessOp>())
297 return Precedence::MEMBER_ACCESS;
302 auto op = value.getDefiningOp<MemberAccessOp>();
304 .emitWithParensOnLowerPrecedence(Precedence::MEMBER_ACCESS);
306 if (op.getAccessKind() == MemberAccessKind::Arrow)
308 else if (op.getAccessKind() == MemberAccessKind::Dot)
311 p.
emitError(op,
"member access kind not implemented");
313 p << op.getMemberName();
336 if (value.getDefiningOp<VariableOp>())
337 return Precedence::VAR;
342 p << value.getDefiningOp<VariableOp>().getName();
346 p.
emitType(op.getVariable().getType());
347 p <<
" " << op.getName();
373 if (isa<BlockArgument>(value) &&
374 value.getParentRegion()->getParentOfType<FuncOp>())
375 return Precedence::VAR;
381 auto func = value.getParentRegion()->getParentOfType<FuncOp>();
382 for (
auto [arg, name] :
383 llvm::zip(func.getArguments(), func.getArgNames())) {
385 p << cast<StringAttr>(name).getValue();
396 if (func.getExternC())
397 p <<
"extern \"C\" ";
400 if (func.getFunctionType().getNumResults() == 0)
403 p.
emitType(func.getFunctionType().getResult(0));
405 p <<
" " << func.getSymName() <<
"(";
409 if (func.isDeclaration() && func.getArgNames().empty())
410 llvm::interleaveComma(func.getFunctionType().getInputs(), p,
411 [&](Type ty) { p.emitType(ty); });
413 llvm::interleaveComma(
414 llvm::zip(func.getFunctionType().getInputs(), func.getArgNames()), p,
415 [&](std::tuple<Type, Attribute> arg) {
416 p.emitType(std::get<0>(arg));
417 p <<
" " << cast<StringAttr>(std::get<1>(arg)).getValue();
423 if (func.isDeclaration()) {
441 if (value.getDefiningOp<CallOp>())
442 return Precedence::FUNCTION_CALL;
447 printCall(value.getDefiningOp<CallOp>(), p);
453 if (op.getNumResults() > 0)
462 p << op.getCallee() <<
"(";
463 llvm::interleaveComma(op.getOperands(), p, [&](
auto arg) {
464 p.getInlinable(arg).emitWithParensOnLowerPrecedence(Precedence::COMMA);
479 if (value.getDefiningOp<CallIndirectOp>())
480 return Precedence::FUNCTION_CALL;
486 printCall(value.getDefiningOp<CallIndirectOp>(), p);
492 if (op.getNumResults() > 0)
504 llvm::interleaveComma(op.getCalleeOperands(), p, [&](
auto arg) {
505 p.getInlinable(arg).emitWithParensOnLowerPrecedence(Precedence::COMMA);
516 return isa<ReturnOp>(op) && cast<ReturnOp>(op)->getNumOperands() <= 1;
521 if (!op.getReturnValues().empty()) {
536template <
typename Ty, const
char Mn[]>
549 p << type.getModuleName().getValue();
555template <
typename Ty>
558 p <<
"sc_" << Ty::getMnemonic() <<
"<" << type.getWidth() <<
">";
564template <
typename Ty>
567 p <<
"sc_" << Ty::getMnemonic();
579 SCModuleEmitter, CtorEmitter, SCFuncEmitter, MethodEmitter, ThreadEmitter,
581 SignalWriteEmitter, SignalReadEmitter, SignalEmitter, SensitiveEmitter,
593 static constexpr const char in[] =
"sc_in";
594 static constexpr const char inout[] =
"sc_inout";
595 static constexpr const char out[] =
"sc_out";
596 static constexpr const char signal[] =
"sc_signal";
600 SignalTypeEmitter<InputType, in>, SignalTypeEmitter<InOutType, inout>,
601 SignalTypeEmitter<OutputType, out>, SignalTypeEmitter<SignalType, signal>,
603 IntegerTypeEmitter<IntType>, IntegerTypeEmitter<UIntType>,
604 IntegerTypeEmitter<BigIntType>, IntegerTypeEmitter<BigUIntType>,
606 DynIntegerTypeEmitter<IntBaseType>, DynIntegerTypeEmitter<UIntBaseType>,
607 DynIntegerTypeEmitter<SignedType>, DynIntegerTypeEmitter<UnsignedType>,
609 IntegerTypeEmitter<BitVectorType>, IntegerTypeEmitter<LogicVectorType>,
611 DynIntegerTypeEmitter<BitVectorBaseType>,
612 DynIntegerTypeEmitter<LogicVectorBaseType>,
614 DynIntegerTypeEmitter<LogicType>, ModuleTypeEmitter>();
Emit a systemc.cpp.call operation.
void printCall(CallOp op, EmissionPrinter &p)
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
void emitInlined(Value value, EmissionPrinter &p) override
void emitStatement(CallOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
Emit a systemc.cpp.call_indirect operation.
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
void printCall(CallIndirectOp op, EmissionPrinter &p)
void emitInlined(Value value, EmissionPrinter &p) override
void emitStatement(CallIndirectOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
This class collects a set of emission patterns with base type 'PatternTy'.
This is intended to be the driving class for all pattern-based IR emission.
void emitRegion(Region ®ion)
Emit the given region to the ostream associated with this printer.
mlir::raw_indented_ostream & getOstream() const
InlineEmitter getInlinable(Value value)
Emit the expression represented by the given value to the ostream associated with this printer accord...
void emitType(Type type)
Emit the given type to the ostream associated with this printer according to the emission patterns re...
InFlightDiagnostic emitError(Operation *op, const Twine &message)
Emit an error on the operation and fail emission.
void emitWithParensOnLowerPrecedence(Precedence prec, StringRef lParen="(", StringRef rParen=")") const
This class allows a pattern's match function for inlining to pass its result's precedence to the patt...
void populateSystemCOpEmitters(OpEmissionPatternSet &patterns, MLIRContext *context)
Register SystemC operation emission patterns.
void populateSystemCTypeEmitters(TypeEmissionPatternSet &patterns)
Register SystemC type emission patterns.
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Emit a systemc.cpp.assign operation.
void emitStatement(AssignOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
Emit a systemc.instance.bind_port operation using the operator() rather than .bind() variant.
void emitStatement(BindPortOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
Emit a systemc.cpp.func function.
void emitInlined(Value value, EmissionPrinter &p) override
void emitStatement(FuncOp func, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
Emit a systemc.cpp.member_access operation.
void emitInlined(Value value, EmissionPrinter &p) override
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
Emit a systemc.cpp.return operation.
void emitStatement(ReturnOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
bool matchStatement(Operation *op) override
Emit a systemc.cpp.variable operation.
void emitStatement(VariableOp op, EmissionPrinter &p) override
Emit zero (default) or more statements for the given operation.
void emitInlined(Value value, EmissionPrinter &p) override
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
This is a convenience class providing default implementations for operation emission patterns.
OpEmissionPattern(MLIRContext *context)
void emitInlined(mlir::Value value, EmissionPrinter &p) override
Emit the expression for the given value.
void emitStatement(mlir::Operation *op, EmissionPrinter &p) final
Emit zero or more statements for the given operation.
MatchResult matchInlinable(Value value) override
Checks if this pattern is applicable to the given value to emit an inlinable expression.
This is a convenience class providing default implementations for type emission patterns.
void emitType(Type type, EmissionPrinter &p) final
Emit the given type to the emission printer.