16 #include "mlir/Dialect/Func/IR/FuncOps.h"
17 #include "mlir/Pass/Pass.h"
18 #include "mlir/Transforms/DialectConversion.h"
22 #define GEN_PASS_DEF_SYSTEMCLOWERINSTANCEINTEROP
23 #include "circt/Dialect/SystemC/Passes.h.inc"
28 using namespace circt;
37 class InteropVerilatedOpConversion
43 matchAndRewrite(InteropVerilatedOp op, OpAdaptor adaptor,
44 ConversionPatternRewriter &rewriter)
const override {
49 SmallString<128> verilatedModuleName(
"V");
50 verilatedModuleName += op.getModuleName();
53 Location loc = op.getLoc();
58 SymbolTable::lookupNearestSymbolFrom(op, op.getModuleNameAttr());
59 OpBuilder includeBuilder(hwModule);
60 includeBuilder.create<emitc::IncludeOp>(
61 loc, (verilatedModuleName +
".h").str(),
false);
64 Value state = rewriter
65 .create<interop::ProceduralAllocOp>(loc, stateType,
66 InteropMechanism::CPP)
69 insertStateInitialization(rewriter, loc, state);
71 ValueRange results = insertUpdateLogic(
72 rewriter, loc, state, adaptor.getInputs(), op.getResults(),
73 adaptor.getInputNames(), adaptor.getResultNames());
75 insertStateDeallocation(rewriter, loc, state);
79 rewriter.replaceOp(op, results);
86 void insertStateInitialization(PatternRewriter &rewriter, Location loc,
88 auto initOp = rewriter.create<interop::ProceduralInitOp>(
89 loc, state, InteropMechanism::CPP);
91 OpBuilder initBuilder = OpBuilder::atBlockBegin(initOp.getBody());
93 initBuilder.create<NewOp>(loc, state.getType(), ValueRange());
94 initBuilder.create<interop::ReturnOp>(loc, newState);
100 ValueRange insertUpdateLogic(PatternRewriter &rewriter, Location loc,
101 Value stateValue, ValueRange inputValues,
102 ValueRange resultValues, ArrayAttr inputNames,
103 ArrayAttr resultNames)
const {
104 auto updateOp = rewriter.create<interop::ProceduralUpdateOp>(
105 loc, resultValues.getTypes(), inputValues, stateValue,
106 InteropMechanism::CPP);
108 OpBuilder updateBuilder = OpBuilder::atBlockBegin(updateOp.getBody());
111 Value state = updateOp.getBody()->getArguments().front();
112 for (
size_t i = 0; i < inputValues.size(); ++i) {
113 Value member = updateBuilder.create<MemberAccessOp>(
114 loc, inputValues[i].getType(), state, cast<StringAttr>(inputNames[i]),
115 MemberAccessKind::Arrow);
116 updateBuilder.create<AssignOp>(loc, member,
117 updateOp.getBody()->getArgument(i + 1));
121 auto evalFunc = updateBuilder.create<MemberAccessOp>(
123 "eval", MemberAccessKind::Arrow);
128 updateBuilder.create<func::CallIndirectOp>(loc, evalFunc.getResult());
131 SmallVector<Value> results;
132 for (
size_t i = 0; i < resultValues.size(); ++i) {
133 results.push_back(updateBuilder.create<MemberAccessOp>(
134 loc, resultValues[i].getType(), state,
135 cast<StringAttr>(resultNames[i]).getValue(),
136 MemberAccessKind::Arrow));
139 updateBuilder.create<interop::ReturnOp>(loc, results);
141 return updateOp->getResults();
145 void insertStateDeallocation(PatternRewriter &rewriter, Location loc,
147 auto deallocOp = rewriter.create<interop::ProceduralDeallocOp>(
148 loc, state, InteropMechanism::CPP);
150 OpBuilder deallocBuilder = OpBuilder::atBlockBegin(deallocOp.getBody());
151 deallocBuilder.create<DeleteOp>(loc, deallocOp.getBody()->getArgument(0));
161 struct SystemCLowerInstanceInteropPass
162 : circt::systemc::impl::SystemCLowerInstanceInteropBase<
163 SystemCLowerInstanceInteropPass> {
164 void runOnOperation()
override;
169 RewritePatternSet &
patterns, MLIRContext *ctx) {
170 patterns.add<InteropVerilatedOpConversion>(ctx);
173 void SystemCLowerInstanceInteropPass::runOnOperation() {
174 RewritePatternSet
patterns(&getContext());
176 ConversionTarget target(getContext());
177 target.addLegalDialect<interop::InteropDialect>();
178 target.addLegalDialect<emitc::EmitCDialect>();
179 target.addLegalDialect<SystemCDialect>();
180 target.addLegalOp<func::CallIndirectOp>();
181 target.addIllegalOp<InteropVerilatedOp>();
188 applyPartialConversion(getOperation(), target, std::move(
patterns))))
194 return std::make_unique<SystemCLowerInstanceInteropPass>();
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
std::unique_ptr< mlir::Pass > createSystemCLowerInstanceInteropPass()
Create the SystemC Lower Interop pass.
void populateSystemCLowerInstanceInteropPatterns(mlir::RewritePatternSet &patterns, mlir::MLIRContext *ctx)
Populate the rewrite patterns for SystemC's instance-side interop lowerings.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.