Skip to content

Commit

Permalink
Added a common low-level log interface
Browse files Browse the repository at this point in the history
  • Loading branch information
LarsAsplund committed Jul 8, 2023
1 parent 8fcbf59 commit 26a7db3
Show file tree
Hide file tree
Showing 18 changed files with 6,489 additions and 214 deletions.
5,841 changes: 5,841 additions & 0 deletions examples/vhdl/osvvm_log_integration/osvvm_integration/AlertLogPkg.vhd

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
-- 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-2023, Lars Asplund lars.anders.asplund@gmail.com

library vunit_lib;
context vunit_lib.vunit_context;

package body common_log_pkg is
procedure write_to_log(
file log_destination : text;
msg : string := "";
log_time : time := no_time;
log_level : string := "";
log_source_name : string := "";
str_1, str_2, str_3, str_4, str_5, str_6, str_7, str_8, str_9, str_10 : string := "";
val_1, val_2, val_3, val_4, val_5, val_6, val_7, val_8, val_9, val_10 : integer := no_val
) is
constant stripped_log_level : string := strip(log_level);

alias prefix is str_2;
alias suffix is str_3;

variable logger : logger_t;
variable vunit_log_level : log_level_t;
variable full_msg : line;
begin
logger := get_logger(log_source_name);

if stripped_log_level = "WARNING" then
vunit_log_level := warning;
elsif stripped_log_level = "ERROR" then
vunit_log_level := error;
elsif stripped_log_level = "FAILURE" then
vunit_log_level := failure;
elsif stripped_log_level = "DEBUG" then
vunit_log_level := debug;
elsif stripped_log_level = "PASSED" then
vunit_log_level := pass;
else
vunit_log_level := info;
end if;

if prefix /= "" then
write(full_msg, prefix & " ");
end if;

write(full_msg, msg);

if suffix /= "" then
write(full_msg, " " & suffix);
end if;

log(logger, msg, vunit_log_level, path_offset => 4);
end;

end package body;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
-- 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-2023, Lars Asplund lars.anders.asplund@gmail.com

use work.ansi_pkg.all;
use work.log_levels_pkg.all;
use work.string_ops.upper;

library osvvm;
use osvvm.AlertLogPkg.all;

package body common_log_pkg is

