17 #include "mlir/IR/Builders.h"
18 #include "llvm/Support/MemoryBuffer.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/Process.h"
22 using namespace circt;
32 struct HWGeneratorCalloutPass
33 :
public sv::HWGeneratorCalloutPassBase<HWGeneratorCalloutPass> {
34 void runOnOperation()
override;
36 void processGenerator(HWModuleGeneratedOp generatedModuleOp,
37 StringRef generatorExe,
38 ArrayRef<StringRef> extraGeneratorArgs);
42 void HWGeneratorCalloutPass::runOnOperation() {
43 ModuleOp root = getOperation();
44 SmallVector<StringRef> genOptions;
45 StringRef extraGeneratorArgs(genExecArgs);
46 extraGeneratorArgs.split(genOptions,
';');
48 SmallString<32> execName = llvm::sys::path::filename(genExecutable);
49 SmallString<32> execPath = llvm::sys::path::parent_path(genExecutable);
51 auto generatorExe = llvm::sys::findProgramByName(execName, {execPath});
54 generatorExe = llvm::sys::findProgramByName(execName);
57 root.emitError(
"cannot find executable '" + execName +
"' in path '" +
61 for (
auto &op : llvm::make_early_inc_range(root.getBody()->getOperations())) {
62 if (
auto generator = dyn_cast<HWModuleGeneratedOp>(op))
63 processGenerator(generator, *generatorExe, extraGeneratorArgs);
67 void HWGeneratorCalloutPass::processGenerator(
68 HWModuleGeneratedOp generatedModuleOp, StringRef generatorExe,
69 ArrayRef<StringRef> extraGeneratorArgs) {
72 dyn_cast<HWGeneratorSchemaOp>(generatedModuleOp.getGeneratorKindOp());
78 if (genSchema.getDescriptor().str() != schemaName)
81 SmallVector<std::string> generatorArgs;
83 generatorArgs.push_back(generatorExe.str());
84 for (
auto o : extraGeneratorArgs)
85 generatorArgs.push_back(o.str());
88 generatedModuleOp.getVerilogModuleNameAttr().getValue().str();
91 generatorArgs.push_back(
"--moduleName");
92 generatorArgs.push_back(moduleName);
96 for (
auto attr : genSchema.getRequiredAttrs()) {
97 auto sAttr = attr.cast<StringAttr>();
99 StringRef portName = sAttr.getValue();
100 generatorArgs.push_back(
"--" + portName.str());
102 auto v = generatedModuleOp->getAttr(portName);
103 if (
auto intV = v.dyn_cast<IntegerAttr>())
104 generatorArgs.push_back(std::to_string(intV.getValue().getZExtValue()));
105 else if (
auto strV = v.dyn_cast<StringAttr>())
106 generatorArgs.push_back(strV.getValue().str());
108 generatedModuleOp.emitError(
109 "portname attribute " + portName +
110 " value specified on the rtl.module.generated operation is not "
112 "only integer and string types supported.");
116 SmallVector<StringRef> generatorArgStrRef;
117 for (
const std::string &a : generatorArgs)
118 generatorArgStrRef.push_back(a);
121 SmallString<32> genExecOutFileName;
122 auto errCode = llvm::sys::fs::getPotentiallyUniqueTempFileName(
123 "generatorCalloutTemp", StringRef(
""), genExecOutFileName);
127 generatedModuleOp.emitError(
"cannot generate a unique temporary file name");
130 std::optional<StringRef> redirects[] = {
131 std::nullopt, StringRef(genExecOutFileName), std::nullopt};
132 int result = llvm::sys::ExecuteAndWait(
133 generatorExe, generatorArgStrRef, std::nullopt,
138 generatedModuleOp.emitError(
"execution of '" + generatorExe +
"' failed");
142 auto bufferRead = llvm::MemoryBuffer::getFile(genExecOutFileName);
143 if (!bufferRead || !*bufferRead) {
144 generatedModuleOp.emitError(
"execution of '" + generatorExe +
145 "' did not produce any output file named '" +
146 genExecOutFileName +
"'");
151 auto fileContent = (*bufferRead)->getBuffer().split(
'\n').first.str();
152 OpBuilder
builder(generatedModuleOp);
154 generatedModuleOp.getLoc(), generatedModuleOp.getVerilogModuleNameAttr(),
155 generatedModuleOp.getPortList());
158 extMod->setAttr(
"filenames",
builder.getStringAttr(fileContent));
159 generatedModuleOp.erase();
163 return std::make_unique<HWGeneratorCalloutPass>();
std::unique_ptr< mlir::Pass > createHWGeneratorCalloutPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.