aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/ticket89/project/src93/bfm_common_pkg.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/gna/ticket89/project/src93/bfm_common_pkg.vhd')
-rw-r--r--testsuite/gna/ticket89/project/src93/bfm_common_pkg.vhd396
1 files changed, 396 insertions, 0 deletions
diff --git a/testsuite/gna/ticket89/project/src93/bfm_common_pkg.vhd b/testsuite/gna/ticket89/project/src93/bfm_common_pkg.vhd
new file mode 100644
index 000000000..8a5780432
--- /dev/null
+++ b/testsuite/gna/ticket89/project/src93/bfm_common_pkg.vhd
@@ -0,0 +1,396 @@
+--========================================================================================================================
+-- Copyright (c) 2015 by Bitvis AS. All rights reserved.
+-- A free license is hereby granted, free of charge, to any person obtaining
+-- a copy of this VHDL code and associated documentation files (for 'Bitvis Utility Library'),
+-- to use, copy, modify, merge, publish and/or distribute - subject to the following conditions:
+-- - This copyright notice shall be included as is in all copies or substantial portions of the code and documentation
+-- - The files included in Bitvis Utility Library may only be used as a part of this library as a whole
+-- - The License file may not be modified
+-- - The calls in the code to the license file ('show_license') may not be removed or modified.
+-- - No other conditions whatsoever may be added to those of this License
+
+-- BITVIS UTILITY LIBRARY AND ANY PART THEREOF ARE 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 COPYRIGHT HOLDERS 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 BITVIS UTILITY LIBRARY.
+--========================================================================================================================
+
+------------------------------------------------------------------------------------------
+-- VHDL unit : Bitvis Utility Library : bfm_common_pkg
+--
+-- Description : See library quick reference (under 'doc') and README-file(s)
+------------------------------------------------------------------------------------------
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.math_real.all;
+use ieee.numeric_std.all;
+use std.textio.all;
+
+use work.types_pkg.all;
+use work.string_methods_pkg.all;
+use work.methods_pkg.all;
+
+library ieee_proposed;
+use ieee_proposed.standard_additions.all;
+use ieee_proposed.std_logic_1164_additions.all;
+use ieee_proposed.standard_textio_additions.all;
+
+package bfm_common_pkg is
+ -- General declarations related to BFMs
+ type t_normalization_mode is (ALLOW_WIDER, ALLOW_NARROWER, ALLOW_WIDER_NARROWER, ALLOW_EXACT_ONLY);
+
+ -- Functions/procedures
+ impure function normalise(
+ constant value : in std_logic_vector;
+ constant target : in std_logic_vector;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "slv"
+ ) return std_logic_vector;
+
+ impure function normalise(
+ constant value : in unsigned;
+ constant target : in unsigned;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "unsigned"
+ ) return unsigned;
+
+ impure function normalise(
+ constant value : in signed;
+ constant target : in signed;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "signed"
+ ) return signed;
+
+
+ -- Functions/procedures
+ impure function normalize_and_check(
+ constant value : in std_logic_vector;
+ constant target : in std_logic_vector;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "slv"
+ ) return std_logic_vector;
+
+ impure function normalize_and_check(
+ constant value : in unsigned;
+ constant target : in unsigned;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "unsigned"
+ ) return unsigned;
+
+ impure function normalize_and_check(
+ constant value : in signed;
+ constant target : in signed;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "signed"
+ ) return signed;
+
+ procedure wait_until_given_time_after_rising_edge (
+ signal clk : in std_logic;
+ constant wait_time : in time
+ );
+
+end package bfm_common_pkg;
+--=================================================================================================
+
+package body bfm_common_pkg is
+ constant C_SCOPE : string := "bfm_common";
+
+ -- Normalize 'value' to the width given by 'target' and perform sanity check.
+ impure function normalize_and_check(
+ constant value : in std_logic_vector;
+ constant target : in std_logic_vector;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "slv"
+ ) return std_logic_vector is
+ constant name : string := "normalize_and_check(" & val_type & ": " &
+ value_name & "=" & to_string(value, HEX, AS_IS) & ", " &
+ target_name & "=" & to_string(target, HEX, AS_IS) & ")";
+ alias a_value : std_logic_vector(value'length - 1 downto 0) is value;
+ alias a_target : std_logic_vector(target'length - 1 downto 0) is target;
+ variable v_normalized_value : std_logic_vector(target'length - 1 downto 0);
+ begin
+ -- Verify that value and target are not zero-length vectors
+ if value'length = 0 then
+ tb_error(name & " => Value length is zero! " & msg, C_SCOPE);
+ return v_normalized_value;
+ elsif target'length = 0 then
+ tb_error(name & " => Target length is zero! " & msg, C_SCOPE);
+ return v_normalized_value;
+ end if;
+ -- If value'length > target'length, remove leading zeros from value
+ if (a_value'length > a_target'length) then
+ v_normalized_value := a_value(a_target'length - 1 downto 0);
+ -- Sanity checks
+ if not (mode = ALLOW_WIDER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " without using ALLOW_WIDER mode. " & msg, C_SCOPE);
+ end if;
+ if not matching_widths(a_value, a_target) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " and has non-zeros in the extended MSB. " & msg, C_SCOPE);
+ end if;
+ -- If value'length = target'length
+ elsif (a_value'length = a_target'length) then
+ v_normalized_value := a_value;
+ -- If value'length < target'length, add padding (leading zeros) to value
+ elsif (a_value'length < a_target'length) then
+ v_normalized_value := (others => '0');
+ v_normalized_value(a_value'length - 1 downto 0) := a_value;
+ -- Sanity check
+ if not (mode = ALLOW_NARROWER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is narrower than " & target_name & " without using ALLOW_NARROWER mode. " & msg, C_SCOPE);
+ end if;
+ end if;
+
+ return v_normalized_value;
+ end;
+
+ impure function normalize_and_check(
+ constant value : in unsigned;
+ constant target : in unsigned;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "unsigned"
+ ) return unsigned is
+ begin
+ return unsigned( normalize_and_check(std_logic_vector(value), std_logic_vector(target), mode, value_name, target_name, msg, val_type) );
+ end;
+
+ impure function normalize_and_check(
+ constant value : in signed;
+ constant target : in signed;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "signed"
+ ) return signed is
+ constant name : string := "normalize_and_check(" & val_type & ": " &
+ value_name & "=" & to_string(std_logic_vector(value)) & ", " &
+ target_name & "=" & to_string(std_logic_vector(target)) & ")";
+ alias a_value : signed(value'length - 1 downto 0) is value;
+ alias a_target : signed(target'length - 1 downto 0) is target;
+ variable v_normalized_value : signed(target'length - 1 downto 0);
+ begin
+ -- Verify that value and target are not zero-length vectors
+ if value'length = 0 then
+ tb_error(name & " => Value length is zero! " & msg, C_SCOPE);
+ return v_normalized_value;
+ elsif target'length = 0 then
+ tb_error(name & " => Target length is zero! " & msg, C_SCOPE);
+ return v_normalized_value;
+ end if;
+ -- If value'length > target'length, remove leading zeros/ones from value
+ if a_value'length > a_target'length then
+ v_normalized_value := a_value(a_target'length - 1 downto 0);
+ -- Sanity checks
+ if not (mode = ALLOW_WIDER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " without using ALLOW_WIDER mode. " & msg, C_SCOPE);
+ end if;
+
+ if a_value(a_value'high) = '0' then -- positive value
+ if not matching_widths(a_value, a_target) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " and has non-zeros in the extended MSB. " & msg, C_SCOPE);
+ end if;
+ elsif a_value(a_value'high) = '1' then -- negative value
+ for i in a_value'high downto a_target'length loop
+ if a_value(i) = '0' then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " and has non-sign bits in the extended MSB. " & msg, C_SCOPE);
+ end if;
+ end loop;
+ end if;
+ -- If value'length = target'length
+ elsif a_value'length = a_target'length then
+ v_normalized_value := a_value;
+ -- If value'length < target'length, add padding (leading zeros/ones) to value
+ elsif a_value'length < a_target'length then
+ if a_value(a_value'high) = '0' then -- positive value
+ v_normalized_value := (others => '0');
+ elsif a_value(a_value'high) = '1' then -- negative value
+ v_normalized_value := (others => '1');
+ end if;
+ v_normalized_value(a_value'length - 1 downto 0) := a_value;
+ -- Sanity check
+ if not (mode = ALLOW_NARROWER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is narrower than " & target_name & " without using ALLOW_NARROWER mode. " & msg, C_SCOPE);
+ end if;
+ end if;
+
+ return v_normalized_value;
+ end;
+
+
+ -- Normalise 'value' to the width given by 'target'.
+ impure function normalise(
+ constant value : in std_logic_vector;
+ constant target : in std_logic_vector;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "slv"
+ ) return std_logic_vector is
+ constant name : string := "normalise(" & val_type & ": " &
+ value_name & "=" & to_string(value, HEX, AS_IS) & ", " &
+ target_name & "=" & to_string(target, HEX, AS_IS) & ")";
+ alias a_value : std_logic_vector(value'length - 1 downto 0) is value;
+ alias a_target : std_logic_vector(target'length - 1 downto 0) is target;
+ variable v_normalised_value : std_logic_vector(target'length - 1 downto 0);
+ begin
+ deprecate(get_procedure_name_from_instance_name(value'instance_name), "Use normalize_and_check().");
+ -- Verify that value and target are not zero-length vectors
+ if value'length = 0 then
+ tb_error(name & " => Value length is zero! " & msg, C_SCOPE);
+ return v_normalised_value;
+ elsif target'length = 0 then
+ tb_error(name & " => Target length is zero! " & msg, C_SCOPE);
+ return v_normalised_value;
+ end if;
+ -- If value'length > target'length, remove leading zeros from value
+ if (a_value'length > a_target'length) then
+ v_normalised_value := a_value(a_target'length - 1 downto 0);
+ -- Sanity checks
+ if not (mode = ALLOW_WIDER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " without using ALLOW_WIDER mode. " & msg, C_SCOPE);
+ end if;
+ if not matching_widths(a_value, a_target) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " and has non-zeros in the extended MSB. " & msg, C_SCOPE);
+ end if;
+ -- If value'length = target'length
+ elsif (a_value'length = a_target'length) then
+ v_normalised_value := a_value;
+ -- If value'length < target'length, add padding (leading zeros) to value
+ elsif (a_value'length < a_target'length) then
+ v_normalised_value := (others => '0');
+ v_normalised_value(a_value'length - 1 downto 0) := a_value;
+ -- Sanity check
+ if not (mode = ALLOW_NARROWER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is narrower than " & target_name & " without using ALLOW_NARROWER mode. " & msg, C_SCOPE);
+ end if;
+ end if;
+
+ return v_normalised_value;
+ end;
+
+ impure function normalise(
+ constant value : in unsigned;
+ constant target : in unsigned;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "unsigned"
+ ) return unsigned is
+ begin
+ return unsigned( normalise(std_logic_vector(value), std_logic_vector(target), mode, value_name, target_name, msg, val_type) );
+ end;
+
+ impure function normalise(
+ constant value : in signed;
+ constant target : in signed;
+ constant mode : in t_normalization_mode;
+ constant value_name : string;
+ constant target_name : string;
+ constant msg : string;
+ constant val_type : string := "signed"
+ ) return signed is
+ constant name : string := "normalise(" & val_type & ": " &
+ value_name & "=" & to_string(std_logic_vector(value)) & ", " &
+ target_name & "=" & to_string(std_logic_vector(target)) & ")";
+ alias a_value : signed(value'length - 1 downto 0) is value;
+ alias a_target : signed(target'length - 1 downto 0) is target;
+ variable v_normalised_value : signed(target'length - 1 downto 0);
+ begin
+ deprecate(get_procedure_name_from_instance_name(value'instance_name), "Use normalize_and_check().");
+ -- Verify that value and target are not zero-length vectors
+ if value'length = 0 then
+ tb_error(name & " => Value length is zero! " & msg, C_SCOPE);
+ return v_normalised_value;
+ elsif target'length = 0 then
+ tb_error(name & " => Target length is zero! " & msg, C_SCOPE);
+ return v_normalised_value;
+ end if;
+ -- If value'length > target'length, remove leading zeros/ones from value
+ if a_value'length > a_target'length then
+ v_normalised_value := a_value(a_target'length - 1 downto 0);
+ -- Sanity checks
+ if not (mode = ALLOW_WIDER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " without using ALLOW_WIDER mode. " & msg, C_SCOPE);
+ end if;
+
+ if a_value(a_value'high) = '0' then -- positive value
+ if not matching_widths(a_value, a_target) then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " and has non-zeros in the extended MSB. " & msg, C_SCOPE);
+ end if;
+ elsif a_value(a_value'high) = '1' then -- negative value
+ for i in a_value'high downto a_target'length loop
+ if a_value(i) = '0' then
+ tb_error(name & " => " & value_name & " is wider than " & target_name & " and has non-sign bits in the extended MSB. " & msg, C_SCOPE);
+ end if;
+ end loop;
+ end if;
+ -- If value'length = target'length
+ elsif a_value'length = a_target'length then
+ v_normalised_value := a_value;
+ -- If value'length < target'length, add padding (leading zeros/ones) to value
+ elsif a_value'length < a_target'length then
+ if a_value(a_value'high) = '0' then -- positive value
+ v_normalised_value := (others => '0');
+ elsif a_value(a_value'high) = '1' then -- negative value
+ v_normalised_value := (others => '1');
+ end if;
+ v_normalised_value(a_value'length - 1 downto 0) := a_value;
+ -- Sanity check
+ if not (mode = ALLOW_NARROWER or mode = ALLOW_WIDER_NARROWER) then
+ tb_error(name & " => " & value_name & " is narrower than " & target_name & " without using ALLOW_NARROWER mode. " & msg, C_SCOPE);
+ end if;
+ end if;
+
+ return v_normalised_value;
+ end;
+
+ -- Wait until wait_time after rising_edge(clk)
+ procedure wait_until_given_time_after_rising_edge (
+ signal clk : in std_logic;
+ constant wait_time : in time
+ ) is
+ variable v_remaining_wait_time : time;
+ begin
+ -- If the time since the previous rising_edge is less than wait_time,
+ -- we don't have to wait until the next rising_edge,
+ -- only wait_time minus the time already passed since rising_edge
+ if (clk'last_event <= wait_time and -- less than wait_time has passed since last event
+ clk'last_value = '0' and clk = '1' -- last event was a rising_edge
+ ) then
+ v_remaining_wait_time := wait_time - clk'last_event; -- Wait until wait_time after rising_edge
+ else
+ wait until rising_edge(clk);
+ v_remaining_wait_time := wait_time; -- Wait until wait_time after rising_edge
+ end if;
+ wait for v_remaining_wait_time;
+ end;
+
+end package body bfm_common_pkg;