-- -- Copyright 1989 by --- -- -- This code is distributed for the purposes of evaluating the -- Waveform And Vector Exchange Specification (WAVES) proposal -- presented to the IEEE by the WAVES Analysis Group. This code -- may not be used for commercial purposes and may not be -- redistributed without permission of the Chairman of the WAVES -- Analysis Group, Mr Robert Hillman. -- -- Address comments or questions to -- Robert Hillman Lee Shombert -- RADC/RBRP Harris Corporation -- Griffis AFB, NY PO Box 94000 MS 16/4010 -- (315) 330-2241 Melbourne, FL 32902 -- (407) 727-6040 -- -- -- TIMESTAMP: 13-DEC-1989 11:14:06.99 -- -- CHANGES: -- 21 DEC 89 L SHOMBERT -- Changed library specifications. Libraries are now: -- WAVES_SLIB -> WAVES_STANDARD -- WAVES_PLIB -> WAVES_PORT -- MATCH functions read WAVES_MATCH_LIST type rather than -- WAVES_PORT_LIST type. The APPLY procedure increments -- the vector counter in WAVES_PORT and toggles the MATCH -- field. The significant counter and comparator are in -- the leftmost pin. -- -- 21 FEB 90 A WILMOT -- The declarations for INDEX, FRAME_EVENT and -- FRAME_ELIST were moved into this package from the -- WAVES_OBJECTS package. This reflects current usage in -- the examples and boilerplates, where frames and frame_sets -- are defined without reference to WAVES_OBJECTS (and its -- dependence on the TEST_PINS declaration). -- The mode of the CONNECT parameter to APPLY and TAG was -- changed from inout to out. -- -- package body WAVES_INTERFACE is -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- The following three functions make it easy to declare an EVENT_TIME. -- -- The first function returns an event time with no tolerances. The -- nominal time defaults to 0 ns. -- -- The second function returns an event time with symmetric bounds. -- -- The third function allows the bounds to be specified independently. -- function ETIME ( NOMINAL : TIME := 0 ns ) return EVENT_TIME is begin return ( NOMINAL, FALSE, 0 ns, 0 ns ); end ETIME; function ETIME ( NOMINAL : TIME; EARLIEST_AND_LATEST : TIME ) return EVENT_TIME is begin return ( NOMINAL, TRUE, others => EARLIEST_AND_LATEST); end ETIME; function ETIME ( NOMINAL : TIME; EARLIEST : TIME; LATEST : TIME ) return EVENT_TIME is begin return ( NOMINAL, TRUE, EARLIEST, LATEST); end ETIME; function MERGE_ETIME ( A : EVENT_TIME; B : EVENT_TIME ) return EVENT_TIME is variable X : EVENT_TIME := A; begin if not X.TOLERANCES_SPECIFIED then X.TOLERANCES_SPECIFIED := B.TOLERANCES_SPECIFIED; X.EARLIEST := B.EARLIEST; X.LATEST := B.LATEST; end if; return X; end MERGE_ETIME; -- -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- INTERNAL -=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- These two functions return the minimum of the inputs and the maximum -- of the inputs respectively. They are just service routines for other -- procedures in this package. -- function MIN(A, B : INTEGER) return INTEGER is begin if A <= B then return A; else return B; end if; end MIN; function MAX(A, B : INTEGER) return INTEGER is begin if A >= B then return A; else return B; end if; end MAX; -- -=-=-=-=-=-=-=-=-=-=-=-=-=- PACKAGE PRIVATE -=-=-=-=-=-=-=-=-=-=-=-=- -- -- This constant is used to determine whether a tagged event contains a -- real event or is just an empty placeholder. -- -- See also declaration of EMPTY_EVENT in WAVES_OBJECTS body constant EMPTY_EVENT : INTEGER := -1; -- -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- The following functions are used by to create and manipulate frames, -- frame sets, and frame set arrays. The first set of functions return -- the incoming object with it last index range adjusted to be (1 to L), -- truncating or padding with unspecified tagged events, as appropriate. -- The second set of operations are array concatenation, treating a -- frame set as an array of frames and a frame set array as an array of -- frame sets. -- function PROMOTE ( DATA : FRAME_1 ) return FRAME_2 is variable TEMP_2 : FRAME_2 (1 to 1, DATA'RANGE(1)); begin for I in DATA'RANGE(1) loop TEMP_2(1, I) := DATA(I); end loop; return TEMP_2; end PROMOTE; function PROMOTE ( DATA : FRAME_2 ) return FRAME_3 is variable TEMP_3 : FRAME_3 (1 to 1, DATA'RANGE(1), DATA'RANGE(2)); begin for I in DATA'RANGE(1) loop for J in DATA'RANGE(2) loop TEMP_3(1, I, J) := DATA(I, J); end loop; end loop; return TEMP_3; end PROMOTE; function RESIZE ( DATA : FRAME_1; LENGTH_1 : POSITIVE ) return FRAME_1 is variable TEMP_1 : FRAME_1 (1 to LENGTH_1); begin for I in DATA'RANGE(1) loop TEMP_1(I).VALUE := EMPTY_EVENT; end loop; for I in 1 to MIN(LENGTH_1, DATA'LENGTH(1)) loop TEMP_1(I) := DATA(I); end loop; return TEMP_1; end RESIZE; function RESIZE ( DATA : FRAME_2; LENGTH_2 : POSITIVE; LENGTH_1 : POSITIVE ) return FRAME_2 is variable TEMP_2 : FRAME_2 (1 to LENGTH_2, 1 to LENGTH_1); begin for I in TEMP_2'RANGE(1) loop for J in TEMP_2'RANGE(2) loop TEMP_2(I, J).VALUE := EMPTY_EVENT; end loop; end loop; for I in 1 to MIN(LENGTH_2, DATA'LENGTH(1)) loop for J in 1 to MIN(LENGTH_1, DATA'LENGTH(2)) loop TEMP_2(I, J) := DATA(I, J); end loop; end loop; return TEMP_2; end RESIZE; function RESIZE ( DATA : FRAME_3; LENGTH_3 : POSITIVE; LENGTH_2 : POSITIVE; LENGTH_1 : POSITIVE ) return FRAME_3 is variable TEMP_3 : FRAME_3 (1 to LENGTH_3, 1 to LENGTH_2, 1 to LENGTH_1); begin for I in TEMP_3'RANGE(1) loop for J in TEMP_3'RANGE(2) loop for K in TEMP_3'RANGE(3) loop TEMP_3(I, J, K).VALUE := EMPTY_EVENT; end loop; end loop; end loop; for I in 1 to MIN(LENGTH_3, DATA'LENGTH(1)) loop for J in 1 to MIN(LENGTH_2, DATA'LENGTH(2)) loop for K in 1 to MIN(LENGTH_1, DATA'LENGTH(3)) loop TEMP_3(I, J, K) := DATA(I, J, K); end loop; end loop; end loop; return TEMP_3; end RESIZE; -- -- The following three functions trim unspecified tagged events from -- the various frame types. -- function TRIM ( DATA : FRAME_1 ) return FRAME_1 is variable LENGTH_1 : NATURAL := 1; begin for I in DATA'LENGTH(1) downto 1 loop if DATA(I).VALUE > EMPTY_EVENT then LENGTH_1 := I; exit; end if; end loop; return RESIZE(DATA, LENGTH_1); end TRIM; function TRIM ( DATA : FRAME_2 ) return FRAME_2 is variable LENGTH_1 : NATURAL := 1; variable LENGTH_2 : NATURAL := 1; begin for I in DATA'LENGTH(1) downto 1 loop for J in DATA'LENGTH(2) downto 1 loop if DATA(I, J).VALUE > EMPTY_EVENT then LENGTH_1 := I; exit; end if; end loop; end loop; for J in DATA'LENGTH(2) downto 1 loop for I in DATA'LENGTH(1) downto 1 loop if DATA(I, J).VALUE > EMPTY_EVENT then LENGTH_2 := J; exit; end if; end loop; end loop; return RESIZE(DATA, LENGTH_1, LENGTH_2); end TRIM; function TRIM ( DATA : FRAME_3 ) return FRAME_3 is variable LENGTH_1 : NATURAL := 1; variable LENGTH_2 : NATURAL := 1; variable LENGTH_3 : NATURAL := 1; begin for I in DATA'LENGTH(1) downto 1 loop for J in DATA'LENGTH(2) downto 1 loop for K in DATA'LENGTH(3) downto 1 loop if DATA(I, J, K).VALUE > EMPTY_EVENT then LENGTH_1 := I; exit; end if; end loop; end loop; end loop; for J in DATA'LENGTH(2) downto 1 loop for I in DATA'LENGTH(1) downto 1 loop for K in DATA'LENGTH(3) downto 1 loop if DATA(I, J, K).VALUE > EMPTY_EVENT then LENGTH_2 := I; exit; end if; end loop; end loop; end loop; for K in DATA'LENGTH(3) downto 1 loop for I in DATA'LENGTH(1) downto 1 loop for J in DATA'LENGTH(2) downto 1 loop if DATA(I, J, K).VALUE > EMPTY_EVENT then LENGTH_3 := I; exit; end if; end loop; end loop; end loop; return RESIZE(DATA, LENGTH_1, LENGTH_2, LENGTH_3); end TRIM; -- -- The following functions concatenate two objects of the same -- dimensionality, returning a similar object of the same -- dimensionality. The effect is similar to the concatentation of -- one dimensional arrays. Secondary array dimensions are adjusted -- prior to concatenation. Normally, one would trim these arrays prior -- to concatenation to eliminate "null" rows of tagged events. -- function CONCAT(A, B : FRAME_1) return FRAME_1 is variable INDEX : NATURAL := 0; variable TEMP_1 : FRAME_1 (1 to A'LENGTH + B'LENGTH); begin for I in 1 to A'LENGTH(1) loop TEMP_1(I) := A(I); end loop; for I in 1 to B'LENGTH(1) loop TEMP_1(I + A'LENGTH(1)) := B(I); end loop; return TEMP_1; end CONCAT; function CONCAT(A, B : FRAME_2) return FRAME_2 is variable LENGTH_1 : POSITIVE := MAX(A'LENGTH(2), B'LENGTH(2)); variable TEMP_2 : FRAME_2 (1 to A'LENGTH(1) + B'LENGTH(1), 1 to LENGTH_1); begin if A'LENGTH(2) /= B'LENGTH(2) then return CONCAT(RESIZE(A,A'LENGTH(1), LENGTH_1), RESIZE(B,B'LENGTH(1), LENGTH_1)); else for I in 1 to A'LENGTH(1) loop for J in 1 to LENGTH_1 loop TEMP_2(I, J) := A(I, J); end loop; end loop; for I in 1 to B'LENGTH(1) loop for J in 1 to LENGTH_1 loop TEMP_2(I + A'LENGTH(1), J) := B(I, J); end loop; end loop; return TEMP_2; end if; end CONCAT; function CONCAT(A, B : FRAME_3) return FRAME_3 is variable LENGTH_1 : POSITIVE := MAX(A'LENGTH(3), B'LENGTH(3)); variable LENGTH_2 : POSITIVE := MAX(A'LENGTH(2), B'LENGTH(2)); variable TEMP_3 : FRAME_3 (1 to A'LENGTH(1) + B'LENGTH(1), 1 to LENGTH_2, 1 to LENGTH_1); begin if A'LENGTH(2) /= B'LENGTH(2) or A'LENGTH(3) /= B'LENGTH(3) then return CONCAT(RESIZE(A,A'LENGTH(1), LENGTH_2, LENGTH_1), RESIZE(B,B'LENGTH(1), LENGTH_2, LENGTH_1)); else for I in 1 to A'LENGTH(1) loop for J in 1 to LENGTH_2 loop for K in 1 to LENGTH_1 loop TEMP_3(I, J, K) := A(I, J, K); end loop; end loop; end loop; for I in 1 to B'LENGTH(1) loop for J in 1 to LENGTH_2 loop for K in 1 to LENGTH_1 loop TEMP_3(I + A'LENGTH(1), J, K) := B(I, J, K); end loop; end loop; end loop; return TEMP_3; end if; end CONCAT; -- -- The following functions allow a WAVES dataset to create a frame set -- from a set of frames using the concatenation operator. Input -- parameters are not trimmed, to allow frame sets to contain empty -- frames. -- function "+"(A : FRAME_1; B : FRAME_1) return FRAME_2 is begin return CONCAT(PROMOTE(A), PROMOTE(B)); end "+"; function "+"(A : FRAME_2; B : FRAME_1) return FRAME_2 is begin return CONCAT(A, PROMOTE(B)); end "+"; function "+"(A : FRAME_1; B : FRAME_2) return FRAME_2 is begin return CONCAT(PROMOTE(A), B); end "+"; function "+"(A : FRAME_2; B : FRAME_2) return FRAME_2 is begin return CONCAT(A, B); end "+"; -- -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- The following functions convert a single tagged event into a frame -- (a list of tagged events). The empty case returns a frame of length -- one with the tagged event marked unspecified. -- function FRAME_TAGGED_EVENT return FRAME is variable TEMP_1 : FRAME_1 (1 to 1); begin TEMP_1(1).VALUE := -1; return TEMP_1; end FRAME_TAGGED_EVENT; function FRAME_TAGGED_EVENT ( EVENTS : TAGGED_EVENT ) return FRAME is variable TEMP_1 : FRAME_1 (1 to 1); begin TEMP_1(1).VALUE := EVENTS.VALUE; TEMP_1(1).TIME := EVENTS.TIME; return TEMP_1; end FRAME_TAGGED_EVENT; -- -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- The following functions convert a single event or a single event list -- into a frame (a list of tagged events). The empty case returns a -- frame of length one with the tagged event marked unspecified. -- function INDEX ( VALUE : LOGIC_VALUE ) return INTEGER is begin return LOGIC_VALUE'POS(VALUE); end INDEX; function FRAME_EVENT return FRAME is begin return FRAME_TAGGED_EVENT; end FRAME_EVENT; function FRAME_EVENT ( EVENTS : EVENT ) return FRAME is variable I : INTEGER := INDEX(EVENTS.VALUE); variable T : TAGGED_EVENT := (I, EVENTS.TIME); begin return FRAME_TAGGED_EVENT(T); end FRAME_EVENT; function FRAME_ELIST return FRAME is begin return FRAME_TAGGED_EVENT; end FRAME_ELIST; function FRAME_ELIST ( EVENTS : EVENT_LIST ) return FRAME is variable X : FRAME(EVENTS'RANGE); begin for I in X'RANGE loop X(I) := (INDEX(EVENTS(I).VALUE), EVENTS(I).TIME); end loop; return X; end FRAME_ELIST; -- -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- PROCEDURE -=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- This subprogram performs signal assignments to the CONNECT parameter -- based on the PERIOD and EVENTS parameters. If the CODES parameter is -- not null, then the character codes are applied to CONNECT as well. -- The dimensions of CONNECT, EVENTS, and CODES (if present) must be -- identical. The vector counter in the WAVES_PORT of the leftmost pin -- is incremented and the comparator reset field is toggled. The -- subprogram waits for PERIOD.NOMINAL before returning to the caller. -- -- The following procedure is implementation dependent and un-standardized procedure APPLY ( signal CONNECT : out WAVES_PORT_LIST; PERIOD : in EVENT_TIME; EVENTS : in FRAME_SET; CODES : in STRING := "") is begin assert CONNECT'LENGTH = EVENTS'LENGTH(1); assert CODES'LENGTH = 0 or CODES'LENGTH = CONNECT'LENGTH; for PIN in CONNECT'RANGE loop for E in EVENTS'RANGE(2) loop exit when EVENTS(PIN,E).VALUE <= EMPTY_EVENT; CONNECT(PIN).DATA <= transport EVENTS(PIN, E).VALUE after EVENTS(PIN, E).TIME.NOMINAL ; end loop; if CODES'LENGTH > 0 then CONNECT(PIN).CODE <= transport CODES(PIN) ; else CONNECT(PIN).CODE <= transport NUL ; end if; end loop; -- This implementation of TAG and MATCH is not compatible with -- current implementation of WAVES datasets -- CONNECT(CONNECT'LEFT).VECTOR <= transport -- CONNECT(CONNECT'LEFT).VECTOR + 1; -- CONNECT(CONNECT'LEFT).COMPARE <= transport -- not CONNECT(CONNECT'LEFT).COMPARE; wait for PERIOD.NOMINAL; end APPLY; -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- PROCEDURE -=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- This subprogram performs signal assignments to the CONNECT parameter -- based on the TAG_LABEL parameter. The string in this parameter is -- sent through the CONNECT parameter to the outside simulation -- environment, and is used to pass messages (labels), mostly for debug -- purposes. -- procedure TAG ( signal CONNECT : out WAVES_PORT_LIST; TAG_LABEL : in STRING ) is begin for I in TAG_LABEL'RANGE loop CONNECT(CONNECT'LEFT).MESSAGE <= transport TAG_LABEL(I); wait for 0 ns; end loop; end TAG; -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=- FUNCTION -=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- -- This function returns the logical AND of the match values for every -- element in the CONNECT parameter. -- function MATCH ( CONNECT : in WAVES_MATCH_LIST ) return BOOLEAN is variable FLAG : BOOLEAN := TRUE; begin for I in CONNECT'RANGE loop FLAG := FLAG and CONNECT(I); end loop; return FLAG; end MATCH; end WAVES_INTERFACE;