Skip to content

Commit

Permalink
vhpidirect: add 'arrays/logicvector'
Browse files Browse the repository at this point in the history
  • Loading branch information
radonnachie authored and umarcor committed Apr 21, 2020
1 parent 9547159 commit 9c06dfd
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
vhpidirect/shared/dlopen,
vhpidirect/shared/shghdl,
vhpidirect/arrays/intvector,
vhpidirect/arrays/logicvector,
]
runs-on: ubuntu-latest
env:
Expand Down Expand Up @@ -57,6 +58,7 @@ jobs:
#vhpidirect/shared/dlopen, ! dlfcn.h is not available on win
#vhpidirect/shared/shghdl, ! dlfcn.h is not available on win
vhpidirect/arrays/intvector,
vhpidirect/arrays/logicvector,
]
runs-on: windows-latest
env:
Expand Down
54 changes: 54 additions & 0 deletions doc/vhpidirect/examples/arrays.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,57 @@ functionally equivalent:
Note that VHPIDIRECT resources are defined in a package (as shown in :ref:`COSIM:VHPIDIRECT:Examples:quickstart:package`).
The same package and the corresponding C source file (``caux.c``) are used in both examples, even though ``vhdlalloc`` does
not need neither ``[c_]allocIntArr`` nor ``[c_]freePointer``.

.. _COSIM:VHPIDIRECT:Examples:arrays:logicvectors:

:cosimtree:`logicvector <vhpidirect/arrays/logicvector>`
**************************************************************

Commonly signals in VHDL are of a logic type or a vector thereof (``std_logic`` and ``std_logic_vector``), coming from IEEE's ``std_logic_1164`` package.
These types can hold values other than high and low (``1`` and ``0``) and are enumerated as:

0. 'U'
1. 'X'
2. '0'
3. '1'
4. 'Z'
5. 'W'
6. 'L'
7. 'H'
8. '-'

As mentioned in :ref:`Restrictions_on_foreign_declarations`:

- Because the number of enumeration values is less than 256, logic values are transported in 8 bit words (a ``char`` type in C).

- In this example two declarations make handling logic values in C a bit easier:

- Providing logic values in C as their enumeration numbers is simplified with the use of a matching enumeration, ``HDL_LOGIC_STATES``.
- Printing out a logic value's associated character is also simplified with the ``const char HDL_LOGIC_CHAR[]`` declaration.

- Logic vectors, of a bounded size, can be easily created in C as a ``char[]`` and passed to VHDL to be read as an ``access`` type in VHDL, in this case an access of a subtype of std_logic_vector.


This example builds on the integer vector example (:ref:`COSIM:VHPIDIRECT:Examples:arrays:intvector`), by instead passing an array of logic values. Foreign subprograms are declared that enable receiving the size of two different logic vectors as well as the vectors themselves from C. There is only one subprogram to get the size of both C arrays, and it takes in an integer to determine which array's size gets returned.

.. HINT::
The ``getLogicVecSize`` in VHDL is declared as receiving a ``boolean`` argument. In C the function is declared to receive an ``char`` argument. The VHDL booleans ``false`` and ``true`` are enumerations, and have integer values, ``0`` and ``1`` respectively. As with the logic values, the boolean enumerations use fewer than 8 bits, so the single byte in C's ``char`` variable receives the VHDL enumeration correctly.

For illustrative purposes, the two vectors are populated with logic values in different ways:

- LogicVectorA's indices are manually filled with enumeration values from HDL_LOGIC_STATES.

- .. code-block:: C

logic_vec_A[0] = HDL_U;

- LogicVectorB's indices are filled with an integer value.

- .. code-block:: C

for(int i = 0; i < SIZE_LOGIC_VEC_B; i++){
logic_vec_B[i] = 8-i;
}

.. ATTENTION::
The integer values that are given to ``char`` variables in C which are intended to be read as VHDL logic values, must be limited to [0, 8]. This ensures that they represent one of the 9 enumerated logic values.
52 changes: 52 additions & 0 deletions vhpidirect/arrays/logicvector/caux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <stdio.h>
#define SIZE_LOGIC_VEC_A (sizeof(logic_vec_A)/sizeof(char))
#define SIZE_LOGIC_VEC_B (sizeof(logic_vec_B)/sizeof(char))

