Skip to content

Commit a25df3d

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 a25df3d

File tree

4 files changed

+140
-107
lines changed

4 files changed

+140
-107
lines changed

include/circt/Conversion/ImportVerilog.h

Lines changed: 19 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/PassManager.h"
18+
#include "mlir/Pass/PassOptions.h"
1719
#include <cstdint>
1820
#include <optional>
1921
#include <string>
@@ -150,6 +152,23 @@ importVerilog(llvm::SourceMgr &sourceMgr, mlir::MLIRContext *context,
150152
mlir::TimingScope &ts, mlir::ModuleOp module,
151153
const ImportVerilogOptions *options = nullptr);
152154

155+
/// Optimize and simplify the Moore dialect IR.
156+
void verilogToMoorePipeline(mlir::PassManager &pm);
157+
158+
/// Convert Moore dialect IR into core dialect IR
159+
void mooreToCorePipeline(mlir::PassManager &pm);
160+
161+
/// Convert LLHD dialect IR into core dialect IR
162+
struct LlhdToCorePipelineOptions
163+
: mlir::PassPipelineOptions<LlhdToCorePipelineOptions> {
164+
Option<bool> detectMemories{
165+
"detect-memories",
166+
cl::desc("Detect memories and lower them to `seq.firmem`"),
167+
cl::init(true)};
168+
};
169+
void llhdToCorePipeline(mlir::PassManager &pm,
170+
const LlhdToCorePipelineOptions &options);
171+
153172
/// Run the files in a source manager through Slang's Verilog preprocessor and
154173
/// emit the result to the given output stream.
155174
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: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@
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"
1622
#include "mlir/Support/Timing.h"
1723
#include "mlir/Tools/mlir-translate/Translation.h"
24+
#include "mlir/Transforms/Passes.h"
1825
#include "llvm/ADT/Hashing.h"
1926
#include "llvm/Support/SourceMgr.h"
2027

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

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+
verilogToMoorePipeline(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)