-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[slang] Add virtual interface declaration checks #1088
base: master
Are you sure you want to change the base?
[slang] Add virtual interface declaration checks #1088
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1088 +/- ##
==========================================
+ Coverage 94.76% 94.87% +0.11%
==========================================
Files 191 191
Lines 47716 47802 +86
==========================================
+ Hits 45217 45352 +135
+ Misses 2499 2450 -49
... and 18 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
source/ast/types/AllTypes.cpp
Outdated
@@ -1131,6 +1181,9 @@ const Type& VirtualInterfaceType::fromSyntax(const ASTContext& context, | |||
auto& iface = InstanceSymbol::createVirtual(context, loc, def->as<DefinitionSymbol>(), | |||
syntax.parameters); | |||
|
|||
InterfaceDefVisitor iDVisitor(iface, context); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We really don't want to rerun this checker on every virtual interface type declaration -- ideally we only run it once per unique interface instantiation. My thinking was to track hierarchical lookups more closely, registering them on instances as they pass through them. Primarily this would be to support caching of instance bodies to avoid unnecessary elaboration work, but as a side effect would make this kind of checking much easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instance hierarchical identifiers caching was added
source/ast/types/AllTypes.cpp
Outdated
void handle(const T& symbol) { | ||
if constexpr (std::is_base_of_v<Symbol, T>) { | ||
if (symbol.kind == SymbolKind::Instance) { | ||
const auto* inst = symbol.template as_if<InstanceSymbol>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems wrong; instantiating an interface inside another interface doesn't make it a port, so we shouldn't error on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still in progress
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the first version of the solution, I misunderstood LRM in this term, sorry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add that check in the last commit
scripts/diagnostics.txt
Outdated
@@ -543,6 +545,7 @@ note InfoTask "$info encountered{}" | |||
note NoteComparisonReduces "comparison reduces to ({} {} {})" | |||
note NoteCommonAncestor "common ancestor here violates that constraint" | |||
warning explicit-static StaticInitializerMustBeExplicit "initializing a static variable in a procedural context requires an explicit 'static' keyword" | |||
note VirtualInterfaceDecl "virtual interface declared here" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general we don't need to keep adding new notes that are very slight variations of existing ones; the more general "declared here" note is fine for these purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
ecd57c9
to
c7148fe
Compare
65784ef
to
ddfe20d
Compare
for (auto& name : scope.getNameMap()) { | ||
if (auto inst = name.second->as_if<InstanceSymbol>()) { | ||
auto instDef = &inst->getDefinition(); | ||
if (instDef == &defSym && inst->body.hierIdentifiers.has_value()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely not correct; just because the definition is the same doesn't mean the hierarchical identifiers will be the same, since behavior can vary on the parameters of the instance controlling generate blocks in the child.
This is a generally hard problem; my thinking in the past was that I would keep track of found hierarchical identifiers during Lookup and caching based on a more complicated cache key that takes into account parameters, interface ports, any active configurations, etc. Tracking for that is here: #949
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I have an idea for a hash - Can it be a std::hash
of std::string
consisting of an instance kind (for example interface
or module
), instance type (for example - module type identifier) and a set of parameter values with their identifiers?
For example for such module:
module mem_model #(
parameter ADDR_WIDTH=8;
parameter DATA_WIDTH=32;)
(clk, addr, data);
input clk;
input [ADDR_WIDTH-1:0] addr;
output [DATA_WIDTH-1:0] data;
.....
.....
endmodule
and it's instances:
//Creates mem_1 instance with default addr and data widths.
mem_model mem_1 (.clk(clk),
.addr(addr_1),
.data(data_1));
//Creates mem_2 instance with addr width = 4 and data width = 8.
mem_model #(4,8) mem_2 (.clk(clk),
.addr(addr_2),
.data(data_2));
//Creates mem_3 instance with addr width = 32 and data width = 64.
mem_model #(32,64) mem_3 (.clk(clk),
.addr(addr_3),
.data(data_3));
//Creates mem_4 instance with default addr width and data width = 64.
mem_model #(DATA_WIDTH=64) mem_4 (.clk(clk),
.addr(addr_3),
.data(data_3));
hash strings can have a form:
"module mem_model(ADDR_WIDTH=8, DATA_WIDTH=32)" // for mem_1
"module mem_model(ADDR_WIDTH=4, DATA_WIDTH=8)" // for mem_2
"module mem_model(ADDR_WIDTH=32, DATA_WIDTH=64)" // for mem_3
"module mem_model(ADDR_WIDTH=8, DATA_WIDTH=64)" // for mem_4
What do you think about this suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no reason for it to be a string; you can just hash the relevant fields. This diff from a long time ago removed an InstanceCache that I had in slang at one point: 0892da3#diff-18c21a73a1abf2b9e1aa72758848d9bceee11a575bfab7d762dfc51217ec26c3
That's a good start but it also needs to work correctly with hierarchical references into and out of cached instances, which is very tricky and something I need to think more carefully about (which is one of the reasons why I removed this back in the day).
In this PR i add some virtual interface checks such as:
That checks related to part of #522