static const char HDL_LOGIC_CHAR[] = { 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'};

enum HDL_LOGIC_STATES {
HDL_U = 0,
HDL_X = 1,
HDL_0 = 2,
HDL_1 = 3,
HDL_Z = 4,
HDL_W = 5,
HDL_L = 6,
HDL_H = 7,
HDL_D = 8,
};

char logic_vec_A[3];
char logic_vec_B[6];

int getLogicVecSize(char returnA){
if(returnA)
return SIZE_LOGIC_VEC_A;
else
return SIZE_LOGIC_VEC_B;
}

char* getLogicVecA(){
//The HDL_LOGIC_STATES enum is used
logic_vec_A[0] = HDL_U;
logic_vec_A[1] = HDL_X;
logic_vec_A[2] = HDL_0;

printf("A: 1D Array Logic Values [%ld]:\n", SIZE_LOGIC_VEC_A);
for(int i = 0; i < SIZE_LOGIC_VEC_A; i++){
printf("[%d] = %c\t", i, HDL_LOGIC_CHAR[logic_vec_A[i]]);
}
printf("\n");
return logic_vec_A;
}

char* getLogicVecB(){
//The equivalent value of HDL_LOGIC_STATES is used
printf("B: 1D Array Logic Values [%ld]:\n", SIZE_LOGIC_VEC_B);
for(int i = 0; i < SIZE_LOGIC_VEC_B; i++){
logic_vec_B[i] = 8-i;//The last 'SIZE_LOGIC_VEC_B' HDL_LOGIC values, in reverse order.
printf("[%d] = %c\t", i, HDL_LOGIC_CHAR[logic_vec_B[i]]);
}
printf("\n");
return logic_vec_B;
}
14 changes: 14 additions & 0 deletions vhpidirect/arrays/logicvector/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env sh

cd "$(dirname $0)"

set -e

echo "Analyze tb.vhd"
ghdl -a tb.vhd

echo "Build tb (with caux.c)"
ghdl -e -Wl,caux.c tb

echo "Execute tb"
./tb
53 changes: 53 additions & 0 deletions vhpidirect/arrays/logicvector/tb.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
library ieee;
use ieee.std_logic_1164.all;

entity tb is
end;

architecture arch of tb is
begin

process

function getLogicVecSize(returnSizeOfA: boolean) return integer is
begin assert false report "VHPIDIRECT getLogicVecSize" severity failure; end;
attribute foreign of getLogicVecSize : function is "VHPIDIRECT getLogicVecSize";

subtype logic_vec_a_t is std_logic_vector(0 to getLogicVecSize(true)-1);
type logic_vec_a_ptr_t is access logic_vec_a_t;

subtype logic_vec_b_t is std_ulogic_vector(0 to getLogicVecSize(false)-1);
type logic_vec_b_ptr_t is access logic_vec_b_t;

function getLogicVecA return logic_vec_a_ptr_t is
begin assert false report "VHPIDIRECT getLogicVecA" severity failure; end;
attribute foreign of getLogicVecA : function is "VHPIDIRECT getLogicVecA";

function getLogicVecB return logic_vec_b_ptr_t is
begin assert false report "VHPIDIRECT getLogicVecB" severity failure; end;
attribute foreign of getLogicVecB : function is "VHPIDIRECT getLogicVecB";

variable g_logic_vec_a: logic_vec_a_ptr_t := getLogicVecA;
variable g_logic_vec_b: logic_vec_b_ptr_t := getLogicVecB;

constant logicArray: std_logic_vector(0 to 8) := ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-');

begin

report "g_logic_vec_a'length: " & integer'image(g_logic_vec_a'length) severity note;

for x in g_logic_vec_a'range loop
report "Asserting VecA [" & integer'image(x) & "]: " & std_logic'image(g_logic_vec_a(x)) severity note;
assert g_logic_vec_a(x) = logicArray(x) severity failure;
end loop;

report "g_logic_vec_b'length: " & integer'image(g_logic_vec_b'length) severity note;

for x in g_logic_vec_b'range loop
report "Asserting VecB [" & integer'image(x) & "]: " & std_logic'image(g_logic_vec_b(x)) severity note;
assert g_logic_vec_b(x) = logicArray(8-x) severity failure;
end loop;

wait;
end process;
end;

0 comments on commit 9c06dfd

Please sign in to comment.