![]() |
|
|
|
#1 |
|
Inside testbenches, it is often the case that multiple instances of
some stimuli (think ethernet interfaces, PCI busses) have a generic number (G_ETHERNET_INTERFACE_NO) which is then set to 0, 1, 2, ... manually. I want to auto-initialize such interfaces, which means that each such interface has a shared variable or signal (interface_no) and an init process, say like this: architecture tst of einterface is shared variable interface_no: natural; begin ... Get_Interface_No: process begin alloc_number(interface_no); wait; end; end; A package should provide the alloc_number procedure: package allocator is procedure alloc_number(variable n: out natural); end allocator; package body allocator is shared variable numbers: natural:=0; procedure alloc_number(variable n: out natural) is begin n:=numbers; numbers:=number+1; end; end allocator; If you use 10 interfaces, the interfaces should get different interface numbers from 0 to 9. The order is insignificant, but is is required that all interfaces get their own number. While this works on my Modelsim 6 on my single processor machine, it is not portable in VHDL'93. The LRM states, that if shared variables are accessed in the same simulation cycle (like here), we can assume *nothing* about the order of execution (not a problem here) and also if (the problem here) the accesses are sequential: "A description is erroneous if it depends on whether or how an implementation sequentializes access to shared variables." Is there a way in VHDL'93 do solve this problem (in a portable, non erroneous way)? Hubble Hubble |
|
|
|
|
#2 |
|
Posts: n/a
|
Use a for...generate to instantiate your components and use the loop
index as your interface number. Nicolas Nicolas Matringe |
|
|
|
#3 |
|
Posts: n/a
|
This is not possible, sorry. To be more specific:
I designed a "testbench bus", where I can attach various standard entities, which I want to address by name. Currently, I have to assign a number and a name to each of these entities. I want to allocate these numbers automatically and have already working code for modelsim, however erroneous according to the LRM. Hubble Hubble |
|
|
|
#4 |
|
Posts: n/a
|
Hi Hubble,
I am not sure where you read that line in your OP: ---- "A description is erroneous if it depends on whether or how an implementation sequentializes access to shared variables." ------ I've 2002 LRM and a quick search didn't reveal it. However I found an interesting stuff - there is this "protected type" definition that might satisfy your requirement (In my gut feeling your implementation is fine too). As per LRM 2002 version, section 3.5 -------- A protected type definition defines a protected type. A protected type implements instantiatiable regions of sequential statements, each of which are guaranteed exclusive access to shared data ------- Good Luck Sri -- Srinivasan Venkataramanan Co-Author: SystemVerilog Assertions Handbook, http://www.abv-sva.org Co-Author: Using PSL/SUGAR for Formal and Dynamic Verification 2nd Edition. http://www.noveldv.com I own my words and not my employer, unless specifically mentioned "Hubble" <> wrote in message news: oups.com... > This is not possible, sorry. To be more specific: > > I designed a "testbench bus", where I can attach various standard > entities, which I want to address by name. Currently, I have to assign > a number and a name to each of these entities. I want to allocate these > numbers automatically and have already working code for modelsim, > however erroneous according to the LRM. > > Hubble > Srinivasan Venkataramanan |
|
|
|
#5 |
|
Posts: n/a
|
The line is from the LRM of VHDL'93.
http://www.microlab.ch/courses/vlsi/..._4.HTM#4.3.1.3 Using the technique of allocating, I have code to allocate dynamic messages (type: access string), holding them in a dynamic array (type access array (<>)) and passing integer indices in signals. The code is working on Modelsim 6.0 but illegal in VHDL'93. Hubble. Hubble |
|
|
|
#6 |
|
Posts: n/a
|
Just to be more specific, here is a prototype implementation of
"dynamic string" in VHDL'93 A process/procedure can call tbs_dynstring_new and gets an integer id. Using this id, it can get/set the strings. One can use things like report "message was " & tbs_dynstring_get(dstring); and pass dstrings as signals a.s.o. When a simulator executes each process one after the other, but in arbitrary order, the package will run. But if it decides (on a multiprocessor machine) to execute id:=idcnt; idcnt:=idcnt+1 in parallel, it will fail. (Note that the package is not well tested yet) Hubble. -- VHDL'93 code -- tbs_dynstring_new and free suffer from concurrent shared variable access problems package tbs_dynstring is subtype tbs_dynstring is natural; constant C_NODYNSTRING: tbs_dynstring:=0; -- basic functions impure function tbs_dynstring_new(s: string:=""; minlen: natural:=0) return tbs_dynstring; procedure tbs_dynstring_free(id: tbs_dynstring); impure function tbs_dynstring_get(id: tbs_dynstring) return string; impure function tbs_dynstring_length(id: tbs_dynstring) return natural; procedure tbs_dynstring_set(id: tbs_dynstring; s: string:=""; minlen: natural:=0); end tbs_dynstring; package body tbs_dynstring is constant C_INITIALIDS: natural:=100; constant C_MINLENGTH: natural:=8; type tbs_dynstring_ref is access string; type id_fields is record lenfree: natural; -- current length or next free element str: tbs_dynstring_ref; -- allocated memory end record; type id_array is array (natural range <>) of id_fields; type ids_ref is access id_array; -- -- ids holds string pointers and length and grows exponentially if necessary -- if a string is freed, it is not deallocated, but its index is copied to -- freelist and the old freelist is copied to its length field. Therefore, -- the lenfree sequence is a list of freed elements. -- shared variable ids : ids_ref; shared variable idcnt: natural:=1; -- occupied and free elements in ids shared variable freelist: natural:=C_NODYNSTRING; -- check if ids has idcnt elements at min and grow ids if necessary procedure sufficientids is variable newsize: natural; variable old: ids_ref; begin if ids=null then ids:=new id_array(0 to C_INITIALIDS-1); end if; if idcnt<ids'length then return; end if; newsize:=2*ids'length; old:=ids; ids:=new id_array(0 to newsize-1); ids(0 to idcnt-1):=old(0 to idcnt-1); deallocate(old); end procedure sufficientids; impure function tbs_dynstring_new(s: string:=""; minlen: natural:=0) return tbs_dynstring is variable id: tbs_dynstring; begin if freelist/=C_NODYNSTRING then -- take last element from freelist id:=freelist; freelist:=ids(id).lenfree; -- restore old freelist else -- take next element, grow ids if necessary id:=idcnt; idcnt:=idcnt+1; sufficientids; end if; tbs_dynstring_set(id,s,minlen); return id; end tbs_dynstring_new; procedure tbs_dynstring_free(id: tbs_dynstring) is begin ids(id).lenfree:=freelist; -- save old freelist freelist:=id; end procedure tbs_dynstring_free; impure function tbs_dynstring_get(id: tbs_dynstring) return string is begin return ids(id).str(1 to ids(id).lenfree); end function tbs_dynstring_get; impure function tbs_dynstring_length(id: tbs_dynstring) return natural is begin return ids(id).lenfree; end function tbs_dynstring_length; procedure tbs_dynstring_set(id: tbs_dynstring; s: string:=""; minlen: natural:=0) is variable bytes: natural; begin bytes:=s'length; if bytes<=C_MINLENGTH then bytes:=C_MINLENGTH; end if; if minlen /= 0 and bytes<minlen then bytes:=minlen; end if; if ids(id).str=null then -- if not previously allocated, simply allocate ids(id).str:=new string(1 to bytes); elsif ids(id).str'length<bytes then -- reallocated deallocate(ids(id).str); ids(id).str:=new string(1 to bytes); end if; -- set str and length ids(id).str(1 to s'length):=s; ids(id).lenfree:=s'length; end procedure tbs_dynstring_set; end tbs_dynstring; Hubble |
|
|
|
#7 |
|
Posts: n/a
|
You can do what you want quite legally in VHDL but it takes a few steps.
Basically it involves defining a new resolved type based on integer and introducing a package containing a global signal of the new resolved integer type which is referenced by all DUT instances. This is from memory, as I don't have the code here on my laptop but it is something along these lines: 1) Define the resolved type based on integer (or unsigned or anything else) 2) Define a signal og the type defined in 1) in a global package. Initialise this signal to 0; 3) In each of your instances add an initialisation process. The initialisation process does the following: a) read the external signal b) attempt to increment the external signal c) wait 0 ns (VERY IMPORTANT) d) read back the external signal e) if the read-back value is the same as the locally computed incremented value then THIS instance has succeeded so this part of the initialisation loop. If not, repeat the above from a) downward. f) When THIS instance has won the resolved increment step, use the previous external signal value as your local index. I hope I didn't miss something here, but I know it basically works. I used the same principle in a previous test bench to allow multiple processes to write strings to a shared external string signal without consuming time. It may be the weekend before I find my code. If you are still having problems drop a line to the NG on friday. Regards, Charles Charles, SAG |
|
|
|
#8 |
|
Posts: n/a
|
Thanky you, Charles
I already thought of this a bit, but it seemed to me somewhat complicated. So in the package, dyn_string_new and dynstring_free have to arbirtrate through the external signal and -unfortunatly- wait for 0 ns (in some cases several times), so they cannot be used in processes with a sensitivity list. Not a real problem for me. Since my "testbench bus" already uses self defined resolved signals for the responses, it should not be a problem for me to implement it like this. Regards Hubble. Hubble |
|
|
|
#9 |
|
Posts: n/a
|
Hi Hubble,
I have since taken a look at my old code. I was mistaken in thinking I had the same situation as you. My resolution function received a structure containing a text-message, the requesting unit-id and the resolution-winner id (which was passed in on a generic). The units repeatedly posted the message until they were accepted as winner. Anyway, to your situation, there are however two ways I can think of that might work. 1) Create a file of unique integers one per line. Declare the file in your package. The init routine in your unit reads a line and extracts the integer which then becomes the unit-id. This should work because, to my knowledge, the LRM guarantees serialisation as long as the file is open globally and your individual processes always read a line at a time. 2) If you don't like file-io, hash your unit names (or at least as much of the name required for the smallest unique string) to a unique simulation time (e.g. in fs or ps). When each unit reaches it's unique simulation time it takes the current value of a global integer and then increments it. Regards, Charles Charles, SAG |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| auto printer change when moving laptop from office to home | moorpheus | Hardware | 0 | 01-17-2008 12:38 PM |
| auto shutdown of VLAN | vthakur001 | Hardware | 0 | 11-28-2007 03:06 PM |
| ISDN cards auto detect!!!! | Harinath | Hardware | 0 | 09-12-2006 12:25 PM |
| Auto Cad | donvier | Hardware | 0 | 09-10-2006 07:57 AM |
| auto start, and auto replay possible? | Dik Mus | DVD Video | 3 | 10-28-2003 12:09 PM |