[FIRRTL] Support "invalidate <mem, instance>"

Add support for invalidation syntax that invalidates an instance or a
memory.  This was never technically supported before, though it should
have been.  Previously, this was only supported through the "is invalid"
path which is has been deprecated for FIRRTL versions >=3.

Fixes #7730.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit is contained in:
Schuyler Eldridge 2024-10-25 18:30:37 -04:00
parent 8235381b9f
commit 3c53d09bf1
No known key found for this signature in database
GPG Key ID: 50C5E9936AAD536D
3 changed files with 53 additions and 15 deletions

View File

@ -3960,7 +3960,52 @@ ParseResult FIRStmtParser::parseInvalidate() {
auto startTok = consumeToken(FIRToken::kw_invalidate);
Value lhs;
if (parseExp(lhs, "expected connect expression") || parseOptionalInfo())
StringRef id;
auto loc = getToken().getLoc();
SymbolValueEntry symtabEntry;
if (parseId(id, "expected static reference expression") ||
moduleContext.lookupSymbolEntry(symtabEntry, id, loc))
return failure();
// If we looked up a normal value (e.g., wire, register, or port), then we
// just need to get any optional trailing expression. Invalidate this.
if (!moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc, false)) {
if (parseOptionalExpPostscript(lhs, /*allowDynamic=*/false) ||
parseOptionalInfo())
return failure();
locationProcessor.setLoc(startTok.getLoc());
emitInvalidate(lhs);
return success();
}
// We're dealing with an instance. This instance may or may not have a
// trailing expression. Handle the special case of no trailing expression
// first by invalidating all of its results.
assert(symtabEntry.is<UnbundledID>() && "should be an instance");
if (getToken().isNot(FIRToken::period)) {
locationProcessor.setLoc(loc);
// Invalidate all of the results of the bundled value.
unsigned unbundledId = symtabEntry.get<UnbundledID>() - 1;
UnbundledValueEntry &ubEntry = moduleContext.getUnbundledEntry(unbundledId);
for (auto elt : ubEntry)
emitInvalidate(elt.second);
return success();
}
// Handle the case of an instance with a trailing expression. This must begin
// with a '.' (until we add instance arrays).
StringRef fieldName;
if (parseToken(FIRToken::period, "expected '.' in field reference") ||
parseFieldId(fieldName, "expected field name") ||
moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
return failure();
// Update with any trailing expression and invalidate it.
if (parseOptionalExpPostscript(lhs, /*allowDynamic=*/false) ||
parseOptionalInfo())
return failure();
locationProcessor.setLoc(startTok.getLoc());

View File

@ -29,10 +29,8 @@ circuit TestHarness:
write-latency => 1
read-under-write => undefined
invalidate foo_m.r
invalidate foo_m.w
invalidate foo_combmem.r
invalidate foo_combmem.w
invalidate foo_m
invalidate foo_combmem
extmodule Foo_BlackBox:
defname = Foo_BlackBox
@ -58,10 +56,8 @@ circuit TestHarness:
write-latency => 1
read-under-write => undefined
invalidate bar_m.r
invalidate bar_m.w
invalidate bar_combmem.r
invalidate bar_combmem.w
invalidate bar_m
invalidate bar_combmem
extmodule Bar_BlackBox:
defname = Bar_BlackBox
@ -87,10 +83,8 @@ circuit TestHarness:
write-latency => 1
read-under-write => undefined
invalidate baz_m.r
invalidate baz_m.w
invalidate baz_combmem.r
invalidate baz_combmem.w
invalidate baz_m
invalidate baz_combmem
extmodule Baz_BlackBox:
defname = Baz_BlackBox

View File

@ -776,8 +776,7 @@ circuit MyModule : ; CHECK: firrtl.circuit "MyModule" {
; CHECK: firrtl.matchingconnect %U0_in0, [[INV]]
; CHECK: [[INV:%.+]] = firrtl.invalidvalue : !firrtl.bundle<a: uint<5>>
; CHECK: firrtl.matchingconnect %U0_in1, [[INV]]
invalidate U0.in0
invalidate U0.in1
invalidate U0
; This reference is declared after its first use.
; https://github.com/llvm/circt/issues/163