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 = func::FuncOp::create(builder,
107 simFunc.getVerilogName()
108 ? *simFunc.getVerilogName()
109 : simFunc.getSymName(),
116 auto funcOp = func::FuncOp::create(
118 loweringState.nameSpace.newName(simFunc.getSymName() +
"_wrapper"),
119 moduleType.getFuncType());
122 loweringState.dpiFuncDeclMapping[simFunc.getSymNameAttr()] = funcOp;
124 builder.setInsertionPointToStart(funcOp.addEntryBlock());
125 SmallVector<Value> functionInputs;
126 SmallVector<LLVM::AllocaOp> functionOutputAllocas;
128 size_t inputIndex = 0;
129 for (
auto arg : moduleType.getPorts()) {
131 return funcOp->emitError() <<
"inout is currently not supported";
134 functionInputs.push_back(funcOp.getArgument(inputIndex));
139 LLVM::ConstantOp::create(builder, builder.getI64IntegerAttr(1));
140 auto alloca = LLVM::AllocaOp::create(
141 builder, builder.getType<LLVM::LLVMPointerType>(), arg.type, one);
142 functionInputs.push_back(alloca);
143 functionOutputAllocas.push_back(alloca);
147 func::CallOp::create(builder, func, functionInputs);
149 SmallVector<Value> results;
150 for (
auto functionOutputAlloca : functionOutputAllocas)
151 results.push_back(LLVM::LoadOp::create(
152 builder, functionOutputAlloca.getElemType(), functionOutputAlloca));
154 func::ReturnOp::create(builder, results);
160LogicalResult LowerDPIFuncPass::lowerDPI() {
161 LLVM_DEBUG(llvm::dbgs() <<
"Lowering sim DPI func to func.func\n");
162 auto op = getOperation();
164 state.nameSpace.add(op);
165 auto &symbolTable = getAnalysis<SymbolTable>();
166 for (
auto simFunc :
llvm::make_early_inc_range(op.getOps<sim::DPIFuncOp>()))
167 if (failed(lowerDPIFuncOp(simFunc, state, symbolTable)))
170 op.walk([&](sim::DPICallOp op) {
171 auto func = state.dpiFuncDeclMapping.at(op.getCalleeAttr().getAttr());
172 op.setCallee(func.getSymNameAttr());
177void LowerDPIFuncPass::runOnOperation() {
178 if (failed(lowerDPI()))
179 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.