CIRCT  18.0.0git
ESILowerToHW.cpp
Go to the documentation of this file.
1 //===- ESILowerToHW.cpp - Lower ESI to HW -----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Lower to HW/SV conversions and pass.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "../PassDetails.h"
14 
18 #include "circt/Dialect/HW/HWOps.h"
19 #include "circt/Dialect/SV/SVOps.h"
21 #include "circt/Support/LLVM.h"
22 #include "circt/Support/SymCache.h"
23 
24 #include "mlir/Transforms/DialectConversion.h"
25 
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/ADT/TypeSwitch.h"
28 #include "llvm/Support/JSON.h"
29 
30 using namespace circt;
31 using namespace circt::esi;
32 using namespace circt::esi::detail;
33 using namespace circt::hw;
34 using namespace circt::sv;
35 
36 namespace {
37 /// Lower PipelineStageOp ops to an HW implementation. Unwrap and re-wrap
38 /// appropriately. Another conversion will take care merging the resulting
39 /// adjacent wrap/unwrap ops.
40 struct PipelineStageLowering : public OpConversionPattern<PipelineStageOp> {
41 public:
42  PipelineStageLowering(ESIHWBuilder &builder, MLIRContext *ctxt)
44  using OpConversionPattern::OpConversionPattern;
45 
46  LogicalResult
47  matchAndRewrite(PipelineStageOp stage, OpAdaptor adaptor,
48  ConversionPatternRewriter &rewriter) const final;
49 
50 private:
52 };
53 } // anonymous namespace
54 
55 LogicalResult PipelineStageLowering::matchAndRewrite(
56  PipelineStageOp stage, OpAdaptor adaptor,
57  ConversionPatternRewriter &rewriter) const {
58  auto loc = stage.getLoc();
59  auto chPort = stage.getInput().getType().dyn_cast<ChannelType>();
60  if (!chPort)
61  return rewriter.notifyMatchFailure(stage, "stage had wrong type");
62  Operation *symTable = stage->getParentWithTrait<OpTrait::SymbolTable>();
63  auto stageModule = builder.declareStage(symTable, stage);
64 
65  size_t width = circt::hw::getBitWidth(chPort.getInner());
66 
67  ArrayAttr stageParams =
68  builder.getStageParameterList(rewriter.getUI32IntegerAttr(width));
69 
70  // Unwrap the channel. The ready signal is a Value we haven't created yet,
71  // so create a temp value and replace it later. Give this constant an
72  // odd-looking type to make debugging easier.
73  circt::BackedgeBuilder back(rewriter, loc);
74  circt::Backedge wrapReady = back.get(rewriter.getI1Type());
75  auto unwrap =
76  rewriter.create<UnwrapValidReadyOp>(loc, stage.getInput(), wrapReady);
77 
78  StringRef pipeStageName = "pipelineStage";
79  if (auto name = stage->getAttrOfType<StringAttr>("name"))
80  pipeStageName = name.getValue();
81 
82  // Instantiate the "ESI_PipelineStage" external module.
83  circt::Backedge stageReady = back.get(rewriter.getI1Type());
84  llvm::SmallVector<Value> operands = {stage.getClk(), stage.getRst()};
85  operands.push_back(unwrap.getRawOutput());
86  operands.push_back(unwrap.getValid());
87  operands.push_back(stageReady);
88  auto stageInst = rewriter.create<InstanceOp>(loc, stageModule, pipeStageName,
89  operands, stageParams);
90  auto stageInstResults = stageInst.getResults();
91 
92  // Set a_ready (from the unwrap) back edge correctly to its output from
93  // stage.
94  wrapReady.setValue(stageInstResults[0]);
95  Value x, xValid;
96  x = stageInstResults[1];
97  xValid = stageInstResults[2];
98 
99  // Wrap up the output of the HW stage module.
100  auto wrap = rewriter.create<WrapValidReadyOp>(
101  loc, chPort, rewriter.getI1Type(), x, xValid);
102  // Set the stages x_ready backedge correctly.
103  stageReady.setValue(wrap.getReady());
104 
105  rewriter.replaceOp(stage, wrap.getChanOutput());
106  return success();
107 }
108 
109 namespace {
110 struct NullSourceOpLowering : public OpConversionPattern<NullSourceOp> {
111 public:
112  NullSourceOpLowering(MLIRContext *ctxt) : OpConversionPattern(ctxt) {}
113  using OpConversionPattern::OpConversionPattern;
114 
115  LogicalResult
116  matchAndRewrite(NullSourceOp nullop, OpAdaptor adaptor,
117  ConversionPatternRewriter &rewriter) const final;
118 };
119 } // anonymous namespace
120 
121 LogicalResult NullSourceOpLowering::matchAndRewrite(
122  NullSourceOp nullop, OpAdaptor adaptor,
123  ConversionPatternRewriter &rewriter) const {
124  auto innerType = nullop.getOut().getType().cast<ChannelType>().getInner();
125  Location loc = nullop.getLoc();
126  int64_t width = hw::getBitWidth(innerType);
127  if (width == -1)
128  return rewriter.notifyMatchFailure(
129  nullop, "NullOp lowering only supports hw types");
130  auto valid =
131  rewriter.create<hw::ConstantOp>(nullop.getLoc(), rewriter.getI1Type(), 0);
132  auto zero =
133  rewriter.create<hw::ConstantOp>(loc, rewriter.getIntegerType(width), 0);
134  auto typedZero = rewriter.create<hw::BitcastOp>(loc, innerType, zero);
135  auto wrap = rewriter.create<WrapValidReadyOp>(loc, typedZero, valid);
136  wrap->setAttr("name", rewriter.getStringAttr("nullsource"));
137  rewriter.replaceOp(nullop, {wrap.getChanOutput()});
138  return success();
139 }
140 
141 namespace {
142 /// Eliminate back-to-back wrap-unwraps to reduce the number of ESI channels.
143 struct RemoveWrapUnwrap : public ConversionPattern {
144 public:
145  RemoveWrapUnwrap(MLIRContext *context)
146  : ConversionPattern(MatchAnyOpTypeTag(), /*benefit=*/1, context) {}
147 
148  LogicalResult
149  matchAndRewrite(Operation *op, ArrayRef<Value> operands,
150  ConversionPatternRewriter &rewriter) const override {
151  Value valid, ready, data;
152  WrapValidReadyOp wrap = dyn_cast<WrapValidReadyOp>(op);
153  UnwrapValidReadyOp unwrap = dyn_cast<UnwrapValidReadyOp>(op);
154  if (wrap) {
155  if (!wrap.getChanOutput().hasOneUse() ||
156  !(unwrap = dyn_cast<UnwrapValidReadyOp>(
157  wrap.getChanOutput().use_begin()->getOwner())))
158  return rewriter.notifyMatchFailure(
159  wrap, "This conversion only supports wrap-unwrap back-to-back. "
160  "Could not find 'unwrap'.");
161 
162  data = operands[0];
163  valid = operands[1];
164  ready = unwrap.getReady();
165  } else if (unwrap) {
166  wrap = dyn_cast<WrapValidReadyOp>(operands[0].getDefiningOp());
167  if (!wrap)
168  return rewriter.notifyMatchFailure(
169  operands[0].getDefiningOp(),
170  "This conversion only supports wrap-unwrap back-to-back. "
171  "Could not find 'wrap'.");
172  valid = wrap.getValid();
173  data = wrap.getRawInput();
174  ready = operands[1];
175  } else {
176  return failure();
177  }
178 
179  if (!wrap.getChanOutput().hasOneUse())
180  return rewriter.notifyMatchFailure(wrap, [](Diagnostic &d) {
181  d << "This conversion only supports wrap-unwrap back-to-back. "
182  "Wrap didn't have exactly one use.";
183  });
184  rewriter.replaceOp(wrap, {nullptr, ready});
185  rewriter.replaceOp(unwrap, {data, valid});
186  return success();
187  }
188 };
189 } // anonymous namespace
190 
191 namespace {
192 /// Use the op canonicalizer to lower away the op. Assumes the canonicalizer
193 /// deletes the op.
194 template <typename Op>
195 struct CanonicalizerOpLowering : public OpConversionPattern<Op> {
196 public:
197  CanonicalizerOpLowering(MLIRContext *ctxt) : OpConversionPattern<Op>(ctxt) {}
198 
199  LogicalResult
200  matchAndRewrite(Op op, typename Op::Adaptor adaptor,
201  ConversionPatternRewriter &rewriter) const final {
202  if (failed(Op::canonicalize(op, rewriter)))
203  return rewriter.notifyMatchFailure(op->getLoc(), "canonicalizer failed");
204  return success();
205  }
206 };
207 } // anonymous namespace
208 
209 namespace {
210 struct ESItoHWPass : public LowerESItoHWBase<ESItoHWPass> {
211  void runOnOperation() override;
212 };
213 } // anonymous namespace
214 
215 namespace {
216 /// Lower a `wrap.iface` to `wrap.vr` by extracting the wires then feeding the
217 /// new `wrap.vr`.
218 struct WrapInterfaceLower : public OpConversionPattern<WrapSVInterfaceOp> {
219 public:
220  using OpConversionPattern::OpConversionPattern;
221 
222  LogicalResult
223  matchAndRewrite(WrapSVInterfaceOp wrap, OpAdaptor adaptor,
224  ConversionPatternRewriter &rewriter) const final;
225 };
226 } // anonymous namespace
227 
228 LogicalResult
229 WrapInterfaceLower::matchAndRewrite(WrapSVInterfaceOp wrap, OpAdaptor adaptor,
230  ConversionPatternRewriter &rewriter) const {
231  auto operands = adaptor.getOperands();
232  if (operands.size() != 1)
233  return rewriter.notifyMatchFailure(wrap, [&operands](Diagnostic &d) {
234  d << "wrap.iface has 1 argument. Got " << operands.size() << "operands";
235  });
236  auto sinkModport = dyn_cast<GetModportOp>(operands[0].getDefiningOp());
237  if (!sinkModport)
238  return failure();
239  auto ifaceInstance =
240  dyn_cast<InterfaceInstanceOp>(sinkModport.getIface().getDefiningOp());
241  if (!ifaceInstance)
242  return failure();
243 
244  auto loc = wrap.getLoc();
245  auto validSignal = rewriter.create<ReadInterfaceSignalOp>(
246  loc, ifaceInstance, ESIHWBuilder::validStr);
247  Value dataSignal;
248  dataSignal = rewriter.create<ReadInterfaceSignalOp>(loc, ifaceInstance,
250  auto wrapVR = rewriter.create<WrapValidReadyOp>(loc, dataSignal, validSignal);
251  rewriter.create<AssignInterfaceSignalOp>(
252  loc, ifaceInstance, ESIHWBuilder::readyStr, wrapVR.getReady());
253  rewriter.replaceOp(wrap, {wrapVR.getChanOutput()});
254  return success();
255 }
256 
257 namespace {
258 /// Lower an unwrap interface to just extract the wires and feed them into an
259 /// `unwrap.vr`.
260 struct UnwrapInterfaceLower : public OpConversionPattern<UnwrapSVInterfaceOp> {
261 public:
262  UnwrapInterfaceLower(MLIRContext *ctxt) : OpConversionPattern(ctxt) {}
263  using OpConversionPattern::OpConversionPattern;
264 
265  LogicalResult
266  matchAndRewrite(UnwrapSVInterfaceOp wrap, OpAdaptor adaptor,
267  ConversionPatternRewriter &rewriter) const final;
268 };
269 } // anonymous namespace
270 
271 LogicalResult UnwrapInterfaceLower::matchAndRewrite(
272  UnwrapSVInterfaceOp unwrap, OpAdaptor adaptor,
273  ConversionPatternRewriter &rewriter) const {
274  auto operands = adaptor.getOperands();
275  if (operands.size() != 2)
276  return rewriter.notifyMatchFailure(unwrap, [&operands](Diagnostic &d) {
277  d << "Unwrap.iface has 2 arguments. Got " << operands.size()
278  << "operands";
279  });
280 
281  auto sourceModport = dyn_cast<GetModportOp>(operands[1].getDefiningOp());
282  if (!sourceModport)
283  return failure();
284  auto ifaceInstance =
285  dyn_cast<InterfaceInstanceOp>(sourceModport.getIface().getDefiningOp());
286  if (!ifaceInstance)
287  return failure();
288 
289  auto loc = unwrap.getLoc();
290  auto readySignal = rewriter.create<ReadInterfaceSignalOp>(
291  loc, ifaceInstance, ESIHWBuilder::readyStr);
292  auto unwrapVR =
293  rewriter.create<UnwrapValidReadyOp>(loc, operands[0], readySignal);
294  rewriter.create<AssignInterfaceSignalOp>(
295  loc, ifaceInstance, ESIHWBuilder::validStr, unwrapVR.getValid());
296 
297  rewriter.create<AssignInterfaceSignalOp>(
298  loc, ifaceInstance, ESIHWBuilder::dataStr, unwrapVR.getRawOutput());
299  rewriter.eraseOp(unwrap);
300  return success();
301 }
302 
303 namespace {
304 /// Lower `CosimEndpointOp` ops to a SystemVerilog extern module and a Capnp
305 /// gasket op.
306 struct CosimToHostLowering : public OpConversionPattern<CosimToHostEndpointOp> {
307 public:
308  CosimToHostLowering(ESIHWBuilder &b)
309  : OpConversionPattern(b.getContext(), 1), builder(b) {}
310 
311  using OpConversionPattern::OpConversionPattern;
312 
313  LogicalResult
314  matchAndRewrite(CosimToHostEndpointOp, OpAdaptor adaptor,
315  ConversionPatternRewriter &rewriter) const final;
316 
317 private:
319 };
320 } // anonymous namespace
321 
322 LogicalResult CosimToHostLowering::matchAndRewrite(
323  CosimToHostEndpointOp ep, OpAdaptor adaptor,
324  ConversionPatternRewriter &rewriter) const {
325  auto loc = ep.getLoc();
326  auto *ctxt = rewriter.getContext();
327  circt::BackedgeBuilder bb(rewriter, loc);
328 
329  Value toHost = adaptor.getToHost();
330  Type type = toHost.getType();
331  uint64_t width = getWidth(type);
332 
333  // Set all the parameters.
334  SmallVector<Attribute, 8> params;
335  params.push_back(ParamDeclAttr::get("TO_HOST_TYPE_ID", getTypeID(type)));
336  params.push_back(ParamDeclAttr::get("TO_HOST_SIZE_BITS",
337  rewriter.getI32IntegerAttr(width)));
338 
339  // Set up the egest route to drive the EP's toHost ports.
340  auto sendReady = bb.get(rewriter.getI1Type());
341  UnwrapValidReadyOp unwrapSend =
342  rewriter.create<UnwrapValidReadyOp>(loc, toHost, sendReady);
343  auto castedSendData = rewriter.create<hw::BitcastOp>(
344  loc, rewriter.getIntegerType(width), unwrapSend.getRawOutput());
345 
346  // Build or get the cached Cosim Endpoint module parameterization.
347  Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
348  HWModuleExternOp endpoint =
349  builder.declareCosimEndpointToHostModule(symTable);
350 
351  // Create replacement Cosim_Endpoint instance.
352  Value operands[] = {
353  adaptor.getClk(),
354  adaptor.getRst(),
355  unwrapSend.getValid(),
356  castedSendData.getResult(),
357  };
358  auto cosimEpModule = rewriter.create<InstanceOp>(
359  loc, endpoint, ep.getNameAttr(), operands, ArrayAttr::get(ctxt, params));
360  sendReady.setValue(cosimEpModule.getResult(0));
361 
362  // Replace the CosimEndpointOp op.
363  rewriter.eraseOp(ep);
364 
365  return success();
366 }
367 
368 namespace {
369 /// Lower `CosimEndpointOp` ops to a SystemVerilog extern module and a Capnp
370 /// gasket op.
371 struct CosimFromHostLowering
372  : public OpConversionPattern<CosimFromHostEndpointOp> {
373 public:
374  CosimFromHostLowering(ESIHWBuilder &b)
375  : OpConversionPattern(b.getContext(), 1), builder(b) {}
376 
377  using OpConversionPattern::OpConversionPattern;
378 
379  LogicalResult
380  matchAndRewrite(CosimFromHostEndpointOp, OpAdaptor adaptor,
381  ConversionPatternRewriter &rewriter) const final;
382 
383 private:
385 };
386 } // anonymous namespace
387 
388 LogicalResult CosimFromHostLowering::matchAndRewrite(
389  CosimFromHostEndpointOp ep, OpAdaptor adaptor,
390  ConversionPatternRewriter &rewriter) const {
391  auto loc = ep.getLoc();
392  auto *ctxt = rewriter.getContext();
393  circt::BackedgeBuilder bb(rewriter, loc);
394 
395  ChannelType type = ep.getFromHost().getType();
396  uint64_t width = getWidth(type);
397 
398  // Set all the parameters.
399  SmallVector<Attribute, 8> params;
400  params.push_back(ParamDeclAttr::get("FROM_HOST_TYPE_ID", getTypeID(type)));
401  params.push_back(ParamDeclAttr::get("FROM_HOST_SIZE_BITS",
402  rewriter.getI32IntegerAttr(width)));
403 
404  // Get information necessary for injest path.
405  auto recvReady = bb.get(rewriter.getI1Type());
406 
407  // Build or get the cached Cosim Endpoint module parameterization.
408  Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
409  HWModuleExternOp endpoint =
410  builder.declareCosimEndpointFromHostModule(symTable);
411 
412  // Create replacement Cosim_Endpoint instance.
413  StringAttr nameAttr = ep->getAttr("name").dyn_cast_or_null<StringAttr>();
414  StringRef name = nameAttr ? nameAttr.getValue() : "CosimEndpointOp";
415  Value operands[] = {adaptor.getClk(), adaptor.getRst(), recvReady};
416 
417  auto cosimEpModule = rewriter.create<InstanceOp>(
418  loc, endpoint, name, operands, ArrayAttr::get(ctxt, params));
419 
420  // Set up the injest path.
421  Value recvDataFromCosim = cosimEpModule.getResult(1);
422  Value recvValidFromCosim = cosimEpModule.getResult(0);
423  auto castedRecvData =
424  rewriter.create<hw::BitcastOp>(loc, type.getInner(), recvDataFromCosim);
425  WrapValidReadyOp wrapRecv = rewriter.create<WrapValidReadyOp>(
426  loc, castedRecvData.getResult(), recvValidFromCosim);
427  recvReady.setValue(wrapRecv.getReady());
428 
429  // Replace the CosimEndpointOp op.
430  rewriter.replaceOp(ep, wrapRecv.getChanOutput());
431 
432  return success();
433 }
434 
435 namespace {
436 /// Lower `CompressedManifestOps` ops to a SystemVerilog extern module.
437 struct CosimManifestLowering
438  : public OpConversionPattern<CompressedManifestOp> {
439 public:
440  using OpConversionPattern::OpConversionPattern;
441 
442  LogicalResult
443  matchAndRewrite(CompressedManifestOp, OpAdaptor adaptor,
444  ConversionPatternRewriter &rewriter) const final;
445 };
446 } // anonymous namespace
447 
448 LogicalResult CosimManifestLowering::matchAndRewrite(
449  CompressedManifestOp op, OpAdaptor adaptor,
450  ConversionPatternRewriter &rewriter) const {
451  MLIRContext *ctxt = rewriter.getContext();
452  Location loc = op.getLoc();
453 
454  // Declare external module.
455  Attribute params[] = {
456  ParamDeclAttr::get("COMPRESSED_MANIFEST_SIZE", rewriter.getI32Type())};
457  PortInfo ports[] = {
458  {{rewriter.getStringAttr("compressed_manifest"),
459  rewriter.getType<hw::UnpackedArrayType>(
460  rewriter.getI8Type(),
462  rewriter.getStringAttr("COMPRESSED_MANIFEST_SIZE"),
463  rewriter.getI32Type())),
465  0},
466  };
467  rewriter.setInsertionPointToEnd(
468  op->getParentOfType<mlir::ModuleOp>().getBody());
469  auto manifestModule = rewriter.create<HWModuleExternOp>(
470  loc, rewriter.getStringAttr("Cosim_Manifest"), ports, "Cosim_Manifest",
471  ArrayAttr::get(ctxt, params));
472 
473  rewriter.setInsertionPoint(op);
474 
475  // Assemble the manifest data into a constant.
476  SmallVector<Attribute> bytes;
477  for (char b : op.getCompressedManifest().getData())
478  bytes.push_back(rewriter.getI8IntegerAttr(b));
479  auto manifestConstant = rewriter.create<hw::AggregateConstantOp>(
480  loc, hw::UnpackedArrayType::get(rewriter.getI8Type(), bytes.size()),
481  rewriter.getArrayAttr(bytes));
482  auto manifestLogic =
483  rewriter.create<sv::LogicOp>(loc, manifestConstant.getType());
484  rewriter.create<sv::AssignOp>(loc, manifestLogic, manifestConstant);
485  auto manifest = rewriter.create<sv::ReadInOutOp>(loc, manifestLogic);
486 
487  // Then instantiate the external module.
488  rewriter.create<hw::InstanceOp>(
489  loc, manifestModule, "__manifest", ArrayRef<Value>({manifest}),
490  rewriter.getArrayAttr(
491  {ParamDeclAttr::get("COMPRESSED_MANIFEST_SIZE",
492  rewriter.getI32IntegerAttr(bytes.size()))}));
493  rewriter.eraseOp(op);
494  return success();
495 }
496 
497 void ESItoHWPass::runOnOperation() {
498  auto top = getOperation();
499  auto *ctxt = &getContext();
500 
501  ConversionTarget noBundlesTarget(*ctxt);
502  noBundlesTarget.markUnknownOpDynamicallyLegal(
503  [](Operation *) { return true; });
504  noBundlesTarget.addIllegalOp<PackBundleOp>();
505  noBundlesTarget.addIllegalOp<UnpackBundleOp>();
506  RewritePatternSet bundlePatterns(&getContext());
507  bundlePatterns.add<CanonicalizerOpLowering<PackBundleOp>>(&getContext());
508  bundlePatterns.add<CanonicalizerOpLowering<UnpackBundleOp>>(&getContext());
509  if (failed(applyPartialConversion(getOperation(), noBundlesTarget,
510  std::move(bundlePatterns))))
511  signalPassFailure();
512 
513  // Set up a conversion and give it a set of laws.
514  ConversionTarget pass1Target(*ctxt);
515  pass1Target.addLegalDialect<comb::CombDialect>();
516  pass1Target.addLegalDialect<HWDialect>();
517  pass1Target.addLegalDialect<SVDialect>();
518  pass1Target.addLegalOp<WrapValidReadyOp, UnwrapValidReadyOp>();
519 
520  pass1Target.addIllegalOp<WrapSVInterfaceOp, UnwrapSVInterfaceOp>();
521  pass1Target.addIllegalOp<PipelineStageOp>();
522  pass1Target.addIllegalOp<CompressedManifestOp>();
523 
524  // Add all the conversion patterns.
525  ESIHWBuilder esiBuilder(top);
526  RewritePatternSet pass1Patterns(ctxt);
527  pass1Patterns.insert<PipelineStageLowering>(esiBuilder, ctxt);
528  pass1Patterns.insert<WrapInterfaceLower>(ctxt);
529  pass1Patterns.insert<UnwrapInterfaceLower>(ctxt);
530  pass1Patterns.insert<CosimToHostLowering>(esiBuilder);
531  pass1Patterns.insert<CosimFromHostLowering>(esiBuilder);
532  pass1Patterns.insert<NullSourceOpLowering>(ctxt);
533 
534  if (platform == Platform::cosim) {
535  pass1Patterns.insert<CosimManifestLowering>(ctxt);
536  }
537 
538  // Run the conversion.
539  if (failed(
540  applyPartialConversion(top, pass1Target, std::move(pass1Patterns))))
541  signalPassFailure();
542 
543  ConversionTarget pass2Target(*ctxt);
544  pass2Target.addLegalDialect<comb::CombDialect>();
545  pass2Target.addLegalDialect<HWDialect>();
546  pass2Target.addLegalDialect<SVDialect>();
547  pass2Target.addIllegalDialect<ESIDialect>();
548 
549  RewritePatternSet pass2Patterns(ctxt);
550  pass2Patterns.insert<CanonicalizerOpLowering<UnwrapFIFOOp>>(ctxt);
551  pass2Patterns.insert<CanonicalizerOpLowering<WrapFIFOOp>>(ctxt);
552  pass2Patterns.insert<RemoveWrapUnwrap>(ctxt);
553  if (failed(
554  applyPartialConversion(top, pass2Target, std::move(pass2Patterns))))
555  signalPassFailure();
556 }
557 
558 std::unique_ptr<OperationPass<ModuleOp>> circt::esi::createESItoHWPass() {
559  return std::make_unique<ESItoHWPass>();
560 }
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
int32_t width
Definition: FIRRTL.cpp:27
@ Input
Definition: HW.h:32
static EvaluatorValuePtr unwrap(OMEvaluatorValue c)
Definition: OM.cpp:100
Builder builder
Instantiate one of these and use it to build typed backedges.
Backedge is a wrapper class around a Value.
void setValue(mlir::Value)
Assist the lowering steps for conversions which need to create auxiliary IR.
Definition: PassDetails.h:50
static constexpr char validStr[]
Definition: PassDetails.h:70
static constexpr char readyStr[]
Definition: PassDetails.h:71
static constexpr char dataStr[]
Definition: PassDetails.h:70
def create(data_type, value)
Definition: hw.py:405
def create(data_type, value)
Definition: hw.py:397
def create(dest, src)
Definition: sv.py:98
def create(value)
Definition: sv.py:106
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:53
uint64_t getWidth(Type t)
Definition: ESIPasses.cpp:34
StringAttr getTypeID(Type t)
Definition: ESIPasses.cpp:26
std::unique_ptr< OperationPass< ModuleOp > > createESItoHWPass()
mlir::Type innerType(mlir::Type type)
Definition: ESITypes.cpp:184
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
Definition: HWTypes.cpp:102
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
Definition: DebugAnalysis.h:21
static constexpr char cosim[]
Definition: ESIPasses.h:28
This holds the name, type, direction of a module's ports.