Skip to content

Commit 3e2e27c

Browse files
committed
Move circt-verilog pipeline into ImportVerilog.
Break out the circt-verilog import pipeline so it can reused easily.
1 parent 4d81b97 commit 3e2e27c

File tree

4 files changed

+142
-107
lines changed

4 files changed

+142
-107
lines changed

include/circt/Conversion/ImportVerilog.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#define CIRCT_CONVERSION_IMPORTVERILOG_H
1515

1616
#include "circt/Support/LLVM.h"
17+
#include "mlir/Pass/PassOptions.h"
18+
#include "llvm/Support/CommandLine.h"
1719
#include <cstdint>
1820
#include <optional>
1921
#include <string>
@@ -25,6 +27,7 @@ class SourceMgr;
2527

2628
namespace mlir {
2729
class LocationAttr;
30+
class PassManager;
2831
class TimingScope;
2932
} // namespace mlir
3033

@@ -150,6 +153,23 @@ importVerilog(llvm::SourceMgr &sourceMgr, mlir::MLIRContext *context,
150153
mlir::TimingScope &ts, mlir::ModuleOp module,
151154
const ImportVerilogOptions *options = nullptr);
152155

156+
/// Optimize and simplify the Moore dialect IR.
157+
void populateVerilogToMoorePipeline(mlir::PassManager &pm);
158+
159+
/// Convert Moore dialect IR into core dialect IR
160+
void mooreToCorePipeline(mlir::PassManager &pm);
161+
162+
/// Convert LLHD dialect IR into core dialect IR
163+
struct LlhdToCorePipelineOptions
164+
: mlir::PassPipelineOptions<LlhdToCorePipelineOptions> {
165+
Option<bool> detectMemories{
166+
*this, "detect-memories",
167+
llvm::cl::desc("Detect memories and lower them to `seq.firmem`"),
168+
llvm::cl::init(true)};
169+
};
170+
void llhdToCorePipeline(mlir::PassManager &pm,
171+
const LlhdToCorePipelineOptions &options);
172+
153173
/// Run the files in a source manager through Slang's Verilog preprocessor and
154174
/// emit the result to the given output stream.
155175
mlir::LogicalResult