procedure write_to_log(
file log_destination : text;
msg : string := "";
log_time : time := no_time;
log_level : string := "";
log_source_name : string := "";
str_1, str_2, str_3, str_4, str_5, str_6, str_7, str_8, str_9, str_10 : string := "";
val_1, val_2, val_3, val_4, val_5, val_6, val_7, val_8, val_9, val_10 : integer := no_val
) is
begin
if (log_level = "warning") or (log_level = "error") or (log_level = "failure") then
Alert(GetAlertLogID(log_source_name), msg, AlertType'value(upper(log_level)));
elsif (log_level = "debug") then
osvvm.AlertLogPkg.Log(GetAlertLogID(log_source_name), msg, DEBUG);
elsif (log_level = "pass") then
osvvm.AlertLogPkg.Log(GetAlertLogID(log_source_name), msg, PASSED);
else
osvvm.AlertLogPkg.Log(GetAlertLogID(log_source_name), msg);
end if;
end;

end package body;
63 changes: 63 additions & 0 deletions examples/vhdl/osvvm_log_integration/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env python3

# 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-2023, Lars Asplund lars.anders.asplund@gmail.com

from pathlib import Path
from itertools import product
from vunit import VUnit, VUnitCLI

cli = VUnitCLI()
cli.parser.add_argument(
"--use-osvvm-log",
action="store_true",
default=False,
help="Re-direct VUnit log output to OSVVM log handling",
)
cli.parser.add_argument(
"--use-vunit-log",
action="store_true",
default=False,
help="Re-direct OSVVM log output to VUnit log handling",
)
args = cli.parse_args()
if args.use_osvvm_log and args.use_vunit_log:
raise RuntimeError("Only one of --use-osvvm-log and --use-vunit-log can be used at any time.")
args.clean = True
prj = VUnit.from_args(args=args)
root = Path(__file__).parent
if args.use_osvvm_log:
prj.add_vhdl_builtins(use_external_log=Path(root / "osvvm_integration" / "vunit_to_osvvm_common_log_pkg-body.vhd"))
else:
prj.add_vhdl_builtins()

lib = prj.add_library("lib")
lib.add_source_files(root / "*.vhd")
lib.test_bench("tb_example").set_generic("use_osvvm_log", args.use_osvvm_log)
lib.test_bench("tb_example").set_generic("use_vunit_log", args.use_vunit_log)

osvvm = prj.add_library("osvvm")
osvvm_files_to_compile = [
"NamePkg.vhd",
"OsvvmGlobalPkg.vhd",
"TranscriptPkg.vhd",
"TextUtilPkg.vhd",
"OsvvmScriptSettingsPkg.vhd",
"OsvvmScriptSettingsPkg_default.vhd",
]
for osvvm_file in osvvm_files_to_compile:
osvvm.add_source_files(root / ".." / ".." / ".." / "vunit" / "vhdl" / "osvvm" / osvvm_file)

if args.use_vunit_log:
osvvm.add_source_files(root / ".." / ".." / ".." / "vunit" / "vhdl" / "logging" / "src" / "common_log_pkg.vhd")
osvvm.add_source_files(root / "osvvm_integration" / "osvvm_to_vunit_common_log_pkg-body.vhd")
osvvm.add_source_files(root / "osvvm_integration" / "AlertLogPkg.vhd")
else:
osvvm.add_source_files(root / ".." / ".." / ".." / "vunit" / "vhdl" / "osvvm" / "AlertLogPkg.vhd")


prj.set_compile_option("rivierapro.vcom_flags", ["-dbg"])
prj.main()
85 changes: 85 additions & 0 deletions examples/vhdl/osvvm_log_integration/tb_example.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
-- 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-2023, Lars Asplund lars.anders.asplund@gmail.com

library vunit_lib;
context vunit_lib.vunit_context;

library osvvm;
use osvvm.AlertLogPkg.all;

library ieee;
use ieee.std_logic_1164.all;

entity tb_example is
generic (
runner_cfg : string;
use_osvvm_log : boolean;
use_vunit_log : boolean);
end entity;

architecture tb of tb_example is

begin
main : process
constant logger : logger_t := get_logger("A VUnit logger name");
constant parent_logger : logger_t := get_logger("VUnit parent");
constant child_logger : logger_t := get_logger("VUnit child", parent_logger);
constant checker : checker_t := new_checker(logger);

constant id : AlertLogIDType := GetAlertLogID("An OSVVM ID");
constant parent_id : AlertLogIDType := GetAlertLogID("OSVVM parent");
constant child_id : AlertLogIDType := GetAlertLogID("OSVVM child", parent_id);
begin
test_runner_setup(runner, runner_cfg);
set_stop_level(failure);

if use_osvvm_log then
print(LF & "-------------------------------------------------------------------");
print("This is what VUnit log messages look like when piped through OSVVM:");
print("-------------------------------------------------------------------" & LF);
else
print(LF & "------------------------------------------------------------------------");
print("This is what standard VUnit log messages look like. Call run.py");
print("with --use-osvvm-log to see what is looks like when piped through OSVVM.");
print("------------------------------------------------------------------------" & LF);
end if;

info(logger, "Hello from VUnit");
check(checker, false, "An error from VUnit");
info(child_logger, "Hello from VUnit hierarchy");

if use_vunit_log then
print(LF & "-------------------------------------------------------------------");
print("This is what OSVVM log messages look like when piped through VUnit:");
print("-------------------------------------------------------------------" & LF);
else
print(LF & "------------------------------------------------------------------------");
print("This is what standard OSVVM log messages look like. Call run.py");
print("with --use-vunit-log to see what is looks like when piped through VUnit.");
print("------------------------------------------------------------------------" & LF);
end if;

osvvm.AlertLogPkg.Log(id, "Hello from OSVVM");
Alert(id, "An error from OSVVM");
osvvm.AlertLogPkg.Log(child_id, "Hello from OSVVM hierarchy");

if use_osvvm_log then
print(LF & "------------------------------------------------------------------------");
print("Only log messages are piped through OSVVM. Print messages outside of the");
print("the logging framework are unaffected. For example this FAILURE");
print("message.");
print("------------------------------------------------------------------------" & LF);
else
print(LF & "");
end if;

test_runner_cleanup(runner);
end process;

test_runner_watchdog(runner, 1000 ns);


end architecture;
29 changes: 29 additions & 0 deletions tests/acceptance/artificial/vhdl/other_logging_framework.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-- 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-2023, Lars Asplund lars.anders.asplund@gmail.com

use std.textio.all;

package body common_log_pkg is

procedure write_to_log(
file log_destination : text;
msg : string := "";
log_time : time := no_time;
log_level : string := "";
log_source_name : string := "";
str_1, str_2, str_3, str_4, str_5, str_6, str_7, str_8, str_9, str_10 : string := "";
val_1, val_2, val_3, val_4, val_5, val_6, val_7, val_8, val_9, val_10 : integer := no_val
) is
file f : text;
variable l : line;
begin
file_open(f, msg & "/external_logging_framework.txt", write_mode);
write(l, string'("Using external logging framework"));
writeline(f, l);
file_close(f);
end;

end package body;
27 changes: 26 additions & 1 deletion tests/acceptance/artificial/vhdl/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
root = Path(__file__).parent

vu = VUnit.from_argv()
vu.add_vhdl_builtins()
vu.add_vhdl_builtins(use_external_log=root / "other_logging_framework.vhd")

lib = vu.add_library("lib")
lib2 = vu.add_library("lib2")

for file in glob(str(root / "*.vhd")):
if "tb_set_generic" in file:
lib2.add_source_files(file)
elif "other_logging_framework" in file:
continue
else:
lib.add_source_files(file)

Expand Down Expand Up @@ -92,10 +94,33 @@ def configure_tb_assert_stop_level(ui):
test.set_sim_option("vhdl_assert_stop_level", vhdl_assert_stop_level)


def configure_tb_external_logging_framework(ui):
tb = ui.library("lib").entity("tb_external_logging_framework")

def pre_config(output_path):
(Path(output_path) / "external_logging_framework.txt").unlink(missing_ok=True)

return True

def post_check(output_path):
if not (Path(output_path) / "external_logging_framework.txt").exists():
return False

return (
(Path(output_path) / "external_logging_framework.txt")
.read_text()
.startswith("Using external logging framework")
)

tb.set_pre_config(pre_config)
tb.set_post_check(post_check)


configure_tb_with_generic_config()
configure_tb_same_sim_all_pass(vu)
configure_tb_set_generic(vu)
configure_tb_assert_stop_level(vu)
configure_tb_external_logging_framework(vu)
lib.entity("tb_no_generic_override").set_generic("g_val", False)
lib.entity("tb_ieee_warning").test("pass").set_sim_option("disable_ieee_warnings", True)
lib.entity("tb_other_file_tests").scan_tests_from_file(str(root / "other_file_tests.vhd"))
Expand Down
24 changes: 24 additions & 0 deletions tests/acceptance/artificial/vhdl/tb_external_logging_framework.vhd
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-2023, Lars Asplund lars.anders.asplund@gmail.com

library vunit_lib;
context vunit_lib.vunit_context;

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

architecture vunit_test_bench of tb_external_logging_framework is
begin
test_runner : process
begin
test_runner_setup(runner, runner_cfg);
info(output_path(runner_cfg));
test_runner_cleanup(runner);
wait;
end process;
end architecture;
1 change: 1 addition & 0 deletions tests/acceptance/test_artificial.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def test_exit_0_flag(self):
("passed", "lib.tb_with_generic_config.cfg.Test 3"),
("passed", "lib.tb_with_generic_config.cfg.Test 4"),
("passed", "lib.tb_no_generic_override.all"),
("passed", "lib.tb_external_logging_framework.all"),
("passed", "lib.tb_ieee_warning.pass"),
("failed", "lib.tb_ieee_warning.fail"),
(
Expand Down
7 changes: 7 additions & 0 deletions tests/acceptance/test_external_run_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,13 @@ def test_vhdl_array_axis_vcs_example_project(self):
def test_vhdl_axi_dma_example_project(self):
self.check(ROOT / "examples/vhdl/axi_dma/run.py")

def test_vhdl_osvvm_log_integration(self):
self.check(ROOT / "examples/vhdl/osvvm_log_integration/run.py", exit_code=1)
check_report(
self.report_file,
[("failed", "lib.tb_example.all")],
)

@mark.skipif(
simulator_check(lambda simclass: not simclass.supports_vhdl_contexts()),
reason="This simulator/backend does not support VHDL contexts",
Expand Down
2 changes: 2 additions & 0 deletions tests/lint/test_license.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ def find_licensed_files():
(Path(root) / file_name).resolve(),
):
continue
if file_name == "AlertLogPkg.vhd":
continue
if is_prefix_of(
(VHDL_PATH / "JSON-for-VHDL").resolve(),
(Path(root) / file_name).resolve(),
Expand Down
Loading

0 comments on commit 26a7db3

Please sign in to comment.