Skip to content

Commit

Permalink
add the ghdl-intro.h (2D std_logic)
Browse files Browse the repository at this point in the history
  • Loading branch information
RocketRoss authored and umarcor committed Sep 1, 2020
1 parent 4109f9e commit 0503494
Show file tree
Hide file tree
Showing 5 changed files with 354 additions and 0 deletions.
26 changes: 26 additions & 0 deletions doc/vhpidirect/examples/cinterface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@
C interface
###########

.. IMPORTANT::
This header is a compilation of some functions that are deemed helpful when cosimulating GHDL with C.
It is by no means a requirement of such cosimulation. Rather it aims to provide a framework to
kickstart any complex cosimulations with C.

.. _COSIM:VHPIDIRECT:Examples:cinterface:intro:

:cosimtree:`C Interface Introduction <vhpidirect/quickstart/cinterface/intro>`
******************************************************************************

The primary complex task that the ``ghdl.h`` file intends on making easy is the sharing of unbounded arrays
between VHDL and C. The data type that is defined for a VHDL unbounded array is ``ghdl_NaturalDimArr_t``.
Unbounded arrays (of any primitive type) are passed to C from VHDL as a pointer to this type.

Provided is the ``ghdlToArray(ghdl_NaturalDimArr_t* ptr, void** vec, int* len, int num)`` function, which
enables handling a VHDL unbounded array within C.

The converse operations (taking a C array to an unbounded array in VHDL) are handled by the provided
``ghdlFromPointer`` and ``ghdlFromArray`` functions.

getFlatArrayIndex
testCinterface
freePointers
getLogicVec
getULogicMat

:cosimtree:`demo <vhpidirect/cinterface/demo>`
**********************************************

Expand Down
123 changes: 123 additions & 0 deletions vhpidirect/cinterface/intro/caux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <string.h>

#include <ghdl-intro.h>

char* vec;
bounds_t* vec_bounds;
char* mat;
bounds_t* mat_bounds;
int* len;
int* len2;

int getFlatArrayIndex(int* dimIndex, int* lens, int dims){
if(dims == 1){
return dimIndex[0];
}
else{
return dimIndex[dims-1] + (lens[dims-1]*getFlatArrayIndex(dimIndex, lens, dims-1));
}
}

void testCinterface(
ghdl_NaturalDimArr_t* v_vec_logic,
ghdl_NaturalDimArr_t* v_mat_ulogic
) {

//VECTOR 1D////////////////////////////////////////
printf("\nvector\n");
printUnconstrained(v_vec_logic, 1);
len = malloc(1 * sizeof(int));

char* vec;
ghdlToArray(v_vec_logic, (void**)&vec, len, 1);
for (int i = 0; i < len[0]; i++)
{
printf("C vec_logic[%d] = %c\n", i, HDL_LOGIC_CHAR[vec[i]]);
}
printf("v_vec_logic : %p [%d]\n\n", vec, len[0]);

//MATRIX 2D////////////////////////////////////////
printf("\nmatrix\n");
printUnconstrained(v_mat_ulogic, 2);
len2 = malloc(2 * sizeof(int));

char* mat_ulogic;
ghdlToArray(v_mat_ulogic, (void**)&mat_ulogic, len2, 2);
for (int i = 0; i < len2[0]; i++)
{
for (int j = 0; j < len2[1]; j++)
{
int ind[] = {i, j};
int flatIndex = getFlatArrayIndex(ind, len2, 2);
printf("[%d][%d] = %c (%d)\t", i, j, HDL_LOGIC_CHAR[mat_ulogic[flatIndex]], flatIndex);
}
printf("\n");
}
printf("v_mat_ulogic : %p [%d,%d]\n\n", mat_ulogic, len2[0], len2[1]);

printf("end testCinterface\n\n");
}

void freePointers(){
free(vec);
free(vec_bounds);
free(mat);
free(mat_bounds);
free(len);
free(len2);
}

void getLogicVec(ghdl_NaturalDimArr_t* ptr){
char vecArr[9];
int32_t len[1] = {9};
for(int i = 0; i < len[0]; i++){
vecArr[i] = i;
}
printf("\n");

*ptr = ghdlFromArray((void *)vecArr, len, 1, sizeof(char));
vec_bounds = ptr->bounds;
vec = ptr->array;
printf("1D Array Logic Values [%d]:\n", len[0]);
for(int x = 0; x < len[0]; x++){
printf("[%d] = %c\t", x, HDL_LOGIC_CHAR[x]);
assert(((char*)ptr->array)[x] == vecArr[x]);
//ghdlFromArray creates a deep-copy of the information, so this change is not reflected in VHDL
vecArr[x] = 0;
}

}

void getULogicMat(ghdl_NaturalDimArr_t* ptr){
mat = malloc(3*3*sizeof(int32_t));
int32_t len[2] = {3, 3};
int x, y, ind[2];
for ( x=0 ; x<len[0] ; x++ ) {
ind[0] = x;
for ( y=0 ; y<len[1] ; y++ ) {
ind[1] = y;
int flatIndex = getFlatArrayIndex(ind, len, 2);
mat[flatIndex] = flatIndex%9;
}
}
//ghdl_NaturalDimArr_t* ptr = malloc(sizeof(ghdl_NaturalDimArr_t));
*ptr = ghdlFromPointer((void *)mat, len, 2);
mat_bounds = ptr->bounds;
assert(mat == ptr->array);
printf("\n2D Array values [%d,%d]:\n", len[0], len[1]);
for ( x=0 ; x<len[0] ; x++ ) {
ind[0] = x;
for ( y=0 ; y<len[1] ; y++ ) {
ind[1] = y;
int flatIndex = getFlatArrayIndex(ind, len, 2);
printf("mat[%d][%d] = %c\t", x, y, HDL_LOGIC_CHAR[mat[flatIndex]]);
assert(((char*)ptr->array)[flatIndex] == mat[flatIndex]);
}
printf("\n");
}
}
125 changes: 125 additions & 0 deletions vhpidirect/cinterface/intro/ghdl-intro.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#ifndef GHDL_TYPES_INTRO_H
#define GHDL_TYPES_INTRO_H

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

