@@ -81,7 +81,6 @@ struct ModuleLoweringState {
81
81
82
82
struct FragmentInfo {
83
83
bool needsRegFragment = false ;
84
- bool needsMemFragment = false ;
85
84
} fragment;
86
85
87
86
HWModuleOp module;
@@ -591,9 +590,11 @@ void SeqToSVPass::runOnOperation() {
591
590
// Identify memories and group them by module.
592
591
auto uniqueMems = memLowering.collectMemories (modules);
593
592
MapVector<HWModuleOp, SmallVector<FirMemLowering::MemoryConfig>> memsByModule;
593
+ SmallVector<HWModuleGeneratedOp> generatedModules;
594
594
for (auto &[config, memOps] : uniqueMems) {
595
595
// Create the `HWModuleGeneratedOp`s for each unique configuration.
596
596
auto genOp = memLowering.createMemoryModule (config, memOps);
597
+ generatedModules.push_back (genOp);
597
598
598
599
// Group memories by their parent module for parallelism.
599
600
for (auto memOp : memOps) {
@@ -630,10 +631,10 @@ void SeqToSVPass::runOnOperation() {
630
631
631
632
if (auto *it = memsByModule.find (module); it != memsByModule.end ()) {
632
633
memLowering.lowerMemoriesInModule (module, it->second );
633
- if (!disableMemRandomization) {
634
- state.fragment .needsMemFragment = true ;
635
- }
634
+ // Generated memories need register randomization since `HWMemSimImpl`
635
+ // may add registers.
636
636
needsMemRandomization = true ;
637
+ needsRegRandomization = true ;
637
638
}
638
639
return state.immutableValueLowering .lower ();
639
640
});
@@ -650,8 +651,8 @@ void SeqToSVPass::runOnOperation() {
650
651
651
652
for (auto &[_, state] : moduleLoweringStates) {
652
653
const auto &info = state.fragment ;
653
- if (!info. needsRegFragment && !info. needsMemFragment ) {
654
- // If neither is emitted, just skip it.
654
+ // Do not add fragments if not needed.
655
+ if (!info. needsRegFragment ) {
655
656
continue ;
656
657
}
657
658
@@ -661,16 +662,28 @@ void SeqToSVPass::runOnOperation() {
661
662
module->getAttrOfType <ArrayAttr>(emit::getFragmentsAttrName ()))
662
663
fragmentAttrs = llvm::to_vector (others);
663
664
664
- if (info.needsRegFragment )
665
+ if (info.needsRegFragment ) {
665
666
fragmentAttrs.push_back (randomInitRegFragmentName);
666
- if (info.needsMemFragment )
667
- fragmentAttrs.push_back (randomInitMemFragmentName);
668
- fragmentAttrs.push_back (randomInitFragmentName);
667
+ fragmentAttrs.push_back (randomInitFragmentName);
668
+ }
669
669
670
670
module->setAttr (emit::getFragmentsAttrName (),
671
671
ArrayAttr::get (context, fragmentAttrs));
672
672
}
673
673
674
+ // Set fragments for generated modules.
675
+ SmallVector<Attribute> genModFragments;
676
+ if (!disableRegRandomization)
677
+ genModFragments.push_back (randomInitRegFragmentName);
678
+ if (!disableMemRandomization)
679
+ genModFragments.push_back (randomInitMemFragmentName);
680
+ if (!genModFragments.empty ()) {
681
+ genModFragments.push_back (randomInitFragmentName);
682
+ auto fragmentAttr = ArrayAttr::get (context, genModFragments);
683
+ for (auto genOp : generatedModules)
684
+ genOp->setAttr (emit::getFragmentsAttrName (), fragmentAttr);
685
+ }
686
+
674
687
// Mark all ops which can have clock types as illegal.
675
688
SeqToSVTypeConverter typeConverter;
676
689
ConversionTarget target (*context);
0 commit comments