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"
57 DenseMap<StringAttr, func::FuncOp> dpiFuncDeclMapping;
61struct LowerDPIFuncPass :
public sim::impl::LowerDPIFuncBase<LowerDPIFuncPass> {
63 LogicalResult lowerDPI();
64 LogicalResult lowerDPIFuncOp(sim::DPIFuncOp simFunc,
66 SymbolTable &symbolTable);
67 void runOnOperation()
override;
72LogicalResult 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(
90 LLVM::LLVMPointerType::get(arg.type.getContext()));
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);
157LogicalResult 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());
174void 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.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.