lib/Conversion/ImportVerilog/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,19 @@ add_circt_translation_library(CIRCTImportVerilog
1515
slang_slang
1616

1717
LINK_LIBS PUBLIC
18+
CIRCTComb
1819
CIRCTDebug
1920
CIRCTHW
21+
CIRCTLLHD
22+
CIRCTLLHDTransforms
2023
CIRCTLTL
2124
CIRCTMoore
25+
CIRCTMooreToCore
26+
CIRCTMooreTransforms
27+
CIRCTSeq
28+
CIRCTSeqTransforms
29+
CIRCTSupport
30+
CIRCTTransforms
2231
CIRCTVerif
2332
MLIRFuncDialect
2433
MLIRSCFDialect

lib/Conversion/ImportVerilog/ImportVerilog.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,18 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "ImportVerilogInternals.h"
14+
#include "circt/Conversion/MooreToCore.h"
15+
#include "circt/Dialect/LLHD/Transforms/LLHDPasses.h"
16+
#include "circt/Dialect/Moore/MoorePasses.h"
17+
#include "circt/Dialect/Seq/SeqPasses.h"
18+
#include "circt/Transforms/Passes.h"
19+
#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
1420
#include "mlir/IR/Diagnostics.h"
1521
#include "mlir/IR/Verifier.h"
22+
#include "mlir/Pass/PassManager.h"
1623
#include "mlir/Support/Timing.h"
1724
#include "mlir/Tools/mlir-translate/Translation.h"
25+
#include "mlir/Transforms/Passes.h"
1826
#include "llvm/ADT/Hashing.h"
1927
#include "llvm/Support/SourceMgr.h"
2028

@@ -390,3 +398,103 @@ void circt::registerFromVerilogTranslation() {
390398
return module;
391399
});
392400
}
401+
402+
//===----------------------------------------------------------------------===//
403+
// Pass Pipeline
404+
//===----------------------------------------------------------------------===//
405+
406+
/// Optimize and simplify the Moore dialect IR.
407+
void circt::populateVerilogToMoorePipeline(PassManager &pm) {
408+
{
409+
// Perform an initial cleanup and preprocessing across all
410+
// modules/functions.
411+
auto &anyPM = pm.nestAny();
412+
anyPM.addPass(mlir::createCSEPass());
413+
anyPM.addPass(mlir::createCanonicalizerPass());
414+
}
415+
416+
// Remove unused symbols.
417+
pm.addPass(mlir::createSymbolDCEPass());
418+
419+
{
420+
// Perform module-specific transformations.
421+
auto &modulePM = pm.nest<moore::SVModuleOp>();
422+
modulePM.addPass(moore::createLowerConcatRefPass());
423+
// TODO: Enable the following once it not longer interferes with @(...)
424+
// event control checks. The introduced dummy variables make the event
425+
// control observe a static local variable that never changes, instead of
426+
// observing a module-wide signal.
427+
// modulePM.addPass(moore::createSimplifyProceduresPass());
428+
modulePM.addPass(mlir::createSROA());
429+
}
430+
431+
{
432+
// Perform a final cleanup across all modules/functions.
433+
auto &anyPM = pm.nestAny();
434+
anyPM.addPass(mlir::createMem2Reg());
435+
anyPM.addPass(mlir::createCSEPass());
436+
anyPM.addPass(mlir::createCanonicalizerPass());
437+
}
438+
}
439+
440+
/// Convert Moore dialect IR into core dialect IR
441+
void circt::mooreToCorePipeline(PassManager &pm) {
442+
// Perform the conversion.
443+
pm.addPass(createConvertMooreToCorePass());
444+
445+
{
446+
// Conversion to the core dialects likely uncovers new canonicalization
447+
// opportunities.
448+
auto &anyPM = pm.nestAny();
449+
anyPM.addPass(mlir::createCSEPass());
450+
anyPM.addPass(mlir::createCanonicalizerPass());
451+
}
452+
}
453+
454+
/// Convert LLHD dialect IR into core dialect IR
455+
void circt::llhdToCorePipeline(PassManager &pm,
456+
const LlhdToCorePipelineOptions &options) {
457+
// Inline function calls and lower SCF to CF.
458+
pm.addNestedPass<hw::HWModuleOp>(llhd::createWrapProceduralOpsPass());
459+
pm.addPass(mlir::createSCFToControlFlowPass());
460+
pm.addPass(llhd::createInlineCallsPass());
461+
pm.addPass(mlir::createSymbolDCEPass());
462+
463+
// Simplify processes, replace signals with process results, and detect
464+
// registers.
465+
auto &modulePM = pm.nest<hw::HWModuleOp>();
466+
// See https://github.com/llvm/circt/issues/8804.
467+
// modulePM.addPass(mlir::createSROA());
468+
modulePM.addPass(llhd::createMem2RegPass());
469+
modulePM.addPass(llhd::createHoistSignalsPass());
470+
modulePM.addPass(llhd::createDeseqPass());
471+
modulePM.addPass(llhd::createLowerProcessesPass());
472+
modulePM.addPass(mlir::createCSEPass());
473+
modulePM.addPass(mlir::createCanonicalizerPass());
474+
475+
// Unroll loops and remove control flow.
476+
modulePM.addPass(llhd::createUnrollLoopsPass());
477+
modulePM.addPass(mlir::createCSEPass());
478+
modulePM.addPass(mlir::createCanonicalizerPass());
479+
modulePM.addPass(llhd::createRemoveControlFlowPass());
480+
modulePM.addPass(mlir::createCSEPass());
481+
modulePM.addPass(mlir::createCanonicalizerPass());
482+
483+
// Convert `arith.select` generated by some of the control flow canonicalizers
484+
// to `comb.mux`.
485+
modulePM.addPass(createMapArithToCombPass());
486+
487+
// Simplify module-level signals.
488+
modulePM.addPass(llhd::createCombineDrivesPass());
489+
modulePM.addPass(llhd::createSig2Reg());
490+
modulePM.addPass(mlir::createCSEPass());
491+
modulePM.addPass(mlir::createCanonicalizerPass());
492+
493+
// Map `seq.firreg` with array type and `hw.array_inject` self-feedback to
494+
// `seq.firmem` ops.
495+
if (options.detectMemories) {
496+
modulePM.addPass(seq::createRegOfVecToMem());
497+
modulePM.addPass(mlir::createCSEPass());
498+
modulePM.addPass(mlir::createCanonicalizerPass());
499+
}
500+
}

