Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2/3] Add external modes to string_ptr and integer_vector_ptr (through VHPIDIRECT) #476

Merged
merged 4 commits into from
Oct 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 38 additions & 11 deletions examples/vhdl/external_buffer/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,55 @@
simulation.
"""

from vunit import VUnit
from vunit import VUnit, ROOT
from os import popen
from os.path import join, dirname

src_path = join(dirname(__file__), "src")
ext_srcs = join(ROOT, "vunit", "vhdl", "data_types", "src", "external", "ghdl")

c_obj = join(src_path, "main.o")
# Compile C application to an object
print(
popen(
" ".join(["gcc", "-fPIC", "-c", join(src_path, "main.c"), "-o", c_obj])
).read()
)
# Compile C applications to an objects
c_iobj = join(src_path, "imain.o")
c_bobj = join(src_path, "bmain.o")

# Enable the external feature for strings
for val in [["int32_t", c_iobj], ["uint8_t", c_bobj]]:
print(
popen(
" ".join(
[
"gcc",
"-fPIC",
"-DTYPE=" + val[0],
"-I",
ext_srcs,
"-c",
join(src_path, "main.c"),
"-o",
val[1],
]
)
).read()
)

# Enable the external feature for strings/byte_vectors and integer_vectors
vu = VUnit.from_argv(vhdl_standard="2008", compile_builtins=False)
vu.add_builtins({"string": True})
vu.add_builtins({"string": True, "integer": True})

lib = vu.add_library("lib")
lib.add_source_files(join(src_path, "tb_ext_*.vhd"))

# Add the C object to the elaboration of GHDL
vu.set_sim_option("ghdl.elab_flags", ["-Wl," + c_obj])
for tb in lib.get_test_benches(pattern="*tb_ext*", allow_empty=False):
tb.set_sim_option(
"ghdl.elab_flags",
["-Wl," + c_bobj, "-Wl,-Wl,--version-script=" + join(ext_srcs, "grt.ver")],
overwrite=True,
)
for tb in lib.get_test_benches(pattern="*tb_ext*_integer*", allow_empty=False):
tb.set_sim_option(
"ghdl.elab_flags",
["-Wl," + c_iobj, "-Wl,-Wl,--version-script=" + join(ext_srcs, "grt.ver")],
overwrite=True,
)

vu.main()
59 changes: 21 additions & 38 deletions examples/vhdl/external_buffer/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,39 @@ positions. Then, the VHDL simulation is executed, where the (external) array/buf
is used. When the simulation is finished, the results are checked. The content of
the buffer is printed both before and after the simulation.

NOTE: This file is expected to be used along with tb_ext_byte_vector.vhd or tb_ext_string.vhd
This source file is used for both string/byte_vector and integer_vector.
Accordingly, TYPE must be defined as uint8_t or int32_t during compilation.
Keep in mind that the buffer (D) is of type uint8_t*, independently of TYPE, i.e.
accesses are casted.

NOTE: This file is expected to be used along with tb_ext_string.vhd, tb_ext_byte_vector.vhd
or tb_ext_integer_vector.vhd
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "vhpidirect_user.h"

extern int ghdl_main (int argc, char **argv);

uint8_t *D[1];
const uint32_t length = 5;

// Check procedure, to be executed when GHDL exits.
// The simulation is expected to copy the first 1/3 elements to positions [1/3, 2/3),
// while incrementing each value by one, and then copy elements from [1/3, 2/3) to
// [2/3, 3/3), while incrementing each value by two.
/*
Check procedure, to be executed when GHDL exits.
The simulation is expected to copy the first 1/3 elements to positions [1/3, 2/3),
while incrementing each value by one, and then copy elements from [1/3, 2/3) to
[2/3, 3/3), while incrementing each value by two.
*/
static void exit_handler(void) {
int i, j, z, k;
uint8_t expected, got;
unsigned i, j, z, k;
TYPE expected, got;
k = 0;
for (j=0; j<3; j++) {
k += j;
for(i=0; i<length; i++) {
z = (length*j)+i;

expected = (i+1)*11 + k;
got = D[0][z];
got = ((TYPE*)D[0])[z];
if (expected != got) {
printf("check error %d: %d %d\n", z, expected, got);
exit(1);
Expand All @@ -50,19 +56,20 @@ static void exit_handler(void) {
int main(int argc, char **argv) {
// Allocate a buffer which is three times the number of values
// that we want to copy/modify
D[0] = (uint8_t *) malloc(3*length*sizeof(uint8_t));
D[0] = (uint8_t *) malloc(3*length*sizeof(TYPE));
if ( D[0] == NULL ) {
perror("execution of malloc() failed!\n");
return -1;
}
// Initialize the first 1/3 of the buffer
int i;
for(i=0; i<length; i++) {
D[0][i] = (i+1)*11;
((TYPE*)D[0])[i] = (i+1)*11;
}
// Print all the buffer
printf("sizeof: %lu\n", sizeof(TYPE));
for(i=0; i<3*length; i++) {
printf("%d: %d\n", i, D[0][i]);
printf("%d: %d\n", i, ((TYPE*)D[0])[i]);
}

// Register a function to be called when GHDL exits
Expand All @@ -71,27 +78,3 @@ int main(int argc, char **argv) {
// Start the simulation
return ghdl_main(argc, argv);
}

// External through access (mode = extacc)

void set_string_ptr(uint8_t id, uint8_t *p) {
//printf("C set_string_ptr(%d, %p)\n", id, p);
D[id] = p;
}

uintptr_t get_string_ptr(uint8_t id) {
//printf("C get_string_ptr(%d): %p\n", id, D[id]);
return (uintptr_t)D[id];
}

// External through functions (mode = extfnc)

void write_char(uint8_t id, uint32_t i, uint8_t v ) {
//printf("C write_char(%d, %d): %d\n", id, i, v);
D[id][i] = v;
}

uint8_t read_char(uint8_t id, uint32_t i) {
//printf("C read_char(%d, %d): %d\n", id, i, D[id][i]);
return D[id][i];
}
55 changes: 55 additions & 0 deletions examples/vhdl/external_buffer/src/tb_ext_integer_vector.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
-- You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com

-- NOTE: This file is expected to be used along with foreign languages (C)
-- through VHPIDIRECT: https://ghdl.readthedocs.io/en/latest/using/Foreign.html
-- See main.c for an example of a wrapper application.

--library vunit_lib;
--context vunit_lib.vunit_context;

library vunit_lib;
use vunit_lib.run_pkg.all;
use vunit_lib.logger_pkg.all;
use vunit_lib.types_pkg.all;
use vunit_lib.integer_vector_ptr_pkg.all;

entity tb_external_integer_vector is
generic ( runner_cfg : string );
end entity;

architecture tb of tb_external_integer_vector is

constant block_len : natural := 5;

constant ebuf: integer_vector_ptr_t := new_integer_vector_ptr( 3*block_len, extfnc, 0); -- external through VHPIDIRECT functions 'read_char' and 'write_char'
constant abuf: integer_vector_ptr_t := new_integer_vector_ptr( 3*block_len, extacc, 0); -- external through access (requires VHPIDIRECT function 'get_string_ptr')

begin

main: process
variable val, ind: integer;
begin
test_runner_setup(runner, runner_cfg);
info("Init test");
for x in 0 to block_len-1 loop
val := get(ebuf, x) + 1;
ind := block_len+x;
set(ebuf, ind, val);
info("SET " & to_string(ind) & ": " & to_string(val));
end loop;
for x in block_len to 2*block_len-1 loop
val := get(abuf, x) + 2;
ind := block_len+x;
set(abuf, ind, val);
info("SET " & to_string(ind) & ": " & to_string(val));
end loop;
info("End test");
test_runner_cleanup(runner);
wait;
end process;

end architecture;
45 changes: 24 additions & 21 deletions vunit/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,14 @@ def _add_data_types(self, external=None):
"""
Add data types packages (sources corresponding to VHPIDIRECT arrays, or their placeholders)

