Merge branch 'master' into verilog-ams
This commit is contained in:
commit
30570adf31
|
|
@ -386,82 +386,6 @@ at <src>.
|
|||
|
||||
<label> .array "name", <src> ;
|
||||
|
||||
MEMORY STATEMENTS:
|
||||
|
||||
Memories are arrays of words, each word a vvp_vector4_t vector of the
|
||||
same width. The memory is canonically addressed as a 1-dimensional
|
||||
array of words, although indices are stored with the memory for
|
||||
calculating a canonical address from a multi-dimensional address.
|
||||
|
||||
Three types of memory statement perform (1) creation of a memory, (2)
|
||||
connecting a read port to an existing memory, and (3) initializing the
|
||||
memory's contents.
|
||||
|
||||
<label> .mem "name", <msb>,<lsb>, <last>,<first> ... ;
|
||||
|
||||
The pair of numbers <msb>,<lsb> defines the word width. The pair
|
||||
<last>,<first> defines the address range. Multiple address ranges are
|
||||
allowed for multidimensional indexing. This statement creates the
|
||||
memory array and makes it available to procedural code.
|
||||
|
||||
Procedural access to the memory references the memory as single array
|
||||
of words, with the base address==0, and the last address the size (in
|
||||
words) of the memory -1. It is up to the compiler to convert Verilog
|
||||
index sets to a canonical address. The multi-dimensional index set is
|
||||
available for VPI use.
|
||||
|
||||
Structural read access is implemented in terms of address and data
|
||||
ports. The addresses applied to the address port are expected to be
|
||||
in canonical form.
|
||||
|
||||
A read port is a functor that takes a single input, the read address,
|
||||
and outputs the word value at the given (canonical) address.
|
||||
|
||||
<label> .mem/port <memid>, <address> ;
|
||||
|
||||
<label> identifies the vector of output functors, to allow connections
|
||||
to the data output. <memid> is the label of the memory.
|
||||
|
||||
Any address input change, or any change in the addressed memory
|
||||
contents, is immediately propagated to the port output.
|
||||
|
||||
A write port is a superset of a read port. It is a 4-input functor
|
||||
that accepts the word address, an event input, a write enable input,
|
||||
and the data input.
|
||||
|
||||
<label> .mem/port <memid>, <address>, <event>, <we>, <data> ;
|
||||
|
||||
<event> is an event functor that triggers a write, if the <we> input
|
||||
is true. <data> is the input that connect to the data input
|
||||
port. For asynchronous transparent write operation, connect
|
||||
<event> to C4<z>, the RAM will transparently follow any changes on
|
||||
address and data lines, while <we> is true.
|
||||
|
||||
There is no Verilog construct that calls for a structural write port
|
||||
to a memory, but synthesis may ask for lpm_ram_d[pq] objects.
|
||||
|
||||
To initialize a memory, use:
|
||||
|
||||
.mem/init <memid> <start>, val , val ... ;
|
||||
|
||||
<memid> is the label of the memory, and the <start> is the start
|
||||
address (canonical) of the first word to be initialized. The start
|
||||
address allows multiple statements be used to initialize words of a
|
||||
memory.
|
||||
|
||||
The values are one per word.
|
||||
|
||||
Procedural access to the memory employs an index register to address a
|
||||
bit location in the memory, via the commands:
|
||||
|
||||
%load/m <bit>, <memid> ;
|
||||
%set/m <memid>, <bit> ;
|
||||
%assign/m <memid>, <delay>, <bit> ;
|
||||
|
||||
The memory bit is addressed by index register 3. The value of
|
||||
register 3 is the index in the memory's bit space, where each data
|
||||
word occupies a multiple of four bits.
|
||||
|
||||
|
||||
EVENT STATEMENTS
|
||||
|
||||
|
|
|
|||
20
vvp/array.cc
20
vvp/array.cc
|
|
@ -354,9 +354,14 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
|
|||
|
||||
assert(obj);
|
||||
unsigned index = decode_array_word_pointer(obj, parent);
|
||||
unsigned width = parent->vals_width;
|
||||
|
||||
vpip_vec4_get_value(parent->vals[index], parent->vals_width,
|
||||
false, value);
|
||||
/* If we don't have a value yet just return X. */
|
||||
if (parent->vals[index].size() == 0) {
|
||||
vpip_vec4_get_value(vvp_vector4_t(width), width, false, value);
|
||||
} else {
|
||||
vpip_vec4_get_value(parent->vals[index], width, false, value);
|
||||
}
|
||||
}
|
||||
|
||||
static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int flags)
|
||||
|
|
@ -493,8 +498,15 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value)
|
|||
assert(parent->vals);
|
||||
assert(obj->address < parent->array_count);
|
||||
|
||||
vpip_vec4_get_value(parent->vals[obj->address],
|
||||
parent->vals_width, false, value);
|
||||
unsigned index = obj->address;
|
||||
unsigned width = parent->vals_width;
|
||||
|
||||
/* If we don't have a value yet just return X. */
|
||||
if (parent->vals[index].size() == 0) {
|
||||
vpip_vec4_get_value(vvp_vector4_t(width), width, false, value);
|
||||
} else {
|
||||
vpip_vec4_get_value(parent->vals[index], width, false, value);
|
||||
}
|
||||
}
|
||||
|
||||
static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int)
|
||||
|
|
|
|||
|
|
@ -80,20 +80,6 @@ is given by the <delayx> value. This should not be 0, 1 or 3, of course,
|
|||
since these registers contain the vector width, base part select and
|
||||
word address.
|
||||
|
||||
* %assign/mv <memory-label>, <delay>, <bit> (DEPRECATED)
|
||||
|
||||
the %assign/mv instruction assigns a vector value to a word in the
|
||||
labeled memory. The <delay> is the delay in simulation time to the
|
||||
assignment (0 for non-blocking assignment) and the <bit> is the base
|
||||
of the vector to write.
|
||||
|
||||
The width of the word is retrieved from index register 0.
|
||||
|
||||
The base of a part select is retrieved from index register 1.
|
||||
|
||||
The address of the word in the memory is from index register 3. The
|
||||
address is canonical form.
|
||||
|
||||
* %assign/v0 <var-label>, <delay>, <bit>
|
||||
* %assign/v0/d <var-label>, <delayx>, <bit>
|
||||
|
||||
|
|
@ -443,12 +429,6 @@ This instruction is similar to %load/av, but it loads only a single
|
|||
bit, and the <index> is the selector for the bit to use. If <index> is
|
||||
out of range, then x is loaded.
|
||||
|
||||
* %load/mv <bit>, <memory-label>, <wid>
|
||||
|
||||
this instruction loads a word from the specified memory. The word
|
||||
address is in index register 3. The width should match the width of
|
||||
the memory word.
|
||||
|
||||
* %load/nx <bit>, <vpi-label>, <idx>
|
||||
|
||||
This instruction load a value from a .net object bit. Since .net
|
||||
|
|
@ -668,19 +648,6 @@ width is implied from the <wid> that is the argument. This is the part
|
|||
The address (in canonical form) is precalculated and loaded into index
|
||||
register 3. This is the address of the word within the array.
|
||||
|
||||
* %set/mv <memory-label>, <bit>, <wid>
|
||||
|
||||
This sets a thread vector to a memory word. The <memory-label>
|
||||
addresses a memory device, and the <bit>,<wid> describe a vector to be
|
||||
written. Index register 3 contains the address of the word within the
|
||||
memory.
|
||||
|
||||
The base of a part select is retrieved from index register 1.
|
||||
|
||||
The address (in canonical form) is precalculated and loaded into index
|
||||
register 3.
|
||||
|
||||
|
||||
* %set/wr <vpi-label>, <bit>
|
||||
|
||||
This instruction writes a real word to the specified VPI-like object.
|
||||
|
|
|
|||
Loading…
Reference in New Issue