Skip to content

Commit 2cfb732

Browse files
committed
Added array utility
1 parent 1d31b1a commit 2cfb732

8 files changed

Lines changed: 1084 additions & 11 deletions

File tree

acceptance_test/test_array.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This Source Code Form is subject to the terms of the Mozilla Public
2+
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
# You can obtain one at http://mozilla.org/MPL/2.0/.
4+
#
5+
# Copyright (c) 2014, Lars Asplund lars.anders.asplund@gmail.com
6+
7+
import unittest
8+
from os.path import abspath, join, dirname
9+
from vunit.ui import VUnit
10+
from common import has_modelsim
11+
12+
@unittest.skipUnless(has_modelsim(), 'Requires modelsim')
13+
class TestArray(unittest.TestCase):
14+
def run_sim(self, vhdl_standard):
15+
output_path = join(dirname(abspath(__file__)), 'array_out')
16+
src_path = join(dirname(abspath(__file__)), '..', 'vhdl', 'array')
17+
18+
vu = VUnit(clean=True,
19+
output_path=output_path,
20+
vhdl_standard=vhdl_standard)
21+
22+
vu.add_library("lib")
23+
vu.add_array_util("lib")
24+
vu.add_source_files(join(src_path, "test", "*.vhd"), "lib")
25+
26+
try:
27+
vu.main()
28+
except SystemExit as e:
29+
self.assertEqual(e.code, 0)
30+
31+
def test_array_vhdl_2008(self):
32+
self.run_sim('2008')

acceptance_test/test_example_projects.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,44 +18,51 @@ def setUp(self):
1818

