External Names for Types
Proposal Information
- Current Owner: JimLewis, ...
- Contributors: JimLewis, ...
- Date Proposed: 2014-May-26
- Date Last Updated: 2014-May-26
- Priority:
- Complexity:
- Focus: Testbench
- Related Issues: None
- Competing Issues: None
Requirement Summary
Create external names to types.
Rationale
For a testbench to do actions based, such as coverage, on the state of a statemachine, knowledge of the enumerated type of the statemachine is required. Unfortunately the type definition is most often defined in the RTL code and currently there is no easy way to access it.
Current Solutions
Minimally touch the RTL code
In many organizations, there is independent test and verification. In these teams, the testbench team is not permitted to modify the RTL code. Hence, we need an approach that minimally touches the RTL code.
Statemachine in an RTL block. The comments with "instrumentation for testbench" are extra steps required to allow the testbench team to access state information.
entity block1 is
port ( ... ) ;
end entity block 1 ;
architecture rtl of block1 is
type RingStateType is (S0, S1, S2, S3) ;
signal State : RingStateType ;
signal State_int : integer ; -- instrumentation for testbench
begin
-- synthesis translate_off -- instrumentation for testbench
State_int <= RingType'pos(State ) ; -- instrumentation for testbench
-- synthesis translate_on -- instrumentation for testbench
...
In this approach enumeration information is lost. The following package uses integer constants to replicate this information - note this is potentially error prone as there is no guarantee the constants will remain in sync with the design.
package TbPkg is
-- replicate the state values as constant of type integer
constant STATE_S0 : integer := 0 ;
constant STATE_S1 : integer := 1 ;
constant STATE_S2 : integer := 2 ;
constant STATE_S3 : integer := 3 ;
constant S0_BIN : CovBinType := GenBin(STATE_S0) ;
constant S1_BIN : CovBinType := GenBin(STATE_S1) ;
constant S2_BIN : CovBinType := GenBin(STATE_S2) ;
constant S3_BIN : CovBinType := GenBin(STATE_S3) ;
...
end package TbPkg ;
At this point, our testbench can access the package
TbPkg and the integer valued State_int signal.
architecture Test1 of Testbench is
alias Ring_State_int is <<signal .Testbench.U_RTL_TOP.Block1.State_int : integer>>;
shared variable CovState : CovPType;
...
begin
RecordCovProc : process
begin
CovState.SetName("Ring State Transistions");
-- TEST_LOGIC_RESET
CovState.AddCross("S0 to S1", S0_BIN, S1_BIN);
CovState.AddCross("S1 to S2", S1_BIN, S2_BIN);
CovState.AddCross("S2 to S3", S2_BIN, S3_BIN);
CovState.AddCross("S3 to S0", S3_BIN, S0_BIN);
Proposal
Concept 1: Use a selected name path through the library into an entity See LCS_2016_028
We need an approach that provides type value information at compile time and not elaboration time.
Hence, we need our alias to be able to reach down a selected name path through the library. That would suggest that we use an alias such shown in the following package:
package TbPkg is
alias extRingStateType is work.EntityName(ArchitectureName).RingStateType;
constant S0_BIN : CovBinType := GenBin(extRingStateType'Pos(S0)) ;
constant S1_BIN : CovBinType := GenBin(extRingStateType'Pos(S1)) ;
...
end package TbPkg ;
At this point, our testbench can access the package
TbPkg and the values of
RingStateType via extRingStateType .</pre>
architecture Test1 of Testbench is
alias Ring_State is <<signal .Testbench.U_RTL_TOP.Block1.Statet : extRingStateType >>;
shared variable CovState : CovPType;
...
begin
RecordCovProc : process
begin
CovState.SetName("Ring State Transistions");
-- TEST_LOGIC_RESET
CovState.AddCross("S0 to S1", S0_BIN, S1_BIN);
CovState.AddCross("S1 to S2", S1_BIN, S2_BIN);
CovState.AddCross("S2 to S3", S2_BIN, S3_BIN);
CovState.AddCross("S3 to S0", S3_BIN, S0_BIN);
Issues: This implementation introduces a selected path into the declarative region an entity/architecture. This results in compile order dependencies on a particular entity/architecture, however, these are a normal part of the language.
What does it mean if there are two instances of a particular design? How would this complicate the situation?
Concept 2: Allow a External Name to an signal reference an anonymous type
Allow an anonymous type to be used with an external signal name
package TbPkg is
constant S0_BIN : CovBinType ;
constant S1_BIN : CovBinType ;
end package TbPkg ;
package body TbPkg is
alias Ring_State is <<signal .Testbench.U_RTL_TOP.Block1.Statet : (<>) >>;
constant S0_BIN : CovBinType := GenBin("S0", Ring_State'subtype'pos(Ring_State'subtype'value("S0") ) ) ;
constant S1_BIN : CovBinType := GenBin("S1", Ring_State'subtype'pos(Ring_State'subtype'value("S1") ) ) ;
end package body TbPkg ;
Concept X: Create an external name which uses an instance path to the type. Not Feasible
Extend external_name to include external_type_name:
external_name ::=
external_constant_name
| external_signal_name
| external_variable_name
| external_type_name
Define external_type_name in a similar fashion to how a other names are accessed.
In the testbench package one can do the following. Now the values that the package uses as value of
RingType can be checked against the type definition:
package TbPkg is
alias extRingStateType is <<type .Testbench.U_RTL_TOP.Block1.RingStateType>>;
constant S0_BIN : CovBinType := GenBin(extRingStateType'Pos(S0)) ;
constant S1_BIN : CovBinType := GenBin(extRingStateType'Pos(S1)) ;
...
end package TbPkg ;
At this point, our testbench can access the package
TbPkg and the values of
RingStateType via extRingStateType .
architecture Test1 of Testbench is
alias Ring_State is <<signal .Testbench.U_RTL_TOP.Block1.Statet : extRingStateType >>;
shared variable CovState : CovPType;
...
begin
RecordCovProc : process
begin
CovState.SetName("Ring State Transistions");
-- TEST_LOGIC_RESET
CovState.AddCross("S0 to S1", S0_BIN, S1_BIN);
CovState.AddCross("S1 to S2", S1_BIN, S2_BIN);
CovState.AddCross("S2 to S3", S2_BIN, S3_BIN);
CovState.AddCross("S3 to S0", S3_BIN, S0_BIN);
Major Issues: Type names of
RingStateType are not available until the design has been elaborated. Hence, an approach constructed in a similar manner to external names for signals does not seem too practical.
Comments
--
LievenLemiengre - 2015-06-04
From a compiler POV this is
extremely hard. You would have to do elaboration during type resolving.
--
TristanGingold - 2016-12-21
Yes, only referencing a type from a design unit looks doable, provided it is locally static.
--
ErnstChristen - 2018-08-16
An expanded name that denotes a type does just that. It doesn't make any of the properties of the type visible, such as enumeration literals, predefined operations. Such properties would have to be accessed one by one with a corresponding expanded name. The type properties are made available through a use clause, which makes the denoted type directly visible along with its properties.
While the issues related to the analysis of a design unit probably could be fixed by making appropriate changes to 12.4 Use clause, a more serious issue arises during elaboration. Since the expanded name exists in the uninstantiated model, and since a type declaration has to be elaborated to make the type known, this would require elaborating L.E(A) without instantiating it. What if E has generics without defaults or ports with unconstrained types? What about the concurrent statements in A, e.g. drivers associated with signal assignment statements, processes sensitive to a signal declared in a package.
Supporters
JimLewis
--
RyanHinton - 2014-06-18
--
Brent Hayhoe - 2014-06-19
--
TorstenMeissner - 2016-05-18