Commit b8eafac0 authored by Martin Jeřábek's avatar Martin Jeřábek

ci: generate wrappers for unit tests; use image with ghdl-gcc

parent 7effbee7
image: ghdl/ext:vunit image: mjerabek/ghdl
before_script: before_script:
- apt-get -y install lcov make - "export PATH=/opt/ghdl/bin:$PATH"
build_ip_and_tests: build_ip_and_tests:
stage: build stage: build
...@@ -16,15 +16,15 @@ build_ip_and_tests: ...@@ -16,15 +16,15 @@ build_ip_and_tests:
- cd driver - cd driver
- "make -j`nproc`" - "make -j`nproc`"
test_ip: test_ip_unit:
stage: test stage: test
allow_failure: true allow_failure: true
script: script:
- cd test - cd test
- make test XUNIT=1 - make test_unit XUNIT=1
- make coverage - make coverage
coverage: "/lines......: ([^%]+%)/" coverage: "/lines......: ([^%]+%)/"
artifacts: artifacts:
paths: paths:
- code_html - code_html
- test.xml - test_unit.xml
...@@ -17,8 +17,10 @@ elaborate: ...@@ -17,8 +17,10 @@ elaborate:
test: test:
$(PYTHON) run.py $(TEST_FLAGS) $(PYTHON) run.py $(TEST_FLAGS)
test_unit: test_unit:
$(PYTHON) run.py $(TEST_FLAGS) 'lib.tb_*_unit_test.*'
test_feature: test_feature:
test_sanity: test_sanity:
$(PYTHON) run.py $(TEST_FLAGS) 'lib.tb_sanity.*'
coverage: coverage:
lcov --capture --directory . --output-file $@ lcov --capture --directory . --output-file $@
......
...@@ -6,12 +6,14 @@ ...@@ -6,12 +6,14 @@
# $ VUNIT_SIMULATOR=ghdl python run.py # $ VUNIT_SIMULATOR=ghdl python run.py
from os.path import join, dirname from os.path import join, dirname
from vunit import VUnit from vunit.ui import VUnit
from glob import glob from glob import glob
from pprint import pprint from pprint import pprint
import os import os
import signal import signal
import subprocess import subprocess
import re
from textwrap import dedent
def get_children_pids(parent_pid): def get_children_pids(parent_pid):
cmd = subprocess.run("ps -o pid --ppid {} --noheaders".format(parent_pid), shell=True, stdout=subprocess.PIPE, check=False) cmd = subprocess.run("ps -o pid --ppid {} --noheaders".format(parent_pid), shell=True, stdout=subprocess.PIPE, check=False)
...@@ -27,6 +29,34 @@ def recursive_kill(pid, sig=signal.SIGTERM): ...@@ -27,6 +29,34 @@ def recursive_kill(pid, sig=signal.SIGTERM):
except ProcessLookupError as e: except ProcessLookupError as e:
pass pass
def create_wrapper(lib):
files = lib.get_source_files()
tests = []
r = re.compile(r'^architecture\s+(\S+)\s+of\s+CAN_test\s+is$')
for file in files:
with open(file.name, 'rt', encoding='utf-8') as f:
for l in f:
m = r.match(l)
if m:
tests.append(m.group(1))
wrapper = []
with open("tb_wrappers.vhd", "wt", encoding='utf-8') as f:
for test in tests:
f.write(dedent("""\
library work;
USE work.CANtestLib.All;
entity tb_{test} is generic (runner_cfg : string); end entity;
architecture tb of tb_{test} is
for all:CAN_test use entity work.CAN_test({test});
begin
tb:entity work.vunittb_wrapper generic map(xrunner_cfg => runner_cfg);
end architecture;
-- -----------------------------------------------------------------------------
""".format(test=test)
))
lib.add_source_file("tb_wrappers.vhd")
# ghdl creates a new process group for itself and fails to kill its child when it receives a signal :( # ghdl creates a new process group for itself and fails to kill its child when it receives a signal :(
def sighandler(signo, frame): def sighandler(signo, frame):
signal.signal(signo, signal.SIG_DFL) signal.signal(signo, signal.SIG_DFL)
...@@ -43,9 +73,12 @@ root = dirname(__file__) ...@@ -43,9 +73,12 @@ root = dirname(__file__)
ui = VUnit.from_argv() ui = VUnit.from_argv()
lib = ui.add_library("lib") lib = ui.add_library("lib")
for pattern in ['../src/**/*.vhd', '*.vhd', 'unit/**/*.vhd', 'sanity/*.vhd', 'lib/*.vhd']: for pattern in ['../src/**/*.vhd', '*.vhd', 'unit/**/*.vhd', 'sanity/*.vhd', 'lib/*.vhd']:
p = join(root, pattern) p = join(root, pattern)
for f in glob(p, recursive=True): for f in glob(p, recursive=True):
lib.add_source_file(str(f)) if f != "tb_wrappers.vhd":
lib.add_source_file(str(f))
create_wrapper(lib)
#lib.add_compile_option("ghdl.flags", ["-Wc,-g"]) #lib.add_compile_option("ghdl.flags", ["-Wc,-g"])
......
--------------------------------------------------------------------------------
--
-- CTU CAN FD IP Core
-- Copyright (C) 2015-2018 Ondrej Ille <ondrej.ille@gmail.com>
--
-- Project advisors and co-authors:
-- Jiri Novak <jnovak@fel.cvut.cz>
-- Pavel Pisa <pisa@cmp.felk.cvut.cz>
-- Martin Jerabek <jerabma7@fel.cvut.cz>
-- Department of Measurement (http://meas.fel.cvut.cz/)
-- Faculty of Electrical Engineering (http://www.fel.cvut.cz)
-- Czech Technical University (http://www.cvut.cz/)
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this VHDL component and associated documentation files (the "Component"),
-- to deal in the Component without restriction, including without limitation
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
-- and/or sell copies of the Component, and to permit persons to whom the
-- Component is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Component.
--
-- THE COMPONENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
-- IN THE COMPONENT.
--
-- The CAN protocol is developed by Robert Bosch GmbH and protected by patents.
-- Anybody who wants to implement this IP core on silicon has to obtain a CAN
-- protocol license from Bosch.
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Purpose:
-- VUnit wrapper for sanity test.
--------------------------------------------------------------------------------
-- Revision History:
-- February 2018 First Implementation - Martin Jerabek
--------------------------------------------------------------------------------
library vunit_lib;
context vunit_lib.vunit_context;
library ieee;
library work;
use ieee.std_logic_1164.all;
USE work.CANtestLib.All;
entity vunittb_wrapper is
generic (
xrunner_cfg : string;
ok : boolean := false;
iterations : natural := 1;
log_level : log_lvl_type := info_l;
error_beh : err_beh_type := quit; -- Test behaviour when error occurs: Quit, or Go on
error_tol : natural := 0 -- Error tolerance, error counter should not
-- exceed this value in order for the test to pass
);
end entity;
architecture tb of vunittb_wrapper is
signal t_errors : natural := 0;
signal t_status : test_status_type;
signal t_run : boolean;
begin
g:if ok generate
i_test: CAN_test
port map (
iterations => iterations,
log_level => log_level,
error_beh => error_beh,
error_tol => error_tol,
errors => t_errors,
status => t_status,
run => t_run
);
end generate;
main:process
begin
test_runner_setup(runner, xrunner_cfg);
while test_suite loop
if run("test") then
t_run <= true;
wait until t_status = passed or t_status = failed;
report "Done";
report to_string(t_errors);
wait for 100 ns;
t_run <= false;
end if;
end loop;
test_runner_cleanup(runner, t_errors > 0);
end process;
end architecture;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment