-- 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
-- Thomas B. Preusser
--
-- Package: Simulation constants, functions and utilities.
--
-- Description:
--
-- .. TODO:: No documentation available.
--
-- License:
-- =============================================================================
-- Copyright 2007-2016 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.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.math_real.all;
library PoC;
use PoC.utils.all;
-- use PoC.strings.all;
use PoC.vectors.all;
-- use PoC.physical.all;
package [docs]sim_types is
constant C_SIM_VERBOSE : boolean := FALSE; -- POC_VERBOSE
-- ===========================================================================
-- Simulation Task and Status Management
-- ===========================================================================
type T_SIM_BOOLVEC is array(integer range <>) of boolean;
subtype T_SIM_TEST_ID is integer range -1 to 1023;
subtype T_SIM_TEST_NAME is string(1 to 256);
subtype T_SIM_PROCESS_ID is natural range 0 to 1023;
subtype T_SIM_PROCESS_NAME is string(1 to 64);
subtype T_SIM_PROCESS_INSTNAME is string(1 to 256);
type T_SIM_PROCESS_ID_VECTOR is array(natural range <>) of T_SIM_PROCESS_ID;
type T_SIM_TEST_STATUS is (
SIM_TEST_STATUS_CREATED,
SIM_TEST_STATUS_ACTIVE,
SIM_TEST_STATUS_ENDED,
SIM_TEST_STATUS_ZOMBI
);
type T_SIM_PROCESS_STATUS is (
SIM_PROCESS_STATUS_ACTIVE,
SIM_PROCESS_STATUS_ENDED
);
type T_SIM_TEST is record
ID : T_SIM_TEST_ID;
Name : T_SIM_TEST_NAME;
Status : T_SIM_TEST_STATUS;
ProcessIDs : T_SIM_PROCESS_ID_VECTOR(T_SIM_PROCESS_ID);
ProcessCount : T_SIM_PROCESS_ID;
ActiveProcessCount : T_SIM_PROCESS_ID;
end record;
type T_SIM_TEST_VECTOR is array(integer range <>) of T_SIM_TEST;
type T_SIM_PROCESS is record
ID : T_SIM_PROCESS_ID;
TestID : T_SIM_TEST_ID;
Name : T_SIM_PROCESS_NAME;
Status : T_SIM_PROCESS_STATUS;
IsLowPriority : boolean;
end record;
type T_SIM_PROCESS_VECTOR is array(natural range <>) of T_SIM_PROCESS;
constant C_SIM_DEFAULT_TEST_ID : T_SIM_TEST_ID := -1;
constant C_SIM_DEFAULT_TEST_NAME : string := "Default test";
-- ===========================================================================
-- Random Numbers
-- ===========================================================================
type T_SIM_RAND_SEED is record
Seed1 : integer;
Seed2 : integer;
end record;
procedure [docs]randInitializeSeed(Seed : inout T_SIM_RAND_SEED);
procedure [docs]randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedValue : in T_SIM_RAND_SEED);
procedure [docs]randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedVector : in T_INTVEC);
procedure [docs]randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedVector : in string);
function [docs]randInitializeSeed return T_SIM_RAND_SEED;
function [docs]randInitializeSeed(SeedValue : T_SIM_RAND_SEED) return T_SIM_RAND_SEED;
function [docs]randInitializeSeed(SeedVector : T_INTVEC) return T_SIM_RAND_SEED;
function [docs]randInitializeSeed(SeedVector : string) return T_SIM_RAND_SEED;
-- Uniform distributed random values
-- ===========================================================================
procedure [docs]randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL);
procedure [docs]randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; Minimum : integer; Maximum : integer);
procedure [docs]randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Minimum : REAL; Maximum : REAL);
-- Normal / Gaussian distributed random values
-- ===========================================================================
procedure [docs]randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; StandardDeviation : REAL := 1.0; Mean : REAL := 0.0);
procedure [docs]randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; StandardDeviation : in REAL; Mean : in REAL; Minimum : in integer; Maximum : in integer);
procedure [docs]randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; StandardDeviation : in REAL; Mean : in REAL; Minimum : in REAL; Maximum : in REAL);
-- Poisson distributed random values
-- ===========================================================================
procedure [docs]randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Mean : in REAL);
procedure [docs]randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; Mean : in REAL; Minimum : in integer; Maximum : in integer);
procedure [docs]randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Mean : in REAL; Minimum : in REAL; Maximum : in REAL);
-- ===========================================================================
-- Clock Generation
-- ===========================================================================
-- type T_PERCENT is INTEGER'range units
type T_PERCENT is range integer'low to INTEGER'high units
ppb;
ppm = 1000 ppb;
permil = 1000 ppm;
percent = 10 permil;
one = 100 percent;
end units;
subtype T_WANDER is T_PERCENT range -1 one to 1 one;
subtype T_DUTYCYCLE is T_PERCENT range 0 ppb to 1 one;
type T_DEGREE is range integer'low to INTEGER'high units
second;
minute = 60 second;
deg = 60 minute;
end units;
subtype T_PHASE is T_DEGREE range -360 deg to 360 deg;
function [docs]ite(cond : boolean; value1 : T_DEGREE; value2 : T_DEGREE) return T_DEGREE;
end package;
package body sim_types is
function ite(cond : boolean; value1 : T_DEGREE; value2 : T_DEGREE) return T_DEGREE is
begin
if cond then
return value1;
else
return value2;
end if;
end function;
-- ===========================================================================
-- Random Numbers
-- ===========================================================================
constant MAX_SEED1_VALUE : positive := 2147483562;
constant MAX_SEED2_VALUE : positive := 2147483398;
function randGenerateInitialSeed return T_SIM_RAND_SEED is
begin
return (
Seed1 => 5,
Seed2 => 3423
);
end function;
function randBoundSeed(SeedValue : in T_SIM_RAND_SEED) return T_SIM_RAND_SEED is
begin
return (
Seed1 => (SeedValue.Seed1 - 1 mod MAX_SEED1_VALUE) + 1,
Seed2 => (SeedValue.Seed2 - 1 mod MAX_SEED2_VALUE) + 1
);
end function;
procedure randInitializeSeed(Seed : inout T_SIM_RAND_SEED) is
begin
Seed := randGenerateInitialSeed;
end procedure;
procedure randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedValue : in T_SIM_RAND_SEED) is
begin
Seed := randBoundSeed(SeedValue);
end procedure;
procedure randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedVector : in T_INTVEC) is
begin
if (SeedVector'length = 0) then
Seed := randGenerateInitialSeed;
elsif (SeedVector'length = 1) then
Seed := randBoundSeed(T_SIM_RAND_SEED'(
Seed1 => SeedVector(0),
Seed2 => 92346
));
elsif (SeedVector'length = 2) then
Seed := randBoundSeed(T_SIM_RAND_SEED'(
Seed1 => SeedVector(0),
Seed2 => SeedVector(1)
));
else
-- FIXME:
-- Seed.Seed1 := SeedVector(0);
-- Seed.Seed2 := SeedVector(1);
end if;
end procedure;
procedure randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedVector : in string) is
begin
if (SeedVector'length = 0) then
Seed := randGenerateInitialSeed;
elsif (SeedVector'length = 1) then
Seed := T_SIM_RAND_SEED'(
Seed1 => character'pos(SeedVector(1)),
Seed2 => 39834
);
elsif (SeedVector'length = 2) then
Seed := T_SIM_RAND_SEED'(
Seed1 => character'pos(SeedVector(1)),
Seed2 => character'pos(SeedVector(2))
);
else
-- FIXME:
-- Seed.Seed1 := CHARACTER'pos(SeedVector(0));
-- Seed.Seed2 := CHARACTER'pos(SeedVector(1));
end if;
end procedure;
function randInitializeSeed return T_SIM_RAND_SEED is
begin
return randGenerateInitialSeed;
end function;
function randInitializeSeed(SeedValue : T_SIM_RAND_SEED) return T_SIM_RAND_SEED is
begin
return randBoundSeed(SeedValue);
end function;
function randInitializeSeed(SeedVector : T_INTVEC) return T_SIM_RAND_SEED is
variable Result : T_SIM_RAND_SEED;
begin
randInitializeSeed(Result, SeedVector);
return Result;
end function;
function randInitializeSeed(SeedVector : string) return T_SIM_RAND_SEED is
variable Result : T_SIM_RAND_SEED;
begin
randInitializeSeed(Result, SeedVector);
return Result;
end function;
-- ===========================================================================
-- Uniform distributed random values
-- ===========================================================================
procedure randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL) is
begin
ieee.math_real.Uniform(Seed.Seed1, Seed.Seed2, Value);
end procedure;
procedure randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; Minimum : integer; Maximum : integer) is
variable rand : REAL;
begin
if Maximum < Minimum then report "randUniformDistributedValue: Maximum must be greater than Minimum." severity FAILURE; end if;
ieee.math_real.Uniform(Seed.Seed1, Seed.Seed2, rand);
Value := scale(rand, Minimum, Maximum);
end procedure;
procedure randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Minimum : REAL; Maximum : REAL) is
variable rand : REAL;
begin
if Maximum < Minimum then report "randUniformDistributedValue: Maximum must be greater than Minimum." severity FAILURE; end if;
ieee.math_real.Uniform(Seed.Seed1, Seed.Seed2, rand);
Value := scale(rand, Minimum, Maximum);
end procedure;
-- ===========================================================================
-- Normal / Gaussian distributed random values
-- ===========================================================================
procedure randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; StandardDeviation : REAL := 1.0; Mean : REAL := 0.0) is
variable rand1 : REAL;
variable rand2 : REAL;
begin
if StandardDeviation < 0.0 then report "randNormalDistributedValue: Standard deviation must be >= 0.0" severity FAILURE; end if;
-- Box Muller transformation
ieee.math_real.Uniform(Seed.Seed1, Seed.Seed2, rand1);
ieee.math_real.Uniform(Seed.Seed1, Seed.Seed2, rand2);
-- standard normal distribution: mean 0, variance 1
Value := StandardDeviation * (sqrt(-2.0 * log(rand1)) * cos(MATH_2_PI * rand2)) + Mean;
end procedure;
procedure randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; StandardDeviation : in REAL; Mean : in REAL; Minimum : in integer; Maximum : in integer) is
variable rand_real : REAL;
variable rand_int : integer;
begin
if Maximum < Minimum then report "randNormalDistributedValue: Maximum must be greater than Minimum." severity FAILURE; end if;
if StandardDeviation < 0.0 then report "randNormalDistributedValue: Standard deviation must be >= 0.0" severity FAILURE; end if;
while TRUE loop
randNormalDistributedValue(Seed, rand_real, StandardDeviation, Mean);
rand_int := integer(round(rand_real));
exit when ((Minimum <= rand_int) and (rand_int <= Maximum));
end loop;
Value := rand_int;
end procedure;
procedure randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; StandardDeviation : in REAL; Mean : in REAL; Minimum : in REAL; Maximum : in REAL) is
variable rand : REAL;
begin
if Maximum < Minimum then report "randNormalDistributedValue: Maximum must be greater than Minimum." severity FAILURE; end if;
if StandardDeviation < 0.0 then report "randNormalDistributedValue: Standard deviation must be >= 0.0" severity FAILURE; end if;
while TRUE loop
randNormalDistributedValue(Seed, rand, StandardDeviation, Mean);
exit when ((Minimum <= rand) and (rand <= Maximum));
end loop;
Value := rand;
end procedure;
-- ===========================================================================
-- Poisson distributed random values
-- ===========================================================================
procedure randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Mean : in REAL) is
variable Product : Real;
variable Bound : Real;
variable rand : Real;
variable Result : Real;
begin
Product := 1.0;
Result := 0.0;
Bound := exp(-1.0 * Mean);
if ((Mean <= 0.0) or (Bound <= 0.0)) then
report "randPoissonDistributedValue: Mean must be greater than 0.0." severity FAILURE;
return;
end if;
while (Product >= Bound) loop
ieee.math_real.Uniform(Seed.Seed1, Seed.Seed2, rand);
Product := Product * rand;
Result := Result + 1.0;
end loop;
Value := Result;
end procedure;
procedure randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; Mean : in REAL; Minimum : in integer; Maximum : in integer) is
variable rand_real : REAL;
variable rand_int : integer;
begin
if Maximum < Minimum then report "randPoissonDistributedValue: Maximum must be greater than Minimum." severity FAILURE; end if;
while TRUE loop
randPoissonDistributedValue(Seed, rand_real, Mean);
rand_int := integer(round(rand_real));
exit when ((Minimum <= rand_int) and (rand_int <= Maximum));
end loop;
Value := rand_int;
end procedure;
procedure randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Mean : in REAL; Minimum : in REAL; Maximum : in REAL) is
variable rand : REAL;
begin
if Maximum < Minimum then report "randPoissonDistributedValue: Maximum must be greater than Minimum." severity FAILURE; end if;
while TRUE loop
randPoissonDistributedValue(Seed, rand, Mean);
exit when ((Minimum <= rand) and (rand <= Maximum));
end loop;
Value := rand;
end procedure;
end package body;