-- 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 -- -- License: -- ============================================================================= -- Copyright 2007-2016 Technische Universitaet Dresden - Germany -- Chair for 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; 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; InstanceName : STRING) return T_SIM_PROCESS_ID; impure function registerProcess(Name : STRING) return T_SIM_PROCESS_ID; procedure deactivateProcess(procID : T_SIM_PROCESS_ID); -- Test Management impure function createTest(Name : STRING) return T_SIM_TEST_ID; -- Run Management procedure stopAllClocks; impure function isStopped return BOOLEAN; end protected; end package; package body sim_protected is -- Simulation process and Status Management -- =========================================================================== type T_SIM_STATUS is protected body -- status variable IsInitialized : BOOLEAN := FALSE; variable IsFinalized : BOOLEAN := FALSE; -- 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 MainClockEnable : BOOLEAN := 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 Tests : T_SIM_TEST_VECTOR(T_SIM_TEST_ID); -- Initializer procedure initialize is begin IsInitialized := TRUE; end procedure; procedure finalize is begin if (IsFinalized = FALSE) then if (ActiveProcessCount = 0) then writeReport; IsFinalized := TRUE; 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 assertion(condition : BOOLEAN; Message : STRING := "") is begin AssertCount := AssertCount + 1; if (condition = FALSE) then fail(Message); FailedAssertCount := FailedAssertCount + 1; end if; end procedure; procedure writeMessage(Message : STRING) is variable LineBuffer : LINE; begin write(LineBuffer, Message); writeline(output, LineBuffer); end procedure; procedure writeReport is variable LineBuffer : LINE; begin write(LineBuffer, (CR & STRING'("========================================"))); write(LineBuffer, (CR & STRING'("POC TESTBENCH REPORT"))); write(LineBuffer, (CR & STRING'("========================================"))); write(LineBuffer, (CR & STRING'("Assertions ") & INTEGER'image(AssertCount))); write(LineBuffer, (CR & STRING'(" failed ") & INTEGER'image(FailedAssertCount))); write(LineBuffer, (CR & STRING'("Processes ") & INTEGER'image(ProcessCount))); write(LineBuffer, (CR & STRING'(" active ") & INTEGER'image(ActiveProcessCount))); for i in 0 to ProcessCount - 1 loop if (Processes(i).Status = SIM_PROCESS_STATUS_ACTIVE) then write(LineBuffer, (CR & STRING'(" ") & str_trim(Processes(i).Name))); end if; end loop; write(LineBuffer, (CR & STRING'("Tests ") & INTEGER'image(TestCount))); for i in 0 to TestCount - 1 loop write(LineBuffer, (CR & STRING'(" ") & str_ralign(INTEGER'image(i), log10ceil(T_SIM_TEST_ID'high)) & ": " & str_trim(Tests(i).Name))); end loop; write(LineBuffer, (CR & STRING'("========================================"))); if (AssertCount = 0) then write(LineBuffer, (CR & STRING'("SIMULATION RESULT = NO ASSERTS"))); elsif (Passed = TRUE) then write(LineBuffer, (CR & STRING'("SIMULATION RESULT = PASSED"))); else write(LineBuffer, (CR & STRING'("SIMULATION RESULT = FAILED"))); end if; write(LineBuffer, (CR & STRING'("========================================"))); writeline(output, LineBuffer); end procedure; -- impure function registerProcess(Name : STRING; InstanceName : STRING) return T_SIM_PROCESS_ID is impure function registerProcess(Name : STRING) return T_SIM_PROCESS_ID is variable Proc : T_SIM_PROCESS; begin Proc.ID := ProcessCount; Proc.Name := resize(Name, T_SIM_PROCESS_NAME'length); -- Proc.InstanceName := resize(InstanceName, T_SIM_PROCESS_INSTNAME'length); Proc.Status := SIM_PROCESS_STATUS_ACTIVE; Processes(Proc.ID) := Proc; ProcessCount := ProcessCount + 1; ActiveProcessCount := ActiveProcessCount + 1; return Proc.ID; end function; procedure deactivateProcess(ProcID : T_SIM_PROCESS_ID) is variable hasActiveProcesses : BOOLEAN := FALSE; begin if (ProcID < ProcessCount) then if (Processes(ProcID).Status = SIM_PROCESS_STATUS_ACTIVE) then Processes(ProcID).Status := SIM_PROCESS_STATUS_ENDED; ActiveProcessCount := ActiveProcessCount - 1; end if; end if; if (ActiveProcessCount = 0) then stopAllClocks; end if; end procedure; impure function createTest(Name : STRING) return T_SIM_TEST_ID is variable Test : T_SIM_TEST; begin Test.ID := TestCount; Test.Name := resize(Name, T_SIM_TEST_NAME'length); Test.Status := SIM_TEST_STATUS_ACTIVE; Tests(Test.ID) := Test; TestCount := TestCount + 1; return Test.ID; end function; procedure stopAllClocks is begin MainClockEnable := FALSE; end procedure; impure function isStopped return BOOLEAN is begin return not MainClockEnable; end function; end protected body; end package body;