diff --git a/examples/vhdl/json4vhdl/run.py b/examples/vhdl/json4vhdl/run.py index 4ff6d10037..51009fd47a 100644 --- a/examples/vhdl/json4vhdl/run.py +++ b/examples/vhdl/json4vhdl/run.py @@ -25,6 +25,11 @@ tb_cfg = read_json(join(root, "src/test/data/data.json")) tb_cfg["dump_debug_data"] = False -vu.set_generic("tb_cfg", encode_json(tb_cfg)) + +json_str = encode_json(tb_cfg) + +vu.set_generic("tb_cfg", json_str) + +vu.set_generic("tb_cfg_b16", json_str.encode("utf-8").hex()) vu.main() diff --git a/examples/vhdl/json4vhdl/src/test/tb_json_gens.vhd b/examples/vhdl/json4vhdl/src/test/tb_json_gens.vhd index 2a09e0e304..64e40730ba 100644 --- a/examples/vhdl/json4vhdl/src/test/tb_json_gens.vhd +++ b/examples/vhdl/json4vhdl/src/test/tb_json_gens.vhd @@ -5,6 +5,7 @@ -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com library vunit_lib; context vunit_lib.vunit_context; +use vunit_lib.encodings_pkg.all; library JSON; context JSON.json_ctx; @@ -13,68 +14,73 @@ entity tb_json_gens is runner_cfg : string; tb_path : string; tb_cfg : string; + tb_cfg_b16 : string; tb_cfg_file : string := "data/data.json" ); end entity; architecture tb of tb_json_gens is - -- tb_cfg contains stringified content - constant JSONContent : T_JSON := jsonLoad(tb_cfg); +begin + main: process - -- tb_cfg is the path of a JSON file - constant JSONFileContent : T_JSON := jsonLoad(tb_path & tb_cfg_file); + procedure run_test(JSONContent : T_JSON) is + -- get array of integers from JSON content + constant img_arr : integer_vector := jsonGetIntegerArray(JSONContent, "Image"); + begin + -- Content extracted from the JSON + info("JSONContent: " & lf & JSONContent.Content); - -- record to be filled by function decode - type img_t is record - image_width : positive; - image_height : positive; - dump_debug_data : boolean; - end record img_t; + -- Integer array, extracted by function jsonGetIntegerArray with data from the JSON + for i in 0 to img_arr'length-1 loop + info("Image array [" & integer'image(i) & "]: " & integer'image(img_arr(i))); + end loop; - -- function to fill img_t with content extracted from a JSON input - impure function decode(Content : T_JSON) return img_t is - begin - return (image_width => positive'value( jsonGetString(Content, "Image/0") ), - image_height => positive'value( jsonGetString(Content, "Image/1") ), - dump_debug_data => jsonGetBoolean(Content, "dump_debug_data") ); - end function decode; + -- Image dimensions as strings, get from the content from the JSON file + info("Image: " & jsonGetString(JSONContent, "Image/0") & ',' & jsonGetString(JSONContent, "Image/1")); - constant img : img_t := decode(JSONContent); + -- Some other content, deep in the JSON + info("Platform/ML505/FPGA: " & jsonGetString(JSONContent, "Platform/ML505/FPGA")); + info("Platform/KC705/IIC/0/Devices/0/Name: " & jsonGetString(JSONContent, "Platform/KC705/IIC/0/Devices/0/Name")); + end procedure; - -- get array of integers from JSON content - constant img_arr : integer_vector := jsonGetIntegerArray(JSONContent, "Image"); + procedure run_record_test(JSONContent : T_JSON) is + type img_t is record + image_width : positive; + image_height : positive; + dump_debug_data : boolean; + end record img_t; + + -- fill img_t with content extracted from a JSON input + constant img : img_t := ( + image_width => positive'value( jsonGetString(JSONContent, "Image/0") ), + image_height => positive'value( jsonGetString(JSONContent, "Image/1") ), + dump_debug_data => jsonGetBoolean(JSONContent, "dump_debug_data") + ); + begin + -- Image dimensions in a record, filled with data from the stringified generic + info("Image: " & integer'image(img.image_width) & ',' & integer'image(img.image_height)); + end procedure; + + variable JSONContent : T_JSON; -begin - main: process begin test_runner_setup(runner, runner_cfg); while test_suite loop - if run("test") then - -- Content extracted from the stringified generic - info("JSONContent: " & lf & JSONContent.Content); - - -- Full path of the JSON file, and extracted content + if run("stringified JSON generic") then + info("RAW generic: " & tb_cfg); + JSONContent := jsonLoad(tb_cfg); + run_test(JSONContent); + run_record_test(JSONContent); + elsif run("b16encoded stringified JSON generic") then + info("RAW generic: " & tb_cfg_b16); + JSONContent := jsonLoad(b16decode(tb_cfg_b16)); + run_test(JSONContent); + run_record_test(JSONContent); + elsif run("JSON from file path generic") then + -- Full path of the JSON file info("tb_path & tb_cfg_file: " & tb_path & tb_cfg_file); - info("JSONFileContent: " & lf & JSONFileContent.Content); - - -- Image dimensions in a record, filled by function decode with data from the stringified generic - info("Image: " & integer'image(img.image_width) & ',' & integer'image(img.image_height)); - - -- Integer array, extracted by function decode_array with data from the stringified generic - for i in 0 to img_arr'length-1 loop - info("Image array [" & integer'image(i) & "]: " & integer'image(img_arr(i))); - end loop; - - -- Image dimensions as strings, get from the content from the JSON file - info("Image: " & jsonGetString(JSONFileContent, "Image/0") & ',' & jsonGetString(JSONFileContent, "Image/1")); - - -- Some other content, deep in the JSON sources - info("Platform/ML505/FPGA: " & jsonGetString(JSONContent, "Platform/ML505/FPGA")); - info("Platform/ML505/FPGA: " & jsonGetString(JSONFileContent, "Platform/ML505/FPGA")); - - info("Platform/KC705/IIC/0/Devices/0/Name: " & jsonGetString(JSONContent, "Platform/KC705/IIC/0/Devices/0/Name")); - info("Platform/KC705/IIC/0/Devices/0/Name: " & jsonGetString(JSONFileContent, "Platform/KC705/IIC/0/Devices/0/Name")); + run_test(jsonLoad(tb_path & tb_cfg_file)); end if; end loop; test_runner_cleanup(runner); diff --git a/vunit/builtins.py b/vunit/builtins.py index f6548f4ffe..e6cef89386 100644 --- a/vunit/builtins.py +++ b/vunit/builtins.py @@ -243,6 +243,7 @@ def add_vhdl_builtins(self, external=None): self._add_files(join(VHDL_PATH, "*.vhd")) for path in ( "core", + "encodings", "logging", "string_ops", "check", diff --git a/vunit/vhdl/encodings/run.py b/vunit/vhdl/encodings/run.py new file mode 100644 index 0000000000..358a18325b --- /dev/null +++ b/vunit/vhdl/encodings/run.py @@ -0,0 +1,16 @@ +# 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 + +from os.path import join, dirname +from vunit import VUnit + +root = dirname(__file__) + +ui = VUnit.from_argv() + +lib = ui.library("vunit_lib") +lib.add_source_files(join(root, "test", "*.vhd")) +ui.main() diff --git a/vunit/vhdl/encodings/src/encodings_pkg.vhd b/vunit/vhdl/encodings/src/encodings_pkg.vhd new file mode 100644 index 0000000000..d3eb6f2ca7 --- /dev/null +++ b/vunit/vhdl/encodings/src/encodings_pkg.vhd @@ -0,0 +1,59 @@ +-- 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 encodings_pkg is + + function b16decode(str: string) return string; + function b16encode(str: string) return string; + +end; + +package body encodings_pkg is + + function to_natural (c: character) return natural is + constant offset_0 : natural := character'pos('0'); + constant offset_U : natural := character'pos('A') - 10; + constant offset_l : natural := character'pos('a') - 10; + variable num: integer := -1; + begin + num := character'pos(c); + case c is + when '0' to '9' => return num - offset_0; + when 'A' to 'F' => return num - offset_U; + when 'a' to 'f' => return num - offset_l; + when others => return -1; + end case; + end; + + function b16decode(str: string) return string is + variable res: string (1 to str'length/2); + begin + for x in 1 to str'length/2 loop + res(x) := character'val(to_natural(str(2*x-1)) *16 + to_natural(str(2*x))); + end loop; + return res; + end; + + function to_character(num: natural) return character is + begin + if num<10 then + return character'val(num+48); + end if; + return character'val(num+87); + end; + + function b16encode(str: string) return string is + variable res: string (1 to 2*str'length); + variable num: natural; + begin + for x in 1 to str'length loop + num := character'pos(str(x)); + res(2*x-1 to 2*x) := to_character(num / 16) & to_character(num rem 16); + end loop; + return res; + end function; + +end; diff --git a/vunit/vhdl/encodings/test/tb_encodings_pkg.vhd b/vunit/vhdl/encodings/test/tb_encodings_pkg.vhd new file mode 100644 index 0000000000..335c094cf2 --- /dev/null +++ b/vunit/vhdl/encodings/test/tb_encodings_pkg.vhd @@ -0,0 +1,31 @@ +-- 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 + +library vunit_lib; +use vunit_lib.run_pkg.all; +use vunit_lib.check_pkg.all; +use vunit_lib.encodings_pkg.all; + +entity tb_encodings is + generic (runner_cfg : string); +end; + +architecture a of tb_encodings is + constant str: string := "[""test"",[true,false,18,null,""hello""],[9,8],3324.34,832432,""world""]"; + constant enc: string := "5b2274657374222c5b747275652c66616c73652c31382c6e756c6c2c2268656c6c6f225d2c5b392c385d2c333332342e33342c3833323433322c22776f726c64225d"; +begin + main : process + variable gstr: string(1 to str'length); + variable genc: string(1 to enc'length); + begin + test_runner_setup(runner, runner_cfg); + gstr := b16decode(enc); + genc := b16encode(str); + check_equal(gstr, str); + check_equal(genc, enc); + test_runner_cleanup(runner); + end process; +end;