tools/circt-verilog/circt-verilog.cpp

Lines changed: 5 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "circt/Conversion/ImportVerilog.h"
16-
#include "circt/Conversion/MooreToCore.h"
1716
#include "circt/Dialect/Comb/CombDialect.h"
1817
#include "circt/Dialect/Debug/DebugDialect.h"
1918
#include "circt/Dialect/HW/HWDialect.h"
@@ -23,12 +22,9 @@
2322
#include "circt/Dialect/Moore/MooreDialect.h"
2423
#include "circt/Dialect/Moore/MoorePasses.h"
2524
#include "circt/Dialect/Seq/SeqDialect.h"
26-
#include "circt/Dialect/Seq/SeqPasses.h"
2725
#include "circt/Dialect/Verif/VerifDialect.h"
2826
#include "circt/Support/Passes.h"
2927
#include "circt/Support/Version.h"
30-
#include "circt/Transforms/Passes.h"
31-
#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
3228
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
3329
#include "mlir/Dialect/Func/Extensions/InlinerExtension.h"
3430
#include "mlir/Dialect/Func/IR/FuncOps.h"
@@ -40,7 +36,6 @@
4036
#include "mlir/Parser/Parser.h"
4137
#include "mlir/Pass/PassManager.h"
4238
#include "mlir/Support/FileUtilities.h"
43-
#include "mlir/Transforms/Passes.h"
4439
#include "llvm/Support/CommandLine.h"
4540
#include "llvm/Support/InitLLVM.h"
4641
#include "llvm/Support/SourceMgr.h"
@@ -281,115 +276,18 @@ struct CLOptions {
281276

282277
static CLOptions opts;
283278

284-
//===----------------------------------------------------------------------===//
285-
// Pass Pipeline
286-
//===----------------------------------------------------------------------===//
287-
288-
/// Optimize and simplify the Moore dialect IR.
289-
static void populateMooreTransforms(PassManager &pm) {
290-
{
291-
// Perform an initial cleanup and preprocessing across all
292-
// modules/functions.
293-
auto &anyPM = pm.nestAny();
294-
anyPM.addPass(mlir::createCSEPass());
295-
anyPM.addPass(mlir::createCanonicalizerPass());
296-
}
297-
298-
// Remove unused symbols.
299-
pm.addPass(mlir::createSymbolDCEPass());
300-
301-
{
302-
// Perform module-specific transformations.
303-
auto &modulePM = pm.nest<moore::SVModuleOp>();
304-
modulePM.addPass(moore::createLowerConcatRefPass());
305-
// TODO: Enable the following once it not longer interferes with @(...)
306-
// event control checks. The introduced dummy variables make the event
307-
// control observe a static local variable that never changes, instead of
308-
// observing a module-wide signal.
309-
// modulePM.addPass(moore::createSimplifyProceduresPass());
310-
modulePM.addPass(mlir::createSROA());
311-
}
312-
313-
{
314-
// Perform a final cleanup across all modules/functions.
315-
auto &anyPM = pm.nestAny();
316-
anyPM.addPass(mlir::createMem2Reg());
317-
anyPM.addPass(mlir::createCSEPass());
318-
anyPM.addPass(mlir::createCanonicalizerPass());
319-
}
320-
}
321-
322-
/// Convert Moore dialect IR into core dialect IR
323-
static void populateMooreToCoreLowering(PassManager &pm) {
324-
// Perform the conversion.
325-
pm.addPass(createConvertMooreToCorePass());
326-
327-
{
328-
// Conversion to the core dialects likely uncovers new canonicalization
329-
// opportunities.
330-
auto &anyPM = pm.nestAny();
331-
anyPM.addPass(mlir::createCSEPass());
332-
anyPM.addPass(mlir::createCanonicalizerPass());
333-
}
334-
}
335-
336-
/// Convert LLHD dialect IR into core dialect IR
337-
static void populateLLHDLowering(PassManager &pm) {
338-
// Inline function calls and lower SCF to CF.
339-
pm.addNestedPass<hw::HWModuleOp>(llhd::createWrapProceduralOpsPass());
340-
pm.addPass(mlir::createSCFToControlFlowPass());
341-
pm.addPass(llhd::createInlineCallsPass());
342-
pm.addPass(mlir::createSymbolDCEPass());
343-
344-
// Simplify processes, replace signals with process results, and detect
345-
// registers.
346-
auto &modulePM = pm.nest<hw::HWModuleOp>();
347-
// See https://github.com/llvm/circt/issues/8804.
348-
// modulePM.addPass(mlir::createSROA());
349-
modulePM.addPass(llhd::createMem2RegPass());
350-
modulePM.addPass(llhd::createHoistSignalsPass());
351-
modulePM.addPass(llhd::createDeseqPass());
352-
modulePM.addPass(llhd::createLowerProcessesPass());
353-
modulePM.addPass(mlir::createCSEPass());
354-
modulePM.addPass(mlir::createCanonicalizerPass());
355-
356-
// Unroll loops and remove control flow.
357-
modulePM.addPass(llhd::createUnrollLoopsPass());
358-
modulePM.addPass(mlir::createCSEPass());
359-
modulePM.addPass(mlir::createCanonicalizerPass());
360-
modulePM.addPass(llhd::createRemoveControlFlowPass());
361-
modulePM.addPass(mlir::createCSEPass());
362-
modulePM.addPass(mlir::createCanonicalizerPass());
363-
364-
// Convert `arith.select` generated by some of the control flow canonicalizers
365-
// to `comb.mux`.
366-
modulePM.addPass(createMapArithToCombPass());
367-
368-
// Simplify module-level signals.
369-
modulePM.addPass(llhd::createCombineDrivesPass());
370-
modulePM.addPass(llhd::createSig2Reg());
371-
modulePM.addPass(mlir::createCSEPass());
372-
modulePM.addPass(mlir::createCanonicalizerPass());
373-
374-
// Map `seq.firreg` with array type and `hw.array_inject` self-feedback to
375-
// `seq.firmem` ops.
376-
if (opts.detectMemories) {
377-
modulePM.addPass(seq::createRegOfVecToMem());
378-
modulePM.addPass(mlir::createCSEPass());
379-
modulePM.addPass(mlir::createCanonicalizerPass());
380-
}
381-
}
382-
383279
/// Populate the given pass manager with transformations as configured by the
384280
/// command line options.
385281
static void populatePasses(PassManager &pm) {
386-
populateMooreTransforms(pm);
282+
populateVerilogToMoorePipeline(pm);
387283
if (opts.loweringMode == LoweringMode::OutputIRMoore)
388284
return;
389-
populateMooreToCoreLowering(pm);
285+
mooreToCorePipeline(pm);
390286
if (opts.loweringMode == LoweringMode::OutputIRLLHD)
391287
return;
392-
populateLLHDLowering(pm);
288+
LlhdToCorePipelineOptions options;
289+
options.detectMemories = opts.detectMemories;
290+
llhdToCorePipeline(pm, options);
393291
}
394292

395293
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)