According standard RFC 2578 3.2. IMPORTing Symbols:
Note that when symbols from "enterprise-specific" information modules
are referenced (e.g., a descriptor), there is the possibility of
collision. As such, if different objects with the same descriptor
are IMPORTed, then this ambiguity is resolved by prefixing the
descriptor with the name of the information module and a dot ("."),
i.e.,
"module.descriptor"
(All descriptors must be unique within any information module.)
Of course, this notation can be used to refer to objects even when
there is no collision when IMPORTing symbols.
Everything seems to be clear, but...
i cannot find in standard where it can be used and i cannot find any mib that using "qualified" descriptors.
It seems that no one uses it. Is in real mib "qualified" descriptors used and how it used?
I made up some test cases for my compiler product, so post them here for your reference.
TEST1-MIB module who defines mytest as 9998.
TEST1-MIB DEFINITIONS ::= BEGIN
IMPORTS
enterprises
FROM SNMPv2-SMI;
mytest OBJECT IDENTIFIER ::= { enterprises 9998 }
END
TEST2-MIB module who defines mytest as 9999.
TEST2-MIB DEFINITIONS ::= BEGIN
IMPORTS
enterprises
FROM SNMPv2-SMI;
mytest OBJECT IDENTIFIER ::= { enterprises 9999 }
END
Then when TEST3-MIB module tries to import both, we need the prefix to determine which mytest would be used,
TEST3-MIB DEFINITIONS ::= BEGIN
IMPORTS
mytest
FROM TEST1-MIB
mytest
FROM TEST2-MIB;
mytest1 OBJECT IDENTIFIER ::= { TEST2-MIB.mytest 9999 }
END
Related
I have a complex Lazarus program. One of my sources uses the standard units Graphics and ZStream, both of them contain a definition for clDefault.
The one (in Graphics) is:
const
clDefault = TColor($20000000);
The other (in ZStream) is:
type
Tcompressionlevel=(
clnone, {Do not use compression, just copy data.}
clfastest, {Use fast (but less) compression.}
cldefault, {Use default compression}
clmax {Use maximum compression}
);
In my code when I refer to clDefault I get a compiler error, because I want to use the const definition above to assign it a destination of TColor type, while the compiler tries to use the enumerated constant from ZStream.
How can I instruct the compiler to use the correct definition I want?
Using unit namespaces you can prefix the const clDefault with its unit name:
Graphics.clDefault
This will let the compiler pinpoint the wanted declaration in this case.
From Freepascal docs:
The rules of unit scope imply that an identifier of a unit can be redefined. To have access to an identifier of another unit that was redeclared in the current unit, precede it with that other units name...
I use a TCL script to generate a VHDL pkg for each submodule repository that stores the compilation date time and git hash of the submodule. The constant storing 32 bit git hash is called MAIN_GIT_HASH and is an std_logic_vector.
I now have multiple packages that all contain a constant called MAIN_GIT_HASH and I need to include them into the same source file using the VHDL "use" directive. Now the question is, what is the correct way to select the correct constant from each package since just writing "MAIN_GIT_HASH" will be ambigious?
Each of the packages either needs to have a unique name or needs to be analyzed into a separate library.
If you use separate libraries, you simply reference it using a package path:
library Submodule1 ;
use Submodule1.HashPkg.MAIN_GIT_HASH ; -- just get the relevant constant
Should a design need to reference more than one HashPkg (like your use case), then you can reference the constant with the same notation as above:
HashReg <= Submodule1.HashPkg.MAIN_GIT_HASH ;
If you use unique named packages, then they could all be put into the same library. Assuming that that library is the same as the one into which you are compiling the current design unit, then you can reference it as being in work:
use work.Submodule1HashPkg.MAIN_GIT_HASH ;
. . .
HashReg <= work.Submodule1HashPkg.MAIN_GIT_HASH ;
Use selected names.
The cause:
IEEE Std 1076-2008
12.4 Use clauses
In order to determine which declarations are made directly visible at a given place by use clauses, consider the set of declarations identified by all use clauses whose scopes enclose this place. Any declaration in this set is a potentially visible declaration. A potentially visible declaration is actually made directly visible except in the following three cases:
a) A potentially visible declaration is not made directly visible if the place considered is within the immediate scope of a homograph of the declaration.
b) If two potentially visible declarations are homographs and one is explicitly declared and the other is implicitly declared, then the implicit declaration is not made directly visible.
c) Potentially visible declarations that have the same designator and that are not covered by case b) are not made directly visible unless each of them is either an enumeration literal specification or the declaration of a subprogram.
12.3 Visibility
...Each of two declarations is said to be a homograph of the other if and only if both declarations have the same designator, and they denote different named entities, and either overloading is allowed for at most one of the two, or overloading is allowed for both declarations and they have the same parameter and result type profile (see 4.5.1).
12.5 The context of overload resolution
12.5 The context of overload resolution
Overloading is defined for names, subprograms, and enumeration literals.
Your constant declarations are not homographs, not enumeration literals nor declarations of subprograms. None of the multiple declarations of constants with the same name would be directly visible.
4.7 Package declarations
Items declared immediately within a simple or a generic-mapped package declaration become visible by selection within a given design unit wherever the name of that package is visible in the given unit. Such items may also be made directly visible by an appropriate use clause (see 12.4). Items declared immediately within an uninstantiated package declaration cannot be made visible outside of the package.
The cure:
back to 12.3:
Visibility is either by selection or direct. A declaration is visible by selection at places that are defined as follows:
...
f) For a declaration given in a package declaration, other than in a package declaration that defines an uninstantiated package: at the place of the suffix in a selected name whose prefix denotes the package.
...
8.3 Selected names
A selected name is used to denote a named entity whose declaration appears either within the declaration of another named entity or within a design library.
selected_name ::= prefix . suffix
suffix ::=
simple_name
| character_literal
| operator_symbol
| all
A selected name can denote an element of a record, an object designated by an access value, or a named entity whose declaration is contained within another named entity, particularly within a library, a package, or a protected type. Furthermore, a selected name can denote all named entities whose declarations are contained within a library or a package.
If we peruse 8. Names, 8.1 General we find that a prefix can be a name, including a selected name.
A code example:
library ieee;
use ieee.std_logic_1164.all;
package pkg1 is
constant MAIN_GIT_HASH: std_logic_vector := x"ffffffff";
end pkg1;
library ieee;
use ieee.std_logic_1164.all;
package pkg2 is
constant MAIN_GIT_HASH: std_logic_vector := x"00000000";
end pkg2;
library ieee;
use ieee.std_logic_1164.all;
use work.pkg1.all;
use work.pkg2.all;
entity foo is
end entity;
architecture fum of foo is
function to_string (inp: std_logic_vector) return string is -- before -2008
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
process
begin
report LF & HT & " MAIN_GIT_HASH = " & to_string(work.MAIN_GIT_HASH);
report LF & HT & "pkg1 MAIN_GIT_HASH = "
& to_string(work.pkg1.MAIN_GIT_HASH);
report LF & HT & "pkg2 MAIN_GIT_HASH = "
& to_string(work.pkg2.MAIN_GIT_HASH);
wait;
end process;
end architecture;
where
ghdl:error: compilation error
%: ghdl -a multiple_packages.vhdl
multiple_packages.vhdl:37:63:error: unit "main_git_hash" not found in library "work"
report LF & HT & " MAIN_GIT_HASH = " & to_string(work.MAIN_GIT_HASH);
^
ghdl:error: compilation error
%:
ghdl isn't very descriptive (doesn't track visibility in it's name look up to tell us why it isn't visible) while Modelsim may be more expressive, something along the lines of:
Error (10621): VHDL Use Clause error at multiple_packages.vhdl(37): more than one Use Clause imports a declaration of simple name "MAIN_GIT_HASH"
This error shows up a lot where users provide use clauses for both IEEE package numeric_std and Synopsys package std_logic_arith.
Commenting out line 37 we can demonstrate the use of selected names where direct visibility is not available:
ghdl:error: compilation error
%: ghdl -a multiple_packages.vhdl
%: ghdl -e foo
%: ghdl -r foo
multiple_packages.vhdl:38:9:#0ms:(report note):
pkg1 MAIN_GIT_HASH = 11111111111111111111111111111111
multiple_packages.vhdl:40:9:#0ms:(report note):
pkg2 MAIN_GIT_HASH = 00000000000000000000000000000000
%:
Note with a use work.all; making the package names visible the selected name prefixes could be simple_names instead of themselves being selected names.
I looked into a code like this. For Example:
typedef C;
C::T x; //illegal;
typedef C::T c_t; //legal
c_t y;
class C;
typedef int T;
endclass
Why is the first use :: of illegal and the second legal?
SystemVerilog requires that a type identifier must be known to be a type before you can reference that type. This is explained at the beginning of Section 6.18 of the 1800-2017 LRM where this example comes from.
The problem with your declaration of x is that C::T is not a known type at that point.
When you put a typedef in front of C::T the parser knows that it must be a type, there is no other valid choice.
The double colon is used the scope resolution operator. It is used for accessing classes within a package and static data within a class.
You can find good usage examples in the page 14 of this reference manual.
This is the class scope resolution operator. It is used to specify an identifier defined within the scope of a class. Because classes and other scopes can have the same identifiers, the class scope resolution operator uniquely identifies a member, a parameter or local parameter of a particular class.
More info can be found in IEEE 1800-2017, ch. 8.23 Class scope resolution operator.
Is it possible in any version of VHDL, maybe in 2008, to use a type before it's declared?
E.g. I have this array declaration in the architecture of an entity:
type my_array is array (integer range <>) of my_type;
And still in the same architecture section, but later in the file I have this:
type my_type is record
my_field: signed(31 downto 0);
end record;
Now this gives the following error in Vivado:
[Synth 8-1031] my_type is not declared
The solution is of course to move the record declaration above the array declaration. However this gets very complicated and messy with the number of types increasing (since you basically have to topologically sort your types taking their dependencies into account).
Something like this is supported in every major programming language so I figured maybe it would also exist in VHDL. I also vaguely remember reading about this having been added to VHDL 2008 but can't find any resources about it and my quick test with VHDL 2008 was negative.
So is it possible to use a type in VHDL before its declared, given that the type is declared still in the same architecture, same file, but a few lines below?
Is it possible in any version of VHDL, maybe in 2008, to use a type before it's declared?
No.
IEEE Std 1076-2008 6. Declarations
6.1 General
The language defines several kinds of named entities that are declared explicitly or implicitly by declarations. Each entity’s name is defined by the declaration, either as an identifier or as an operator symbol or a character literal.
...
For each form of declaration, the language rules define a certain region of text called the scope of the declaration (see 12.2). ...
12.2 Scope of declarations
The scope of a declaration, except for an architecture body, extends from the beginning of the declaration to the end of the immediately closing declarative region; the scope of an architecture body extends from the beginning to the end of the architecture body. In either case, this part of the scope of a declaration is called the immediate scope.
12.3 Visibility
A declaration is visible only within a certain part of its scope; this part starts at the end of the declaration except in the declaration of a design unit other than a PSL verification unit, a package declaration, or a protected type declaration, in which case it starts immediately after the reserved word is occurring after the identifier of the design unit, a package declaration, or protected type declaration. This rule applies to both explicit and implicit declarations.
It's the visibility rules stopping you from referencing a type before it's declared.
Also VHDL does not support forward declaration of types other than interface type declarations (generic types), but does for subtypes as your example my_array shows.
The generic types Brian indicates usefulness is limited lacking synthesis vendor support as well as limitations on operations of a type (see 6.5.3 Interface type declarations) summarized in Peter Ashenden's book VHDL 2008 Just the New Stuff:
1.1 Generic Types
VHDL-2008 defines a number of rules covering formal generic types and the ways they can be used. The formal generic type name can potentially represent any constrained type, except a file type or a protected type. The entity can only assume that operations available for all such types are applicable, namely: assignment; allocation using new; type qualification and type conversion; and equality and inequality operations. The formal generic type cannot be used as the type of a file element or an attribute. Moreover, it can only be used as the type of an explicitly declared constant or a signal (including a port) if the actual type is not an access type and does not contain a subelement of an access type. For signals, the predefined equality operator of the actual type is used for driver update and event detection.
Note that for access types there is a special case, where an incomplete type declaration can be references, in order to allow types for linked lists, like:
type value_cell; -- Incomplete declaration
type value_ptr is access value_cell; -- value_cell only for access type
type value_cell is record -- Full declaration
value : bit_vector(0 to 3);
next_cell : value_ptr;
end record value_cell;
However, this is not using the type before declared, and the access type is neither synthesizable, but it is a useful technique for test bench code.
As far as I understand the normal practice is to create object groups which are listed in MODULE-COMPLIANCE (this is done by the MIB designer), then the agent implementer describes the AGENT-CAPABILITIES with its VARIATIONs based on the groups used in single/multiple MODULE-COMPLIANCEs. The AGENT-CAPABILITIES is supposed to describe what the agent can do "compared" to the groups included in the MODULE-COMPLIANCE. What if the implementation fully complies with the MODULE-COMPLIANCE? Can I INCLUDE the MODULE-COMPLIANCE instead of listing all the groups it contains?
The snmpb validator and a couple of others do not raise any warnings.
xyzCompl MODULE-COMPLIANCE
STATUS current
DESCRIPTION "Module Compliance"
MODULE
MANDATORY-GROUPS { xyzFirstGroup, ... , xyzLastGroup }
::= { xyzCompanyCompl 1}
xyzAgent AGENT-CAPABILITIES
PRODUCT-RELEASE "Agent release v1"
STATUS current
DESCRIPTION "xyz Agent"
SUPPORTS XYZ-MIB
-- what usually gets included
INCLUDES { xyzFirstGroup, ... , xyzLastGroup }
-- what I want to include
INCLUDES { xyzCompl }
::= { xyzCompanyAgents 1 }
It is explicitly legal for INCLUDES to reference OIDs other than OBJECT-GROUPs and NOTIFICATION-GROUPs in SMIv1 modules, per RFC 2576 §2.3 (emphasis mine):
In order to ease coexistence, object groups defined in an SMIv1
compliant MIB module may be referenced by the INCLUDES clause of an
invocation of the AGENT-CAPABILITIES macro: upon encountering a
reference to an OBJECT IDENTIFIER subtree defined in an SMIv1 MIB
module, all leaf objects which are subordinate to the subtree and
have a STATUS clause value of mandatory are deemed to be INCLUDED.
The specs are silent with regards to INCLUDES referencing non-GROUP OIDs of SMIv2 modules, so it is somewhat ambiguous as to whether INCLUDES { xyzCompl } is legal.
On the one hand, with some exceptions SMIv2 modules can be converted to SMIv1 and vise versa, and converting from SMIv2 to SMIv1 xyzCompl would be converted to a simple OBJECT IDENTIFIER ::= assignment, which would be indistinguishable from any other; that would imply it to be legal.
On the other hand, it specifies that only those objects with STATUS mandatory are deemed to be included. SMIv2 STATUS "current" is not the same thing as SMIv1 STATUS "mandatory" (although they are the closest things to each other; the "must implement" implication of "mandatory" is subsumed by MODULE-COMPLIANCE rules in SMIv2). This could be interpreted to mean they would not be included because their STATUS isn't "mandatory", or it could be interpreted that, since the MODULE-COMPLIANCE is specified in the SUPPORTS clause, and the MODULE-COMPLIANCE specifies what are mandatory groups, that this is sufficiently equivalent to STATUS mandatory as to be included.
However, per the emphasized bit in the quoted section of RFC 2576 all of this only applies if the OBJECT-TYPEs you are intending to specify as included have OID prefixes the same as your MODULE-COMPLIANCE OID, which is very much not recommended and is also unlikely, and so it's all kind of moot: unless your OBJECT-TYPEs are OID children of xyzCompl, they're not included, despite being members of groups you've specified in MANDATORY-GROUPS!
Conclusion: it is legal syntax, hence there is no complaint, but it is unlikely to be specifying what you are intending it to. Without seeing the rest of the MIB, I would say that this AGENT-CAPABILITIES would be saying it SUPPORTS XYZ-MIB while also not supporting any objects from XYZ-MIB if it uses INCLUDES { xyzCompl }.