• How entity name is resolved in architecture body

    From Tomas Whitlock@21:1/5 to All on Mon May 30 11:26:32 2022
    Hi all,

    I'm working on a tool that is supposed to read VHDL and create an abstract representation of a design unit.

    I have run into a problem where I'm trying to understand how this common form of an entity declaration + architecture body is accepted by VHDL compilers such as Vivado Simulator / Synthesis, ModelSim / Questa and no doubt others:

    entity e is
    ...
    end entity;

    architecture a of e is
    ...
    begin
    ...
    end architecture;

    After repeatedly reading the VHDL LRMs of '93, 2002, 2008 etc., it seems to me that, if the rules are interpreted literally, the entity 'e' should not be visible to at the point where the architecture body declaration references it.

    Yet all of the VHDL compilers that I've ever encountered will happily accept the above VHDL as valid.

    The LRM mentions a "library declarative region", in which primary design units of that library are visible, but it doesn't say where it applies. The LRM doesn't seem to leave much room for the library declarative region to be nested within some other
    declarative region, so I don't know what to make of it.

    So my question is:

    Do most VHDL compilers bend the rules and add some additional rules of their own (for example, adding "use work.all;" to the predefined language environment), or am I missing something in the LRM that makes the entities of the work library visible to an
    architecture body declaration (when being compiled into the same work library)?

    Thanks in advance for any insights.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Vraj Patel@21:1/5 to All on Mon May 30 15:01:43 2022
    Wouldn't that code be valid under the specification when you look at default binding indication?

    For the VHDL 2000 standard which I just looked thru that would be Section 5.2.2.

    The VHDL reference guide webpages (https://www.ics.uci.edu/~jmoorkan/vhdlref/confspec.html - I believe this site is for the 93 standard) sums it up nicely as follows:
    "In the absence of an explicit configuration for any part of a model, default binding will occur. For each unbound instance of every component, an entity will be selected whose name, port names and port types etc. match those in the corresponding
    component declaration. Where an entity has more than one architecture, the last analysed architecture will be used."

    This answer is not to imply that the current tools don't bend rules when it comes to following the written standard. I cannot answer with confidence if they do or don't.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tomas Whitlock@21:1/5 to patel...@gmail.com on Mon May 30 16:00:19 2022
    On Monday, 30 May 2022 at 23:01:56 UTC+1, patel...@gmail.com wrote:
    Wouldn't that code be valid under the specification when you look at default binding indication?

    For the VHDL 2000 standard which I just looked thru that would be Section 5.2.2.

    The VHDL reference guide webpages (https://www.ics.uci.edu/~jmoorkan/vhdlref/confspec.html - I believe this site is for the 93 standard) sums it up nicely as follows:
    "In the absence of an explicit configuration for any part of a model, default binding will occur. For each unbound instance of every component, an entity will be selected whose name, port names and port types etc. match those in the corresponding
    component declaration. Where an entity has more than one architecture, the last analysed architecture will be used."

    This answer is not to imply that the current tools don't bend rules when it comes to following the written standard. I cannot answer with confidence if they do or don't.

    Hi Patel,

    I appreciate you taking the time to reply, but I don't think that section of the standard is relevant to this question, and maybe I haven't stated by question clearly enough.

    I'm not trying to understand out how VHDL chooses an architecture for an instantation, but rather: how is entity 'e' even visible when the compiler encounters 'architecture a of e'. There are no use clauses in the example I've used and according to the
    LRM, the only predefined context is "library std, work; use std.standard.all;".

    So the Root Declarative Region shouldn't contain 'e', and therefore according to the visibilty, scope etc. rules, 'e' shouldn't even be visible and the compiler should error and say so (by my interpretation of the LRM, at least).

    It occurs to me that maybe for an architecture declaration, all existing VHDL compilers have a special case *for architecture bodies only* in which the entity's name is looked up in the Library Declarative Region as opposed to the Root Declarative Region,
    and hence 'e' is visible.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Vraj Patel@21:1/5 to All on Mon May 30 18:23:07 2022
    Hi,

    I have a better grasp of the question you are asking however, do you mind explaining how you get to this assertion you state as true using quotes of the standard to support the assertion:

    "So the Root Declarative Region shouldn't contain 'e', and therefore according to the visibilty, scope etc. rules, 'e' shouldn't even be visible and the compiler should error and say so (by my interpretation of the LRM, at least)."

    It would make the question more clear to me and perhaps to others. Specifically, I am interested as to how you think there would be no visibility of ''e" to the compiler.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tomas Whitlock@21:1/5 to patel...@gmail.com on Tue May 31 01:42:27 2022
    On Tuesday, 31 May 2022 at 02:23:09 UTC+1, patel...@gmail.com wrote:
    Hi,

    I have a better grasp of the question you are asking however, do you mind explaining how you get to this assertion you state as true using quotes of the standard to support the assertion:
    "So the Root Declarative Region shouldn't contain 'e', and therefore according to the visibilty, scope etc. rules, 'e' shouldn't even be visible and the compiler should error and say so (by my interpretation of the LRM, at least)."
    It would make the question more clear to me and perhaps to others. Specifically, I am interested as to how you think there would be no visibility of ''e" to the compiler.

    Hi Patel,

    Ok, here goes with my interpretation of the rules that matter for this case (from VHDL-2002 LRM):

    10.1 "In addition to the above declarative regions, there is a root declarative region, not associated with a portion
    of the text of the description, but encompassing any given primary unit. At the beginning of the analysis of a
    given primary unit, there are no declarations whose scopes (see 10.2) are within the root declarative region."

    So this is saying that when starting to parse a VHDL file, the root declarative region has no declarations. Seems pretty obvious. But this is supposed to apply to primary units - but how does the compiler know if it's looking at a primary or secondary
    unit until it has successfully parsed part of it? Surely this applies to all design units, primary & secondary.

    It says in 11.2:

    "Every design unit except package STANDARD is assumed to contain the following implicit context items as
    part of its context clause:

    library STD, WORK ; use STD.STANDARD.all ;"

    So this is how the predefined stuff gets into the root declarative region and is visible. Before the compiler gets to parsing any VHDL code, even context clauses, the root declarative region has only the following visible in it: std (library), work (
    library) and everything in std.standard.* . Notably, this does not include any entities of the work library such as entity 'e' from my example.

    I believe that if a VHDL file has multiple design units, whether primary or secondary, parsing of each design unit begins with a fresh new root declarative region with nothing in it except the predefined stuff. So after 'end entity;' of my example, the
    compiler begins a fresh new root declarative region (not containing 'e').

    I haven't found any special case treatment of the entity_name of an architecture body in the LRM, so I conclude that in a literal interpretation of the rules, you should actually need

    architecture a of work.e is -- OK: 'e' visible by selection
    ...
    begin
    ...
    end architecture;

    OR

    use work.e;

    architecture a of e -- OK: 'e' made visible by use clause
    ...
    begin
    ...
    end architecture;

    I guess that in most VHDL compilers, there is a special case where the entity_name lookup for an architecture body is not done within the root declarative region but instead goes to the library declarative region (which certainly does have 'e' visible).
    The library declarative region is mentioned in a couple of places in the LRM and nowhere else, so it's not exactly obvious what its purpose is or why the LRM even mentions it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Charles Bailey@21:1/5 to Tomas Whitlock on Tue May 31 15:24:38 2022
    On 2022-05-31 03:42, Tomas Whitlock wrote:
    On Tuesday, 31 May 2022 at 02:23:09 UTC+1, patel...@gmail.com wrote:
    Hi,

    I have a better grasp of the question you are asking however, do you mind explaining how you get to this assertion you state as true using quotes of the standard to support the assertion:
    "So the Root Declarative Region shouldn't contain 'e', and therefore according to the visibilty, scope etc. rules, 'e' shouldn't even be visible and the compiler should error and say so (by my interpretation of the LRM, at least)."
    It would make the question more clear to me and perhaps to others. Specifically, I am interested as to how you think there would be no visibility of ''e" to the compiler.

    Hi Patel,

    Ok, here goes with my interpretation of the rules that matter for this case (from VHDL-2002 LRM):

    10.1 "In addition to the above declarative regions, there is a root declarative region, not associated with a portion
    of the text of the description, but encompassing any given primary unit. At the beginning of the analysis of a
    given primary unit, there are no declarations whose scopes (see 10.2) are within the root declarative region."

    So this is saying that when starting to parse a VHDL file, the root declarative region has no declarations. Seems pretty obvious. But this is supposed to apply to primary units - but how does the compiler know if it's looking at a primary or secondary
    unit until it has successfully parsed part of it? Surely this applies to all design units, primary & secondary.

    It says in 11.2:

    "Every design unit except package STANDARD is assumed to contain the following implicit context items as
    part of its context clause:

    library STD, WORK ; use STD.STANDARD.all ;"

    So this is how the predefined stuff gets into the root declarative region and is visible. Before the compiler gets to parsing any VHDL code, even context clauses, the root declarative region has only the following visible in it: std (library), work (
    library) and everything in std.standard.* . Notably, this does not include any entities of the work library such as entity 'e' from my example.

    I believe that if a VHDL file has multiple design units, whether primary or secondary, parsing of each design unit begins with a fresh new root declarative region with nothing in it except the predefined stuff. So after 'end entity;' of my example, the
    compiler begins a fresh new root declarative region (not containing 'e').

    I haven't found any special case treatment of the entity_name of an architecture body in the LRM, so I conclude that in a literal interpretation of the rules, you should actually need

    architecture a of work.e is -- OK: 'e' visible by selection
    ...
    begin
    ...
    end architecture;

    OR

    use work.e;

    architecture a of e -- OK: 'e' made visible by use clause
    ...
    begin
    ...
    end architecture;

    I guess that in most VHDL compilers, there is a special case where the entity_name lookup for an architecture body is not done within the root declarative region but instead goes to the library declarative region (which certainly does have 'e' visible).
    The library declarative region is mentioned in a couple of places in the LRM and nowhere else, so it's not exactly obvious what its purpose is or why the LRM even mentions it.

    The WORK library is always visible without it needing to be declared.
    Entity 'e' was compiled into library WORK so it is visible when the architecture is compiled. I've never seen the USE statement used for
    anything other than pulling in packages. 'e' is an entity, not a
    package. I don't think the tools are bending the rules in this case.

    Charles Bailey

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tomas Whitlock@21:1/5 to Charles Bailey on Wed Jun 1 02:08:27 2022
    On Tuesday, 31 May 2022 at 21:24:43 UTC+1, Charles Bailey wrote:
    On 2022-05-31 03:42, Tomas Whitlock wrote:
    On Tuesday, 31 May 2022 at 02:23:09 UTC+1, patel...@gmail.com wrote:
    *snip* for brevity
    I guess that in most VHDL compilers, there is a special case where the entity_name lookup for an architecture body is not done within the root declarative region but instead goes to the library declarative region (which certainly does have 'e'
    visible). The library declarative region is mentioned in a couple of places in the LRM and nowhere else, so it's not exactly obvious what its purpose is or why the LRM even mentions it.

    The WORK library is always visible without it needing to be declared.
    Entity 'e' was compiled into library WORK so it is visible when the architecture is compiled. I've never seen the USE statement used for anything other than pulling in packages. 'e' is an entity, not a
    package. I don't think the tools are bending the rules in this case.

    Charles Bailey

    Hi Charles,

    Respectfully, I don't agree. 'e' is only visible if the LRM's scope and visibility rules say it is. By my reading of the LRM, what is visible at the beginning of compilation of a design unit consists of only: work, std & std.standard.all. That excludes '
    e'.

    The VHDL grammar says this:

    architecture_body ::=
    architecture identifier of entity_name is
    architecture_declarative_part
    begin
    architecture_statement_part
    end [ architecture ] [ architecture_simple_name ] ;

    The fact that the entity for the architecture is identified by 'entity_name' (as opposed to a 'simple_name') means that it must be subject to the scope & visibility rules like any other kind of name. I don't see anything in the LRM to indicate that there
    is a special case for this entity_name, though I might have missed something. ModelSim accepts 'work.e' as well as 'e', indicating that it does indeed treat entity_name as a 'name', and allows selected names etc.

    In the absense of a use clause that makes 'e' visible, why would it be visible just prior to the architecture body declaration that I used as an example?

    Can you explain why you think 'e' is visible according to the scope and visibility rules? Or do you know of a rule in the LRM that means the usual scope and visibility rules don't apply in this case, and instead the compiler just looks in the work
    library?

    I'm not trying to be argumentative, merely trying to confirm that my understanding of the way the entity name is resolved is correct. I would agree as a practical matter that the way all known VHDL compilers work in treating 'e' as being visible is for
    the best.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tomas Whitlock@21:1/5 to All on Wed Jun 1 02:22:50 2022
    Also, the following VHDL gives an error in ModelSim:

    entity e is end entity;

    package p is
    alias e_alias is e;
    end package;

    ** Error: entity_visibility.vhd(4): (vcom-1136) Unknown identifier "e".

    On the other hand, ModelSim accepts either of the following without error:

    entity e is end entity;

    package p is
    alias e_alias is work.e;
    end package;

    OR

    entity e is end entity;

    use work.e;

    package p is
    alias e_alias is e;
    end package;

    Which shows that according to the usual visibility and scope rules, 'e' is not visible except by selection or by a use clause. So architecture bodies appear to have special case handling for 'entity_name'.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tomas Whitlock@21:1/5 to All on Wed Jun 1 12:54:55 2022
    Update: I've now taken a look (I think) at what GHDL does for the 'entity_name' of 'architecture_body'. If understand the code correctly, it does this:

    If the 'entity_name' string is syntactically equivalent to an 'identifier' (i.e. not a selected name or anything like that), then attempt to look it up in the 'work' library. The usual scope and visibility rules are not applied in this case.

    Otherwise, attempt to look up the 'entity_name' string in the usual way, i.e. look it up in the current declarative region, which for an architecture_body must be a root declarative region. The usual scope and visibility rules are applied in this case.

    This seems like a reasonable way to go.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tomas Whitlock@21:1/5 to All on Thu Jun 2 12:35:53 2022
    @Charles Bailey - Having thought about this some more, I think you are correct to say that implementations are not bending the rules. They are implementing 'entity_name' resolution as per the rules, but the rules for that particular case are weird and
    the LRM doesn't explain the subtleties well.

    I also think there's pretty much no way to implement this in a VHDL compiler without treating it as a special case, like the solution used in GHDL.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)