aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue317/PoC/src/sim
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2017-05-18 08:01:02 +0200
committerTristan Gingold <tgingold@free.fr>2017-05-18 08:01:02 +0200
commitcff9d9a80bc14e81684fd5e02a361c171737022d (patch)
treecc40a1f680ae5a8ecd1db3e6f27c6a0cbfb30741 /testsuite/gna/issue317/PoC/src/sim
parent2e3634206b04775398f712a4da735d70a32020f2 (diff)
downloadghdl-cff9d9a80bc14e81684fd5e02a361c171737022d.tar.gz
ghdl-cff9d9a80bc14e81684fd5e02a361c171737022d.tar.bz2
ghdl-cff9d9a80bc14e81684fd5e02a361c171737022d.zip
Add testcase for #317
Diffstat (limited to 'testsuite/gna/issue317/PoC/src/sim')
-rw-r--r--testsuite/gna/issue317/PoC/src/sim/sim_global.v08.vhdl42
-rw-r--r--testsuite/gna/issue317/PoC/src/sim/sim_protected.v08.vhdl489
-rw-r--r--testsuite/gna/issue317/PoC/src/sim/sim_simulation.v08.vhdl173
-rw-r--r--testsuite/gna/issue317/PoC/src/sim/sim_types.vhdl376
-rw-r--r--testsuite/gna/issue317/PoC/src/sim/sim_waveform.vhdl981
5 files changed, 2061 insertions, 0 deletions
diff --git a/testsuite/gna/issue317/PoC/src/sim/sim_global.v08.vhdl b/testsuite/gna/issue317/PoC/src/sim/sim_global.v08.vhdl
new file mode 100644
index 000000000..02ebe003e
--- /dev/null
+++ b/testsuite/gna/issue317/PoC/src/sim/sim_global.v08.vhdl
@@ -0,0 +1,42 @@
+-- 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
+--
+-- Package: Global simulation constants and shared varibales.
+--
+-- 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 PoC;
+use PoC.FileIO.all;
+use PoC.sim_protected.all;
+
+
+package sim_global is
+ -- The default global status objects.
+ -- ===========================================================================
+ shared variable globalSimulationStatus : T_SIM_STATUS;
+ shared variable globalLogFile : T_LOGFILE;
+ shared variable globalStdOut : T_STDOUT;
+end package;
diff --git a/testsuite/gna/issue317/PoC/src/sim/sim_protected.v08.vhdl b/testsuite/gna/issue317/PoC/src/sim/sim_protected.v08.vhdl
new file mode 100644
index 000000000..64b9568bb
--- /dev/null
+++ b/testsuite/gna/issue317/PoC/src/sim/sim_protected.v08.vhdl
@@ -0,0 +1,489 @@
+-- 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.
+-- =============================================================================
+
+use STD.TextIO.all;
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+
+library PoC;
+use PoC.utils.all;
+use PoC.strings.all;
+use PoC.vectors.all;
+use PoC.physical.all;
+
+use PoC.sim_types.all;
+
+
+package sim_protected is
+ -- Simulation Task and Status Management
+ -- ===========================================================================
+ type T_SIM_STATUS is protected
+ -- Initializer and Finalizer
+ procedure initialize(MaxAssertFailures : natural := natural'high; MaxSimulationRuntime : TIME := TIME'high);
+ procedure finalize;
+
+ -- Assertions
+ procedure fail(Message : string := "");
+ procedure assertion(Condition : boolean; Message : string := "");
+ procedure writeMessage(Message : string);
+ procedure writeReport;
+
+ -- Process Management
+ impure function registerProcess(Name : string; IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID;
+ impure function registerProcess(TestID : T_SIM_TEST_ID; Name : string; IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID;
+ procedure deactivateProcess(procID : T_SIM_PROCESS_ID; SkipLowPriority : boolean := FALSE);
+ procedure stopAllProcesses;
+ procedure stopProcesses(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID);
+
+ -- Test Management
+ procedure createDefaultTest;
+ impure function createTest(Name : string) return T_SIM_TEST_ID;
+ procedure activateDefaultTest;
+ procedure finalizeTest;
+ procedure finalizeTest(TestID : T_SIM_TEST_ID);
+
+ -- Run Management
+ procedure stopAllClocks;
+ procedure stopClocks(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID);
+
+ impure function isStopped(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean;
+ impure function isFinalized(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean;
+ impure function isAllFinalized return boolean;
+ end protected;
+end package;
+
+
+package body sim_protected is
+ -- Simulation process and Status Management
+ -- ===========================================================================
+ type T_SIM_STATUS_STATE is record
+ IsInitialized : boolean;
+ IsFinalized : boolean;
+ end record;
+
+ type T_SIM_STATUS is protected body
+ -- status
+ variable State : T_SIM_STATUS_STATE := (FALSE, FALSE);
+
+ variable Max_AssertFailures : natural := natural'high;
+ variable Max_SimulationRuntime : time := time'high;
+
+ -- Internal state variable to log a failure condition for final reporting.
+ -- Once de-asserted, this variable will never return to a value of true.
+ variable Passed : boolean := TRUE;
+ variable AssertCount : natural := 0;
+ variable FailedAssertCount : natural := 0;
+
+ -- Clock Management
+ variable MainProcessEnables : T_SIM_BOOLVEC(T_SIM_TEST_ID) := (others => TRUE);
+ variable MainClockEnables : T_SIM_BOOLVEC(T_SIM_TEST_ID) := (others => TRUE);
+
+ -- Process Management
+ variable ProcessCount : natural := 0;
+ variable ActiveProcessCount : natural := 0;
+ variable Processes : T_SIM_PROCESS_VECTOR(T_SIM_PROCESS_ID);
+
+ -- Test Management
+ variable TestCount : natural := 0;
+ variable ActiveTestCount : natural := 0;
+ variable Tests : T_SIM_TEST_VECTOR(T_SIM_TEST_ID);
+
+ -- Initializer
+ procedure init is
+ begin
+ if (State.IsInitialized = FALSE) then
+ if C_SIM_VERBOSE then report "init:" severity NOTE; end if;
+ State.IsInitialized := TRUE;
+ createDefaultTest;
+ end if;
+ end procedure;
+
+ procedure initialize(MaxAssertFailures : natural := natural'high; MaxSimulationRuntime : TIME := TIME'high) is
+ begin
+ if C_SIM_VERBOSE then report "initialize:" severity NOTE; end if;
+ init;
+ Max_AssertFailures := MaxAssertFailures;
+ Max_SimulationRuntime := MaxSimulationRuntime;
+ end procedure;
+
+ procedure finalize is
+ begin
+ if (State.IsFinalized = FALSE) then
+ if C_SIM_VERBOSE then report "finalize: " severity NOTE; end if;
+ State.IsFinalized := TRUE;
+ for i in C_SIM_DEFAULT_TEST_ID to TestCount - 1 loop
+ finalizeTest(i);
+ end loop;
+ writeReport;
+ end if;
+ end procedure;
+
+ procedure writeReport_Header is
+ variable LineBuffer : LINE;
+ begin
+ write(LineBuffer, ( string'("========================================")));
+ write(LineBuffer, (LF & string'("POC TESTBENCH REPORT")));
+ write(LineBuffer, (LF & string'("========================================")));
+ writeline(output, LineBuffer);
+ end procedure;
+
+ procedure writeReport_TestReport(Prefix : string := "") is
+ variable LineBuffer : LINE;
+ begin
+ if (Tests(C_SIM_DEFAULT_TEST_ID).Status /= SIM_TEST_STATUS_CREATED) then
+ write(LineBuffer, Prefix & "Tests " & integer'image(TestCount + 1));
+ write(LineBuffer, LF & Prefix & " " & str_ralign("-1", log10ceilnz(TestCount + 1) + 1) & ": " & C_SIM_DEFAULT_TEST_NAME);
+ else
+ write(LineBuffer, Prefix & "Tests " & integer'image(TestCount));
+ end if;
+ for i in 0 to TestCount - 1 loop
+ write(LineBuffer, LF & Prefix & " " & str_ralign(integer'image(i), log10ceilnz(TestCount)) & ": " & str_trim(Tests(i).Name));
+ end loop;
+ writeline(output, LineBuffer);
+ end procedure;
+
+ procedure writeReport_AssertReport(Prefix : string := "") is
+ variable LineBuffer : LINE;
+ begin
+ write(LineBuffer, Prefix & "Assertions " & integer'image(AssertCount));
+ write(LineBuffer, LF & Prefix & " failed " & integer'image(FailedAssertCount) & ite((FailedAssertCount >= Max_AssertFailures), " Too many failed asserts!", ""));
+ writeline(output, LineBuffer);
+ end procedure;
+
+ procedure writeReport_ProcessReport(Prefix : string := "") is
+ variable LineBuffer : LINE;
+ begin
+ write(LineBuffer, Prefix & "Processes " & integer'image(ProcessCount));
+ write(LineBuffer, LF & Prefix & " active " & integer'image(ActiveProcessCount));
+ -- report killed processes
+ for i in 0 to ProcessCount - 1 loop
+ if ((Processes(i).Status = SIM_PROCESS_STATUS_ACTIVE) and (Processes(i).IsLowPriority = FALSE)) then
+ write(LineBuffer, LF & Prefix & " " & str_ralign(integer'image(i), log10ceilnz(ProcessCount)) & ": " & str_trim(Processes(i).Name));
+ end if;
+ end loop;
+ writeline(output, LineBuffer);
+ end procedure;
+
+ procedure writeReport_RuntimeReport(Prefix : string := "") is
+ variable LineBuffer : LINE;
+ begin
+ write(LineBuffer, Prefix & "Runtime " & to_string(now, 1));
+ writeline(output, LineBuffer);
+ end procedure;
+
+ procedure writeReport_SimulationResult is
+ variable LineBuffer : LINE;
+ begin
+ write(LineBuffer, ( string'("========================================")));
+ if not Passed then write(LineBuffer, (LF & string'("SIMULATION RESULT = FAILED")));
+ elsif AssertCount = 0 then write(LineBuffer, (LF & string'("SIMULATION RESULT = NO ASSERTS")));
+ elsif Passed then write(LineBuffer, (LF & string'("SIMULATION RESULT = PASSED")));
+ end if;
+ write(LineBuffer, (LF & string'("========================================")));
+ writeline(output, LineBuffer);
+ end procedure;
+
+ procedure writeReport is
+ variable LineBuffer : LINE;
+ begin
+ writeReport_Header;
+ writeReport_TestReport("");
+ write(LineBuffer, LF & "Overall");
+ writeline(output, LineBuffer);
+ writeReport_AssertReport(" ");
+ writeReport_ProcessReport(" ");
+ writeReport_RuntimeReport(" ");
+ writeReport_SimulationResult;
+ end procedure;
+
+ procedure assertion(condition : boolean; Message : string := "") is
+ begin
+ AssertCount := AssertCount + 1;
+ if not condition then
+ fail(Message);
+ FailedAssertCount := FailedAssertCount + 1;
+ if (FailedAssertCount >= Max_AssertFailures) then
+ stopAllProcesses;
+ end if;
+ end if;
+ end procedure;
+
+ procedure fail(Message : string := "") is
+ begin
+ if (Message'length > 0) then
+ report Message severity ERROR;
+ end if;
+ Passed := FALSE;
+ end procedure;
+
+ procedure writeMessage(Message : string) is
+ variable LineBuffer : LINE;
+ begin
+ write(LineBuffer, Message);
+ writeline(output, LineBuffer);
+ end procedure;
+
+ procedure createDefaultTest is
+ variable Test : T_SIM_TEST;
+ begin
+ if (State.IsInitialized = FALSE) then
+ init;
+ end if;
+ if C_SIM_VERBOSE then report "createDefaultTest(" & C_SIM_DEFAULT_TEST_NAME & "):" severity NOTE; end if;
+ Test.ID := C_SIM_DEFAULT_TEST_ID;
+ Test.Name := resize(C_SIM_DEFAULT_TEST_NAME, T_SIM_TEST_NAME'length);
+ Test.Status := SIM_TEST_STATUS_CREATED;
+ Test.ProcessIDs := (others => 0);
+ Test.ProcessCount := 0;
+ Test.ActiveProcessCount := 0;
+ -- add to the internal structure
+ Tests(Test.ID) := Test;
+ end procedure;
+
+ impure function createTest(Name : string) return T_SIM_TEST_ID is
+ variable Test : T_SIM_TEST;
+ begin
+ if (State.IsInitialized = FALSE) then
+ init;
+ end if;
+ if C_SIM_VERBOSE then report "createTest(" & Name & "): => " & T_SIM_TEST_ID'image(TestCount) severity NOTE; end if;
+ Test.ID := TestCount;
+ Test.Name := resize(Name, T_SIM_TEST_NAME'length);
+ Test.Status := SIM_TEST_STATUS_ACTIVE;
+ Test.ProcessIDs := (others => 0);
+ Test.ProcessCount := 0;
+ Test.ActiveProcessCount := 0;
+ -- add to the internal structure
+ Tests(Test.ID) := Test;
+ TestCount := TestCount + 1;
+ ActiveTestCount := ActiveTestCount + 1;
+ -- return TestID for finalizeTest
+ return Test.ID;
+ end function;
+
+ procedure activateDefaultTest is
+ begin
+ if (Tests(C_SIM_DEFAULT_TEST_ID).Status = SIM_TEST_STATUS_CREATED) then
+ Tests(C_SIM_DEFAULT_TEST_ID).Status := SIM_TEST_STATUS_ACTIVE;
+ ActiveTestCount := ActiveTestCount + 1;
+ end if;
+ end procedure;
+
+ procedure finalizeTest is
+ begin
+ finalizeTest(C_SIM_DEFAULT_TEST_ID);
+ end procedure;
+
+ procedure finalizeTest(TestID : T_SIM_TEST_ID) is
+ begin
+ if (TestID >= TestCount) then
+ report "TestID (" & T_SIM_TEST_ID'image(TestID) & ") is unknown." severity FAILURE;
+ return;
+ end if;
+
+ if TestID = C_SIM_DEFAULT_TEST_ID then
+ if (Tests(C_SIM_DEFAULT_TEST_ID).Status = SIM_TEST_STATUS_CREATED) then
+ if C_SIM_VERBOSE then report "finalizeTest(" & integer'image(C_SIM_DEFAULT_TEST_ID) & "): inactive" severity NOTE; end if;
+ Tests(C_SIM_DEFAULT_TEST_ID).Status := SIM_TEST_STATUS_ENDED;
+ stopProcesses(C_SIM_DEFAULT_TEST_ID);
+ return;
+ elsif (Tests(C_SIM_DEFAULT_TEST_ID).Status = SIM_TEST_STATUS_ACTIVE) then
+ if ActiveTestCount > 1 then
+ for ProcIdx in 0 to Tests(C_SIM_DEFAULT_TEST_ID).ProcessCount - 1 loop
+ deactivateProcess(Tests(C_SIM_DEFAULT_TEST_ID).ProcessIDs(ProcIdx), TRUE);
+ end loop;
+ Tests(C_SIM_DEFAULT_TEST_ID).Status := SIM_TEST_STATUS_ZOMBI;
+ return;
+ else
+ if C_SIM_VERBOSE then report "finalizeTest(" & integer'image(C_SIM_DEFAULT_TEST_ID) & "): active" severity NOTE; end if;
+ Tests(C_SIM_DEFAULT_TEST_ID).Status := SIM_TEST_STATUS_ENDED;
+ ActiveTestCount := ActiveTestCount - 1;
+ stopProcesses(C_SIM_DEFAULT_TEST_ID);
+ end if;
+ end if;
+ elsif (Tests(TestID).Status /= SIM_TEST_STATUS_ENDED) then
+ if C_SIM_VERBOSE then report "finalizeTest(TestID=" & T_SIM_TEST_ID'image(TestID) & "): " severity NOTE; end if;
+ Tests(TestID).Status := SIM_TEST_STATUS_ENDED;
+ ActiveTestCount := ActiveTestCount - 1;
+
+ if (Tests(TestID).ActiveProcessCount > 0) then
+ fail("Test " & integer'image(TestID) & " '" & str_trim(Tests(TestID).Name) & "' has still active process while finalizing:");
+ for ProcIdx in 0 to Tests(TestID).ProcessCount - 1 loop
+ if (Processes(Tests(TestID).ProcessIDs(ProcIdx)).Status = SIM_PROCESS_STATUS_ACTIVE) then
+ report " " & Processes(Tests(TestID).ProcessIDs(ProcIdx)).Name severity WARNING;
+ end if;
+ end loop;
+ end if;
+ stopProcesses(TestID);
+ end if;
+
+ if ActiveTestCount = 0 then
+ finalize;
+ elsif ActiveTestCount = 1 then
+ if (Tests(C_SIM_DEFAULT_TEST_ID).Status = SIM_TEST_STATUS_ACTIVE) then
+ finalizeTest(C_SIM_DEFAULT_TEST_ID);
+ elsif (Tests(C_SIM_DEFAULT_TEST_ID).Status = SIM_TEST_STATUS_ZOMBI) then
+ stopProcesses(C_SIM_DEFAULT_TEST_ID);
+ else
+ return;
+ end if;
+ finalize;
+ end if;
+ end procedure;
+
+ impure function registerProcess(Name : string; IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID is
+ begin
+ return registerProcess(C_SIM_DEFAULT_TEST_ID, Name, IsLowPriority);
+ end function;
+
+ impure function registerProcess(TestID : T_SIM_TEST_ID; Name : string; IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID is
+ variable Proc : T_SIM_PROCESS;
+ variable TestProcID : T_SIM_TEST_ID;
+ begin
+ if (State.IsInitialized = FALSE) then
+ init;
+ end if;
+ if TestID = C_SIM_DEFAULT_TEST_ID then
+ activateDefaultTest;
+ end if;
+
+ if (TestID >= TestCount) then
+ report "TestID (" & T_SIM_TEST_ID'image(TestID) & ") is unknown." severity FAILURE;
+ return T_SIM_PROCESS_ID'high;
+ end if;
+
+ if C_SIM_VERBOSE then report "registerProcess(TestID=" & T_SIM_TEST_ID'image(TestID) & ", " & Name & "): => " & T_SIM_PROCESS_ID'image(ProcessCount) severity NOTE; end if;
+ Proc.ID := ProcessCount;
+ Proc.TestID := TestID;
+ Proc.Name := resize(Name, T_SIM_PROCESS_NAME'length);
+ Proc.Status := SIM_PROCESS_STATUS_ACTIVE;
+ Proc.IsLowPriority := IsLowPriority;
+
+ -- add process to list
+ Processes(Proc.ID) := Proc;
+ ProcessCount := ProcessCount + 1;
+ ActiveProcessCount := inc_if(not IsLowPriority, ActiveProcessCount);
+ -- add process to test
+ TestProcID := Tests(TestID).ProcessCount;
+ Tests(TestID).ProcessIDs(TestProcID) := Proc.ID;
+ Tests(TestID).ProcessCount := TestProcID + 1;
+ Tests(TestID).ActiveProcessCount := inc_if(not IsLowPriority, Tests(TestID).ActiveProcessCount);
+ -- return the process ID
+ return Proc.ID;
+ end function;
+
+ procedure deactivateProcess(ProcID : T_SIM_PROCESS_ID; SkipLowPriority : boolean := FALSE) is
+ variable TestID : T_SIM_TEST_ID;
+ begin
+ if (ProcID >= ProcessCount) then
+ report "ProcID (" & T_SIM_PROCESS_ID'image(ProcID) & ") is unknown." severity FAILURE;
+ return;
+ elsif (Processes(ProcID).IsLowPriority and SkipLowPriority) then
+ return;
+ end if;
+
+ TestID := Processes(ProcID).TestID;
+ -- deactivate process
+ if (Processes(ProcID).Status = SIM_PROCESS_STATUS_ACTIVE) then
+ if C_SIM_VERBOSE then report "deactivateProcess(ProcID=" & T_SIM_PROCESS_ID'image(ProcID) & "): TestID=" & T_SIM_TEST_ID'image(TestID) & " Name=" & str_trim(Processes(ProcID).Name) severity NOTE; end if;
+ Processes(ProcID).Status := SIM_PROCESS_STATUS_ENDED;
+ ActiveProcessCount := dec_if(not Processes(ProcID).IsLowPriority, ActiveProcessCount);
+ Tests(TestID).ActiveProcessCount := dec_if(not Processes(ProcID).IsLowPriority, Tests(TestID).ActiveProcessCount);
+ if (Tests(TestID).ActiveProcessCount = 0) then
+ finalizeTest(TestID);
+ end if;
+ end if;
+ end procedure;
+
+ procedure stopAllProcesses is
+ begin
+ if C_SIM_VERBOSE then report "stopAllProcesses:" severity NOTE; end if;
+ for i in C_SIM_DEFAULT_TEST_ID to TestCount - 1 loop
+ stopProcesses(i);
+ end loop;
+ end procedure;
+
+ procedure stopProcesses(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) is
+ begin
+ if (TestID >= TestCount) then
+ report "TestID (" & T_SIM_TEST_ID'image(TestID) & ") is unknown." severity FAILURE;
+ return;
+ end if;
+
+ if C_SIM_VERBOSE then report "stopProcesses(TestID=" & T_SIM_TEST_ID'image(TestID) & "): Name=" & str_trim(Tests(TestID).Name) severity NOTE; end if;
+ MainProcessEnables(TestID) := FALSE;
+ stopClocks(TestID);
+ end procedure;
+
+ procedure stopAllClocks is
+ begin
+ if C_SIM_VERBOSE then report "stopAllClocks:" severity NOTE; end if;
+ for i in C_SIM_DEFAULT_TEST_ID to TestCount - 1 loop
+ stopClocks(i);
+ end loop;
+ end procedure;
+
+ procedure stopClocks(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) is
+ begin
+ if (TestID >= TestCount) then
+ report "TestID (" & T_SIM_TEST_ID'image(TestID) & ") is unknown." severity FAILURE;
+ return;
+ end if;
+
+ if C_SIM_VERBOSE then report "stopClocks(TestID=" & T_SIM_TEST_ID'image(TestID) & "): Name=" & str_trim(Tests(TestID).Name) severity NOTE; end if;
+ MainClockEnables(TestID) := FALSE;
+ end procedure;
+
+ impure function isStopped(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean is
+ begin
+ return not MainClockEnables(TestID);
+ end function;
+
+ impure function isFinalized(TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean is
+ begin
+ return (Tests(TestID).Status = SIM_TEST_STATUS_ENDED);
+ end function;
+
+ impure function isAllFinalized return boolean is
+ begin
+ if (State.IsFinalized = TRUE) then
+ if ActiveTestCount = 0 then
+ return TRUE;
+ end if;
+ report "isAllFinalized: " severity ERROR;
+ return FALSE;
+ else
+ return FALSE;
+ end if;
+ end function;
+ end protected body;
+end package body;
diff --git a/testsuite/gna/issue317/PoC/src/sim/sim_simulation.v08.vhdl b/testsuite/gna/issue317/PoC/src/sim/sim_simulation.v08.vhdl
new file mode 100644
index 000000000..81a964b95
--- /dev/null
+++ b/testsuite/gna/issue317/PoC/src/sim/sim_simulation.v08.vhdl
@@ -0,0 +1,173 @@
+-- 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;
+
+use PoC.sim_global.all;
+use PoC.sim_types.all;
+use PoC.sim_protected.all;
+
+
+package simulation is
+ -- Legacy interface for pre VHDL-2002
+ -- ===========================================================================
+ -- prepared aliases, if GHDL gets the aliases fixed. Reported on 08.02.2015 as Issue #38
+ -- alias simmInitialize is globalSimulationStatus.initialize[NATURAL, TIME];
+ -- alias simmFinalize is globalSimulationStatus.finalize[];
+
+ -- alias simmCreateTest is globalSimulationStatus.createTest[STRING return T_SIM_TEST_ID];
+ -- alias simmFinalizeTest is globalSimulationStatus.finalizeTest[T_SIM_TEST_ID];
+ -- alias simmRegisterProcess is globalSimulationStatus.registerProcess[T_SIM_TEST_ID, STRING, BOOLEAN return T_SIM_PROCESS_ID];
+ -- alias simmRegisterProcess is globalSimulationStatus.registerProcess[STRING, BOOLEAN return T_SIM_PROCESS_ID];
+ -- alias simmDeactivateProcess is globalSimulationStatus.deactivateProcess[T_SIM_PROCESS_ID];
+
+ -- alias simmIsStopped is globalSimulationStatus.isStopped[T_SIM_TEST_ID return BOOLEAN];
+ -- alias simmIsFinalized is globalSimulationStatus.isFinalized[T_SIM_TEST_ID return BOOLEAN];
+ -- alias simmIsAllFinalized is globalSimulationStatus.isAllFinalized [return BOOLEAN];
+
+ -- alias simmAssertion is globalSimulationStatus.assertion[BOOLEAN, STRING];
+ -- alias simmFail is globalSimulationStatus.fail[STRING];
+ -- alias simmWriteMessage is globalSimulationStatus.writeMessage[STRING];
+
+ procedure simInitialize(MaxAssertFailures : natural := natural'high; MaxSimulationRuntime : TIME := TIME'high);
+ procedure simFinalize;
+
+ impure function simCreateTest(Name : string) return T_SIM_TEST_ID;
+ procedure simFinalizeTest(constant TestID : T_SIM_TEST_ID);
+ impure function simRegisterProcess(Name : string; constant IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID;
+ impure function simRegisterProcess(constant TestID : T_SIM_TEST_ID; Name : string; constant IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID;
+ procedure simDeactivateProcess(ProcID : T_SIM_PROCESS_ID);
+
+ impure function simIsStopped(constant TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean;
+ impure function simIsFinalized(constant TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean;
+ impure function simIsAllFinalized return boolean;
+
+ procedure simAssertion(cond : in boolean; Message : in string := "");
+ procedure simFail(Message : in string := "");
+ procedure simWriteMessage(Message : in string := "");
+
+ -- TODO: integrate VCD simulation functions and procedures from sim_value_change_dump.vhdl here
+
+ -- checksum functions
+ -- ===========================================================================
+ -- TODO: move checksum functions here
+end package;
+
+
+package body simulation is
+ -- legacy procedures
+ -- ===========================================================================
+ -- TODO: undocumented group
+ procedure simInitialize(MaxAssertFailures : natural := natural'high; MaxSimulationRuntime : TIME := TIME'high) is
+ begin
+ globalSimulationStatus.initialize(MaxAssertFailures, MaxSimulationRuntime);
+ if C_SIM_VERBOSE then report "simInitialize:" severity NOTE; end if;
+ if (MaxSimulationRuntime /= time'high) then
+ wait for MaxSimulationRuntime;
+ report "simInitialize: TIMEOUT" severity ERROR;
+ globalSimulationStatus.finalize;
+ end if;
+ end procedure;
+
+ procedure simFinalize is
+ begin
+ globalSimulationStatus.finalize;
+ end procedure;
+
+ impure function simCreateTest(Name : string) return T_SIM_TEST_ID is
+ begin
+ return globalSimulationStatus.createTest(Name);
+ end function;
+
+ procedure simFinalizeTest(constant TestID : T_SIM_TEST_ID) is
+ begin
+ globalSimulationStatus.finalizeTest(TestID);
+ end procedure;
+
+ impure function simRegisterProcess(Name : string; constant IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID is
+ begin
+ return globalSimulationStatus.registerProcess(Name, IsLowPriority);
+ end function;
+
+ impure function simRegisterProcess(constant TestID : T_SIM_TEST_ID; Name : string; constant IsLowPriority : boolean := FALSE) return T_SIM_PROCESS_ID is
+ begin
+ return globalSimulationStatus.registerProcess(TestID, Name, IsLowPriority);
+ end function;
+
+ procedure simDeactivateProcess(ProcID : T_SIM_PROCESS_ID) is
+ begin
+ globalSimulationStatus.deactivateProcess(ProcID);
+ end procedure;
+
+ impure function simIsStopped(constant TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean is
+ begin
+ return globalSimulationStatus.isStopped(TestID);
+ end function;
+
+ impure function simIsFinalized(constant TestID : T_SIM_TEST_ID := C_SIM_DEFAULT_TEST_ID) return boolean is
+ begin
+ return globalSimulationStatus.isFinalized(TestID);
+ end function;
+
+ impure function simIsAllFinalized return boolean is
+ begin
+ return globalSimulationStatus.isAllFinalized;
+ end function;
+
+ -- TODO: undocumented group
+ procedure simWriteMessage(Message : in string := "") is
+ begin
+ globalSimulationStatus.writeMessage(Message);
+ end procedure;
+
+ procedure simFail(Message : in string := "") is
+ begin
+ globalSimulationStatus.fail(Message);
+ end procedure;
+
+ procedure simAssertion(cond : in boolean; Message : in string := "") is
+ begin
+ globalSimulationStatus.assertion(cond, Message);
+ end procedure;
+
+ -- checksum functions
+ -- ===========================================================================
+ -- TODO: move checksum functions here
+end package body;
diff --git a/testsuite/gna/issue317/PoC/src/sim/sim_types.vhdl b/testsuite/gna/issue317/PoC/src/sim/sim_types.vhdl
new file mode 100644
index 000000000..332cd4e16
--- /dev/null
+++ b/testsuite/gna/issue317/PoC/src/sim/sim_types.vhdl
@@ -0,0 +1,376 @@
+-- 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 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 randInitializeSeed(Seed : inout T_SIM_RAND_SEED);
+ procedure randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedValue : in T_SIM_RAND_SEED);
+ procedure randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedVector : in T_INTVEC);
+ procedure randInitializeSeed(Seed : inout T_SIM_RAND_SEED; SeedVector : in string);
+ function randInitializeSeed return T_SIM_RAND_SEED;
+ function randInitializeSeed(SeedValue : T_SIM_RAND_SEED) return T_SIM_RAND_SEED;
+ function randInitializeSeed(SeedVector : T_INTVEC) return T_SIM_RAND_SEED;
+ function randInitializeSeed(SeedVector : string) return T_SIM_RAND_SEED;
+
+
+ -- Uniform distributed random values
+ -- ===========================================================================
+ procedure randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL);
+ procedure randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; Minimum : integer; Maximum : integer);
+ procedure randUniformDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Minimum : REAL; Maximum : REAL);
+
+ -- Normal / Gaussian distributed random values
+ -- ===========================================================================
+ procedure randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; StandardDeviation : REAL := 1.0; Mean : REAL := 0.0);
+ procedure randNormalDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; StandardDeviation : in REAL; Mean : in REAL; Minimum : in integer; Maximum : in integer);
+ procedure 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 randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out REAL; Mean : in REAL);
+ procedure randPoissonDistributedValue(Seed : inout T_SIM_RAND_SEED; Value : out integer; Mean : in REAL; Minimum : in integer; Maximum : in integer);
+ procedure 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 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;
diff --git a/testsuite/gna/issue317/PoC/src/sim/sim_waveform.vhdl b/testsuite/gna/issue317/PoC/src/sim/sim_waveform.vhdl
new file mode 100644
index 000000000..3c70eeac1
--- /dev/null
+++ b/testsuite/gna/issue317/PoC/src/sim/sim_waveform.vhdl
@@ -0,0 +1,981 @@
+-- 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
+--
+-- 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;
+
+use PoC.sim_types.all;
+-- use PoC.sim_random.all;
+use PoC.simulation.all;
+
+
+package waveform is
+ -- clock generation
+ -- ===========================================================================
+ procedure simGenerateClock(
+ signal Clock : out std_logic;
+ constant Frequency : in FREQ;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ );
+ procedure simGenerateClock(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Clock : out std_logic;
+ constant Frequency : in FREQ;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ );
+ procedure simGenerateClock(
+ signal Clock : out std_logic;
+ constant Period : in time;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ );
+ procedure simGenerateClock(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Clock : out std_logic;
+ constant Period : in time;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ );
+
+ procedure simWaitUntilRisingEdge(signal Clock : in std_logic; constant Times : in positive);
+ procedure simWaitUntilRisingEdge(constant TestID : in T_SIM_TEST_ID; signal Clock : in std_logic; constant Times : in positive);
+ procedure simWaitUntilFallingEdge(signal Clock : in std_logic; constant Times : in positive);
+ procedure simWaitUntilFallingEdge(constant TestID : in T_SIM_TEST_ID; signal Clock : in std_logic; constant Times : in positive);
+
+ procedure simGenerateClock2(constant TestID : in T_SIM_TEST_ID; signal Clock : out std_logic; signal Debug : out REAL; constant Period : in time);
+
+ -- waveform description
+ -- ===========================================================================
+ type T_SIM_WAVEFORM_TUPLE_SL is record
+ Delay : time;
+ Value : std_logic;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_8 is record
+ Delay : time;
+ Value : T_SLV_8;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_16 is record
+ Delay : time;
+ Value : T_SLV_16;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_24 is record
+ Delay : time;
+ Value : T_SLV_24;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_32 is record
+ Delay : time;
+ Value : T_SLV_32;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_48 is record
+ Delay : time;
+ Value : T_SLV_48;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_64 is record
+ Delay : time;
+ Value : T_SLV_64;
+ end record;
+
+ subtype T_SIM_WAVEFORM is TIME_VECTOR; -- use predefined physical type TIME here
+ type T_SIM_WAVEFORM_SL is array(natural range <>) of T_SIM_WAVEFORM_TUPLE_SL;
+ type T_SIM_WAVEFORM_SLV_8 is array(natural range <>) of T_SIM_WAVEFORM_TUPLE_SLV_8;
+ type T_SIM_WAVEFORM_SLV_16 is array(natural range <>) of T_SIM_WAVEFORM_TUPLE_SLV_16;
+ type T_SIM_WAVEFORM_SLV_24 is array(natural range <>) of T_SIM_WAVEFORM_TUPLE_SLV_24;
+ type T_SIM_WAVEFORM_SLV_32 is array(natural range <>) of T_SIM_WAVEFORM_TUPLE_SLV_32;
+ type T_SIM_WAVEFORM_SLV_48 is array(natural range <>) of T_SIM_WAVEFORM_TUPLE_SLV_48;
+ type T_SIM_WAVEFORM_SLV_64 is array(natural range <>) of T_SIM_WAVEFORM_TUPLE_SLV_64;
+
+ -- waveform generation procedures
+ -- ===========================================================================
+ -- TODO: get initial value from Waveform(0) if .Delay = o fs, otherwise use (others => 'U') ?
+ procedure simGenerateWaveform(
+ signal Wave : out boolean;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in boolean := FALSE
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out boolean;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in boolean := FALSE
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in std_logic := '0'
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in std_logic := '0'
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM_SL;
+ constant InitialValue : in std_logic := '0'
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM_SL;
+ constant InitialValue : in std_logic := '0'
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_8;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_8;
+ constant InitialValue : in T_SLV_8 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_8;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_8;
+ constant InitialValue : in T_SLV_8 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_16;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_16;
+ constant InitialValue : in T_SLV_16 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_16;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_16;
+ constant InitialValue : in T_SLV_16 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_24;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_24;
+ constant InitialValue : in T_SLV_24 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_24;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_24;
+ constant InitialValue : in T_SLV_24 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_32;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_32;
+ constant InitialValue : in T_SLV_32 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_32;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_32;
+ constant InitialValue : in T_SLV_32 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_48;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_48;
+ constant InitialValue : in T_SLV_48 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_48;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_48;
+ constant InitialValue : in T_SLV_48 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_64;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_64;
+ constant InitialValue : in T_SLV_64 := (others => '0')
+ );
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_64;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_64;
+ constant InitialValue : in T_SLV_64 := (others => '0')
+ );
+
+ function "*" (Wave : T_SIM_WAVEFORM; Times : natural) return T_SIM_WAVEFORM;
+ function ">" (Wave : T_SIM_WAVEFORM; Offset : time) return T_SIM_WAVEFORM;
+ function "<" (Wave : T_SIM_WAVEFORM; Offset : time) return T_SIM_WAVEFORM;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_8; Times : natural) return T_SIM_WAVEFORM_SLV_8;
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_8; Offset : time) return T_SIM_WAVEFORM_SLV_8;
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_8; Offset : TIME) return T_SIM_WAVEFORM_SLV_8;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_16; Times : natural) return T_SIM_WAVEFORM_SLV_16;
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_16; Offset : time) return T_SIM_WAVEFORM_SLV_16;
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_16; Offset : TIME) return T_SIM_WAVEFORM_SLV_16;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_24; Times : natural) return T_SIM_WAVEFORM_SLV_24;
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_24; Offset : time) return T_SIM_WAVEFORM_SLV_24;
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_24; Offset : TIME) return T_SIM_WAVEFORM_SLV_24;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_32; Times : natural) return T_SIM_WAVEFORM_SLV_32;
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_32; Offset : time) return T_SIM_WAVEFORM_SLV_32;
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_32; Offset : TIME) return T_SIM_WAVEFORM_SLV_32;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_48; Times : natural) return T_SIM_WAVEFORM_SLV_48;
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_48; Offset : time) return T_SIM_WAVEFORM_SLV_48;
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_48; Offset : TIME) return T_SIM_WAVEFORM_SLV_48;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_64; Times : natural) return T_SIM_WAVEFORM_SLV_64;
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_64; Offset : time) return T_SIM_WAVEFORM_SLV_64;
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_64; Offset : TIME) return T_SIM_WAVEFORM_SLV_64;
+
+ -- convert arrays to waveforms
+ -- TODO: optimize waveform if input data doesn't change
+ -- TODO: write single bit variant
+ function to_waveform(bv : bit_vector; Delay : time) return T_SIM_WAVEFORM;
+ function to_waveform(slv : std_logic_vector; Delay : time) return T_SIM_WAVEFORM_SL;
+ function to_waveform(slvv : T_SLVV_8; Delay : time) return T_SIM_WAVEFORM_SLV_8;
+ function to_waveform(slvv : T_SLVV_16; Delay : time) return T_SIM_WAVEFORM_SLV_16;
+ function to_waveform(slvv : T_SLVV_24; Delay : time) return T_SIM_WAVEFORM_SLV_24;
+ function to_waveform(slvv : T_SLVV_32; Delay : time) return T_SIM_WAVEFORM_SLV_32;
+ function to_waveform(slvv : T_SLVV_48; Delay : time) return T_SIM_WAVEFORM_SLV_48;
+ function to_waveform(slvv : T_SLVV_64; Delay : time) return T_SIM_WAVEFORM_SLV_64;
+
+ -- predefined common waveforms
+ function simGenerateWaveform_Reset(constant Pause : time := 0 ns; ResetPulse : time := 10 ns) return T_SIM_WAVEFORM;
+
+ -- TODO: integrate VCD simulation functions and procedures from sim_value_change_dump.vhdl here
+ end package;
+
+
+package body waveform is
+ -- clock generation
+ -- ===========================================================================
+ procedure simGenerateClock(
+ signal Clock : out std_logic;
+ constant Frequency : in FREQ;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ ) is
+ constant Period : time := to_time(Frequency);
+ begin
+ simGenerateClock(C_SIM_DEFAULT_TEST_ID, Clock, Period, Phase, DutyCycle, Wander);
+ end procedure;
+
+ procedure simGenerateClock(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Clock : out std_logic;
+ constant Frequency : in FREQ;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ ) is
+ constant Period : time := to_time(Frequency);
+ begin
+ simGenerateClock(TestID, Clock, Period, Phase, DutyCycle, Wander);
+ end procedure;
+
+ procedure simGenerateClock(
+ signal Clock : out std_logic;
+ constant Period : in time;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ ) is
+ begin
+ simGenerateClock(C_SIM_DEFAULT_TEST_ID, Clock, Period, Phase, DutyCycle, Wander);
+ end procedure;
+
+ procedure simGenerateClock(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Clock : out std_logic;
+ constant Period : in time;
+ constant Phase : in T_PHASE := 0 deg;
+ constant DutyCycle : in T_DUTYCYCLE := 50 percent;
+ constant Wander : in T_WANDER := 0 permil
+ ) is
+ constant NormalizedPhase : T_PHASE := ite((Phase >= 0 deg), Phase, Phase + 360 deg); -- move Phase into the range of 0° to 360°
+ constant PhaseAsFactor : REAL := real(NormalizedPhase / 1 second) / 1296000.0; -- 1,296,000 = 3,600 seconds * 360 degree per cycle
+ constant WanderAsFactor : REAL := real(Wander / 1 ppb) / 1.0e9;
+ constant DutyCycleAsFactor : REAL := real(DutyCycle / 1 permil) / 1000.0;
+ constant Delay : time := Period * PhaseAsFactor;
+ constant TimeHigh : time := Period * DutyCycleAsFactor + (Period * (WanderAsFactor / 2.0)); -- add 50% wander to the high level
+ constant TimeLow : time := Period - TimeHigh + (Period * WanderAsFactor); -- and 50% to the low level
+ constant ClockAfterRun_cy : positive := 5;
+
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateClock(period=" & to_string(Period, 2) & ")", IsLowPriority => TRUE);
+ begin
+ -- report "simGenerateClock: (Instance: '" & Clock'instance_name & "')" & LF &
+ -- "Period: " & TIME'image(Period) & LF &
+ -- "Phase: " & T_PHASE'image(Phase) & LF &
+ -- "DutyCycle: " & T_DUTYCYCLE'image(DutyCycle) & LF &
+ -- "PhaseAsFactor: " & REAL'image(PhaseAsFactor) & LF &
+ -- "WanderAsFactor: " & REAL'image(WanderAsFactor) & LF &
+ -- "DutyCycleAsFactor: " & REAL'image(DutyCycleAsFactor) & LF &
+ -- "Delay: " & TIME'image(Delay) & LF &
+ -- "TimeHigh: " & TIME'image(TimeHigh) & LF &
+ -- "TimeLow: " & TIME'image(TimeLow)
+ -- severity NOTE;
+
+ if (Delay = 0 ns) then
+ null;
+ elsif (Delay <= TimeLow) then
+ Clock <= '0';
+ wait for Delay;
+ else
+ Clock <= '1';
+ wait for Delay - TimeLow;
+ Clock <= '0';
+ wait for TimeLow;
+ end if;
+ Clock <= '1';
+ while not simIsStopped(TestID) loop
+ wait for TimeHigh;
+ Clock <= '0';
+ wait for TimeLow;
+ Clock <= '1';
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ -- create N more cycles to allow other processes to recognize the stop condition (clock after run)
+ for i in 1 to ClockAfterRun_cy loop
+ wait for TimeHigh;
+ Clock <= '0';
+ wait for TimeLow;
+ Clock <= '1';
+ end loop;
+ Clock <= '0';
+ end procedure;
+
+ type T_SIM_NORMAL_DIST_PARAMETER is record
+ StandardDeviation : REAL;
+ Mean : REAL;
+ end record;
+ type T_JITTER_DISTRIBUTION is array (natural range <>) of T_SIM_NORMAL_DIST_PARAMETER;
+
+ procedure simGenerateClock2(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Clock : out std_logic;
+ signal Debug : out REAL;
+ constant Period : in time
+ ) is
+ constant TimeHigh : time := Period * 0.5;
+ constant TimeLow : time := Period - TimeHigh;
+ constant JitterPeakPeak : REAL := 0.1; -- UI
+ constant JitterAsFactor : REAL := JitterPeakPeak / 4.0; -- Maximum jitter per edge
+ constant JitterDistribution : T_JITTER_DISTRIBUTION := (
+ -- 0 => (StandardDeviation => 0.2, Mean => -0.4),
+ -- 1 => (StandardDeviation => 0.2, Mean => 0.4)
+
+ -- 0 => (StandardDeviation => 0.2, Mean => -0.4),
+ -- 1 => (StandardDeviation => 0.3, Mean => -0.1),
+ -- 2 => (StandardDeviation => 0.5, Mean => 0.0),
+ -- 3 => (StandardDeviation => 0.3, Mean => 0.1),
+ -- 4 => (StandardDeviation => 0.2, Mean => 0.4)
+
+ 0 => (StandardDeviation => 0.15, Mean => -0.6),
+ 1 => (StandardDeviation => 0.2, Mean => -0.3),
+ 2 => (StandardDeviation => 0.25, Mean => -0.2),
+ 3 => (StandardDeviation => 0.3, Mean => 0.0),
+ 4 => (StandardDeviation => 0.25, Mean => 0.2),
+ 5 => (StandardDeviation => 0.2, Mean => 0.3),
+ 6 => (StandardDeviation => 0.15, Mean => 0.6)
+ );
+ variable Seed : T_SIM_RAND_SEED;
+ variable rand : REAL;
+ variable Jitter : REAL;
+ variable Index : natural;
+
+ constant ClockAfterRun_cy : positive := 5;
+ begin
+ Clock <= '1';
+ randInitializeSeed(Seed);
+
+ while not simIsStopped(TestID) loop
+ ieee.math_real.Uniform(Seed.Seed1, Seed.Seed2, rand);
+ Index := scale(rand, 0, JitterDistribution'length * 10) mod JitterDistribution'length;
+ randNormalDistributedValue(Seed, rand, JitterDistribution(Index).StandardDeviation, JitterDistribution(Index).Mean, -1.0, 1.0);
+
+ Jitter := JitterAsFactor * rand;
+ Debug <= rand;
+
+ -- Debug <= integer(rand * 256.0 + 256.0);
+ wait for TimeHigh + (Period * Jitter);
+ Clock <= '0';
+ wait for TimeLow + (Period * Jitter);
+ Clock <= '1';
+ end loop;
+ -- create N more cycles to allow other processes to recognize the stop condition (clock after run)
+ for i in 1 to ClockAfterRun_cy loop
+ wait for TimeHigh;
+ Clock <= '0';
+ wait for TimeLow;
+ Clock <= '1';
+ end loop;
+ Clock <= '0';
+ end procedure;
+
+
+ procedure simWaitUntilRisingEdge(signal Clock : in std_logic; constant Times : in positive) is
+ begin
+ simWaitUntilRisingEdge(C_SIM_DEFAULT_TEST_ID, Clock, Times);
+ end procedure;
+
+ procedure simWaitUntilRisingEdge(constant TestID : in T_SIM_TEST_ID; signal Clock : in std_logic; constant Times : in positive) is
+ begin
+ for i in 1 to Times loop
+ wait until rising_edge(Clock);
+ exit when simIsStopped(TestID);
+ end loop;
+ end procedure;
+
+ procedure simWaitUntilFallingEdge(signal Clock : in std_logic; constant Times : in positive) is
+ begin
+ simWaitUntilFallingEdge(C_SIM_DEFAULT_TEST_ID, Clock, Times);
+ end procedure;
+
+ procedure simWaitUntilFallingEdge(constant TestID : in T_SIM_TEST_ID; signal Clock : in std_logic; constant Times : in positive) is
+ begin
+ for i in 1 to Times loop
+ wait until falling_edge(Clock);
+ exit when simIsStopped(TestID);
+ end loop;
+ end procedure;
+
+ -- waveform generation
+ -- ===========================================================================
+ procedure simGenerateWaveform(
+ signal Wave : out boolean;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in boolean := FALSE
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out boolean;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in boolean := FALSE
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ variable State : boolean;
+ begin
+ State := InitialValue;
+ Wave <= State;
+ for i in Waveform'range loop
+ wait for Waveform(i);
+ State := not State;
+ Wave <= State;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in std_logic := '0'
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM;
+ constant InitialValue : in std_logic := '0'
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ variable State : std_logic;
+ begin
+ State := InitialValue;
+ Wave <= State;
+ for i in Waveform'range loop
+ wait for Waveform(i);
+ State := not State;
+ Wave <= State;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM_SL;
+ constant InitialValue : in std_logic := '0'
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out std_logic;
+ constant Waveform : in T_SIM_WAVEFORM_SL;
+ constant InitialValue : in std_logic := '0'
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_8;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_8;
+ constant InitialValue : in T_SLV_8 := (others => '0')
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_8;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_8;
+ constant InitialValue : in T_SLV_8 := (others => '0')
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_16;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_16;
+ constant InitialValue : in T_SLV_16 := (others => '0')
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_16;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_16;
+ constant InitialValue : in T_SLV_16 := (others => '0')
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_24;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_24;
+ constant InitialValue : in T_SLV_24 := (others => '0')
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_24;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_24;
+ constant InitialValue : in T_SLV_24 := (others => '0')
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_32;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_32;
+ constant InitialValue : in T_SLV_32 := (others => '0')
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_32;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_32;
+ constant InitialValue : in T_SLV_32 := (others => '0')
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_48;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_48;
+ constant InitialValue : in T_SLV_48 := (others => '0')
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_48;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_48;
+ constant InitialValue : in T_SLV_48 := (others => '0')
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ signal Wave : out T_SLV_64;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_64;
+ constant InitialValue : in T_SLV_64 := (others => '0')
+ ) is
+ begin
+ simGenerateWaveform(C_SIM_DEFAULT_TEST_ID, Wave, Waveform, InitialValue);
+ end procedure;
+
+ procedure simGenerateWaveform(
+ constant TestID : in T_SIM_TEST_ID;
+ signal Wave : out T_SLV_64;
+ constant Waveform : in T_SIM_WAVEFORM_SLV_64;
+ constant InitialValue : in T_SLV_64 := (others => '0')
+ ) is
+ constant PROCESS_ID : T_SIM_PROCESS_ID := simRegisterProcess(TestID, "simGenerateWaveform");
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ exit when simIsStopped(TestID);
+ end loop;
+ simDeactivateProcess(PROCESS_ID);
+ end procedure;
+
+ -- Waveform arithmetic
+ function "*" (Wave : T_SIM_WAVEFORM; Times : natural) return T_SIM_WAVEFORM is
+ variable Result : T_SIM_WAVEFORM(0 to Wave'length * Times - 1);
+ begin
+ for i in 0 to Times - 1 loop
+ Result(i * Wave'length to (i + 1) * Wave'length - 1) := Wave;
+ end loop;
+ return Result;
+ end function;
+
+ function ">" (Wave : T_SIM_WAVEFORM; Offset : time) return T_SIM_WAVEFORM is
+ begin
+ return (Wave(Wave'low) + Offset) & Wave(Wave'low + 1 to Wave'high);
+ end function;
+
+ function "<" (Wave : T_SIM_WAVEFORM; Offset : time) return T_SIM_WAVEFORM is
+ variable Result : T_SIM_WAVEFORM(Wave'range);
+ variable TimePos : time;
+ begin
+ report "Has bugs" severity ERROR;
+ TimePos := 0 fs;
+ for i in Wave'range loop
+ TimePos := TimePos + Wave(i);
+ if TimePos > Offset then
+ return (TimePos - Offset) & Wave(i + 1 to Wave'high);
+ end if;
+ end loop;
+ return (0 => 0 fs);
+ end function;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_8; Times : natural) return T_SIM_WAVEFORM_SLV_8 is
+ variable Result : T_SIM_WAVEFORM_SLV_8(0 to Wave'length * Times - 1);
+ begin
+ for i in 0 to Times - 1 loop
+ Result(i * Wave'length to (i + 1) * Wave'length - 1) := Wave;
+ end loop;
+ return Result;
+ end function;
+
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_8; Offset : time) return T_SIM_WAVEFORM_SLV_8 is
+ begin
+ return T_SIM_WAVEFORM_TUPLE_SLV_8'(
+ Delay => Wave(Wave'low).Delay + Offset,
+ Value => Wave(Wave'low).Value
+ ) & Wave(Wave'low + 1 to Wave'high);
+ end function;
+
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_8; Offset : TIME) return T_SIM_WAVEFORM_SLV_8 is
+ -- begin
+ -- report "Not implemented" severity FAILURE;
+ -- end function;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_16; Times : natural) return T_SIM_WAVEFORM_SLV_16 is
+ variable Result : T_SIM_WAVEFORM_SLV_16(0 to Wave'length * Times - 1);
+ begin
+ for i in 0 to Times - 1 loop
+ Result(i * Wave'length to (i + 1) * Wave'length - 1) := Wave;
+ end loop;
+ return Result;
+ end function;
+
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_16; Offset : time) return T_SIM_WAVEFORM_SLV_16 is
+ begin
+ return T_SIM_WAVEFORM_TUPLE_SLV_16'(
+ Delay => Wave(Wave'low).Delay + Offset,
+ Value => Wave(Wave'low).Value
+ ) & Wave(Wave'low + 1 to Wave'high);
+ end function;
+
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_16; Offset : TIME) return T_SIM_WAVEFORM_SLV_16 is
+ -- begin
+ -- report "Not implemented" severity FAILURE;
+ -- end function;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_24; Times : natural) return T_SIM_WAVEFORM_SLV_24 is
+ variable Result : T_SIM_WAVEFORM_SLV_24(0 to Wave'length * Times - 1);
+ begin
+ for i in 0 to Times - 1 loop
+ Result(i * Wave'length to (i + 1) * Wave'length - 1) := Wave;
+ end loop;
+ return Result;
+ end function;
+
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_24; Offset : time) return T_SIM_WAVEFORM_SLV_24 is
+ begin
+ return T_SIM_WAVEFORM_TUPLE_SLV_24'(
+ Delay => Wave(Wave'low).Delay + Offset,
+ Value => Wave(Wave'low).Value
+ ) & Wave(Wave'low + 1 to Wave'high);
+ end function;
+
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_24; Offset : TIME) return T_SIM_WAVEFORM_SLV_24 is
+ -- begin
+ -- report "Not implemented" severity FAILURE;
+ -- end function;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_32; Times : natural) return T_SIM_WAVEFORM_SLV_32 is
+ variable Result : T_SIM_WAVEFORM_SLV_32(0 to Wave'length * Times - 1);
+ begin
+ for i in 0 to Times - 1 loop
+ Result(i * Wave'length to (i + 1) * Wave'length - 1) := Wave;
+ end loop;
+ return Result;
+ end function;
+
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_32; Offset : time) return T_SIM_WAVEFORM_SLV_32 is
+ begin
+ return T_SIM_WAVEFORM_TUPLE_SLV_32'(
+ Delay => Wave(Wave'low).Delay + Offset,
+ Value => Wave(Wave'low).Value
+ ) & Wave(Wave'low + 1 to Wave'high);
+ end function;
+
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_32; Offset : TIME) return T_SIM_WAVEFORM_SLV_32 is
+ -- begin
+ -- report "Not implemented" severity FAILURE;
+ -- end function;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_48; Times : natural) return T_SIM_WAVEFORM_SLV_48 is
+ variable Result : T_SIM_WAVEFORM_SLV_48(0 to Wave'length * Times - 1);
+ begin
+ for i in 0 to Times - 1 loop
+ Result(i * Wave'length to (i + 1) * Wave'length - 1) := Wave;
+ end loop;
+ return Result;
+ end function;
+
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_48; Offset : time) return T_SIM_WAVEFORM_SLV_48 is
+ begin
+ return T_SIM_WAVEFORM_TUPLE_SLV_48'(
+ Delay => Wave(Wave'low).Delay + Offset,
+ Value => Wave(Wave'low).Value
+ ) & Wave(Wave'low + 1 to Wave'high);
+ end function;
+
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_48; Offset : TIME) return T_SIM_WAVEFORM_SLV_48 is
+ -- begin
+ -- report "Not implemented" severity FAILURE;
+ -- end function;
+
+ function "*" (Wave : T_SIM_WAVEFORM_SLV_64; Times : natural) return T_SIM_WAVEFORM_SLV_64 is
+ variable Result : T_SIM_WAVEFORM_SLV_64(0 to Wave'length * Times - 1);
+ begin
+ for i in 0 to Times - 1 loop
+ Result(i * Wave'length to (i + 1) * Wave'length - 1) := Wave;
+ end loop;
+ return Result;
+ end function;
+
+ function ">" (Wave : T_SIM_WAVEFORM_SLV_64; Offset : time) return T_SIM_WAVEFORM_SLV_64 is
+ begin
+ return T_SIM_WAVEFORM_TUPLE_SLV_64'(
+ Delay => Wave(Wave'low).Delay + Offset,
+ Value => Wave(Wave'low).Value
+ ) & Wave(Wave'low + 1 to Wave'high);
+ end function;
+
+ -- function "<" (Wave : T_SIM_WAVEFORM_SLV_64; Offset : TIME) return T_SIM_WAVEFORM_SLV_64 is
+ -- begin
+ -- report "Not implemented" severity FAILURE;
+ -- end function;
+
+
+ function to_waveform(bv : bit_vector; Delay : time) return T_SIM_WAVEFORM is
+ variable Result : T_SIM_WAVEFORM(0 to bv'length - 1);
+ begin
+ report "Has bugs" severity ERROR;
+ for i in 0 to bv'length - 1 loop
+ Result(i) := Delay;
+ end loop;
+ return Result;
+ end function;
+
+ function to_waveform(slv : std_logic_vector; Delay : time) return T_SIM_WAVEFORM_SL is
+ variable Result : T_SIM_WAVEFORM_SL(0 to slv'length - 1);
+ begin
+ for i in 0 to slv'length - 1 loop
+ Result(i).Delay := Delay;
+ Result(i).Value := slv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function to_waveform(slvv : T_SLVV_8; Delay : time) return T_SIM_WAVEFORM_SLV_8 is
+ variable Result : T_SIM_WAVEFORM_SLV_8(0 to slvv'length - 1);
+ begin
+ for i in 0 to slvv'length - 1 loop
+ Result(i).Delay := Delay;
+ Result(i).Value := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function to_waveform(slvv : T_SLVV_16; Delay : time) return T_SIM_WAVEFORM_SLV_16 is
+ variable Result : T_SIM_WAVEFORM_SLV_16(0 to slvv'length - 1);
+ begin
+ for i in 0 to slvv'length - 1 loop
+ Result(i).Delay := Delay;
+ Result(i).Value := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function to_waveform(slvv : T_SLVV_24; Delay : time) return T_SIM_WAVEFORM_SLV_24 is
+ variable Result : T_SIM_WAVEFORM_SLV_24(0 to slvv'length - 1);
+ begin
+ for i in 0 to slvv'length - 1 loop
+ Result(i).Delay := Delay;
+ Result(i).Value := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function to_waveform(slvv : T_SLVV_32; Delay : time) return T_SIM_WAVEFORM_SLV_32 is
+ variable Result : T_SIM_WAVEFORM_SLV_32(0 to slvv'length - 1);
+ begin
+ for i in 0 to slvv'length - 1 loop
+ Result(i).Delay := Delay;
+ Result(i).Value := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function to_waveform(slvv : T_SLVV_48; Delay : time) return T_SIM_WAVEFORM_SLV_48 is
+ variable Result : T_SIM_WAVEFORM_SLV_48(0 to slvv'length - 1);
+ begin
+ for i in 0 to slvv'length - 1 loop
+ Result(i).Delay := Delay;
+ Result(i).Value := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function to_waveform(slvv : T_SLVV_64; Delay : time) return T_SIM_WAVEFORM_SLV_64 is
+ variable Result : T_SIM_WAVEFORM_SLV_64(0 to slvv'length - 1);
+ begin
+ for i in 0 to slvv'length - 1 loop
+ Result(i).Delay := Delay;
+ Result(i).Value := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ -- predefined common waveforms
+ function simGenerateWaveform_Reset(constant Pause : time := 0 ns; ResetPulse : time := 10 ns) return T_SIM_WAVEFORM is
+ variable p : time;
+ variable rp : time;
+ begin
+ -- WORKAROUND: for Mentor QuestaSim/ModelSim
+ -- Version: 10.4c
+ -- Issue:
+ -- return (0 => Pause, 1 => ResetPulse); always evaluates to (0 ns, 10 ns),
+ -- regardless of the passed function parameters
+ -- Bugfix:
+ -- The bugfix will be included in 10.5a, but this workaround must be
+ -- present until Altera updates the embedded ModelSim Altera Edition.
+ p := Pause;
+ rp := ResetPulse;
+ return (0 => p, 1 => rp);
+ end function;
+end package body;