2024-10-04 23:29:34 +08:00

7152 lines
269 KiB
VHDL

-- ----------------------------------------------------------------------------
-- Title : Standard VITAL Memory Package
-- :
-- Library : Vital_Memory
-- :
-- Developers : IEEE DASC Timing Working Group (TWG), PAR 1076.4
-- : Ekambaram Balaji, LSI Logic Corporation
-- : Jose De Castro, Consultant
-- : Prakash Bare, GDA Technologies
-- : William Yam, LSI Logic Corporation
-- : Dennis Brophy, Model Technology
-- :
-- Purpose : This packages defines standard types, constants, functions
-- : and procedures for use in developing ASIC memory models.
-- :
-- ----------------------------------------------------------------------------
--
-- ----------------------------------------------------------------------------
-- Modification History :
-- ----------------------------------------------------------------------------
-- Ver:|Auth:| Date:| Changes Made:
-- 0.1 | eb |071796| First prototye as part of VITAL memory proposal
-- 0.2 | jdc |012897| Initial prototyping with proposed MTM scheme
-- 0.3 | jdc |090297| Extensive updates for TAG review (functional)
-- 0.4 | eb |091597| Changed naming conventions for VitalMemoryTable
-- | | | Added interface of VitalMemoryCrossPorts() &
-- | | | VitalMemoryViolation().
-- 0.5 | jdc |092997| Completed naming changes thoughout package body.
-- | | | Testing with simgle port test model looks ok.
-- 0.6 | jdc |121797| Major updates to the packages:
-- | | | - Implement VitalMemoryCrossPorts()
-- | | | - Use new VitalAddressValueType
-- | | | - Use new VitalCrossPortModeType enum
-- | | | - Overloading without SamePort args
-- | | | - Honor erroneous address values
-- | | | - Honor ports disabled with 'Z'
-- | | | - Implement implicit read 'M' table symbol
-- | | | - Cleanup buses to use (H DOWNTO L)
-- | | | - Message control via MsgOn,HeaderMsg,PortName
-- | | | - Tested with 1P1RW,2P2RW,4P2R2W,4P4RW cases
-- 0.7 | jdc |052698| Bug fixes to the packages:
-- | | | - Fix failure with negative Address values
-- | | | - Added debug messages for VMT table search
-- | | | - Remove 'S' for action column (only 's')
-- | | | - Remove 's' for response column (only 'S')
-- | | | - Remove 'X' for action and response columns
-- 0.8 | jdc |061298| Implemented VitalMemoryViolation()
-- | | | - Minimal functionality violation tables
-- | | | - Missing:
-- | | | - Cannot handle wide violation variables
-- | | | - Cannot handle sub-word cases
-- | | | Fixed IIC version of MemoryMatch
-- | | | Fixed 'M' vs 'm' switched on debug output
-- | | | TO BE DONE:
-- | | | - Implement 'd' corrupting a single bit
-- | | | - Implement 'D' corrupting a single bit
-- 0.9 |eb/sc|080498| Added UNDEF value for VitalPortFlagType
-- 0.10|eb/sc|080798| Added CORRUPT value for VitalPortFlagType
-- 0.11|eb/sc|081798| Added overloaded function interface for
-- | | | VitalDeclareMemory
-- 0.14| jdc |113198| Merging of memory functionality and version
-- | | | 1.4 9/17/98 of timing package from Prakash
-- 0.15| jdc |120198| Major development of VMV functionality
-- 0.16| jdc |120298| Complete VMV functionlality for initial testing
-- | | | - New ViolationTableCorruptMask() procedure
-- | | | - New MemoryTableCorruptMask() procedure
-- | | | - HandleMemoryAction():
-- | | | - Removed DataOutBus bogus output
-- | | | - Replaced DataOutTmp with DataInTmp
-- | | | - Added CorruptMask input handling
-- | | | - Implemented 'd','D' using CorruptMask
-- | | | - CorruptMask on 'd','C','L','D','E'
-- | | | - CorruptMask ignored on 'c','l','e'
-- | | | - Changed 'l','d','e' to set PortFlag to CORRUPT
-- | | | - Changed 'L','D','E' to set PortFlag to CORRUPT
-- | | | - Changed 'c','l','d','e' to ignore HighBit, LowBit
-- | | | - Changed 'C','L','D','E' to use HighBit, LowBit
-- | | | - HandleDataAction():
-- | | | - Added CorruptMask input handling
-- | | | - Implemented 'd','D' using CorruptMask
-- | | | - CorruptMask on 'd','C','L','D','E'
-- | | | - CorruptMask ignored on 'l','e'
-- | | | - Changed 'l','d','e' to set PortFlag to CORRUPT
-- | | | - Changed 'L','D','E' to set PortFlag to CORRUPT
-- | | | - Changed 'l','d','e' to ignore HighBit, LowBit
-- | | | - Changed 'L','D','E' to use HighBit, LowBit
-- | | | - MemoryTableLookUp():
-- | | | - Added MsgOn table debug output
-- | | | - Uses new MemoryTableCorruptMask()
-- | | | - ViolationTableLookUp():
-- | | | - Uses new ViolationTableCorruptMask()
-- 0.17| jdc |120898| - Added VitalMemoryViolationSymbolType,
-- | | | VitalMemoryViolationTableType data
-- | | | types but not used yet (need to discuss)
-- | | | - Added overload for VitalMemoryViolation()
-- | | | which does not have array flags
-- | | | - Bug fixes for VMV functionality:
-- | | | - ViolationTableLookUp() not handling '-' in
-- | | | scalar violation matching
-- | | | - VitalMemoryViolation() now normalizes
-- | | | VFlagArrayTmp'LEFT as LSB before calling
-- | | | ViolationTableLookUp() for proper scanning
-- | | | - ViolationTableCorruptMask() had to remove
-- | | | normalization of CorruptMaskTmp and
-- | | | ViolMaskTmp for proper MSB:LSB corruption
-- | | | - HandleMemoryAction(), HandleDataAction()
-- | | | - Removed 'D','E' since not being used
-- | | | - Use XOR instead of OR for corrupt masks
-- | | | - Now 'd' is sensitive to HighBit, LowBit
-- | | | - Fixed LowBit overflow in bit writeable case
-- | | | - MemoryTableCorruptMask()
-- | | | - ViolationTableCorruptMask()
-- | | | - VitalMemoryTable()
-- | | | - VitalMemoryCrossPorts()
-- | | | - Fixed VitalMemoryViolation() failing on
-- | | | error AddressValue from earlier VMT()
-- | | | - Minor cleanup of code formatting
-- 0.18| jdc |032599| - In VitalDeclareMemory()
-- | | | - Added BinaryLoadFile formal arg and
-- | | | modified LoadMemory() to handle bin
-- | | | - Added NOCHANGE to VitalPortFlagType
-- | | | - For VitalCrossPortModeType
-- | | | - Added CpContention enum
-- | | | - In HandleDataAction()
-- | | | - Set PortFlag := NOCHANGE for 'S'
-- | | | - In HandleMemoryAction()
-- | | | - Set PortFlag := NOCHANGE for 's'
-- | | | - In VitalMemoryTable() and
-- | | | VitalMemoryViolation()
-- | | | - Honor PortFlag = NOCHANGE returned
-- | | | from HandleMemoryAction()
-- | | | - In VitalMemoryCrossPorts()
-- | | | - Fixed Address = AddressJ for all
-- | | | conditions of DoWrCont & DoCpRead
-- | | | - Handle CpContention like WrContOnly
-- | | | under CpReadOnly conditions, with
-- | | | associated memory message changes
-- | | | - Handle PortFlag = NOCHANGE like
-- | | | PortFlag = READ for actions
-- | | | - Modeling change:
-- | | | - Need to init PortFlag every delta
-- | | | PortFlag_A := (OTHES => UNDEF);
-- | | | - Updated InternalTimingCheck code
-- 0.19| jdc |042599| - Fixes for bit-writeable cases
-- | | | - Check PortFlag after HandleDataAction
-- | | | in VitalMemoryViolation()
-- 0.20| jdc |042599| - Merge PortFlag changes from Prakash
-- | | | and Willian:
-- | | | VitalMemorySchedulePathDelay()
-- | | | VitalMemoryExpandPortFlag()
-- 0.21| jdc |072199| - Changed VitalCrossPortModeType enums,
-- | | | added new CpReadAndReadContention.
-- | | | - Fixed VitalMemoryCrossPorts() parameter
-- | | | SamePortFlag to INOUT so that it can
-- | | | set CORRUPT or READ value.
-- | | | - Fixed VitalMemoryTable() where PortFlag
-- | | | setting by HandleDataAction() is being
-- | | | ignored when HandleMemoryAction() sets
-- | | | PortFlagTmp to NOCHANGE.
-- | | | - Fixed VitalMemoryViolation() to set
-- | | | all bits of PortFlag when violating.
-- 0.22| jdc |072399| - Added HIGHZ to PortFlagType. HandleData
-- | | | checks whether the previous state is HIGHZ.
-- | | | If yes then portFlag should be NOCHANGE
-- | | | for VMPD to ignore IORetain corruption.
-- | | | The idea is that the first Z should be
-- | | | propagated but later ones should be ignored.
-- | | |
-- 0.23| jdc |100499| - Took code checked in by Dennis 09/28/99
-- | | | - Changed VitalPortFlagType to record of
-- | | | new VitalPortStateType to hold current,
-- | | | previous values and separate disable.
-- | | | Also created VitalDefaultPortFlag const.
-- | | | Removed usage of PortFlag NOCHANGE
-- | | | - VitalMemoryTable() changes:
-- | | | Optimized return when all curr = prev
-- | | | AddressValue is now INOUT to optimize
-- | | | Transfer PF.MemoryCurrent to MemoryPrevious
-- | | | Transfer PF.DataCurrent to DataPrevious
-- | | | Reset PF.OutputDisable to FALSE
-- | | | Expects PortFlag init in declaration
-- | | | No need to init PortFlag every delta
-- | | | - VitalMemorySchedulePathDelay() changes:
-- | | | Initialize with VitalDefaultPortFlag
-- | | | Check PortFlag.OutputDisable
-- | | | - HandleMemoryAction() changes:
-- | | | Set value of PortFlag.MemoryCurrent
-- | | | Never set PortFlag.OutputDisable
-- | | | - HandleDataAction() changes:
-- | | | Set value of PortFlag.DataCurrent
-- | | | Set PortFlag.DataCurrent for HIGHZ
-- | | | - VitalMemoryCrossPorts() changes:
-- | | | Check/set value of PF.MemoryCurrent
-- | | | Check value of PF.OutputDisable
-- | | | - VitalMemoryViolation() changes:
-- | | | Fixed bug - not reading inout PF value
-- | | | Clean up setting of PortFlag
-- 0.24| jdc |100899| - Modified update of PF.OutputDisable
-- | | | to correctly accomodate 2P1W1R case:
-- | | | the read port should not exhibit
-- | | | IO retain corrupt when reading
-- | | | addr unrelated to addr being written.
-- 0.25| jdc |100999| - VitalMemoryViolation() change:
-- | | | Fixed bug with RDNWR mode incorrectly
-- | | | updating the PF.OutputDisable
-- 0.26| jdc |100999| - VitalMemoryCrossPorts() change:
-- | | | Fixed bugs with update of PF
-- 0.27| jdc |101499| - VitalMemoryCrossPorts() change:
-- | | | Added DoRdWrCont message (ErrMcpRdWrCo,
-- | | | Memory cross port read/write data only
-- | | | contention)
-- | | | - VitalMemoryTable() change:
-- | | | Set PF.OutputDisable := TRUE for the
-- | | | optimized cases.
-- 0.28| pb |112399| - Added 8 VMPD procedures for vector
-- | | | PathCondition support. Now the total
-- | | | number of overloadings for VMPD is 24.
-- | | | - Number of overloadings for SetupHold
-- | | | procedures increased to 5. Scalar violations
-- | | | are not supported anymore. Vector checkEnabled
-- | | | support is provided through the new overloading
-- 0.29| jdc |120999| - HandleMemoryAction() HandleDataAction()
-- | | | Reinstated 'D' and 'E' actions but
-- | | | with new PortFlagType
-- | | | - Updated file handling syntax, must compile
-- | | | with -93 syntax now.
-- 0.30| jdc |022300| - Formated for 80 column max width
-- ----------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.Vital_Timing.all;
USE IEEE.Vital_Primitives.all;
LIBRARY STD;
USE STD.TEXTIO.ALL;
-- ----------------------------------------------------------------------------
PACKAGE BODY Vital_Memory IS
-- ----------------------------------------------------------------------------
-- Timing Section
-- ----------------------------------------------------------------------------
FILE LogFile : TEXT OPEN write_mode IS "delayLog";
FILE Output : TEXT OPEN write_mode IS "STD_OUTPUT";
-- Added for turning off the debug msg..
CONSTANT PrintDebugMsg : STD_ULOGIC := '0';
-- '0' - don't print in STD OUTPUT
-- '1' - print in STD OUTPUT
-- Type and constant definitions for type conversion.
TYPE MVL9_TO_CHAR_TBL IS ARRAY (STD_ULOGIC) OF character;
--constant MVL9_to_char: MVL9_TO_CHAR_TBL := "UX01ZWLH-";
CONSTANT MVL9_to_char: MVL9_TO_CHAR_TBL := "XX01ZX010";
-- ----------------------------------------------------------------------------
-- STD_LOGIC WRITE UTILITIES
-- ----------------------------------------------------------------------------
PROCEDURE WRITE(
l : INOUT line;
val : IN std_logic_vector;
justify : IN side := right;
field : IN width := 0
) IS
VARIABLE invect : std_logic_vector(val'LENGTH DOWNTO 1);
VARIABLE ins : STRING(val'LENGTH DOWNTO 1);
BEGIN
invect := val;
FOR I IN invect'length DOWNTO 1 LOOP
ins(I) := MVL9_to_char(invect(I));
END LOOP;
WRITE(L, ins, justify, field);
END;
PROCEDURE WRITE(
l : INOUT line;
val : IN std_ulogic;
justify : IN side := right;
field : in width := 0
) IS
VARIABLE ins : CHARACTER;
BEGIN
ins := MVL9_to_char(val);
WRITE(L, ins, justify, field);
END;
-- ----------------------------------------------------------------------------
PROCEDURE DelayValue(
InputTime : IN TIME ;
outline : INOUT LINE
) IS
CONSTANT header : STRING := "TIME'HIGH";
BEGIN
IF(InputTime = TIME'HIGH) THEN
WRITE(outline, header);
ELSE
WRITE(outline, InputTime);
END IF;
END DelayValue;
-- ----------------------------------------------------------------------------
PROCEDURE PrintScheduleDataArray (
ScheduleDataArray : IN VitalMemoryScheduleDataVectorType
) IS
VARIABLE outline1 : LINE;
VARIABLE outline2 : LINE;
VARIABLE value : TIME;
CONSTANT empty : STRING := " ";
CONSTANT header1 : STRING := "i Age PropDly RetainDly";
CONSTANT header2 : STRING := "i Sc.Value Output Lastvalue Sc.Time";
BEGIN
WRITE (outline1, empty);
WRITE (outline1, NOW);
outline2 := outline1;
WRITELINE (LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITE (outline1, header1);
outline2 := outline1;
WRITELINE (LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
FOR i IN ScheduleDataArray'RANGE LOOP
WRITE (outline1, i );
WRITE (outline1, empty);
DelayValue(ScheduleDataArray(i).InputAge, outline1);
WRITE (outline1, empty);
DelayValue(ScheduleDataArray(i).PropDelay, outline1);
WRITE (outline1, empty);
DelayValue(ScheduleDataArray(i).OutputRetainDelay, outline1);
outline2 := outline1;
WRITELINE (LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
END LOOP;
WRITE (outline1, header2);
outline2 := outline1;
WRITELINE (LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
FOR i IN ScheduleDataArray'RANGE LOOP
WRITE (outline1, i );
WRITE (outline1, empty);
WRITE (outline1, ScheduleDataArray(i).ScheduleValue);
WRITE (outline1, empty);
WRITE (outline1, ScheduleDataArray(i).OutputData);
WRITE (outline1, empty);
WRITE (outline1, ScheduleDataArray(i).LastOutputValue );
WRITE (outline1, empty);
DelayValue(ScheduleDataArray(i).ScheduleTime, outline1);
outline2 := outline1;
WRITELINE (LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
END LOOP;
WRITE (outline1, empty);
WRITE (outline2, empty);
WRITELINE (LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (Output, outline2);
END IF;
END PrintScheduleDataArray;
-- ----------------------------------------------------------------------------
PROCEDURE PrintArcType (
ArcType : IN VitalMemoryArcType
) IS
VARIABLE outline1, outline2 : LINE;
CONSTANT empty : STRING := " ";
CONSTANT cross : STRING := "CrossArc";
CONSTANT para : STRING := "ParallelArc";
CONSTANT sub : STRING := "SubWordArc";
CONSTANT Header1 : STRING := "Path considered @ ";
CONSTANT Header2 : STRING := " is ";
BEGIN
WRITELINE (LogFile, outline1);
WRITE (outline1, header1);
WRITE (outline1, NOW);
WRITE (outline1, empty);
WRITE (outline1, header2);
WRITE (outline1, empty);
case ArcType is
WHEN CrossArc =>
WRITE (outline1, cross);
WHEN ParallelArc =>
WRITE (outline1, para);
WHEN SubwordArc =>
WRITE (outline1, sub);
END CASE;
outline2 := outline1 ;
-- Appears on STD OUT
IF (PrintDebugMsg = '1') THEN
WRITELINE (Output, outline1);
END IF;
WRITELINE (LogFile, outline2);
END PrintArcType;
-- ----------------------------------------------------------------------------
-- This returns the value picked from the delay array
-- ----------------------------------------------------------------------------
PROCEDURE PrintDelay (
outbitpos : IN INTEGER;
InputArrayLow : IN INTEGER;
InputArrayHigh : IN INTEGER;
debugprop : IN VitalTimeArrayT;
debugretain : IN VitalTimeArrayT
) IS
VARIABLE outline1 : LINE;
VARIABLE outline2 : LINE;
VARIABLE outline3 : LINE;
VARIABLE outline4 : LINE;
VARIABLE outline5 : LINE;
VARIABLE outline6 : LINE;
CONSTANT empty : STRING := " ";
CONSTANT empty5 : STRING := " ";
CONSTANT header1 : STRING := "Prop. delays : ";
CONSTANT header2 : STRING := "Retain delays : ";
CONSTANT header3 : STRING := "output bit : ";
BEGIN
WRITE(outline1, header3);
WRITE(outline1, outbitpos);
outline2 := outline1;
WRITELINE(LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE(output, outline2);
END IF;
WRITE(outline1, header1);
WRITE (outline1, empty5);
FOR i IN InputArrayHigh DOWNTO InputArrayLow LOOP
DelayValue(debugprop(i), outline1);
WRITE(outline1, empty);
END LOOP;
outline2 := outline1;
WRITELINE(LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE(output, outline2);
END IF;
WRITE(outline1, header2);
WRITE (outline1, empty5);
FOR i in InputArrayHigh DOWNTO InputArrayLow LOOP
DelayValue(debugretain(i), outline1);
WRITE(outline1, empty);
END LOOP;
outline2 := outline1;
WRITELINE(LogFile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE(output, outline2);
END IF;
END PrintDelay;
-- ----------------------------------------------------------------------------
PROCEDURE DebugMsg1 IS
CONSTANT header1:STRING:= "******************************************";
CONSTANT header2 :STRING:="Entering the process because of an i/p change";
variable outline1, outline2 : LINE;
BEGIN
WRITE(outline1, header1);
outline2 := outline1;
WRITELINE (Logfile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITE(outline1, header2);
outline2 := outline1;
WRITELINE (Logfile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITE(outline1, header1);
outline2 := outline1;
WRITELINE (Logfile, outline1);
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
END DebugMsg1;
-- ----------------------------------------------------------------------------
PROCEDURE ScheduleDebugMsg IS
CONSTANT header1 : STRING := "******************************************";
CONSTANT header2 : STRING := "Finished executing all the procedures";
VARIABLE outline1 : LINE;
VARIABLE outline2 : LINE;
BEGIN
WRITE(outline1, header1);
outline2 := outline1;
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITELINE (Logfile, outline1);
WRITE(outline1, header2);
outline2 := outline1;
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITELINE (Logfile, outline1);
WRITE(outline1, header1);
outline2 := outline1;
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITELINE (Logfile, outline1);
END ScheduleDebugMsg;
-- ----------------------------------------------------------------------------
PROCEDURE PrintInputName(
InputSignalName : IN STRING
) IS
VARIABLE outline1 : LINE;
VARIABLE outline2 : LINE;
CONSTANT header1 : STRING := "***Changing input is ";
CONSTANT header2 : STRING := "(";
CONSTANT header3 : STRING := ")";
CONSTANT header4 : STRING := "****";
CONSTANT header5 : STRING := "******************************************";
CONSTANT header6 : STRING:="Entering the process because of an i/p change";
CONSTANT empty : STRING := " ";
BEGIN
WRITE(outline1, header5);
outline2 := outline1;
WRITELINE (output, outline1);
WRITELINE (Logfile, outline2);
WRITE(outline1, header6);
outline2 := outline1;
WRITELINE (output, outline1);
WRITELINE (Logfile, outline2);
WRITE(outline1, header5);
outline2 := outline1;
WRITELINE (output, outline1);
WRITELINE (Logfile, outline2);
WRITE(outline1, header1);
WRITE(outline1, InputSignalName);
WRITE(outline1, empty);
WRITE(outline1, now);
WRITE(outline1, empty);
WRITE(outline1, header4);
WRITELINE (output, outline1);
WRITELINE (Logfile, outline2);
END PrintInputName;
-- ----------------------------------------------------------------------------
PROCEDURE PrintInputChangeTime(
ChangeTimeArray : IN VitalTimeArrayT
) IS
VARIABLE outline1 : LINE;
VARIABLE outline2 : LINE;
CONSTANT header5 : STRING := "*************************************";
CONSTANT header6 : STRING:="ChangeTime Array : ";
CONSTANT empty : STRING := " ";
BEGIN
WRITE(outline1, header5);
outline2 := outline1;
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITELINE (Logfile, outline1);
WRITE(outline1, header6);
FOR i in ChangeTimeArray'range LOOP
WRITE(outline1, ChangeTimeArray(i));
WRITE(outline1, empty);
END LOOP;
outline2 := outline1;
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITELINE (Logfile, outline1);
WRITE(outline1, header5);
outline2 := outline1;
IF (PrintDebugMsg = '1') THEN
WRITELINE (output, outline2);
END IF;
WRITELINE (Logfile, outline1);
END PrintInputChangeTime;
-- ----------------------------------------------------------------------------
PROCEDURE PrintInputChangeTime(
ChangeTime : IN Time
) IS
VARIABLE ChangeTimeArray : VitalTimeArrayT(0 DOWNTO 0);
BEGIN
ChangeTimeArray(0) := ChangeTime;
PrintInputChangeTime(ChangeTimeArray);
END PrintInputChangeTime;
-- ----------------------------------------------------------------------------
-- for debug purpose
CONSTANT MaxNoInputBits : INTEGER := 1000;
TYPE VitalMemoryDelayType IS RECORD
PropDelay : TIME;
OutputRetainDelay : TIME;
END RECORD;
-- ----------------------------------------------------------------------------
-- PROCEDURE: IntToStr
--
-- PARAMETERS: InputInt - Integer to be converted to String.
-- ResultStr - String buffer for converted Integer
-- AppendPos - Position in buffer to place result
--
-- DESCRIPTION: This procedure is used to convert an input integer
-- into a string representation. The converted string
-- may be placed at a specific position in the result
-- buffer.
--
-- ----------------------------------------------------------------------------
PROCEDURE IntToStr (
InputInt : IN INTEGER ;
ResultStr : INOUT STRING ( 1 TO 256) ;
AppendPos : INOUT NATURAL
) IS
-- Look-up table. Given an int, we can get the character.
TYPE integer_table_type IS ARRAY (0 TO 9) OF CHARACTER ;
CONSTANT integer_table : integer_table_type :=
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ;
-- Local variables used in this function.
VARIABLE inpVal : INTEGER := inputInt ;
VARIABLE divisor : INTEGER := 10 ;
VARIABLE tmpStrIndex : INTEGER := 1 ;
VARIABLE tmpStr : STRING ( 1 TO 256 ) ;
BEGIN
IF ( inpVal = 0 ) THEN
tmpStr(tmpStrIndex) := integer_table ( 0 ) ;
tmpStrIndex := tmpStrIndex + 1 ;
ELSE
WHILE ( inpVal > 0 ) LOOP
tmpStr(tmpStrIndex) := integer_table (inpVal mod divisor);
tmpStrIndex := tmpStrIndex + 1 ;
inpVal := inpVal / divisor ;
END LOOP ;
END IF ;
IF (appendPos /= 1 ) THEN
resultStr(appendPos) := ',' ;
appendPos := appendPos + 1 ;
END IF ;
FOR i IN tmpStrIndex-1 DOWNTO 1 LOOP
resultStr(appendPos) := tmpStr(i) ;
appendPos := appendPos + 1 ;
END LOOP ;
END IntToStr ;
-- ----------------------------------------------------------------------------
TYPE CheckType IS (
SetupCheck,
HoldCheck,
RecoveryCheck,
RemovalCheck,
PulseWidCheck,
PeriodCheck
);
TYPE CheckInfoType IS RECORD
Violation : BOOLEAN;
CheckKind : CheckType;
ObsTime : TIME;
ExpTime : TIME;
DetTime : TIME;
State : X01;
END RECORD;
TYPE LogicCvtTableType IS ARRAY (std_ulogic) OF CHARACTER;
TYPE HiLoStrType IS ARRAY (std_ulogic RANGE 'X' TO '1') OF STRING(1 TO 4);
CONSTANT LogicCvtTable : LogicCvtTableType
:= ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-');
CONSTANT HiLoStr : HiLoStrType := (" X ", " Low", "High" );
TYPE EdgeSymbolMatchType IS ARRAY (X01,X01,VitalEdgeSymbolType) OF BOOLEAN;
-- last value, present value, edge symbol
CONSTANT EdgeSymbolMatch : EdgeSymbolMatchType :=
(
'X' =>
( 'X'=>( OTHERS => FALSE),
'0'=>('N'|'F'|'v'|'E'|'D'|'*' => TRUE, OTHERS => FALSE ),
'1'=>('P'|'R'|'^'|'E'|'A'|'*' => TRUE, OTHERS => FALSE )
),
'0' =>
( 'X'=>( 'r'|'p'|'R'|'A'|'*' => TRUE, OTHERS => FALSE ),
'0'=>( OTHERS => FALSE ),
'1'=>( '/'|'P'|'p'|'R'|'*' => TRUE, OTHERS => FALSE )
),
'1' =>
( 'X'=>( 'f'|'n'|'F'|'D'|'*' => TRUE, OTHERS => FALSE ),
'0'=>( '\'|'N'|'n'|'F'|'*' => TRUE, OTHERS => FALSE ),
'1'=>( OTHERS => FALSE )
)
);
-- ----------------------------------------------------------------------------
FUNCTION Minimum (
CONSTANT t1, t2 : IN TIME
) RETURN TIME IS
BEGIN
IF (t1 < t2) THEN RETURN (t1); ELSE RETURN (t2); END IF;
END Minimum;
-- ----------------------------------------------------------------------------
FUNCTION Maximum (
CONSTANT t1, t2 : IN TIME
) RETURN TIME IS
BEGIN
IF (t1 < t2) THEN RETURN (t2); ELSE RETURN (t1); END IF;
END Maximum;
-- ----------------------------------------------------------------------------
-- FUNCTION: VitalMemoryCalcDelay
-- Description: Select Transition dependent Delay.
-- Used internally by VitalMemorySelectDelay.
-- ----------------------------------------------------------------------------
FUNCTION VitalMemoryCalcDelay (
CONSTANT NewVal : IN STD_ULOGIC := 'X';
CONSTANT OldVal : IN STD_ULOGIC := 'X';
CONSTANT Delay : IN VitalDelayType01ZX
) RETURN VitalMemoryDelayType IS
VARIABLE Result : VitalMemoryDelayType;
BEGIN
CASE Oldval IS
WHEN '0' | 'L' =>
CASE Newval IS
WHEN '0' | 'L' =>
Result.PropDelay := Delay(tr10);
WHEN '1' | 'H' =>
Result.PropDelay := Delay(tr01);
WHEN 'Z' =>
Result.PropDelay := Delay(tr0Z);
WHEN OTHERS =>
Result.PropDelay := Minimum(Delay(tr01), Delay(tr0Z));
END CASE;
Result.OutputRetainDelay := Delay(tr0X);
WHEN '1' | 'H' =>
CASE Newval IS
WHEN '0' | 'L' =>
Result.PropDelay := Delay(tr10);
WHEN '1' | 'H' =>
Result.PropDelay := Delay(tr01);
WHEN 'Z' =>
Result.PropDelay := Delay(tr1Z);
WHEN OTHERS =>
Result.PropDelay := Minimum(Delay(tr10), Delay(tr1Z));
END CASE;
Result.OutputRetainDelay := Delay(tr1X);
WHEN 'Z' =>
CASE Newval IS
WHEN '0' | 'L' =>
Result.PropDelay := Delay(trZ0);
WHEN '1' | 'H' =>
Result.PropDelay := Delay(trZ1);
WHEN 'Z' =>
Result.PropDelay := Maximum(Delay(tr1Z), Delay(tr0Z));
WHEN OTHERS =>
Result.PropDelay := Minimum(Delay(trZ1), Delay(trZ0));
END CASE;
Result.OutputRetainDelay := Delay(trZX);
WHEN OTHERS =>
CASE Newval IS
WHEN '0' | 'L' =>
Result.PropDelay := Maximum(Delay(tr10), Delay(trZ0));
WHEN '1' | 'H' =>
Result.PropDelay := Maximum(Delay(tr01), Delay(trZ1));
WHEN 'Z' =>
Result.PropDelay := Maximum(Delay(tr1Z), Delay(tr0Z));
WHEN OTHERS =>
Result.PropDelay := Maximum(Delay(tr10), Delay(tr01));
END CASE;
Result.OutputRetainDelay := Minimum(Delay(tr1X), Delay(tr0X));
END CASE;
RETURN Result;
END VitalMemoryCalcDelay;
-- ----------------------------------------------------------------------------
FUNCTION VitalMemoryCalcDelay (
CONSTANT NewVal : IN STD_ULOGIC := 'X';
CONSTANT OldVal : IN STD_ULOGIC := 'X';
CONSTANT Delay : IN VitalDelayType01Z
) RETURN VitalMemoryDelayType IS
VARIABLE Result : VitalMemoryDelayType;
BEGIN
CASE Oldval IS
WHEN '0' | 'L' =>
CASE Newval IS
WHEN '0' | 'L' => Result.PropDelay := Delay(tr10);
WHEN '1' | 'H' => Result.PropDelay := Delay(tr01);
WHEN OTHERS =>
Result.PropDelay := Minimum(Delay(tr01), Delay(tr10));
END CASE;
Result.OutputRetainDelay := Delay(tr0Z);
WHEN '1' | 'H' =>
CASE Newval IS
WHEN '0' | 'L' => Result.PropDelay := Delay(tr10);
WHEN '1' | 'H' => Result.PropDelay := Delay(tr01);
WHEN OTHERS =>
Result.PropDelay := Minimum(Delay(tr10), Delay(tr01));
END CASE;
Result.OutputRetainDelay := Delay(tr1Z);
WHEN OTHERS =>
Result.PropDelay := Maximum(Delay(tr10),Delay(tr01));
Result.OutputRetainDelay := Minimum(Delay(tr1Z),Delay(tr0Z));
END CASE;
RETURN Result;
END VitalMemoryCalcDelay;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryUpdateInputChangeTime (
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
VARIABLE NumBitsPerSubword : INTEGER
) IS
VARIABLE LastInputValue : STD_LOGIC_VECTOR(InputSignal'LENGTH-1 downto 0);
VARIABLE InSignalNorm : STD_LOGIC_VECTOR(InputSignal'LENGTH-1 downto 0);
VARIABLE ChangeTimeNorm : VitalTimeArrayT(InputSignal'LENGTH-1 downto 0);
VARIABLE BitsPerWord : INTEGER;
BEGIN
LastInputValue := InputSignal'LAST_VALUE;
IF NumBitsPerSubword = DefaultNumBitsPerSubword THEN
BitsPerWord := InputSignal'LENGTH;
ELSE
BitsPerWord := NumBitsPerSubword;
END IF;
FOR i IN InSignalNorm'RANGE LOOP
IF (InSignalNorm(i) /= LastInputValue(i)) THEN
ChangeTimeNorm(i/BitsPerWord) := NOW - InputSignal'LAST_EVENT;
ELSE
ChangeTimeNorm(i/BitsPerWord) := InputChangeTimeArray(i);
END IF;
END LOOP;
FOR i IN ChangeTimeNorm'RANGE LOOP
ChangeTimeNorm(i) := ChangeTimeNorm(i/BitsPerword);
END LOOP;
InputChangeTimeArray := ChangeTimeNorm;
-- for debug purpose only
PrintInputChangeTime(InputChangeTimeArray);
END VitalMemoryUpdateInputChangeTime;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemoryUpdateInputChangeTime
-- Description: Time since previous event for each bit of the input
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryUpdateInputChangeTime (
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR
) IS
VARIABLE LastInputValue : STD_LOGIC_VECTOR(InputSignal'RANGE) ;
BEGIN
LastInputValue := InputSignal'LAST_VALUE;
FOR i IN InputSignal'RANGE LOOP
IF (InputSignal(i) /= LastInputValue(i)) THEN
InputChangeTimeArray(i) := NOW - InputSignal'LAST_EVENT;
END IF;
END LOOP;
-- for debug purpose only
PrintInputChangeTime(InputChangeTimeArray);
END VitalMemoryUpdateInputChangeTime;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryUpdateInputChangeTime (
VARIABLE InputChangeTime : INOUT TIME;
SIGNAL InputSignal : IN STD_ULOGIC
) IS
BEGIN
InputChangeTime := NOW - InputSignal'LAST_EVENT;
-- for debug purpose only
PrintInputChangeTime(InputChangeTime);
END VitalMemoryUpdateInputChangeTime;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryExpandPortFlag (
CONSTANT PortFlag : IN VitalPortFlagVectorType;
CONSTANT NumBitsPerSubword : IN INTEGER;
VARIABLE ExpandedPortFlag : OUT VitalPortFlagVectorType
) IS
VARIABLE PortFlagNorm : VitalPortFlagVectorType(
PortFlag'LENGTH-1 downto 0) := PortFlag;
VARIABLE ExpandedPortFlagNorm : VitalPortFlagVectorType(
ExpandedPortFlag'LENGTH-1 downto 0);
VARIABLE SubwordIndex : INTEGER;
BEGIN
FOR Index IN INTEGER RANGE 0 to ExpandedPortFlag'LENGTH-1 LOOP
IF NumBitsPerSubword = DefaultNumBitsPerSubword THEN
SubwordIndex := 0;
ELSE
SubwordIndex := Index / NumBitsPerSubword;
END IF;
ExpandedPortFlagNorm(Index) := PortFlagNorm(SubWordIndex);
END LOOP;
ExpandedPortFlag := ExpandedPortFlagNorm;
END VitalMemoryExpandPortFlag;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemorySelectDelay
-- Description : Select Propagation Delay. Used internally by
-- VitalMemoryAddPathDelay.
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- VitalDelayArrayType01ZX
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySelectDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
VARIABLE InputChangeTimeArray : IN VitalTimeArrayT;
CONSTANT OutputSignalName : IN STRING :="";
CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX;
CONSTANT ArcType : IN VitalMemoryArcType;
CONSTANT PathConditionArray : IN VitalBoolArrayT;
CONSTANT OutputRetainFlag : IN BOOLEAN
) IS
VARIABLE InputArrayLow : INTEGER := 0;
VARIABLE InputArrayHigh : INTEGER := 0;
VARIABLE DelayArrayIndex : INTEGER := 0;
VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword;
VARIABLE NewValue : STD_ULOGIC;
VARIABLE OldValue : STD_ULOGIC;
VARIABLE OutputLength : INTEGER := 0;
VARIABLE OutArrayIndex : INTEGER;
VARIABLE PropDelay : TIME;
VARIABLE RetainDelay : TIME;
VARIABLE CurPropDelay : TIME;
VARIABLE CurRetainDelay : TIME;
VARIABLE InputAge : TIME;
VARIABLE CurInputAge : TIME;
VARIABLE InputChangeTimeNorm : VitalTimeArrayT(
InputChangeTimeArray'LENGTH-1 downto 0):=InputChangeTimeArray;
VARIABLE DelayArrayNorm : VitalDelayArrayType01ZX(
PathDelayArray'LENGTH-1 downto 0):= PathDelayArray;
VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType
(ScheduleDataArray'LENGTH-1 downto 0):= ScheduleDataArray;
-- for debug purpose
VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
BEGIN
-- for debug purpose
PrintArcType(ArcType);
OutputLength := ScheduleDataArray'LENGTH;
FOR OutBitPos IN 0 to (OutputLength -1) LOOP
NEXT WHEN PathConditionArray(OutBitPos) = FALSE;
NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue
= ScheduleDataArrayNorm(OutBitPos).OutputData) AND
(ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW) AND
(OutputRetainFlag = FALSE ));
NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData;
OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue;
PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay;
InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge;
RetainDelay:=ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay;
NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord;
CASE ArcType IS
WHEN ParallelArc =>
InputArrayLow := OutBitPos;
InputArrayHigh := OutBitPos;
DelayArrayIndex := OutBitPos;
WHEN CrossArc =>
InputArrayLow := 0;
InputArrayHigh := InputChangeTimeArray'LENGTH - 1 ;
DelayArrayIndex := OutBitPos;
WHEN SubwordArc =>
InputArrayLow := OutBitPos / NumBitsPerSubWord;
InputArrayHigh := OutBitPos / NumBitsPerSubWord;
DelayArrayIndex := OutBitPos +
(OutputLength * (OutBitPos / NumBitsPerSubWord));
END CASE;
FOR i IN InputArrayLow TO InputArrayHigh LOOP
(CurPropDelay,CurRetainDelay) :=
VitalMemoryCalcDelay (
NewValue, OldValue, DelayArrayNorm(DelayArrayIndex)
);
IF (OutputRetainFlag = FALSE) THEN
CurRetainDelay := TIME'HIGH;
END IF;
-- for debug purpose
debugprop(i) := CurPropDelay;
debugretain(i) := CurRetainDelay;
IF ArcType = CrossArc THEN
DelayArrayIndex := DelayArrayIndex + OutputLength;
END IF;
-- If there is one input change at a time, then choose the
-- delay from that input. If there is simultaneous input
-- change, then choose the minimum of propagation delays
IF (InputChangeTimeNorm(i) < 0 ns)THEN
CurInputAge := TIME'HIGH;
ELSE
CurInputAge := NOW - InputChangeTimeNorm(i);
END IF;
IF (CurInputAge < InputAge)THEN
PropDelay := CurPropDelay;
RetainDelay := CurRetainDelay;
InputAge := CurInputAge;
ELSIF (CurInputAge = InputAge)THEN
IF (CurPropDelay < PropDelay) THEN
PropDelay := CurPropDelay;
END IF;
IF (OutputRetainFlag = TRUE) THEN
IF (CurRetainDelay < RetainDelay) THEN
RetainDelay := CurRetainDelay;
END IF;
END IF;
END IF;
END LOOP;
-- Store it back to data strucutre
ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay;
ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay:= RetainDelay;
ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge;
-- for debug purpose
PrintDelay(outbitPos,InputArrayLow, InputArrayHigh,
debugprop, debugretain);
END LOOP;
ScheduleDataArray := ScheduleDataArrayNorm;
END VitalMemorySelectDelay;
-- ----------------------------------------------------------------------------
-- VitalDelayArrayType01Z
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySelectDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
VARIABLE InputChangeTimeArray : IN VitalTimeArrayT;
CONSTANT OutputSignalName : IN STRING :="";
CONSTANT PathDelayArray : IN VitalDelayArrayType01Z;
CONSTANT ArcType : IN VitalMemoryArcType;
CONSTANT PathConditionArray : IN VitalBoolArrayT;
CONSTANT OutputRetainFlag : IN BOOLEAN
) IS
VARIABLE InputArrayLow : INTEGER := 0;
VARIABLE InputArrayHigh : INTEGER := 0;
VARIABLE DelayArrayIndex : INTEGER := 0;
VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword;
VARIABLE NewValue : STD_ULOGIC;
VARIABLE OldValue : STD_ULOGIC;
VARIABLE OutputLength : INTEGER := 0;
VARIABLE OutArrayIndex : INTEGER;
VARIABLE PropDelay : TIME;
VARIABLE RetainDelay : TIME;
VARIABLE CurPropDelay : TIME;
VARIABLE CurRetainDelay : TIME;
VARIABLE InputAge : TIME;
VARIABLE CurInputAge : TIME;
VARIABLE InputChangeTimeNorm : VitalTimeArrayT(
InputChangeTimeArray'LENGTH-1 downto 0):=InputChangeTimeArray;
VARIABLE DelayArrayNorm : VitalDelayArrayType01Z(
PathDelayArray'LENGTH-1 downto 0):= PathDelayArray;
VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType
(ScheduleDataArray'LENGTH-1 downto 0):=ScheduleDataArray;
-- for debug purpose
VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
BEGIN
-- for debug purpose
PrintArcType(ArcType);
OutputLength := ScheduleDataArray'LENGTH;
FOR OutBitPos IN 0 to (OutputLength -1) LOOP
NEXT WHEN PathConditionArray(OutBitPos) = FALSE;
NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue
= ScheduleDataArrayNorm(OutBitPos).OutputData) AND
(ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW) AND
(OutputRetainFlag = FALSE));
NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData;
OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue;
PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay;
InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge;
RetainDelay:=ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay;
NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord;
CASE ArcType IS
WHEN ParallelArc =>
InputArrayLow := OutBitPos;
InputArrayHigh := OutBitPos;
DelayArrayIndex := OutBitPos;
WHEN CrossArc =>
InputArrayLow := 0;
InputArrayHigh := InputChangeTimeArray'LENGTH-1;
DelayArrayIndex := OutBitPos;
WHEN SubwordArc =>
InputArrayLow := OutBitPos / NumBitsPerSubWord;
InputArrayHigh := OutBitPos / NumBitsPerSubWord;
DelayArrayIndex := OutBitPos +
(OutputLength * (OutBitPos / NumBitsPerSubWord));
END CASE;
FOR i IN InputArrayLow TO InputArrayHigh LOOP
(CurPropDelay, CurRetainDelay) :=
VitalMemoryCalcDelay (
NewValue, OldValue, DelayArrayNorm(DelayArrayIndex)
);
IF (OutputRetainFlag = FALSE) THEN
CurRetainDelay := TIME'HIGH;
END IF;
-- for debug purpose
debugprop(i) := CurPropDelay;
debugretain(i) := CurRetainDelay;
IF (ArcType = CrossArc) THEN
DelayArrayIndex := DelayArrayIndex + OutputLength;
END IF;
-- If there is one input change at a time, then choose the
-- delay from that input. If there is simultaneous input
-- change, then choose the minimum of propagation delays
IF (InputChangeTimeNorm(i) < 0 ns) THEN
CurInputAge := TIME'HIGH;
ELSE
CurInputAge := NOW - InputChangeTimeNorm(i);
END IF;
IF (CurInputAge < InputAge) THEN
PropDelay := CurPropDelay;
RetainDelay := CurRetainDelay;
InputAge := CurInputAge;
ELSIF (CurInputAge = InputAge) THEN
IF (CurPropDelay < PropDelay) THEN
PropDelay := CurPropDelay;
END IF;
IF (OutputRetainFlag = TRUE) THEN
IF (CurRetainDelay < RetainDelay) THEN
RetainDelay := CurRetainDelay;
END IF;
END IF;
END IF;
END LOOP;
-- Store it back to data strucutre
ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay;
ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay:= RetainDelay;
ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge;
-- for debug purpose
PrintDelay(outbitPos, InputArrayLow, InputArrayHigh,
debugprop, debugretain);
END LOOP;
ScheduleDataArray := ScheduleDataArrayNorm;
END VitalMemorySelectDelay;
-- ----------------------------------------------------------------------------
-- VitalDelayArrayType01
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySelectDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
VARIABLE InputChangeTimeArray : IN VitalTimeArrayT;
CONSTANT OutputSignalName : IN STRING :="";
CONSTANT PathDelayArray : IN VitalDelayArrayType01;
CONSTANT ArcType : IN VitalMemoryArcType;
CONSTANT PathConditionArray : IN VitalBoolArrayT
) IS
VARIABLE CurPathDelay : VitalMemoryDelayType;
VARIABLE InputArrayLow : INTEGER := 0;
VARIABLE InputArrayHigh : INTEGER := 0;
VARIABLE DelayArrayIndex : INTEGER := 0;
VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword;
VARIABLE NewValue : STD_ULOGIC;
VARIABLE OldValue : STD_ULOGIC;
VARIABLE OutputLength : INTEGER := 0;
VARIABLE OutArrayIndex : INTEGER;
VARIABLE PropDelay : TIME;
VARIABLE CurPropDelay : TIME;
VARIABLE InputAge : TIME;
VARIABLE CurInputAge : TIME;
VARIABLE InputChangeTimeNorm : VitalTimeArrayT(
InputChangeTimeArray'LENGTH-1 downto 0):= InputChangeTimeArray;
VARIABLE DelayArrayNorm : VitalDelayArrayType01(
PathDelayArray'LENGTH-1 downto 0):= PathDelayArray;
VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType
(ScheduleDataArray'LENGTH-1 downto 0):=ScheduleDataArray;
-- for debug purpose
VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
BEGIN
-- for debug purpose
PrintArcType(ArcType);
OutputLength := ScheduleDataArray'LENGTH;
FOR OutBitPos IN 0 to (OutputLength -1) LOOP
NEXT WHEN PathConditionArray(OutBitPos) = FALSE;
NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue
= ScheduleDataArrayNorm(OutBitPos).OutputData) AND
(ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW));
NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData;
OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue;
PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay;
InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge;
NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord;
CASE ArcType IS
WHEN ParallelArc =>
InputArrayLow := OutBitPos;
InputArrayHigh := OutBitPos;
DelayArrayIndex := OutBitPos;
WHEN CrossArc =>
InputArrayLow := 0;
InputArrayHigh := InputChangeTimeArray'LENGTH-1;
DelayArrayIndex := OutBitPos;
WHEN SubwordArc =>
InputArrayLow := OutBitPos / NumBitsPerSubWord;
InputArrayHigh := OutBitPos / NumBitsPerSubWord;
DelayArrayIndex := OutBitPos +
(OutputLength * (OutBitPos / NumBitsPerSubWord));
END CASE;
FOR i IN InputArrayLow TO InputArrayHigh LOOP
CurPropDelay:= VitalCalcDelay (NewValue,
OldValue, DelayArrayNorm(DelayArrayIndex));
-- for debug purpose
debugprop(i) := CurPropDelay;
debugretain(i) := TIME'HIGH;
IF (ArcType = CrossArc) THEN
DelayArrayIndex := DelayArrayIndex + OutputLength;
END IF;
-- If there is one input change at a time, then choose the
-- delay from that input. If there is simultaneous input
-- change, then choose the minimum of propagation delays
IF (InputChangeTimeNorm(i) < 0 ns) THEN
CurInputAge := TIME'HIGH;
ELSE
CurInputAge := NOW - InputChangeTimeNorm(i);
END IF;
IF (CurInputAge < InputAge) THEN
PropDelay := CurPropDelay;
InputAge := CurInputAge;
ELSIF (CurInputAge = InputAge) THEN
IF (CurPropDelay < PropDelay) THEN
PropDelay := CurPropDelay;
END IF;
END IF;
END LOOP;
-- Store it back to data strucutre
ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay;
ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge;
-- for debug purpose
PrintDelay(outbitPos, InputArrayLow, InputArrayHigh,
debugprop, debugretain);
END LOOP;
ScheduleDataArray := ScheduleDataArrayNorm;
END VitalMemorySelectDelay;
-- ----------------------------------------------------------------------------
-- VitalDelayArrayType
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySelectDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
VARIABLE InputChangeTimeArray : IN VitalTimeArrayT;
CONSTANT OutputSignalName : IN STRING :="";
CONSTANT PathDelayArray : IN VitalDelayArrayType;
CONSTANT ArcType : IN VitalMemoryArcType;
CONSTANT PathConditionArray : IN VitalBoolArrayT
) IS
VARIABLE InputArrayLow : INTEGER := 0;
VARIABLE InputArrayHigh : INTEGER := 0;
VARIABLE DelayArrayIndex : INTEGER := 0;
VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword;
VARIABLE NewValue : STD_ULOGIC;
VARIABLE OldValue : STD_ULOGIC;
VARIABLE OutputLength : INTEGER := 0;
VARIABLE OutArrayIndex : INTEGER;
VARIABLE PropDelay : TIME;
VARIABLE CurPropDelay : TIME;
VARIABLE InputAge : TIME;
VARIABLE CurInputAge : TIME;
VARIABLE InputChangeTimeNorm : VitalTimeArrayT(
InputChangeTimeArray'LENGTH-1 downto 0) := InputChangeTimeArray;
VARIABLE DelayArrayNorm : VitalDelayArrayType(
PathDelayArray'LENGTH-1 downto 0) := PathDelayArray;
VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType
(ScheduleDataArray'LENGTH-1 downto 0) := ScheduleDataArray;
-- for debug purpose
VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0);
BEGIN
-- for debug purpose
PrintArcType(ArcType);
OutputLength := ScheduleDataArray'LENGTH;
FOR OutBitPos IN 0 to (OutputLength -1) LOOP
NEXT WHEN PathConditionArray(OutBitPos) = FALSE;
NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue
= ScheduleDataArrayNorm(OutBitPos).OutputData) AND
(ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW));
NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData;
OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue;
PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay;
InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge;
NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord;
CASE ArcType IS
WHEN ParallelArc =>
InputArrayLow := OutBitPos;
InputArrayHigh := OutBitPos;
DelayArrayIndex := OutBitPos;
WHEN CrossArc =>
InputArrayLow := 0;
InputArrayHigh := InputChangeTimeArray'LENGTH-1;
DelayArrayIndex := OutBitPos;
WHEN SubwordArc =>
InputArrayLow := OutBitPos / NumBitsPerSubWord;
InputArrayHigh := OutBitPos / NumBitsPerSubWord;
DelayArrayIndex := OutBitPos +
(OutputLength * (OutBitPos / NumBitsPerSubWord));
END CASE;
FOR i IN InputArrayLow TO InputArrayHigh LOOP
CurPropDelay := VitalCalcDelay (NewValue,
OldValue, DelayArrayNorm(DelayArrayIndex));
-- for debug purpose
debugprop(i) := CurPropDelay;
debugretain(i) := TIME'HIGH;
IF (ArcType = CrossArc) THEN
DelayArrayIndex := DelayArrayIndex + OutputLength;
END IF;
-- If there is one input change at a time, then choose the
-- delay from that input. If there is simultaneous input
-- change, then choose the minimum of propagation delays
IF (InputChangeTimeNorm(i) < 0 ns) THEN
CurInputAge := TIME'HIGH;
ELSE
CurInputAge := NOW - InputChangeTimeNorm(i);
END IF;
IF (CurInputAge < InputAge) THEN
PropDelay := CurPropDelay;
InputAge := CurInputAge;
ELSIF (CurInputAge = InputAge) THEN
IF (CurPropDelay < PropDelay) THEN
PropDelay := CurPropDelay;
END IF;
END IF;
END LOOP;
-- Store it back to data strucutre
ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay;
ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge;
-- for debug purpose
PrintDelay(outbitPos, InputArrayLow, InputArrayHigh,
debugprop, debugretain);
END LOOP;
ScheduleDataArray := ScheduleDataArrayNorm;
END VitalMemorySelectDelay;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemoryInitPathDelay
-- Description: To initialize Schedule Data structure for an
-- output.
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryInitPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
VARIABLE OutputDataArray : IN STD_LOGIC_VECTOR;
CONSTANT NumBitsPerSubWord : IN INTEGER := DefaultNumBitsPerSubword
) IS
BEGIN
-- Initialize the ScheduleData Structure.
FOR i IN OutputDataArray'RANGE LOOP
ScheduleDataArray(i).OutputData := OutputDataArray(i);
ScheduleDataArray(i).PropDelay := TIME'HIGH;
ScheduleDataArray(i).OutputRetainDelay := TIME'HIGH;
ScheduleDataArray(i).InputAge := TIME'HIGH;
ScheduleDataArray(i).NumBitsPerSubWord := NumBitsPerSubWord;
-- Update LastOutputValue of Output if the Output has
-- already been scheduled.
IF ((ScheduleDataArray(i).ScheduleValue /= OutputDataArray(i)) AND
(ScheduleDataArray(i).ScheduleTime <= NOW)) THEN
ScheduleDataArray(i).LastOutputValue
:= ScheduleDataArray(i).ScheduleValue;
END IF;
END LOOP;
-- for debug purpose
DebugMsg1;
PrintScheduleDataArray(ScheduleDataArray);
END VitalMemoryInitPathDelay;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryInitPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
VARIABLE OutputData : IN STD_ULOGIC
) IS
VARIABLE ScheduledataArray: VitalMemoryScheduleDataVectorType
(0 downto 0);
VARIABLE OutputDataArray : STD_LOGIC_VECTOR(0 downto 0);
BEGIN
ScheduledataArray(0) := ScheduleData;
OutputDataArray(0) := OutputData;
VitalMemoryInitPathDelay (
ScheduleDataArray => ScheduleDataArray,
OutputDataArray => OutputDataArray,
NumBitsPerSubWord => DefaultNumBitsPerSubword
);
-- for debug purpose
DebugMsg1;
PrintScheduleDataArray( ScheduleDataArray);
END VitalMemoryInitPathDelay;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemoryAddPathDelay
-- Description: Declare a path for one scalar/vector input to
-- the output for which Schedule Data has been
-- initialized previously.
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- #1
-- DelayType - VitalMemoryDelayType
-- Input - Scalar
-- Output - Scalar
-- Delay - Scalar
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelay : IN VitalDelayType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
) IS
VARIABLE ScheduleDataArray :
VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE PathDelayArray : VitalDelayArrayType(0 downto 0);
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
PathDelayArray(0) := PathDelay;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #2
-- DelayType - VitalMemoryDelayType
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray
);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #3
-- DelayType - VitalMemoryDelayType
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray : IN VitalBoolArrayT
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm :
VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR Mem400
VARIABLE PathConditionArrayExp :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #4
-- DelayType - VitalMemoryDelayType
-- Input - Vector
-- Output - Scalar
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
) IS
VARIABLE ScheduleDataArray : VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #5
-- DelayType - VitalMemoryDelayType
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
) IS
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #6
-- DelayType - VitalMemoryDelayType
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray : IN VitalBoolArrayT
) IS
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm :
VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400;
VARIABLE PathConditionArrayExp :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #7
-- DelayType - VitalMemoryDelayType01
-- Input - Scalar
-- Output - Scalar
-- Delay - Scalar
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelay : IN VitalDelayType01;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
) IS
VARIABLE ScheduleDataArray :
VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE PathDelayArray : VitalDelayArrayType01(0 downto 0);
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
PathDelayArray(0) := PathDelay;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #8
-- DelayType - VitalMemoryDelayType01
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType01;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #9
-- DelayType - VitalMemoryDelayType01
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType01;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray: IN VitalBoolArrayT
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm :
VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400;
VARIABLE PathConditionArrayExp :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #10
-- DelayType - VitalMemoryDelayType01
-- Input - Vector
-- Output - Scalar
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray: INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
)IS
VARIABLE ScheduleDataArray :
VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #11
-- DelayType - VitalMemoryDelayType01
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE
) IS
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #12
-- DelayType - VitalMemoryDelayType01
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray : IN VitalBoolArrayT
) IS
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm :
VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400;
VARIABLE PathConditionArrayExp :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #13
-- DelayType - VitalMemoryDelayType01Z
-- Input - Scalar
-- Output - Scalar
-- Delay - Scalar
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelay : IN VitalDelayType01Z;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE
) IS
VARIABLE ScheduleDataArray :
VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE PathDelayArray : VitalDelayArrayType01Z(0 downto 0);
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
PathDelayArray(0) := PathDelay;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #14
-- DelayType - VitalMemoryDelayType01Z
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType01Z;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #15
-- DelayType - VitalMemoryDelayType01Z
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType01Z;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray: IN VitalBoolArrayT;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm : VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0);
VARIABLE PathConditionArrayExp : VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword := ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #16
-- DelayType - VitalMemoryDelayType01Z
-- Input - Vector
-- Output - Scalar
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01Z;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE;
CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt
) IS
VARIABLE ScheduleDataArray :
VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
NumBitsPerSubword := ScheduleDataArray(0).NumBitsPerSubword;
IF (OutputRetainBehavior = WordCorrupt AND
ArcType = ParallelArc AND
OutputRetainFlag = TRUE) THEN
VitalMemoryUpdateInputChangeTime(
InputChangeTimeArray,
InputSignal,
NumBitsPerSubword
);
ELSE
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
END IF;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #17
-- DelayType - VitalMemoryDelayType01Z
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01Z;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE;
CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt
) IS
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword;
IF (OutputRetainBehavior = WordCorrupt AND
ArcType = ParallelArc AND
OutputRetainFlag = TRUE) THEN
VitalMemoryUpdateInputChangeTime(
InputChangeTimeArray,
InputSignal,
NumBitsPerSubword
);
ELSE
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
END IF;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #18
-- DelayType - VitalMemoryDelayType01Z
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01Z;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray : IN VitalBoolArrayT;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE;
CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt
) IS
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm :
VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0);
VARIABLE PathConditionArrayExp :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword := ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
IF (OutputRetainBehavior = WordCorrupt AND
ArcType = ParallelArc AND
OutputRetainFlag = TRUE) THEN
VitalMemoryUpdateInputChangeTime(
InputChangeTimeArray, InputSignal,
NumBitsPerSubword);
ELSE
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
END IF;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #19
-- DelayType - VitalMemoryDelayType01XZ
-- Input - Scalar
-- Output - Scalar
-- Delay - Scalar
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelay : IN VitalDelayType01ZX;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE
) IS
VARIABLE ScheduleDataArray :
VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE PathDelayArray : VitalDelayArrayType01ZX(0 downto 0);
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
PathDelayArray(0) := PathDelay;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #20
-- DelayType - VitalMemoryDelayType01XZ
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray :INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #21
-- DelayType - VitalMemoryDelayType01XZ
-- Input - Scalar
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray :INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_ULOGIC;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTime : INOUT TIME;
CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray: IN VitalBoolArrayT;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE
) IS
VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0);
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm :
VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400;
VARIABLE PathConditionArrayExp :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal);
InputChangeTimeArray(0) := InputChangeTime;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #22
-- DelayType - VitalMemoryDelayType01XZ
-- Input - Vector
-- Output - Scalar
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE;
CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt
) IS
VARIABLE ScheduleDataArray :
VitalMemoryScheduleDataVectorType(0 downto 0);
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0);
BEGIN
PathConditionArray(0) := PathCondition;
ScheduleDataArray(0) := ScheduleData;
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword;
IF (OutputRetainBehavior = WordCorrupt AND
ArcType = ParallelArc AND
OutputRetainFlag = TRUE) THEN
VitalMemoryUpdateInputChangeTime(
InputChangeTimeArray, InputSignal,
NumBitsPerSubword);
ELSE
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
END IF;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #23
-- DelayType - VitalMemoryDelayType01XZ
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Scalar
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathCondition : IN BOOLEAN := TRUE;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE;
CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt
) IS
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArray :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
FOR i IN PathConditionArray'RANGE LOOP
PathConditionArray(i) := PathCondition;
END LOOP;
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword;
IF (OutputRetainBehavior = WordCorrupt AND
ArcType = ParallelArc AND
OutputRetainFlag = TRUE) THEN
VitalMemoryUpdateInputChangeTime(
InputChangeTimeArray, InputSignal,
NumBitsPerSubword);
ELSE
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
END IF;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArray, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- #24
-- DelayType - VitalMemoryDelayType01XZ
-- Input - Vector
-- Output - Vector
-- Delay - Vector
-- Condition - Vector
PROCEDURE VitalMemoryAddPathDelay (
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType;
SIGNAL InputSignal : IN STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT;
CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT PathConditionArray : IN VitalBoolArrayT;
CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE;
CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt
) IS
VARIABLE NumBitsPerSubword : INTEGER;
VARIABLE PathConditionArrayNorm :
VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400;
VARIABLE PathConditionArrayExp :
VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0);
BEGIN
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword;
FOR i IN PathConditionArrayExp'RANGE LOOP
PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword);
END LOOP;
IF (OutputRetainBehavior = WordCorrupt AND
ArcType = ParallelArc AND
OutputRetainFlag = TRUE) THEN
VitalMemoryUpdateInputChangeTime(
InputChangeTimeArray, InputSignal,
NumBitsPerSubword);
ELSE
VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal);
END IF;
VitalMemorySelectDelay(
ScheduleDataArray, InputChangeTimeArray,
OutputSignalName, PathDelayArray,
ArcType, PathConditionArrayExp, OutputRetainFlag);
END VitalMemoryAddPathDelay;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemorySchedulePathDelay
-- Description: Schedule Output after Propagation Delay selected
-- by checking all the paths added thru'
-- VitalMemoryAddPathDelay.
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySchedulePathDelay (
SIGNAL OutSignal : OUT STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
CONSTANT PortFlag : IN VitalPortFlagType := VitalDefaultPortFlag;
CONSTANT OutputMap : IN VitalOutputMapType:= VitalDefaultOutputMap;
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType
) IS
VARIABLE Age : TIME;
VARIABLE PropDelay : TIME;
VARIABLE RetainDelay : TIME;
VARIABLE Data : STD_ULOGIC;
BEGIN
IF (PortFlag.OutputDisable /= TRUE) THEN
FOR i IN ScheduleDataArray'RANGE LOOP
PropDelay := ScheduleDataArray(i).PropDelay;
RetainDelay := ScheduleDataArray(i).OutputRetainDelay;
NEXT WHEN PropDelay = TIME'HIGH;
Age := ScheduleDataArray(i).InputAge;
Data := ScheduleDataArray(i).OutputData;
IF (Age < RetainDelay and RetainDelay < PropDelay) THEN
OutSignal(i) <= TRANSPORT 'X' AFTER (RetainDelay - Age);
END IF;
IF (Age <= PropDelay) THEN
OutSignal(i)<= TRANSPORT OutputMap(Data)AFTER (PropDelay-Age);
ScheduleDataArray(i).ScheduleValue := Data;
ScheduleDataArray(i).ScheduleTime := NOW + PropDelay - Age;
END IF;
END LOOP;
END IF;
-- for debug purpose
PrintScheduleDataArray(ScheduleDataArray);
-- for debug purpose
ScheduleDebugMsg;
END VitalMemorySchedulePathDelay;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemorySchedulePathDelay
-- Description: Schedule Output after Propagation Delay selected
-- by checking all the paths added thru'
-- VitalMemoryAddPathDelay.
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySchedulePathDelay (
SIGNAL OutSignal : OUT STD_LOGIC_VECTOR;
CONSTANT OutputSignalName : IN STRING :="";
CONSTANT PortFlag : IN VitalPortFlagVectorType;
CONSTANT OutputMap : IN VitalOutputMapType:= VitalDefaultOutputMap;
VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType
) IS
VARIABLE Age : TIME;
VARIABLE PropDelay : TIME;
VARIABLE RetainDelay : TIME;
VARIABLE Data : STD_ULOGIC;
VARIABLE ExpandedPortFlag :
VitalPortFlagVectorType(ScheduleDataArray'RANGE);
VARIABLE NumBitsPerSubword : INTEGER;
BEGIN
NumBitsPerSubword :=
ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword;
VitalMemoryExpandPortFlag( PortFlag, NumBitsPerSubword, ExpandedPortFlag );
FOR i IN ScheduleDataArray'RANGE LOOP
NEXT WHEN ExpandedPortFlag(i).OutputDisable = TRUE;
PropDelay := ScheduleDataArray(i).PropDelay;
RetainDelay := ScheduleDataArray(i).OutputRetainDelay;
NEXT WHEN PropDelay = TIME'HIGH;
Age := ScheduleDataArray(i).InputAge;
Data := ScheduleDataArray(i).OutputData;
IF (Age < RetainDelay and RetainDelay < PropDelay) THEN
OutSignal(i) <= TRANSPORT 'X' AFTER (RetainDelay - Age);
END IF;
IF (Age <= PropDelay) THEN
OutSignal(i)<= TRANSPORT OutputMap(Data)AFTER (PropDelay-Age);
ScheduleDataArray(i).ScheduleValue := Data;
ScheduleDataArray(i).ScheduleTime := NOW + PropDelay - Age;
END IF;
END LOOP;
-- for debug purpose
PrintScheduleDataArray(ScheduleDataArray);
-- for debug purpose
ScheduleDebugMsg;
END VitalMemorySchedulePathDelay;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySchedulePathDelay (
SIGNAL OutSignal : OUT STD_ULOGIC;
CONSTANT OutputSignalName: IN STRING :="";
CONSTANT PortFlag : IN VitalPortFlagType := VitalDefaultPortFlag;
CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap;
VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType
) IS
VARIABLE Age : TIME;
VARIABLE PropDelay : TIME;
VARIABLE RetainDelay : TIME;
VARIABLE Data : STD_ULOGIC;
VARIABLE ScheduleDataArray : VitalMemoryScheduleDataVectorType (0 downto 0);
BEGIN
IF (PortFlag.OutputDisable /= TRUE) THEN
ScheduledataArray(0) := ScheduleData;
PropDelay := ScheduleDataArray(0).PropDelay;
RetainDelay := ScheduleDataArray(0).OutputRetainDelay;
Age := ScheduleDataArray(0).InputAge;
Data := ScheduleDataArray(0).OutputData;
IF (Age < RetainDelay and RetainDelay < PropDelay) THEN
OutSignal <= TRANSPORT 'X' AFTER (RetainDelay - Age);
END IF;
IF (Age <= PropDelay and PropDelay /= TIME'HIGH) THEN
OutSignal <= TRANSPORT OutputMap(Data) AFTER (PropDelay - Age);
ScheduleDataArray(0).ScheduleValue := Data;
ScheduleDataArray(0).ScheduleTime := NOW + PropDelay - Age;
END IF;
END IF;
-- for debug purpose
PrintScheduleDataArray(ScheduleDataArray);
-- for debug purpose
ScheduleDebugMsg;
END VitalMemorySchedulePathDelay;
-- ----------------------------------------------------------------------------
-- Procedure : InternalTimingCheck
-- ----------------------------------------------------------------------------
PROCEDURE InternalTimingCheck (
CONSTANT TestSignal : IN std_ulogic;
CONSTANT RefSignal : IN std_ulogic;
CONSTANT TestDelay : IN TIME := 0 ns;
CONSTANT RefDelay : IN TIME := 0 ns;
CONSTANT SetupHigh : IN TIME := 0 ns;
CONSTANT SetupLow : IN TIME := 0 ns;
CONSTANT HoldHigh : IN TIME := 0 ns;
CONSTANT HoldLow : IN TIME := 0 ns;
VARIABLE RefTime : IN TIME;
VARIABLE RefEdge : IN BOOLEAN;
VARIABLE TestTime : IN TIME;
VARIABLE TestEvent : IN BOOLEAN;
VARIABLE SetupEn : INOUT BOOLEAN;
VARIABLE HoldEn : INOUT BOOLEAN;
VARIABLE CheckInfo : INOUT CheckInfoType;
CONSTANT MsgOn : IN BOOLEAN
) IS
VARIABLE bias : TIME;
VARIABLE actualObsTime : TIME;
VARIABLE BC : TIME;
VARIABLE Message :LINE;
BEGIN
-- Check SETUP constraint
IF (RefEdge) THEN
IF (SetupEn) THEN
CheckInfo.ObsTime := RefTime - TestTime;
CheckInfo.State := To_X01(TestSignal);
CASE CheckInfo.State IS
WHEN '0' =>
CheckInfo.ExpTime := SetupLow;
-- start of new code IR245-246
BC := HoldHigh;
-- end of new code IR245-246
WHEN '1' =>
CheckInfo.ExpTime := SetupHigh;
-- start of new code IR245-246
BC := HoldLow;
-- end of new code IR245-246
WHEN 'X' =>
CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow);
-- start of new code IR245-246
BC := Maximum(HoldHigh,HoldLow);
-- end of new code IR245-246
END CASE;
-- added the second condition for IR 245-246
CheckInfo.Violation :=
((CheckInfo.ObsTime < CheckInfo.ExpTime)
AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns))));
-- start of new code IR245-246
IF (CheckInfo.ExpTime = 0 ns) THEN
CheckInfo.CheckKind := HoldCheck;
ELSE
CheckInfo.CheckKind := SetupCheck;
END IF;
-- end of new code IR245-246
SetupEn := FALSE;
ELSE
CheckInfo.Violation := FALSE;
END IF;
-- Check HOLD constraint
ELSIF (TestEvent) THEN
IF HoldEn THEN
CheckInfo.ObsTime := TestTime - RefTime;
CheckInfo.State := To_X01(TestSignal);
CASE CheckInfo.State IS
WHEN '0' =>
CheckInfo.ExpTime := HoldHigh;
-- new code for unnamed IR
CheckInfo.State := '1';
-- start of new code IR245-246
BC := SetupLow;
-- end of new code IR245-246
WHEN '1' =>
CheckInfo.ExpTime := HoldLow;
-- new code for unnamed IR
CheckInfo.State := '0';
-- start of new code IR245-246
BC := SetupHigh;
-- end of new code IR245-246
WHEN 'X' =>
CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow);
-- start of new code IR245-246
BC := Maximum(SetupHigh,SetupLow);
-- end of new code IR245-246
END CASE;
-- added the second condition for IR 245-246
CheckInfo.Violation :=
((CheckInfo.ObsTime < CheckInfo.ExpTime)
AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns))));
-- start of new code IR245-246
IF (CheckInfo.ExpTime = 0 ns) THEN
CheckInfo.CheckKind := SetupCheck;
ELSE
CheckInfo.CheckKind := HoldCheck;
END IF;
-- end of new code IR245-246
HoldEn := NOT CheckInfo.Violation;
ELSE
CheckInfo.Violation := FALSE;
END IF;
ELSE
CheckInfo.Violation := FALSE;
END IF;
-- Adjust report values to account for internal model delays
-- Note: TestDelay, RefDelay, TestTime, RefTime are non-negative
-- Note: bias may be negative or positive
IF MsgOn AND CheckInfo.Violation THEN
-- modified the code for correct reporting of violation in case of
-- order of signals being reversed because of internal delays
-- new variable
actualObsTime := (TestTime-TestDelay)-(RefTime-RefDelay);
bias := TestDelay - RefDelay;
IF (actualObsTime < 0 ns) THEN -- It should be a setup check
IF ( CheckInfo.CheckKind = HoldCheck) THEN
CheckInfo.CheckKind := SetupCheck;
CASE CheckInfo.State IS
WHEN '0' => CheckInfo.ExpTime := SetupLow;
WHEN '1' => CheckInfo.ExpTime := SetupHigh;
WHEN 'X' => CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow);
END CASE;
END IF;
CheckInfo.ObsTime := -actualObsTime;
CheckInfo.ExpTime := CheckInfo.ExpTime + bias;
CheckInfo.DetTime := RefTime - RefDelay;
ELSE -- It should be a hold check
IF (CheckInfo.CheckKind = SetupCheck) THEN
CheckInfo.CheckKind := HoldCheck;
CASE CheckInfo.State IS
WHEN '0' =>
CheckInfo.ExpTime := HoldHigh;
CheckInfo.State := '1';
WHEN '1' =>
CheckInfo.ExpTime := HoldLow;
CheckInfo.State := '0';
WHEN 'X' =>
CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow);
END CASE;
END IF;
CheckInfo.ObsTime := actualObsTime;
CheckInfo.ExpTime := CheckInfo.ExpTime - bias;
CheckInfo.DetTime := TestTime - TestDelay;
END IF;
END IF;
END InternalTimingCheck;
-- ----------------------------------------------------------------------------
-- Setup and Hold Time Check Routine
-- ----------------------------------------------------------------------------
PROCEDURE TimingArrayIndex (
SIGNAL InputSignal : IN Std_logic_vector;
CONSTANT ArrayIndexNorm : IN INTEGER;
VARIABLE Index : OUT INTEGER
) IS
BEGIN
IF (InputSignal'LEFT > InputSignal'RIGHT) THEN
Index := ArrayIndexNorm + InputSignal'RIGHT;
ELSE
Index := InputSignal'RIGHT - ArrayIndexNorm;
END IF;
END TimingArrayIndex;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryReportViolation (
CONSTANT TestSignalName : IN STRING := "";
CONSTANT RefSignalName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT CheckInfo : IN CheckInfoType;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
) IS
VARIABLE Message : LINE;
BEGIN
IF (NOT CheckInfo.Violation) THEN
RETURN;
END IF;
Write ( Message, HeaderMsg );
CASE CheckInfo.CheckKind IS
WHEN SetupCheck => Write ( Message, STRING'(" SETUP ") );
WHEN HoldCheck => Write ( Message, STRING'(" HOLD ") );
WHEN RecoveryCheck => Write ( Message, STRING'(" RECOVERY ") );
WHEN RemovalCheck => Write ( Message, STRING'(" REMOVAL ") );
WHEN PulseWidCheck => Write ( Message, STRING'(" PULSE WIDTH "));
WHEN PeriodCheck => Write ( Message, STRING'(" PERIOD ") );
END CASE;
Write ( Message, HiLoStr(CheckInfo.State) );
Write ( Message, STRING'(" VIOLATION ON ") );
Write ( Message, TestSignalName );
IF (RefSignalName'LENGTH > 0) THEN
Write ( Message, STRING'(" WITH RESPECT TO ") );
Write ( Message, RefSignalName );
END IF;
Write ( Message, ';' & LF );
Write ( Message, STRING'(" Expected := ") );
Write ( Message, CheckInfo.ExpTime);
Write ( Message, STRING'("; Observed := ") );
Write ( Message, CheckInfo.ObsTime);
Write ( Message, STRING'("; At : ") );
Write ( Message, CheckInfo.DetTime);
ASSERT FALSE REPORT Message.ALL SEVERITY MsgSeverity;
DEALLOCATE (Message);
END VitalMemoryReportViolation;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryReportViolation (
CONSTANT TestSignalName : IN STRING := "";
CONSTANT RefSignalName : IN STRING := "";
CONSTANT TestArrayIndex : IN INTEGER;
CONSTANT RefArrayIndex : IN INTEGER;
SIGNAL TestSignal : IN std_logic_vector;
SIGNAL RefSignal : IN std_logic_vector;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT CheckInfo : IN CheckInfoType;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
) IS
VARIABLE Message : LINE;
VARIABLE i, j : INTEGER;
BEGIN
IF (NOT CheckInfo.Violation) THEN
RETURN;
END IF;
Write ( Message, HeaderMsg );
CASE CheckInfo.CheckKind IS
WHEN SetupCheck => Write ( Message, STRING'(" SETUP ") );
WHEN HoldCheck => Write ( Message, STRING'(" HOLD ") );
WHEN PulseWidCheck => Write ( Message, STRING'(" PULSE WIDTH "));
WHEN PeriodCheck => Write ( Message, STRING'(" PERIOD ") );
WHEN OTHERS => Write ( Message, STRING'(" UNKNOWN ") );
END CASE;
Write ( Message, HiLoStr(CheckInfo.State) );
Write ( Message, STRING'(" VIOLATION ON ") );
Write ( Message, TestSignalName );
TimingArrayIndex(TestSignal, TestArrayIndex, i);
CASE MsgFormat IS
WHEN Scalar =>
NULL;
WHEN VectorEnum =>
Write ( Message, '_');
Write ( Message, i);
WHEN Vector =>
Write ( Message, '(');
Write ( Message, i);
Write ( Message, ')');
END CASE;
IF (RefSignalName'LENGTH > 0) THEN
Write ( Message, STRING'(" WITH RESPECT TO ") );
Write ( Message, RefSignalName );
END IF;
IF(RefSignal'LENGTH > 0) THEN
TimingArrayIndex(RefSignal, RefArrayIndex, j);
CASE MsgFormat IS
WHEN Scalar =>
NULL;
WHEN VectorEnum =>
Write ( Message, '_');
Write ( Message, j);
WHEN Vector =>
Write ( Message, '(');
Write ( Message, j);
Write ( Message, ')');
END CASE;
END IF;
Write ( Message, ';' & LF );
Write ( Message, STRING'(" Expected := ") );
Write ( Message, CheckInfo.ExpTime);
Write ( Message, STRING'("; Observed := ") );
Write ( Message, CheckInfo.ObsTime);
Write ( Message, STRING'("; At : ") );
Write ( Message, CheckInfo.DetTime);
ASSERT FALSE REPORT Message.ALL SEVERITY MsgSeverity;
DEALLOCATE (Message);
END VitalMemoryReportViolation;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryReportViolation (
CONSTANT TestSignalName : IN STRING := "";
CONSTANT RefSignalName : IN STRING := "";
CONSTANT TestArrayIndex : IN INTEGER;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT CheckInfo : IN CheckInfoType;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
) IS
VARIABLE Message : LINE;
BEGIN
IF (NOT CheckInfo.Violation) THEN
RETURN;
END IF;
Write ( Message, HeaderMsg );
CASE CheckInfo.CheckKind IS
WHEN SetupCheck => Write ( Message, STRING'(" SETUP ") );
WHEN HoldCheck => Write ( Message, STRING'(" HOLD ") );
WHEN PulseWidCheck => Write ( Message, STRING'(" PULSE WIDTH "));
WHEN PeriodCheck => Write ( Message, STRING'(" PERIOD ") );
WHEN OTHERS => Write ( Message, STRING'(" UNKNOWN ") );
END CASE;
Write ( Message, HiLoStr(CheckInfo.State) );
Write ( Message, STRING'(" VIOLATION ON ") );
Write ( Message, TestSignalName );
CASE MsgFormat IS
WHEN Scalar =>
NULL;
WHEN VectorEnum =>
Write ( Message, '_');
Write ( Message, TestArrayIndex);
WHEN Vector =>
Write ( Message, '(');
Write ( Message, TestArrayIndex);
Write ( Message, ')');
END CASE;
IF (RefSignalName'LENGTH > 0) THEN
Write ( Message, STRING'(" WITH RESPECT TO ") );
Write ( Message, RefSignalName );
END IF;
Write ( Message, ';' & LF );
Write ( Message, STRING'(" Expected := ") );
Write ( Message, CheckInfo.ExpTime);
Write ( Message, STRING'("; Observed := ") );
Write ( Message, CheckInfo.ObsTime);
Write ( Message, STRING'("; At : ") );
Write ( Message, CheckInfo.DetTime);
ASSERT FALSE REPORT Message.ALL SEVERITY MsgSeverity;
DEALLOCATE (Message);
END VitalMemoryReportViolation;
-- ----------------------------------------------------------------------------
FUNCTION VitalMemoryTimingDataInit
RETURN VitalMemoryTimingDataType IS
BEGIN
RETURN (FALSE, 'X', 0 ns, FALSE, 'X', 0 ns, FALSE,
NULL, NULL, NULL, NULL, NULL, NULL);
END;
-- ----------------------------------------------------------------------------
-- Procedure: VitalSetupHoldCheck
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySetupHoldCheck (
VARIABLE Violation : OUT X01ArrayT;
VARIABLE TimingData : INOUT VitalMemoryTimingDataType;
SIGNAL TestSignal : IN std_ulogic;
CONSTANT TestSignalName: IN STRING := "";
CONSTANT TestDelay : IN TIME := 0 ns;
SIGNAL RefSignal : IN std_ulogic;
CONSTANT RefSignalName : IN STRING := "";
CONSTANT RefDelay : IN TIME := 0 ns;
CONSTANT SetupHigh : IN VitalDelayType;
CONSTANT SetupLow : IN VitalDelayType;
CONSTANT HoldHigh : IN VitalDelayType;
CONSTANT HoldLow : IN VitalDelayType;
CONSTANT CheckEnabled : IN VitalBoolArrayT;
CONSTANT RefTransition : IN VitalEdgeSymbolType;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
--IR252 3/23/98
CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE;
CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE
) IS
VARIABLE CheckInfo : CheckInfoType;
VARIABLE CheckEnScalar : BOOLEAN := FALSE;
VARIABLE ViolationInt : X01ArrayT(CheckEnabled'RANGE);
VARIABLE RefEdge : BOOLEAN;
VARIABLE TestEvent : BOOLEAN;
VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay);
VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay);
VARIABLE bias : TIME;
BEGIN
-- Initialization of working area.
IF (TimingData.NotFirstFlag = FALSE) THEN
TimingData.TestLast := To_X01(TestSignal);
TimingData.RefLast := To_X01(RefSignal);
TimingData.NotFirstFlag := TRUE;
END IF;
-- Detect reference edges and record the time of the last edge
RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal),
RefTransition);
TimingData.RefLast := To_X01(RefSignal);
IF (RefEdge) THEN
TimingData.RefTime := NOW;
--TimingData.HoldEnA.all := (TestSignal'RANGE=>TRUE);
--IR252 3/23/98
TimingData.SetupEn := TimingData.SetupEn AND EnableSetupOnRef;
TimingData.HoldEn := EnableHoldOnRef;
END IF;
-- Detect test (data) changes and record the time of the last change
TestEvent := TimingData.TestLast /= To_X01Z(TestSignal);
TimingData.TestLast := To_X01Z(TestSignal);
IF TestEvent THEN
TimingData.SetupEn := EnableSetupOnTest ; --IR252 3/23/98
TimingData.HoldEn := TimingData.HoldEn AND EnableHoldOnTest ;
--IR252 3/23/98
TimingData.TestTime := NOW;
END IF;
FOR i IN CheckEnabled'RANGE LOOP
IF CheckEnabled(i) = TRUE THEN
CheckEnScalar := TRUE;
END IF;
ViolationInt(i) := '0';
END LOOP;
IF (CheckEnScalar) THEN
InternalTimingCheck (
TestSignal => TestSignal,
RefSignal => RefSignal,
TestDelay => TestDly,
RefDelay => RefDly,
SetupHigh => SetupHigh,
SetupLow => SetupLow,
HoldHigh => HoldHigh,
HoldLow => HoldLow,
RefTime => TimingData.RefTime,
RefEdge => RefEdge,
TestTime => TimingData.TestTime,
TestEvent => TestEvent,
SetupEn => TimingData.SetupEn,
HoldEn => TimingData.HoldEn,
CheckInfo => CheckInfo,
MsgOn => MsgOn
);
-- Report any detected violations and set return violation flag
IF CheckInfo.Violation THEN
IF (MsgOn) THEN
VitalMemoryReportViolation (TestSignalName, RefSignalName,
HeaderMsg, CheckInfo, MsgSeverity );
END IF;
IF (XOn) THEN
FOR i IN CheckEnabled'RANGE LOOP
IF CheckEnabled(i) = TRUE THEN
ViolationInt(i) := 'X';
END IF;
END LOOP;
END IF;
END IF;
END IF;
Violation := ViolationInt;
END VitalMemorySetupHoldCheck;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySetupHoldCheck (
VARIABLE Violation : OUT X01ArrayT;
VARIABLE TimingData : INOUT VitalMemoryTimingDataType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName: IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
SIGNAL RefSignal : IN std_ulogic;
CONSTANT RefSignalName : IN STRING := "";
CONSTANT RefDelay : IN TIME := 0 ns;
CONSTANT SetupHigh : IN VitalDelayArraytype;
CONSTANT SetupLow : IN VitalDelayArraytype;
CONSTANT HoldHigh : IN VitalDelayArraytype;
CONSTANT HoldLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN BOOLEAN := TRUE;
CONSTANT RefTransition : IN VitalEdgeSymbolType;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
--IR252 3/23/98
CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE;
CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE
) IS
VARIABLE CheckInfo : CheckInfoType;
VARIABLE RefEdge : BOOLEAN;
VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE);
VARIABLE TestDly : TIME;
VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay);
VARIABLE bias : TIME;
BEGIN
-- Initialization of working area.
IF (TimingData.NotFirstFlag = FALSE) THEN
TimingData.TestLastA := NEW std_logic_vector(TestSignal'RANGE);
TimingData.TestTimeA := NEW VitalTimeArrayT(TestSignal'RANGE);
TimingData.HoldEnA := NEW VitalBoolArrayT(TestSignal'RANGE);
TimingData.SetupEnA := NEW VitalBoolArrayT(TestSignal'RANGE);
FOR i IN TestSignal'RANGE LOOP
TimingData.TestLastA(i) := To_X01(TestSignal(i));
END LOOP;
TimingData.RefLast := To_X01(RefSignal);
TimingData.NotFirstFlag := TRUE;
END IF;
-- Detect reference edges and record the time of the last edge
RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal),
RefTransition);
TimingData.RefLast := To_X01(RefSignal);
IF (RefEdge) THEN
TimingData.RefTime := NOW;
--TimingData.HoldEnA.all := (TestSignal'RANGE=>TRUE);
--IR252 3/23/98
FOR i IN TestSignal'RANGE LOOP
TimingData.SetupEnA(i)
:= TimingData.SetupEnA(i) AND EnableSetupOnRef;
TimingData.HoldEnA(i) := EnableHoldOnRef;
END LOOP;
END IF;
-- Detect test (data) changes and record the time of the last change
FOR i IN TestSignal'RANGE LOOP
TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignal(i));
TimingData.TestLastA(i) := To_X01Z(TestSignal(i));
IF TestEvent(i) THEN
TimingData.SetupEnA(i) := EnableSetupOnTest ; --IR252 3/23/98
TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest ;
--IR252 3/23/98
TimingData.TestTimeA(i) := NOW;
--TimingData.SetupEnA(i) := TRUE;
TimingData.TestTime := NOW;
END IF;
END LOOP;
FOR i IN TestSignal'RANGE LOOP
Violation(i) := '0';
IF (CheckEnabled) THEN
TestDly := Maximum(0 ns, TestDelay(i));
InternalTimingCheck (
TestSignal => TestSignal(i),
RefSignal => RefSignal,
TestDelay => TestDly,
RefDelay => RefDly,
SetupHigh => SetupHigh(i),
SetupLow => SetupLow(i),
HoldHigh => HoldHigh(i),
HoldLow => HoldLow(i),
RefTime => TimingData.RefTime,
RefEdge => RefEdge,
TestTime => TimingData.TestTimeA(i),
TestEvent => TestEvent(i),
SetupEn => TimingData.SetupEnA(i),
HoldEn => TimingData.HoldEnA(i),
CheckInfo => CheckInfo,
MsgOn => MsgOn
);
-- Report any detected violations and set return violation flag
IF CheckInfo.Violation THEN
IF (MsgOn) THEN
VitalMemoryReportViolation (TestSignalName, RefSignalName, i ,
HeaderMsg, CheckInfo, MsgFormat, MsgSeverity );
END IF;
IF (XOn) THEN
Violation(i) := 'X';
END IF;
END IF;
END IF;
END LOOP;
END VitalMemorySetupHoldCheck;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySetupHoldCheck (
VARIABLE Violation : OUT X01ArrayT;
VARIABLE TimingData : INOUT VitalMemoryTimingDataType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName: IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
SIGNAL RefSignal : IN std_ulogic;
CONSTANT RefSignalName : IN STRING := "";
CONSTANT RefDelay : IN TIME := 0 ns;
CONSTANT SetupHigh : IN VitalDelayArraytype;
CONSTANT SetupLow : IN VitalDelayArraytype;
CONSTANT HoldHigh : IN VitalDelayArraytype;
CONSTANT HoldLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN VitalBoolArrayT;
CONSTANT RefTransition : IN VitalEdgeSymbolType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT NumBitsPerSubWord : IN INTEGER := 1;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
--IR252 3/23/98
CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE;
CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE
) IS
VARIABLE CheckInfo : CheckInfoType;
VARIABLE ViolationInt : X01ArrayT(TestSignal'RANGE);
VARIABLE ViolationIntNorm: X01ArrayT(TestSignal'LENGTH-1 downto 0);
VARIABLE ViolationNorm : X01ArrayT(Violation'LENGTH-1 downto 0);
VARIABLE CheckEnInt : VitalBoolArrayT(TestSignal'RANGE);
VARIABLE CheckEnIntNorm : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0);
VARIABLE CheckEnScalar : BOOLEAN := FALSE; --Mem IR 401
VARIABLE CheckEnabledNorm: VitalBoolArrayT(CheckEnabled'LENGTH-1 downto 0);
VARIABLE RefEdge : BOOLEAN;
VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE);
VARIABLE TestDly : TIME;
VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay);
VARIABLE bias : TIME;
BEGIN
-- Initialization of working area.
IF (TimingData.NotFirstFlag = FALSE) THEN
TimingData.TestLastA := NEW std_logic_vector(TestSignal'RANGE);
TimingData.TestTimeA := NEW VitalTimeArrayT(TestSignal'RANGE);
TimingData.HoldEnA := NEW VitalBoolArrayT(TestSignal'RANGE);
TimingData.SetupEnA := NEW VitalBoolArrayT(TestSignal'RANGE);
FOR i IN TestSignal'RANGE LOOP
TimingData.TestLastA(i) := To_X01(TestSignal(i));
END LOOP;
TimingData.RefLast := To_X01(RefSignal);
TimingData.NotFirstFlag := TRUE;
END IF;
-- Detect reference edges and record the time of the last edge
RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal),
RefTransition);
TimingData.RefLast := To_X01(RefSignal);
IF RefEdge THEN
TimingData.RefTime := NOW;
--TimingData.HoldEnA.all := (TestSignal'RANGE=>TRUE);
--IR252 3/23/98
FOR i IN TestSignal'RANGE LOOP
TimingData.SetupEnA(i)
:= TimingData.SetupEnA(i) AND EnableSetupOnRef;
TimingData.HoldEnA(i) := EnableHoldOnRef;
END LOOP;
END IF;
-- Detect test (data) changes and record the time of the last change
FOR i IN TestSignal'RANGE LOOP
TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignal(i));
TimingData.TestLastA(i) := To_X01Z(TestSignal(i));
IF TestEvent(i) THEN
TimingData.SetupEnA(i) := EnableSetupOnTest ; --IR252 3/23/98
TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest ;
--IR252 3/23/98
TimingData.TestTimeA(i) := NOW;
--TimingData.SetupEnA(i) := TRUE;
TimingData.TestTime := NOW;
END IF;
END LOOP;
IF ArcType = CrossArc THEN
CheckEnScalar := FALSE;
FOR i IN CheckEnabled'RANGE LOOP
IF CheckEnabled(i) = TRUE THEN
CheckEnScalar := TRUE;
END IF;
END LOOP;
FOR i IN CheckEnInt'RANGE LOOP
CheckEnInt(i) := CheckEnScalar;
END LOOP;
ELSE
FOR i IN CheckEnIntNorm'RANGE LOOP
CheckEnIntNorm(i) := CheckEnabledNorm(i / NumBitsPerSubWord );
END LOOP;
CheckEnInt := CheckEnIntNorm;
END IF;
FOR i IN TestSignal'RANGE LOOP
ViolationInt(i) := '0';
IF (CheckEnInt(i)) THEN
TestDly := Maximum(0 ns, TestDelay(i));
InternalTimingCheck (
TestSignal => TestSignal(i),
RefSignal => RefSignal,
TestDelay => TestDly,
RefDelay => RefDly,
SetupHigh => SetupHigh(i),
SetupLow => SetupLow(i),
HoldHigh => HoldHigh(i),
HoldLow => HoldLow(i),
RefTime => TimingData.RefTime,
RefEdge => RefEdge,
TestTime => TimingData.TestTimeA(i),
TestEvent => TestEvent(i),
SetupEn => TimingData.SetupEnA(i),
HoldEn => TimingData.HoldEnA(i),
CheckInfo => CheckInfo,
MsgOn => MsgOn
);
-- Report any detected violations and set return violation flag
IF CheckInfo.Violation THEN
IF (MsgOn) THEN
VitalMemoryReportViolation (TestSignalName, RefSignalName, i ,
HeaderMsg, CheckInfo, MsgFormat, MsgSeverity );
END IF;
IF (XOn) THEN
ViolationInt(i) := 'X';
END IF;
END IF;
END IF;
END LOOP;
IF (ViolationInt'LENGTH = Violation'LENGTH) THEN
Violation := ViolationInt;
ELSE
ViolationIntNorm := ViolationInt;
FOR i IN ViolationNorm'RANGE LOOP
ViolationNorm(i) := '0';
END LOOP;
FOR i IN ViolationIntNorm'RANGE LOOP
IF (ViolationIntNorm(i) = 'X') THEN
ViolationNorm(i / NumBitsPerSubWord) := 'X';
END IF;
END LOOP;
Violation := ViolationNorm;
END IF;
END VitalMemorySetupHoldCheck;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySetupHoldCheck (
VARIABLE Violation : OUT X01ArrayT;
VARIABLE TimingData : INOUT VitalMemoryTimingDataType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName: IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
SIGNAL RefSignal : IN std_logic_vector;
CONSTANT RefSignalName : IN STRING := "";
CONSTANT RefDelay : IN VitalDelayArraytype;
CONSTANT SetupHigh : IN VitalDelayArraytype;
CONSTANT SetupLow : IN VitalDelayArraytype;
CONSTANT HoldHigh : IN VitalDelayArraytype;
CONSTANT HoldLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN BOOLEAN := TRUE;
CONSTANT RefTransition : IN VitalEdgeSymbolType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT NumBitsPerSubWord : IN INTEGER := 1;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
--IR252 3/23/98
CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE;
CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE
) IS
VARIABLE CheckInfo : CheckInfoType;
VARIABLE RefEdge : VitalBoolArrayT(RefSignal'LENGTH-1 downto 0);
VARIABLE TestEvent : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0);
VARIABLE TestDly : TIME;
VARIABLE RefDly : TIME;
VARIABLE bias : TIME;
VARIABLE NumTestBits : NATURAL := TestSignal'LENGTH;
VARIABLE NumRefBits : NATURAL := RefSignal'LENGTH;
VARIABLE NumChecks : NATURAL;
VARIABLE ViolationTest : X01ArrayT(NumTestBits-1 downto 0);
VARIABLE ViolationRef : X01ArrayT(NumRefBits-1 downto 0);
VARIABLE TestSignalNorm : std_logic_vector(NumTestBits-1 downto 0)
:= TestSignal;
VARIABLE TestDelayNorm : VitalDelayArraytype(NumTestBits-1 downto 0)
:= TestDelay;
VARIABLE RefSignalNorm : std_logic_vector(NumRefBits-1 downto 0)
:= RefSignal;
VARIABLE RefDelayNorm : VitalDelayArraytype(NumRefBits-1 downto 0)
:= RefDelay;
VARIABLE SetupHighNorm : VitalDelayArraytype(SetupHigh'LENGTH-1 downto 0)
:= SetupHigh;
VARIABLE SetupLowNorm : VitalDelayArraytype(SetupLow'LENGTH-1 downto 0)
:= SetupLow;
VARIABLE HoldHighNorm : VitalDelayArraytype(HoldHigh'LENGTH-1 downto 0)
:= HoldHigh;
VARIABLE HoldLowNorm : VitalDelayArraytype(HoldLow'LENGTH-1 downto 0)
:= HoldLow;
VARIABLE RefBitLow : NATURAL;
VARIABLE RefBitHigh : NATURAL;
VARIABLE EnArrayIndex : NATURAL;
VARIABLE TimingArrayIndex: NATURAL;
BEGIN
-- Initialization of working area.
IF (TimingData.NotFirstFlag = FALSE) THEN
TimingData.TestLastA := NEW std_logic_vector(NumTestBits-1 downto 0);
TimingData.TestTimeA := NEW VitalTimeArrayT(NumTestBits-1 downto 0);
TimingData.RefTimeA := NEW VitalTimeArrayT(NumRefBits-1 downto 0);
TimingData.RefLastA := NEW X01ArrayT(NumRefBits-1 downto 0);
IF (ArcType = CrossArc) THEN
NumChecks := RefSignal'LENGTH * TestSignal'LENGTH;
ELSE
NumChecks := TestSignal'LENGTH;
END IF;
TimingData.HoldEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0);
TimingData.SetupEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0);
FOR i IN TestSignalNorm'RANGE LOOP
TimingData.TestLastA(i) := To_X01(TestSignalNorm(i));
END LOOP;
FOR i IN RefSignalNorm'RANGE LOOP
TimingData.RefLastA(i) := To_X01(RefSignalNorm(i));
END LOOP;
TimingData.NotFirstFlag := TRUE;
END IF;
-- Detect reference edges and record the time of the last edge
FOR i IN RefSignalNorm'RANGE LOOP
RefEdge(i) := EdgeSymbolMatch(TimingData.RefLastA(i),
To_X01(RefSignalNorm(i)), RefTransition);
TimingData.RefLastA(i) := To_X01(RefSignalNorm(i));
IF (RefEdge(i)) THEN
TimingData.RefTimeA(i) := NOW;
END IF;
END LOOP;
-- Detect test (data) changes and record the time of the last change
FOR i IN TestSignalNorm'RANGE LOOP
TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignalNorm(i));
TimingData.TestLastA(i) := To_X01Z(TestSignalNorm(i));
IF (TestEvent(i)) THEN
TimingData.TestTimeA(i) := NOW;
END IF;
END LOOP;
FOR i IN ViolationTest'RANGE LOOP
ViolationTest(i) := '0';
END LOOP;
FOR i IN ViolationRef'RANGE LOOP
ViolationRef(i) := '0';
END LOOP;
FOR i IN TestSignalNorm'RANGE LOOP
IF (ArcType = CrossArc) THEN
FOR j IN RefSignalNorm'RANGE LOOP
IF (TestEvent(i)) THEN
--TimingData.SetupEnA(i*NumRefBits+j) := TRUE;
--IR252
TimingData.SetupEnA(i*NumRefBits+j) := EnableSetupOnTest;
TimingData.HoldEnA(i*NumRefBits+j)
:= TimingData.HoldEnA(i*NumRefBits+j) AND EnableHoldOnTest;
END IF;
IF (RefEdge(j)) THEN
--TimingData.HoldEnA(i*NumRefBits+j) := TRUE;
--IR252
TimingData.HoldEnA(i*NumRefBits+j) := EnableHoldOnRef;
TimingData.SetupEnA(i*NumRefBits+j)
:= TimingData.SetupEnA(i*NumRefBits+j) AND EnableSetupOnRef;
END IF;
END LOOP;
RefBitLow := 0;
RefBitHigh := NumRefBits-1;
TimingArrayIndex := i;
ELSE
IF ArcType = SubwordArc THEN
RefBitLow := i / NumBitsPerSubWord;
TimingArrayIndex := i + NumTestBits * RefBitLow;
ELSE
RefBitLow := i;
TimingArrayIndex := i;
END IF;
RefBitHigh := RefBitLow;
IF TestEvent(i) THEN
--TimingData.SetupEnA(i) := TRUE;
--IR252
TimingData.SetupEnA(i) := EnableSetupOnTest;
TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest;
END IF;
IF RefEdge(RefBitLow) THEN
--TimingData.HoldEnA(i) := TRUE;
--IR252
TimingData.HoldEnA(i) := EnableHoldOnRef;
TimingData.SetupEnA(i) := TimingData.SetupEnA(i) AND EnableSetupOnRef;
END IF;
END IF;
EnArrayIndex := i;
FOR j IN RefBitLow to RefBitHigh LOOP
IF (CheckEnabled) THEN
TestDly := Maximum(0 ns, TestDelayNorm(i));
RefDly := Maximum(0 ns, RefDelayNorm(j));
InternalTimingCheck (
TestSignal => TestSignalNorm(i),
RefSignal => RefSignalNorm(j),
TestDelay => TestDly,
RefDelay => RefDly,
SetupHigh => SetupHighNorm(TimingArrayIndex),
SetupLow => SetupLowNorm(TimingArrayIndex),
HoldHigh => HoldHighNorm(TimingArrayIndex),
HoldLow => HoldLowNorm(TimingArrayIndex),
RefTime => TimingData.RefTimeA(j),
RefEdge => RefEdge(j),
TestTime => TimingData.TestTimeA(i),
TestEvent => TestEvent(i),
SetupEn => TimingData.SetupEnA(EnArrayIndex),
HoldEn => TimingData.HoldEnA(EnArrayIndex),
CheckInfo => CheckInfo,
MsgOn => MsgOn
);
-- Report any detected violations and set return violation flag
IF (CheckInfo.Violation) THEN
IF (MsgOn) THEN
VitalMemoryReportViolation (TestSignalName, RefSignalName, i, j,
TestSignal, RefSignal, HeaderMsg, CheckInfo,
MsgFormat, MsgSeverity );
END IF;
IF (XOn) THEN
ViolationTest(i) := 'X';
ViolationRef(j) := 'X';
END IF;
END IF;
END IF;
TimingArrayIndex := TimingArrayIndex + NumRefBits;
EnArrayIndex := EnArrayIndex + NumRefBits;
END LOOP;
END LOOP;
IF (ArcType = CrossArc) THEN
Violation := ViolationRef;
ELSE
IF (Violation'LENGTH = ViolationRef'LENGTH) THEN
Violation := ViolationRef;
ELSE
Violation := ViolationTest;
END IF;
END IF;
END VitalMemorySetupHoldCheck;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySetupHoldCheck (
VARIABLE Violation : OUT X01ArrayT;
VARIABLE TimingData : INOUT VitalMemoryTimingDataType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName: IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
SIGNAL RefSignal : IN std_logic_vector;
CONSTANT RefSignalName : IN STRING := "";
CONSTANT RefDelay : IN VitalDelayArraytype;
CONSTANT SetupHigh : IN VitalDelayArraytype;
CONSTANT SetupLow : IN VitalDelayArraytype;
CONSTANT HoldHigh : IN VitalDelayArraytype;
CONSTANT HoldLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN VitalBoolArrayT;
CONSTANT RefTransition : IN VitalEdgeSymbolType;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT NumBitsPerSubWord : IN INTEGER := 1;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
--IR252 3/23/98
CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE;
CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE
) IS
VARIABLE CheckInfo : CheckInfoType;
VARIABLE RefEdge : VitalBoolArrayT(RefSignal'LENGTH-1 downto 0);
VARIABLE TestEvent : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0);
VARIABLE TestDly : TIME;
VARIABLE RefDly : TIME;
VARIABLE bias : TIME;
VARIABLE NumTestBits : NATURAL := TestSignal'LENGTH;
VARIABLE NumRefBits : NATURAL := RefSignal'LENGTH;
VARIABLE NumChecks : NATURAL;
VARIABLE ViolationTest : X01ArrayT(NumTestBits-1 downto 0);
VARIABLE ViolationRef : X01ArrayT(NumRefBits-1 downto 0);
VARIABLE TestSignalNorm : std_logic_vector(NumTestBits-1 downto 0)
:= TestSignal;
VARIABLE TestDelayNorm : VitalDelayArraytype(NumTestBits-1 downto 0)
:= TestDelay;
VARIABLE RefSignalNorm : std_logic_vector(NumRefBits-1 downto 0)
:= RefSignal;
VARIABLE RefDelayNorm : VitalDelayArraytype(NumRefBits-1 downto 0)
:= RefDelay;
VARIABLE CheckEnNorm : VitalBoolArrayT(NumRefBits-1 downto 0)
:= CheckEnabled;
VARIABLE SetupHighNorm : VitalDelayArraytype(SetupHigh'LENGTH-1 downto 0)
:= SetupHigh;
VARIABLE SetupLowNorm : VitalDelayArraytype(SetupLow'LENGTH-1 downto 0)
:= SetupLow;
VARIABLE HoldHighNorm : VitalDelayArraytype(HoldHigh'LENGTH-1 downto 0)
:= HoldHigh;
VARIABLE HoldLowNorm : VitalDelayArraytype(HoldLow'LENGTH-1 downto 0)
:= HoldLow;
VARIABLE RefBitLow : NATURAL;
VARIABLE RefBitHigh : NATURAL;
VARIABLE EnArrayIndex : NATURAL;
VARIABLE TimingArrayIndex: NATURAL;
BEGIN
-- Initialization of working area.
IF (TimingData.NotFirstFlag = FALSE) THEN
TimingData.TestLastA := NEW std_logic_vector(NumTestBits-1 downto 0);
TimingData.TestTimeA := NEW VitalTimeArrayT(NumTestBits-1 downto 0);
TimingData.RefTimeA := NEW VitalTimeArrayT(NumRefBits-1 downto 0);
TimingData.RefLastA := NEW X01ArrayT(NumRefBits-1 downto 0);
IF ArcType = CrossArc THEN
NumChecks := RefSignal'LENGTH * TestSignal'LENGTH;
ELSE
NumChecks := TestSignal'LENGTH;
END IF;
TimingData.HoldEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0);
TimingData.SetupEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0);
FOR i IN TestSignalNorm'RANGE LOOP
TimingData.TestLastA(i) := To_X01(TestSignalNorm(i));
END LOOP;
FOR i IN RefSignalNorm'RANGE LOOP
TimingData.RefLastA(i) := To_X01(RefSignalNorm(i));
END LOOP;
TimingData.NotFirstFlag := TRUE;
END IF;
-- Detect reference edges and record the time of the last edge
FOR i IN RefSignalNorm'RANGE LOOP
RefEdge(i) := EdgeSymbolMatch(TimingData.RefLastA(i),
To_X01(RefSignalNorm(i)), RefTransition);
TimingData.RefLastA(i) := To_X01(RefSignalNorm(i));
IF RefEdge(i) THEN
TimingData.RefTimeA(i) := NOW;
END IF;
END LOOP;
-- Detect test (data) changes and record the time of the last change
FOR i IN TestSignalNorm'RANGE LOOP
TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignalNorm(i));
TimingData.TestLastA(i) := To_X01Z(TestSignalNorm(i));
IF TestEvent(i) THEN
TimingData.TestTimeA(i) := NOW;
END IF;
END LOOP;
FOR i IN ViolationTest'RANGE LOOP
ViolationTest(i) := '0';
END LOOP;
FOR i IN ViolationRef'RANGE LOOP
ViolationRef(i) := '0';
END LOOP;
FOR i IN TestSignalNorm'RANGE LOOP
IF (ArcType = CrossArc) THEN
FOR j IN RefSignalNorm'RANGE LOOP
IF (TestEvent(i)) THEN
--TimingData.SetupEnA(i*NumRefBits+j) := TRUE;
--IR252
TimingData.SetupEnA(i*NumRefBits+j) := EnableSetupOnTest;
TimingData.HoldEnA(i*NumRefBits+j)
:= TimingData.HoldEnA(i*NumRefBits+j) AND EnableHoldOnTest;
END IF;
IF (RefEdge(j)) THEN
--TimingData.HoldEnA(i*NumRefBits+j) := TRUE;
--IR252
TimingData.HoldEnA(i*NumRefBits+j) := EnableHoldOnRef;
TimingData.SetupEnA(i*NumRefBits+j)
:= TimingData.SetupEnA(i*NumRefBits+j) AND EnableSetupOnRef;
END IF;
END LOOP;
RefBitLow := 0;
RefBitHigh := NumRefBits-1;
TimingArrayIndex := i;
ELSE
IF (ArcType = SubwordArc) THEN
RefBitLow := i / NumBitsPerSubWord;
TimingArrayIndex := i + NumTestBits * RefBitLow;
ELSE
RefBitLow := i;
TimingArrayIndex := i;
END IF;
RefBitHigh := RefBitLow;
IF (TestEvent(i)) THEN
--TimingData.SetupEnA(i) := TRUE;
--IR252
TimingData.SetupEnA(i) := EnableSetupOnTest;
TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest;
END IF;
IF (RefEdge(RefBitLow)) THEN
--TimingData.HoldEnA(i) := TRUE;
--IR252
TimingData.HoldEnA(i) := EnableHoldOnRef;
TimingData.SetupEnA(i) := TimingData.SetupEnA(i) AND EnableSetupOnRef;
END IF;
END IF;
EnArrayIndex := i;
FOR j IN RefBitLow to RefBitHigh LOOP
IF (CheckEnNorm(j)) THEN
TestDly := Maximum(0 ns, TestDelayNorm(i));
RefDly := Maximum(0 ns, RefDelayNorm(j));
InternalTimingCheck (
TestSignal => TestSignalNorm(i),
RefSignal => RefSignalNorm(j),
TestDelay => TestDly,
RefDelay => RefDly,
SetupHigh => SetupHighNorm(TimingArrayIndex),
SetupLow => SetupLowNorm(TimingArrayIndex),
HoldHigh => HoldHighNorm(TimingArrayIndex),
HoldLow => HoldLowNorm(TimingArrayIndex),
RefTime => TimingData.RefTimeA(j),
RefEdge => RefEdge(j),
TestTime => TimingData.TestTimeA(i),
TestEvent => TestEvent(i),
SetupEn => TimingData.SetupEnA(EnArrayIndex),
HoldEn => TimingData.HoldEnA(EnArrayIndex),
CheckInfo => CheckInfo,
MsgOn => MsgOn
);
-- Report any detected violations and set return violation flag
IF (CheckInfo.Violation) THEN
IF (MsgOn) THEN
VitalMemoryReportViolation (TestSignalName, RefSignalName, i, j,
TestSignal, RefSignal, HeaderMsg, CheckInfo,
MsgFormat, MsgSeverity );
END IF;
IF (XOn) THEN
ViolationTest(i) := 'X';
ViolationRef(j) := 'X';
END IF;
END IF;
END IF;
TimingArrayIndex := TimingArrayIndex + NumRefBits;
EnArrayIndex := EnArrayIndex + NumRefBits;
END LOOP;
END LOOP;
IF (ArcType = CrossArc) THEN
Violation := ViolationRef;
ELSE
IF (Violation'LENGTH = ViolationRef'LENGTH) THEN
Violation := ViolationRef;
ELSE
Violation := ViolationTest;
END IF;
END IF;
END VitalMemorySetupHoldCheck;
-- ----------------------------------------------------------------------------
-- scalar violations not needed
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySetupHoldCheck (
VARIABLE Violation : OUT X01;
VARIABLE TimingData : INOUT VitalMemoryTimingDataType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName: IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
SIGNAL RefSignal : IN std_ulogic;
CONSTANT RefSignalName : IN STRING := "";
CONSTANT RefDelay : IN TIME := 0 ns;
CONSTANT SetupHigh : IN VitalDelayArraytype;
CONSTANT SetupLow : IN VitalDelayArraytype;
CONSTANT HoldHigh : IN VitalDelayArraytype;
CONSTANT HoldLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN BOOLEAN := TRUE;
CONSTANT RefTransition : IN VitalEdgeSymbolType;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
--IR252 3/23/98
CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE;
CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE
) IS
VARIABLE CheckInfo : CheckInfoType;
VARIABLE RefEdge : BOOLEAN;
VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE);
VARIABLE TestDly : TIME;
VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay);
VARIABLE bias : TIME;
BEGIN
-- Initialization of working area.
IF (TimingData.NotFirstFlag = FALSE) THEN
TimingData.TestLastA := NEW std_logic_vector(TestSignal'RANGE);
TimingData.TestTimeA := NEW VitalTimeArrayT(TestSignal'RANGE);
TimingData.HoldEnA := NEW VitalBoolArrayT(TestSignal'RANGE);
TimingData.SetupEnA := NEW VitalBoolArrayT(TestSignal'RANGE);
FOR i IN TestSignal'RANGE LOOP
TimingData.TestLastA(i) := To_X01(TestSignal(i));
END LOOP;
TimingData.RefLast := To_X01(RefSignal);
TimingData.NotFirstFlag := TRUE;
END IF;
-- Detect reference edges and record the time of the last edge
RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal),
RefTransition);
TimingData.RefLast := To_X01(RefSignal);
IF (RefEdge) THEN
TimingData.RefTime := NOW;
--TimingData.HoldEnA.all := (TestSignal'RANGE=>TRUE);
--IR252 3/23/98
FOR i IN TestSignal'RANGE LOOP
TimingData.SetupEnA(i)
:= TimingData.SetupEnA(i) AND EnableSetupOnRef;
TimingData.HoldEnA(i) := EnableHoldOnRef;
END LOOP;
END IF;
-- Detect test (data) changes and record the time of the last change
FOR i IN TestSignal'RANGE LOOP
TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignal(i));
TimingData.TestLastA(i) := To_X01Z(TestSignal(i));
IF TestEvent(i) THEN
TimingData.SetupEnA(i) := EnableSetupOnTest ; --IR252 3/23/98
TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest ;
--IR252 3/23/98
TimingData.TestTimeA(i) := NOW;
--TimingData.SetupEnA(i) := TRUE;
TimingData.TestTime := NOW;
END IF;
END LOOP;
Violation := '0';
FOR i IN TestSignal'RANGE LOOP
IF (CheckEnabled) THEN
TestDly := Maximum(0 ns, TestDelay(i));
InternalTimingCheck (
TestSignal => TestSignal(i),
RefSignal => RefSignal,
TestDelay => TestDly,
RefDelay => RefDly,
SetupHigh => SetupHigh(i),
SetupLow => SetupLow(i),
HoldHigh => HoldHigh(i),
HoldLow => HoldLow(i),
RefTime => TimingData.RefTime,
RefEdge => RefEdge,
TestTime => TimingData.TestTimeA(i),
TestEvent => TestEvent(i),
SetupEn => TimingData.SetupEnA(i),
HoldEn => TimingData.HoldEnA(i),
CheckInfo => CheckInfo,
MsgOn => MsgOn
);
-- Report any detected violations and set return violation flag
IF CheckInfo.Violation THEN
IF (MsgOn) THEN
VitalMemoryReportViolation (TestSignalName, RefSignalName, i ,
HeaderMsg, CheckInfo, MsgFormat, MsgSeverity );
END IF;
IF (XOn) THEN
Violation := 'X';
END IF;
END IF;
END IF;
END LOOP;
END VitalMemorySetupHoldCheck;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemorySetupHoldCheck (
VARIABLE Violation : OUT X01;
VARIABLE TimingData : INOUT VitalMemoryTimingDataType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName: IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
SIGNAL RefSignal : IN std_logic_vector;
CONSTANT RefSignalName : IN STRING := "";
CONSTANT RefDelay : IN VitalDelayArraytype;
CONSTANT SetupHigh : IN VitalDelayArraytype;
CONSTANT SetupLow : IN VitalDelayArraytype;
CONSTANT HoldHigh : IN VitalDelayArraytype;
CONSTANT HoldLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN BOOLEAN := TRUE;
CONSTANT RefTransition : IN VitalEdgeSymbolType;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT ArcType : IN VitalMemoryArcType := CrossArc;
CONSTANT NumBitsPerSubWord : IN INTEGER := 1;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType;
--IR252 3/23/98
CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE;
CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE;
CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE
) IS
VARIABLE CheckInfo : CheckInfoType;
VARIABLE RefEdge : VitalBoolArrayT(RefSignal'LENGTH-1 downto 0);
VARIABLE TestEvent : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0);
VARIABLE TestDly : TIME;
VARIABLE RefDly : TIME;
VARIABLE bias : TIME;
VARIABLE NumTestBits : NATURAL := TestSignal'LENGTH;
VARIABLE NumRefBits : NATURAL := RefSignal'LENGTH;
VARIABLE NumChecks : NATURAL;
VARIABLE TestSignalNorm : std_logic_vector(NumTestBits-1 downto 0)
:= TestSignal;
VARIABLE TestDelayNorm : VitalDelayArraytype(NumTestBits-1 downto 0)
:= TestDelay;
VARIABLE RefSignalNorm : std_logic_vector(NumRefBits-1 downto 0)
:= RefSignal;
VARIABLE RefDelayNorm : VitalDelayArraytype(NumRefBits-1 downto 0)
:= RefDelay;
VARIABLE SetupHighNorm : VitalDelayArraytype(SetupHigh'LENGTH-1 downto 0)
:= SetupHigh;
VARIABLE SetupLowNorm : VitalDelayArraytype(SetupLow'LENGTH-1 downto 0)
:= SetupLow;
VARIABLE HoldHighNorm : VitalDelayArraytype(HoldHigh'LENGTH-1 downto 0)
:= HoldHigh;
VARIABLE HoldLowNorm : VitalDelayArraytype(HoldLow'LENGTH-1 downto 0)
:= HoldLow;
VARIABLE RefBitLow : NATURAL;
VARIABLE RefBitHigh : NATURAL;
VARIABLE EnArrayIndex : NATURAL;
VARIABLE TimingArrayIndex: NATURAL;
BEGIN
-- Initialization of working area.
IF (TimingData.NotFirstFlag = FALSE) THEN
TimingData.TestLastA := NEW std_logic_vector(NumTestBits-1 downto 0);
TimingData.TestTimeA := NEW VitalTimeArrayT(NumTestBits-1 downto 0);
TimingData.RefTimeA := NEW VitalTimeArrayT(NumRefBits-1 downto 0);
TimingData.RefLastA := NEW X01ArrayT(NumRefBits-1 downto 0);
IF (ArcType = CrossArc) THEN
NumChecks := RefSignal'LENGTH * TestSignal'LENGTH;
ELSE
NumChecks := TestSignal'LENGTH;
END IF;
TimingData.HoldEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0);
TimingData.SetupEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0);
FOR i IN TestSignalNorm'RANGE LOOP
TimingData.TestLastA(i) := To_X01(TestSignalNorm(i));
END LOOP;
FOR i IN RefSignalNorm'RANGE LOOP
TimingData.RefLastA(i) := To_X01(RefSignalNorm(i));
END LOOP;
TimingData.NotFirstFlag := TRUE;
END IF;
-- Detect reference edges and record the time of the last edge
FOR i IN RefSignalNorm'RANGE LOOP
RefEdge(i) := EdgeSymbolMatch(TimingData.RefLastA(i),
To_X01(RefSignalNorm(i)), RefTransition);
TimingData.RefLastA(i) := To_X01(RefSignalNorm(i));
IF (RefEdge(i)) THEN
TimingData.RefTimeA(i) := NOW;
END IF;
END LOOP;
-- Detect test (data) changes and record the time of the last change
FOR i IN TestSignalNorm'RANGE LOOP
TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignalNorm(i));
TimingData.TestLastA(i) := To_X01Z(TestSignalNorm(i));
IF (TestEvent(i)) THEN
TimingData.TestTimeA(i) := NOW;
END IF;
END LOOP;
FOR i IN TestSignalNorm'RANGE LOOP
IF (ArcType = CrossArc) THEN
FOR j IN RefSignalNorm'RANGE LOOP
IF (TestEvent(i)) THEN
--TimingData.SetupEnA(i*NumRefBits+j) := TRUE;
--IR252
TimingData.SetupEnA(i*NumRefBits+j) := EnableSetupOnTest;
TimingData.HoldEnA(i*NumRefBits+j)
:= TimingData.HoldEnA(i*NumRefBits+j) AND EnableHoldOnTest;
END IF;
IF (RefEdge(j)) THEN
--TimingData.HoldEnA(i*NumRefBits+j) := TRUE;
--IR252
TimingData.HoldEnA(i*NumRefBits+j) := EnableHoldOnRef;
TimingData.SetupEnA(i*NumRefBits+j)
:= TimingData.SetupEnA(i*NumRefBits+j) AND EnableSetupOnRef;
END IF;
END LOOP;
RefBitLow := 0;
RefBitHigh := NumRefBits-1;
TimingArrayIndex := i;
ELSE
IF (ArcType = SubwordArc) THEN
RefBitLow := i / NumBitsPerSubWord;
TimingArrayIndex := i + NumTestBits * RefBitLow;
ELSE
RefBitLow := i;
TimingArrayIndex := i;
END IF;
RefBitHigh := RefBitLow;
IF (TestEvent(i)) THEN
--TimingData.SetupEnA(i) := TRUE;
--IR252
TimingData.SetupEnA(i) := EnableSetupOnTest;
TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest;
END IF;
IF (RefEdge(RefBitLow)) THEN
--TimingData.HoldEnA(i) := TRUE;
--IR252
TimingData.HoldEnA(i) := EnableHoldOnRef;
TimingData.SetupEnA(i) := TimingData.SetupEnA(i) AND EnableSetupOnRef;
END IF;
END IF;
EnArrayIndex := i;
Violation := '0';
FOR j IN RefBitLow to RefBitHigh LOOP
IF (CheckEnabled) THEN
TestDly := Maximum(0 ns, TestDelayNorm(i));
RefDly := Maximum(0 ns, RefDelayNorm(j));
InternalTimingCheck (
TestSignal => TestSignalNorm(i),
RefSignal => RefSignalNorm(j),
TestDelay => TestDly,
RefDelay => RefDly,
SetupHigh => SetupHighNorm(TimingArrayIndex),
SetupLow => SetupLowNorm(TimingArrayIndex),
HoldHigh => HoldHighNorm(TimingArrayIndex),
HoldLow => HoldLowNorm(TimingArrayIndex),
RefTime => TimingData.RefTimeA(j),
RefEdge => RefEdge(j),
TestTime => TimingData.TestTimeA(i),
TestEvent => TestEvent(i),
SetupEn => TimingData.SetupEnA(EnArrayIndex),
HoldEn => TimingData.HoldEnA(EnArrayIndex),
CheckInfo => CheckInfo,
MsgOn => MsgOn
);
-- Report any detected violations and set return violation flag
IF (CheckInfo.Violation) THEN
IF (MsgOn) THEN
VitalMemoryReportViolation (TestSignalName, RefSignalName, i, j,
TestSignal, RefSignal, HeaderMsg, CheckInfo,
MsgFormat, MsgSeverity );
END IF;
IF (XOn) THEN
Violation := 'X';
END IF;
END IF;
END IF;
TimingArrayIndex := TimingArrayIndex + NumRefBits;
EnArrayIndex := EnArrayIndex + NumRefBits;
END LOOP;
END LOOP;
END VitalMemorySetupHoldCheck;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryPeriodPulseCheck (
VARIABLE Violation : OUT X01;
VARIABLE PeriodData : INOUT VitalPeriodDataArrayType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName : IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
CONSTANT Period : IN VitalDelayArraytype;
CONSTANT PulseWidthHigh : IN VitalDelayArraytype;
CONSTANT PulseWidthLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN BOOLEAN := TRUE;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType
) IS
VARIABLE TestDly : VitalDelayType;
VARIABLE CheckInfo : CheckInfoType;
VARIABLE PeriodObs : VitalDelayType;
VARIABLE PulseTest : BOOLEAN;
VARIABLE PeriodTest: BOOLEAN;
VARIABLE TestValue : X01;
BEGIN
-- Initialize for no violation
Violation := '0'; --MEM IR 402
FOR i IN TestSignal'RANGE LOOP
TestDly := Maximum(0 ns, TestDelay(i));
TestValue := To_X01(TestSignal(i));
IF (PeriodData(i).NotFirstFlag = FALSE) THEN
PeriodData(i).Rise := -Maximum(Period(i),
Maximum(PulseWidthHigh(i),PulseWidthLow(i)));
PeriodData(i).Fall := -Maximum(Period(i),
Maximum(PulseWidthHigh(i),PulseWidthLow(i)));
PeriodData(i).Last := TestValue;
PeriodData(i).NotFirstFlag := TRUE;
END IF;
-- Initialize for no violation
-- Violation := '0'; --Mem IR 402
-- No violation possible if no test signal change
NEXT WHEN (PeriodData(i).Last = TestValue);
-- record starting pulse times
IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'P')) THEN
-- Compute period times, then record the High Rise Time
PeriodObs := NOW - PeriodData(i).Rise;
PeriodData(i).Rise := NOW;
PeriodTest := TRUE;
ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'N')) THEN
-- Compute period times, then record the Low Fall Time
PeriodObs := NOW - PeriodData(i).Fall;
PeriodData(i).Fall := NOW;
PeriodTest := TRUE;
ELSE
PeriodTest := FALSE;
END IF;
-- do checks on pulse ends
IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'p')) THEN
-- Compute pulse times
CheckInfo.ObsTime := NOW - PeriodData(i).Fall;
CheckInfo.ExpTime := PulseWidthLow(i);
PulseTest := TRUE;
ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'n')) THEN
-- Compute pulse times
CheckInfo.ObsTime := NOW - PeriodData(i).Rise;
CheckInfo.ExpTime := PulseWidthHigh(i);
PulseTest := TRUE;
ELSE
PulseTest := FALSE;
END IF;
IF (PulseTest AND CheckEnabled) THEN
-- Verify Pulse Width [ignore 1st edge]
IF (CheckInfo.ObsTime < CheckInfo.ExpTime) THEN
IF (XOn) THEN
Violation := 'X';
END IF;
IF (MsgOn) THEN
CheckInfo.Violation := TRUE;
CheckInfo.CheckKind := PulseWidCheck;
CheckInfo.DetTime := NOW - TestDly;
CheckInfo.State := PeriodData(i).Last;
VitalMemoryReportViolation (TestSignalName, "", i,
HeaderMsg, CheckInfo, MsgFormat, MsgSeverity );
END IF; -- MsgOn
END IF;
END IF;
IF (PeriodTest AND CheckEnabled) THEN
-- Verify the Period [ignore 1st edge]
CheckInfo.ObsTime := PeriodObs;
CheckInfo.ExpTime := Period(i);
IF ( CheckInfo.ObsTime < CheckInfo.ExpTime ) THEN
IF (XOn) THEN
Violation := 'X';
END IF;
IF (MsgOn) THEN
CheckInfo.Violation := TRUE;
CheckInfo.CheckKind := PeriodCheck;
CheckInfo.DetTime := NOW - TestDly;
CheckInfo.State := TestValue;
VitalMemoryReportViolation (TestSignalName, "", i,
HeaderMsg, CheckInfo, MsgFormat, MsgSeverity );
END IF; -- MsgOn
END IF;
END IF;
PeriodData(i).Last := TestValue;
END LOOP;
END VitalMemoryPeriodPulseCheck;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryPeriodPulseCheck (
VARIABLE Violation : OUT X01ArrayT;
VARIABLE PeriodData : INOUT VitalPeriodDataArrayType;
SIGNAL TestSignal : IN std_logic_vector;
CONSTANT TestSignalName : IN STRING := "";
CONSTANT TestDelay : IN VitalDelayArraytype;
CONSTANT Period : IN VitalDelayArraytype;
CONSTANT PulseWidthHigh : IN VitalDelayArraytype;
CONSTANT PulseWidthLow : IN VitalDelayArraytype;
CONSTANT CheckEnabled : IN BOOLEAN := TRUE;
CONSTANT HeaderMsg : IN STRING := " ";
CONSTANT XOn : IN BOOLEAN := TRUE;
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING;
CONSTANT MsgFormat : IN VitalMemoryMsgFormatType
)IS
VARIABLE TestDly : VitalDelayType;
VARIABLE CheckInfo : CheckInfoType;
VARIABLE PeriodObs : VitalDelayType;
VARIABLE PulseTest : BOOLEAN;
VARIABLE PeriodTest: BOOLEAN;
VARIABLE TestValue : X01;
BEGIN
FOR i IN TestSignal'RANGE LOOP
TestDly := Maximum(0 ns, TestDelay(i));
TestValue := To_X01(TestSignal(i));
IF (PeriodData(i).NotFirstFlag = FALSE) THEN
PeriodData(i).Rise := -Maximum(Period(i),
Maximum(PulseWidthHigh(i),PulseWidthLow(i)));
PeriodData(i).Fall := -Maximum(Period(i),
Maximum(PulseWidthHigh(i),PulseWidthLow(i)));
PeriodData(i).Last := TestValue;
PeriodData(i).NotFirstFlag := TRUE;
END IF;
-- Initialize for no violation
Violation(i) := '0';
-- No violation possible if no test signal change
NEXT WHEN (PeriodData(i).Last = TestValue);
-- record starting pulse times
IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'P')) THEN
-- Compute period times, then record the High Rise Time
PeriodObs := NOW - PeriodData(i).Rise;
PeriodData(i).Rise := NOW;
PeriodTest := TRUE;
ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'N')) THEN
-- Compute period times, then record the Low Fall Time
PeriodObs := NOW - PeriodData(i).Fall;
PeriodData(i).Fall := NOW;
PeriodTest := TRUE;
ELSE
PeriodTest := FALSE;
END IF;
-- do checks on pulse ends
IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'p')) THEN
-- Compute pulse times
CheckInfo.ObsTime := NOW - PeriodData(i).Fall;
CheckInfo.ExpTime := PulseWidthLow(i);
PulseTest := TRUE;
ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'n')) THEN
-- Compute pulse times
CheckInfo.ObsTime := NOW - PeriodData(i).Rise;
CheckInfo.ExpTime := PulseWidthHigh(i);
PulseTest := TRUE;
ELSE
PulseTest := FALSE;
END IF;
IF (PulseTest AND CheckEnabled) THEN
-- Verify Pulse Width [ignore 1st edge]
IF (CheckInfo.ObsTime < CheckInfo.ExpTime) THEN
IF (XOn) THEN
Violation(i) := 'X';
END IF;
IF (MsgOn) THEN
CheckInfo.Violation := TRUE;
CheckInfo.CheckKind := PulseWidCheck;
CheckInfo.DetTime := NOW - TestDly;
CheckInfo.State := PeriodData(i).Last;
VitalMemoryReportViolation (TestSignalName, "", i,
HeaderMsg, CheckInfo, MsgFormat, MsgSeverity );
END IF; -- MsgOn
END IF;
END IF;
IF (PeriodTest AND CheckEnabled) THEN
-- Verify the Period [ignore 1st edge]
CheckInfo.ObsTime := PeriodObs;
CheckInfo.ExpTime := Period(i);
IF ( CheckInfo.ObsTime < CheckInfo.ExpTime ) THEN
IF (XOn) THEN
Violation(i) := 'X';
END IF;
IF (MsgOn) THEN
CheckInfo.Violation := TRUE;
CheckInfo.CheckKind := PeriodCheck;
CheckInfo.DetTime := NOW - TestDly;
CheckInfo.State := TestValue;
VitalMemoryReportViolation (TestSignalName, "", i,
HeaderMsg, CheckInfo, MsgFOrmat, MsgSeverity );
END IF; -- MsgOn
END IF;
END IF;
PeriodData(i).Last := TestValue;
END LOOP;
END VitalMemoryPeriodPulseCheck;
-- ----------------------------------------------------------------------------
-- Functionality Section
-- ----------------------------------------------------------------------------
-- Look-up table. Given an int, we can get the 4-bit bit_vector.
TYPE HexToBitvTableType IS ARRAY (NATURAL RANGE <>) OF
std_logic_vector(3 DOWNTO 0) ;
CONSTANT HexToBitvTable : HexToBitvTableType (0 TO 15) :=
(
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
) ;
-- ----------------------------------------------------------------------------
-- Misc Utilities Local Utilities
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- Procedure: IsSpace
-- Parameters: ch -- input character
-- Description: Returns TRUE or FALSE depending on the input character
-- being white space or not.
-- ----------------------------------------------------------------------------
FUNCTION IsSpace (ch : character)
RETURN boolean IS
BEGIN
RETURN ((ch = ' ') OR (ch = CR) OR (ch = HT) OR (ch = NUL));
END IsSpace;
-- ----------------------------------------------------------------------------
-- Procedure: LenOfString
-- Parameters: Str -- input string
-- Description: Returns the NATURAL length of the input string.
-- as terminated by the first NUL character.
-- ----------------------------------------------------------------------------
FUNCTION LenOfString (Str : STRING)
RETURN NATURAL IS
VARIABLE StrRight : NATURAL;
BEGIN
StrRight := Str'RIGHT;
FOR i IN Str'RANGE LOOP
IF (Str(i) = NUL) THEN
StrRight := i - 1;
EXIT;
END IF;
END LOOP;
RETURN (StrRight);
END LenOfString;
-- ----------------------------------------------------------------------------
-- Procedure: HexToInt
-- Parameters: Hex -- input character or string
-- Description: Converts input character or string interpreted as a
-- hexadecimal representation to integer value.
-- ----------------------------------------------------------------------------
FUNCTION HexToInt(Hex : CHARACTER) RETURN INTEGER IS
CONSTANT HexChars : STRING := "0123456789ABCDEFabcdef";
CONSTANT XHiChar : CHARACTER := 'X';
CONSTANT XLoChar : CHARACTER := 'x';
BEGIN
IF (Hex = XLoChar OR Hex = XHiChar) THEN
RETURN (23);
END IF;
FOR i IN 1 TO 16 LOOP
IF(Hex = HexChars(i)) THEN
RETURN (i-1);
END IF;
END LOOP;
FOR i IN 17 TO 22 LOOP
IF (Hex = HexChars(i)) THEN
RETURN (i-7);
END IF;
END LOOP;
ASSERT FALSE REPORT
"Invalid character received by HexToInt function"
SEVERITY WARNING;
RETURN (0);
END HexToInt;
-- ----------------------------------------------------------------------------
FUNCTION HexToInt (Hex : STRING) RETURN INTEGER IS
VARIABLE Value : INTEGER := 0;
VARIABLE Length : INTEGER;
BEGIN
Length := LenOfString(hex);
IF (Length > 8) THEN
ASSERT FALSE REPORT
"Invalid string length received by HexToInt function"
SEVERITY WARNING;
ELSE
FOR i IN 1 TO Length LOOP
Value := Value + HexToInt(Hex(i)) * 16 ** (Length - i);
END LOOP;
END IF;
RETURN (Value);
END HexToInt;
-- ----------------------------------------------------------------------------
-- Procedure: HexToBitv
-- Parameters: Hex -- Input hex string
-- Description: Converts input hex string to a std_logic_vector
-- ----------------------------------------------------------------------------
FUNCTION HexToBitv(
Hex : STRING
) RETURN std_logic_vector is
VARIABLE Index : INTEGER := 0 ;
VARIABLE ValHexToInt : INTEGER ;
VARIABLE BitsPerHex : INTEGER := 4 ; -- Denotes no. of bits per hex char.
VARIABLE HexLen : NATURAL := (BitsPerHex * LenOfString(Hex)) ;
VARIABLE TableVal : std_logic_vector(3 DOWNTO 0) ;
VARIABLE Result : std_logic_vector(HexLen-1 DOWNTO 0) ;
BEGIN
-- Assign 4-bit wide bit vector to result directly from a look-up table.
Index := 0 ;
WHILE ( Index < HexLen ) LOOP
ValHexToInt := HexToInt( Hex((HexLen - Index)/BitsPerHex ) );
IF ( ValHexToInt = 23 ) THEN
TableVal := "XXXX";
ELSE
-- Look up from the table.
TableVal := HexToBitvTable( ValHexToInt ) ;
END IF;
-- Assign now.
Result(Index+3 DOWNTO Index) := TableVal ;
-- Get ready for next block of 4-bits.
Index := Index + 4 ;
END LOOP ;
RETURN Result ;
END HexToBitv ;
-- ----------------------------------------------------------------------------
-- Procedure: BinToBitv
-- Parameters: Bin -- Input bin string
-- Description: Converts input bin string to a std_logic_vector
-- ----------------------------------------------------------------------------
FUNCTION BinToBitv(
Bin : STRING
) RETURN std_logic_vector is
VARIABLE Index : INTEGER := 0 ;
VARIABLE Length : NATURAL := LenOfString(Bin);
VARIABLE BitVal : std_ulogic;
VARIABLE Result : std_logic_vector(Length-1 DOWNTO 0) ;
BEGIN
Index := 0 ;
WHILE ( Index < Length ) LOOP
IF (Bin(Length-Index) = '0') THEN
BitVal := '0';
ELSIF (Bin(Length-Index) = '1') THEN
BitVal := '1';
ELSE
BitVal := 'X';
END IF ;
-- Assign now.
Result(Index) := BitVal ;
Index := Index + 1 ;
END LOOP ;
RETURN Result ;
END BinToBitv ;
-- ----------------------------------------------------------------------------
-- For Memory Table Modeling
-- ----------------------------------------------------------------------------
TYPE To_MemoryCharType IS ARRAY (VitalMemorySymbolType) OF CHARACTER;
CONSTANT To_MemoryChar : To_MemoryCharType :=
( '/', '\', 'P', 'N', 'r', 'f', 'p', 'n', 'R', 'F', '^', 'v',
'E', 'A', 'D', '*', 'X', '0', '1', '-', 'B', 'Z', 'S',
'g', 'u', 'i', 'G', 'U', 'I',
'w', 's',
'c', 'l', 'd', 'e', 'C', 'L',
'M', 'm', 't' );
TYPE ValidMemoryTableInputType IS ARRAY (VitalMemorySymbolType) OF BOOLEAN;
CONSTANT ValidMemoryTableInput : ValidMemoryTableInputType :=
-- '/', '\', 'P', 'N', 'r', 'f',
( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
-- 'p', 'n', 'R', 'F', '^', 'v',
TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
-- 'E', 'A', 'D', '*',
TRUE, TRUE, TRUE, TRUE,
-- 'X', '0', '1', '-', 'B', 'Z',
TRUE, TRUE, TRUE, TRUE, TRUE, FALSE,
-- 'S',
TRUE,
-- 'g', 'u', 'i', 'G', 'U', 'I',
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
-- 'w', 's',
FALSE, FALSE,
-- 'c', 'l', 'd', 'e', 'C', 'L',
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
-- 'M', 'm', 't'
FALSE, FALSE, FALSE);
TYPE MemoryTableMatchType IS ARRAY (X01,X01,VitalMemorySymbolType) OF BOOLEAN;
-- last value, present value, table symbol
CONSTANT MemoryTableMatch : MemoryTableMatchType := (
( -- X (lastvalue)
-- / \ P N r f
-- p n R F ^ v
-- E A D *
-- X 0 1 - B Z S
-- g u i G U I
-- w s
-- c l d e, C L
-- m t
( FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,
TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE),
( FALSE,FALSE,FALSE,TRUE, FALSE,FALSE,
FALSE,FALSE,FALSE,TRUE, FALSE,TRUE,
TRUE, FALSE,TRUE, TRUE,
FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE),
( FALSE,FALSE,TRUE, FALSE,FALSE,FALSE,
FALSE,FALSE,TRUE, FALSE,TRUE, FALSE,
TRUE, TRUE, FALSE,TRUE,
FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE)
),
(-- 0 (lastvalue)
-- / \ P N r f
-- p n R F ^ v
-- E A D *
-- X 0 1 - B Z S
-- g u i G U I
-- w s
-- c l d e, C L
-- m t
( FALSE,FALSE,FALSE,FALSE,TRUE, FALSE,
TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,
FALSE,TRUE, FALSE,TRUE,
TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE),
( FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,
FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,TRUE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE),
( TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,
TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,TRUE,
FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE)
),
(-- 1 (lastvalue)
-- / \ P N r f
-- p n R F ^ v
-- E A D *
-- X 0 1 - B Z S
-- g u i G U I
-- w s
-- c l d e, C L
-- m t
( FALSE,FALSE,FALSE,FALSE,FALSE,TRUE ,
FALSE,TRUE, FALSE,TRUE, FALSE,FALSE,
FALSE,FALSE,TRUE, TRUE,
TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE),
( FALSE,TRUE, FALSE,TRUE, FALSE,FALSE,
FALSE,TRUE, FALSE,TRUE, FALSE,FALSE,
FALSE,FALSE,FALSE,TRUE,
FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE),
( FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,TRUE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,
FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
FALSE,FALSE,FALSE)
)
);
-- ----------------------------------------------------------------------------
-- Error Message Types and Tables
-- ----------------------------------------------------------------------------
TYPE VitalMemoryErrorType IS (
ErrGoodAddr, -- 'g' Good address (no transition)
ErrUnknAddr, -- 'u' 'X' levels in address (no transition)
ErrInvaAddr, -- 'i' Invalid address (no transition)
ErrGoodTrAddr, -- 'G' Good address (with transition)
ErrUnknTrAddr, -- 'U' 'X' levels in address (with transition)
ErrInvaTrAddr, -- 'I' Invalid address (with transition)
ErrWrDatMem, -- 'w' Writing data to memory
ErrNoChgMem, -- 's' Retaining previous memory contents
ErrCrAllMem, -- 'c' Corrupting entire memory with 'X'
ErrCrWrdMem, -- 'l' Corrupting a word in memory with 'X'
ErrCrBitMem, -- 'd' Corrupting a single bit in memory with 'X'
ErrCrDatMem, -- 'e' Corrupting a word with 'X' based on data in
ErrCrAllSubMem,-- 'C' Corrupting a sub-word entire memory with 'X'
ErrCrWrdSubMem,-- 'L' Corrupting a sub-word in memory with 'X'
ErrCrBitSubMem,-- 'D' Corrupting a single bit of a memory sub-word with 'X'
ErrCrDatSubMem,-- 'E' Corrupting a sub-word with 'X' based on data in
ErrCrWrdOut, -- 'l' Corrupting data out with 'X'
ErrCrBitOut, -- 'd' Corrupting a single bit of data out with 'X'
ErrCrDatOut, -- 'e' Corrupting data out with 'X' based on data in
ErrCrWrdSubOut,-- 'L' Corrupting data out sub-word with 'X'
ErrCrBitSubOut,-- 'D' Corrupting a single bit of data out sub-word with 'X'
ErrCrDatSubOut,-- 'E' Corrupting data out sub-word with 'X' based on data in
ErrImplOut, -- 'M' Implicit read from memory to data out
ErrReadOut, -- 'm' Reading data from memory to data out
ErrAssgOut, -- 't' Transferring from data in to data out
ErrAsgXOut, -- 'X' Assigning unknown level to data out
ErrAsg0Out, -- '0' Assigning low level to data out
ErrAsg1Out, -- '1' Assigning high level to data out
ErrAsgZOut, -- 'Z' Assigning high impedence to data out
ErrAsgSOut, -- 'S' Keeping data out at steady value
ErrAsgXMem, -- 'X' Assigning unknown level to memory location
ErrAsg0Mem, -- '0' Assigning low level to memory location
ErrAsg1Mem, -- '1' Assigning high level to memory location
ErrAsgZMem, -- 'Z' Assigning high impedence to memory location
ErrDefMemAct, -- No memory table match, using default action
ErrInitMem, -- Initialize memory contents
ErrMcpWrCont, -- Memory cross port to same port write contention
ErrMcpCpCont, -- Memory cross port read/write data/memory contention
ErrMcpCpRead, -- Memory cross port read to same port
ErrMcpRdWrCo, -- Memory cross port read/write data only contention
ErrMcpCpWrCont,-- Memory cross port to cross port write contention
ErrUnknMemDo, -- Unknown memory action
ErrUnknDatDo, -- Unknown data action
ErrUnknSymbol, -- Illegal memory symbol
ErrLdIlgArg,
ErrLdAddrRng,
ErrLdMemInfo,
ErrLdFileEmpty,
ErrPrintString
);
TYPE VitalMemoryErrorSeverityType IS
ARRAY (VitalMemoryErrorType) OF SEVERITY_LEVEL;
CONSTANT VitalMemoryErrorSeverity :
VitalMemoryErrorSeverityType := (
ErrGoodAddr => NOTE,
ErrUnknAddr => WARNING,
ErrInvaAddr => WARNING,
ErrGoodTrAddr => NOTE,
ErrUnknTrAddr => WARNING,
ErrInvaTrAddr => WARNING,
ErrWrDatMem => NOTE,
ErrNoChgMem => NOTE,
ErrCrAllMem => WARNING,
ErrCrWrdMem => WARNING,
ErrCrBitMem => WARNING,
ErrCrDatMem => WARNING,
ErrCrAllSubMem => WARNING,
ErrCrWrdSubMem => WARNING,
ErrCrBitSubMem => WARNING,
ErrCrDatSubMem => WARNING,
ErrCrWrdOut => WARNING,
ErrCrBitOut => WARNING,
ErrCrDatOut => WARNING,
ErrCrWrdSubOut => WARNING,
ErrCrBitSubOut => WARNING,
ErrCrDatSubOut => WARNING,
ErrImplOut => NOTE,
ErrReadOut => NOTE,
ErrAssgOut => NOTE,
ErrAsgXOut => NOTE,
ErrAsg0Out => NOTE,
ErrAsg1Out => NOTE,
ErrAsgZOut => NOTE,
ErrAsgSOut => NOTE,
ErrAsgXMem => NOTE,
ErrAsg0Mem => NOTE,
ErrAsg1Mem => NOTE,
ErrAsgZMem => NOTE,
ErrDefMemAct => NOTE,
ErrInitMem => NOTE,
ErrMcpWrCont => WARNING,
ErrMcpCpCont => WARNING,
ErrMcpCpRead => WARNING,
ErrMcpRdWrCo => WARNING,
ErrMcpCpWrCont => WARNING,
ErrUnknMemDo => ERROR,
ErrUnknDatDo => ERROR,
ErrUnknSymbol => ERROR,
ErrLdIlgArg => ERROR,
ErrLdAddrRng => WARNING,
ErrLdMemInfo => NOTE,
ErrLdFileEmpty => ERROR,
ErrPrintString => WARNING
);
-- ----------------------------------------------------------------------------
CONSTANT MsgGoodAddr : STRING
:= "Good address (no transition)";
CONSTANT MsgUnknAddr : STRING
:= "Unknown address (no transition)";
CONSTANT MsgInvaAddr : STRING
:= "Invalid address (no transition)";
CONSTANT MsgGoodTrAddr : STRING
:= "Good address (with transition)";
CONSTANT MsgUnknTrAddr : STRING
:= "Unknown address (with transition)";
CONSTANT MsgInvaTrAddr : STRING
:= "Invalid address (with transition)";
CONSTANT MsgNoChgMem : STRING
:= "Retaining previous memory contents";
CONSTANT MsgWrDatMem : STRING
:= "Writing data to memory";
CONSTANT MsgCrAllMem : STRING
:= "Corrupting entire memory with 'X'";
CONSTANT MsgCrWrdMem : STRING
:= "Corrupting a word in memory with 'X'";
CONSTANT MsgCrBitMem : STRING
:= "Corrupting a single bit in memory with 'X'";
CONSTANT MsgCrDatMem : STRING
:= "Corrupting a word with 'X' based on data in";
CONSTANT MsgCrAllSubMem : STRING
:= "Corrupting a sub-word entire memory with 'X'";
CONSTANT MsgCrWrdSubMem : STRING
:= "Corrupting a sub-word in memory with 'X'";
CONSTANT MsgCrBitSubMem : STRING
:= "Corrupting a single bit of a sub-word with 'X'";
CONSTANT MsgCrDatSubMem : STRING
:= "Corrupting a sub-word with 'X' based on data in";
CONSTANT MsgCrWrdOut : STRING
:= "Corrupting data out with 'X'";
CONSTANT MsgCrBitOut : STRING
:= "Corrupting a single bit of data out with 'X'";
CONSTANT MsgCrDatOut : STRING
:= "Corrupting data out with 'X' based on data in";
CONSTANT MsgCrWrdSubOut : STRING
:= "Corrupting data out sub-word with 'X'";
CONSTANT MsgCrBitSubOut : STRING
:= "Corrupting a single bit of data out sub-word with 'X'";
CONSTANT MsgCrDatSubOut : STRING
:= "Corrupting data out sub-word with 'X' based on data in";
CONSTANT MsgImplOut : STRING
:= "Implicit read from memory to data out";
CONSTANT MsgReadOut : STRING
:= "Reading data from memory to data out";
CONSTANT MsgAssgOut : STRING
:= "Transferring from data in to data out";
CONSTANT MsgAsgXOut : STRING
:= "Assigning unknown level to data out";
CONSTANT MsgAsg0Out : STRING
:= "Assigning low level to data out";
CONSTANT MsgAsg1Out : STRING
:= "Assigning high level to data out";
CONSTANT MsgAsgZOut : STRING
:= "Assigning high impedance to data out";
CONSTANT MsgAsgSOut : STRING
:= "Keeping data out at steady value";
CONSTANT MsgAsgXMem : STRING
:= "Assigning unknown level to memory location";
CONSTANT MsgAsg0Mem : STRING
:= "Assigning low level to memory location";
CONSTANT MsgAsg1Mem : STRING
:= "Assigning high level to memory location";
CONSTANT MsgAsgZMem : STRING
:= "Assigning high impedance to memory location";
CONSTANT MsgDefMemAct : STRING
:= "No memory table match, using default action";
CONSTANT MsgInitMem : STRING
:= "Initializing memory contents";
CONSTANT MsgMcpWrCont : STRING
:= "Same port write contention";
CONSTANT MsgMcpCpCont : STRING
:= "Cross port read/write data/memory contention";
CONSTANT MsgMcpCpRead : STRING
:= "Cross port read to same port";
CONSTANT MsgMcpRdWrCo : STRING
:= "Cross port read/write data only contention";
CONSTANT MsgMcpCpWrCont : STRING
:= "Cross port write contention";
CONSTANT MsgUnknMemDo : STRING
:= "Unknown memory action";
CONSTANT MsgUnknDatDo : STRING
:= "Unknown data action";
CONSTANT MsgUnknSymbol : STRING
:= "Illegal memory symbol";
CONSTANT MsgLdIlgArg : STRING
:= "Illegal bit arguments while loading memory.";
CONSTANT MsgLdMemInfo : STRING
:= "Loading data from the file into memory.";
CONSTANT MsgLdAddrRng : STRING
:= "Address out of range while loading memory.";
CONSTANT MsgLdFileEmpty : STRING
:= "Memory load file is empty.";
CONSTANT MsgPrintString : STRING
:= "";
CONSTANT MsgUnknown : STRING
:= "Unknown error message.";
CONSTANT MsgVMT : STRING
:= "VitalMemoryTable";
CONSTANT MsgVMV : STRING
:= "VitalMemoryViolation";
CONSTANT MsgVDM : STRING
:= "VitalDeclareMemory";
CONSTANT MsgVMCP : STRING
:= "VitalMemoryCrossPorts";
-- ----------------------------------------------------------------------------
-- LOCAL Utilities
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- Procedure: MemoryMessage
-- Parameters: ErrorId -- Input error code
-- Description: This function looks up the input error code and returns
-- the string value of the associated message.
-- ----------------------------------------------------------------------------
FUNCTION MemoryMessage (
CONSTANT ErrorId : IN VitalMemoryErrorType
) RETURN STRING IS
BEGIN
CASE ErrorId IS
WHEN ErrGoodAddr => RETURN MsgGoodAddr ;
WHEN ErrUnknAddr => RETURN MsgUnknAddr ;
WHEN ErrInvaAddr => RETURN MsgInvaAddr ;
WHEN ErrGoodTrAddr => RETURN MsgGoodTrAddr ;
WHEN ErrUnknTrAddr => RETURN MsgUnknTrAddr ;
WHEN ErrInvaTrAddr => RETURN MsgInvaTrAddr ;
WHEN ErrWrDatMem => RETURN MsgWrDatMem ;
WHEN ErrNoChgMem => RETURN MsgNoChgMem ;
WHEN ErrCrAllMem => RETURN MsgCrAllMem ;
WHEN ErrCrWrdMem => RETURN MsgCrWrdMem ;
WHEN ErrCrBitMem => RETURN MsgCrBitMem ;
WHEN ErrCrDatMem => RETURN MsgCrDatMem ;
WHEN ErrCrAllSubMem => RETURN MsgCrAllSubMem;
WHEN ErrCrWrdSubMem => RETURN MsgCrWrdSubMem;
WHEN ErrCrBitSubMem => RETURN MsgCrBitSubMem;
WHEN ErrCrDatSubMem => RETURN MsgCrDatSubMem;
WHEN ErrCrWrdOut => RETURN MsgCrWrdOut ;
WHEN ErrCrBitOut => RETURN MsgCrBitOut ;
WHEN ErrCrDatOut => RETURN MsgCrDatOut ;
WHEN ErrCrWrdSubOut => RETURN MsgCrWrdSubOut;
WHEN ErrCrBitSubOut => RETURN MsgCrBitSubOut;
WHEN ErrCrDatSubOut => RETURN MsgCrDatSubOut;
WHEN ErrImplOut => RETURN MsgImplOut ;
WHEN ErrReadOut => RETURN MsgReadOut ;
WHEN ErrAssgOut => RETURN MsgAssgOut ;
WHEN ErrAsgXOut => RETURN MsgAsgXOut ;
WHEN ErrAsg0Out => RETURN MsgAsg0Out ;
WHEN ErrAsg1Out => RETURN MsgAsg1Out ;
WHEN ErrAsgZOut => RETURN MsgAsgZOut ;
WHEN ErrAsgSOut => RETURN MsgAsgSOut ;
WHEN ErrAsgXMem => RETURN MsgAsgXMem ;
WHEN ErrAsg0Mem => RETURN MsgAsg0Mem ;
WHEN ErrAsg1Mem => RETURN MsgAsg1Mem ;
WHEN ErrAsgZMem => RETURN MsgAsgZMem ;
WHEN ErrDefMemAct => RETURN MsgDefMemAct ;
WHEN ErrInitMem => RETURN MsgInitMem ;
WHEN ErrMcpWrCont => RETURN MsgMcpWrCont ;
WHEN ErrMcpCpCont => RETURN MsgMcpCpCont ;
WHEN ErrMcpCpRead => RETURN MsgMcpCpRead ;
WHEN ErrMcpRdWrCo => RETURN MsgMcpRdWrCo ;
WHEN ErrMcpCpWrCont => RETURN MsgMcpCpWrCont;
WHEN ErrUnknMemDo => RETURN MsgUnknMemDo ;
WHEN ErrUnknDatDo => RETURN MsgUnknDatDo ;
WHEN ErrUnknSymbol => RETURN MsgUnknSymbol ;
WHEN ErrLdIlgArg => RETURN MsgLdIlgArg ;
WHEN ErrLdAddrRng => RETURN MsgLdAddrRng ;
WHEN ErrLdMemInfo => RETURN MsgLdMemInfo ;
WHEN ErrLdFileEmpty => RETURN MsgLdFileEmpty;
WHEN ErrPrintString => RETURN MsgPrintString;
WHEN OTHERS => RETURN MsgUnknown ;
END CASE;
END;
-- ----------------------------------------------------------------------------
-- Procedure: PrintMemoryMessage
-- Parameters: Routine -- String identifying the calling routine
-- ErrorId -- Input error code for message lookup
-- Info -- Output string or character
-- InfoStr -- Additional output string
-- Info1 -- Additional output integer
-- Info2 -- Additional output integer
-- Info3 -- Additional output integer
-- Description: This procedure prints out a memory status message
-- given the input error id and other status information.
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT ErrorId : IN VitalMemoryErrorType
) IS
BEGIN
ASSERT FALSE
REPORT Routine & ": " & MemoryMessage(ErrorId)
SEVERITY VitalMemoryErrorSeverity(ErrorId);
END;
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT ErrorId : IN VitalMemoryErrorType;
CONSTANT Info : IN STRING
) IS
BEGIN
ASSERT FALSE
REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & Info
SEVERITY VitalMemoryErrorSeverity(ErrorId);
END;
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT ErrorId : IN VitalMemoryErrorType;
CONSTANT Info1 : IN STRING;
CONSTANT Info2 : IN STRING
) IS
BEGIN
ASSERT FALSE
REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & Info1 & " " & Info2
SEVERITY VitalMemoryErrorSeverity(ErrorId);
END;
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT ErrorId : IN VitalMemoryErrorType;
CONSTANT Info : IN CHARACTER
) IS
BEGIN
ASSERT FALSE
REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & Info
SEVERITY VitalMemoryErrorSeverity(ErrorId);
END;
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT ErrorId : IN VitalMemoryErrorType;
CONSTANT InfoStr : IN STRING;
CONSTANT Info1 : IN NATURAL
) IS
VARIABLE TmpStr : STRING ( 1 TO 256 ) ;
VARIABLE TmpInt : INTEGER := 1;
BEGIN
IntToStr(Info1,TmpStr,TmpInt);
ASSERT FALSE
REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & InfoStr & " " & TmpStr
SEVERITY VitalMemoryErrorSeverity(ErrorId);
END;
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT ErrorId : IN VitalMemoryErrorType;
CONSTANT InfoStr : IN STRING;
CONSTANT Info1 : IN NATURAL;
CONSTANT Info2 : IN NATURAL
) IS
VARIABLE TmpStr : STRING ( 1 TO 256 ) ;
VARIABLE TmpInt : INTEGER := 1;
BEGIN
IntToStr(Info1,TmpStr,TmpInt);
IntToStr(Info2,TmpStr,TmpInt);
ASSERT FALSE
REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & InfoStr & " " & TmpStr
SEVERITY VitalMemoryErrorSeverity(ErrorId);
END;
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT ErrorId : IN VitalMemoryErrorType;
CONSTANT InfoStr : IN STRING;
CONSTANT Info1 : IN NATURAL;
CONSTANT Info2 : IN NATURAL;
CONSTANT Info3 : IN NATURAL
) IS
VARIABLE TmpStr : STRING ( 1 TO 256 ) ;
VARIABLE TmpInt : INTEGER := 1;
BEGIN
IntToStr(Info1,TmpStr,TmpInt);
IntToStr(Info2,TmpStr,TmpInt);
IntToStr(Info3,TmpStr,TmpInt);
ASSERT FALSE
REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & InfoStr & " " & TmpStr
SEVERITY VitalMemoryErrorSeverity(ErrorId);
END;
-- ----------------------------------------------------------------------------
PROCEDURE PrintMemoryMessage (
CONSTANT Routine : IN STRING;
CONSTANT Table : IN VitalMemoryTableType;
CONSTANT Index : IN INTEGER;
CONSTANT InfoStr : IN STRING
) IS
CONSTANT TableEntries : INTEGER := Table'LENGTH(1);
CONSTANT TableWidth : INTEGER := Table'LENGTH(2);
VARIABLE TmpStr : STRING ( 1 TO 256 ) ;
VARIABLE TmpInt : INTEGER := 1;
BEGIN
IF (Index < 0 AND Index > TableEntries-1) THEN
ASSERT FALSE
REPORT Routine & ": Memory table search failure"
SEVERITY ERROR;
END IF;
ColLoop:
FOR i IN 0 TO TableWidth-1 LOOP
IF (i >= 64) THEN
TmpStr(TmpInt) := '.';
TmpInt := TmpInt + 1;
TmpStr(TmpInt) := '.';
TmpInt := TmpInt + 1;
TmpStr(TmpInt) := '.';
TmpInt := TmpInt + 1;
EXIT ColLoop;
END IF;
TmpStr(TmpInt) := ''';
TmpInt := TmpInt + 1;
TmpStr(TmpInt) := To_MemoryChar(Table(Index,i));
TmpInt := TmpInt + 1;
TmpStr(TmpInt) := ''';
TmpInt := TmpInt + 1;
IF (i < TableWidth-1) THEN
TmpStr(TmpInt) := ',';
TmpInt := TmpInt + 1;
END IF;
END LOOP;
ASSERT FALSE
REPORT Routine & ": Port=" & InfoStr & " TableRow=" & TmpStr
SEVERITY NOTE;
END;
-- ----------------------------------------------------------------------------
-- Procedure: DecodeAddress
-- Parameters: Address - Converted address.
-- AddrFlag - Flag to indicte address match
-- MemoryData - Information about memory characteristics
-- PrevAddressBus - Previous input address value
-- AddressBus - Input address value.
-- Description: This procedure is used for transforming a valid
-- address value to an integer in order to access memory.
-- It performs address bound checking as well.
-- Sets Address to -1 for unknowns
-- Sets Address to -2 for out of range
-- ----------------------------------------------------------------------------
PROCEDURE DecodeAddress (
VARIABLE Address : INOUT INTEGER;
VARIABLE AddrFlag : INOUT VitalMemorySymbolType;
VARIABLE MemoryData : IN VitalMemoryDataType;
CONSTANT PrevAddressBus : IN std_logic_vector;
CONSTANT AddressBus : IN std_logic_vector
) IS
VARIABLE Power : NATURAL;
VARIABLE AddrUnkn : BOOLEAN;
BEGIN
Power := 0;
AddrUnkn := FALSE;
-- It is assumed that always Address'LEFT represents the Most significant bit.
FOR i IN AddressBus'RANGE LOOP
Power := Power * 2;
IF (AddressBus(i) /= '1' AND AddressBus(i) /= '0') THEN
AddrUnkn := TRUE;
Power := 0;
EXIT;
ELSIF (AddressBus(i) = '1') THEN
Power := Power + 1;
END IF;
END LOOP;
Address := Power;
AddrFlag := 'g';
IF (AddrUnkn) THEN
AddrFlag := 'u'; -- unknown addr
Address := -1;
END IF;
IF ( Power > (MemoryData.NoOfWords - 1)) THEN
AddrFlag := 'i'; -- invalid addr
Address := -2;
END IF;
IF (PrevAddressBus /= AddressBus) THEN
CASE AddrFlag IS
WHEN 'g' => AddrFlag := 'G';
WHEN 'u' => AddrFlag := 'U';
WHEN 'i' => AddrFlag := 'I';
WHEN OTHERS =>
ASSERT FALSE REPORT
"DecodeAddress: Internal error. [AddrFlag]="
& To_MemoryChar(AddrFlag)
SEVERITY ERROR;
END CASE;
END IF;
END DecodeAddress;
-- ----------------------------------------------------------------------------
-- Procedure: DecodeData
-- Parameters: DataFlag - Flag to indicte data match
-- PrevDataInBus - Previous input data value
-- DataInBus - Input data value.
-- HighBit - High bit offset value.
-- LowBit - Low bit offset value.
-- Description: This procedure is used for interpreting the input data
-- as a data flag for subsequent table matching.
-- ----------------------------------------------------------------------------
PROCEDURE DecodeData (
VARIABLE DataFlag : INOUT VitalMemorySymbolType;
CONSTANT PrevDataInBus : IN std_logic_vector;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT HighBit : IN NATURAL;
CONSTANT LowBit : IN NATURAL
) IS
VARIABLE DataUnkn : BOOLEAN := FALSE;
BEGIN
FOR i IN LowBit TO HighBit LOOP
IF DataInBus(i) /= '1' AND DataInBus(i) /= '0' THEN
DataUnkn := TRUE;
EXIT;
END IF;
END LOOP;
DataFlag := 'g';
IF (DataUnkn) THEN
DataFlag := 'u'; -- unknown addr
END IF;
IF (PrevDataInBus(HighBit DOWNTO LowBit) /=
DataInBus(HighBit DOWNTO LowBit)) THEN
CASE DataFlag IS
WHEN 'g' => DataFlag := 'G';
WHEN 'u' => DataFlag := 'U';
WHEN OTHERS =>
ASSERT FALSE REPORT
"DecodeData: Internal error. [DataFlag]="
& To_MemoryChar(DataFlag)
SEVERITY ERROR;
END CASE;
END IF;
END DecodeData;
-- ----------------------------------------------------------------------------
-- Procedure: WriteMemory
-- Parameters: MemoryPtr - Pointer to the memory array.
-- DataInBus - Input Data to be written.
-- Address - Address of the memory location.
-- BitPosition - Position of bit in memory location.
-- HighBit - High bit offset value.
-- LowBit - Low bit offset value.
-- Description: This procedure is used to write to a memory location
-- on a bit/byte/word basis.
-- The high bit and low bit offset are used for byte write
-- operations.These parameters specify the data byte for write.
-- In the case of word write the complete memory word is used.
-- This procedure is overloaded for bit,byte and word write
-- memory operations.The number of parameters may vary.
-- ----------------------------------------------------------------------------
PROCEDURE WriteMemory (
VARIABLE MemoryPtr : INOUT VitalMemoryDataType;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT Address : IN INTEGER;
CONSTANT HighBit : IN NATURAL;
CONSTANT LowBit : IN NATURAL
) IS
VARIABLE TmpData : std_logic_vector(DataInBus'LENGTH - 1 DOWNTO 0);
BEGIN
-- Address bound checking.
IF ( Address < 0 OR Address > (MemoryPtr.NoOfWords - 1)) THEN
PrintMemoryMessage ( "WriteMemory", ErrPrintString,
"Aborting write operation as address is out of range.") ;
RETURN;
END IF;
TmpData := To_UX01(DataInBus);
FOR i in LowBit to HighBit LOOP
MemoryPtr.MemoryArrayPtr(Address).all(i) := TmpData(i);
END LOOP;
END WriteMemory;
-- ----------------------------------------------------------------------------
PROCEDURE WriteMemory (
VARIABLE MemoryPtr : INOUT VitalMemoryDataType;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT Address : IN INTEGER;
CONSTANT BitPosition : IN NATURAL
) IS
VARIABLE HighBit : NATURAL;
VARIABLE LowBit : NATURAL;
BEGIN
HighBit := BitPosition;
LowBit := BitPosition;
WriteMemory (MemoryPtr, DataInBus, Address, HighBit, LowBit);
END WriteMemory;
-- ----------------------------------------------------------------------------
PROCEDURE WriteMemory (
VARIABLE MemoryPtr : INOUT VitalMemoryDataType;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT Address : IN INTEGER
) IS
VARIABLE HighBit : NATURAL;
VARIABLE LowBit : NATURAL;
BEGIN
HighBit := MemoryPtr.NoOfBitsPerWord - 1;
LowBit := 0;
WriteMemory (MemoryPtr, DataInBus, Address, HighBit, LowBit);
END WriteMemory;
-- ----------------------------------------------------------------------------
-- Procedure: ReadMemory
-- Parameters: MemoryPtr - Pointer to the memory array.
-- DataOut - Output Data to be read in this.
-- Address - Address of the memory location.
-- BitPosition - Position of bit in memory location.
-- HighBit - High bit offset value.
-- LowBit - Low bit offset value.
-- Description: This procedure is used to read from a memory location
-- on a bit/byte/word basis.
-- The high bit and low bit offset are used for byte write
-- operations.These parameters specify the data byte for
-- read.In the case of word write the complete memory word
-- is used.This procedure is overloaded for bit,byte and
-- word write memory operations.The number of parameters
-- may vary.
-- ----------------------------------------------------------------------------
PROCEDURE ReadMemory (
VARIABLE MemoryPtr : INOUT VitalMemoryDataType;
VARIABLE DataOut : OUT std_logic_vector;
CONSTANT Address : IN INTEGER;
CONSTANT HighBit : IN NATURAL;
CONSTANT LowBit : IN NATURAL
) IS
VARIABLE DataOutTmp : std_logic_vector(MemoryPtr.NoOfBitsPerWord-1 DOWNTO 0);
VARIABLE length : NATURAL := (HighBit - LowBit + 1);
BEGIN
-- Address bound checking.
IF ( Address > (MemoryPtr.NoOfWords - 1)) THEN
PrintMemoryMessage (
"ReadMemory",ErrInvaAddr,
"[Address,NoOfWords]=",Address,MemoryPtr.NoOfWords
);
FOR i in LowBit to HighBit LOOP
DataOutTmp(i) := 'X';
END LOOP;
ELSE
FOR i in LowBit to HighBit LOOP
DataOutTmp(i) := MemoryPtr.MemoryArrayPtr (Address).all(i);
END LOOP;
END IF;
DataOut := DataOutTmp;
END ReadMemory;
-- ----------------------------------------------------------------------------
PROCEDURE ReadMemory (
VARIABLE MemoryPtr : INOUT VitalMemoryDataType;
VARIABLE DataOut : OUT std_logic_vector;
CONSTANT Address : IN INTEGER;
CONSTANT BitPosition : IN NATURAL
) IS
VARIABLE HighBit : NATURAL;
VARIABLE LowBit : NATURAL;
BEGIN
HighBit := BitPosition;
LowBit := BitPosition;
ReadMemory (MemoryPtr, DataOut, Address, HighBit, LowBit);
END ReadMemory;
-- ----------------------------------------------------------------------------
PROCEDURE ReadMemory (
VARIABLE MemoryPtr : INOUT VitalMemoryDataType;
VARIABLE DataOut : OUT std_logic_vector;
CONSTANT Address : IN INTEGER
) IS
VARIABLE HighBit : NATURAL;
VARIABLE LowBit : NATURAL;
BEGIN
HighBit := MemoryPtr.NoOfBitsPerWord - 1;
LowBit := 0;
ReadMemory (MemoryPtr, DataOut, Address, HighBit, LowBit);
END ReadMemory;
-- ----------------------------------------------------------------------------
-- Procedure: LoadMemory
-- Parameters: MemoryPtr - Pointer to the memory array.
-- FileName - Name of the output file.
-- HighBit - High bit offset value.
-- LowBit - Low bit offset value.
-- Description: This procedure is used to load the contents of the memory
-- from a specified input file.
-- The high bit and low bit offset are used so that same task
-- can be used for all bit/byte/word write operations.
-- In the case of a bit write RAM the HighBit and LowBit have
-- the same value.
-- This procedure is overloaded for word write operations.
-- ----------------------------------------------------------------------------
PROCEDURE LoadMemory (
VARIABLE MemoryPtr : INOUT VitalMemoryDataType;
CONSTANT FileName : IN STRING;
CONSTANT BinaryFile : IN BOOLEAN := FALSE
) IS
FILE Fptr : TEXT OPEN read_mode IS FileName;
VARIABLE OneLine : LINE;
VARIABLE Ignore : CHARACTER;
VARIABLE Index : NATURAL := 1;
VARIABLE LineNo : NATURAL := 0;
VARIABLE Address : INTEGER := 0;
VARIABLE DataInBus : std_logic_vector(MemoryPtr.NoOfBitsPerWord-1 DOWNTO 0);
VARIABLE AddrStr : STRING(1 TO 80) ;
VARIABLE DataInStr : STRING(1 TO 255) ;
BEGIN
IF (ENDFILE(fptr)) THEN
PrintMemoryMessage (MsgVDM, ErrLdFileEmpty,
"[FileName]="&FileName);
RETURN;
END IF ;
PrintMemoryMessage (
MsgVDM,ErrLdMemInfo, "[FileName]="&FileName
);
WHILE (NOT ENDFILE(fptr)) LOOP
ReadLine(Fptr, OneLine);
LineNo := LineNo + 1 ;
-- First ignoring leading spaces.
WHILE (OneLine'LENGTH /= 0 and IsSpace(OneLine(1))) LOOP
READ (OneLine, Ignore) ; -- Ignoring the space character.
END LOOP ;
-- Note that, by now oneline has been "stripped" of its leading spaces.
IF ( OneLine(1) = '@' ) THEN
READ (OneLine, Ignore); -- Ignore the '@' character and read the string.
-- Now strip off spaces, if any, between '@' and Address string.
WHILE (OneLine'LENGTH /= 0 and IsSpace(OneLine(1))) LOOP
READ (OneLine, Ignore) ; -- Ignoring the space character.
END LOOP ;
-- Now get the string which represents the address into string variable.
Index := 1;
WHILE (OneLine'LENGTH /= 0 AND (NOT(IsSpace(OneLine(1))))) LOOP
READ(OneLine, AddrStr(Index));
Index := Index + 1;
END LOOP ;
AddrStr(Index) := NUL;
-- Now convert the hex string into a hex integer
Address := HexToInt(AddrStr) ;
ELSE
IF ( LineNo /= 1 ) THEN
Address := Address + 1;
END IF;
END IF ;
IF ( Address > (MemoryPtr.NoOfWords - 1) ) THEN
PrintMemoryMessage (MsgVDM, ErrLdAddrRng,
"[Address,lineno]=", Address, LineNo) ;
EXIT ;
END IF;
-- Now strip off spaces, between Address string and DataInBus string.
WHILE (OneLine'LENGTH /= 0 AND IsSpace(OneLine(1))) LOOP
READ (OneLine, Ignore) ; -- Ignoring the space character.
END LOOP ;
Index := 1;
WHILE (OneLine'LENGTH /= 0 AND (NOT(IsSpace(OneLine(1))))) LOOP
READ(OneLine, DataInStr(Index));
Index := Index + 1;
END LOOP ;
DataInStr(Index) := NUL;
IF (BinaryFile) THEN
DataInBus := BinToBitv (DataInStr);
ELSE
DataInBus := HexToBitv (DataInStr);
END IF ;
WriteMemory (MemoryPtr, DataInBus, Address);
END LOOP ;
END LoadMemory;
-- ----------------------------------------------------------------------------
-- Procedure: MemoryMatch
-- Parameters: Symbol - Symbol from memory table
-- TestFlag - Interpreted data or address symbol
-- In2 - input from VitalMemoryTable procedure
-- to memory table
-- In2LastValue - Previous value of input
-- Err - TRUE if symbol is not a valid input symbol
-- ReturnValue - TRUE if match occurred
-- Description: This procedure sets ReturnValue to true if in2 matches
-- symbol (from the memory table). If symbol is an edge
-- value edge is set to true and in2 and in2LastValue are
-- checked against symbol. Err is set to true if symbol
-- is an invalid value for the input portion of the memory
-- table.
-- ----------------------------------------------------------------------------
PROCEDURE MemoryMatch (
CONSTANT Symbol : IN VitalMemorySymbolType;
CONSTANT In2 : IN std_ulogic;
CONSTANT In2LastValue : IN std_ulogic;
VARIABLE Err : OUT BOOLEAN;
VARIABLE ReturnValue : OUT BOOLEAN
) IS
BEGIN
IF (NOT ValidMemoryTableInput(Symbol) ) THEN
PrintMemoryMessage(MsgVMT,ErrUnknSymbol,To_MemoryChar(Symbol));
Err := TRUE;
ReturnValue := FALSE;
ELSE
ReturnValue := MemoryTableMatch(To_X01(In2LastValue), To_X01(In2), Symbol);
Err := FALSE;
END IF;
END;
-- ----------------------------------------------------------------------------
PROCEDURE MemoryMatch (
CONSTANT Symbol : IN VitalMemorySymbolType;
CONSTANT TestFlag : IN VitalMemorySymbolType;
VARIABLE Err : OUT BOOLEAN;
VARIABLE ReturnValue : OUT BOOLEAN
) IS
BEGIN
Err := FALSE;
ReturnValue := FALSE;
CASE Symbol IS
WHEN 'g'|'u'|'i'|'G'|'U'|'I'|'-'|'*'|'S' =>
IF (Symbol = TestFlag) THEN
ReturnValue := TRUE;
ELSE
CASE Symbol IS
WHEN '-' =>
ReturnValue := TRUE;
Err := FALSE;
WHEN '*' =>
IF (TestFlag = 'G' OR
TestFlag = 'U' OR
TestFlag = 'I') THEN
ReturnValue := TRUE;
Err := FALSE;
END IF;
WHEN 'S' =>
IF (TestFlag = 'g' OR
TestFlag = 'u' OR
TestFlag = 'i') THEN
ReturnValue := TRUE;
Err := FALSE;
END IF;
WHEN OTHERS =>
ReturnValue := FALSE;
END CASE;
END IF;
WHEN OTHERS =>
Err := TRUE;
RETURN;
END CASE;
END;
-- ----------------------------------------------------------------------------
-- Procedure: MemoryTableCorruptMask
-- Description: Compute memory and data corruption masks for memory table
-- ----------------------------------------------------------------------------
PROCEDURE MemoryTableCorruptMask (
VARIABLE CorruptMask : OUT std_logic_vector;
CONSTANT Action : IN VitalMemorySymbolType;
CONSTANT EnableIndex : IN INTEGER;
CONSTANT BitsPerWord : IN INTEGER;
CONSTANT BitsPerSubWord : IN INTEGER;
CONSTANT BitsPerEnable : IN INTEGER
) IS
VARIABLE CorruptMaskTmp : std_logic_vector (CorruptMask'RANGE)
:= (OTHERS => '0');
VARIABLE ViolFlAryPosn : INTEGER;
VARIABLE HighBit : INTEGER;
VARIABLE LowBit : INTEGER;
BEGIN
CASE (Action) IS
WHEN 'c'|'l'|'e' =>
-- Corrupt whole word
CorruptMaskTmp := (OTHERS => 'X');
CorruptMask := CorruptMaskTmp;
RETURN;
WHEN 'd'|'C'|'L'|'D'|'E' =>
-- Process corruption below
WHEN OTHERS =>
-- No data or memory corruption
CorruptMaskTmp := (OTHERS => '0');
CorruptMask := CorruptMaskTmp;
RETURN;
END CASE;
IF (Action = 'd') THEN
CorruptMaskTmp := (OTHERS => 'X');
CorruptMask := CorruptMaskTmp;
RETURN;
END IF;
-- Remaining are subword cases 'C', 'L', 'D', 'E'
CorruptMaskTmp := (OTHERS => '0');
LowBit := 0;
HighBit := BitsPerSubWord-1;
SubWordLoop:
FOR i IN 0 TO BitsPerEnable-1 LOOP
IF (i = EnableIndex) THEN
FOR j IN HighBit TO LowBit LOOP
CorruptMaskTmp(j) := 'X';
END LOOP;
END IF;
-- Calculate HighBit and LowBit
LowBit := LowBit + BitsPerSubWord;
IF (LowBit > BitsPerWord) THEN
LowBit := BitsPerWord;
END IF;
HighBit := LowBit + BitsPerSubWord;
IF (HighBit > BitsPerWord) THEN
HighBit := BitsPerWord;
ELSE
HighBit := HighBit - 1;
END IF;
END LOOP;
CorruptMask := CorruptMaskTmp;
RETURN;
END;
-- ----------------------------------------------------------------------------
PROCEDURE MemoryTableCorruptMask (
VARIABLE CorruptMask : OUT std_logic_vector;
CONSTANT Action : IN VitalMemorySymbolType
) IS
VARIABLE CorruptMaskTmp : std_logic_vector (0 TO CorruptMask'LENGTH-1)
:= (OTHERS => '0');
VARIABLE ViolFlAryPosn : INTEGER;
VARIABLE HighBit : INTEGER;
VARIABLE LowBit : INTEGER;
BEGIN
CASE (Action) IS
WHEN 'c'|'l'|'d'|'e'|'C'|'L'|'D'|'E' =>
-- Corrupt whole word
CorruptMaskTmp := (OTHERS => 'X');
CorruptMask := CorruptMaskTmp;
RETURN;
WHEN OTHERS =>
-- No data or memory corruption
CorruptMaskTmp := (OTHERS => '0');
CorruptMask := CorruptMaskTmp;
RETURN;
END CASE;
RETURN;
END;
-- ----------------------------------------------------------------------------
-- Procedure: MemoryTableCorruptMask
-- Description: Compute memory and data corruption masks for violation table
-- ----------------------------------------------------------------------------
PROCEDURE ViolationTableCorruptMask (
VARIABLE CorruptMask : OUT std_logic_vector;
CONSTANT Action : IN VitalMemorySymbolType;
CONSTANT ViolationFlags : IN std_logic_vector;
CONSTANT ViolationFlagsArray : IN std_logic_vector;
CONSTANT ViolationSizesArray : IN VitalMemoryViolFlagSizeType;
CONSTANT ViolationTable : IN VitalMemoryTableType;
CONSTANT TableIndex : IN INTEGER;
CONSTANT BitsPerWord : IN INTEGER;
CONSTANT BitsPerSubWord : IN INTEGER;
CONSTANT BitsPerEnable : IN INTEGER
) IS
VARIABLE CorruptMaskTmp : std_logic_vector (CorruptMask'RANGE)
:= (OTHERS => '0');
VARIABLE ViolMaskTmp : std_logic_vector (CorruptMask'RANGE)
:= (OTHERS => '0');
VARIABLE ViolFlAryPosn : INTEGER;
VARIABLE HighBit : INTEGER;
VARIABLE LowBit : INTEGER;
CONSTANT ViolFlagsSize : INTEGER := ViolationFlags'LENGTH;
CONSTANT ViolFlArySize : INTEGER := ViolationFlagsArray'LENGTH;
CONSTANT TableEntries : INTEGER := ViolationTable'LENGTH(1);
CONSTANT TableWidth : INTEGER := ViolationTable'LENGTH(2);
CONSTANT DatActionNdx : INTEGER := TableWidth - 1;
CONSTANT MemActionNdx : INTEGER := TableWidth - 2;
BEGIN
CASE (Action) IS
WHEN 'c'|'l'|'e' =>
-- Corrupt whole word
CorruptMaskTmp := (OTHERS => 'X');
CorruptMask := CorruptMaskTmp;
RETURN;
WHEN 'd'|'C'|'L'|'D'|'E' =>
-- Process corruption below
WHEN OTHERS =>
-- No data or memory corruption
CorruptMaskTmp := (OTHERS => '0');
CorruptMask := CorruptMaskTmp;
RETURN;
END CASE;
RowLoop: -- Check each element of the ViolationFlags
FOR j IN 0 TO ViolFlagsSize LOOP
IF (j = ViolFlagsSize) THEN
ViolFlAryPosn := 0;
RowLoop2: -- Check relevant elements of the ViolationFlagsArray
FOR k IN 0 TO MemActionNdx - ViolFlagsSize - 1 LOOP
IF (ViolationTable(TableIndex, k + ViolFlagsSize) = 'X') THEN
MaskLoop: -- Set the 'X' bits in the violation mask
FOR m IN INTEGER RANGE 0 TO CorruptMask'LENGTH-1 LOOP
IF (m <= ViolationSizesArray(k)-1) THEN
ViolMaskTmp(m) := ViolMaskTmp(m) XOR
ViolationFlagsArray(ViolFlAryPosn+m);
ELSE
EXIT MaskLoop;
END IF;
END LOOP;
END IF;
ViolFlAryPosn := ViolFlAryPosn + ViolationSizesArray(k);
END LOOP;
ELSE
IF (ViolationTable(TableIndex, j) = 'X') THEN
ViolMaskTmp(0) := ViolMaskTmp(0) XOR ViolationFlags(j);
END IF;
END IF;
END LOOP;
IF (Action = 'd') THEN
CorruptMask := ViolMaskTmp;
RETURN;
END IF;
-- Remaining are subword cases 'C', 'L', 'D', 'E'
CorruptMaskTmp := (OTHERS => '0');
LowBit := 0;
HighBit := BitsPerSubWord-1;
SubWordLoop:
FOR i IN 0 TO BitsPerEnable-1 LOOP
IF (ViolMaskTmp(i) = 'X') THEN
FOR j IN HighBit TO LowBit LOOP
CorruptMaskTmp(j) := 'X';
END LOOP;
END IF;
-- Calculate HighBit and LowBit
LowBit := LowBit + BitsPerSubWord;
IF (LowBit > BitsPerWord) THEN
LowBit := BitsPerWord;
END IF;
HighBit := LowBit + BitsPerSubWord;
IF (HighBit > BitsPerWord) THEN
HighBit := BitsPerWord;
ELSE
HighBit := HighBit - 1;
END IF;
END LOOP;
CorruptMask := CorruptMaskTmp;
RETURN;
END;
-- ----------------------------------------------------------------------------
-- Procedure: MemoryTableLookUp
-- Parameters: MemoryAction - Output memory action to be performed
-- DataAction - Output data action to be performed
-- PrevControls - Previous data in for edge detection
-- PrevEnableBus - Previous enables for edge detection
-- Controls - Agregate of scalar control lines
-- EnableBus - Concatenation of vector control lines
-- EnableIndex - Current slice of vector control lines
-- AddrFlag - Matching symbol from address decoding
-- DataFlag - Matching symbol from data decoding
-- MemoryTable - Input memory action table
-- PortName - Port name string for messages
-- HeaderMsg - Header string for messages
-- MsgOn - Control message output
--
-- Description: This function is used to find the output of the
-- MemoryTable corresponding to a given set of inputs.
--
-- ----------------------------------------------------------------------------
PROCEDURE MemoryTableLookUp (
VARIABLE MemoryAction : OUT VitalMemorySymbolType;
VARIABLE DataAction : OUT VitalMemorySymbolType;
VARIABLE MemoryCorruptMask : OUT std_logic_vector;
VARIABLE DataCorruptMask : OUT std_logic_vector;
CONSTANT PrevControls : IN std_logic_vector;
CONSTANT Controls : IN std_logic_vector;
CONSTANT AddrFlag : IN VitalMemorySymbolType;
CONSTANT DataFlag : IN VitalMemorySymbolType;
CONSTANT MemoryTable : IN VitalMemoryTableType;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE
) IS
CONSTANT ControlsSize : INTEGER := Controls'LENGTH;
CONSTANT TableEntries : INTEGER := MemoryTable'LENGTH(1);
CONSTANT TableWidth : INTEGER := MemoryTable'LENGTH(2);
CONSTANT DatActionNdx : INTEGER := TableWidth - 1;
CONSTANT MemActionNdx : INTEGER := TableWidth - 2;
CONSTANT DataInBusNdx : INTEGER := TableWidth - 3;
CONSTANT AddressBusNdx : INTEGER := TableWidth - 4;
VARIABLE AddrFlagTable : VitalMemorySymbolType;
VARIABLE Match : BOOLEAN;
VARIABLE Err : BOOLEAN := FALSE;
VARIABLE TableAlias : VitalMemoryTableType(
0 TO TableEntries - 1,
0 TO TableWidth - 1)
:= MemoryTable;
BEGIN
ColLoop: -- Compare each entry in the table
FOR i IN TableAlias'RANGE(1) LOOP
RowLoop: -- Check each element of the Controls
FOR j IN 0 TO ControlsSize LOOP
IF (j = ControlsSize) THEN
-- a match occurred, now check AddrFlag, DataFlag
MemoryMatch(TableAlias(i,AddressBusNdx),AddrFlag,Err,Match);
IF (Match) THEN
MemoryMatch(TableAlias(i,DataInBusNdx),DataFlag,Err,Match);
IF (Match) THEN
MemoryTableCorruptMask (
CorruptMask => MemoryCorruptMask ,
Action => TableAlias(i, MemActionNdx)
);
MemoryTableCorruptMask (
CorruptMask => DataCorruptMask ,
Action => TableAlias(i, DatActionNdx)
);
-- get the return memory and data actions
MemoryAction := TableAlias(i, MemActionNdx);
DataAction := TableAlias(i, DatActionNdx);
-- DEBUG: The lines below report table search
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMT,TableAlias,i,PortName);
END IF;
-- DEBUG: The lines above report table search
RETURN;
END IF;
END IF;
ELSE
-- Match memory table inputs
MemoryMatch ( TableAlias(i,j),
Controls(j), PrevControls(j),
Err, Match);
END IF;
EXIT RowLoop WHEN NOT(Match);
EXIT ColLoop WHEN Err;
END LOOP RowLoop;
END LOOP ColLoop;
-- no match found, return default action
MemoryAction := 's'; -- no change to memory
DataAction := 'S'; -- no change to dataout
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMT,ErrDefMemAct,HeaderMsg,PortName);
END IF;
RETURN;
END;
-- ----------------------------------------------------------------------------
PROCEDURE MemoryTableLookUp (
VARIABLE MemoryAction : OUT VitalMemorySymbolType;
VARIABLE DataAction : OUT VitalMemorySymbolType;
VARIABLE MemoryCorruptMask : OUT std_logic_vector;
VARIABLE DataCorruptMask : OUT std_logic_vector;
CONSTANT PrevControls : IN std_logic_vector;
CONSTANT PrevEnableBus : IN std_logic_vector;
CONSTANT Controls : IN std_logic_vector;
CONSTANT EnableBus : IN std_logic_vector;
CONSTANT EnableIndex : IN INTEGER;
CONSTANT BitsPerWord : IN INTEGER;
CONSTANT BitsPerSubWord : IN INTEGER;
CONSTANT BitsPerEnable : IN INTEGER;
CONSTANT AddrFlag : IN VitalMemorySymbolType;
CONSTANT DataFlag : IN VitalMemorySymbolType;
CONSTANT MemoryTable : IN VitalMemoryTableType;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE
) IS
CONSTANT ControlsSize : INTEGER := Controls'LENGTH;
CONSTANT TableEntries : INTEGER := MemoryTable'LENGTH(1);
CONSTANT TableWidth : INTEGER := MemoryTable'LENGTH(2);
CONSTANT DatActionNdx : INTEGER := TableWidth - 1;
CONSTANT MemActionNdx : INTEGER := TableWidth - 2;
CONSTANT DataInBusNdx : INTEGER := TableWidth - 3;
CONSTANT AddressBusNdx : INTEGER := TableWidth - 4;
VARIABLE AddrFlagTable : VitalMemorySymbolType;
VARIABLE Match : BOOLEAN;
VARIABLE Err : BOOLEAN := FALSE;
VARIABLE TableAlias : VitalMemoryTableType(
0 TO TableEntries - 1,
0 TO TableWidth - 1)
:= MemoryTable;
BEGIN
ColLoop: -- Compare each entry in the table
FOR i IN TableAlias'RANGE(1) LOOP
RowLoop: -- Check each element of the Controls
FOR j IN 0 TO ControlsSize LOOP
IF (j = ControlsSize) THEN
-- a match occurred, now check EnableBus, AddrFlag, DataFlag
IF (EnableIndex >= 0) THEN
RowLoop2: -- Check relevant elements of the EnableBus
FOR k IN 0 TO AddressBusNdx - ControlsSize - 1 LOOP
MemoryMatch ( TableAlias(i,k + ControlsSize),
EnableBus(k * BitsPerEnable + EnableIndex),
PrevEnableBus(k * BitsPerEnable + EnableIndex),
Err, Match);
EXIT RowLoop2 WHEN NOT(Match);
END LOOP;
END IF;
IF (Match) THEN
MemoryMatch(TableAlias(i,AddressBusNdx),AddrFlag,Err,Match);
IF (Match) THEN
MemoryMatch(TableAlias(i,DataInBusNdx),DataFlag,Err,Match);
IF (Match) THEN
MemoryTableCorruptMask (
CorruptMask => MemoryCorruptMask ,
Action => TableAlias(i, MemActionNdx),
EnableIndex => EnableIndex ,
BitsPerWord => BitsPerWord ,
BitsPerSubWord => BitsPerSubWord ,
BitsPerEnable => BitsPerEnable
);
MemoryTableCorruptMask (
CorruptMask => DataCorruptMask ,
Action => TableAlias(i, DatActionNdx),
EnableIndex => EnableIndex ,
BitsPerWord => BitsPerWord ,
BitsPerSubWord => BitsPerSubWord ,
BitsPerEnable => BitsPerEnable
);
-- get the return memory and data actions
MemoryAction := TableAlias(i, MemActionNdx);
DataAction := TableAlias(i, DatActionNdx);
-- DEBUG: The lines below report table search
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMT,TableAlias,i,PortName);
END IF;
-- DEBUG: The lines above report table search
RETURN;
END IF;
END IF;
END IF;
ELSE
-- Match memory table inputs
MemoryMatch ( TableAlias(i,j),
Controls(j), PrevControls(j),
Err, Match);
END IF;
EXIT RowLoop WHEN NOT(Match);
EXIT ColLoop WHEN Err;
END LOOP RowLoop;
END LOOP ColLoop;
-- no match found, return default action
MemoryAction := 's'; -- no change to memory
DataAction := 'S'; -- no change to dataout
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMT,ErrDefMemAct,HeaderMsg,PortName);
END IF;
RETURN;
END;
-- ----------------------------------------------------------------------------
-- Procedure: ViolationTableLookUp
-- Parameters: MemoryAction - Output memory action to be performed
-- DataAction - Output data action to be performed
-- TimingDataArray - This is currently not used (comment out)
-- ViolationArray - Aggregation of violation variables
-- ViolationTable - Input memory violation table
-- PortName - Port name string for messages
-- HeaderMsg - Header string for messages
-- MsgOn - Control message output
-- Description: This function is used to find the output of the
-- ViolationTable corresponding to a given set of inputs.
-- ----------------------------------------------------------------------------
PROCEDURE ViolationTableLookUp (
VARIABLE MemoryAction : OUT VitalMemorySymbolType;
VARIABLE DataAction : OUT VitalMemorySymbolType;
VARIABLE MemoryCorruptMask : OUT std_logic_vector;
VARIABLE DataCorruptMask : OUT std_logic_vector;
CONSTANT ViolationFlags : IN std_logic_vector;
CONSTANT ViolationFlagsArray : IN std_logic_vector;
CONSTANT ViolationSizesArray : IN VitalMemoryViolFlagSizeType;
CONSTANT ViolationTable : IN VitalMemoryTableType;
CONSTANT BitsPerWord : IN INTEGER;
CONSTANT BitsPerSubWord : IN INTEGER;
CONSTANT BitsPerEnable : IN INTEGER;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE
) IS
CONSTANT ViolFlagsSize : INTEGER := ViolationFlags'LENGTH;
CONSTANT ViolFlArySize : INTEGER := ViolationFlagsArray'LENGTH;
VARIABLE ViolFlAryPosn : INTEGER;
VARIABLE ViolFlAryItem : std_ulogic;
CONSTANT ViolSzArySize : INTEGER := ViolationSizesArray'LENGTH;
CONSTANT TableEntries : INTEGER := ViolationTable'LENGTH(1);
CONSTANT TableWidth : INTEGER := ViolationTable'LENGTH(2);
CONSTANT DatActionNdx : INTEGER := TableWidth - 1;
CONSTANT MemActionNdx : INTEGER := TableWidth - 2;
VARIABLE HighBit : NATURAL := 0;
VARIABLE LowBit : NATURAL := 0;
VARIABLE Match : BOOLEAN;
VARIABLE Err : BOOLEAN := FALSE;
VARIABLE TableAlias : VitalMemoryTableType(
0 TO TableEntries - 1,
0 TO TableWidth - 1)
:= ViolationTable;
BEGIN
ColLoop: -- Compare each entry in the table
FOR i IN TableAlias'RANGE(1) LOOP
RowLoop: -- Check each element of the ViolationFlags
FOR j IN 0 TO ViolFlagsSize LOOP
IF (j = ViolFlagsSize) THEN
ViolFlAryPosn := 0;
RowLoop2: -- Check relevant elements of the ViolationFlagsArray
FOR k IN 0 TO MemActionNdx - ViolFlagsSize - 1 LOOP
ViolFlAryItem := '0';
SubwordLoop: -- Check for 'X' in ViolationFlagsArray chunk
FOR s IN ViolFlAryPosn TO ViolFlAryPosn+ViolationSizesArray(k)-1 LOOP
IF (ViolationFlagsArray(s) = 'X') THEN
ViolFlAryItem := 'X';
EXIT SubwordLoop;
END IF;
END LOOP;
MemoryMatch ( TableAlias(i,k + ViolFlagsSize),
ViolFlAryItem,ViolFlAryItem,
Err, Match);
ViolFlAryPosn := ViolFlAryPosn + ViolationSizesArray(k);
EXIT RowLoop2 WHEN NOT(Match);
END LOOP;
IF (Match) THEN
-- Compute memory and data corruption masks
ViolationTableCorruptMask(
CorruptMask => MemoryCorruptMask ,
Action => TableAlias(i, MemActionNdx),
ViolationFlags => ViolationFlags ,
ViolationFlagsArray => ViolationFlagsArray ,
ViolationSizesArray => ViolationSizesArray ,
ViolationTable => ViolationTable ,
TableIndex => i ,
BitsPerWord => BitsPerWord ,
BitsPerSubWord => BitsPerSubWord ,
BitsPerEnable => BitsPerEnable
);
ViolationTableCorruptMask(
CorruptMask => DataCorruptMask ,
Action => TableAlias(i, DatActionNdx),
ViolationFlags => ViolationFlags ,
ViolationFlagsArray => ViolationFlagsArray ,
ViolationSizesArray => ViolationSizesArray ,
ViolationTable => ViolationTable ,
TableIndex => i ,
BitsPerWord => BitsPerWord ,
BitsPerSubWord => BitsPerSubWord ,
BitsPerEnable => BitsPerEnable
);
-- get the return memory and data actions
MemoryAction := TableAlias(i, MemActionNdx);
DataAction := TableAlias(i, DatActionNdx);
-- DEBUG: The lines below report table search
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMV,TableAlias,i,PortName);
END IF;
-- DEBUG: The lines above report table search
RETURN;
END IF;
ELSE
-- Match violation table inputs
Err := FALSE;
Match := FALSE;
IF (TableAlias(i,j) /= 'X' AND
TableAlias(i,j) /= '0' AND
TableAlias(i,j) /= '-') THEN
Err := TRUE;
ELSIF (TableAlias(i,j) = '-' OR
(TableAlias(i,j) = 'X' AND ViolationFlags(j) = 'X') OR
(TableAlias(i,j) = '0' AND ViolationFlags(j) = '0')) THEN
Match := TRUE;
END IF;
END IF;
EXIT RowLoop WHEN NOT(Match);
EXIT ColLoop WHEN Err;
END LOOP RowLoop;
END LOOP ColLoop;
-- no match found, return default action
MemoryAction := 's'; -- no change to memory
DataAction := 'S'; -- no change to dataout
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMV,ErrDefMemAct,HeaderMsg,PortName);
END IF;
RETURN;
END;
-- ----------------------------------------------------------------------------
-- Procedure: HandleMemoryAction
-- Parameters: MemoryData - Pointer to memory data structure
-- PortFlag - Indicates read/write mode of port
-- CorruptMask - XOR'ed with DataInBus when corrupting
-- DataInBus - Current data bus in
-- Address - Current address integer
-- HighBit - Current address high bit
-- LowBit - Current address low bit
-- MemoryTable - Input memory action table
-- MemoryAction - Memory action to be performed
-- PortName - Port name string for messages
-- HeaderMsg - Header string for messages
-- MsgOn - Control message output
-- Description: This procedure performs the specified memory action on
-- the input memory data structure.
-- ----------------------------------------------------------------------------
PROCEDURE HandleMemoryAction (
VARIABLE MemoryData : INOUT VitalMemoryDataType;
VARIABLE PortFlag : INOUT VitalPortFlagType;
CONSTANT CorruptMask : IN std_logic_vector;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT Address : IN INTEGER;
CONSTANT HighBit : IN NATURAL;
CONSTANT LowBit : IN NATURAL;
CONSTANT MemoryTable : IN VitalMemoryTableType;
CONSTANT MemoryAction : IN VitalMemorySymbolType;
CONSTANT CallerName : IN STRING;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE
) IS
VARIABLE DataInTmp : std_logic_vector(DataInBus'RANGE)
:= DataInBus;
BEGIN
-- Handle the memory action
CASE MemoryAction IS
WHEN 'w' =>
-- Writing data to memory
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrWrDatMem,HeaderMsg,PortName);
END IF;
WriteMemory(MemoryData,DataInBus,Address,HighBit,LowBit);
PortFlag.MemoryCurrent := WRITE;
WHEN 's' =>
-- Retaining previous memory contents
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrNoChgMem,HeaderMsg,PortName);
END IF;
-- Set memory current to quiet state
PortFlag.MemoryCurrent := READ;
WHEN 'c' =>
-- Corrupting entire memory with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrAllMem,HeaderMsg,PortName);
END IF;
DataInTmp := (OTHERS => 'X');
-- No need to CorruptMask
FOR i IN 0 TO MemoryData.NoOfWords-1 LOOP
WriteMemory(MemoryData,DataInTmp,i);
END LOOP;
PortFlag.MemoryCurrent := CORRUPT;
WHEN 'l' =>
-- Corrupting a word in memory with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrWrdMem,HeaderMsg,PortName);
END IF;
DataInTmp := (OTHERS => 'X');
-- No need to CorruptMask
WriteMemory(MemoryData,DataInTmp,Address);
PortFlag.MemoryCurrent := CORRUPT;
WHEN 'd' =>
-- Corrupting a single bit in memory with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrBitMem,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataInTmp,Address);
DataInTmp := DataInTmp XOR CorruptMask;
WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit);
PortFlag.MemoryCurrent := CORRUPT;
WHEN 'e' =>
-- Corrupting a word with 'X' based on data in
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrDatMem,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataInTmp,Address);
IF (DataInTmp /= DataInBus) THEN
DataInTmp := (OTHERS => 'X');
-- No need to CorruptMask
WriteMemory(MemoryData,DataInTmp,Address);
END IF;
PortFlag.MemoryCurrent := CORRUPT;
WHEN 'C' =>
-- Corrupting a sub-word entire memory with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrAllSubMem,HeaderMsg,PortName);
END IF;
FOR i IN 0 TO MemoryData.NoOfWords-1 LOOP
ReadMemory(MemoryData,DataInTmp,i);
DataInTmp := DataInTmp XOR CorruptMask;
WriteMemory(MemoryData,DataInTmp,i,HighBit,LowBit);
END LOOP;
PortFlag.MemoryCurrent := CORRUPT;
WHEN 'L' =>
-- Corrupting a sub-word in memory with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrWrdSubMem,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataInTmp,Address);
DataInTmp := DataInTmp XOR CorruptMask;
WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit);
PortFlag.MemoryCurrent := CORRUPT;
WHEN 'D' =>
-- Corrupting a single bit of a memory sub-word with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrBitSubMem,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataInTmp,Address);
DataInTmp := DataInTmp XOR CorruptMask;
WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit);
PortFlag.MemoryCurrent := CORRUPT;
WHEN 'E' =>
-- Corrupting a sub-word with 'X' based on data in
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrDatSubMem,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataInTmp,Address);
IF (DataInBus(HighBit DOWNTO LowBit) /=
DataInTmp(HighBit DOWNTO LowBit)) THEN
DataInTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X');
WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit);
END IF;
--PortFlag := WRITE;
PortFlag.MemoryCurrent := CORRUPT;
WHEN '0' =>
-- Assigning low level to memory location
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAsg0Mem,HeaderMsg,PortName);
END IF;
DataInTmp := (OTHERS => '0');
WriteMemory(MemoryData,DataInTmp,Address, HighBit, LowBit);
PortFlag.MemoryCurrent := WRITE;
WHEN '1' =>
-- Assigning high level to memory location
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAsg1Mem,HeaderMsg,PortName);
END IF;
DataInTmp := (OTHERS => '1');
WriteMemory(MemoryData,DataInTmp,Address, HighBit, LowBit);
PortFlag.MemoryCurrent := WRITE;
WHEN 'Z' =>
-- Assigning high impedence to memory location
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAsgZMem,HeaderMsg,PortName);
END IF;
DataInTmp := (OTHERS => 'Z');
WriteMemory(MemoryData,DataInTmp,Address, HighBit, LowBit);
PortFlag.MemoryCurrent := WRITE;
WHEN OTHERS =>
-- Unknown memory action
PortFlag.MemoryCurrent := UNDEF;
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrUnknMemDo,HeaderMsg,PortName);
END IF;
END CASE;
-- Note: HandleMemoryAction does not change the PortFlag.OutputDisable
END;
-- ----------------------------------------------------------------------------
-- Procedure: HandleDataAction
-- Parameters: DataOutBus - Output result of the data action
-- MemoryData - Input pointer to memory data structure
-- PortFlag - Indicates read/write mode of port
-- CorruptMask - XOR'ed with DataInBus when corrupting
-- DataInBus - Current data bus in
-- Address - Current address integer
-- HighBit - Current address high bit
-- LowBit - Current address low bit
-- MemoryTable - Input memory action table
-- DataAction - Data action to be performed
-- PortName - Port name string for messages
-- HeaderMsg - Header string for messages
-- MsgOn - Control message output
-- Description: This procedure performs the specified data action based
-- on the input memory data structure. Checks whether
-- the previous state is HighZ. If yes then portFlag
-- should be NOCHANGE for VMPD to ignore IORetain
-- corruption. The idea is that the first Z should be
-- propagated but later ones should be ignored.
-- ----------------------------------------------------------------------------
PROCEDURE HandleDataAction (
VARIABLE DataOutBus : INOUT std_logic_vector;
VARIABLE MemoryData : INOUT VitalMemoryDataType;
VARIABLE PortFlag : INOUT VitalPortFlagType;
CONSTANT CorruptMask : IN std_logic_vector;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT Address : IN INTEGER;
CONSTANT HighBit : IN NATURAL;
CONSTANT LowBit : IN NATURAL;
CONSTANT MemoryTable : IN VitalMemoryTableType;
CONSTANT DataAction : IN VitalMemorySymbolType;
CONSTANT CallerName : IN STRING;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE
) IS
VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE)
:= DataOutBus;
BEGIN
-- Handle the data action
CASE DataAction IS
WHEN 'l' =>
-- Corrupting data out with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrWrdOut,HeaderMsg,PortName);
END IF;
DataOutTmp := (OTHERS => 'X');
-- No need to CorruptMask
PortFlag.DataCurrent := CORRUPT;
WHEN 'd' =>
-- Corrupting a single bit of data out with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrBitOut,HeaderMsg,PortName);
END IF;
DataOutTmp(HighBit DOWNTO LowBit) :=
DataOutTmp(HighBit DOWNTO LowBit) XOR
CorruptMask(HighBit DOWNTO LowBit);
PortFlag.DataCurrent := CORRUPT;
WHEN 'e' =>
-- Corrupting data out with 'X' based on data in
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrDatOut,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataOutTmp,Address);
IF (DataOutTmp /= DataInBus) THEN
DataOutTmp := (OTHERS => 'X');
-- No need to CorruptMask
END IF;
PortFlag.DataCurrent := CORRUPT;
WHEN 'L' =>
-- Corrupting data out sub-word with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrWrdSubOut,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataOutTmp,Address);
DataOutTmp(HighBit DOWNTO LowBit) :=
DataOutTmp(HighBit DOWNTO LowBit) XOR
CorruptMask(HighBit DOWNTO LowBit);
PortFlag.DataCurrent := CORRUPT;
WHEN 'D' =>
-- Corrupting a single bit of data out sub-word with 'X'
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrBitSubOut,HeaderMsg,PortName);
END IF;
DataOutTmp(HighBit DOWNTO LowBit) :=
DataOutTmp(HighBit DOWNTO LowBit) XOR
CorruptMask(HighBit DOWNTO LowBit);
PortFlag.DataCurrent := CORRUPT;
WHEN 'E' =>
-- Corrupting data out sub-word with 'X' based on data in
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrCrDatSubOut,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataOutTmp,Address);
IF (DataInBus(HighBit DOWNTO LowBit) /=
DataOutTmp(HighBit DOWNTO LowBit)) THEN
DataOutTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X');
-- No need to CorruptMask
END IF;
PortFlag.DataCurrent := CORRUPT;
WHEN 'M' =>
-- Implicit read from memory to data out
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrImplOut,HeaderMsg,PortName);
END IF;
PortFlag.DataCurrent := READ;
WHEN 'm' =>
-- Reading data from memory to data out
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrReadOut,HeaderMsg,PortName);
END IF;
ReadMemory(MemoryData,DataOutTmp,Address);
PortFlag.DataCurrent := READ;
WHEN 't' =>
-- Transferring from data in to data out
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAssgOut,HeaderMsg,PortName);
END IF;
DataOutTmp := DataInBus;
PortFlag.DataCurrent := READ;
WHEN '0' =>
-- Assigning low level to data out
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAsg0Out,HeaderMsg,PortName);
END IF;
DataOutTmp := (OTHERS => '0');
PortFlag.DataCurrent := READ;
WHEN '1' =>
-- Assigning high level to data out
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAsg1Out,HeaderMsg,PortName);
END IF;
DataOutTmp := (OTHERS => '1');
PortFlag.DataCurrent := READ;
WHEN 'Z' =>
-- Assigning high impedence to data out
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAsgZOut,HeaderMsg,PortName);
END IF;
DataOutTmp := (OTHERS => 'Z');
PortFlag.DataCurrent := HIGHZ;
WHEN 'S' =>
-- Keeping data out at steady value
PortFlag.OutputDisable := TRUE;
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrAsgSOut,HeaderMsg,PortName);
END IF;
WHEN OTHERS =>
-- Unknown data action
PortFlag.DataCurrent := UNDEF;
IF (MsgOn) THEN
PrintMemoryMessage(CallerName,ErrUnknDatDo,HeaderMsg,PortName);
END IF;
END CASE;
DataOutBus(HighBit DOWNTO LowBit) := DataOutTmp(HighBit DOWNTO LowBit);
END;
-- ----------------------------------------------------------------------------
-- Memory Table Modeling Primitives
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- Procedure: VitalDeclareMemory
-- Parameters: NoOfWords - Number of words in the memory
-- NoOfBitsPerWord - Number of bits per word in memory
-- NoOfBitsPerSubWord - Number of bits per sub word
-- MemoryLoadFile - Name of data file to load
-- Description: This function is intended to be used to initialize
-- memory data declarations, i.e. to be executed duing
-- simulation elaboration time. Handles the allocation
-- and initialization of memory for the memory data.
-- Default NoOfBitsPerSubWord is NoOfBitsPerWord.
-- ----------------------------------------------------------------------------
IMPURE FUNCTION VitalDeclareMemory (
CONSTANT NoOfWords : IN POSITIVE;
CONSTANT NoOfBitsPerWord : IN POSITIVE;
CONSTANT MemoryLoadFile : IN string := "";
CONSTANT BinaryLoadFile : IN BOOLEAN := FALSE
) RETURN VitalMemoryDataType IS
VARIABLE MemoryPtr : VitalMemoryDataType;
BEGIN
MemoryPtr := VitalDeclareMemory(
NoOfWords => NoOfWords,
NoOfBitsPerWord => NoOfBitsPerWord,
NoOfBitsPerSubWord => NoOfBitsPerWord,
MemoryLoadFile => MemoryLoadFile,
BinaryLoadFile => BinaryLoadFile
);
RETURN MemoryPtr;
END;
-- ----------------------------------------------------------------------------
IMPURE FUNCTION VitalDeclareMemory (
CONSTANT NoOfWords : IN POSITIVE;
CONSTANT NoOfBitsPerWord : IN POSITIVE;
CONSTANT NoOfBitsPerSubWord : IN POSITIVE;
CONSTANT MemoryLoadFile : IN string := "";
CONSTANT BinaryLoadFile : IN BOOLEAN := FALSE
) RETURN VitalMemoryDataType IS
VARIABLE MemoryPtr : VitalMemoryDataType;
VARIABLE BitsPerEnable : NATURAL
:= ((NoOfBitsPerWord-1)
/NoOfBitsPerSubWord)+1;
BEGIN
PrintMemoryMessage(MsgVDM,ErrInitMem);
MemoryPtr := new VitalMemoryArrayRecType '(
NoOfWords => NoOfWords,
NoOfBitsPerWord => NoOfBitsPerWord,
NoOfBitsPerSubWord => NoOfBitsPerSubWord,
NoOfBitsPerEnable => BitsPerEnable,
MemoryArrayPtr => NULL
);
MemoryPtr.MemoryArrayPtr
:= new MemoryArrayType (0 to MemoryPtr.NoOfWords - 1);
FOR i IN 0 TO MemoryPtr.NoOfWords - 1 LOOP
MemoryPtr.MemoryArrayPtr(i)
:= new MemoryWordType (MemoryPtr.NoOfBitsPerWord - 1 DOWNTO 0);
END LOOP;
IF (MemoryLoadFile /= "") THEN
LoadMemory (MemoryPtr, MemoryLoadFile, BinaryLoadFile);
END IF;
RETURN MemoryPtr;
END;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemoryTable
-- Parameters: DataOutBus - Output candidate zero delay data bus out
-- MemoryData - Pointer to memory data structure
-- PrevControls - Previous data in for edge detection
-- PrevEnableBus - Previous enables for edge detection
-- PrevDataInBus - Previous data bus for edge detection
-- PrevAddressBus - Previous address bus for edge detection
-- PortFlag - Indicates port operating mode
-- PortFlagArray - Vector form of PortFlag for sub-word
-- Controls - Agregate of scalar control lines
-- EnableBus - Concatenation of vector control lines
-- DataInBus - Input value of data bus in
-- AddressBus - Input value of address bus in
-- AddressValue - Decoded value of the AddressBus
-- MemoryTable - Input memory action table
-- PortType - The type of port (currently not used)
-- PortName - Port name string for messages
-- HeaderMsg - Header string for messages
-- MsgOn - Control the generation of messages
-- MsgSeverity - Control level of message generation
-- Description: This procedure implements the majority of the memory
-- modeling functionality via lookup of the memory action
-- tables and performing the specified actions if matches
-- are found, or the default actions otherwise. The
-- overloadings are provided for the word and sub-word
-- (using the EnableBus and PortFlagArray arguments) addressing
-- cases.
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryTable (
VARIABLE DataOutBus : INOUT std_logic_vector;
VARIABLE MemoryData : INOUT VitalMemoryDataType;
VARIABLE PrevControls : INOUT std_logic_vector;
VARIABLE PrevDataInBus : INOUT std_logic_vector;
VARIABLE PrevAddressBus : INOUT std_logic_vector;
VARIABLE PortFlag : INOUT VitalPortFlagVectorType;
CONSTANT Controls : IN std_logic_vector;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT AddressBus : IN std_logic_vector;
VARIABLE AddressValue : INOUT VitalAddressValueType;
CONSTANT MemoryTable : IN VitalMemoryTableType;
CONSTANT PortType : IN VitalPortType := UNDEF;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
) IS
VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE)
:= DataOutBus;
VARIABLE MemoryAction : VitalMemorySymbolType;
VARIABLE DataAction : VitalMemorySymbolType;
VARIABLE HighBit : NATURAL := MemoryData.NoOfBitsPerWord-1;
VARIABLE LowBit : NATURAL := 0;
VARIABLE Address : INTEGER := 0;
VARIABLE PortFlagTmp : VitalPortFlagType;
VARIABLE AddrFlag : VitalMemorySymbolType := 'g'; -- good addr
VARIABLE DataFlag : VitalMemorySymbolType := 'g'; -- good data
VARIABLE MemCorruptMask : std_logic_vector (DataOutBus'RANGE);
VARIABLE DatCorruptMask : std_logic_vector (DataOutBus'RANGE);
BEGIN
-- Optimize for case when all current inputs are same as previous
IF (PrevDataInBus = DataInBus
AND PrevAddressBus = AddressBus
AND PrevControls = Controls
AND PortFlag(0).MemoryCurrent = PortFlag(0).MemoryPrevious
AND PortFlag(0).DataCurrent = PortFlag(0).DataPrevious) THEN
PortFlag(0).OutputDisable := TRUE;
RETURN;
END IF;
PortFlag(0).DataPrevious := PortFlag(0).DataCurrent;
PortFlag(0).MemoryPrevious := PortFlag(0).MemoryCurrent;
PortFlag(0).OutputDisable := FALSE;
PortFlagTmp := PortFlag(0);
-- Convert address bus to integer value and table lookup flag
DecodeAddress(
Address => Address ,
AddrFlag => AddrFlag ,
MemoryData => MemoryData ,
PrevAddressBus => PrevAddressBus ,
AddressBus => AddressBus
);
-- Interpret data bus as a table lookup flag
DecodeData (
DataFlag => DataFlag ,
PrevDataInBus => PrevDataInBus ,
DataInBus => DataInBus ,
HighBit => HighBit ,
LowBit => LowBit
);
-- Lookup memory and data actions
MemoryTableLookUp(
MemoryAction => MemoryAction ,
DataAction => DataAction ,
MemoryCorruptMask => MemCorruptMask ,
DataCorruptMask => DatCorruptMask ,
PrevControls => PrevControls ,
Controls => Controls ,
AddrFlag => AddrFlag ,
DataFlag => DataFlag ,
MemoryTable => MemoryTable ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
-- Handle data action before memory action
-- This allows reading previous memory contents
HandleDataAction(
DataOutBus => DataOutTmp ,
MemoryData => MemoryData ,
PortFlag => PortFlagTmp ,
CorruptMask => DatCorruptMask ,
DataInBus => DataInBus ,
Address => Address ,
HighBit => HighBit ,
LowBit => LowBit ,
MemoryTable => MemoryTable ,
DataAction => DataAction ,
CallerName => MsgVMT ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
HandleMemoryAction(
MemoryData => MemoryData ,
PortFlag => PortFlagTmp ,
CorruptMask => MemCorruptMask ,
DataInBus => DataInBus ,
Address => Address ,
HighBit => HighBit ,
LowBit => LowBit ,
MemoryTable => MemoryTable ,
MemoryAction => MemoryAction ,
CallerName => MsgVMT ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
-- Set the output PortFlag(0) value
IF (DataAction = 'S') THEN
PortFlagTmp.OutputDisable := TRUE;
END IF;
IF (PortFlagTmp.DataCurrent = PortFlagTmp.DataPrevious
AND PortFlagTmp.DataCurrent = HIGHZ) THEN
PortFlagTmp.OutputDisable := TRUE;
END IF;
PortFlag(0) := PortFlagTmp;
-- Set previous values for subsequent edge detection
PrevControls := Controls;
PrevDataInBus := DataInBus;
PrevAddressBus := AddressBus;
-- Set the candidate zero delay return value
DataOutBus := DataOutTmp;
-- Set the output AddressValue for VitalMemoryCrossPorts
AddressValue := Address;
END VitalMemoryTable;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryTable (
VARIABLE DataOutBus : INOUT std_logic_vector;
VARIABLE MemoryData : INOUT VitalMemoryDataType;
VARIABLE PrevControls : INOUT std_logic_vector;
VARIABLE PrevEnableBus : INOUT std_logic_vector;
VARIABLE PrevDataInBus : INOUT std_logic_vector;
VARIABLE PrevAddressBus : INOUT std_logic_vector;
VARIABLE PortFlagArray : INOUT VitalPortFlagVectorType;
CONSTANT Controls : IN std_logic_vector;
CONSTANT EnableBus : IN std_logic_vector;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT AddressBus : IN std_logic_vector;
VARIABLE AddressValue : INOUT VitalAddressValueType;
CONSTANT MemoryTable : IN VitalMemoryTableType;
CONSTANT PortType : IN VitalPortType := UNDEF;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
) IS
VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord;
VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord;
VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable;
VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE)
:= DataOutBus;
VARIABLE MemoryAction : VitalMemorySymbolType;
VARIABLE DataAction : VitalMemorySymbolType;
VARIABLE HighBit : NATURAL := BitsPerSubWord-1;
VARIABLE LowBit : NATURAL := 0;
VARIABLE Address : INTEGER := 0;
VARIABLE PortFlagTmp : VitalPortFlagType;
VARIABLE AddrFlag : VitalMemorySymbolType := 'g'; -- good addr
VARIABLE DataFlag : VitalMemorySymbolType := 'g'; -- good data
VARIABLE MemCorruptMask : std_logic_vector (DataOutBus'RANGE);
VARIABLE DatCorruptMask : std_logic_vector (DataOutBus'RANGE);
BEGIN
-- Optimize for case when all current inputs are same as previous
IF (PrevDataInBus = DataInBus
AND PrevAddressBus = AddressBus
AND PrevControls = Controls) THEN
CheckFlags:
FOR i IN 0 TO BitsPerEnable-1 LOOP
IF (PortFlagArray(i).MemoryCurrent /= PortFlagArray(i).MemoryPrevious
OR PortFlagArray(i).DataCurrent /= PortFlagArray(i).DataPrevious) THEN
EXIT CheckFlags;
END IF;
IF (i = BitsPerEnable-1) THEN
FOR j IN 0 TO BitsPerEnable-1 LOOP
PortFlagArray(j).OutputDisable := TRUE;
END LOOP;
RETURN;
END IF;
END LOOP;
END IF;
-- Convert address bus to integer value and table lookup flag
DecodeAddress(
Address => Address,
AddrFlag => AddrFlag,
MemoryData => MemoryData,
PrevAddressBus => PrevAddressBus,
AddressBus => AddressBus
);
-- Perform independent operations for each sub-word
FOR i IN 0 TO BitsPerEnable-1 LOOP
-- Set the output PortFlag(i) value
PortFlagArray(i).DataPrevious := PortFlagArray(i).DataCurrent;
PortFlagArray(i).MemoryPrevious := PortFlagArray(i).MemoryCurrent;
PortFlagArray(i).OutputDisable := FALSE;
PortFlagTmp := PortFlagArray(i);
-- Interpret data bus as a table lookup flag
DecodeData (
DataFlag => DataFlag ,
PrevDataInBus => PrevDataInBus ,
DataInBus => DataInBus ,
HighBit => HighBit ,
LowBit => LowBit
);
-- Lookup memory and data actions
MemoryTableLookUp(
MemoryAction => MemoryAction ,
DataAction => DataAction ,
MemoryCorruptMask => MemCorruptMask ,
DataCorruptMask => DatCorruptMask ,
PrevControls => PrevControls ,
PrevEnableBus => PrevEnableBus ,
Controls => Controls ,
EnableBus => EnableBus ,
EnableIndex => i ,
BitsPerWord => BitsPerWord ,
BitsPerSubWord => BitsPerSubWord ,
BitsPerEnable => BitsPerEnable ,
AddrFlag => AddrFlag ,
DataFlag => DataFlag ,
MemoryTable => MemoryTable ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
-- Handle data action before memory action
-- This allows reading previous memory contents
HandleDataAction(
DataOutBus => DataOutTmp ,
MemoryData => MemoryData ,
PortFlag => PortFlagTmp ,
CorruptMask => DatCorruptMask ,
DataInBus => DataInBus ,
Address => Address ,
HighBit => HighBit ,
LowBit => LowBit ,
MemoryTable => MemoryTable ,
DataAction => DataAction ,
CallerName => MsgVMT ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
HandleMemoryAction(
MemoryData => MemoryData ,
PortFlag => PortFlagTmp ,
CorruptMask => MemCorruptMask ,
DataInBus => DataInBus ,
Address => Address ,
HighBit => HighBit ,
LowBit => LowBit ,
MemoryTable => MemoryTable ,
MemoryAction => MemoryAction ,
CallerName => MsgVMT ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
-- Set the output PortFlag(i) value
IF (DataAction = 'S') THEN
PortFlagTmp.OutputDisable := TRUE;
END IF;
IF (PortFlagTmp.DataCurrent = PortFlagTmp.DataPrevious
AND PortFlagTmp.DataCurrent = HIGHZ) THEN
PortFlagTmp.OutputDisable := TRUE;
END IF;
PortFlagArray(i) := PortFlagTmp;
IF (i < BitsPerEnable-1) THEN
-- Calculate HighBit and LowBit
LowBit := LowBit + BitsPerSubWord;
IF (LowBit > BitsPerWord) THEN
LowBit := BitsPerWord;
END IF;
HighBit := LowBit + BitsPerSubWord;
IF (HighBit > BitsPerWord) THEN
HighBit := BitsPerWord;
ELSE
HighBit := HighBit - 1;
END IF;
END IF;
END LOOP;
-- Set previous values for subsequent edge detection
PrevControls := Controls;
PrevEnableBus := EnableBus;
PrevDataInBus := DataInBus;
PrevAddressBus := AddressBus;
-- Set the candidate zero delay return value
DataOutBus := DataOutTmp;
-- Set the output AddressValue for VitalMemoryCrossPorts
AddressValue := Address;
END VitalMemoryTable;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemoryCrossPorts
-- Parameters: DataOutBus - Output candidate zero delay data bus out
-- MemoryData - Pointer to memory data structure
-- SamePortFlag - Operating mode for same port
-- SamePortAddressValue - Operating modes for cross ports
-- CrossPortAddressArray - Decoded AddressBus for cross ports
-- CrossPortMode - Write contention and crossport read control
-- PortName - Port name string for messages
-- HeaderMsg - Header string for messages
-- MsgOn - Control the generation of messages
-- Description: These procedures control the effect of memory operations
-- on a given port due to operations on other ports in a
-- multi-port memory.
-- This includes data write through when reading and writing
-- to the same address, as well as write contention when
-- there are multiple write to the same address.
-- If addresses do not match then data bus is unchanged.
-- The DataOutBus can be diabled with 'Z' value.
-- If the WritePortFlag is 'CORRUPT', that would mean
-- that the whole memory is corrupted. So, for corrupting
-- the Read port, the Addresses need not be compared.
--
-- CrossPortMode Enum Description
-- 1. CpRead Allows Cross Port Read Only
-- No contention checking.
-- 2. WriteContention Allows for write contention checks
-- only between multiple write ports
-- 3. ReadWriteContention Allows contention between read and
-- write ports. The action is to corrupt
-- the memory and the output bus.
-- 4. CpReadAndWriteContention Is a combination of 1 & 2
-- 5. CpReadAndReadContention Allows contention between read and
-- write ports. The action is to corrupt
-- the dataout bus only. The cp read is
-- performed if not contending.
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryCrossPorts (
VARIABLE DataOutBus : INOUT std_logic_vector;
VARIABLE MemoryData : INOUT VitalMemoryDataType;
VARIABLE SamePortFlag : INOUT VitalPortFlagVectorType;
CONSTANT SamePortAddressValue : IN VitalAddressValueType;
CONSTANT CrossPortFlagArray : IN VitalPortFlagVectorType;
CONSTANT CrossPortAddressArray : IN VitalAddressValueVectorType;
CONSTANT CrossPortMode : IN VitalCrossPortModeType
:= CpReadAndWriteContention;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE
) IS
VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord;
VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord;
VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable;
VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE) := (OTHERS => 'Z');
VARIABLE MemoryTmp : std_logic_vector(DataOutBus'RANGE);
VARIABLE CrossPorts : NATURAL := CrossPortAddressArray'LENGTH;
VARIABLE LowBit : NATURAL := 0;
VARIABLE HighBit : NATURAL := BitsPerSubWord-1;
VARIABLE Address : VitalAddressValueType := SamePortAddressValue;
VARIABLE AddressJ : VitalAddressValueType;
VARIABLE AddressK : VitalAddressValueType;
VARIABLE PortFlagI : VitalPortFlagType;
VARIABLE PortFlagIJ : VitalPortFlagType;
VARIABLE PortFlagIK : VitalPortFlagType;
VARIABLE DoCpRead : BOOLEAN := FALSE;
VARIABLE DoWrCont : BOOLEAN := FALSE;
VARIABLE DoCpCont : BOOLEAN := FALSE;
VARIABLE DoRdWrCont : BOOLEAN := FALSE;
VARIABLE CpWrCont : BOOLEAN := FALSE;
VARIABLE ModeWrCont : BOOLEAN :=
(CrossPortMode=WriteContention) OR
(CrossPortMode=CpReadAndWriteContention);
VARIABLE ModeCpRead : BOOLEAN :=
(CrossPortMode=CpRead) OR
(CrossPortMode=CpReadAndWriteContention);
VARIABLE ModeCpCont : BOOLEAN := (CrossPortMode=ReadWriteContention);
VARIABLE ModeRdWrCont : BOOLEAN := (CrossPortMode=CpReadAndReadContention);
BEGIN
-- Check for disabled port (i.e. OTHERS => 'Z')
IF (DataOutBus = DataOutTmp) THEN
RETURN;
ELSE
DataOutTmp := DataOutBus;
END IF;
-- Check for error in address
IF (Address < 0) THEN
RETURN;
END IF;
ReadMemory(MemoryData,MemoryTmp,Address);
SubWordLoop: -- For each slice of the sub-word I
FOR i IN 0 TO BitsPerEnable-1 LOOP
PortFlagI := SamePortFlag(i);
-- For each cross port J: check with same port address
FOR j IN 0 TO CrossPorts-1 LOOP
PortFlagIJ := CrossPortFlagArray(i+j*BitsPerEnable);
AddressJ := CrossPortAddressArray(j);
IF (AddressJ < 0) THEN
NEXT;
END IF;
DoWrCont := (Address = AddressJ) AND
(ModeWrCont = TRUE) AND
((PortFlagI.MemoryCurrent = WRITE) OR
(PortFlagI.MemoryCurrent = CORRUPT)) AND
((PortFlagIJ.MemoryCurrent = WRITE) OR
(PortFlagIJ.MemoryCurrent = CORRUPT)) ;
DoCpRead := (Address = AddressJ) AND
(ModeCpRead = TRUE) AND
((PortFlagI.MemoryCurrent = READ) OR
(PortFlagI.OutputDisable = TRUE)) AND
((PortFlagIJ.MemoryCurrent = WRITE) OR
(PortFlagIJ.MemoryCurrent = CORRUPT)) ;
DoCpCont := (Address = AddressJ) AND
(ModeCpCont = TRUE) AND
((PortFlagI.MemoryCurrent = READ) OR
(PortFlagI.OutputDisable = TRUE)) AND
((PortFlagIJ.MemoryCurrent = WRITE) OR
(PortFlagIJ.MemoryCurrent = CORRUPT)) ;
DoRdWrCont:= (Address = AddressJ) AND
(ModeRdWrCont = TRUE) AND
((PortFlagI.MemoryCurrent = READ) OR
(PortFlagI.OutputDisable = TRUE)) AND
((PortFlagIJ.MemoryCurrent = WRITE) OR
(PortFlagIJ.MemoryCurrent = CORRUPT)) ;
IF (DoWrCont OR DoCpCont) THEN
-- Corrupt dataout and memory
MemoryTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X');
DataOutTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X');
SamePortFlag(i).MemoryCurrent := CORRUPT;
SamePortFlag(i).DataCurrent := CORRUPT;
SamePortFlag(i).OutputDisable := FALSE;
EXIT;
END IF;
IF (DoCpRead) THEN
-- Update dataout with memory
DataOutTmp(HighBit DOWNTO LowBit) :=
MemoryTmp(HighBit DOWNTO LowBit);
SamePortFlag(i).MemoryCurrent := READ;
SamePortFlag(i).DataCurrent := READ;
SamePortFlag(i).OutputDisable := FALSE;
EXIT;
END IF;
IF (DoRdWrCont) THEN
-- Corrupt dataout only
DataOutTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X');
SamePortFlag(i).DataCurrent := CORRUPT;
SamePortFlag(i).OutputDisable := FALSE;
EXIT;
END IF;
END LOOP;
IF (i < BitsPerEnable-1) THEN
-- Calculate HighBit and LowBit
LowBit := LowBit + BitsPerSubWord;
IF (LowBit > BitsPerWord) THEN
LowBit := BitsPerWord;
END IF;
HighBit := LowBit + BitsPerSubWord;
IF (HighBit > BitsPerWord) THEN
HighBit := BitsPerWord;
ELSE
HighBit := HighBit - 1;
END IF;
END IF;
END LOOP; -- SubWordLoop
DataOutBus := DataOutTmp;
IF (DoWrCont) THEN
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMCP,ErrMcpWrCont,HeaderMsg,PortName);
END IF;
WriteMemory(MemoryData,MemoryTmp,Address);
END IF;
IF (DoCpCont) THEN
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMCP,ErrMcpCpCont,HeaderMsg,PortName);
END IF;
WriteMemory(MemoryData,MemoryTmp,Address);
END IF;
IF (DoCpRead) THEN
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMCP,ErrMcpCpRead,HeaderMsg,PortName);
END IF;
END IF;
IF (DoRdWrCont) THEN
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMCP,ErrMcpRdWrCo,HeaderMsg,PortName);
END IF;
END IF;
END VitalMemoryCrossPorts;
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryCrossPorts (
VARIABLE MemoryData : INOUT VitalMemoryDataType;
CONSTANT CrossPortFlagArray : IN VitalPortFlagVectorType;
CONSTANT CrossPortAddressArray : IN VitalAddressValueVectorType;
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE
) IS
VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord;
VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord;
VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable;
VARIABLE MemoryTmp : std_logic_vector(BitsPerWord-1 DOWNTO 0);
VARIABLE CrossPorts : NATURAL := CrossPortAddressArray'LENGTH;
VARIABLE LowBit : NATURAL := 0;
VARIABLE HighBit : NATURAL := BitsPerSubWord-1;
VARIABLE AddressJ : VitalAddressValueType;
VARIABLE AddressK : VitalAddressValueType;
VARIABLE PortFlagIJ : VitalPortFlagType;
VARIABLE PortFlagIK : VitalPortFlagType;
VARIABLE CpWrCont : BOOLEAN := FALSE;
BEGIN
SubWordLoop: -- For each slice of the sub-word I
FOR i IN 0 TO BitsPerEnable-1 LOOP
-- For each cross port J: check with each cross port K
FOR j IN 0 TO CrossPorts-1 LOOP
PortFlagIJ := CrossPortFlagArray(i+j*BitsPerEnable);
AddressJ := CrossPortAddressArray(j);
-- Check for error in address
IF (AddressJ < 0) THEN
NEXT;
END IF;
ReadMemory(MemoryData,MemoryTmp,AddressJ);
-- For each cross port K
FOR k IN 0 TO CrossPorts-1 LOOP
IF (k <= j) THEN
NEXT;
END IF;
PortFlagIK := CrossPortFlagArray(i+k*BitsPerEnable);
AddressK := CrossPortAddressArray(k);
-- Check for error in address
IF (AddressK < 0) THEN
NEXT;
END IF;
CpWrCont := ( (AddressJ = AddressK) AND
(PortFlagIJ.MemoryCurrent = WRITE) AND
(PortFlagIK.MemoryCurrent = WRITE) ) OR
( (PortFlagIJ.MemoryCurrent = WRITE) AND
(PortFlagIK.MemoryCurrent = CORRUPT) ) OR
( (PortFlagIJ.MemoryCurrent = CORRUPT) AND
(PortFlagIK.MemoryCurrent = WRITE) ) OR
( (PortFlagIJ.MemoryCurrent = CORRUPT) AND
(PortFlagIK.MemoryCurrent = CORRUPT) ) ;
IF (CpWrCont) THEN
-- Corrupt memory only
MemoryTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X');
EXIT;
END IF;
END LOOP; -- FOR k IN 0 TO CrossPorts-1 LOOP
IF (CpWrCont = TRUE) THEN
IF (MsgOn) THEN
PrintMemoryMessage(MsgVMCP,ErrMcpCpWrCont,HeaderMsg);
END IF;
WriteMemory(MemoryData,MemoryTmp,AddressJ);
END IF;
END LOOP; -- FOR j IN 0 TO CrossPorts-1 LOOP
IF (i < BitsPerEnable-1) THEN
-- Calculate HighBit and LowBit
LowBit := LowBit + BitsPerSubWord;
IF (LowBit > BitsPerWord) THEN
LowBit := BitsPerWord;
END IF;
HighBit := LowBit + BitsPerSubWord;
IF (HighBit > BitsPerWord) THEN
HighBit := BitsPerWord;
ELSE
HighBit := HighBit - 1;
END IF;
END IF;
END LOOP; -- SubWordLoop
END VitalMemoryCrossPorts;
-- ----------------------------------------------------------------------------
-- Procedure: VitalMemoryViolation
-- Parameters: DataOutBus - Output zero delay data bus out
-- MemoryData - Pointer to memory data structure
-- PortFlag - Indicates port operating mode
-- TimingDataArray - This is currently not used (comment out)
-- ViolationArray - Aggregation of violation variables
-- DataInBus - Input value of data bus in
-- AddressBus - Input value of address bus in
-- AddressValue - Decoded value of the AddressBus
-- ViolationTable - Input memory violation table
-- PortName - Port name string for messages
-- HeaderMsg - Header string for messages
-- MsgOn - Control the generation of messages
-- MsgSeverity - Control level of message generation
-- Description: This procedure is intended to implement all actions on the
-- memory contents and data out bus as a result of timing viols.
-- It uses the memory action table to perform various corruption
-- policies specified by the user.
-- ----------------------------------------------------------------------------
PROCEDURE VitalMemoryViolation (
VARIABLE DataOutBus : INOUT std_logic_vector;
VARIABLE MemoryData : INOUT VitalMemoryDataType;
VARIABLE PortFlag : INOUT VitalPortFlagVectorType;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT AddressValue : IN VitalAddressValueType;
CONSTANT ViolationFlags : IN std_logic_vector;
CONSTANT ViolationFlagsArray : IN X01ArrayT;
CONSTANT ViolationSizesArray : IN VitalMemoryViolFlagSizeType;
CONSTANT ViolationTable : IN VitalMemoryTableType;
CONSTANT PortType : IN VitalPortType;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
) IS
VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord;
VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord;
VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable;
VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE)
:= DataOutBus;
VARIABLE MemoryAction : VitalMemorySymbolType;
VARIABLE DataAction : VitalMemorySymbolType;
-- VMT relies on the corrupt masks so HighBit/LowBit are full word
VARIABLE HighBit : NATURAL := BitsPerWord-1;
VARIABLE LowBit : NATURAL := 0;
VARIABLE PortFlagTmp : VitalPortFlagType;
VARIABLE VFlagArrayTmp : std_logic_vector
(0 TO ViolationFlagsArray'LENGTH-1);
VARIABLE MemCorruptMask : std_logic_vector (DataOutBus'RANGE);
VARIABLE DatCorruptMask : std_logic_vector (DataOutBus'RANGE);
BEGIN
-- Don't do anything if given an error address
IF (AddressValue < 0) THEN
RETURN;
END IF;
FOR i IN ViolationFlagsArray'RANGE LOOP
VFlagArrayTmp(i) := ViolationFlagsArray(i);
END LOOP;
-- Lookup memory and data actions
ViolationTableLookUp(
MemoryAction => MemoryAction ,
DataAction => DataAction ,
MemoryCorruptMask => MemCorruptMask ,
DataCorruptMask => DatCorruptMask ,
ViolationFlags => ViolationFlags ,
ViolationFlagsArray => VFlagArrayTmp ,
ViolationSizesArray => ViolationSizesArray ,
ViolationTable => ViolationTable ,
BitsPerWord => BitsPerWord ,
BitsPerSubWord => BitsPerSubWord ,
BitsPerEnable => BitsPerEnable ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
-- Need to read incoming PF value (was not before)
PortFlagTmp := PortFlag(0);
IF (PortType = READ OR PortType = RDNWR) THEN
-- Handle data action before memory action
-- This allows reading previous memory contents
HandleDataAction(
DataOutBus => DataOutTmp ,
MemoryData => MemoryData ,
PortFlag => PortFlagTmp ,
CorruptMask => DatCorruptMask ,
DataInBus => DataInBus ,
Address => AddressValue ,
HighBit => HighBit ,
LowBit => LowBit ,
MemoryTable => ViolationTable ,
DataAction => DataAction ,
CallerName => MsgVMV ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
END IF;
IF (PortType = WRITE OR PortType = RDNWR) THEN
HandleMemoryAction(
MemoryData => MemoryData ,
PortFlag => PortFlagTmp ,
CorruptMask => MemCorruptMask ,
DataInBus => DataInBus ,
Address => AddressValue ,
HighBit => HighBit ,
LowBit => LowBit ,
MemoryTable => ViolationTable ,
MemoryAction => MemoryAction ,
CallerName => MsgVMV ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn
);
END IF;
-- Check if we need to turn off PF.OutputDisable
IF (DataAction /= 'S') THEN
PortFlagTmp.OutputDisable := FALSE;
-- Set the output PortFlag(0) value
-- Note that all bits of PortFlag get PortFlagTmp
FOR i IN PortFlag'RANGE LOOP
PortFlag(i) := PortFlagTmp;
END LOOP;
END IF;
-- Set the candidate zero delay return value
DataOutBus := DataOutTmp;
END;
PROCEDURE VitalMemoryViolation (
VARIABLE DataOutBus : INOUT std_logic_vector;
VARIABLE MemoryData : INOUT VitalMemoryDataType;
VARIABLE PortFlag : INOUT VitalPortFlagVectorType;
CONSTANT DataInBus : IN std_logic_vector;
CONSTANT AddressValue : IN VitalAddressValueType;
CONSTANT ViolationFlags : IN std_logic_vector;
CONSTANT ViolationTable : IN VitalMemoryTableType;
CONSTANT PortType : IN VitalPortType;
CONSTANT PortName : IN STRING := "";
CONSTANT HeaderMsg : IN STRING := "";
CONSTANT MsgOn : IN BOOLEAN := TRUE;
CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
) IS
VARIABLE VFlagArrayTmp : X01ArrayT (0 TO 0);
BEGIN
VitalMemoryViolation (
DataOutBus => DataOutBus ,
MemoryData => MemoryData ,
PortFlag => PortFlag ,
DataInBus => DataInBus ,
AddressValue => AddressValue ,
ViolationFlags => ViolationFlags ,
ViolationFlagsArray => VFlagArrayTmp ,
ViolationSizesArray => ( 0 => 0 ) ,
ViolationTable => ViolationTable ,
PortType => PortType ,
PortName => PortName ,
HeaderMsg => HeaderMsg ,
MsgOn => MsgOn ,
MsgSeverity => MsgSeverity
);
END;
END Vital_Memory ;