1919
def test_uart_example_project(self):
2020
path = join(dirname(__file__), "..", "examples")
21-
check_call([sys.executable, join(path, "uart", "run.py"),
22-
"--clean",
21+
check_call([sys.executable, join(path, "uart", "run.py"),
22+
"--clean",
2323
"--output-path=%s" % self.output_path,
2424
"--xunit-xml=%s" % self.report_file])
25-
check_call([sys.executable, join(path, "uart", "run_with_preprocessing.py"),
26-
"--clean",
25+
check_call([sys.executable, join(path, "uart", "run_with_preprocessing.py"),
26+
"--clean",
2727
"--output-path=%s" % self.output_path,
2828
"--xunit-xml=%s" % self.report_file])
2929

3030
def test_logging_example_project(self):
3131
path = join(dirname(__file__), "..", "examples", "logging")
3232
check_call([sys.executable, join(path, "compile.py"),
33-
"--clean",
33+
"--clean",
3434
"--output-path=%s" % self.output_path,
3535
"--xunit-xml=%s" % self.report_file])
3636

3737
def test_check_example_project(self):
3838
path = join(dirname(__file__), "..", "examples", "check")
3939
check_call([sys.executable, join(path, "compile.py"),
40-
"--clean",
40+
"--clean",
4141
"--output-path=%s" % self.output_path,
4242
"--xunit-xml=%s" % self.report_file])
4343

4444
def test_generate_tests_example_project(self):
4545
path = join(dirname(__file__), "..", "examples", "generate_tests")
4646
check_call([sys.executable, join(path, "run.py"),
47-
"--clean",
47+
"--clean",
48+
"--output-path=%s" % self.output_path,
49+
"--xunit-xml=%s" % self.report_file])
50+
51+
def test_array_example_project(self):
52+
path = join(dirname(__file__), "..", "examples", "array")
53+
check_call([sys.executable, join(path, "run.py"),
54+
"--clean",
4855
"--output-path=%s" % self.output_path,
4956
"--xunit-xml=%s" % self.report_file])
5057

5158
def test_user_guide_example_project(self):
5259
path = join(dirname(__file__), "..", "examples", "user_guide")
5360
retcode = call([sys.executable, join(path, "run.py"),
54-
"--clean",
61+
"--clean",
5562
"--output-path=%s" % self.output_path,
5663
"--xunit-xml=%s" % self.report_file])
5764
self.assertEqual(retcode, 1)
58-
check_report(self.report_file,
65+
check_report(self.report_file,
5966
[("passed", "lib.tb_example"),
6067
("passed", "lib.tb_example_many.test_pass"),
6168
("failed", "lib.tb_example_many.test_fail")])

examples/array/run.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# This Source Code Form is subject to the terms of the Mozilla Public
2+
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
# You can obtain one at http://mozilla.org/MPL/2.0/.
4+
#
5+
# Copyright (c) 2014, Lars Asplund lars.anders.asplund@gmail.com
6+
7+
# Make vunit python module importable
8+
from os.path import join, dirname
9+
import sys
10+
path_to_vunit = join(dirname(__file__), '..', '..')
11+
sys.path.append(path_to_vunit)
12+
# -------
13+
14+
from vunit import VUnit
15+
16+
root = dirname(__file__)
17+
18+
ui = VUnit.from_argv()
19+
ui.add_osvvm()
20+
ui.add_array_util()
21+
lib = ui.add_library("lib")
22+
lib.add_source_files(join(root, "src", "*.vhd"))
23+
lib.add_source_files(join(root, "src", "test", "*.vhd"))
24+
ui.main()

examples/array/src/sobel_x.vhd

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014, Lars Asplund lars.anders.asplund@gmail.com
6+
7+
library ieee;
8+
use ieee.std_logic_1164.all;
9+
use ieee.numeric_std.all;
10+
11+
entity sobel_x is
12+
generic (
13+
data_width : natural);
14+
port (
15+
signal clk : in std_logic;
16+
signal input_tvalid : in std_logic;
17+
signal input_tlast : in std_logic;
18+
signal input_tdata : in unsigned(data_width-1 downto 0);
19+
20+
signal output_tvalid : out std_logic := '0';
21+
signal output_tlast : out std_logic;
22+
signal output_tdata : out signed(data_width downto 0));
23+
end entity;
24+
25+
architecture a of sobel_x is
26+
begin
27+
28+
main : process
29+
variable input_tdata_p1, input_tdata_p2 : unsigned(input_tdata'range) := (others => '0');
30+
variable input_tvalid_p1 : std_logic := '0';
31+
variable input_tlast_p1 : std_logic := '0';
32+
variable first : boolean := true;
33+
variable pos, neg : unsigned(input_tdata'range) := (others => '0');
34+
begin
35+
wait until rising_edge(clk);
36+
output_tvalid <= input_tvalid_p1;
37+
output_tlast <= input_tlast_p1;
38+
39+
if first then
40+
neg := input_tdata_p1;
41+
else
42+
neg := input_tdata_p2;
43+
end if;
44+
45+
if input_tlast_p1 then
46+
pos := input_tdata_p1;
47+
else
48+
pos := input_tdata;
49+
end if;
50+
51+
output_tdata <= signed(resize(pos, output_tdata'length) -
52+
resize(neg, output_tdata'length));
53+
54+
if input_tvalid_p1 then
55+
if input_tlast_p1 then
56+
first := true;
57+
else
58+
first := false;
59+
end if;
60+
end if;
61+
62+
input_tlast_p1 := input_tlast;
63+
input_tvalid_p1 := input_tvalid;
64+
65+
input_tdata_p2 := input_tdata_p1;
66+
input_tdata_p1 := input_tdata;
67+
end process;
68+
end architecture;
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014, Lars Asplund lars.anders.asplund@gmail.com
6+
7+
library ieee;
8+
use ieee.std_logic_1164.all;
9+
use ieee.numeric_std.all;
10+
11+
library vunit_lib;
12+
context vunit_lib.vunit_context;
13+
use vunit_lib.array_pkg.all;
14+
15+
16+
library osvvm;
17+
use osvvm.RandomPkg.all;
18+
19+
entity tb_sobel_x is
20+
generic (
21+
runner_cfg : runner_cfg_t;
22+
data_width : natural := 14;
23+
output_path : string);
24+
end entity;
25+
26+
architecture tb of tb_sobel_x is
27+
signal clk : std_logic := '0';
28+
signal input_tvalid : std_logic := '0';
29+
signal input_tlast : std_logic := '0';
30+
signal input_tdata : unsigned(data_width-1 downto 0) := (others => '0');
31+
signal output_tvalid : std_logic;
32+
signal output_tlast : std_logic;
33+
signal output_tdata : signed(input_tdata'length downto 0);
34+
35+
shared variable image : array_t;
36+
shared variable reference_image : array_t;
37+
signal start, data_check_done, stimuli_done : boolean := false;
38+
begin
39+
40+
main : process
41+
procedure sobel_x(variable image : inout array_t;
42+
variable result : inout array_t) is
43+
begin
44+
result.init_2d(width => image.width,
45+
height => image.height,
46+
bit_width => image.bit_width+1,
47+
is_signed => true);
48+
49+
for y in 0 to image.height-1 loop
50+
for x in 0 to image.width-1 loop
51+
result.set(x, y,
52+
value => (image.get(minimum(x+1, image.width-1),y) -
53+
image.get(maximum(x-1, 0), y)));
54+
end loop;
55+
end loop;
56+
57+
end procedure;
58+
59+
variable rnd : RandomPType;
60+
61+
procedure randomize(variable arr : inout array_t) is
62+
begin
63+
for idx in 0 to arr.length-1 loop
64+
arr.set(idx, value => rnd.RandInt(arr.lower_limit, arr.upper_limit));
65+
end loop;
66+
end procedure;
67+
68+
procedure test_one_image(width, height : natural) is
69+
begin
70+
image.init_2d(width => width, height => height,
71+
bit_width => input_tdata'length,
72+
is_signed => false);
73+
randomize(image);
74+
sobel_x(image, result => reference_image);
75+
76+
wait until rising_edge(clk);
77+
start <= true;
78+
wait until rising_edge(clk);
79+
start <= false;
80+
81+
wait until (stimuli_done and
82+
data_check_done and
83+
rising_edge(clk));
84+
end procedure;
85+
86+
begin
87+
test_runner_setup(runner, runner_cfg);
88+
rnd.InitSeed(rnd'instance_name);
89+
test_one_image(128, 64);
90+
test_one_image(1, 13);
91+
test_one_image(16, 1);
92+
test_one_image(1, 1);
93+
test_runner_cleanup(runner);
94+
wait;
95+
end process;
96+
97+
stimuli_process : process
98+
begin
99+
wait until start and rising_edge(clk);
100+
stimuli_done <= false;
101+
102+
report ("Sending image of size " &
103+
to_string(image.width) & "x" &
104+
to_string(image.height));
105+
106+
for y in 0 to image.height-1 loop
107+
for x in 0 to image.width-1 loop
108+
wait until rising_edge(clk);
109+
input_tvalid <= '1';
110+
input_tlast <= '1' when x = image.width-1 else '0';
111+
input_tdata <= to_unsigned(image.get(x,y), input_tdata'length);
112+
end loop;
113+
end loop;
114+
115+
wait until rising_edge(clk);
116+
input_tvalid <= '0';
117+
118+
stimuli_done <= true;
119+
end process;
120+
121+
data_check_process : process
122+
begin
123+
wait until start and rising_edge(clk);
124+
data_check_done <= false;
125+
for y in 0 to reference_image.height-1 loop
126+
for x in 0 to reference_image.width-1 loop
127+
wait until output_tvalid = '1' and rising_edge(clk);
128+
check_equal(output_tlast, x = reference_image.width-1);
129+
check_equal(output_tdata, reference_image.get(x, y),
130+
"x=" & to_string(x) & " y=" & to_string(y));
131+
end loop;
132+
end loop;
133+
report ("Done checking image of size " &
134+
to_string(reference_image.width) & "x" &
135+
to_string(reference_image.height));
136+
data_check_done <= true;
137+
end process;
138+
139+
clk <= not clk after 1 ns;
140+
141+
dut : entity work.sobel_x
142+
generic map (
143+
data_width => input_tdata'length)
144+
port map (
145+
clk => clk,
146+
input_tvalid => input_tvalid,
147+
input_tlast => input_tlast,
148+
input_tdata => input_tdata,
149+
output_tvalid => output_tvalid,
150+
output_tlast => output_tlast,
151+
output_tdata => output_tdata);
152+
153+
end architecture;

0 commit comments

Comments
 (0)