-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
31493fc
commit 32c821c
Showing
2 changed files
with
245 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
-- 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-2024, Lars Asplund [email protected] | ||
-- | ||
-- This package contains common functionality for VCs. | ||
|
||
context work.vunit_context; | ||
context work.com_context; | ||
|
||
package vc_pkg is | ||
type unexpected_msg_type_policy_t is (fail, ignore); | ||
|
||
type std_cfg_t is record | ||
p_id : id_t; | ||
p_actor : actor_t; | ||
p_logger : logger_t; | ||
p_checker : checker_t; | ||
p_unexpected_msg_type_policy : unexpected_msg_type_policy_t; | ||
end record; | ||
|
||
constant null_std_cfg : std_cfg_t := ( | ||
p_id => null_id, | ||
p_actor => null_actor, | ||
p_logger => null_logger, | ||
p_checker => null_checker, | ||
p_unexpected_msg_type_policy => ignore | ||
); | ||
|
||
-- Creates a standard VC configuration with an id, an actor, a logger, a | ||
-- checker, and an unexpected message type policy. | ||
-- | ||
-- If id = null_id, the id will be assigned the name provider:vc_name:n where n is 1 | ||
-- for the first instance and increasing with one for every additional instance. | ||
-- | ||
-- The id must not have an associated actor before the call as that may indicate | ||
-- several users of the same actor. | ||
-- | ||
-- If a logger exist for the id, it will be reused. If not, a new logger is created. | ||
-- A new checker is created that reports to the logger. | ||
impure function create_std_cfg( | ||
id : id_t := null_id; | ||
provider : string := ""; | ||
vc_name : string := ""; | ||
unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail | ||
) return std_cfg_t; | ||
|
||
-- These functions extracts information from the standard VC configuration | ||
impure function get_id(std_cfg : std_cfg_t) return id_t; | ||
impure function get_actor(std_cfg : std_cfg_t) return actor_t; | ||
impure function get_logger(std_cfg : std_cfg_t) return logger_t; | ||
impure function get_checker(std_cfg : std_cfg_t) return checker_t; | ||
impure function unexpected_msg_type_policy(std_cfg : std_cfg_t) return unexpected_msg_type_policy_t; | ||
|
||
-- Handle messages with unexpected message type according to the standard configuration | ||
procedure unexpected_msg_type(msg_type : msg_type_t; std_cfg : std_cfg_t); | ||
|
||
end package; | ||
|
||
package body vc_pkg is | ||
constant vc_pkg_logger : logger_t := get_logger("vunit_lib:vc_pkg"); | ||
constant vc_pkg_checker : checker_t := new_checker(vc_pkg_logger); | ||
|
||
impure function create_std_cfg( | ||
id : id_t := null_id; | ||
provider : string := ""; | ||
vc_name : string := ""; | ||
unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail | ||
) return std_cfg_t is | ||
variable result : std_cfg_t; | ||
variable provider_id : id_t; | ||
variable vc_id : id_t; | ||
begin | ||
if id /= null_id then | ||
result.p_id := id; | ||
else | ||
if provider = "" then | ||
check_failed(vc_pkg_checker, "A provider must be provided."); | ||
|
||
-- Simplifies testing when vc_pkg_checker logger is mocked | ||
return null_std_cfg; | ||
end if; | ||
|
||
if vc_name = "" then | ||
check_failed(vc_pkg_checker, "A VC name must be provided."); | ||
|
||
-- Simplifies testing when vc_pkg_checker logger is mocked | ||
return null_std_cfg; | ||
end if; | ||
|
||
provider_id := get_id(provider); | ||
vc_id := get_id(vc_name, parent => provider_id); | ||
result.p_id := get_id(to_string(num_children(vc_id) + 1), parent => vc_id); | ||
end if; | ||
|
||
result.p_unexpected_msg_type_policy := unexpected_msg_type_policy; | ||
|
||
if find(result.p_id, enable_deferred_creation => false) /= null_actor then | ||
check_failed(vc_pkg_checker, "An actor already exists for " & full_name(result.p_id) & "."); | ||
else | ||
result.p_actor := new_actor(result.p_id); | ||
end if; | ||
|
||
result.p_logger := get_logger(result.p_id); | ||
result.p_checker := new_checker(result.p_logger); | ||
|
||
return result; | ||
end; | ||
|
||
impure function get_id(std_cfg : std_cfg_t) return id_t is | ||
begin | ||
return std_cfg.p_id; | ||
end; | ||
|
||
impure function get_actor(std_cfg : std_cfg_t) return actor_t is | ||
begin | ||
return std_cfg.p_actor; | ||
end; | ||
|
||
impure function get_logger(std_cfg : std_cfg_t) return logger_t is | ||
begin | ||
return std_cfg.p_logger; | ||
end; | ||
|
||
impure function get_checker(std_cfg : std_cfg_t) return checker_t is | ||
begin | ||
return std_cfg.p_checker; | ||
end; | ||
|
||
impure function unexpected_msg_type_policy(std_cfg : std_cfg_t) return unexpected_msg_type_policy_t is | ||
begin | ||
return std_cfg.p_unexpected_msg_type_policy; | ||
end; | ||
|
||
procedure unexpected_msg_type(msg_type : msg_type_t; | ||
std_cfg : std_cfg_t) is | ||
begin | ||
if unexpected_msg_type_policy(std_cfg) = fail then | ||
unexpected_msg_type(msg_type, get_logger(std_cfg)); | ||
end if; | ||
end; | ||
end package body; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
-- 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-2024, Lars Asplund [email protected] | ||
|
||
library vunit_lib; | ||
context vunit_lib.vunit_context; | ||
context work.com_context; | ||
use work.vc_pkg.all; | ||
|
||
entity tb_vc_pkg is | ||
generic(runner_cfg : string); | ||
end entity; | ||
|
||
architecture a of tb_vc_pkg is | ||
begin | ||
|
||
main : process | ||
variable std_cfg : std_cfg_t; | ||
variable id : id_t; | ||
variable actor : actor_t; | ||
|
||
constant vc_pkg_logger : logger_t := get_logger("vunit_lib:vc_pkg"); | ||
constant unknown_msg_type : msg_type_t := new_msg_type("unknown_msg"); | ||
begin | ||
test_runner_setup(runner, runner_cfg); | ||
while test_suite loop | ||
if run("Test that provider must be supplied with null_id") then | ||
mock(vc_pkg_logger, error); | ||
std_cfg := create_std_cfg(vc_name => "my_vc"); | ||
check_only_log(vc_pkg_logger, "A provider must be provided.", error); | ||
unmock(vc_pkg_logger); | ||
|
||
elsif run("Test that vc_name must be supplied with null_id") then | ||
mock(vc_pkg_logger, error); | ||
std_cfg := create_std_cfg(provider => "provider"); | ||
check_only_log(vc_pkg_logger, "A VC name must be provided.", error); | ||
unmock(vc_pkg_logger); | ||
|
||
elsif run("Test standard config with specified id") then | ||
id := get_id("id"); | ||
std_cfg := create_std_cfg(id => id); | ||
check(std_cfg.p_id = id); | ||
check(std_cfg.p_actor = find(id, enable_deferred_creation => false)); | ||
check(std_cfg.p_logger = get_logger(id)); | ||
check(get_logger(std_cfg.p_checker) = get_logger(id)); | ||
check(std_cfg.p_unexpected_msg_type_policy = fail); | ||
|
||
elsif run("Test standard config with null_id") then | ||
for instance in 1 to 3 loop | ||
std_cfg := create_std_cfg(provider => "provider", vc_name => "vc_name"); | ||
id := std_cfg.p_id; | ||
check(id = get_id("provider:vc_name:" & to_string(instance))); | ||
check(std_cfg.p_actor = find(id, enable_deferred_creation => false)); | ||
check(std_cfg.p_logger = get_logger(id)); | ||
check(get_logger(std_cfg.p_checker) = get_logger(id)); | ||
check(std_cfg.p_unexpected_msg_type_policy = fail); | ||
end loop; | ||
|
||
elsif run("Test standard config with specified unexpected message type policy") then | ||
std_cfg := create_std_cfg( | ||
provider => "provider", | ||
vc_name => "vc_name", | ||
unexpected_msg_type_policy => ignore | ||
); | ||
id := std_cfg.p_id; | ||
check(id = get_id("provider:vc_name:1")); | ||
check(std_cfg.p_actor = find(id, enable_deferred_creation => false)); | ||
check(std_cfg.p_logger = get_logger(id)); | ||
check(get_logger(std_cfg.p_checker) = get_logger(id)); | ||
check(std_cfg.p_unexpected_msg_type_policy = ignore); | ||
|
||
elsif run("Test failing on reused actor") then | ||
mock(vc_pkg_logger, error); | ||
id := get_id("foo:bar"); | ||
actor := new_actor(id); | ||
std_cfg := create_std_cfg(id => id); | ||
check_only_log(vc_pkg_logger, "An actor already exists for foo:bar.", error); | ||
unmock(vc_pkg_logger); | ||
|
||
elsif run("Test failing on unexpected message") then | ||
id := get_id("id"); | ||
std_cfg := create_std_cfg(id => id); | ||
mock(get_logger(id), failure); | ||
unexpected_msg_type(unknown_msg_type, std_cfg); | ||
check_only_log(get_logger(id), "Got unexpected message unknown_msg", failure); | ||
unmock(get_logger(id)); | ||
|
||
elsif run("Test ignoring unexpected message") then | ||
id := get_id("id"); | ||
std_cfg := create_std_cfg(id => id, unexpected_msg_type_policy => ignore); | ||
mock(get_logger(id), failure); | ||
unexpected_msg_type(unknown_msg_type, std_cfg); | ||
check_no_log; | ||
unmock(get_logger(id)); | ||
|
||
end if; | ||
end loop; | ||
test_runner_cleanup(runner, fail_on_warning => true); | ||
end process; | ||
end architecture; |