32 #include "mlir/Dialect/Func/IR/FuncOps.h"
33 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
34 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
35 #include "mlir/Transforms/DialectConversion.h"
36 #include "llvm/Support/Debug.h"
38 #define DEBUG_TYPE "sim-lower-dpi-func"
42 #define GEN_PASS_DEF_LOWERDPIFUNC
43 #include "circt/Dialect/Sim/SimPasses.h.inc"
48 using namespace circt;
56 struct LoweringState {
57 DenseMap<StringAttr, func::FuncOp> dpiFuncDeclMapping;
61 struct LowerDPIFuncPass :
public sim::impl::LowerDPIFuncBase<LowerDPIFuncPass> {
63 LogicalResult lowerDPI();
64 LogicalResult lowerDPIFuncOp(sim::DPIFuncOp simFunc,
66 SymbolTable &symbolTable);
67 void runOnOperation()
override;
72 LogicalResult LowerDPIFuncPass::lowerDPIFuncOp(sim::DPIFuncOp simFunc,
74 SymbolTable &symbolTable) {
75 ImplicitLocOpBuilder builder(simFunc.getLoc(), simFunc);
76 auto moduleType = simFunc.getModuleType();
78 llvm::SmallVector<Type> dpiFunctionArgumentTypes;
79 for (
auto arg : moduleType.getPorts()) {
81 if (!arg.type.isInteger())
82 return simFunc->emitError()
83 <<
"non-integer type argument is unsupported now";
86 dpiFunctionArgumentTypes.push_back(arg.type);
89 dpiFunctionArgumentTypes.push_back(
93 auto funcType = builder.getFunctionType(dpiFunctionArgumentTypes, {});
98 if (
auto verilogName = simFunc.getVerilogName()) {
99 func = symbolTable.lookup<func::FuncOp>(*verilogName);
106 func = builder.create<func::FuncOp>(simFunc.getVerilogName()
107 ? *simFunc.getVerilogName()
108 : simFunc.getSymName(),
115 auto funcOp = builder.create<func::FuncOp>(
116 loweringState.nameSpace.newName(simFunc.getSymName() +
"_wrapper"),
117 moduleType.getFuncType());
120 loweringState.dpiFuncDeclMapping[simFunc.getSymNameAttr()] = funcOp;
122 builder.setInsertionPointToStart(funcOp.addEntryBlock());
123 SmallVector<Value> functionInputs;
124 SmallVector<LLVM::AllocaOp> functionOutputAllocas;
126 size_t inputIndex = 0;
127 for (
auto arg : moduleType.getPorts()) {
129 return funcOp->emitError() <<
"inout is currently not supported";
132 functionInputs.push_back(funcOp.getArgument(inputIndex));
136 auto one = builder.create<LLVM::ConstantOp>(builder.getI64IntegerAttr(1));
137 auto alloca = builder.create<LLVM::AllocaOp>(
138 builder.getType<LLVM::LLVMPointerType>(), arg.type, one);
139 functionInputs.push_back(alloca);
140 functionOutputAllocas.push_back(alloca);
144 builder.create<func::CallOp>(func, functionInputs);
146 SmallVector<Value> results;
147 for (
auto functionOutputAlloca : functionOutputAllocas)
148 results.push_back(builder.create<LLVM::LoadOp>(
149 functionOutputAlloca.getElemType(), functionOutputAlloca));
151 builder.create<func::ReturnOp>(results);
157 LogicalResult LowerDPIFuncPass::lowerDPI() {
158 LLVM_DEBUG(llvm::dbgs() <<
"Lowering sim DPI func to func.func\n");
159 auto op = getOperation();
161 state.nameSpace.add(op);
162 auto &symbolTable = getAnalysis<SymbolTable>();
163 for (
auto simFunc : llvm::make_early_inc_range(op.getOps<sim::DPIFuncOp>()))
164 if (failed(lowerDPIFuncOp(simFunc, state, symbolTable)))
167 op.walk([&](sim::DPICallOp op) {
168 auto func = state.dpiFuncDeclMapping.at(op.getCalleeAttr().getAttr());
169 op.setCallee(func.getSymNameAttr());
174 void LowerDPIFuncPass::runOnOperation() {
175 if (failed(lowerDPI()))
176 return signalPassFailure();
std::shared_ptr< calyx::CalyxLoweringState > loweringState
A namespace that is used to store existing names and generate new names in some scope within the IR.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.