-- ---------------------------------------------------------------------------- -- 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 ;