CIRCT  19.0.0git
FIRRTLIntrinsics.cpp
Go to the documentation of this file.
1 //===- FIRRTLIntrinsics.cpp - Lower Intrinsics ------------------*- 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 
10 #include "mlir/Transforms/DialectConversion.h"
11 
12 using namespace circt;
13 using namespace firrtl;
14 
15 //===----------------------------------------------------------------------===//
16 // GenericIntrinsic
17 //===----------------------------------------------------------------------===//
18 
19 ParseResult GenericIntrinsic::hasNInputs(unsigned n) {
20  if (op.getNumOperands() != n)
21  return emitError() << " has " << op.getNumOperands()
22  << " inputs instead of " << n;
23  return success();
24 }
25 
26 ParseResult GenericIntrinsic::hasNOutputElements(unsigned n) {
27  auto b = getOutputBundle();
28  if (!b)
29  return emitError() << " missing output bundle";
30  if (b.getType().getNumElements() != n)
31  return emitError() << " has " << b.getType().getNumElements()
32  << " output elements instead of " << n;
33  return success();
34 }
35 
36 ParseResult GenericIntrinsic::hasNParam(unsigned n, unsigned c) {
37  unsigned num = 0;
38  if (op.getParameters())
39  num = op.getParameters().size();
40  if (num < n || num > n + c) {
41  auto d = emitError() << " has " << num << " parameters instead of ";
42  if (c == 0)
43  d << n;
44  else
45  d << " between " << n << " and " << (n + c);
46  return failure();
47  }
48  return success();
49 }
50 
51 ParseResult GenericIntrinsic::namedParam(StringRef paramName, bool optional) {
52  for (auto a : op.getParameters()) {
53  auto param = cast<ParamDeclAttr>(a);
54  if (param.getName().getValue().equals(paramName)) {
55  if (isa<StringAttr>(param.getValue()))
56  return success();
57 
58  return emitError() << " has parameter '" << param.getName()
59  << "' which should be a string but is not";
60  }
61  }
62  if (optional)
63  return success();
64  return emitError() << " is missing parameter " << paramName;
65 }
66 
67 ParseResult GenericIntrinsic::namedIntParam(StringRef paramName,
68  bool optional) {
69  for (auto a : op.getParameters()) {
70  auto param = cast<ParamDeclAttr>(a);
71  if (param.getName().getValue().equals(paramName)) {
72  if (isa<IntegerAttr>(param.getValue()))
73  return success();
74 
75  return emitError() << " has parameter '" << param.getName()
76  << "' which should be an integer but is not";
77  }
78  }
79  if (optional)
80  return success();
81  return emitError() << " is missing parameter " << paramName;
82 }
83 
84 //===----------------------------------------------------------------------===//
85 // IntrinsicOpConversion
86 //===----------------------------------------------------------------------===//
87 
88 /// Conversion pattern adaptor dispatching via generic intrinsic name.
89 namespace {
90 class IntrinsicOpConversion final
91  : public OpConversionPattern<GenericIntrinsicOp> {
92 public:
93  using OpConversionPattern::OpConversionPattern;
94 
95  using ConversionMapTy = IntrinsicLowerings::ConversionMapTy;
96 
97  IntrinsicOpConversion(MLIRContext *context,
98  const ConversionMapTy &conversions,
99  size_t &numConversions,
100  bool allowUnknownIntrinsics = false)
101  : OpConversionPattern(context), conversions(conversions),
102  numConversions(numConversions),
103  allowUnknownIntrinsics(allowUnknownIntrinsics) {}
104 
105  LogicalResult
106  matchAndRewrite(GenericIntrinsicOp op, OpAdaptor adaptor,
107  ConversionPatternRewriter &rewriter) const override {
108 
109  auto it = conversions.find(op.getIntrinsicAttr());
110  if (it == conversions.end()) {
111  if (!allowUnknownIntrinsics)
112  return op.emitError("unknown intrinsic ") << op.getIntrinsicAttr();
113  return failure();
114  }
115 
116  auto &conv = *it->second;
117  if (conv.check(GenericIntrinsic(op)))
118  return failure();
119  conv.convert(GenericIntrinsic(op), adaptor, rewriter);
120  ++numConversions;
121  return success();
122  }
123 
124 private:
125  const ConversionMapTy &conversions;
126  size_t &numConversions;
127  const bool allowUnknownIntrinsics;
128 };
129 } // namespace
130 
131 //===----------------------------------------------------------------------===//
132 // IntrinsicLowerings
133 //===----------------------------------------------------------------------===//
134 
136  bool allowUnknownIntrinsics) {
137 
138  ConversionTarget target(*context);
139 
140  target.markUnknownOpDynamicallyLegal([](Operation *op) { return true; });
141  if (allowUnknownIntrinsics)
142  target.addDynamicallyLegalOp<GenericIntrinsicOp>(
143  [this](GenericIntrinsicOp op) {
144  return !conversions.contains(op.getIntrinsicAttr());
145  });
146  else
147  target.addIllegalOp<GenericIntrinsicOp>();
148 
149  RewritePatternSet patterns(context);
150  size_t count = 0;
151  patterns.add<IntrinsicOpConversion>(context, conversions, count,
152  allowUnknownIntrinsics);
153 
154  if (failed(mlir::applyPartialConversion(mod, target, std::move(patterns))))
155  return failure();
156 
157  return count;
158 }
159 
160 //===----------------------------------------------------------------------===//
161 // IntrinsicLoweringInterfaceCollection
162 //===----------------------------------------------------------------------===//
163 
165  IntrinsicLowerings &lowering) const {
166  for (const IntrinsicLoweringDialectInterface &interface : *this)
167  interface.populateIntrinsicLowerings(lowering);
168 }
169 
170 //===----------------------------------------------------------------------===//
171 // FIRRTL intrinsic lowering converters
172 //===----------------------------------------------------------------------===//
173 
174 namespace {
175 
176 class CirctSizeofConverter : public IntrinsicOpConverter<SizeOfIntrinsicOp> {
177 public:
178  using IntrinsicOpConverter::IntrinsicOpConverter;
179 
180  bool check(GenericIntrinsic gi) override {
181  return gi.hasNInputs(1) || gi.sizedOutput<UIntType>(32) || gi.hasNParam(0);
182  }
183 };
184 
185 class CirctIsXConverter : public IntrinsicOpConverter<IsXIntrinsicOp> {
186 public:
187  using IntrinsicOpConverter::IntrinsicOpConverter;
188 
189  bool check(GenericIntrinsic gi) override {
190  return gi.hasNInputs(1) || gi.sizedOutput<UIntType>(1) || gi.hasNParam(0);
191  }
192 };
193 
194 class CirctPlusArgTestConverter : public IntrinsicConverter {
195 public:
196  using IntrinsicConverter::IntrinsicConverter;
197 
198  bool check(GenericIntrinsic gi) override {
199  return gi.hasNInputs(0) || gi.sizedOutput<UIntType>(1) ||
200  gi.namedParam("FORMAT") || gi.hasNParam(1);
201  }
202 
203  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
204  PatternRewriter &rewriter) override {
205  rewriter.replaceOpWithNewOp<PlusArgsTestIntrinsicOp>(
206  gi.op, gi.getParamValue<StringAttr>("FORMAT"));
207  }
208 };
209 
210 class CirctPlusArgValueConverter : public IntrinsicConverter {
211 public:
212  using IntrinsicConverter::IntrinsicConverter;
213 
214  bool check(GenericIntrinsic gi) override {
215  return gi.hasNOutputElements(2) ||
216  gi.sizedOutputElement<UIntType>(0, "found", 1) ||
217  gi.hasOutputElement(1, "result") || gi.namedParam("FORMAT") ||
218  gi.hasNParam(1);
219  }
220 
221  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
222  PatternRewriter &rewriter) override {
223  auto bty = gi.getOutputBundle().getType();
224  auto newop = rewriter.create<PlusArgsValueIntrinsicOp>(
225  gi.op.getLoc(), bty.getElementTypePreservingConst(0),
226  bty.getElementTypePreservingConst(1),
227  gi.getParamValue<StringAttr>("FORMAT"));
228  rewriter.replaceOpWithNewOp<BundleCreateOp>(
229  gi.op, bty, ValueRange({newop.getFound(), newop.getResult()}));
230  }
231 };
232 
233 class CirctClockGateConverter
234  : public IntrinsicOpConverter<ClockGateIntrinsicOp> {
235 public:
236  using IntrinsicOpConverter::IntrinsicOpConverter;
237 
238  bool check(GenericIntrinsic gi) override {
239  if (gi.op.getNumOperands() == 3) {
240  return gi.typedInput<ClockType>(0) || gi.sizedInput<UIntType>(1, 1) ||
241  gi.sizedInput<UIntType>(2, 1) || gi.typedOutput<ClockType>() ||
242  gi.hasNParam(0);
243  }
244  if (gi.op.getNumOperands() == 2) {
245  return gi.typedInput<ClockType>(0) || gi.sizedInput<UIntType>(1, 1) ||
246  gi.typedOutput<ClockType>() || gi.hasNParam(0);
247  }
248  gi.emitError() << " has " << gi.op.getNumOperands()
249  << " ports instead of 3 or 4";
250  return true;
251  }
252 };
253 
254 class CirctClockInverterConverter
255  : public IntrinsicOpConverter<ClockInverterIntrinsicOp> {
256 public:
257  using IntrinsicOpConverter::IntrinsicOpConverter;
258 
259  bool check(GenericIntrinsic gi) override {
260  return gi.hasNInputs(1) || gi.typedInput<ClockType>(0) ||
261  gi.typedOutput<ClockType>() || gi.hasNParam(0);
262  }
263 };
264 
265 class CirctClockDividerConverter : public IntrinsicConverter {
266 public:
267  using IntrinsicConverter::IntrinsicConverter;
268 
269  bool check(GenericIntrinsic gi) override {
270  return gi.hasNInputs(1) || gi.typedInput<ClockType>(0) ||
271  gi.typedOutput<ClockType>() || gi.namedIntParam("POW_2") ||
272  gi.hasNParam(1);
273  }
274 
275  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
276  PatternRewriter &rewriter) override {
277  auto pow2 =
278  gi.getParamValue<IntegerAttr>("POW_2").getValue().getZExtValue();
279 
280  auto pow2Attr = rewriter.getI64IntegerAttr(pow2);
281 
282  rewriter.replaceOpWithNewOp<ClockDividerIntrinsicOp>(
283  gi.op, adaptor.getOperands()[0], pow2Attr);
284  }
285 };
286 
287 template <typename OpTy>
288 class CirctLTLBinaryConverter : public IntrinsicOpConverter<OpTy> {
289 public:
291 
292  bool check(GenericIntrinsic gi) override {
293  return gi.hasNInputs(2) || gi.sizedInput<UIntType>(0, 1) ||
294  gi.sizedInput<UIntType>(1, 1) || gi.sizedOutput<UIntType>(1) ||
295  gi.hasNParam(0);
296  }
297 };
298 
299 template <typename OpTy>
300 class CirctLTLUnaryConverter : public IntrinsicOpConverter<OpTy> {
301 public:
303 
304  bool check(GenericIntrinsic gi) override {
305  return gi.hasNInputs(1) || gi.sizedInput<UIntType>(0, 1) ||
306  gi.sizedOutput<UIntType>(1) || gi.hasNParam(0);
307  }
308 };
309 
310 class CirctLTLDelayConverter : public IntrinsicConverter {
311 public:
312  using IntrinsicConverter::IntrinsicConverter;
313 
314  bool check(GenericIntrinsic gi) override {
315  return gi.hasNInputs(1) || gi.sizedInput<UIntType>(0, 1) ||
316  gi.sizedOutput<UIntType>(1) || gi.namedIntParam("delay") ||
317  gi.namedIntParam("length", true) || gi.hasNParam(1, 1);
318  }
319 
320  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
321  PatternRewriter &rewriter) override {
322  auto getI64Attr = [&](IntegerAttr val) {
323  if (!val)
324  return IntegerAttr();
325  return rewriter.getI64IntegerAttr(val.getValue().getZExtValue());
326  };
327  auto delay = getI64Attr(gi.getParamValue<IntegerAttr>("delay"));
328  auto length = getI64Attr(gi.getParamValue<IntegerAttr>("length"));
329  rewriter.replaceOpWithNewOp<LTLDelayIntrinsicOp>(
330  gi.op, gi.op.getResultTypes(), adaptor.getOperands()[0], delay, length);
331  }
332 };
333 
334 class CirctLTLClockConverter
335  : public IntrinsicOpConverter<LTLClockIntrinsicOp> {
336 public:
337  using IntrinsicOpConverter::IntrinsicOpConverter;
338 
339  bool check(GenericIntrinsic gi) override {
340  return gi.hasNInputs(2) || gi.sizedInput<UIntType>(0, 1) ||
341  gi.typedInput<ClockType>(1) || gi.sizedOutput<UIntType>(1) ||
342  gi.hasNParam(0);
343  }
344 };
345 
346 template <class Op>
347 class CirctVerifConverter : public IntrinsicConverter {
348 public:
349  using IntrinsicConverter::IntrinsicConverter;
350 
351  bool check(GenericIntrinsic gi) override {
352  return gi.hasNInputs(1) || gi.sizedInput<UIntType>(0, 1) ||
353  gi.namedParam("label", true) || gi.hasNParam(0, 1) ||
354  gi.hasNoOutput();
355  }
356 
357  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
358  PatternRewriter &rewriter) override {
359  auto label = gi.getParamValue<StringAttr>("label");
360 
361  rewriter.replaceOpWithNewOp<Op>(gi.op, adaptor.getOperands()[0], label);
362  }
363 };
364 
365 class CirctMux2CellConverter
366  : public IntrinsicOpConverter<Mux2CellIntrinsicOp> {
367  using IntrinsicOpConverter::IntrinsicOpConverter;
368 
369  bool check(GenericIntrinsic gi) override {
370  return gi.hasNInputs(3) || gi.typedInput<UIntType>(0) || gi.hasNParam(0) ||
371  gi.hasOutput();
372  }
373 };
374 
375 class CirctMux4CellConverter
376  : public IntrinsicOpConverter<Mux4CellIntrinsicOp> {
377  using IntrinsicOpConverter::IntrinsicOpConverter;
378 
379  bool check(GenericIntrinsic gi) override {
380  return gi.hasNInputs(5) || gi.typedInput<UIntType>(0) || gi.hasNParam(0) ||
381  gi.hasOutput();
382  }
383 };
384 
385 class CirctHasBeenResetConverter
386  : public IntrinsicOpConverter<HasBeenResetIntrinsicOp> {
387 public:
388  using IntrinsicOpConverter::IntrinsicOpConverter;
389 
390  bool check(GenericIntrinsic gi) override {
391  return gi.hasNInputs(2) || gi.typedInput<ClockType>(0) ||
392  gi.hasResetInput(1) || gi.sizedOutput<UIntType>(1) ||
393  gi.hasNParam(0);
394  }
395 };
396 
397 class CirctProbeConverter : public IntrinsicOpConverter<FPGAProbeIntrinsicOp> {
398 public:
399  using IntrinsicOpConverter::IntrinsicOpConverter;
400 
401  bool check(GenericIntrinsic gi) override {
402  return gi.hasNInputs(2) || gi.typedInput<ClockType>(1) || gi.hasNParam(0) ||
403  gi.hasNoOutput();
404  }
405 };
406 
407 template <class OpTy, bool ifElseFatal = false>
408 class CirctAssertConverter : public IntrinsicConverter {
409 public:
410  using IntrinsicConverter::IntrinsicConverter;
411 
412  bool check(GenericIntrinsic gi) override {
413  return gi.typedInput<ClockType>(0) || gi.sizedInput<UIntType>(1, 1) ||
414  gi.sizedInput<UIntType>(2, 1) ||
415  gi.namedParam("format", /*optional=*/true) ||
416  gi.namedParam("label", /*optional=*/true) ||
417  gi.namedParam("guards", /*optional=*/true) || gi.hasNParam(0, 3) ||
418  gi.hasNoOutput();
419  }
420 
421  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
422  PatternRewriter &rewriter) override {
423  auto format = gi.getParamValue<StringAttr>("format");
424  auto label = gi.getParamValue<StringAttr>("label");
425  auto guards = gi.getParamValue<StringAttr>("guards");
426 
427  auto clock = adaptor.getOperands()[0];
428  auto predicate = adaptor.getOperands()[1];
429  auto enable = adaptor.getOperands()[2];
430 
431  auto substitutions = adaptor.getOperands().drop_front(3);
432  auto name = label ? label.strref() : "";
433  // Message is not optional, so provide empty string if not present.
434  auto message = format ? format : rewriter.getStringAttr("");
435  auto op = rewriter.template replaceOpWithNewOp<OpTy>(
436  gi.op, clock, predicate, enable, message, substitutions, name,
437  /*isConcurrent=*/true);
438  if (guards) {
439  SmallVector<StringRef> guardStrings;
440  guards.strref().split(guardStrings, ';', /*MaxSplit=*/-1,
441  /*KeepEmpty=*/false);
442  rewriter.startOpModification(op);
443  op->setAttr("guards", rewriter.getStrArrayAttr(guardStrings));
444  rewriter.finalizeOpModification(op);
445  }
446 
447  if constexpr (ifElseFatal) {
448  rewriter.startOpModification(op);
449  op->setAttr("format", rewriter.getStringAttr("ifElseFatal"));
450  rewriter.finalizeOpModification(op);
451  }
452  }
453 };
454 
455 class CirctCoverConverter : public IntrinsicConverter {
456 public:
457  using IntrinsicConverter::IntrinsicConverter;
458 
459  bool check(GenericIntrinsic gi) override {
460  return gi.hasNInputs(3) || gi.hasNoOutput() ||
461  gi.typedInput<ClockType>(0) || gi.sizedInput<UIntType>(1, 1) ||
462  gi.sizedInput<UIntType>(2, 1) ||
463  gi.namedParam("label", /*optional=*/true) ||
464  gi.namedParam("guards", /*optional=*/true) || gi.hasNParam(0, 2);
465  }
466 
467  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
468  PatternRewriter &rewriter) override {
469  auto label = gi.getParamValue<StringAttr>("label");
470  auto guards = gi.getParamValue<StringAttr>("guards");
471 
472  auto clock = adaptor.getOperands()[0];
473  auto predicate = adaptor.getOperands()[1];
474  auto enable = adaptor.getOperands()[2];
475 
476  auto name = label ? label.strref() : "";
477  // Empty message string for cover, only 'name' / label.
478  auto message = rewriter.getStringAttr("");
479  auto op = rewriter.replaceOpWithNewOp<CoverOp>(
480  gi.op, clock, predicate, enable, message, ValueRange{}, name,
481  /*isConcurrent=*/true);
482  if (guards) {
483  SmallVector<StringRef> guardStrings;
484  guards.strref().split(guardStrings, ';', /*MaxSplit=*/-1,
485  /*KeepEmpty=*/false);
486  rewriter.startOpModification(op);
487  op->setAttr("guards", rewriter.getStrArrayAttr(guardStrings));
488  rewriter.finalizeOpModification(op);
489  }
490  }
491 };
492 
493 class CirctUnclockedAssumeConverter : public IntrinsicConverter {
494 public:
495  using IntrinsicConverter::IntrinsicConverter;
496 
497  bool check(GenericIntrinsic gi) override {
498  return gi.sizedInput<UIntType>(0, 1) || gi.sizedInput<UIntType>(1, 1) ||
499  gi.namedParam("format", /*optional=*/true) ||
500  gi.namedParam("label", /*optional=*/true) ||
501  gi.namedParam("guards", /*optional=*/true) || gi.hasNParam(0, 3) ||
502  gi.hasNoOutput();
503  }
504 
505  void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
506  PatternRewriter &rewriter) override {
507  auto format = gi.getParamValue<StringAttr>("format");
508  auto label = gi.getParamValue<StringAttr>("label");
509  auto guards = gi.getParamValue<StringAttr>("guards");
510 
511  auto predicate = adaptor.getOperands()[0];
512  auto enable = adaptor.getOperands()[1];
513 
514  auto substitutions = adaptor.getOperands().drop_front(2);
515  auto name = label ? label.strref() : "";
516  // Message is not optional, so provide empty string if not present.
517  auto message = format ? format : rewriter.getStringAttr("");
518  auto op = rewriter.template replaceOpWithNewOp<UnclockedAssumeIntrinsicOp>(
519  gi.op, predicate, enable, message, substitutions, name);
520  if (guards) {
521  SmallVector<StringRef> guardStrings;
522  guards.strref().split(guardStrings, ';', /*MaxSplit=*/-1,
523  /*KeepEmpty=*/false);
524  rewriter.startOpModification(op);
525  op->setAttr("guards", rewriter.getStrArrayAttr(guardStrings));
526  rewriter.finalizeOpModification(op);
527  }
528  }
529 };
530 
531 } // namespace
532 
533 //===----------------------------------------------------------------------===//
534 // FIRRTL intrinsic lowering dialect interface
535 //===----------------------------------------------------------------------===//
536 
538  IntrinsicLowerings &lowering) const {
539  lowering.add<CirctSizeofConverter>("circt.sizeof", "circt_sizeof");
540  lowering.add<CirctIsXConverter>("circt.isX", "circt_isX");
541  lowering.add<CirctPlusArgTestConverter>("circt.plusargs.test",
542  "circt_plusargs_test");
543  lowering.add<CirctPlusArgValueConverter>("circt.plusargs.value",
544  "circt_plusargs_value");
545  lowering.add<CirctClockGateConverter>("circt.clock_gate", "circt_clock_gate");
546  lowering.add<CirctClockInverterConverter>("circt.clock_inv",
547  "circt_clock_inv");
548  lowering.add<CirctClockDividerConverter>("circt.clock_div",
549  "circt_clock_div");
550  lowering.add<CirctLTLBinaryConverter<LTLAndIntrinsicOp>>("circt.ltl.and",
551  "circt_ltl_and");
552  lowering.add<CirctLTLBinaryConverter<LTLOrIntrinsicOp>>("circt.ltl.or",
553  "circt_ltl_or");
554  lowering.add<CirctLTLBinaryConverter<LTLConcatIntrinsicOp>>(
555  "circt.ltl.concat", "circt_ltl_concat");
556  lowering.add<CirctLTLBinaryConverter<LTLImplicationIntrinsicOp>>(
557  "circt.ltl.implication", "circt_ltl_implication");
558  lowering.add<CirctLTLBinaryConverter<LTLDisableIntrinsicOp>>(
559  "circt.ltl.disable", "circt_ltl_disable");
560  lowering.add<CirctLTLUnaryConverter<LTLNotIntrinsicOp>>("circt.ltl.not",
561  "circt_ltl_not");
562  lowering.add<CirctLTLUnaryConverter<LTLEventuallyIntrinsicOp>>(
563  "circt.ltl.eventually", "circt_ltl_eventually");
564 
565  lowering.add<CirctLTLDelayConverter>("circt.ltl.delay", "circt_ltl_delay");
566  lowering.add<CirctLTLClockConverter>("circt.ltl.clock", "circt_ltl_clock");
567 
568  lowering.add<CirctVerifConverter<VerifAssertIntrinsicOp>>(
569  "circt.verif.assert", "circt_verif_assert");
570  lowering.add<CirctVerifConverter<VerifAssumeIntrinsicOp>>(
571  "circt.verif.assume", "circt_verif_assume");
572  lowering.add<CirctVerifConverter<VerifCoverIntrinsicOp>>("circt.verif.cover",
573  "circt_verif_cover");
574  lowering.add<CirctMux2CellConverter>("circt.mux2cell", "circt_mux2cell");
575  lowering.add<CirctMux4CellConverter>("circt.mux4cell", "circt_mux4cell");
576  lowering.add<CirctHasBeenResetConverter>("circt.has_been_reset",
577  "circt_has_been_reset");
578  lowering.add<CirctProbeConverter>("circt.fpga_probe", "circt_fpga_probe");
579  lowering.add<CirctAssertConverter<AssertOp>>("circt.chisel_assert",
580  "circt_chisel_assert");
581  lowering.add<CirctAssertConverter<AssertOp, /*ifElseFatal=*/true>>(
582  "circt.chisel_ifelsefatal", "circt_chisel_ifelsefatal");
583  lowering.add<CirctAssertConverter<AssumeOp>>("circt.chisel_assume",
584  "circt_chisel_assume");
585  lowering.add<CirctCoverConverter>("circt.chisel_cover", "circt_chisel_cover");
586  lowering.add<CirctUnclockedAssumeConverter>("circt.unclocked_assume",
587  "circt_unclocked_assume");
588 }
Base class for Intrinsic Converters.
Lowering helper which collects all intrinsic converters.
FailureOr< size_t > lower(FModuleOp mod, bool allowUnknownIntrinsics=false)
Lowers all intrinsics in a module. Returns number converted or failure.
llvm::DenseMap< StringAttr, std::unique_ptr< IntrinsicConverter > > ConversionMapTy
void add(Args... args)
Registers a converter to one or more intrinsic names.
MLIRContext * context
Reference to the MLIR context.
ConversionMapTy conversions
Mapping from intrinsic names to converters.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const override
Helper class for checking and extracting information from the generic instrinsic op.
ParseResult sizedInput(unsigned n, int32_t size)
mlir::TypedValue< BundleType > getOutputBundle()
T getParamValue(StringRef name)
Get parameter value by name, if present, as requested type.
ParseResult hasResetInput(unsigned n)
ParseResult typedInput(unsigned n)
ParseResult hasNOutputElements(unsigned n)
InFlightDiagnostic emitError()
ParseResult namedIntParam(StringRef paramName, bool optional=false)
ParseResult namedParam(StringRef paramName, bool optional=false)
ParseResult sizedOutput(int32_t size)
ParseResult sizedOutputElement(unsigned n, StringRef name, int32_t size)
ParseResult hasNParam(unsigned n, unsigned c=0)
ParseResult hasOutputElement(unsigned n, StringRef name)
ParseResult hasNInputs(unsigned n)
A dialect interface to provide lowering conversions.
virtual void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const =0
void populateIntrinsicLowerings(IntrinsicLowerings &lowerings) const