@@ -352,6 +352,140 @@ static APInt getMaxSignedValue(unsigned bitWidth) {
352
352
return bitWidth > 0 ? APInt::getSignedMaxValue (bitWidth) : APInt ();
353
353
}
354
354
355
+ // NOLINTNEXTLINE(misc-no-recursion)
356
+ static Value coerceSource (PatternRewriter &rewriter, Location &loc,
357
+ FIRRTLBaseType targetType, FIRRTLBaseType sourceType,
358
+ Value source) {
359
+ if (sourceType == targetType)
360
+ return source;
361
+
362
+ auto srcType = sourceType.getAnonymousType ();
363
+ auto tgtType = targetType.getAnonymousType ();
364
+ if (srcType == tgtType)
365
+ return source;
366
+
367
+ auto srcBundleType = dyn_cast<BundleType>(srcType);
368
+ auto tgtBundleType = dyn_cast<BundleType>(tgtType);
369
+ if (srcBundleType && tgtBundleType) {
370
+ auto n = tgtBundleType.getNumElements ();
371
+ SmallVector<Value> elems;
372
+ elems.reserve (n);
373
+ for (unsigned i = 0 ; i < n; ++i) {
374
+ auto srcElemType = srcBundleType.getElementType (i);
375
+ auto tgtElemType = tgtBundleType.getElementType (i);
376
+ auto srcElem = rewriter.create <SubfieldOp>(loc, source, i);
377
+ auto elem =
378
+ coerceSource (rewriter, loc, tgtElemType, srcElemType, srcElem);
379
+ elems.push_back (elem);
380
+ }
381
+ return rewriter.create <BundleCreateOp>(loc, tgtBundleType, elems);
382
+ }
383
+
384
+ auto srcVectorType = dyn_cast<FVectorType>(srcType);
385
+ auto tgtVectorType = dyn_cast<FVectorType>(tgtType);
386
+ if (srcVectorType && tgtVectorType) {
387
+ auto srcElemType = srcVectorType.getElementType ();
388
+ auto tgtElemType = tgtVectorType.getElementType ();
389
+ auto n = tgtVectorType.getNumElements ();
390
+ SmallVector<Value> elems;
391
+ elems.reserve (n);
392
+ for (unsigned i = 0 ; i < n; ++i) {
393
+ auto srcElem = rewriter.create <SubindexOp>(loc, source, i);
394
+ auto elem =
395
+ coerceSource (rewriter, loc, tgtElemType, srcElemType, srcElem);
396
+ elems.push_back (elem);
397
+ }
398
+ return rewriter.create <VectorCreateOp>(loc, tgtVectorType, elems);
399
+ }
400
+
401
+ auto srcIntType = dyn_cast<IntType>(srcType);
402
+ auto tgtIntType = dyn_cast<IntType>(tgtType);
403
+ if (srcIntType && tgtIntType) {
404
+ auto srcWidth = srcIntType.getBitWidthOrSentinel ();
405
+ auto tgtWidth = tgtIntType.getBitWidthOrSentinel ();
406
+ if (tgtWidth < srcWidth) {
407
+ auto delta = srcWidth - tgtWidth;
408
+ Value value = rewriter.create <TailPrimOp>(loc, source, delta);
409
+ if (tgtIntType.isSigned ())
410
+ value = rewriter.create <AsSIntPrimOp>(loc, value);
411
+ return value;
412
+ }
413
+
414
+ if (tgtWidth > srcWidth)
415
+ source = rewriter.create <PadPrimOp>(loc, source, tgtWidth);
416
+ if (tgtIntType.isSigned () && !srcIntType.isSigned ())
417
+ return rewriter.create <AsSIntPrimOp>(loc, source);
418
+ if (!tgtIntType.isSigned () && srcIntType.isSigned ())
419
+ return rewriter.create <AsUIntPrimOp>(loc, source);
420
+ return source;
421
+ }
422
+
423
+ return nullptr ;
424
+ }
425
+
426
+ // / Emit a coercion from a value to a target type. Returns nullptr if the
427
+ // / coercion is not possible. The resulting value is a non-aliasing source
428
+ // / value. As such, we can only emit coercions for passive types.
429
+ static Value coerceSource (PatternRewriter &rewriter, Location loc,
430
+ Type targetType, Value source) {
431
+ Type sourceType = source.getType ();
432
+
433
+ // If the types are syntactically equal, no action is needed.
434
+ if (sourceType == targetType)
435
+ return source;
436
+
437
+ // If either of the types are not FIRRTL base types, we cannot coerce.
438
+ auto sourceFType = type_cast<FIRRTLBaseType>(sourceType);
439
+ auto targetFType = type_cast<FIRRTLBaseType>(targetType);
440
+ if (!sourceFType || !targetFType)
441
+ return nullptr ;
442
+
443
+ // After type_cast resolves type-aliases, the underlying types may be the
444
+ // same. If they are, no action is needed.
445
+ if (sourceFType == targetFType)
446
+ return source;
447
+
448
+ // One last shot at avoiding coercion: recursively unfold type-aliases and
449
+ // check again for syntactic equality. If they are, no action is needed.
450
+ if (sourceFType.getAnonymousType () == targetFType.getAnonymousType ())
451
+ return source;
452
+
453
+ // OK, some coercion is necessary. Check if it's possible.
454
+
455
+ // Give up if either side contains const. Eventually, const will be removed
456
+ // from the compiler.
457
+ if (sourceFType.containsConst () || targetFType.containsConst ())
458
+ return nullptr ;
459
+
460
+ // We can only coerce when all the involved widths are known. We can usually
461
+ // truncate or extend the source value to match the destination, but if either
462
+ // src or dst has an uninferred width, we don't know which way to go.
463
+ if (sourceFType.hasUninferredWidth () || targetFType.hasUninferredWidth ())
464
+ return nullptr ;
465
+
466
+ // Similar story for resets...
467
+ if (sourceFType.hasUninferredReset () || targetFType.hasUninferredReset ())
468
+ return nullptr ;
469
+
470
+ // Give up if the target is not passive. If we have to coerce the source
471
+ // value, the coercion ops will produce a nonaliasing source value, which
472
+ // prevents us from properly coercing to a correct non-passive value.
473
+ if (!targetFType.isPassive () || targetFType.containsAnalog ())
474
+ return nullptr ;
475
+
476
+ // After the earlier recursive checks, we can defer to equivalence checking.
477
+ if (!areTypesEquivalent (targetFType, sourceFType))
478
+ return nullptr ;
479
+
480
+ auto result = coerceSource (rewriter, loc, targetFType, sourceFType, source);
481
+
482
+ // Final sanity check: ensure the result will make matchingconnect happy.
483
+ if (result)
484
+ assert (areTypesAnonymousEquivalent (targetType, result.getType ()));
485
+
486
+ return result;
487
+ }
488
+
355
489
// ===----------------------------------------------------------------------===//
356
490
// Fold Hooks
357
491
// ===----------------------------------------------------------------------===//
@@ -2269,14 +2403,15 @@ canonicalizeRegResetWithOneReset(RegResetOp reg, PatternRewriter &rewriter) {
2269
2403
if (!isDefinedByOneConstantOp (reg.getResetSignal ()))
2270
2404
return failure ();
2271
2405
2272
- auto resetValue = reg.getResetValue ();
2273
- if (reg.getType (0 ) != resetValue.getType ())
2406
+ auto value =
2407
+ coerceSource (rewriter, reg.getLoc (), reg.getType (0 ), reg.getResetValue ());
2408
+ if (!value)
2274
2409
return failure ();
2275
2410
2276
2411
// Ignore 'passthrough'.
2277
2412
(void )dropWrite (rewriter, reg->getResult (0 ), {});
2278
2413
replaceOpWithNewOpAndCopyName<NodeOp>(
2279
- rewriter, reg, resetValue , reg.getNameAttr (), reg.getNameKind (),
2414
+ rewriter, reg, value , reg.getNameAttr (), reg.getNameKind (),
2280
2415
reg.getAnnotationsAttr (), reg.getInnerSymAttr (), reg.getForceable ());
2281
2416
return success ();
2282
2417
}
0 commit comments