aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue317/PoC/src/sim/sim_protected.v08.vhdl
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/gna/issue317/PoC/src/sim/sim_protected.v08.vhdl')
-rw-r--r--testsuite/gna/issue317/PoC/src/sim/sim_protected.v08.vhdl489
1 files changed, 489 insertions, 0 deletions
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;