17#include "mlir/IR/Builders.h"
18#include "mlir/Pass/Pass.h"
19#include "llvm/Support/MemoryBuffer.h"
20#include "llvm/Support/Path.h"
21#include "llvm/Support/Process.h"
25#define GEN_PASS_DEF_HWGENERATORCALLOUTPASS
26#include "circt/Dialect/SV/SVPasses.h.inc"
40struct HWGeneratorCalloutPass
41 :
public circt::sv::impl::HWGeneratorCalloutPassBase<
42 HWGeneratorCalloutPass> {
44 void runOnOperation()
override;
46 void processGenerator(HWModuleGeneratedOp generatedModuleOp,
47 StringRef generatorExe,
48 ArrayRef<StringRef> extraGeneratorArgs);
52void HWGeneratorCalloutPass::runOnOperation() {
53 ModuleOp root = getOperation();
54 SmallVector<StringRef> genOptions;
55 StringRef extraGeneratorArgs(genExecArgs);
56 extraGeneratorArgs.split(genOptions,
';');
58 SmallString<32> execName = llvm::sys::path::filename(genExecutable);
59 SmallString<32> execPath = llvm::sys::path::parent_path(genExecutable);
61 auto generatorExe = llvm::sys::findProgramByName(execName, {execPath});
64 generatorExe = llvm::sys::findProgramByName(execName);
67 root.emitError(
"cannot find executable '" + execName +
"' in path '" +
71 for (
auto &op :
llvm::make_early_inc_range(root.getBody()->getOperations())) {
72 if (
auto generator = dyn_cast<HWModuleGeneratedOp>(op))
73 processGenerator(generator, *generatorExe, extraGeneratorArgs);
77void HWGeneratorCalloutPass::processGenerator(
78 HWModuleGeneratedOp generatedModuleOp, StringRef generatorExe,
79 ArrayRef<StringRef> extraGeneratorArgs) {
82 dyn_cast<HWGeneratorSchemaOp>(generatedModuleOp.getGeneratorKindOp());
88 if (genSchema.getDescriptor().str() != schemaName)
91 SmallVector<std::string> generatorArgs;
93 generatorArgs.push_back(generatorExe.str());
94 for (
auto o : extraGeneratorArgs)
95 generatorArgs.push_back(o.str());
98 generatedModuleOp.getVerilogModuleNameAttr().getValue().str();
101 generatorArgs.push_back(
"--moduleName");
102 generatorArgs.push_back(moduleName);
106 for (
auto attr : genSchema.getRequiredAttrs()) {
107 auto sAttr = cast<StringAttr>(attr);
109 StringRef portName = sAttr.getValue();
110 generatorArgs.push_back(
"--" + portName.str());
112 auto v = generatedModuleOp->getAttr(portName);
113 if (
auto intV = dyn_cast<IntegerAttr>(v))
114 generatorArgs.push_back(std::to_string(intV.getValue().getZExtValue()));
115 else if (
auto strV = dyn_cast<StringAttr>(v))
116 generatorArgs.push_back(strV.getValue().str());
118 generatedModuleOp.emitError(
119 "portname attribute " + portName +
120 " value specified on the rtl.module.generated operation is not "
122 "only integer and string types supported.");
126 SmallVector<StringRef> generatorArgStrRef;
127 for (
const std::string &a : generatorArgs)
128 generatorArgStrRef.push_back(
a);
131 SmallString<32> genExecOutFileName;
132 auto errCode = llvm::sys::fs::getPotentiallyUniqueTempFileName(
133 "generatorCalloutTemp", StringRef(
""), genExecOutFileName);
137 generatedModuleOp.emitError(
"cannot generate a unique temporary file name");
140 std::optional<StringRef> redirects[] = {
141 std::nullopt, StringRef(genExecOutFileName), std::nullopt};
142 int result = llvm::sys::ExecuteAndWait(
143 generatorExe, generatorArgStrRef, std::nullopt,
148 generatedModuleOp.emitError(
"execution of '" + generatorExe +
"' failed");
152 auto bufferRead = llvm::MemoryBuffer::getFile(genExecOutFileName);
153 if (!bufferRead || !*bufferRead) {
154 generatedModuleOp.emitError(
"execution of '" + generatorExe +
155 "' did not produce any output file named '" +
156 genExecOutFileName +
"'");
161 auto fileContent = (*bufferRead)->getBuffer().split(
'\n').first.str();
162 OpBuilder builder(generatedModuleOp);
164 hw::HWModuleExternOp::create(builder, generatedModuleOp.getLoc(),
165 generatedModuleOp.getVerilogModuleNameAttr(),
166 generatedModuleOp.getPortList());
169 extMod->setAttr(
"filenames", builder.getStringAttr(fileContent));
170 generatedModuleOp.erase();
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.