[FIRRTL] Handle memTap on Memories excluded from MemToReg (#3102)

Handle MemTap annotation on Memories that are excluded from `MemToRegOfVec`
 transformation. 
This fixes an issue with the commit #26276bf which updated this pass to only
 work on registers that were generated by `MemToRegOfVec` transformation. The
 assumption here was that every MemOp, should either be lowered to registers
 by `MemToRegOfVec` or to `FMemModuleOp` by `LowerMemory`. So, the GCT pass
 shouldn't expect to see a `MemOp`. 

But yesterday's commit #b923963, updated the `MemToRegOfVec` to exclude
 testbench memories but made the incorrect assumption that testbench memories
 wouldn't have memtap annotations. 
Finally this commit fixes that assumption and handles the Memtap annotation on
 `MemOp`s.
This commit is contained in:
Prithayan Barua 2022-05-11 07:46:57 -07:00 committed by GitHub
parent 0a542f9694
commit ddb1f6e8bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 6 deletions

View File

@ -904,6 +904,35 @@ void GrandCentralTapsPass::processAnnotation(AnnotatedPort &portAnno,
portWiring.push_back(std::move(wiring));
return;
}
// This handles the case when the memtap is on a MemOp, which shouldn't have
// the PortID attribute. Lookup the op without the portID key.
if (auto *op = tappedOps.lookup({key.first, {}})) {
// Extract the memory location we're supposed to access.
auto word = portAnno.anno.getMember<IntegerAttr>("portID");
if (!word) {
blackBox.extModule.emitError("MemTapAnnotation annotation on port ")
<< portName << " missing \"word\" attribute";
signalPassFailure();
return;
}
// Formulate a hierarchical reference into the memory.
// CAVEAT: This just assumes that the memory will map to something that
// can be indexed in the final Verilog. If the memory gets turned into
// an instance of some sort, we lack the information necessary to go in
// and access individual elements of it. This will break horribly since
// we generate memory impls out-of-line already, and memories coming
// from an external generator are even worse. This needs a special node
// in the IR that can properly inject the memory array on emission.
if (!nla)
wiring.prefices =
instancePaths.getAbsolutePaths(op->getParentOfType<FModuleOp>());
wiring.target = PortWiring::Target(op);
("Memory[" + Twine(word.getValue().getLimitedValue()) + "]")
.toVector(wiring.suffix);
portWiring.push_back(std::move(wiring));
return;
}
blackBox.extModule.emitOpError(
"MemTapAnnotation annotation was not scattered to "
"an operation: ")

View File

@ -3,10 +3,7 @@
; - github.com/sifive/$internal:
; - src/test/scala/grandcentral/DataTapsTest.scala
circuit Top : %[[{
"class": "sifive.enterprise.firrtl.MarkDUTAnnotation",
"target": "~Top|Child"
}]]
circuit Top :
extmodule BlackBox :
input in : UInt<1>
output out : UInt<1>
@ -88,6 +85,6 @@ circuit Top : %[[{
; CHECK: module MemTap_2_impl_0(
; CHECK: output _1,
; CHECK: _0);
; CHECK: assign _1 = Top.unsigned_0.signed_0.always_1;
; CHECK: assign _0 = Top.unsigned_0.signed_0.always_0;
; CHECK: assign _1 = Top.unsigned_0.signed_0.always_ext.Memory[1];
; CHECK: assign _0 = Top.unsigned_0.signed_0.always_ext.Memory[0];
; CHECK: endmodule