diff options
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.vhdl | 489 |
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; |