14 #include "../EmissionPrinter.h"
17 using namespace circt;
30 using OpEmissionPattern::OpEmissionPattern;
32 if (isa<BlockArgument>(value) &&
33 value.getParentRegion()->getParentOfType<SCModuleOp>())
34 return Precedence::VAR;
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";
67 using OpEmissionPattern::OpEmissionPattern;
80 using OpEmissionPattern::OpEmissionPattern;
83 if (value.getDefiningOp<SignalReadOp>())
84 return Precedence::FUNCTION_CALL;
96 using OpEmissionPattern::OpEmissionPattern;
99 if (value.getDefiningOp<NewOp>())
100 return Precedence::NEW;
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);
122 using OpEmissionPattern::OpEmissionPattern;
127 p <<
"\nSC_CTOR(" << op->getParentOfType<SCModuleOp>().getModuleName()
135 using OpEmissionPattern::OpEmissionPattern;
144 p <<
"\n~" << op->getParentOfType<SCModuleOp>().getModuleName()
152 using OpEmissionPattern::OpEmissionPattern;
155 if (value.getDefiningOp<SCFuncOp>())
156 return Precedence::VAR;
161 p << value.getDefiningOp<SCFuncOp>().
getName();
167 p <<
"\nvoid " << op.getName() <<
"() ";
174 using OpEmissionPattern::OpEmissionPattern;
185 using OpEmissionPattern::OpEmissionPattern;
188 if (op.getSensitivities().empty())
191 p <<
"sensitive << ";
193 op.getSensitivities(), p,
194 [&](Value sensitive) {
195 p.getInlinable(sensitive).emitWithParensOnLowerPrecedence(
205 using OpEmissionPattern::OpEmissionPattern;
216 using OpEmissionPattern::OpEmissionPattern;
228 using OpEmissionPattern::OpEmissionPattern;
231 if (llvm::isa_and_nonnull<SignalOp>(value.getDefiningOp()))
232 return Precedence::VAR;
237 p << value.getDefiningOp<SignalOp>().
getName();
241 p.
emitType(op.getSignal().getType());
247 p <<
"SC_NAMED(" << op.getName() <<
");\n";
251 p << op.getName() <<
";\n";
257 using OpEmissionPattern::OpEmissionPattern;
260 if (value.getDefiningOp<InstanceDeclOp>())
261 return Precedence::VAR;
266 p << value.getDefiningOp<InstanceDeclOp>().
getName();
271 p <<
" " << op.getName() <<
";\n";
279 using OpEmissionPattern::OpEmissionPattern;
285 p <<
"." << op.getPortName() <<
"(";
293 using OpEmissionPattern::OpEmissionPattern;
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();
319 using OpEmissionPattern::OpEmissionPattern;
333 using OpEmissionPattern::OpEmissionPattern;
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();
369 using OpEmissionPattern::OpEmissionPattern;
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()) {
438 using OpEmissionPattern::OpEmissionPattern;
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);
476 using OpEmissionPattern::OpEmissionPattern;
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);
513 using OpEmissionPattern::OpEmissionPattern;
516 return isa<ReturnOp>(op) && cast<ReturnOp>(op)->getNumOperands() <= 1;
521 if (!op.getReturnValues().empty()) {
536 template <
typename Ty, const
char Mn[]>
549 p << type.getModuleName().getValue();
555 template <
typename Ty>
558 p <<
"sc_" << Ty::getMnemonic() <<
"<" << type.getWidth() <<
">";
564 template <
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.
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...
mlir::raw_indented_ostream & getOstream() const
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.
This is a convenience class providing default implementations for type emission patterns.