:param external: struct to select whether to enable external models for 'string'. Allowed values are:
None, {'string': False}, {'string': True} or {'string': ['path/to/custom/file']}.
:param external: struct to select whether to enable external models for 'string' and/or 'integer' vectors.
{'string': <VAL>, 'integer': <VAL>}. Allowed values are: None, False/True or
['path/to/custom/file'].
"""
self._add_files(join(VHDL_PATH, "data_types", "src", "*.vhd"))

use_ext = {"string": False}
files = {"string": None}
use_ext = {"string": False, "integer": False}
files = {"string": None, "integer": None}

if external:
for ind, val in external.items():
Expand All @@ -91,33 +92,34 @@ def _add_data_types(self, external=None):
use_ext[ind] = True
files[ind] = val

for ind in use_ext:
if use_ext[ind] and simulator_check(
lambda simclass: not simclass.supports_vhpi()
):
for _, val in use_ext.items():
if val and simulator_check(lambda simclass: not simclass.supports_vhpi()):
raise RuntimeError(
"the selected simulator does not support VHPI; must use non-VHPI packages..."
)

ext_path = join(VHDL_PATH, "data_types", "src", "external")

def default_pkg(cond, type_str):
def default_files(cond, type_str):
"""
Return name of VHDL file with default VHPIDIRECT foreign declarations.
"""
return join(
ext_path,
"external_" + type_str + "-" + ("" if cond else "no") + "vhpi.vhd",
)
return [
join(
ext_path,
"external_" + type_str + "-" + ("" if cond else "no") + "vhpi.vhd",
),
join(ext_path, "external_" + type_str + "-body.vhd"),
]

if not files["string"]:
files["string"] = [
default_pkg(use_ext["string"], "string"),
join(ext_path, "external_string-body.vhd"),
]
files["string"] = default_files(use_ext["string"], "string")

if not files["integer"]:
files["integer"] = default_files(use_ext["integer"], "integer_vector")

for ind in files:
for name in files[ind]:
for _, val in files.items():
for name in val:
self._add_files(name)

def _add_array_util(self):
Expand Down Expand Up @@ -234,8 +236,9 @@ def add_vhdl_builtins(self, external=None):
"""
Add vunit VHDL builtin libraries

