mirror of https://github.com/llvm/circt.git
[FIRRTL] Fix handling of new-style NLAs in ExtractInstances (#3345)
Adapt `ExtractInstances` such that it can properly handle the new flavor of NLAs, where non-local annotations would carry a symbol to a hierpath that generally only points at their parent module. The `ExtractInstances` pass had a few assumptions in its implementation about hierpaths pointing at the annotation target op, and each anno having a unique hierpath op associated with it. The implementation can be simplified quite a bit once support for the old-style NLAs can be ripped out. This commit also adds explicit tests to check that the old *and* new style of NLAs are working in parallel. A nasty corner case still exists when extraction requires an NLA to be re-routed because the instance has been extracted past the NLA's original root. If the instance is multiply-extracted, one hierpath gets turned into multiple hierpaths, which will require special handling of *everything* with that hierpath. This commit detects the common case which we can handle and ensures that the hierpath is re-rooted in place, and produces a warning about a potential breakage of hierpath references in the corner case.
This commit is contained in:
parent
9be1e8cd3f
commit
23ae1a7391
|
@ -93,6 +93,17 @@ struct ExtractInstancesPass
|
|||
getOrAddInnerSym(op));
|
||||
}
|
||||
|
||||
/// Create a clone of a `HierPathOp` with a new uniquified name.
|
||||
HierPathOp cloneWithNewNameAndPath(HierPathOp pathOp,
|
||||
ArrayRef<Attribute> newPath) {
|
||||
OpBuilder builder(pathOp);
|
||||
auto newPathOp = builder.cloneWithoutRegions(pathOp);
|
||||
newPathOp.sym_nameAttr(
|
||||
builder.getStringAttr(circuitNamespace.newName(newPathOp.sym_name())));
|
||||
newPathOp.namepathAttr(builder.getArrayAttr(newPath));
|
||||
return newPathOp;
|
||||
}
|
||||
|
||||
bool anythingChanged;
|
||||
bool anyFailures;
|
||||
|
||||
|
@ -431,6 +442,22 @@ void ExtractInstancesPass::collectAnno(InstanceOp inst, Annotation anno) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Find the location in an NLA that corresponds to a given instance (either by
|
||||
/// mentioning exactly the instance, or the instance's parent module). Returns a
|
||||
/// position within the NLA's path, or the length of the path if the instances
|
||||
/// was not found.
|
||||
static unsigned findInstanceInNLA(InstanceOp inst, HierPathOp nla) {
|
||||
unsigned nlaLen = nla.namepath().size();
|
||||
auto instName = inst.inner_symAttr();
|
||||
auto parentName = cast<FModuleOp>(inst->getParentOp()).moduleNameAttr();
|
||||
for (unsigned nlaIdx = 0; nlaIdx < nlaLen; ++nlaIdx) {
|
||||
auto refPart = nla.refPart(nlaIdx);
|
||||
if (nla.modPart(nlaIdx) == parentName && (!refPart || refPart == instName))
|
||||
return nlaIdx;
|
||||
}
|
||||
return nlaLen;
|
||||
}
|
||||
|
||||
/// Move instances in the extraction worklist upwards in the hierarchy. This
|
||||
/// iteratively pushes instances up one level of hierarchy until they have
|
||||
/// arrived in the desired container module.
|
||||
|
@ -528,28 +555,33 @@ void ExtractInstancesPass::extractInstances() {
|
|||
nlaTable.getInstanceNLAs(inst, instanceNLAs);
|
||||
// Map of the NLAs, that are applied to the InstanceOp. That is the NLA
|
||||
// terminates on the InstanceOp.
|
||||
DenseMap<HierPathOp, Annotation> instNonlocalAnnos;
|
||||
// Get the NLAs that are applied on the InstanceOp, since the NLATable does
|
||||
// not return them.
|
||||
DenseMap<HierPathOp, SmallVector<Annotation>> instNonlocalAnnos;
|
||||
AnnotationSet::removeAnnotations(inst, [&](Annotation anno) {
|
||||
// Only consider annotations with a `circt.nonlocal` field.
|
||||
auto nlaName = anno.getMember<FlatSymbolRefAttr>("circt.nonlocal");
|
||||
// Ignore any other anno.
|
||||
if (!nlaName)
|
||||
return false;
|
||||
// Ignore the breadcrumb annos, since NLATable already tracks them.
|
||||
if (!anno.isClass("circt.nonlocal"))
|
||||
if (HierPathOp nla = nlaTable.getNLA(nlaName.getAttr())) {
|
||||
instNonlocalAnnos[nla] = anno;
|
||||
instanceNLAs.insert(nla);
|
||||
}
|
||||
// Track the NLA.
|
||||
if (HierPathOp nla = nlaTable.getNLA(nlaName.getAttr())) {
|
||||
instNonlocalAnnos[nla].push_back(anno);
|
||||
instanceNLAs.insert(nla);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Sort the instance NLAs we've collected by the NLA name to have a
|
||||
// deterministic output.
|
||||
SmallVector<HierPathOp> sortedInstanceNLAs(instanceNLAs.begin(),
|
||||
instanceNLAs.end());
|
||||
llvm::sort(sortedInstanceNLAs,
|
||||
[](auto a, auto b) { return a.sym_name() < b.sym_name(); });
|
||||
|
||||
// Move the original instance one level up such that it is right next to
|
||||
// the instances of the parent module, and wire the instance ports up to
|
||||
// the newly added parent module ports.
|
||||
for (auto *instRecord :
|
||||
instanceGraph->lookup(cast<hw::HWModuleLike>(*parent))->uses()) {
|
||||
auto *instParentNode =
|
||||
instanceGraph->lookup(cast<hw::HWModuleLike>(*parent));
|
||||
for (auto *instRecord : instParentNode->uses()) {
|
||||
auto oldParentInst = cast<InstanceOp>(*instRecord->getInstance());
|
||||
auto newParent = oldParentInst->getParentOfType<FModuleLike>();
|
||||
LLVM_DEBUG(llvm::dbgs() << "- Updating " << oldParentInst << "\n");
|
||||
|
@ -610,23 +642,14 @@ void ExtractInstancesPass::extractInstances() {
|
|||
SmallVector<Annotation> newInstNonlocalAnnos;
|
||||
|
||||
// Update all NLAs that touch the moved instance.
|
||||
for (auto nla : instanceNLAs) {
|
||||
for (auto nla : sortedInstanceNLAs) {
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Updating " << nla << "\n");
|
||||
|
||||
// Find the position of the instance in the NLA path. This is going to
|
||||
// be the position at which we have to modify the NLA.
|
||||
SmallVector<Attribute> nlaPath(nla.namepath().begin(),
|
||||
nla.namepath().end());
|
||||
unsigned nlaIdx;
|
||||
unsigned nlaLen = nlaPath.size();
|
||||
for (nlaIdx = 0; nlaIdx < nlaLen; ++nlaIdx) {
|
||||
auto innerRef = nlaPath[nlaIdx].dyn_cast<InnerRefAttr>();
|
||||
if (!innerRef)
|
||||
continue;
|
||||
if (innerRef.getModule() == parent.moduleNameAttr() &&
|
||||
innerRef.getName() == inst.inner_symAttr())
|
||||
break;
|
||||
}
|
||||
unsigned nlaIdx = findInstanceInNLA(inst, nla);
|
||||
|
||||
// Handle the case where the instance no longer shows up in the NLA's
|
||||
// path. This usually happens if the instance is extracted into multiple
|
||||
|
@ -634,7 +657,7 @@ void ExtractInstancesPass::extractInstances() {
|
|||
// In that case NLAs that were specific to one instance may have been
|
||||
// moved when we arrive at the second instance, and the NLA is already
|
||||
// updated.
|
||||
if (nlaIdx >= nlaLen) {
|
||||
if (nlaIdx >= nlaPath.size()) {
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Instance no longer in path\n");
|
||||
continue;
|
||||
}
|
||||
|
@ -670,26 +693,48 @@ void ExtractInstancesPass::extractInstances() {
|
|||
// was rooted at.
|
||||
if (nlaIdx == 0) {
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Re-rooting " << nlaPath[0] << "\n");
|
||||
assert(nlaPath[0].isa<InnerRefAttr>() &&
|
||||
"head of hierpath must be an InnerRefAttr");
|
||||
nlaPath[0] =
|
||||
InnerRefAttr::get(newParent.moduleNameAttr(),
|
||||
nlaPath[0].cast<InnerRefAttr>().getName());
|
||||
auto builder = OpBuilder::atBlockBegin(getOperation().getBody());
|
||||
|
||||
auto newNla = builder.create<HierPathOp>(
|
||||
newInst.getLoc(), circuitNamespace.newName(nla.sym_name()),
|
||||
builder.getArrayAttr(nlaPath));
|
||||
auto nlaAnno = instNonlocalAnnos.find(nla);
|
||||
if (nlaAnno != instNonlocalAnnos.end()) {
|
||||
Annotation newAnno = nlaAnno->getSecond();
|
||||
newAnno.setMember("circt.nonlocal",
|
||||
FlatSymbolRefAttr::get(newNla.sym_nameAttr()));
|
||||
newInstNonlocalAnnos.push_back(newAnno);
|
||||
if (instParentNode->hasOneUse()) {
|
||||
// Simply update the existing NLA since our parent is only
|
||||
// instantiated once, and we therefore are not creating multiple
|
||||
// instances through the extraction.
|
||||
nlaTable.erase(nla);
|
||||
nla.namepathAttr(builder.getArrayAttr(nlaPath));
|
||||
for (auto anno : instNonlocalAnnos.lookup(nla))
|
||||
newInstNonlocalAnnos.push_back(anno);
|
||||
nlaTable.addNLA(nla);
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Modified to " << nla << "\n");
|
||||
} else {
|
||||
// Since we are extracting to multiple parent locations, create a
|
||||
// new NLA for each instantiation site.
|
||||
auto newNla = cloneWithNewNameAndPath(nla, nlaPath);
|
||||
for (auto anno : instNonlocalAnnos.lookup(nla)) {
|
||||
anno.setMember("circt.nonlocal",
|
||||
FlatSymbolRefAttr::get(newNla.sym_nameAttr()));
|
||||
newInstNonlocalAnnos.push_back(anno);
|
||||
}
|
||||
|
||||
nlaTable.addNLA(newNla);
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Created " << newNla << "\n");
|
||||
// CAVEAT(fschuiki): This results in annotations in the subhierarchy
|
||||
// below `inst` with the old NLA symbol name, instead of those
|
||||
// annotations duplicated for each of the newly-created NLAs. This
|
||||
// shouldn't come up in our current use cases, but is a weakness of
|
||||
// the current implementation. Instead, we should keep an NLA
|
||||
// replication table that we fill with mappings from old NLA names
|
||||
// to lists of new NLA names. A post-pass would then traverse the
|
||||
// entire subhierarchy and go replicate all annotations with the old
|
||||
// names.
|
||||
inst.emitWarning("extraction of instance `")
|
||||
<< inst.instanceName()
|
||||
<< "` could break non-local annotations rooted at `"
|
||||
<< parent.moduleName() << "`";
|
||||
}
|
||||
|
||||
nlaTable.erase(nla);
|
||||
nlasToRemove.insert(nla);
|
||||
nlaTable.addNLA(newNla);
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Created " << newNla << "\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -700,9 +745,7 @@ void ExtractInstancesPass::extractInstances() {
|
|||
// its path. If that is the case we have to convert the NLA into a
|
||||
// regular local annotation.
|
||||
if (nlaPath.size() == 2) {
|
||||
auto nlaAnno = instNonlocalAnnos.find(nla);
|
||||
if (nlaAnno != instNonlocalAnnos.end()) {
|
||||
auto anno = nlaAnno->getSecond();
|
||||
for (auto anno : instNonlocalAnnos.lookup(nla)) {
|
||||
anno.removeMember("circt.nonlocal");
|
||||
newInstNonlocalAnnos.push_back(anno);
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Converted to local "
|
||||
|
@ -717,20 +760,39 @@ void ExtractInstancesPass::extractInstances() {
|
|||
// the `nlaIdx` points at `OldParent::BB`. To make our lives easier,
|
||||
// since we know that `nlaIdx` is a `InnerRefAttr`, we'll modify
|
||||
// `OldParent::BB` to be `NewParent::BB` and delete `NewParent::X`.
|
||||
auto newInnerRef = InnerRefAttr::get(
|
||||
nlaPath[nlaIdx - 1].cast<InnerRefAttr>().getModule(),
|
||||
newInst.inner_symAttr());
|
||||
StringAttr parentName =
|
||||
nlaPath[nlaIdx - 1].cast<InnerRefAttr>().getModule();
|
||||
Attribute newRef;
|
||||
if (nlaPath[nlaIdx].isa<InnerRefAttr>())
|
||||
newRef = InnerRefAttr::get(parentName, newInst.inner_symAttr());
|
||||
else
|
||||
newRef = FlatSymbolRefAttr::get(parentName);
|
||||
LLVM_DEBUG(llvm::dbgs()
|
||||
<< " - Replacing " << nlaPath[nlaIdx - 1] << " and "
|
||||
<< nlaPath[nlaIdx] << " with " << newInnerRef << "\n");
|
||||
nlaPath[nlaIdx] = newInnerRef;
|
||||
<< nlaPath[nlaIdx] << " with " << newRef << "\n");
|
||||
nlaPath[nlaIdx] = newRef;
|
||||
nlaPath.erase(nlaPath.begin() + nlaIdx - 1);
|
||||
nla.namepathAttr(builder.getArrayAttr(nlaPath));
|
||||
auto nlaAnno = instNonlocalAnnos.find(nla);
|
||||
if (nlaAnno != instNonlocalAnnos.end())
|
||||
newInstNonlocalAnnos.push_back(nlaAnno->getSecond());
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Modified to " << nla << "\n");
|
||||
if (newRef.isa<FlatSymbolRefAttr>()) {
|
||||
// Since the original NLA ended at the instance's parent module, there
|
||||
// is no guarantee that the instance is the sole user of the NLA (as
|
||||
// opposed to the original NLA explicitly naming the instance). Create
|
||||
// a new NLA.
|
||||
auto newNla = cloneWithNewNameAndPath(nla, nlaPath);
|
||||
nlaTable.addNLA(newNla);
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Created " << newNla << "\n");
|
||||
for (auto anno : instNonlocalAnnos.lookup(nla)) {
|
||||
anno.setMember("circt.nonlocal",
|
||||
FlatSymbolRefAttr::get(newNla.sym_nameAttr()));
|
||||
newInstNonlocalAnnos.push_back(anno);
|
||||
}
|
||||
} else {
|
||||
nla.namepathAttr(builder.getArrayAttr(nlaPath));
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Modified to " << nla << "\n");
|
||||
for (auto anno : instNonlocalAnnos.lookup(nla))
|
||||
newInstNonlocalAnnos.push_back(anno);
|
||||
}
|
||||
|
||||
// No update to NLATable required, since it will be deleted from the
|
||||
// parent, and it should already exist in the new parent module.
|
||||
continue;
|
||||
|
@ -843,34 +905,30 @@ void ExtractInstancesPass::groupInstances() {
|
|||
// be the position at which we have to modify the NLA.
|
||||
SmallVector<Attribute> nlaPath(nla.namepath().begin(),
|
||||
nla.namepath().end());
|
||||
unsigned nlaIdx;
|
||||
unsigned nlaLen = nlaPath.size();
|
||||
for (nlaIdx = 0; nlaIdx < nlaLen; ++nlaIdx) {
|
||||
auto innerRef = nlaPath[nlaIdx].dyn_cast<InnerRefAttr>();
|
||||
if (!innerRef)
|
||||
continue;
|
||||
if (innerRef.getModule() == parent.moduleNameAttr() &&
|
||||
innerRef.getName() == inst.inner_symAttr())
|
||||
break;
|
||||
}
|
||||
assert(nlaIdx < nlaLen && "instance not found in its own NLA");
|
||||
unsigned nlaIdx = findInstanceInNLA(inst, nla);
|
||||
assert(nlaIdx < nlaPath.size() && "instance not found in its own NLA");
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Position " << nlaIdx << "\n");
|
||||
|
||||
// The relevant part of the NLA is of the form `Top::bb`, which we want
|
||||
// to expand to `Top::wrapperInst` and `Wrapper::bb`.
|
||||
auto ref1 = InnerRefAttr::get(
|
||||
nlaPath[nlaIdx].cast<InnerRefAttr>().getModule(), wrapperInstName);
|
||||
auto ref2 =
|
||||
InnerRefAttr::get(builder.getStringAttr(wrapperName),
|
||||
nlaPath[nlaIdx].cast<InnerRefAttr>().getName());
|
||||
auto wrapperNameAttr = builder.getStringAttr(wrapperName);
|
||||
auto ref1 = InnerRefAttr::get(parent.moduleNameAttr(), wrapperInstName);
|
||||
Attribute ref2;
|
||||
if (auto innerRef = nlaPath[nlaIdx].dyn_cast<InnerRefAttr>())
|
||||
ref2 = InnerRefAttr::get(wrapperNameAttr, innerRef.getName());
|
||||
else
|
||||
ref2 = FlatSymbolRefAttr::get(wrapperNameAttr);
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Expanding " << nlaPath[nlaIdx]
|
||||
<< " to (" << ref1 << ", " << ref2 << ")\n");
|
||||
nlaPath[nlaIdx] = ref1;
|
||||
nlaPath.insert(nlaPath.begin() + nlaIdx + 1, ref2);
|
||||
// CAVEAT: This is likely to conflict with additional users of `nla`
|
||||
// that have nothing to do with this instance. Might need some NLATable
|
||||
// machinery at some point to allow for these things to be updated.
|
||||
nla.namepathAttr(builder.getArrayAttr(nlaPath));
|
||||
LLVM_DEBUG(llvm::dbgs() << " - Modified to " << nla << "\n");
|
||||
// Add the NLA to the wrapper module.
|
||||
nlaTable.addNLAtoModule(nla, ref2.getModule());
|
||||
nlaTable.addNLAtoModule(nla, wrapperNameAttr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,17 +65,27 @@ firrtl.circuit "ExtractBlackBoxesSimple" attributes {annotations = [{class = "fi
|
|||
|
||||
// CHECK: firrtl.circuit "ExtractBlackBoxesSimple2"
|
||||
firrtl.circuit "ExtractBlackBoxesSimple2" attributes {annotations = [{class = "firrtl.transforms.BlackBoxTargetDirAnno", targetDir = "BlackBoxes"}]} {
|
||||
// CHECK: firrtl.hierpath @nla_1{{.*}} [@ExtractBlackBoxesSimple2::@bb, @MyBlackBox]
|
||||
// CHECK-NOT: firrtl.hierpath @nla_2
|
||||
// CHECK-NOT: firrtl.hierpath @nla_3
|
||||
firrtl.hierpath @nla_1 [@BBWrapper::@bb, @MyBlackBox]
|
||||
firrtl.hierpath @nla_2 [@DUTModule::@mod, @BBWrapper::@bb]
|
||||
firrtl.hierpath @nla_3 [@ExtractBlackBoxesSimple2::@dut, @DUTModule::@mod, @BBWrapper::@bb]
|
||||
// Old style NLAs
|
||||
firrtl.hierpath @nla_old1 [@DUTModule::@mod, @BBWrapper::@bb]
|
||||
firrtl.hierpath @nla_old2 [@ExtractBlackBoxesSimple2::@dut, @DUTModule::@mod, @BBWrapper::@bb]
|
||||
// New style NLAs on extracted instance
|
||||
firrtl.hierpath @nla_on1 [@DUTModule::@mod, @BBWrapper]
|
||||
firrtl.hierpath @nla_on2 [@ExtractBlackBoxesSimple2::@dut, @DUTModule::@mod, @BBWrapper]
|
||||
// New style NLAs through extracted instance
|
||||
firrtl.hierpath @nla_thru1 [@BBWrapper::@bb, @MyBlackBox]
|
||||
firrtl.hierpath @nla_thru2 [@DUTModule::@mod, @BBWrapper::@bb, @MyBlackBox]
|
||||
firrtl.hierpath @nla_thru3 [@ExtractBlackBoxesSimple2::@dut, @DUTModule::@mod, @BBWrapper::@bb, @MyBlackBox]
|
||||
// CHECK: firrtl.hierpath [[THRU1:@nla_thru1]] [@ExtractBlackBoxesSimple2::@bb, @MyBlackBox]
|
||||
// CHECK: firrtl.hierpath [[THRU2:@nla_thru2]] [@ExtractBlackBoxesSimple2::@bb, @MyBlackBox]
|
||||
// CHECK: firrtl.hierpath [[THRU3:@nla_thru3]] [@ExtractBlackBoxesSimple2::@bb, @MyBlackBox]
|
||||
|
||||
// Annotation on the extmodule itself
|
||||
// CHECK-LABEL: firrtl.extmodule private @MyBlackBox
|
||||
firrtl.extmodule private @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>) attributes {annotations = [
|
||||
{class = "sifive.enterprise.firrtl.ExtractBlackBoxAnnotation", filename = "BlackBoxes.txt", prefix = "prefix"},
|
||||
{circt.nonlocal = @nla_1, class = "DummyA"}
|
||||
{circt.nonlocal = @nla_thru1, class = "Thru1"},
|
||||
{circt.nonlocal = @nla_thru2, class = "Thru2"},
|
||||
{circt.nonlocal = @nla_thru3, class = "Thru3"}
|
||||
], defname = "MyBlackBox"}
|
||||
// Annotation will be on the instance
|
||||
// CHECK-LABEL: firrtl.extmodule private @MyBlackBox2
|
||||
|
@ -90,8 +100,10 @@ firrtl.circuit "ExtractBlackBoxesSimple2" attributes {annotations = [{class = "f
|
|||
// CHECK-NOT: firrtl.instance bb @MyBlackBox
|
||||
// CHECK-NOT: firrtl.instance bb2 @MyBlackBox2
|
||||
%bb_in, %bb_out = firrtl.instance bb sym @bb {annotations = [
|
||||
{circt.nonlocal = @nla_2, class = "DummyB"},
|
||||
{circt.nonlocal = @nla_3, class = "DummyC"}
|
||||
{circt.nonlocal = @nla_old1, class = "Old1"},
|
||||
{circt.nonlocal = @nla_old2, class = "Old2"},
|
||||
{circt.nonlocal = @nla_on1, class = "On1"},
|
||||
{circt.nonlocal = @nla_on2, class = "On2"}
|
||||
]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
%bb2_in, %bb2_out = firrtl.instance bb2 {annotations = [{class = "sifive.enterprise.firrtl.ExtractBlackBoxAnnotation", filename = "BlackBoxes.txt", prefix = "prefix"}]} @MyBlackBox2(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
// CHECK: firrtl.connect %out, %prefix_0_out
|
||||
|
@ -125,7 +137,7 @@ firrtl.circuit "ExtractBlackBoxesSimple2" attributes {annotations = [{class = "f
|
|||
// CHECK: %dut_in, %dut_out, %dut_prefix_0_in, %dut_prefix_0_out, %dut_prefix_1_in, %dut_prefix_1_out = firrtl.instance dut
|
||||
// CHECK-NOT: annotations =
|
||||
// CHECK-SAME: sym {{@.+}} @DUTModule
|
||||
// CHECK-NEXT: %bb_in, %bb_out = firrtl.instance bb sym [[BB_SYM:@.+]] {annotations = [{class = "DummyB"}, {class = "DummyC"}]} @MyBlackBox
|
||||
// CHECK-NEXT: %bb_in, %bb_out = firrtl.instance bb sym [[BB_SYM:@.+]] {annotations = [{class = "Old1"}, {class = "On1"}, {class = "Old2"}, {class = "On2"}]} @MyBlackBox
|
||||
// CHECK-NEXT: firrtl.strictconnect %bb_in, %dut_prefix_1_in
|
||||
// CHECK-NEXT: firrtl.strictconnect %dut_prefix_1_out, %bb_out
|
||||
// CHECK-NEXT: %bb2_in, %bb2_out = firrtl.instance bb2 sym [[BB2_SYM:@.+]] @MyBlackBox2
|
||||
|
@ -153,25 +165,43 @@ firrtl.circuit "ExtractBlackBoxesSimple2" attributes {annotations = [{class = "f
|
|||
|
||||
// CHECK: firrtl.circuit "ExtractBlackBoxesIntoDUTSubmodule"
|
||||
firrtl.circuit "ExtractBlackBoxesIntoDUTSubmodule" {
|
||||
// CHECK-LABEL: firrtl.hierpath @nla_1 [
|
||||
// CHECK-LABEL: firrtl.hierpath @nla_new_0 [
|
||||
// CHECK-SAME: @ExtractBlackBoxesIntoDUTSubmodule::@tb
|
||||
// CHECK-SAME: @TestHarness::@dut
|
||||
// CHECK-SAME: @DUTModule::@BlackBoxes
|
||||
// CHECK-SAME: @BlackBoxes
|
||||
// CHECK-SAME: ]
|
||||
// CHECK-LABEL: firrtl.hierpath @nla_new_1 [
|
||||
// CHECK-SAME: @ExtractBlackBoxesIntoDUTSubmodule::@tb
|
||||
// CHECK-SAME: @TestHarness::@dut
|
||||
// CHECK-SAME: @DUTModule::@BlackBoxes
|
||||
// CHECK-SAME: @BlackBoxes
|
||||
// CHECK-SAME: ]
|
||||
firrtl.hierpath @nla_new [
|
||||
@ExtractBlackBoxesIntoDUTSubmodule::@tb,
|
||||
@TestHarness::@dut,
|
||||
@DUTModule::@mod,
|
||||
@BBWrapper
|
||||
]
|
||||
// CHECK-LABEL: firrtl.hierpath @nla_old1 [
|
||||
// CHECK-SAME: @ExtractBlackBoxesIntoDUTSubmodule::@tb
|
||||
// CHECK-SAME: @TestHarness::@dut
|
||||
// CHECK-SAME: @DUTModule::@BlackBoxes
|
||||
// CHECK-SAME: @BlackBoxes::@bb1
|
||||
// CHECK-SAME: ]
|
||||
firrtl.hierpath @nla_1 [
|
||||
firrtl.hierpath @nla_old1 [
|
||||
@ExtractBlackBoxesIntoDUTSubmodule::@tb,
|
||||
@TestHarness::@dut,
|
||||
@DUTModule::@mod,
|
||||
@BBWrapper::@bb1
|
||||
]
|
||||
// CHECK-LABEL: firrtl.hierpath @nla_2 [
|
||||
// CHECK-LABEL: firrtl.hierpath @nla_old2 [
|
||||
// CHECK-SAME: @ExtractBlackBoxesIntoDUTSubmodule::@tb
|
||||
// CHECK-SAME: @TestHarness::@dut
|
||||
// CHECK-SAME: @DUTModule::@BlackBoxes
|
||||
// CHECK-SAME: @BlackBoxes::@bb2
|
||||
// CHECK-SAME: ]
|
||||
firrtl.hierpath @nla_2 [
|
||||
firrtl.hierpath @nla_old2 [
|
||||
@ExtractBlackBoxesIntoDUTSubmodule::@tb,
|
||||
@TestHarness::@dut,
|
||||
@DUTModule::@mod,
|
||||
|
@ -179,8 +209,8 @@ firrtl.circuit "ExtractBlackBoxesIntoDUTSubmodule" {
|
|||
]
|
||||
firrtl.extmodule private @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>) attributes {annotations = [{class = "sifive.enterprise.firrtl.ExtractBlackBoxAnnotation", dest = "BlackBoxes", filename = "BlackBoxes.txt", prefix = "bb"}], defname = "MyBlackBox"}
|
||||
firrtl.module private @BBWrapper(in %in: !firrtl.uint<8>, out %out: !firrtl.uint<8>) {
|
||||
%bb1_in, %bb1_out = firrtl.instance bb1 sym @bb1 {annotations = [{circt.nonlocal = @nla_1, class = "Dummy1"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
%bb2_in, %bb2_out = firrtl.instance bb2 sym @bb2 {annotations = [{circt.nonlocal = @nla_2, class = "Dummy2"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
%bb1_in, %bb1_out = firrtl.instance bb1 sym @bb1 {annotations = [{circt.nonlocal = @nla_old1, class = "Dummy1"}, {circt.nonlocal = @nla_new, class = "Dummy3"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
%bb2_in, %bb2_out = firrtl.instance bb2 sym @bb2 {annotations = [{circt.nonlocal = @nla_old2, class = "Dummy2"}, {circt.nonlocal = @nla_new, class = "Dummy4"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
firrtl.connect %out, %bb2_out : !firrtl.uint<8>, !firrtl.uint<8>
|
||||
firrtl.connect %bb2_in, %bb1_out : !firrtl.uint<8>, !firrtl.uint<8>
|
||||
firrtl.connect %bb1_in, %in : !firrtl.uint<8>, !firrtl.uint<8>
|
||||
|
@ -191,10 +221,10 @@ firrtl.circuit "ExtractBlackBoxesIntoDUTSubmodule" {
|
|||
// CHECK-SAME: in %bb_1_in: !firrtl.uint<8>
|
||||
// CHECK-SAME: out %bb_1_out: !firrtl.uint<8>
|
||||
// CHECK-SAME: ) {
|
||||
// CHECK-NEXT: %bb2_in, %bb2_out = firrtl.instance bb2 sym [[BB2_SYM:@.+]] {annotations = [{circt.nonlocal = @nla_2, class = "Dummy2"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
// CHECK-NEXT: %bb2_in, %bb2_out = firrtl.instance bb2 sym [[BB2_SYM:@.+]] {annotations = [{circt.nonlocal = @nla_new_0, class = "Dummy4"}, {circt.nonlocal = @nla_old2, class = "Dummy2"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
// CHECK-NEXT: firrtl.strictconnect %bb2_in, %bb_0_in : !firrtl.uint<8>
|
||||
// CHECK-NEXT: firrtl.strictconnect %bb_0_out, %bb2_out : !firrtl.uint<8>
|
||||
// CHECK-NEXT: %bb1_in, %bb1_out = firrtl.instance bb1 sym [[BB1_SYM:@.+]] {annotations = [{circt.nonlocal = @nla_1, class = "Dummy1"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
// CHECK-NEXT: %bb1_in, %bb1_out = firrtl.instance bb1 sym [[BB1_SYM:@.+]] {annotations = [{circt.nonlocal = @nla_new_1, class = "Dummy3"}, {circt.nonlocal = @nla_old1, class = "Dummy1"}]} @MyBlackBox(in in: !firrtl.uint<8>, out out: !firrtl.uint<8>)
|
||||
// CHECK-NEXT: firrtl.strictconnect %bb1_in, %bb_1_in : !firrtl.uint<8>
|
||||
// CHECK-NEXT: firrtl.strictconnect %bb_1_out, %bb1_out : !firrtl.uint<8>
|
||||
// CHECK-NEXT: }
|
||||
|
|
Loading…
Reference in New Issue