I am trying to structure a testbench such, that each test case is represented by a record which holds all the parameters for the test case, e.g. input file names, generics to be used for DUT instantiation &cetera. The idea is that only one assignment needs to be changed to switch between different test cases.
type string_ptr is access string;
type test_case_t is record
input_file : string_ptr;
...
end record;
shared variable test_case_1 : test_case_t := (
input_file => new string'("path to input file 1")
...
);
shared variable TEST_CASE : test_case_t := test_case_1;
dut: my_module
generic map (
file_name => TEST_CASE.input_file.all
);
...
A string pointer is used for input_file
since no unconstraint arrays are allowed inside a record type declaration (in this case, pre-VHDL-2008).
Due to the string pointer in test_case_t
I have to use a shared variable for test_case_1.
However, when I try to simulate this testbench in Xilinx ISE/ISim 14.4 the simulator keeps using the default value of the generic and not the value I pass to it in the testbench (I assume this is a bug).
I tried to work around the issue with
constant INPUT_FILE : string := TEST_CASE.input_file.all;
dut: my_module
generic map (
file_name => INPUT_FILE
);
...
This is basically using the initial value of a shared variable as the initial value for a constant. However, this assignment will crash the Xilinx compiler before simulation even started (another bug I assume).
At this point I no longer trust the Xilinx tools at all.
My question is if a shared variable can be used to pass generic values to a module as shown above (first code snippet)?
Also, is this usage of shared variable advisable for testbenches? I would have used a constant or signal for test_case_1
but due to the use string_ptr
type in test_case_t
this seems not to be allowed.
You can associate any fixed length string expression as the value of a generic constant as an actual in a generic map to a formal of type string with an unbound subtype indication.
To understand why this works we turn to elaboration of generics.
IEEE Std 1076-2008 (the LRM):
14.3 Elaboration of a block, package, or subprogram header
14.3.2 Generic clause
6.5.6.2 Generic clauses (para 5)
(And note the actual of a generic is an expression and the association list is the generic map. Also note this doesn't match Brian's expectations on how the subtype indication for a string as a generic is determined from his Ada background.)
So that means that this:
is legal VHDL:
As well as this:
Which gives:
So this tells us a couple of things.
ISIM is not quite standard compliant in implementing generics. From the difference in the two architectures we can see that your particular ISIM version likely is not determining the subtype from the actual as per 6.5.6.2 quoted above noting you're trying to deal with string subtype (length). (You'd expect if someone were to point it out Xilinx would fix it).
You could try not providing a default expression in the generic clause in the entity declaration (noting component declarations should match). See 6.5.6.2 para 4:
It's an either or situation, if neither it's an error.
There's also propagating a top level constant or generic (where supported by the tool implementation) requires passing every unique value through generics of each successive hierarchical block element. This would require the implementation supports 6.5.6.2 properly. (See the bit about 6.5.6.2 para 4 above).
And if you were really clever and the simulation and synthesis implementations supported configuration declarations properly there's likely a way to do something through configuration (providing two different use clauses with two different packages providing component declarations with two different actuals in generic clauses - this also requires the VHDL implementation also support 6.5.6.2, also see para 4 above). This method would allow you to simulate different configurations for different sets of actual values.