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 8, 2023
1 parent 630dabd commit a214773
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 71 deletions.
2 changes: 1 addition & 1 deletion include/circt/Dialect/SV/SVPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ createSVExtractTestCodePass(bool disableInstanceExtraction = false,
bool disableRegisterExtraction = false,
bool disableModuleInlining = false);
std::unique_ptr<mlir::Pass>
createHWExportModuleHierarchyPass(std::optional<std::string> directory = {});
createHWExportModuleHierarchyPass();
/// Generate the code for registering passes.
#define GEN_PASS_REGISTRATION
#include "circt/Dialect/SV/SVPasses.h.inc"
Expand Down
50 changes: 50 additions & 0 deletions include/circt/Firtool/Firtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ namespace firtool {
struct FirtoolOptions {
llvm::cl::OptionCategory &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 +258,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 +293,9 @@ struct FirtoolOptions {
FirtoolOptions(llvm::cl::OptionCategory &category) : category(category) {}
};

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

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

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

LogicalResult populatePrepareForExportVerilog(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: 1 addition & 1 deletion lib/Dialect/SV/Transforms/HWExportModuleHierarchy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,6 @@ void HWExportModuleHierarchyPass::runOnOperation() {
//===----------------------------------------------------------------------===//

std::unique_ptr<mlir::Pass>
sv::createHWExportModuleHierarchyPass(std::optional<std::string> directory) {
sv::createHWExportModuleHierarchyPass() {
return std::make_unique<HWExportModuleHierarchyPass>();
}
1 change: 1 addition & 0 deletions lib/Firtool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_circt_library(CIRCTFirtool

LINK_LIBS PUBLIC
CIRCTExportChiselInterface
CIRCTExportVerilog
CIRCTFIRRTLToHW
CIRCTFIRRTLTransforms
CIRCTHWTransforms
Expand Down
70 changes: 70 additions & 0 deletions lib/Firtool/Firtool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,28 @@
#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::populateLowerAnnotations(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 +258,58 @@ LogicalResult firtool::populateHWToSV(mlir::PassManager &pm,

return success();
}

LogicalResult
firtool::populatePrepareForExportVerilog(mlir::PassManager &pm,
const 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());

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

return success();
}

LogicalResult firtool::populateExportVerilog(mlir::PassManager &pm,
const FirtoolOptions &opt,
llvm::raw_ostream &os) {
pm.addPass(createExportVerilogPass(os));

return success();
}

LogicalResult firtool::populateExportSplitVerilog(mlir::PassManager &pm,
const FirtoolOptions &opt,
llvm::StringRef directory) {
pm.addPass(createExportSplitVerilogPass(directory));

return success();
}

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

return success();
}
84 changes: 15 additions & 69 deletions tools/firtool/firtool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include "circt/Support/LoweringOptionsParser.h"
#include "circt/Support/Passes.h"
#include "circt/Support/Version.h"
#include "circt/Transforms/Passes.h"
#include "mlir/Bytecode/BytecodeReader.h"
#include "mlir/Bytecode/BytecodeWriter.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
Expand Down Expand Up @@ -106,22 +105,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 @@ -135,11 +118,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 @@ -214,16 +192,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 @@ -323,14 +291,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::populateLowerAnnotations(pm, firtoolOptions)))
return failure();

// If the user asked for --parse-only, stop after running LowerAnnotations.
if (outputFormat == OutputParseOnly) {
Expand Down Expand Up @@ -361,52 +323,36 @@ 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());
if (failed(firtool::populatePrepareForExportVerilog(pm, firtoolOptions)))
return failure();

// 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,
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());
if (failed(firtool::populateFinalizeIR(pm, firtoolOptions)))
return failure();
}

if (failed(pm.run(module.get())))
Expand Down

0 comments on commit a214773

Please sign in to comment.