Basic sanity checking of various constructs.
This is a set of basic but rather ad-hoc sanity checks that don't really fit into other places. It is carried out as part of annotate. Some of the things we do here...
We check that ports satisfy basic well-formedness conditions and agree with its port declarations and to issue style warnings for tricky ports. This is meant to identify cases such as:
module foo (o, a, b); | module bar (o, a, b); output o; | output o; input a; | input c; // oops, no such port // oops, no declaration for b | ... endmodule | endmodule
This is mostly straightforward. One complication is that ports can have many names internally, for instance:
module baz (o, a, .foo( {b, c} ), d) ; ... endmodule
So, in general, we need to gather the names from the port expressions. While we're at it we may issue various port style warnings.
Most name clash checking for real scopes is done by shadowcheck, but
things like the external port names for a module, e.g., the
module foo (.a1(b1), .a2(b2)) ; ... endmodule
aren't separate from other scopes, so we check them here. We similarly check the external names listed by modports.
SystemVerilog 25.3 (page 713) prohibits interfaces from instantiating submodules, but interfaces are allowed to instantiate other interfaces. Since we can't tell until after parsing whether a particular instance refers to a module, interface, or user-defined primitive and use the same representation for all of these, we check here that any such instances really do refer to interfaces.