Skip to content

Commit

Permalink
[Firtool] Move the remaining pass additions into lib
Browse files Browse the repository at this point in the history
  • Loading branch information
SpriteOvO committed Sep 19, 2023
1 parent 89f8246 commit 7fdad47
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 80 deletions.
52 changes: 52 additions & 0 deletions include/circt/Firtool/Firtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,28 @@ namespace firtool {
struct FirtoolOptions {
llvm::cl::OptionCategory &category;

llvm::cl::opt<std::string> outputFilename{
"o", llvm::cl::desc("Output filename, or directory for split output"),
llvm::cl::value_desc("filename"), llvm::cl::init("-"),
llvm::cl::cat(category)};

llvm::cl::opt<bool> disableAnnotationsUnknown{
"disable-annotation-unknown",
llvm::cl::desc("Ignore unknown annotations when parsing"),
llvm::cl::init(false), llvm::cl::cat(category)};

llvm::cl::opt<bool> disableAnnotationsClassless{
"disable-annotation-classless",
llvm::cl::desc("Ignore annotations without a class when parsing"),
llvm::cl::init(false), llvm::cl::cat(category)};

llvm::cl::opt<bool> lowerAnnotationsNoRefTypePorts{
"lower-annotations-no-ref-type-ports",
llvm::cl::desc(
"Create real ports instead of ref type ports when resolving "
"wiring problems inside the LowerAnnotations pass"),
llvm::cl::init(false), llvm::cl::Hidden, llvm::cl::cat(category)};

llvm::cl::opt<circt::firrtl::PreserveAggregate::PreserveMode>
preserveAggregate{
"preserve-aggregate", llvm::cl::desc("Specify input file format:"),
Expand Down Expand Up @@ -241,6 +263,22 @@ struct FirtoolOptions {
llvm::cl::location(clockGateOpts.testEnableName),
llvm::cl::init("test_en"), llvm::cl::cat(category)};

llvm::cl::opt<bool> exportModuleHierarchy{
"export-module-hierarchy",
llvm::cl::desc("Export module and instance hierarchy as JSON"),
llvm::cl::init(false), llvm::cl::cat(category)};

llvm::cl::opt<bool> stripFirDebugInfo{
"strip-fir-debug-info",
llvm::cl::desc(
"Disable source fir locator information in output Verilog"),
llvm::cl::init(true), llvm::cl::cat(category)};

llvm::cl::opt<bool> stripDebugInfo{
"strip-debug-info",
llvm::cl::desc("Disable source locator information in output Verilog"),
llvm::cl::init(false), llvm::cl::cat(category)};

bool isRandomEnabled(RandomKind kind) const {
return disableRandom != RandomKind::All && disableRandom != kind;
}
Expand All @@ -260,6 +298,9 @@ struct FirtoolOptions {
FirtoolOptions(llvm::cl::OptionCategory &category) : category(category) {}
};

LogicalResult populatePreprocessTransforms(mlir::PassManager &pm,
const FirtoolOptions &opt);

LogicalResult populateCHIRRTLToLowFIRRTL(mlir::PassManager &pm,
const FirtoolOptions &opt,
ModuleOp module,
Expand All @@ -270,6 +311,17 @@ LogicalResult populateLowFIRRTLToHW(mlir::PassManager &pm,

LogicalResult populateHWToSV(mlir::PassManager &pm, const FirtoolOptions &opt);

LogicalResult populateExportVerilog(mlir::PassManager &pm,
const FirtoolOptions &opt,
llvm::raw_ostream &os);

LogicalResult populateExportSplitVerilog(mlir::PassManager &pm,
const FirtoolOptions &opt,
llvm::StringRef directory);

LogicalResult populateFinalizeIR(mlir::PassManager &pm,
const FirtoolOptions &opt);

} // namespace firtool
} // namespace circt

Expand Down
2 changes: 2 additions & 0 deletions lib/Firtool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ add_circt_library(CIRCTFirtool

LINK_LIBS PUBLIC
CIRCTExportChiselInterface
CIRCTExportVerilog
CIRCTFIRRTLToHW
CIRCTFIRRTLTransforms
CIRCTHWTransforms
CIRCTOMTransforms
CIRCTSeqToSV
CIRCTSeqTransforms
CIRCTSVTransforms
Expand Down
78 changes: 78 additions & 0 deletions lib/Firtool/Firtool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,32 @@
#include "circt/Dialect/FIRRTL/FIRRTLOps.h"
#include "circt/Dialect/FIRRTL/Passes.h"
#include "circt/Dialect/HW/HWPasses.h"
#include "circt/Dialect/OM/OMPasses.h"
#include "circt/Dialect/SV/SVPasses.h"
#include "circt/Dialect/Seq/SeqPasses.h"
#include "circt/Support/Passes.h"
#include "circt/Transforms/Passes.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

using namespace llvm;
using namespace circt;

LogicalResult firtool::populatePreprocessTransforms(mlir::PassManager &pm,
const FirtoolOptions &opt) {
// Legalize away "open" aggregates to hw-only versions.
pm.nest<firrtl::CircuitOp>().addPass(firrtl::createLowerOpenAggsPass());

pm.nest<firrtl::CircuitOp>().addPass(firrtl::createResolvePathsPass());

pm.nest<firrtl::CircuitOp>().addPass(firrtl::createLowerFIRRTLAnnotationsPass(
opt.disableAnnotationsUnknown, opt.disableAnnotationsClassless,
opt.lowerAnnotationsNoRefTypePorts));

return success();
}

LogicalResult firtool::populateCHIRRTLToLowFIRRTL(mlir::PassManager &pm,
const FirtoolOptions &opt,
ModuleOp module,
Expand Down Expand Up @@ -243,3 +259,65 @@ LogicalResult firtool::populateHWToSV(mlir::PassManager &pm,

return success();
}

namespace detail {
LogicalResult
populatePrepareForExportVerilog(mlir::PassManager &pm,
const firtool::FirtoolOptions &opt) {

// Legalize unsupported operations within the modules.
pm.nest<hw::HWModuleOp>().addPass(sv::createHWLegalizeModulesPass());

// Tidy up the IR to improve verilog emission quality.
if (!opt.disableOptimization)
pm.nest<hw::HWModuleOp>().addPass(sv::createPrettifyVerilogPass());

if (opt.stripFirDebugInfo)
pm.addPass(circt::createStripDebugInfoWithPredPass([](mlir::Location loc) {
if (auto fileLoc = loc.dyn_cast<FileLineColLoc>())
return fileLoc.getFilename().getValue().endswith(".fir");
return false;
}));

if (opt.stripDebugInfo)
pm.addPass(circt::createStripDebugInfoWithPredPass(
[](mlir::Location loc) { return true; }));

// Emit module and testbench hierarchy JSON files.
if (opt.exportModuleHierarchy)
pm.addPass(sv::createHWExportModuleHierarchyPass(opt.outputFilename));

// Check inner symbols and inner refs.
pm.addPass(hw::createVerifyInnerRefNamespacePass());

return success();
}
} // namespace detail

LogicalResult firtool::populateExportVerilog(mlir::PassManager &pm,
const FirtoolOptions &opt,
llvm::raw_ostream &os) {
if (failed(::detail::populatePrepareForExportVerilog(pm, opt)))
return failure();

pm.addPass(createExportVerilogPass(os));
return success();
}

LogicalResult firtool::populateExportSplitVerilog(mlir::PassManager &pm,
const FirtoolOptions &opt,
llvm::StringRef directory) {
if (failed(::detail::populatePrepareForExportVerilog(pm, opt)))
return failure();

pm.addPass(createExportSplitVerilogPass(directory));
return success();
}

LogicalResult firtool::populateFinalizeIR(mlir::PassManager &pm,
const FirtoolOptions &opt) {
pm.addPass(firrtl::createFinalizeIRPass());
pm.addPass(om::createFreezePathsPass());

return success();
}
103 changes: 23 additions & 80 deletions tools/firtool/firtool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ static cl::opt<std::string> inputFilename(cl::Positional,
cl::desc("<input file>"),
cl::init("-"), cl::cat(mainCategory));

static cl::opt<std::string> outputFilename(
"o", cl::desc("Output filename, or directory for split output"),
cl::value_desc("filename"), cl::init("-"), cl::cat(mainCategory));

static cl::opt<bool>
splitInputFile("split-input-file",
cl::desc("Split the input file into pieces and process each "
Expand All @@ -107,22 +103,6 @@ static cl::opt<bool>
"expected-* lines on the corresponding line"),
cl::init(false), cl::Hidden, cl::cat(mainCategory));

static cl::opt<bool> disableAnnotationsClassless(
"disable-annotation-classless",
cl::desc("Ignore annotations without a class when parsing"),
cl::init(false), cl::cat(mainCategory));

static cl::opt<bool> disableAnnotationsUnknown(
"disable-annotation-unknown",
cl::desc("Ignore unknown annotations when parsing"), cl::init(false),
cl::cat(mainCategory));

static cl::opt<bool> lowerAnnotationsNoRefTypePorts(
"lower-annotations-no-ref-type-ports",
cl::desc("Create real ports instead of ref type ports when resolving "
"wiring problems inside the LowerAnnotations pass"),
cl::init(false), cl::Hidden, cl::cat(mainCategory));

using InfoLocHandling = firrtl::FIRParserOptions::InfoLocHandling;
static cl::opt<InfoLocHandling> infoLocHandling(
cl::desc("Location tracking:"),
Expand All @@ -136,11 +116,6 @@ static cl::opt<InfoLocHandling> infoLocHandling(
"Use @info locations when present, fallback to .fir locations")),
cl::init(InfoLocHandling::PreferInfo), cl::cat(mainCategory));

static cl::opt<bool> exportModuleHierarchy(
"export-module-hierarchy",
cl::desc("Export module and instance hierarchy as JSON"), cl::init(false),
cl::cat(mainCategory));

static cl::opt<bool>
scalarizeTopModule("scalarize-top-module",
cl::desc("Scalarize the ports of the top module"),
Expand Down Expand Up @@ -215,16 +190,6 @@ static cl::opt<bool>
cl::desc("Log executions of toplevel module passes"),
cl::init(false), cl::cat(mainCategory));

static cl::opt<bool> stripFirDebugInfo(
"strip-fir-debug-info",
cl::desc("Disable source fir locator information in output Verilog"),
cl::init(true), cl::cat(mainCategory));

static cl::opt<bool> stripDebugInfo(
"strip-debug-info",
cl::desc("Disable source locator information in output Verilog"),
cl::init(false), cl::cat(mainCategory));

static LoweringOptionsOption loweringOptions(mainCategory);

/// Check output stream before writing bytecode to it.
Expand Down Expand Up @@ -324,14 +289,8 @@ static LogicalResult processBuffer(
if (failed(applyPassManagerCLOptions(pm)))
return failure();

// Legalize away "open" aggregates to hw-only versions.
pm.nest<firrtl::CircuitOp>().addPass(firrtl::createLowerOpenAggsPass());

pm.nest<firrtl::CircuitOp>().addPass(firrtl::createResolvePathsPass());

pm.nest<firrtl::CircuitOp>().addPass(firrtl::createLowerFIRRTLAnnotationsPass(
disableAnnotationsUnknown, disableAnnotationsClassless,
lowerAnnotationsNoRefTypePorts));
if (failed(firtool::populatePreprocessTransforms(pm, firtoolOptions)))
return failure();

// If the user asked for --parse-only, stop after running LowerAnnotations.
if (outputFormat == OutputParseOnly) {
Expand Down Expand Up @@ -362,54 +321,34 @@ static LogicalResult processBuffer(
// Add passes specific to Verilog emission if we're going there.
if (outputFormat == OutputVerilog || outputFormat == OutputSplitVerilog ||
outputFormat == OutputIRVerilog) {
// Legalize unsupported operations within the modules.
pm.nest<hw::HWModuleOp>().addPass(sv::createHWLegalizeModulesPass());

// Tidy up the IR to improve verilog emission quality.
if (!firtoolOptions.disableOptimization)
pm.nest<hw::HWModuleOp>().addPass(sv::createPrettifyVerilogPass());

if (stripFirDebugInfo)
pm.addPass(
circt::createStripDebugInfoWithPredPass([](mlir::Location loc) {
if (auto fileLoc = loc.dyn_cast<FileLineColLoc>())
return fileLoc.getFilename().getValue().endswith(".fir");
return false;
}));

if (stripDebugInfo)
pm.addPass(circt::createStripDebugInfoWithPredPass(
[](mlir::Location loc) { return true; }));

// Emit module and testbench hierarchy JSON files.
if (exportModuleHierarchy)
pm.addPass(sv::createHWExportModuleHierarchyPass(outputFilename));

// Check inner symbols and inner refs.
pm.addPass(hw::createVerifyInnerRefNamespacePass());

// Emit a single file or multiple files depending on the output format.
switch (outputFormat) {
default:
llvm_unreachable("can't reach this");
case OutputVerilog:
pm.addPass(createExportVerilogPass((*outputFile)->os()));
if (failed(firtool::populateExportVerilog(pm, firtoolOptions,
(*outputFile)->os())))
return failure();
break;
case OutputSplitVerilog:
pm.addPass(createExportSplitVerilogPass(outputFilename));
if (failed(firtool::populateExportSplitVerilog(
pm, firtoolOptions, firtoolOptions.outputFilename)))
return failure();
break;
case OutputIRVerilog:
// Run the ExportVerilog pass to get its lowering, but discard the output.
pm.addPass(createExportVerilogPass(llvm::nulls()));
if (failed(firtool::populateExportVerilog(pm, firtoolOptions,
llvm::nulls())))
return failure();
break;
}

// Run final IR mutations to clean it up after ExportVerilog and before
// emitting the final MLIR.
if (!mlirOutFile.empty()) {
pm.addPass(firrtl::createFinalizeIRPass());
pm.addPass(om::createFreezePathsPass());
}
if (!mlirOutFile.empty())
if (failed(firtool::populateFinalizeIR(pm, firtoolOptions)))
return failure();
}

if (failed(pm.run(module.get())))
Expand Down Expand Up @@ -559,21 +498,25 @@ static LogicalResult executeFirtool(MLIRContext &context) {
std::optional<std::unique_ptr<llvm::ToolOutputFile>> outputFile;
if (outputFormat != OutputSplitVerilog) {
// Create an output file.
outputFile.emplace(openOutputFile(outputFilename, &errorMessage));
outputFile.emplace(
openOutputFile(firtoolOptions.outputFilename, &errorMessage));
if (!(*outputFile)) {
llvm::errs() << errorMessage << "\n";
return failure();
}
} else {
// Create an output directory.
if (outputFilename.isDefaultOption() || outputFilename == "-") {
if (firtoolOptions.outputFilename.isDefaultOption() ||
firtoolOptions.outputFilename == "-") {
llvm::errs() << "missing output directory: specify with -o=<dir>\n";
return failure();
}
auto error = llvm::sys::fs::create_directories(outputFilename);
auto error =
llvm::sys::fs::create_directories(firtoolOptions.outputFilename);
if (error) {
llvm::errs() << "cannot create output directory '" << outputFilename
<< "': " << error.message() << "\n";
llvm::errs() << "cannot create output directory '"
<< firtoolOptions.outputFilename << "': " << error.message()
<< "\n";
return failure();
}
}
Expand Down

0 comments on commit 7fdad47

Please sign in to comment.