aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue317/PoC/src/common/physical.vhdl
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/gna/issue317/PoC/src/common/physical.vhdl')
-rw-r--r--testsuite/gna/issue317/PoC/src/common/physical.vhdl1039
1 files changed, 1039 insertions, 0 deletions
diff --git a/testsuite/gna/issue317/PoC/src/common/physical.vhdl b/testsuite/gna/issue317/PoC/src/common/physical.vhdl
new file mode 100644
index 000000000..b8b07d7e6
--- /dev/null
+++ b/testsuite/gna/issue317/PoC/src/common/physical.vhdl
@@ -0,0 +1,1039 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+-- =============================================================================
+-- Authors: Patrick Lehmann
+-- Martin Zabel
+-- Thomas B. Preusser
+--
+-- Package: This VHDL package declares new physical types and their
+-- conversion functions.
+--
+-- Description:
+-- -------------------------------------
+-- For detailed documentation see below.
+--
+-- NAMING CONVENTION:
+-- t - time
+-- p - period
+-- d - delay
+-- f - frequency
+-- br - baud rate
+-- vec - vector
+--
+-- ATTENTION:
+-- This package is not supported by Xilinx Synthese Tools prior to 14.7!
+--
+-- It was successfully tested with:
+-- - Xilinx Synthesis Tool (XST) 14.7 and Xilinx ISE Simulator (iSim) 14.7
+-- - Quartus II 13.1
+-- - QuestaSim 10.0d
+-- - GHDL 0.31
+--
+-- Tool chains with known issues:
+-- - Xilinx Vivado Synthesis 2014.4
+--
+-- Untested tool chains
+-- - Xilinx Vivado Simulator (xSim) 2014.4
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair of VLSI-Design, Diagnostics and Architecture
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+-- =============================================================================
+
+library IEEE;
+use IEEE.math_real.all;
+
+library PoC;
+use PoC.config.all;
+use PoC.utils.all;
+use PoC.strings.all;
+
+
+package physical is
+
+ type FREQ is range 0 to integer'high units
+ Hz;
+ kHz = 1000 Hz;
+ MHz = 1000 kHz;
+ GHz = 1000 MHz;
+ end units;
+
+ type BAUD is range 0 to integer'high units
+ Bd;
+ kBd = 1000 Bd;
+ MBd = 1000 kBd;
+ GBd = 1000 MBd;
+ end units;
+
+ type MEMORY is range 0 to integer'high units
+ Byte;
+ KiB = 1024 Byte;
+ MiB = 1024 KiB;
+ GiB = 1024 MiB;
+ end units;
+
+ -- vector data types
+ type T_TIMEVEC is array(natural range <>) of time;
+ type T_FREQVEC is array(natural range <>) of FREQ;
+ type T_BAUDVEC is array(natural range <>) of BAUD;
+ type T_MEMVEC is array(natural range <>) of MEMORY;
+
+ -- if true: TimingToCycles reports difference between expected and actual result
+ constant C_PHYSICAL_REPORT_TIMING_DEVIATION : boolean := TRUE;
+
+ -- conversion functions
+ function to_time(f : FREQ) return time;
+ function to_freq(p : time) return FREQ;
+ function to_freq(br : BAUD) return FREQ;
+ function to_baud(str : string) return BAUD;
+
+ -- inter-type arithmetic
+ function div(a : time; b : time) return real;
+ function div(a : FREQ; b : FREQ) return real;
+
+ function "/"(x : real; t : time) return FREQ;
+ function "/"(x : real; f : FREQ) return time;
+ function "*"(t : time; f : FREQ) return real;
+ function "*"(f : FREQ; t : time) return real;
+
+ -- if-then-else
+ function ite(cond : boolean; value1 : time; value2 : time) return time;
+ function ite(cond : boolean; value1 : FREQ; value2 : FREQ) return FREQ;
+ function ite(cond : boolean; value1 : BAUD; value2 : BAUD) return BAUD;
+ function ite(cond : boolean; value1 : MEMORY; value2 : MEMORY) return MEMORY;
+
+ -- min/ max for 2 arguments
+ function tmin(arg1 : time; arg2 : time) return time; -- Calculates: min(arg1, arg2) for times
+ function fmin(arg1 : FREQ; arg2 : FREQ) return FREQ; -- Calculates: min(arg1, arg2) for frequencies
+ function bmin(arg1 : BAUD; arg2 : BAUD) return BAUD; -- Calculates: min(arg1, arg2) for symbols per second
+ function mmin(arg1 : MEMORY; arg2 : MEMORY) return MEMORY; -- Calculates: min(arg1, arg2) for memory
+
+ function tmax(arg1 : time; arg2 : time) return time; -- Calculates: max(arg1, arg2) for times
+ function fmax(arg1 : FREQ; arg2 : FREQ) return FREQ; -- Calculates: max(arg1, arg2) for frequencies
+ function bmax(arg1 : BAUD; arg2 : BAUD) return BAUD; -- Calculates: max(arg1, arg2) for symbols per second
+ function mmax(arg1 : MEMORY; arg2 : MEMORY) return MEMORY; -- Calculates: max(arg1, arg2) for memory
+
+ -- min/max/sum as vector aggregation
+ function tmin(vec : T_TIMEVEC) return time; -- Calculates: min(vec) for a time vector
+ function fmin(vec : T_FREQVEC) return FREQ; -- Calculates: min(vec) for a frequency vector
+ function bmin(vec : T_BAUDVEC) return BAUD; -- Calculates: min(vec) for a baud vector
+ function mmin(vec : T_MEMVEC) return MEMORY; -- Calculates: min(vec) for a memory vector
+
+ function tmax(vec : T_TIMEVEC) return time; -- Calculates: max(vec) for a time vector
+ function fmax(vec : T_FREQVEC) return FREQ; -- Calculates: max(vec) for a frequency vector
+ function bmax(vec : T_BAUDVEC) return BAUD; -- Calculates: max(vec) for a baud vector
+ function mmax(vec : T_MEMVEC) return MEMORY; -- Calculates: max(vec) for a memory vector
+
+ function tsum(vec : T_TIMEVEC) return time; -- Calculates: sum(vec) for a time vector
+ function fsum(vec : T_FREQVEC) return FREQ; -- Calculates: sum(vec) for a frequency vector
+ function bsum(vec : T_BAUDVEC) return BAUD; -- Calculates: sum(vec) for a baud vector
+ function msum(vec : T_MEMVEC) return MEMORY; -- Calculates: sum(vec) for a memory vector
+
+ -- convert standard types (NATURAL, REAL) to time (TIME)
+ function fs2Time(t_fs : integer) return time;
+ function ps2Time(t_ps : integer) return time;
+ function ns2Time(t_ns : integer) return time;
+ function us2Time(t_us : integer) return time;
+ function ms2Time(t_ms : integer) return time;
+ function sec2Time(t_sec : integer) return time;
+
+ function fs2Time(t_fs : REAL) return time;
+ function ps2Time(t_ps : REAL) return time;
+ function ns2Time(t_ns : REAL) return time;
+ function us2Time(t_us : REAL) return time;
+ function ms2Time(t_ms : REAL) return time;
+ function sec2Time(t_sec : REAL) return time;
+
+ -- convert standard types (NATURAL, REAL) to period (TIME)
+ function Hz2Time(f_Hz : natural) return time;
+ function kHz2Time(f_kHz : natural) return time;
+ function MHz2Time(f_MHz : natural) return time;
+ function GHz2Time(f_GHz : natural) return time;
+
+ function Hz2Time(f_Hz : REAL) return time;
+ function kHz2Time(f_kHz : REAL) return time;
+ function MHz2Time(f_MHz : REAL) return time;
+ function GHz2Time(f_GHz : REAL) return time;
+
+ -- convert standard types (NATURAL, REAL) to frequency (FREQ)
+ function Hz2Freq(f_Hz : natural) return FREQ;
+ function kHz2Freq(f_kHz : natural) return FREQ;
+ function MHz2Freq(f_MHz : natural) return FREQ;
+ function GHz2Freq(f_GHz : natural) return FREQ;
+
+ function Hz2Freq(f_Hz : REAL) return FREQ;
+ function kHz2Freq(f_kHz : REAL) return FREQ;
+ function MHz2Freq(f_MHz : REAL) return FREQ;
+ function GHz2Freq(f_GHz : REAL) return FREQ;
+
+ -- convert physical types to standard type (REAL)
+ function to_real(t : time; scale : time) return REAL;
+ function to_real(f : FREQ; scale : FREQ) return REAL;
+ function to_real(br : BAUD; scale : BAUD) return REAL;
+ function to_real(mem : MEMORY; scale : MEMORY) return REAL;
+
+ -- convert physical types to standard type (INTEGER)
+ function to_int(t : time; scale : time; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return integer;
+ function to_int(f : FREQ; scale : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return integer;
+ function to_int(br : BAUD; scale : BAUD; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return integer;
+ function to_int(mem : MEMORY; scale : MEMORY; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return integer;
+
+ -- calculate needed counter cycles to achieve a given 1. timing/delay and 2. frequency/period
+ function TimingToCycles(Timing : time; Clock_Period : time; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return natural;
+ function TimingToCycles(Timing : time; Clock_Frequency : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return natural;
+
+ function CyclesToDelay(Cycles : natural; Clock_Period : time) return time;
+ function CyclesToDelay(Cycles : natural; Clock_Frequency : FREQ) return time;
+
+ -- convert and format physical types to STRING
+ function to_string(t : time; precision : natural) return string;
+ function to_string(f : FREQ; precision : natural) return string;
+ function to_string(br : BAUD; precision : natural) return string;
+ function to_string(mem : MEMORY; precision : natural) return string;
+end package;
+
+
+package body physical is
+
+ -- WORKAROUND: for simulators with a "Minimal Time Resolution" > 1 fs
+ -- Version: all
+ -- Vendors: all
+ -- Issue:
+ -- Some simulators use a lower minimal time resolution (MTR) than the VHDL
+ -- standard (LRM) defines (1 fs). Usually, the MTR is set to 1 ps or 1 ns.
+ -- Most simulators allow the user to specify a higher MTR -> check the
+ -- simulator documentation.
+ -- Solution:
+ -- The currently set MTR can be calculated in VHDL. Using the correct MTR
+ -- can prevent cleared intermediate values and division by zero errors.
+ -- Examples:
+ -- Mentor Graphics QuestaSim/ModelSim (vSim): default MTR = ? ??
+ -- Xilinx ISE Simulator (iSim): default MTR = 1 ps
+ -- Xilinx Vivado Simulator (xSim): default MTR = 1 ps
+ function MinimalTimeResolutionInSimulation return time is
+ begin
+ if (1 fs > 0 sec) then return 1 fs;
+ elsif (1 ps > 0 sec) then return 1 ps;
+ elsif (1 ns > 0 sec) then return 1 ns;
+ elsif (1 us > 0 sec) then return 1 us;
+ elsif (1 ms > 0 sec) then return 1 ms;
+ else return 1 sec;
+ end if;
+ end function;
+
+ -- real division for physical types
+ -- ===========================================================================
+ function div(a : time; b : time) return REAL is
+ constant MTRIS : time := MinimalTimeResolutionInSimulation;
+ variable a_real : real;
+ variable b_real : real;
+ begin
+ -- WORKAROUND: for Altera Quartus
+ -- Version: all
+ -- Issue:
+ -- Results of TIME arithmetic must be in 32-bit integer range, because
+ -- the internally used 64-bit integer for type TIME can not be
+ -- represented in VHDL.
+ -- Solution:
+ -- Pre- and post-scale all values to stay in the integer range.
+ if a < 1 us then
+ a_real := real(a / MTRIS);
+ elsif a < 1 ms then
+ a_real := real(a / (1000 * MTRIS)) * 1000.0;
+ elsif a < 1 sec then
+ a_real := real(a / (1000000 * MTRIS)) * 1000000.0;
+ else
+ a_real := real(a / (1000000000 * MTRIS)) * 1000000000.0;
+ end if;
+
+ if b < 1 us then
+ b_real := real(b / MTRIS);
+ elsif b < 1 ms then
+ b_real := real(b / (1000 * MTRIS)) * 1000.0;
+ elsif b < 1 sec then
+ b_real := real(b / (1000000 * MTRIS)) * 1000000.0;
+ else
+ b_real := real(b / (1000000000 * MTRIS)) * 1000000000.0;
+ end if;
+
+ return a_real / b_real;
+ end function;
+
+ function div(a : FREQ; b : FREQ) return REAL is
+ begin
+ return real(a / 1 Hz) / real(b / 1 Hz);
+ end function;
+
+ function div(a : BAUD; b : BAUD) return REAL is
+ begin
+ return real(a / 1 Bd) / real(b / 1 Bd);
+ end function;
+
+ function div(a : MEMORY; b : MEMORY) return REAL is
+ begin
+ return real(a / 1 Byte) / real(b / 1 Byte);
+ end function;
+
+ -- conversion functions
+ -- ===========================================================================
+ function to_time(f : FREQ) return time is
+ variable res : time;
+ begin
+ res := div(1000 MHz, f) * 1 ns;
+ if POC_VERBOSE then
+ report "to_time: f= " & to_string(f, 3) & " return " & to_string(res, 3) severity note;
+ end if;
+ return res;
+ end function;
+
+ function to_freq(p : time) return FREQ is
+ variable res : FREQ;
+ begin
+ if (p <= 1 sec) then res := div(1 sec, p) * 1 Hz;
+ else report "to_freq: input period exceeds output frequency scale." severity failure;
+ end if;
+ if POC_VERBOSE then
+ report "to_freq: p= " & to_string(p, 3) & " return " & to_string(res, 3) severity note;
+ end if;
+ return res;
+ end function;
+
+ function to_freq(br : BAUD) return FREQ is
+ variable res : FREQ;
+ begin
+ res := (br / 1 Bd) * 1 Hz;
+ if POC_VERBOSE then
+ report "to_freq: br= " & to_string(br, 3) & " return " & to_string(res, 3) severity note;
+ end if;
+ return res;
+ end function;
+
+ function to_baud(str : string) return BAUD is
+ variable pos : integer;
+ variable int : natural;
+ variable base : positive;
+ variable frac : natural;
+ variable digits : natural;
+ begin
+ pos := str'low;
+ int := 0;
+ frac := 0;
+ digits := 0;
+ -- read integer part
+ for i in pos to str'high loop
+ if chr_isDigit(str(i)) then int := int * 10 + to_digit_dec(str(i));
+ elsif (str(i) = '.') then pos := -i; exit;
+ elsif (str(i) = ' ') then pos := i; exit;
+ else pos := 0; exit;
+ end if;
+ end loop;
+ -- read fractional part
+ if ((pos < 0) and (-pos < str'high)) then
+ for i in -pos+1 to str'high loop
+ if ((frac = 0) and (str(i) = '0')) then next;
+ elsif chr_isDigit(str(i)) then frac := frac * 10 + to_digit_dec(str(i));
+ elsif (str(i) = ' ') then digits := i + pos - 1; pos := i; exit;
+ else pos := 0; exit;
+ end if;
+ end loop;
+ end if;
+ -- abort if format is unknown
+ if pos = 0 then report "to_baud: Unknown format" severity FAILURE; end if;
+ -- parse unit
+ pos := pos + 1;
+ if ((pos + 1 = str'high) and (str(pos to pos + 1) = "Bd")) then
+ return int * 1 Bd;
+ elsif (pos + 2 = str'high) then
+ if (str(pos to pos + 2) = "kBd") then
+ if frac = 0 then return (int * 1 kBd);
+ elsif (digits <= 3) then return (int * 1 kBd) + (frac * 10**(3 - digits) * 1 Bd);
+ else return (int * 1 kBd) + (frac / 10**(digits - 3) * 100 Bd);
+ end if;
+ elsif (str(pos to pos + 2) = "MBd") then
+ if frac = 0 then return (int * 1 kBd);
+ elsif (digits <= 3) then return (int * 1 MBd) + (frac * 10**(3 - digits) * 1 kBd);
+ elsif (digits <= 6) then return (int * 1 MBd) + (frac * 10**(6 - digits) * 1 Bd);
+ else return (int * 1 MBd) + (frac / 10**(digits - 6) * 100000 Bd);
+ end if;
+ elsif (str(pos to pos + 2) = "GBd") then
+ if frac = 0 then return (int * 1 kBd);
+ elsif (digits <= 3) then return (int * 1 GBd) + (frac * 10**(3 - digits) * 1 MBd);
+ elsif (digits <= 6) then return (int * 1 GBd) + (frac * 10**(6 - digits) * 1 kBd);
+ elsif (digits <= 9) then return (int * 1 GBd) + (frac * 10**(9 - digits) * 1 Bd);
+ else return (int * 1 GBd) + (frac / 10**(digits - 9) * 100000000 Bd);
+ end if;
+ else
+ report "to_baud: Unknown unit." severity FAILURE;
+ end if;
+ else
+ report "to_baud: Unknown format" severity FAILURE;
+ end if;
+ return 0 Bd;
+ end function;
+
+ -- inter-type arithmetic
+ -- ===========================================================================
+ function "/"(x : real; t : time) return FREQ is
+ begin
+ return x*div(1 ms, t) * 1 kHz;
+ end function;
+ function "/"(x : real; f : FREQ) return time is
+ begin
+ return x*div(1 kHz, f) * 1 ms;
+ end function;
+ function "*"(t : time; f : FREQ) return real is
+ begin
+ return div(t, 1.0/f);
+ end function;
+ function "*"(f : FREQ; t : time) return real is
+ begin
+ return div(f, 1.0/t);
+ end function;
+
+ -- if-then-else
+ -- ===========================================================================
+ function ite(cond : boolean; value1 : time; value2 : time) return time is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : boolean; value1 : FREQ; value2 : FREQ) return FREQ is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : boolean; value1 : BAUD; value2 : BAUD) return BAUD is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : boolean; value1 : MEMORY; value2 : MEMORY) return MEMORY is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ -- min/ max for 2 arguments
+ -- ===========================================================================
+ -- Calculates: min(arg1, arg2) for times
+ function tmin(arg1 : time; arg2 : time) return time is
+ begin
+ if arg1 < arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: min(arg1, arg2) for frequencies
+ function fmin(arg1 : FREQ; arg2 : FREQ) return FREQ is
+ begin
+ if arg1 < arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: min(arg1, arg2) for symbols per second
+ function bmin(arg1 : BAUD; arg2 : BAUD) return BAUD is
+ begin
+ if arg1 < arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: min(arg1, arg2) for memory
+ function mmin(arg1 : MEMORY; arg2 : MEMORY) return MEMORY is
+ begin
+ if arg1 < arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for times
+ function tmax(arg1 : time; arg2 : time) return time is
+ begin
+ if arg1 > arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for frequencies
+ function fmax(arg1 : FREQ; arg2 : FREQ) return FREQ is
+ begin
+ if arg1 > arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for symbols per second
+ function bmax(arg1 : BAUD; arg2 : BAUD) return BAUD is
+ begin
+ if arg1 > arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for memory
+ function mmax(arg1 : MEMORY; arg2 : MEMORY) return MEMORY is
+ begin
+ if arg1 > arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- min/max/sum as vector aggregation
+ -- ===========================================================================
+ -- Calculates: min(vec) for a time vector
+ function tmin(vec : T_TIMEVEC) return time is
+ variable res : time := time'high;
+ begin
+ for i in vec'range loop
+ if vec(i) < res then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: min(vec) for a frequency vector
+ function fmin(vec : T_FREQVEC) return FREQ is
+ variable res : FREQ := FREQ'high;
+ begin
+ for i in vec'range loop
+ if (integer(FREQ'pos(vec(i))) < integer(FREQ'pos(res))) then -- Quartus workaround
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: min(vec) for a baud vector
+ function bmin(vec : T_BAUDVEC) return BAUD is
+ variable res : BAUD := BAUD'high;
+ begin
+ for i in vec'range loop
+ if (integer(BAUD'pos(vec(i))) < integer(BAUD'pos(res))) then -- Quartus workaround
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: min(vec) for a memory vector
+ function mmin(vec : T_MEMVEC) return MEMORY is
+ variable res : MEMORY := MEMORY'high;
+ begin
+ for i in vec'range loop
+ if (integer(MEMORY'pos(vec(i))) < integer(MEMORY'pos(res))) then -- Quartus workaround
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a time vector
+ function tmax(vec : T_TIMEVEC) return time is
+ variable res : time := time'low;
+ begin
+ for i in vec'range loop
+ if vec(i) > res then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a frequency vector
+ function fmax(vec : T_FREQVEC) return FREQ is
+ variable res : FREQ := FREQ'low;
+ begin
+ for i in vec'range loop
+ if (integer(FREQ'pos(vec(i))) > integer(FREQ'pos(res))) then -- Quartus workaround
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a baud vector
+ function bmax(vec : T_BAUDVEC) return BAUD is
+ variable res : BAUD := BAUD'low;
+ begin
+ for i in vec'range loop
+ if (integer(BAUD'pos(vec(i))) > integer(BAUD'pos(res))) then -- Quartus workaround
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a memory vector
+ function mmax(vec : T_MEMVEC) return MEMORY is
+ variable res : MEMORY := MEMORY'low;
+ begin
+ for i in vec'range loop
+ if (integer(MEMORY'pos(vec(i))) > integer(MEMORY'pos(res))) then -- Quartus workaround
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a time vector
+ function tsum(vec : T_TIMEVEC) return time is
+ variable res : time := 0 fs;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a frequency vector
+ function fsum(vec : T_FREQVEC) return FREQ is
+ variable res : FREQ := 0 Hz;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a baud vector
+ function bsum(vec : T_BAUDVEC) return BAUD is
+ variable res : BAUD := 0 Bd;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a memory vector
+ function msum(vec : T_MEMVEC) return MEMORY is
+ variable res : MEMORY := 0 Byte;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- convert standard types (NATURAL, REAL) to time (TIME)
+ -- ===========================================================================
+ function fs2Time(t_fs : integer) return time is
+ begin
+ return t_fs * 1 fs;
+ end function;
+
+ function ps2Time(t_ps : integer) return time is
+ begin
+ return t_ps * 1 ps;
+ end function;
+
+ function ns2Time(t_ns : integer) return time is
+ begin
+ return t_ns * 1 ns;
+ end function;
+
+ function us2Time(t_us : integer) return time is
+ begin
+ return t_us * 1 us;
+ end function;
+
+ function ms2Time(t_ms : integer) return time is
+ begin
+ return t_ms * 1 ms;
+ end function;
+
+ function sec2Time(t_sec : integer) return time is
+ begin
+ return t_sec * 1 sec;
+ end function;
+
+ function fs2Time(t_fs : REAL) return time is
+ begin
+ return t_fs * 1 fs;
+ end function;
+
+ function ps2Time(t_ps : REAL) return time is
+ begin
+ return t_ps * 1 ps;
+ end function;
+
+ function ns2Time(t_ns : REAL) return time is
+ begin
+ return t_ns * 1 ns;
+ end function;
+
+ function us2Time(t_us : REAL) return time is
+ begin
+ return t_us * 1 us;
+ end function;
+
+ function ms2Time(t_ms : REAL) return time is
+ begin
+ return t_ms * 1 ms;
+ end function;
+
+ function sec2Time(t_sec : REAL) return time is
+ begin
+ return t_sec * 1 sec;
+ end function;
+
+ -- convert standard types (NATURAL, REAL) to period (TIME)
+ -- ===========================================================================
+ function Hz2Time(f_Hz : natural) return time is
+ begin
+ return 1 sec / f_Hz;
+ end function;
+
+ function kHz2Time(f_kHz : natural) return time is
+ begin
+ return 1 ms / f_kHz;
+ end function;
+
+ function MHz2Time(f_MHz : natural) return time
+ is
+ begin
+ return 1 us / f_MHz;
+ end function;
+
+ function GHz2Time(f_GHz : natural) return time is
+ begin
+ return 1 ns / f_GHz;
+ end function;
+
+ function Hz2Time(f_Hz : REAL) return time is
+ begin
+ return 1 sec / f_Hz;
+ end function;
+
+ function kHz2Time(f_kHz : REAL) return time is
+ begin
+ return 1 ms / f_kHz;
+ end function;
+
+ function MHz2Time(f_MHz : REAL) return time is
+ begin
+ return 1 us / f_MHz;
+ end function;
+
+ function GHz2Time(f_GHz : REAL) return time is
+ begin
+ return 1 ns / f_GHz;
+ end function;
+
+ -- convert standard types (NATURAL, REAL) to frequency (FREQ)
+ -- ===========================================================================
+ function Hz2Freq(f_Hz : natural) return FREQ is
+ begin
+ return f_Hz * 1 Hz;
+ end function;
+
+ function kHz2Freq(f_kHz : natural) return FREQ is
+ begin
+ return f_kHz * 1 kHz;
+ end function;
+
+ function MHz2Freq(f_MHz : natural) return FREQ is
+ begin
+ return f_MHz * 1 MHz;
+ end function;
+
+ function GHz2Freq(f_GHz : natural) return FREQ is
+ begin
+ return f_GHz * 1 GHz;
+ end function;
+
+ function Hz2Freq(f_Hz : REAL) return FREQ is
+ begin
+ return f_Hz * 1 Hz;
+ end function;
+
+ function kHz2Freq(f_kHz : REAL )return FREQ is
+ begin
+ return f_kHz * 1 kHz;
+ end function;
+
+ function MHz2Freq(f_MHz : REAL )return FREQ is
+ begin
+ return f_MHz * 1 MHz;
+ end function;
+
+ function GHz2Freq(f_GHz : REAL )return FREQ is
+ begin
+ return f_GHz * 1 GHz;
+ end function;
+
+ -- convert physical types to standard type (REAL)
+ -- ===========================================================================
+ function to_real(t : time; scale : time) return REAL is
+ begin
+ if (scale = 1 fs) then return div(t, 1 fs);
+ elsif (scale = 1 ps) then return div(t, 1 ps);
+ elsif (scale = 1 ns) then return div(t, 1 ns);
+ elsif (scale = 1 us) then return div(t, 1 us);
+ elsif (scale = 1 ms) then return div(t, 1 ms);
+ elsif (scale = 1 sec) then return div(t, 1 sec);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ return 0.0;
+ end if;
+ end;
+
+ function to_real(f : FREQ; scale : FREQ) return REAL is
+ begin
+ if (scale = 1 Hz) then return div(f, 1 Hz);
+ elsif (scale = 1 kHz) then return div(f, 1 kHz);
+ elsif (scale = 1 MHz) then return div(f, 1 MHz);
+ elsif (scale = 1 GHz) then return div(f, 1 GHz);
+-- elsif (scale = 1 THz) then return div(f, 1 THz);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ end if;
+ return 0.0;
+ end;
+
+ function to_real(br : BAUD; scale : BAUD) return REAL is
+ begin
+ if (scale = 1 Bd) then return div(br, 1 Bd);
+ elsif (scale = 1 kBd) then return div(br, 1 kBd);
+ elsif (scale = 1 MBd) then return div(br, 1 MBd);
+ elsif (scale = 1 GBd) then return div(br, 1 GBd);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ end if;
+ return 0.0;
+ end;
+
+ function to_real(mem : MEMORY; scale : MEMORY) return REAL is
+ begin
+ if (scale = 1 Byte) then return div(mem, 1 Byte);
+ elsif (scale = 1 KiB) then return div(mem, 1 KiB);
+ elsif (scale = 1 MiB) then return div(mem, 1 MiB);
+ elsif (scale = 1 GiB) then return div(mem, 1 GiB);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ end if;
+ return 0.0;
+ end;
+
+ -- convert physical types to standard type (INTEGER)
+ -- ===========================================================================
+ function to_int(t : time; scale : time; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return integer is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(t, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(t, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(t, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ return 0;
+ end;
+
+ function to_int(f : FREQ; scale : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return integer is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(f, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(f, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(f, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ return 0;
+ end;
+
+ function to_int(br : BAUD; scale : BAUD; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return integer is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(br, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(br, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(br, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ return 0;
+ end;
+
+ function to_int(mem : MEMORY; scale : MEMORY; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return integer is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(mem, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(mem, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(mem, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ return 0;
+ end;
+
+ -- calculate needed counter cycles to achieve a given 1. timing/delay and 2. frequency/period
+ -- ===========================================================================
+ -- @param Timing A given timing or delay, which should be achieved
+ -- @param Clock_Period The period of the circuits clock
+ -- @RoundingStyle Default = ROUND_UP; other choises: ROUND_UP, ROUND_DOWN, ROUND_TO_NEAREST
+ function TimingToCycles(Timing : time; Clock_Period : time; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return natural is
+ variable res_real : REAL;
+ variable res_nat : natural;
+ variable res_time : time;
+ variable res_dev : REAL;
+ begin
+ res_real := div(Timing, Clock_Period);
+ case RoundingStyle is
+ when ROUND_TO_NEAREST => res_nat := natural(round(res_real));
+ when ROUND_UP => res_nat := natural(ceil(res_real));
+ when ROUND_DOWN => res_nat := natural(floor(res_real));
+ when others => report "RoundingStyle '" & T_ROUNDING_STYLE'image(RoundingStyle) & "' not supported." severity failure;
+ end case;
+ res_time := CyclesToDelay(res_nat, Clock_Period);
+ res_dev := (div(res_time, Timing) - 1.0) * 100.0;
+
+ if POC_VERBOSE then
+ report "TimingToCycles: " & LF &
+ " Timing: " & to_string(Timing, 3) & LF &
+ " Clock_Period: " & to_string(Clock_Period, 3) & LF &
+ " RoundingStyle: " & str_substr(T_ROUNDING_STYLE'image(RoundingStyle), 7) & LF &
+ " res_real = " & str_format(res_real, 3) & LF &
+ " => " & integer'image(res_nat)
+ severity note;
+ end if;
+
+ if C_PHYSICAL_REPORT_TIMING_DEVIATION then
+ report "TimingToCycles (timing deviation report): " & LF &
+ " timing to achieve: " & to_string(Timing, 3) & LF &
+ " calculated cycles: " & integer'image(res_nat) & " cy" & LF &
+ " resulting timing: " & to_string(res_time, 3) & LF &
+ " deviation: " & to_string(res_time - Timing, 3) & " (" & str_format(res_dev, 2) & "%)"
+ severity note;
+ end if;
+
+ return res_nat;
+ end;
+
+ function TimingToCycles(Timing : time; Clock_Frequency : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return natural is
+ begin
+ return TimingToCycles(Timing, to_time(Clock_Frequency), RoundingStyle);
+ end function;
+
+ function CyclesToDelay(Cycles : natural; Clock_Period : time) return time is
+ begin
+ return Clock_Period * Cycles;
+ end function;
+
+ function CyclesToDelay(Cycles : natural; Clock_Frequency : FREQ) return time is
+ begin
+ return CyclesToDelay(Cycles, to_time(Clock_Frequency));
+ end function;
+
+ -- convert and format physical types to STRING
+ function to_string(t : time; precision : natural) return string is
+ variable tt : time;
+ variable unit : string(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ tt := abs t;
+ if (tt < 1 ps) then
+ unit(1 to 2) := "fs";
+ value := to_real(tt, 1 fs);
+ elsif (tt < 1 ns) then
+ unit(1 to 2) := "ps";
+ value := to_real(tt, 1 ps);
+ elsif (tt < 1 us) then
+ unit(1 to 2) := "ns";
+ value := to_real(tt, 1 ns);
+ elsif (tt < 1 ms) then
+ unit(1 to 2) := "us";
+ value := to_real(tt, 1 us);
+ elsif (tt < 1 sec) then
+ unit(1 to 2) := "ms";
+ value := to_real(tt, 1 ms);
+ else
+ unit := "sec";
+ value := to_real(tt, 1 sec);
+ end if;
+
+ return ite(t >= 0 fs, str_format(value, precision) & " " & str_trim(unit),
+ '-' & str_format(value, precision) & " " & str_trim(unit));
+ end function;
+
+ function to_string(f : FREQ; precision : natural) return string is
+ variable unit : string(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ if (f < 1 kHz) then
+ unit(1 to 2) := "Hz";
+ value := to_real(f, 1 Hz);
+ elsif (f < 1 MHz) then
+ unit := "kHz";
+ value := to_real(f, 1 kHz);
+ elsif (f < 1 GHz) then
+ unit := "MHz";
+ value := to_real(f, 1 MHz);
+ else
+ unit := "GHz";
+ value := to_real(f, 1 GHz);
+ end if;
+
+ return str_format(value, precision) & " " & str_trim(unit);
+ end function;
+
+ function to_string(br : BAUD; precision : natural) return string is
+ variable unit : string(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ if (br < 1 kBd) then
+ unit(1 to 2) := "Bd";
+ value := to_real(br, 1 Bd);
+ elsif (br < 1 MBd) then
+ unit := "kBd";
+ value := to_real(br, 1 kBd);
+ elsif (br < 1 GBd) then
+ unit := "MBd";
+ value := to_real(br, 1 MBd);
+ else
+ unit := "GBd";
+ value := to_real(br, 1 GBd);
+ end if;
+
+ return str_format(value, precision) & " " & str_trim(unit);
+ end function;
+
+ function to_string(mem : MEMORY; precision : natural) return string is
+ variable unit : string(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ if (mem < 1 KiB) then
+ unit(1) := 'B';
+ value := to_real(mem, 1 Byte);
+ elsif (mem < 1 MiB) then
+ unit := "KiB";
+ value := to_real(mem, 1 KiB);
+ elsif (mem < 1 GiB) then
+ unit := "MiB";
+ value := to_real(mem, 1 MiB);
+ else
+ unit := "GiB";
+ value := to_real(mem, 1 GiB);
+ end if;
+
+ return str_format(value, precision) & " " & str_trim(unit);
+ end function;
+
+end package body;