mirror of https://github.com/llvm/circt.git
[circt-verilog] Add register-to-memory pass to pipeline (#8773)
Add the new RegOfVecToMem pass to the circt-verilog pipeline. This will detect memories described as `always` blocks and map them from the current `seq.firreg` representation to the correpsonding `seq.firmem`. This allows later parts of the pipeline to reason about memories more easily and transform them if needed.
This commit is contained in:
parent
5c3780f58b
commit
dbbc952d89
|
@ -0,0 +1,34 @@
|
|||
// RUN: circt-verilog %s | FileCheck %s --check-prefixes=CHECK,MEMON
|
||||
// RUN: circt-verilog --detect-memories=1 %s | FileCheck %s --check-prefixes=CHECK,MEMON
|
||||
// RUN: circt-verilog --detect-memories=0 %s | FileCheck %s --check-prefixes=CHECK,MEMOFF
|
||||
// REQUIRES: slang
|
||||
// Internal issue in Slang v3 about jump depending on uninitialised value.
|
||||
// UNSUPPORTED: valgrind
|
||||
|
||||
// CHECK-LABEL: hw.module @Memory(
|
||||
module Memory(
|
||||
input bit clock,
|
||||
input bit [3:0] waddr,
|
||||
input bit [41:0] wdata,
|
||||
input bit wenable,
|
||||
input bit [3:0] raddr,
|
||||
output bit [41:0] rdata
|
||||
);
|
||||
// CHECK-DAG: [[CLK:%.+]] = seq.to_clock %clock
|
||||
|
||||
// MEMON-DAG: [[MEM:%.+]] = seq.firmem 0, 1, undefined, undefined : <16 x 42, mask 1>
|
||||
// MEMON-DAG: [[RDATA:%.+]] = seq.firmem.read_port [[MEM]][%raddr]
|
||||
// MEMON-DAG: seq.firmem.write_port %mem[%waddr] = %wdata, clock [[CLK]] enable %wenable
|
||||
|
||||
// MEMOFF-DAG: [[REG:%.+]] = seq.firreg [[NEXT:%.+]] clock [[CLK]] : !hw.array<16xi42>
|
||||
// MEMOFF-DAG: [[TMP:%.+]] = hw.array_inject [[REG]][%waddr], %wdata
|
||||
// MEMOFF-DAG: [[NEXT]] = comb.mux bin %wenable, [[TMP]], [[REG]]
|
||||
// MEMOFF-DAG: [[RDATA:%.+]] = hw.array_get [[REG]][%raddr]
|
||||
|
||||
// CHECK: hw.output [[RDATA]]
|
||||
bit [41:0] storage [15:0];
|
||||
always_ff @(posedge clock)
|
||||
if (wenable)
|
||||
storage[waddr] <= wdata;
|
||||
assign rdata = storage[raddr];
|
||||
endmodule
|
|
@ -9,6 +9,7 @@ set(libs
|
|||
CIRCTMooreToCore
|
||||
CIRCTMooreTransforms
|
||||
CIRCTSeq
|
||||
CIRCTSeqTransforms
|
||||
CIRCTSim
|
||||
CIRCTSupport
|
||||
CIRCTTransforms
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "circt/Dialect/Moore/MooreDialect.h"
|
||||
#include "circt/Dialect/Moore/MoorePasses.h"
|
||||
#include "circt/Dialect/Seq/SeqDialect.h"
|
||||
#include "circt/Dialect/Seq/SeqPasses.h"
|
||||
#include "circt/Dialect/Sim/SimDialect.h"
|
||||
#include "circt/Dialect/Verif/VerifDialect.h"
|
||||
#include "circt/Support/Passes.h"
|
||||
|
@ -129,6 +130,11 @@ struct CLOptions {
|
|||
cl::desc("Interpret `always @(*)` as `always_comb`"), cl::init(true),
|
||||
cl::cat(cat)};
|
||||
|
||||
cl::opt<bool> detectMemories{
|
||||
"detect-memories",
|
||||
cl::desc("Detect memories and lower them to `seq.firmem`"),
|
||||
cl::init(true), cl::cat(cat)};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Include paths
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -354,6 +360,14 @@ static void populateLLHDLowering(PassManager &pm) {
|
|||
modulePM.addPass(llhd::createSig2Reg());
|
||||
modulePM.addPass(mlir::createCSEPass());
|
||||
modulePM.addPass(mlir::createCanonicalizerPass());
|
||||
|
||||
// Map `seq.firreg` with array type and `hw.array_inject` self-feedback to
|
||||
// `seq.firmem` ops.
|
||||
if (opts.detectMemories) {
|
||||
modulePM.addPass(seq::createRegOfVecToMem());
|
||||
modulePM.addPass(mlir::createCSEPass());
|
||||
modulePM.addPass(mlir::createCanonicalizerPass());
|
||||
}
|
||||
}
|
||||
|
||||
/// Populate the given pass manager with transformations as configured by the
|
||||
|
|
Loading…
Reference in New Issue