:param external: struct to select whether to enable external models for 'string'. Allowed values are:
None, {'string': False}, {'string': True} or {'string': ['path/to/custom/file']}.
:param external: struct to select whether to enable external models for 'string' and/or 'integer' vectors.
{'string': <VAL>, 'integer': <VAL>}. Allowed values are: None, False/True or
['path/to/custom/file'].
"""
self._add_data_types(external=external)
self._add_files(join(VHDL_PATH, "*.vhd"))
Expand Down
5 changes: 3 additions & 2 deletions vunit/ui/vunit.py
Original file line number Diff line number Diff line change
Expand Up @@ -945,8 +945,9 @@ def add_builtins(self, external=None):
"""
Add vunit VHDL builtin libraries

:param external: struct to select whether to enable external models for 'string'. Allowed values are:
None, {'string': False}, {'string': True} or {'string': ['path/to/custom/file']}.
:param external: struct to select whether to enable external models for 'string' and/or 'integer' vectors.
{'string': <VAL>, 'integer': <VAL>}. Allowed values are: None, False/True or
['path/to/custom/file'].
"""
self._builtins.add_vhdl_builtins(external=external)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
-- You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com

package body external_integer_vector_pkg is
procedure write_integer (
id : integer;
i : integer;
v : integer
)is begin
assert false report "VHPI write_integer" severity failure;
end;

impure function read_integer (
id : integer;
i : integer
) return integer is begin
assert false report "VHPI read_integer" severity failure;
end;

impure function get_ptr (
id : integer
) return extintvec_access_t is begin
assert false report "VHPI get_intvec_ptr" severity failure;
end;
end package body;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
-- You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com

use work.types_pkg.all;

package external_integer_vector_pkg is
procedure write_integer (
id : integer;
i : integer;
v : integer
);

impure function read_integer (
id : integer;
i : integer
) return integer;

impure function get_ptr (
id : integer
) return extintvec_access_t;
end package;
Loading