17#include "mlir/Pass/Pass.h" 
   18#include "mlir/Transforms/DialectConversion.h" 
   19#include "llvm/ADT/TypeSwitch.h" 
   23#define GEN_PASS_DEF_LOWERSEQHLMEM 
   24#include "circt/Dialect/Seq/SeqPasses.h.inc" 
   33struct SimpleBehavioralMemoryLowering
 
   39  using OpConversionPattern::OpConversionPattern;
 
   42  matchAndRewrite(seq::HLMemOp mem, OpAdaptor adaptor,
 
   43                  ConversionPatternRewriter &rewriter) 
const final {
 
   46    auto memType = mem.getMemType();
 
   47    if (memType.getShape().size() != 1)
 
   48      return rewriter.notifyMatchFailure(
 
   49          mem, 
"only unidimensional memories are supported");
 
   50    auto size = memType.getShape()[0];
 
   53    llvm::SmallVector<seq::ReadPortOp> readOps;
 
   54    llvm::SmallVector<seq::WritePortOp> writeOps;
 
   55    for (
auto *user : mem.getHandle().getUsers()) {
 
   56      auto res = llvm::TypeSwitch<Operation *, LogicalResult>(user)
 
   57                     .Case([&](seq::ReadPortOp op) {
 
   58                       readOps.push_back(op);
 
   61                     .Case([&](seq::WritePortOp op) {
 
   62                       writeOps.push_back(op);
 
   65                     .Default([&](Operation *op) { 
return failure(); });
 
   67        return rewriter.notifyMatchFailure(user, 
"unsupported port type");
 
   70    auto clk = mem.getClk();
 
   71    auto rst = mem.getRst();
 
   72    auto memName = mem.getName();
 
   75    hw::UnpackedArrayType memArrType =
 
   76        hw::UnpackedArrayType::get(memType.getElementType(), size);
 
   78        sv::RegOp::create(rewriter, mem.getLoc(), memArrType, mem.getNameAttr())
 
   89    llvm::SmallVector<WriteTuple> writeTuples;
 
   90    for (
auto writeOp : writeOps) {
 
   91      if (writeOp.getLatency() != 1)
 
   92        return rewriter.notifyMatchFailure(
 
   93            writeOp, 
"only supports write ports with latency == 1");
 
   94      auto addr = writeOp.getAddresses()[0];
 
   95      auto data = writeOp.getInData();
 
   96      auto en = writeOp.getWrEn();
 
   97      writeTuples.push_back({writeOp.getLoc(), 
addr, 
data, 
en});
 
   98      rewriter.eraseOp(writeOp);
 
  101    auto hwClk = seq::FromClockOp::create(rewriter, 
clk.getLoc(), 
clk);
 
  102    sv::AlwaysFFOp::create(
 
  103        rewriter, mem.getLoc(), sv::EventControl::AtPosEdge, hwClk,
 
  104        sv::ResetType::SyncReset, sv::EventControl::AtPosEdge, rst, [&] {
 
  105          for (auto [loc, address, data, en] : writeTuples) {
 
  106            Value a = address, d = data; 
 
  109            sv::IfOp::create(rewriter, loc, en, [&] {
 
  111                  sv::ArrayIndexInOutOp::create(rewriter, l, svMem, a);
 
  112              sv::PAssignOp::create(rewriter, l, memLoc, d);
 
  123    for (
auto [ri, readOp] : 
llvm::enumerate(readOps)) {
 
  124      rewriter.setInsertionPointAfter(readOp);
 
  125      auto loc = readOp.getLoc();
 
  127      auto readAddress = readOp.getAddresses()[0];
 
  128      unsigned latency = readOp.getLatency();
 
  129      unsigned addressDelayCycles = latency - 1;
 
  132        for (
unsigned i = 0; i < addressDelayCycles; ++i) {
 
  134              rewriter, loc, readAddress, clk,
 
  135              rewriter.getStringAttr(memName + 
"_rdaddr" + std::to_string(ri) +
 
  136                                     "_dly" + std::to_string(i)));
 
  142          sv::ArrayIndexInOutOp::create(rewriter, loc, svMem, readAddress);
 
  147            rewriter, loc, readData, clk,
 
  148            rewriter.getStringAttr(memName + 
"_rd" + std::to_string(ri) +
 
  151      rewriter.replaceOp(readOp, {readData});
 
  154    rewriter.eraseOp(mem);
 
  158struct LowerSeqHLMemPass
 
  159    : 
public circt::seq::impl::LowerSeqHLMemBase<LowerSeqHLMemPass> {
 
  160  void runOnOperation() 
override;
 
  165void LowerSeqHLMemPass::runOnOperation() {
 
  168  MLIRContext &
ctxt = getContext();
 
  169  ConversionTarget target(ctxt);
 
  172  target.addIllegalOp<seq::HLMemOp, seq::ReadPortOp, seq::WritePortOp>();
 
  173  target.addLegalDialect<sv::SVDialect, seq::SeqDialect>();
 
  177  if (failed(applyPartialConversion(top, target, std::move(
patterns))))
 
  182  return std::make_unique<LowerSeqHLMemPass>();
 
 
create(cls, result_type, reset=None, reset_value=None, name=None, sym_name=None, **kwargs)
 
std::unique_ptr< mlir::Pass > createLowerSeqHLMemPass()
 
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.