--synopsys synthesis_off ---------------------------------------------------------------------------- -- -- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. -- -- This program is proprietary and confidential information of -- Synopsys, Inc. and may be used and disclosed only as authorized -- in a license agreement controlling such use and disclosure. -- -- Package name: vhdlzq.vhd -- -- Purpose: This package defines a zero length queue type and operations -- on that type. This package can be copied and changed to allow -- queueing different types. -- -- Author: PH -- ---------------------------------------------------------------------------- -- -- Generic zero length queue package. -- -- A zero length queue package allows two processes to rendezvous at a -- particular instant of simulated time. They also communicate a value -- during the rendezvous. -- -- To make you own zero length queue type: -- 1. Make a copy of this package. -- 2. Change the name of the package (both specification and body). -- 3. Change the subtype indication in the declaration of QE_TYPE. -- -- To use a queue: -- 1. Declare a signal of the queue type: -- signal IQ: INTEGER_ZQUEUES.QTYPE; -- 2. Use SEND and RECEIVE to request a rendezvous (the data value is -- communicated from the sender to the receiver): -- SEND(E, IQ); -- RECEIVE(E, IQ); -- 4. Notes about SEND and RECEIVE: -- a. SEND and RECEIVE block until the rendezvous completes. -- b. These two procedures take an optional parameter (PRIORITY) -- that is used to choose between multiple processes that -- want to send or receive on the queue at the same instant of -- simulated time. An error is raised if multiple senders or -- receivers want to operate simultaneously on the queue and -- each sender or receiver does not have a unique priority. -- c. Lower PRIORITY numbers are serviced before higher PRIORITY -- numbers. -- d. Each of these procedures will consume at least 2 -- simulation cycles (more if an operation blocks or multiple -- processes wish to operate on the queue simultaneously). -- 5. EMPTY and FULL always return TRUE, LENGTH always returns 0. -- 6. To ensure the consistency of the queue abstraction, the queue object -- should not be directly read or updated (except through port -- association), but manipulated only through the SEND, -- RECEIVE, EMPTY, FULL, and LENGTH subprograms. -- 7. Several components of the queue data structure are maintained -- so that the user can instrument the use of the queue. These -- components can be safely read, monitored, and traced from -- within the simulator. For a queue Q, these components are: -- Q.C.length The length of the queue. Same value as -- returned by the function LENGTH. -- Q.C.Qput Last value inserted into Q by a put operation. -- Q.C.Qget Last value removed from Q by a get operation. -- Q.C.Qsend Last value inserted into Q by a send operation. -- This is updated when a process returns from -- a call on SEND. -- Q.C.Qreceive Last value removed from Q by a receive -- operation. This is updated when a process -- returns from a call on RECEIVE. -- Q.C.Qswait The length of time the last process which -- returned from a SEND waited. -- Q.C.Qrwait The length of time the last process which -- returned from a RECEIVE waited. -- Q.C.Qwait The length of time the last queue element -- removed from the queue by either a GET or -- RECEIVE operation was in the queue plus the -- length of time its sender was delayed. -- (I.e. the length of time between when the -- value was sent and when it was received.) -- Q.C.Qslength The number of waiting senders. -- Q.C.Qrlength The number of waiting receivers. -- 8. If you don't want this instrumentation, you can delete all the -- lines in this file that contain --INSTRUMENTATION--. This -- will make your queue take less space. -- library SYNOPSYS; use SYNOPSYS.ATTRIBUTES.REFLEXIVE; package INTEGER_ZQUEUES is subtype QE_TYPE is INTEGER; -- replace INTEGER with type to be queued -- -- The rest of the declarations in the package specification and body -- should not be modified. -- type QOP is (Q_NOP, Q_0SEND, Q_0RECEIVE, Q_RENDEZVOUS); -- -- QCONTROL is a record which controls the rendezvous protocol. -- SPRIORITY is the priority of a sending process. -- RPRIORITY is the priority of a receiving process. -- OP is used to determine if a process is currently requesting access -- to the queue, and if so whether it is a send or receive. It is -- used to communicate that a rendezvous is taking place. -- E is used to communicate the value which is passed between processes -- during a rendezvous. -- type QCONTROL is record SPRIORITY, RPRIORITY: natural; OP: QOP; E: QE_TYPE; Qsend, Qreceive: QE_TYPE; --INSTRUMENTATION-- Qswait, Qrwait, Qwait: TIME; --INSTRUMENTATION-- Qslength, Qrlength: NATURAL; --INSTRUMENTATION-- length: NATURAL; --INSTRUMENTATION-- Qput, Qget: QE_TYPE; --INSTRUMENTATION-- end record; type QCA is array (natural range <>) of QCONTROL; function QCRF (X: QCA) return QCONTROL; -- For performance improvement on Synopsys's simulator: attribute REFLEXIVE of QCRF: function is TRUE; type QTYPE is record C: QCRF QCONTROL; end record; procedure SEND(E: QE_TYPE; signal Q: inout QTYPE; PRIORITY: natural := 0); procedure RECEIVE(E: out QE_TYPE; signal Q: inout QTYPE; PRIORITY: natural := 0); function EMPTY(Q: QTYPE) return boolean; function FULL(Q: QTYPE) return boolean; function LENGTH(Q: QTYPE) return natural; end; package body INTEGER_ZQUEUES is -- -- All the work for zero-length queues takes place in the resolution function. -- A rendezvous occurs when we have both a sender and a receiver. Most of -- this function is concerned with finding the highest priority sender and -- receiver. Once they are found, the control record is filled in with the -- rendezvous information. -- function QCRF (X: QCA) return QCONTROL is variable R: QCONTROL; variable FOUND_SDR, FOUND_RCVR: boolean := FALSE; variable SDR, RCVR: integer range X'range; variable Qslength, Qrlength: NATURAL := 0; --INSTRUMENTATION-- begin -- find highest priority sender. for I in X'range loop Qslength := Qslength + X(I).Qslength; --INSTRUMENTATION-- Qrlength := Qrlength + X(I).Qrlength; --INSTRUMENTATION-- next when X(I).OP /= Q_0SEND and X(I).OP /= Q_RENDEZVOUS; if not FOUND_SDR or X(I).SPRIORITY < X(SDR).SPRIORITY then FOUND_SDR := true; SDR := I; next; end if; assert X(I).SPRIORITY > X(SDR).SPRIORITY report "Two processes operating on the same queue at the same time with the same priority" severity FAILURE; end loop; -- find highest priority receiver. for I in X'range loop next when X(I).OP /= Q_0RECEIVE and X(I).OP /= Q_RENDEZVOUS; if not FOUND_RCVR or X(I).RPRIORITY < X(RCVR).RPRIORITY then FOUND_RCVR := true; RCVR := I; next; end if; assert X(I).RPRIORITY > X(RCVR).RPRIORITY report "Two processes operating on the same queue at the same time with the same priority" severity FAILURE; end loop; if FOUND_SDR and FOUND_RCVR then R.SPRIORITY := X(SDR).SPRIORITY; R.RPRIORITY := X(RCVR).RPRIORITY; R.E := X(SDR).E; R.Qsend := R.E; --INSTRUMENTATION-- R.Qreceive := R.E; --INSTRUMENTATION-- R.OP := Q_RENDEZVOUS; elsif not FOUND_RCVR then R := X(SDR); elsif not FOUND_SDR then R := X(RCVR); end if; R.Qslength := Qslength; --INSTRUMENTATION-- R.Qrlength := Qrlength; --INSTRUMENTATION-- return R; end; function EMPTY(Q: QTYPE) return boolean is begin return TRUE; end; function FULL(Q: QTYPE) return boolean is begin return TRUE; end; function LENGTH(Q: QTYPE) return natural is begin return 0; end; procedure SEND(E: QE_TYPE; signal Q: inout QTYPE; PRIORITY: natural := 0) is variable XT: TIME := NOW; --INSTRUMENTATION-- begin Q.C.Qslength <= 1; --INSTRUMENTATION-- Q.C.SPRIORITY <= PRIORITY; Q.C.OP <= Q_0SEND; Q.C.E <= E; wait on Q until Q.C.SPRIORITY = PRIORITY and Q.C.OP = Q_RENDEZVOUS; Q.C.OP <= Q_NOP; Q.C.Qslength <= 0; --INSTRUMENTATION-- Q.C.Qswait <= NOW-XT; --INSTRUMENTATION-- Q.C.Qwait <= NOW-XT; --INSTRUMENTATION-- wait for 0 ns; end SEND; procedure RECEIVE(E: out QE_TYPE; signal Q: inout QTYPE; PRIORITY: natural := 0) is variable XT: TIME := NOW; --INSTRUMENTATION-- begin Q.C.Qrlength <= 1; --INSTRUMENTATION-- Q.C.RPRIORITY <= PRIORITY; Q.C.OP <= Q_0RECEIVE; wait on Q until Q.C.RPRIORITY = PRIORITY and Q.C.OP = Q_RENDEZVOUS; E := Q.C.E; Q.C.OP <= Q_NOP; Q.C.Qrlength <= 0; --INSTRUMENTATION-- Q.C.Qrwait <= NOW-XT; --INSTRUMENTATION-- wait for 0 ns; end RECEIVE; end; --synopsys synthesis_on