VHPIDIRECT Demo¶
The following sources show how to pass different types of data to/from VHDL and C through VHPIDIRECT.
Note
ghdl.h
is a reference of GHDL’s ABI, which can be imported to easily convert data types. However, the ABI is not settled, so it might change without prior notice.
#!/usr/bin/env sh
cd "$(dirname $0)"
set -e
ghdl -a -O0 -g tb.vhd
ghdl -e -O0 -g -Wl,-I./ -Wl,main.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"
use std.textio.line;
library ieee;
use ieee.std_logic_1164.all;
entity tb is
end;
architecture arch of tb is
type rec_t is record
r_char: character;
r_int : integer;
end record;
type enum_t is (standby, start, busy, done);
type int_vec_t is array(natural range <>) of integer;
type real_vec_t is array(natural range <>) of real;
type bool_vec_t is array(natural range <>) of boolean;
type time_vec_t is array(natural range <>) of time;
type rec_vec_t is array(natural range <>) of rec_t;
type enum_vec_t is array(natural range <>) of enum_t;
type real_2vec_t is array (natural range <>, natural range <>) of real;
type int_2vec_t is array(natural range <>, natural range <>) of integer;
type int_3vec_t is array(natural range <>, natural range <>, natural range <>) of integer;
begin
process
procedure testCinterface(
v_logic : std_logic := 'H';
v_ulogic : std_ulogic := 'Z';
v_char : character := 'k';
v_int : integer := -6;
v_nat : natural := 9;
v_pos : positive := 3;
v_real : real := 3.34;
v_bool : boolean := true;
v_bit : bit := '1';
v_time : time := 20 ns;
v_rec : rec_t := ('y', 5);
v_enum : enum_t := busy;
v_str : string := "hellostr";
v_vec_int : int_vec_t := (11, 22, 33, 44, 55);
v_vec_real : real_vec_t := (0.5, 1.75, 3.33, -0.125, -0.67, -2.21);
v_vec_bool : bool_vec_t := (false, true, true, false);
v_vec_bit : bit_vector := ('1', '0', '1', '0');
v_vec_time : time_vec_t := (1 ns, 50 ps, 1.34 us);
v_vec_rec : rec_vec_t := (('x', 17),('y', 25));
v_vec_enum : enum_vec_t := (start, busy, standby);
v_2vec_real : real_2vec_t := ((0.1, 0.25, 0.5),(3.33, 4.25, 5.0));
v_mat_int : int_2vec_t := ((11, 22, 33), (44, 55, 66));
v_3d_int : int_3vec_t := ( ((11, 22, 33), (44, 55, 66)), ((77, 88, 99), (110, 121, 132)) )
) is
begin assert false report "VHPIDIRECT testCinterface" severity failure; end;
attribute foreign of testCinterface : procedure is "VHPIDIRECT testCinterface";
function getString return string is
begin assert false report "VHPIDIRECT getString" severity failure; end;
attribute foreign of getString : function is "VHPIDIRECT getString";
function getIntVec return int_vec_t is
begin assert false report "VHPIDIRECT getIntVec" severity failure; end;
attribute foreign of getIntVec : function is "VHPIDIRECT getIntVec";
function getIntMat return int_2vec_t is
begin assert false report "VHPIDIRECT getIntMat" severity failure; end;
attribute foreign of getIntMat : function is "VHPIDIRECT getIntMat";
function getInt3d return int_3vec_t is
begin assert false report "VHPIDIRECT getInt3d" severity failure; end;
attribute foreign of getInt3d : function is "VHPIDIRECT getInt3d";
function getLine return line is
begin assert false report "VHPIDIRECT getLine" severity failure; end;
attribute foreign of getLine : function is "VHPIDIRECT getLine";
constant g_str: string := getString;
constant g_int_vec: int_vec_t := getIntVec;
constant g_int_mat: int_2vec_t := getIntMat;
constant g_int_3d: int_3vec_t := getInt3d;
variable g_line: line := getLine;
function getLogicValue(logic : std_logic) return integer is
begin assert false report "VHPIDIRECT getLogicValue" severity failure; end;
attribute foreign of getLogicValue : function is "VHPIDIRECT getLogicIntValue";
function getUlogicValue(logic : std_ulogic) return integer is
begin assert false report "VHPIDIRECT getUlogicValue" severity failure; end;
attribute foreign of getUlogicValue : function is "VHPIDIRECT getLogicIntValue";
function getBitValue(bitVal : bit) return integer is
begin assert false report "VHPIDIRECT getBitValue" severity failure; end;
attribute foreign of getBitValue : function is "VHPIDIRECT getLogicIntValue";
procedure freeCPointers is
begin assert false report "VHPIDIRECT freeCPointers" severity failure; end;
attribute foreign of freeCPointers : procedure is "VHPIDIRECT freePointers";
variable spareInt: integer;
begin
testCinterface(
v_logic => 'H',
v_ulogic => 'Z',
v_char => 'k',
v_int => -6,
v_nat => 9,
v_pos => 3,
v_real => 3.34,
v_bool => true,
v_bit => '1',
v_time => 20 ns,
v_rec => ('y', 5),
v_enum => busy,
v_str => "hellostr",
v_vec_int => (11, 22, 33, 44, 55),
v_vec_real => (0.5, 1.75, 3.33, -0.125, -0.67, -2.21),
v_vec_bool => (false, true, true, false),
v_vec_bit => ('1', '0', '1', '0'),
v_vec_time => (1 ns, 50 ps, 1.34 us),
v_vec_rec => (('x', 17),('y', 25)),
v_vec_enum => (start, busy, standby),
v_2vec_real => ((0.1, 0.25, 0.5),(3.33, 4.25, 5.0)),
v_mat_int => ((11, 22, 33), (44, 55, 66)),
v_3d_int => ( ((11, 22, 33), (44, 55, 66)), ((77, 88, 99), (110, 121, 132)) )
);
report "g_str'length: " & integer'image(g_str'length) severity note;
if g_str'length /= 0 then
report "g_str: " & g_str severity note;
end if;
report "string: " & getString severity note;--g_str results from calling getString(), calling it again means a malloc'd pointer can be lost.
report "g_int_vec'length: " & integer'image(g_int_vec'length) severity note;
for x in g_int_vec'range loop
report integer'image(x) & ": " & integer'image(g_int_vec(x)) severity note;
assert g_int_vec(x) = 11*(x+1) severity warning;
end loop;
report "g_line: " & g_line.all severity note;
report "getLine: " & getLine.all severity note;--g_line results from calling getLine(), calling it again means a malloc'd pointer can be lost.
assert getLine.all = "HELLO WORLD" severity failure;
assert 0 = getLogicValue('U') severity error;
assert 1 = getLogicValue('X') severity error;
assert 2 = getLogicValue('0') severity error;
assert 3 = getLogicValue('1') severity error;
assert 4 = getLogicValue('Z') severity error;
assert 5 = getLogicValue('W') severity error;
assert 6 = getLogicValue('L') severity error;
assert 7 = getLogicValue('H') severity error;
assert 8 = getLogicValue('-') severity error;
assert 0 = getUlogicValue('U') severity error;
assert 1 = getUlogicValue('X') severity error;
assert 2 = getUlogicValue('0') severity error;
assert 3 = getUlogicValue('1') severity error;
assert 4 = getUlogicValue('Z') severity error;
assert 5 = getUlogicValue('W') severity error;
assert 6 = getUlogicValue('L') severity error;
assert 7 = getUlogicValue('H') severity error;
assert 8 = getUlogicValue('-') severity error;
assert 0 = getBitValue('0') severity error;
assert 1 = getBitValue('1') severity error;
spareInt := 0;
report "g_int_mat'length: " & integer'image(g_int_mat'length) severity note;
for i in g_int_mat'range(1) loop
for j in g_int_mat'range(2) loop
spareInt := spareInt + 1;
report "Asserting Mat [" & integer'image(i) & "," & integer'image(j) & "]: " & integer'image(g_int_mat(i, j)) severity note;
assert g_int_mat(i, j) = 11*spareInt severity error;
end loop ;
end loop ;
spareInt := 0;
report "g_int_3d'length: " & integer'image(g_int_3d'length) severity note;
for i in g_int_3d'range(1) loop
for j in g_int_3d'range(2) loop
for k in g_int_3d'range(3) loop
spareInt := spareInt + 1;
report "Asserting 3D [" & integer'image(i) & "," & integer'image(j) & "," & integer'image(k) & "]: " & integer'image(g_int_3d(i, j, k)) severity note;
assert g_int_3d(i, j, k) = 11*spareInt severity error;
end loop;
end loop ;
end loop ;
freeCPointers;
report "No errors/failures. Concluding testbench." severity note;
wait;
end process;
end;
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <string.h>
#include <ghdl.h>
typedef struct rec_t {
char r_char;
int32_t r_int;
} rec_t;
typedef enum {standby, start, busy, done} enum_t;
int32_t* vec;
bounds_t* vec_bounds;
int32_t* mat;
bounds_t* mat_bounds;
int32_t* d3_ptr;
bounds_t* d3_bounds;
int* len;
int* len2;
int* len3;
bounds_t* string_bounds;
ghdl_AccNaturalDimArr_t* line;
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(
char v_logic,
char v_ulogic,
char v_char,
int32_t v_int,
uint32_t v_nat,
uint32_t v_pos,
double v_real,
bool v_bool,
bool v_bit,
int64_t v_time,
rec_t* v_rec,
uint8_t v_enum,
ghdl_NaturalDimArr_t* v_str,
ghdl_NaturalDimArr_t* v_vec_int,
ghdl_NaturalDimArr_t* v_vec_real,
ghdl_NaturalDimArr_t* v_vec_bool,
ghdl_NaturalDimArr_t* v_vec_bit,
ghdl_NaturalDimArr_t* v_vec_phy,
ghdl_NaturalDimArr_t* v_vec_rec,
ghdl_NaturalDimArr_t* v_vec_enum,
ghdl_NaturalDimArr_t* v_2vec_real,
ghdl_NaturalDimArr_t* v_mat_int,
ghdl_NaturalDimArr_t* v_3d_int
) {
assert(v_logic == HDL_H);
printf("v_logic : %c\n", HDL_LOGIC_STATE[v_logic]);
assert(v_ulogic == HDL_Z);
printf("v_ulogic : %c\n", HDL_LOGIC_STATE[v_ulogic]);
assert(v_char == 'k');
printf("v_char : %c\n", v_char);
assert(v_int == -6);
printf("v_int : %d\n", v_int);
assert(v_nat == 9);
printf("v_nat : %d\n", v_nat);
assert(v_pos == 3);
printf("v_pos : %d\n", v_pos);
assert(v_real == 3.34);
printf("v_real : %f\n", v_real);
assert(v_bool == true);
printf("v_bool : %d\n", v_bool);
assert(v_bit == true);
printf("v_bit : %d\n", v_bit);
assert(v_time == 20e6);
printf("v_time : %ld\n", v_time);
assert(v_rec != NULL);
assert(v_rec->r_char == 'y');
assert(v_rec->r_int == 5);
printf("v_rec : %p %c %d\n", v_rec, v_rec->r_char, v_rec->r_int);
assert(v_enum == busy);
printf("v_enum : %d %d\n", v_enum, busy);
char* str = ghdlToString(v_str);
printf("v_str : %p '%s' [%ld]\n", v_str->array, str, strlen(str));
free(str);
len = malloc(2 * sizeof(int));
int32_t* vec_int;
ghdlToArray(v_vec_int, (void**)&vec_int, len, 1);
assert(vec_int[0] == 11);
assert(vec_int[1] == 22);
assert(vec_int[2] == 33);
assert(vec_int[3] == 44);
assert(vec_int[4] == 55);
printf("v_vec_int : %p [%d]\n", vec_int, len[0]);
double* vec_real;
ghdlToArray(v_vec_real, (void**)&vec_real, len, 1);
assert(vec_real[0] == 0.5);
assert(vec_real[1] == 1.75);
assert(vec_real[2] == 3.33);
assert(vec_real[3] == -0.125);
assert(vec_real[4] == -0.67);
assert(vec_real[5] == -2.21);
printf("v_vec_real : %p [%d]\n", vec_real, len[0]);
bool* vec_bool;
ghdlToArray(v_vec_bool, (void**)&vec_bool, len, 1);
assert(vec_bool[0] == 0);
assert(vec_bool[1] == 1);
assert(vec_bool[2] == 1);
assert(vec_bool[3] == 0);
printf("v_vec_bool : %p [%d]\n", vec_bool, len[0]);
bool* vec_bit;
ghdlToArray(v_vec_bit, (void**)&vec_bit, len, 1);
assert(vec_bit[0] == 1);
assert(vec_bit[1] == 0);
assert(vec_bit[2] == 1);
assert(vec_bit[3] == 0);
printf("v_vec_bit : %p [%d]\n", vec_bit, len[0]);
int64_t* vec_phy;
ghdlToArray(v_vec_phy, (void**)&vec_phy, len, 1);
assert(vec_phy[0] == 1e6);
assert(vec_phy[1] == 50e3);
assert(vec_phy[2] == 1.34e9);
printf("v_vec_phy : %p [%d]\n", vec_phy, len[0]);
rec_t* vec_rec;
ghdlToArray(v_vec_rec, (void**)&vec_rec, len, 1);
assert(vec_rec[0].r_char == 'x');
assert(vec_rec[0].r_int == 17);
assert(vec_rec[1].r_char == 'y');
assert(vec_rec[1].r_int == 25);
printf("v_vec_rec : %p [%d]\n", vec_rec, len[0]);
uint8_t* vec_enum;
ghdlToArray(v_vec_enum, (void**)&vec_enum, len, 1);
assert(vec_enum[0] == start);
assert(vec_enum[1] == busy);
assert(vec_enum[2] == standby);
printf("v_vec_enum : %p [%d]\n", vec_enum, len[0]);
double* vec2_real_base;
ghdlToArray(v_2vec_real, (void**)&vec2_real_base, len, 2);
double (*vec2_real)[len[0]] = (double(*)[len[0]])vec2_real_base;
assert(vec2_real[0][0] == 0.1);
assert(vec2_real[0][1] == 0.25);
assert(vec2_real[0][2] == 0.5);
assert(vec2_real[1][0] == 3.33);
assert(vec2_real[1][1] == 4.25);
assert(vec2_real[1][2] == 5.0);
printf("v_2vec_real : %p [%d, %d]\n", vec_enum, len[1], len[0]);
printf("\nVerify GHDL Matrix in C\n");
printAttributes(v_mat_int, 2);
len2 = malloc(2 * sizeof(int));
int32_t* mat_int;
ghdlToArray(v_mat_int, (void**)&mat_int, 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("C assert: %d == (val: %d) @ [%d,%d](%d)\n", 11*(flatIndex+1), mat_int[flatIndex], i, j, flatIndex);
assert(mat_int[flatIndex] == 11*(flatIndex+1));
}
}
printf("v_mat_int : %p [%d,%d]\n\n", mat_int, len2[0], len2[1]);
printf("\nVerify the 3D GHDL array in C\n");
printAttributes(v_3d_int, 3);
len3 = malloc(3 * sizeof(int));
int32_t* d3_int;
ghdlToArray(v_3d_int, (void**)&d3_int, len3, 3);
for(int i = 0; i < len3[0]; i++)
{
for (int j = 0; j < len3[1]; j++)
{
for (int k = 0; k < len3[2]; k++)
{
int ind[] = {i, j, k};
int flatIndex = getFlatArrayIndex(ind, len3, 3);
printf("C assert: %d == (val: %d) @ [%d,%d,%d](%d)\n", 11*(flatIndex+1), d3_int[flatIndex], i, j, k, flatIndex);
assert(d3_int[flatIndex] == 11*(flatIndex+1));
}
}
}
printf("v_3d_int : %p [%d,%d,%d]\n\n", d3_int, len3[0], len3[1], len3[2]);
printf("end testCinterface\n\n");
}
void freePointers(){
free(vec);
free(vec_bounds);
free(mat);
free(mat_bounds);
free(d3_ptr);
free(d3_bounds);
free(string_bounds);
free(line);
free(len);
free(len2);
free(len3);
}
void getString(ghdl_NaturalDimArr_t* ptr) {
if(string_bounds != NULL){//this handles a second call//this handles a second call
free(string_bounds);
}
*ptr = ghdlFromString("HELLO WORLD");
string_bounds = ptr->bounds;
}
void getIntVec(ghdl_NaturalDimArr_t *ptr) {//Notice how similar this is to getIntMat() which is supposedly a 2D array (it is also actually just a flat (1D) array)
vec = malloc(2*3*sizeof(int32_t));
int32_t len[1] = {2*3};
int x, y;
for ( x=0 ; x<2 ; x++ ) {
for ( y=0 ; y<3 ; y++ ) {
int flatIndex = x*3+y;
vec[flatIndex] = 11*(flatIndex+1);
}
}
*ptr = ghdlFromPointer((void *)vec, len, 1);
vec_bounds = ptr->bounds;
assert(ptr->array == vec);
printf("\n1D Array values [%d]:\n", len[0]);
for ( x=0 ; x<len[0] ; x++ ) {
printf("[%d]: %d VS %d\n", x, vec[x], ((int32_t*)ptr->array)[x]);
assert(vec[x] == ((int32_t*)ptr->array)[x]);
}
}
void getIntMat(ghdl_NaturalDimArr_t* ptr){
mat = malloc(2*3*sizeof(int32_t));
int32_t len[2] = {2, 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] = 11*(flatIndex+1);
}
}
*ptr = ghdlFromPointer((void *)mat, len, 2);
mat_bounds = ptr->bounds;
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] = %d\t", x, y, mat[flatIndex]);
assert(mat[flatIndex] == ((uint32_t*)ptr->array)[flatIndex]);
}
printf("\n");
}
}
void getInt3d(ghdl_NaturalDimArr_t* ptr){
int32_t d3[2][4][3];
int32_t len[3] = {2, 4, 3};
int x, y, z, ind[3];
for ( x=0 ; x<len[0] ; x++ ) {
ind[0] = x;
for ( y=0 ; y<len[1] ; y++ ) {
ind[1] = y;
for ( z=0 ; z<len[2] ; z++ ) {
ind[2] = z;
int flatIndex = getFlatArrayIndex(ind, len, 3);
d3[x][y][z] = 11*(flatIndex+1);
}
}
}
*ptr = ghdlFromArray((void *)d3, len, 3, sizeof(int32_t));
d3_ptr = ptr->array;
d3_bounds = ptr->bounds;
printf("\n3D Array values [%d,%d,%d]:\n", len[0], len[1], len[2]);
for ( x=0 ; x<len[0] ; x++ ) {
ind[0] = x;
for ( y=0 ; y<len[1] ; y++ ) {
ind[1] = y;
for ( z=0 ; z<len[2] ; z++ ) {
ind[2] = z;
int flatIndex = getFlatArrayIndex(ind, len, 3);
printf("d3[%d][%d][%d] = %d\t", x, y, z, d3[x][y][z]);
assert(d3[x][y][z] == ((uint32_t*)ptr->array)[flatIndex]);
}
printf("\n");
}
printf("\n");
}
}
ghdl_AccNaturalDimArr_t* getLine() {
if(line != NULL){//this handles a second call
free(line);
}
line = ghdlAccFromString("HELLO WORLD");
return line;
}
int getLogicIntValue(char logic){
return 0 + logic;
}
#ifndef GHDL_TYPES_H
#define GHDL_TYPES_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;
// Access to an unconstrained array with 1 dimension of type 'natural'
typedef struct {
bounds_t range;
uint8_t array[];
} ghdl_AccNaturalDimArr_t;
/*
* Print custom types
*/
void printAttributes(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+1, ptr->bounds[i].left);
printf("bounds[%d].right: %d\n", i+1, ptr->bounds[i].right);
printf("bounds[%d].dir: %d\n", i+1, ptr->bounds[i].dir);
printf("bounds[%d].len: %d\n", i+1, ptr->bounds[i].len);
}
}
/*
* Convert a fat pointer of an unconstrained string, to a (null terminated) C string
*/
// @umarcor
char* ghdlToString(ghdl_NaturalDimArr_t* ptr) {
assert(ptr != NULL);
assert(ptr->bounds != NULL);
int len = ptr->bounds[0].len;
char* str = malloc(sizeof(char) * len + 1);
strncpy(str, ptr->array, len);
str[len] = '\0';
return str;
}
// In the prototype, Bradley declares a value instead of a reference. Why?
// @bradleyharden
/*
char* ghdl_array_to_string(array_t array) {
// Add a null character, because GHDL strings are not null-terminated
char *string = malloc(array.range->len + 1);
strncpy(string, array.array, array.range->len);
string[array.range->len] = '\0';
return string;
}
*/
/*
* 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[num-i-1].len;
}
}
/*
* Convert a (null terminated) C string, to a fat pointer of an unconstrained string
*/
// @umarcor
/*
ghdl_NaturalDimArr_t* ghdlFromString(char* str) {
uint32_t len = strlen(str);
ghdl_NaturalDimArr_t* ptr = malloc(sizeof(ghdl_NaturalDimArr_t));
ptr->array = malloc(sizeof(char) * len);
strncpy((char*)(ptr->array), str, len);
ptr->bounds = malloc(sizeof(bounds_t));
bounds_t* b = ptr->bounds;
b->dim_1.left = 1;
b->dim_1.right = len;
b->dim_1.dir = 0;
b->dim_1.len = len;
return ptr;
}
*/
// Again, the prototype I had (above) returns a reference instead of a value (Bradley's below)
// @bradleyharden
ghdl_NaturalDimArr_t ghdlFromString(char *string) {
bounds_t *range = malloc(sizeof(bounds_t));
assert(range != NULL);
uint32_t len = strlen(string);
range->left = 1;
range->right = len;
range->dir = 0;
range->len = len;
// Don't bother copying the string, because GHDL will do that anyway
return (ghdl_NaturalDimArr_t){.array=string, .bounds=range};
}
// @RocketRoss
/*
* 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;
}
}
// @RocketRoss
/*
* 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) {//handled malloc'd pointer in freeCPointers()
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) {//handled malloc'd pointer in freeCPointers()
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};
}
/*
* Convert an access to an unconstrained string, to a (null terminated) C string
*/
char* ghdlAccToString(ghdl_AccNaturalDimArr_t *line) {//TODO Test //TODO handle malloc'd pointer
// Add a null character, because GHDL strings are not null-terminated
char *string = malloc(line->range.len + 1);
strncpy(string, line->array, line->range.len);
string[line->range.len] = '\0';
}
/*
* Convert C types representing an unconstrained array with a dimension of type 'natural', to an access
*/
// TODO: support 2 and 3 dimensions
ghdl_AccNaturalDimArr_t* ghdlAccFromArray(uint32_t length, size_t bytes) {//TODO handle malloc'd pointer
ghdl_AccNaturalDimArr_t *access = malloc(sizeof(ghdl_AccNaturalDimArr_t) + length * bytes);
assert(access != NULL);
access->range.left = 0;
access->range.right = length - 1;
access->range.dir = 0;
access->range.len = length;
return access;
}
/*
* Convert a (null terminated) C string, to an access to an unconstrained string
*/
/*
// @umarcor
ghdl_AccNaturalDimArr_t* ghdlLineFromString(char *str) {
uint32_t len = strlen(str);
ghdl_AccNaturalDimArr_t *line = malloc(sizeof(ghdl_AccNaturalDimArr_t) + sizeof(char) * len);
line->bounds.left = 1;
line->bounds.right = len;
line->bounds.dir = 0;
line->bounds.len = len;
strncpy(line->array, str, len);
return line;
}
*/
// @bradleyharden
ghdl_AccNaturalDimArr_t* ghdlAccFromString(char *string) {
uint32_t length = strlen(string);
ghdl_AccNaturalDimArr_t *line = ghdlAccFromArray(length, 1);
// New access objects default to numbering from 0,
// but VHDL strings must be numbered from 1
line->range.left++;
line->range.right++;
// Don't copy the null termination
strncpy(line->array, string, length);
return line;
}
/*
* Handle C char for the appropriate values in std_ulogic and std_logic.
*/
// @RocketRoss
static const char HDL_LOGIC_STATE[] = { 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'};
enum HDL_LOGIC_CHAR {
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