// Range/bounds of a dimension of an unconstrained array with dimensions of type 'natural'
typedef struct {
int32_t left;
int32_t right;
int32_t dir;
int32_t len;
} bounds_t;

// Unconstrained array with dimensions of type 'natural'
typedef struct {
void* array;
bounds_t* bounds;
} ghdl_NaturalDimArr_t;

/*
* Print custom types
*/

void printUnconstrained(ghdl_NaturalDimArr_t* ptr, int dims) {
printf("array: %p\n", ptr->array);
printf("bounds: %p\n", ptr->bounds);
int i;
for(i = 0; i < dims; i++){
printf("bounds%d.left: %d\n", i, ptr->bounds[i].left);
printf("bounds%d.right: %d\n", i, ptr->bounds[i].right);
printf("bounds%d.dir: %d\n", i, ptr->bounds[i].dir);
printf("bounds%d.len: %d\n", i, ptr->bounds[i].len);
}
}

/*
* Convert a fat pointer of an uncontrained array with (up to 3) dimensions of type 'natural', to C types
*/

void ghdlToArray(ghdl_NaturalDimArr_t* ptr, void** vec, int* len, int num) {
assert(ptr != NULL);
assert(ptr->bounds != NULL);
*vec = ptr->array;

for (int i = 0; i < num; i++)
{
len[i] = ptr->bounds[i].len;
}
}

/*
* Helper to setup the bounds_t for ghdlFromArray
*/

void ghdlSetRange(bounds_t* r, int len, bool reversed){
if(!reversed){//to
r->left = 0;
r->right = len-1;
r->dir = 0;
r->len = len;
}
else{//downto
r->left = len-1;
r->right = 0;
r->dir = 1;
r->len = len;
}
}

/*
* Convert C types representing an unconstrained array with a dimension of type 'natural', to a fat pointer
*/


ghdl_NaturalDimArr_t ghdlFromPointer(void* vec, int* len, int dims) {
bounds_t* b = malloc(sizeof(bounds_t)*dims);
assert(b != NULL);

for (int i = 0; i < dims; i++)
{
ghdlSetRange(b+i, len[i], false);
}

void *a = vec;
return (ghdl_NaturalDimArr_t){.array= a, .bounds=b};
}

ghdl_NaturalDimArr_t ghdlFromArray(void* vec, int* len, int dims, int sizeOfDataType) {
bounds_t* b = malloc(sizeof(bounds_t)*dims);
int totalSize = 1;
for (int i = 0; i < dims; i++)
{
totalSize *= len[i];
ghdlSetRange(b+i, len[i], false);
}

void *a = malloc(sizeOfDataType * totalSize);
memcpy(a, vec, sizeOfDataType * totalSize);

return (ghdl_NaturalDimArr_t){.array= a, .bounds=b};
}

/*
* Handle C char for the appropriate values in std_ulogic and std_logic.
*/

// @RocketRoss
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,
};

#endif
11 changes: 11 additions & 0 deletions vhpidirect/cinterface/intro/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env sh

cd "$(dirname $0)"

set -e

ghdl -a --std=08 -O0 -g tb.vhd
ghdl -e --std=08 -O0 -g -Wl,-ggdb3 -Wl,-I./ -Wl,caux.c tb &&
./tb
#valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out.txt ./tb &&
#cat valgrind-out.txt | grep -A 4 "LEAK SUMMARY"
69 changes: 69 additions & 0 deletions vhpidirect/cinterface/intro/tb.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use std.textio.line;

library ieee;
use ieee.std_logic_1164.all;

entity tb is
end;

architecture arch of tb is

type ulogic_mat_t is array(natural range <>, natural range <>) of std_ulogic;

begin
process

procedure testCinterface(
v_1D_logic : std_logic_vector;
v_1D_ulogic : ulogic_mat_t
) is
begin assert false report "VHPIDIRECT testCinterface" severity failure; end;
attribute foreign of testCinterface : procedure is "VHPIDIRECT testCinterface";

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

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


procedure freeCPointers is
begin assert false report "VHPIDIRECT freeCPointers" severity failure; end;
attribute foreign of freeCPointers : procedure is "VHPIDIRECT freePointers";

constant g_logic_vec: std_logic_vector := getLogicVec;
constant g_ulogic_mat: ulogic_mat_t := getULogicMat;

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

variable spareInt: integer;
begin

testCinterface(
v_1D_logic => ('1', 'H', 'X'),
v_1D_ulogic => (('1', 'H', 'X'), ('1', 'H', 'X'))
);

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

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

spareInt := 0;
report "g_ulogic_mat'length: " & integer'image(g_ulogic_mat'length) severity note;
for i in g_ulogic_mat'range loop
for j in g_ulogic_mat'range(1) loop
report "Asserting Mat [" & integer'image(i) & "," & integer'image(j) & "]: " & std_logic'image(g_ulogic_mat(i,j)) severity note;
assert g_ulogic_mat(i,j) = logicArray(spareInt) severity failure;
spareInt := spareInt + 1;
end loop ;
end loop ;

freeCPointers;
wait;
end process;
end;

0 comments on commit 0503494

Please sign in to comment.