01-24-2019 09:01 AM
Attached is a minimal test demonstration of a problem I've observed with xsim. In brief, the vhdl package contains a sort of list creating mechanism (not a linked list, but based on an array with indexed elements), and when using the included record as the type for the list elements, a problem is exposed in the way the 'new' keyword handles an initializer for an array: elements that are not supposed to be NULL become NULL.
The procedure shown below takes some initial values and a access type (the specific type defined in the code, which is an array based list) as arguments, and creates a new record with the initial values, returns an accessor for the new record, and also adds an accessor for the new record to the array of those things. What apparently is problematic is getting the ".all" array from the access type and appending another to it all within the initializer list for the "new" command. See the attached files for complete details, but since this comes and goes based on the data within the record, it seems to highlight a data management problem, or how an element is determined to be null or not.
The enclosed zip has a src and sim directory... if you have Vivado 2018.2 (the toolset that I had the problem with) in your executable path, cd to sim and run make sim and it'll simulate and report if NULLs are found. I've tested this on windows 64 bit and linux 64 bit, and both show the same problem. You're looking for "IS NULL !!" in the simulation output. From there, go into the src directory where the one file, a package file, resides. I've pulled everything else out of it that's not necessary to illustrate this bug, but there's not a tremendous amount of verbose comments. I believe that a familiartiy with access types will make it all pretty understandable, but I'm willing to do some explaining if necessary. If you run this with something other than 2018.2 and don't see "IS NULL !!", that would be worth hearing, too.
Long story short: I'm posting this here to:
a) See if it's not really a bug. It sure seems like one to me.
b) Get it into the bug fix queue. I have been using this in modelsim for years, and trying to use xsim is hampered with bugs and non-supported features (to_hstring, for example), and so I put off digging into this for almost 6 months. Clearly one could say "who not just shut up and use modelsim?" and while that's not wrong, the goal here is for xsim to get better by having its shortcomings pointed out, so here's me doing that. Again... unless it's not really a bug, in which case I'm all ears!!
Below, types like "t_something_acc" are access types. Open the source for the complete details.
The record looks like this. If I remove any one of these elements, the bug seems to disappear. I didn't try every possible combination or reordering or whatever, but the full record is normally much more than this, so these were the minimal set I found quickly that still demo the problem.
type t_record is record enum : t_enum; value1 : natural; bool : boolean; value2 : natural; value3 : natural; description : t_desc; end record; type t_record_acc is access t_record;
The process of creating a list of these records looks like this. The list the record is being added to is specified, along with some initial values, and the record is both returned (as an accessor to the record) and appended to the specified list. That list modification is where the problem comes in.
procedure create_record ( desc : in string; value : in natural; list_acc : inout t_list_acc; new_record : out t_record_acc ) is variable v_new_desc : t_desc; variable v_new_record : t_record_acc; variable v_temp_list_acc : t_list_acc; begin v_new_desc := new string'(desc); v_new_record := new t_record'( enum => NA, value1 => value, bool => FALSE, value2 => 0, value3 => 0, description => v_new_desc ); new_record := v_new_record; if (list_acc = null) then list_acc := new t_list'(0 => v_new_record); else v_temp_list_acc := new t_list'(list_acc.all & v_new_record); Deallocate(list_acc); list_acc := new t_list'(v_temp_list_acc.all); Deallocate(v_temp_list_acc); end if; end procedure;
The key problem point is:
v_temp_list_acc := new t_list'(list_acc.all & v_new_record);
If that is instead done via these more verbose steps, the problem doesn't appear:
v_temp_list_acc := new t_list(list_acc.all'high + 1 downto list_acc.all'low); v_temp_list_acc(list_acc.all'high downto list_acc.all'low) := list_acc.all; v_temp_list_acc(list_acc.all'high + 1 ) := v_new_record;
Finally, in case it comes up: yes I do know that this list type thing could be done as a real linked list, but that's not the point here.
Thanks in advance for any help with this.
01-25-2019 01:15 AM
Ahh, the good old problem of simulators struggling with Access types and records (especially when theres an access type or unconstrained array within the record).
All works fine in ActiveHDL:
KERNEL: ========== KERNEL: New record is not null KERNEL: New list index range: 0 to 0 New list elements: 0 is not null KERNEL: ========== KERNEL: New record is not null KERNEL: Old list index range: 0 to 0 Old list elements: 0 is not null KERNEL: New list index range: 0 to 1 New list elements: 0 is not null 1 is not null KERNEL: ========== KERNEL: New record is not null KERNEL: Old list index range: 0 to 1 Old list elements: 0 is not null 1 is not null KERNEL: New list index range: 0 to 2 New list elements: 0 is not null 1 is not null 2 is not null EXECUTION:: FAILURE: Done.
BUT: I have opened about 30 bug reports with Aldec in the last 18 months. Some of which were to do with access type records not initialising properly. My favorite one was where I was able to access one element via another (basically, AHDL was incorrectly mapping the record to RAM!). The outcome is that now Active HDL is a very useable simulator where you can create some very complicated transaction/object based verification testbenches purely in VHDL.
(I dont have access to modelsim where I am now. Im sure it would have bugs too! VHDL 2008 proper isnt much used).
The main difference - Aldec pounced straight on the bug reports and fixed them within a couple of months (usually giving me a beta version with the bug fix too). Xilinx have VHDL on the back burner - so dont expect fixes any time soon. Currently synthesis has better VHDL 2008 support than simulation!!!! (unconstrained record types!)
I do notice you're declaring your own version of the "line" type from textio.
type t_desc is access string;
Have you tried using the line type instead (you'll then be able to use the write functions directly on the record!)?
Keep plugging away. VHDL is very powerful when you do what you're doing.
01-25-2019 01:25 AM
In your code, you deallocate all the pointers after using their data. I wonder if XSIM is somehow passing the .all de-references by references, rather than by value (as its supposed to), so when you deallocate the old variables, it also kills the data (and hence the new arrays).
But your code shows me exactly why Ive never bothered with the vivado simulator.
02-05-2019 03:17 PM
Thanks for testing in ActiveHDL.
Regarding the deallocation and such... note that much of the time it works as it's supposed to, so deallocation is not a problem in those instances.
Regarding redefining the line type as "t_desc", it wasn't intentional, but there's no value in using 'write' and the like in this case, so it's not problematic.
Finally, as stated in the original post, this is pretty straight forward stuff in Modelsim, but there's pressure to use the "free" tools from various sources, so ... here we are.