Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: XactorManager.vr | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | #include <vera_defines.vrh> | |
36 | #include "XactorCtrl.vrh" | |
37 | #include "XactorUtilities.vrh" | |
38 | #include "XactorClk.port.vri" | |
39 | #include "XactorComponentsDefines.vri" | |
40 | ||
41 | #include "XactorDefines.vri" | |
42 | #include "XactorBasePacket.vrh" | |
43 | #include "XactorBaseManager.vrh" | |
44 | #include "XactorBaseExpectDataStruct.vrh" | |
45 | #include "XactorBaseBuilder.vrh" | |
46 | ||
47 | #include "cReport.vrh" | |
48 | ||
49 | class XactorManager extends XactorBaseManager { | |
50 | ||
51 | // ++++++++ Expect Manager properties ++++++++ | |
52 | // This is the Fifo structure where expected packets from the signal | |
53 | // interface are received (a mailbox is used). | |
54 | integer ExpectFifo; | |
55 | // Expect Data Structures are defined in XactorBaseManager | |
56 | ||
57 | // ++++++++ Drive Manager properties ++++++++ | |
58 | // This is the Fifo structure where packets to be driven to the signal | |
59 | // interface are sent (a mailbox is used). | |
60 | integer DriveFifo; | |
61 | // This semaphore is used to schedule requests to drive packets | |
62 | protected integer DriverSemaphore; | |
63 | ||
64 | // Enable/Disable/Reset Transactor property | |
65 | XactorCtrl _XactorCtrl; | |
66 | ||
67 | // +++++++ Sample transaction properties ++++++++ | |
68 | // this packet is used to store the values of transactions coming from the | |
69 | // signal interface | |
70 | protected XactorBasePacket SampledPkt; | |
71 | // this event is triggered when sample flag is set and a new transaction | |
72 | // was sampled from the DUT | |
73 | protected event NewTransaction; | |
74 | ||
75 | // Transactor name | |
76 | protected string XactorName; | |
77 | ||
78 | // Transactor clock port | |
79 | protected XactorClk ClkPort; | |
80 | ||
81 | // MyReport declared in XactorBaseManager | |
82 | ||
83 | task new (XactorBaseBuilder Builder, | |
84 | XactorClk _ClkPort | |
85 | ); | |
86 | ||
87 | // -------------------------------------------------------------------------- | |
88 | // Expect and Drive Manager methods | |
89 | // -------------------------------------------------------------------------- | |
90 | // Prints out pending expects. A packet has to be passed, since data structures | |
91 | // store values in a "compressed way" and packets know how to decode that | |
92 | // information | |
93 | virtual task DumpExpects(); | |
94 | ||
95 | // Returns 1 if an expect with the value ExpectedPacket is pending and 0 otherwise | |
96 | virtual function bit ExpectPending(XactorBasePacket ExpectedPacket); | |
97 | ||
98 | // Returns 1 if the expect with the value in ExpectedPacket is removed successfully | |
99 | // and 0 otherwise | |
100 | virtual function bit Remove(XactorBasePacket ExpectedPacket); | |
101 | ||
102 | // Returns the number of pending expects in all the data structures | |
103 | // of the transactor | |
104 | virtual function integer NumExpects(); | |
105 | ||
106 | // Removes Packet from ExpectDataStruct. Success is 1 if | |
107 | // Packet is removed without problems and 0 otherwise | |
108 | virtual protected task RemoveExpect(XactorBasePacket Packet, | |
109 | var bit Success | |
110 | ); | |
111 | ||
112 | // Same as RemoveExpect, but it will remove Packet from the XExpectDataStruct | |
113 | virtual protected task RemoveXExpect(XactorBasePacket Packet, | |
114 | var bit Success | |
115 | ); | |
116 | ||
117 | // Same as RemoveExpect, but it will remove Packet from the XExpectDataStruct | |
118 | // Compared to RemoveXExpect, this task will call WildCardDelete1 | |
119 | virtual protected task RemoveRefExpect(XactorBasePacket Packet, | |
120 | var bit Success | |
121 | ); | |
122 | ||
123 | // Same as RemoveExpect, but it will remove Packet from the XExpectDataStruct | |
124 | // Compared to RemoveXExpect, this task will call WildCardDelete1 | |
125 | virtual protected task RemoveRefXExpect(XactorBasePacket Packet, | |
126 | var bit Success | |
127 | ); | |
128 | ||
129 | // This task will wait for a maximum of Window cycles for the ExpectedPkt to be removed from | |
130 | // the expect data structures. Removed is an event variable that is triggered when ExpectedPkt is | |
131 | // removed. TransactionRemoved will be 1 if ExpectedPkt was removed and 0 otherwise. Id is the | |
132 | // id number of the expect transaction. | |
133 | virtual task ExpectPkt(XactorBasePacket ExpectedPkt, | |
134 | integer Window, | |
135 | var bit [1:0] Status | |
136 | ); | |
137 | ||
138 | // This task will wait for the next transaction driven by the DUT, it will then sample it and | |
139 | // will return the values through Pkt | |
140 | virtual task SamplePkt(XactorBasePacket Pkt, | |
141 | integer Window | |
142 | ); | |
143 | ||
144 | // This task will be waiting for transactions coming from the DUT | |
145 | // and match them with the pending list of expects (stored in the data structures) | |
146 | virtual protected task ExpectConsumer(); | |
147 | ||
148 | // This task will receive DrivenPkt and will wait D clock cycles before DrivenPkt is | |
149 | // scheduled for driving | |
150 | virtual task DrivePkt(XactorBasePacket DrivenPkt, integer D); | |
151 | ||
152 | // This task will disable the transactor | |
153 | virtual task DisableManager(); | |
154 | ||
155 | // This task will enable the transactor | |
156 | virtual task EnableManager(); | |
157 | ||
158 | // This task will flush the Drive Fifo | |
159 | virtual protected task FlushDriveFifo(); | |
160 | ||
161 | // This task will reset the transactor | |
162 | virtual task ResetManager(); | |
163 | ||
164 | } | |
165 | ||
166 | //////////////// | |
167 | // Definitions | |
168 | //////////////// | |
169 | ||
170 | task XactorManager::new (XactorBaseBuilder Builder, | |
171 | XactorClk _ClkPort | |
172 | ) { | |
173 | // ++++++++ Expect Manager Initialization ++++++++ | |
174 | // The Builder object will be in charge of creating the proper type of | |
175 | // objects for each property handle of this class. | |
176 | XactorName = Builder.CreateName(); | |
177 | ExpectDataStruct = Builder.CreateExpectDataStruct(); | |
178 | XExpectDataStruct = Builder.CreateXExpectDataStruct(); | |
179 | MyReport = Builder.CreateReport(); | |
180 | ExpectFifo = alloc(MAILBOX, 0, 1); | |
181 | if(ExpectFifo == 0) { | |
182 | MyReport.report(RTYP_XACTOR_FMWORK_MEM_ALLOCATION_ERROR, | |
183 | "$0s: Failed to allocate ExpectFifo mailbox!!", | |
184 | XactorName); | |
185 | } | |
186 | ClkPort = _ClkPort; | |
187 | ||
188 | fork { | |
189 | ExpectConsumer(); | |
190 | } | |
191 | join none | |
192 | ||
193 | // ++++++++ Drive Manager initialization +++++++++ | |
194 | DriveFifo = alloc(MAILBOX, 0, 1); | |
195 | if(DriveFifo == 0) { | |
196 | MyReport.report(RTYP_XACTOR_FMWORK_MEM_ALLOCATION_ERROR, | |
197 | "$0s: Failed to allocate DriveFifo mailbox!!", | |
198 | XactorName); | |
199 | } | |
200 | DriverSemaphore = alloc(SEMAPHORE, 0, 1, 1); | |
201 | if(DriverSemaphore == 0) { | |
202 | MyReport.report(RTYP_XACTOR_FMWORK_MEM_ALLOCATION_ERROR, | |
203 | "$0s: Failed to allocate DriverSemaphore semaphore!!", | |
204 | XactorName); | |
205 | } | |
206 | ||
207 | // ++++++++ General properties initialization ++++++++++ | |
208 | _XactorCtrl = new(Builder); | |
209 | } | |
210 | ||
211 | // -------------------------------------------------------------------------- | |
212 | // Expect and Drive Manager methods | |
213 | // -------------------------------------------------------------------------- | |
214 | // Prints out pending expects. A packet has to be passed, since data structures | |
215 | // store values in a "compressed way" and packets know how to decode that | |
216 | // information | |
217 | task XactorManager::DumpExpects() { | |
218 | ||
219 | // First print nodes from the main expect data structure | |
220 | semaphore_get(WAIT, _XactorCtrl.ExpectDataStructSemaphore, 1); | |
221 | MyReport.report(RTYP_INFO, "XactorManager::DumpExpects(): Dumping Expect Structure:\n"); | |
222 | ExpectDataStruct.PrintNodes(); | |
223 | semaphore_put(_XactorCtrl.ExpectDataStructSemaphore, 1); | |
224 | ||
225 | // Then print nodes from the expect data structure that was nodes | |
226 | // with "wildcard" values (X's) | |
227 | semaphore_get(WAIT, _XactorCtrl.XExpectDataStructSemaphore, 1); | |
228 | MyReport.report(RTYP_INFO, "XactorManager::DumpExpects(): Dumping Wildcard Expect Structure:\n"); | |
229 | XExpectDataStruct.PrintNodes(); | |
230 | semaphore_put(_XactorCtrl.XExpectDataStructSemaphore, 1); | |
231 | } | |
232 | ||
233 | // Returns 1 if an expect with the value ExpectedPacket is pending and 0 otherwise | |
234 | function bit XactorManager::ExpectPending(XactorBasePacket ExpectedPacket) { | |
235 | bit ExpectPendingBit = 1'b0; | |
236 | bit XExpectPendingBit = 1'b0; | |
237 | ||
238 | // First check if the expect is pending in the main expect data structure | |
239 | semaphore_get(WAIT, _XactorCtrl.ExpectDataStructSemaphore, 1); | |
240 | if((!(ExpectDataStruct.Empty())) && (!ExpectedPacket.PktUndef())) | |
241 | ExpectPendingBit = ExpectDataStruct.InStructure(ExpectedPacket); | |
242 | semaphore_put(_XactorCtrl.ExpectDataStructSemaphore, 1); | |
243 | ||
244 | // Then check if the expect is in the expect data structure with "wildcards" | |
245 | semaphore_get(WAIT, _XactorCtrl.XExpectDataStructSemaphore, 1); | |
246 | if((!(XExpectDataStruct.Empty())) && (ExpectedPacket.PktUndef())) | |
247 | XExpectPendingBit = XExpectDataStruct.InStructure(ExpectedPacket); | |
248 | semaphore_put(_XactorCtrl.XExpectDataStructSemaphore, 1); | |
249 | ||
250 | ExpectPending = ExpectPendingBit | XExpectPendingBit; | |
251 | } | |
252 | ||
253 | // Returns 1 if the expect with the value in ExpectedPacket is removed successfully | |
254 | // and 0 otherwise | |
255 | function bit XactorManager::Remove(XactorBasePacket ExpectedPacket) { | |
256 | // Success flags when an expect transaction is removed from a data | |
257 | // structure. | |
258 | bit SuccessWildcard = 1'b0; | |
259 | bit Success = 1'b0; | |
260 | ||
261 | // First check if the expect is pending in the main expect data structure | |
262 | RemoveRefExpect(ExpectedPacket, Success); | |
263 | // Then check if the expect is in the expect data structure with "wildcards" | |
264 | RemoveRefXExpect(ExpectedPacket, SuccessWildcard); | |
265 | ||
266 | Remove = Success | SuccessWildcard; | |
267 | } | |
268 | ||
269 | // Returns the number of pending expects in all the data structures | |
270 | // of the transactor | |
271 | function integer XactorManager::NumExpects() { | |
272 | integer Expects = 0; | |
273 | ||
274 | // First count the expects pending in the main expect data structure | |
275 | semaphore_get(WAIT, _XactorCtrl.ExpectDataStructSemaphore, 1); | |
276 | Expects = ExpectDataStruct.CountNodes(); | |
277 | semaphore_put(_XactorCtrl.ExpectDataStructSemaphore, 1); | |
278 | ||
279 | // Then count the expects pending in the expect data structure with "wildcards" | |
280 | semaphore_get(WAIT, _XactorCtrl.XExpectDataStructSemaphore, 1); | |
281 | Expects += XExpectDataStruct.CountNodes(); | |
282 | semaphore_put(_XactorCtrl.XExpectDataStructSemaphore, 1); | |
283 | ||
284 | NumExpects = Expects; | |
285 | } | |
286 | ||
287 | // Removes Packet from ExpectDataStruct. Success is 1 if | |
288 | // Packet is removed without problems and 0 otherwise | |
289 | task XactorManager::RemoveExpect(XactorBasePacket Packet, | |
290 | var bit Success | |
291 | ) { | |
292 | ||
293 | semaphore_get(WAIT, _XactorCtrl.ExpectDataStructSemaphore, 1); | |
294 | if((!(ExpectDataStruct.Empty())) && (!(Packet.PktUndef()))) { | |
295 | ExpectDataStruct.Delete(Packet, | |
296 | Success | |
297 | ); | |
298 | } | |
299 | else | |
300 | Success = 1'b0; | |
301 | semaphore_put(_XactorCtrl.ExpectDataStructSemaphore, 1); | |
302 | ||
303 | if (Success) { | |
304 | Packet.PktDisplay(RTYP_DEBUG_2, "Sampled Transaction with match in ExpectDataSTtructure"); | |
305 | } | |
306 | else { | |
307 | Packet.PktDisplay(RTYP_DEBUG_2, "Sampled Transaction without match in ExpectDataStructure"); | |
308 | } | |
309 | } | |
310 | ||
311 | // Same as RemoveExpect, but it will remove Packet from the XExpectDataStruct | |
312 | task XactorManager::RemoveXExpect(XactorBasePacket Packet, | |
313 | var bit Success | |
314 | ) { | |
315 | ||
316 | semaphore_get(WAIT, _XactorCtrl.XExpectDataStructSemaphore, 1); | |
317 | if(!(XExpectDataStruct.Empty())) { | |
318 | XExpectDataStruct.WildCardDelete1(Packet, | |
319 | Success | |
320 | ); | |
321 | } | |
322 | else | |
323 | Success = 1'b0; | |
324 | semaphore_put(_XactorCtrl.XExpectDataStructSemaphore, 1); | |
325 | ||
326 | if (Success) { | |
327 | Packet.PktDisplay(RTYP_DEBUG_2, "Sampled Transaction with match in XExpectDataStructure"); | |
328 | } | |
329 | else { | |
330 | Packet.PktDisplay(RTYP_DEBUG_2, "Sampled Transaction without match in XExpectDataStructure"); | |
331 | } | |
332 | } | |
333 | ||
334 | // Same as RemoveExpect, but it will remove Packet from the XExpectDataStruct | |
335 | // Compared to RemoveXExpect, this task will call WildCardDelete1 | |
336 | task XactorManager::RemoveRefExpect(XactorBasePacket Packet, | |
337 | var bit Success | |
338 | ) { | |
339 | ||
340 | semaphore_get(WAIT, _XactorCtrl.ExpectDataStructSemaphore, 1); | |
341 | if((!(ExpectDataStruct.Empty())) && (!Packet.PktUndef())) { | |
342 | ExpectDataStruct.RefDelete(Packet, | |
343 | Success | |
344 | ); | |
345 | } | |
346 | else | |
347 | Success = 1'b0; | |
348 | semaphore_put(_XactorCtrl.ExpectDataStructSemaphore, 1); | |
349 | ||
350 | if (Success) { | |
351 | Packet.PktDisplay(RTYP_DEBUG_2, "%0s: Removing expect from Expect Data Structure"); | |
352 | } | |
353 | else { | |
354 | Packet.PktDisplay(RTYP_DEBUG_2, "%0s: Removing expect from Expect Data Structure"); | |
355 | } | |
356 | } | |
357 | ||
358 | // Same as RemoveExpect, but it will remove Packet from the XExpectDataStruct | |
359 | // Compared to RemoveXExpect, this task will call WildCardDelete1 | |
360 | task XactorManager::RemoveRefXExpect(XactorBasePacket Packet, | |
361 | var bit Success | |
362 | ) { | |
363 | ||
364 | semaphore_get(WAIT, _XactorCtrl.XExpectDataStructSemaphore, 1); | |
365 | if((!(XExpectDataStruct.Empty())) && (Packet.PktUndef())) { | |
366 | XExpectDataStruct.RefDelete(Packet, | |
367 | Success | |
368 | ); | |
369 | } | |
370 | else | |
371 | Success = 1'b0; | |
372 | semaphore_put(_XactorCtrl.XExpectDataStructSemaphore, 1); | |
373 | ||
374 | if (Success) { | |
375 | Packet.PktDisplay(RTYP_DEBUG_2, "%0s: Removing expect from XExpect Data Structure"); | |
376 | } | |
377 | else { | |
378 | Packet.PktDisplay(RTYP_DEBUG_2, "%0s: Removing expect from XExpect Data Structure"); | |
379 | } | |
380 | } | |
381 | ||
382 | // This task will wait for a maximum of Window cycles for the ExpectedPkt to be removed from | |
383 | // the expect data structures. Removed is an event variable that is triggered when ExpectedPkt is | |
384 | // removed. TransactionRemoved will be 1 if ExpectedPkt was removed and 0 otherwise. Id is the | |
385 | // id number of the expect transaction. | |
386 | task XactorManager::ExpectPkt(XactorBasePacket ExpectedPkt, | |
387 | integer Window, | |
388 | var bit [1:0] Status | |
389 | ) { | |
390 | // Success flags when an expect transaction is removed from a data | |
391 | // structure. | |
392 | bit SuccessWildcard = 1'b0; | |
393 | bit Success = 1'b0; | |
394 | // Events used when an expect is removed | |
395 | event RemoveEvents[XACT_EXPECT_DATA_STRUCT_REMOVE_EVENTS]; | |
396 | ||
397 | Status = 2'b00; // Status[1] = 1'b0 Expect not removed | |
398 | // Status[1] = 1'b1 Expect removed | |
399 | // Status[0] = 1'b0 Expect removed by transactor | |
400 | // Status[0] = 1'b1 Expect removed by user | |
401 | ||
402 | // Check if the Expected value has "wildcards" or if it only has | |
403 | // valid bits (0's and 1's) and store in the corresponding expect | |
404 | // data structure. | |
405 | if(ExpectedPkt.PktUndef()) { | |
406 | semaphore_get(WAIT, _XactorCtrl.XExpectDataStructSemaphore, 1); | |
407 | XExpectDataStruct.Insert(ExpectedPkt, RemoveEvents); | |
408 | semaphore_put(_XactorCtrl.XExpectDataStructSemaphore, 1); | |
409 | } | |
410 | else { | |
411 | semaphore_get(WAIT, _XactorCtrl.ExpectDataStructSemaphore, 1); | |
412 | ExpectDataStruct.Insert(ExpectedPkt, RemoveEvents); | |
413 | semaphore_put(_XactorCtrl.ExpectDataStructSemaphore, 1); | |
414 | } | |
415 | ||
416 | // Synchronize the waiting cycle to the negative edge of the clock | |
417 | // Two negedges have to pass to start the while loop. This restricts | |
418 | // the minimum value of the expect Window to 1 cycle. A Window with | |
419 | // a value of 0 is not possible since race conditions would make | |
420 | // the code execution unpredictable. | |
421 | repeat(2) | |
422 | @(negedge ClkPort.$XClk); | |
423 | ||
424 | // Wait until the expect is satisfied or it times out. | |
425 | while (!Status[1] && Window) { | |
426 | if(_XactorCtrl.GetDisableFlag() === 1'b1) | |
427 | sync(ANY, _XactorCtrl.GetEnableEvent()); | |
428 | if (sync(CHECK, RemoveEvents[XACT_COMP_EXPECT_REMOVED_EVENT])) { | |
429 | Status[1] = 1'b1; | |
430 | } | |
431 | ||
432 | Window--; | |
433 | if(!Status[1]) | |
434 | @(negedge ClkPort.$XClk); | |
435 | } | |
436 | ||
437 | // If the pending expect transaction was not removed and it has already | |
438 | // timed out, then there is no need for it to stay in any of the expect | |
439 | // data structures. | |
440 | if(Status[1] !== 1'b1) { | |
441 | fork { | |
442 | // Check if the Expected value has "wildcards". If it does, do not | |
443 | // try to delete from this data structure | |
444 | RemoveRefExpect(ExpectedPkt, Success); | |
445 | } | |
446 | { | |
447 | // Check if the Expected value has "wildcards". If it does, try to | |
448 | // delete from this data structure | |
449 | RemoveRefXExpect(ExpectedPkt, SuccessWildcard); | |
450 | } | |
451 | join all | |
452 | ||
453 | Status[0] = 1'b0; // Expect timedout and is removed by transactor | |
454 | } | |
455 | else { | |
456 | // Copy all the fields for the sampled transaction, if "wildcards' are used | |
457 | // NOTE: this is done within the data structures. Look for WildCardDelete1() method. | |
458 | // if(ExpectedPkt.PktUndef()) { | |
459 | // ExpectedPkt.PktCopy(SampledPkt); | |
460 | // } | |
461 | ||
462 | // Check who removed the expect, the transactor through the ExpectConsumer() or | |
463 | // the user through Remove() or Reset(). If both tried to remove the expect, give | |
464 | // priority to the transactor. | |
465 | if (sync(CHECK, RemoveEvents[XACT_COMP_EXPECT_REMOVED_BY_XACTOR_EVENT])) { | |
466 | Status[0] = 1'b0; | |
467 | } | |
468 | else if (sync(CHECK, RemoveEvents[XACT_COMP_EXPECT_REMOVED_BY_USER_EVENT])) { | |
469 | Status[0] = 1'b1; | |
470 | } | |
471 | } | |
472 | } | |
473 | ||
474 | // This task will wait for the next transaction driven by the DUT, it will then sample it and | |
475 | // will return the values through Pkt | |
476 | // The transactor timesout when the DUT hasn't driven any transaction in "Window" cycles. | |
477 | task XactorManager::SamplePkt(XactorBasePacket Pkt, | |
478 | integer Window | |
479 | ) { | |
480 | ||
481 | // This is a flag that is set when a new transaction is sampled | |
482 | bit Success = 0; | |
483 | ||
484 | fork { | |
485 | sync(ANY, NewTransaction); | |
486 | Pkt.PktCopy(SampledPkt); | |
487 | Success = 1'b1; | |
488 | } | |
489 | { | |
490 | while(Window && !Success) { | |
491 | Window--; | |
492 | @(negedge ClkPort.$XClk); | |
493 | } | |
494 | if(!Success) { | |
495 | MyReport.report(RTYP_XACTOR_FMWORK_SAMPLE_TIMEOUT_ERR, | |
496 | "%0s: Timeout waiting for the next transaction from the DUT", | |
497 | XactorName); | |
498 | } | |
499 | else | |
500 | Pkt.PktDisplay(RTYP_INFO, "Transaction Sampled"); | |
501 | } | |
502 | join any | |
503 | } | |
504 | ||
505 | // This task will be waiting for transactions coming from the DUT | |
506 | // and match them with the pending list of expects (stored in the data structures) | |
507 | task XactorManager::ExpectConsumer() { | |
508 | ||
509 | // This is not really used, just to receive the returned value of | |
510 | // mailbox_get | |
511 | integer MailVar; | |
512 | // Success flags when an expect transaction is removed from a data | |
513 | // structure. | |
514 | bit SuccessWildcard; | |
515 | bit Success; | |
516 | ||
517 | // Main Expect Consumer loop | |
518 | while(1) { | |
519 | ||
520 | // Wait for another transaction coming from the Signal Interface | |
521 | MailVar = mailbox_get(WAIT, ExpectFifo, SampledPkt); | |
522 | ||
523 | // Check if sampled packet has undefined values | |
524 | if(SampledPkt.PktUndef()) { | |
525 | SampledPkt.PktDisplay(RTYP_XACTOR_FMWORK_SAMPLED_X_ERR, | |
526 | "X values detected in transaction driven by DUT"); | |
527 | } | |
528 | ||
529 | // Stop the Expect Consumer if the transactor was disabled | |
530 | if(_XactorCtrl.GetDisableFlag()) | |
531 | sync(ANY, _XactorCtrl.GetEnableEvent()); | |
532 | ||
533 | // Trigger the event for a new transaction | |
534 | trigger(ONE_BLAST, NewTransaction); | |
535 | ||
536 | Success = 1'b0; | |
537 | SuccessWildcard = 1'b0; | |
538 | fork { | |
539 | RemoveExpect(SampledPkt, Success); | |
540 | } | |
541 | { | |
542 | RemoveXExpect(SampledPkt, SuccessWildcard); | |
543 | } | |
544 | join all | |
545 | ||
546 | if(SuccessWildcard || Success) { | |
547 | SampledPkt.PktDisplay(RTYP_DEBUG_1, "Expect Consumer: Match found, pending Expect removed"); | |
548 | } | |
549 | else { | |
550 | MyReport.report(RTYP_INFO, "%0s: Dumping Expects since an unexpected transaction was sampled", XactorName); | |
551 | DumpExpects(); | |
552 | SampledPkt.PktDisplay(RTYP_XACTOR_FMWORK_UNEXPECTED_XACTION_ERR, "Expect Consumer: Sampled unexpected transaction"); | |
553 | } | |
554 | } | |
555 | } | |
556 | ||
557 | // This task will receive DrivenPkt and will wait D clock cycles before DrivenPkt is | |
558 | // scheduled for driving | |
559 | task XactorManager::DrivePkt(XactorBasePacket DrivenPkt, integer D) { | |
560 | // Wait D cycles before DrivenPkt is scheduled for driving | |
561 | repeat(D) @(posedge ClkPort.$XClk); | |
562 | // Wait if transactor was disabled | |
563 | if(_XactorCtrl.GetDisableFlag() === 1'b1) | |
564 | sync(ANY, _XactorCtrl.GetEnableEvent()); | |
565 | // Send DrivenPkt to the Signal Interface | |
566 | mailbox_put(DriveFifo, DrivenPkt); | |
567 | // Wait until the packet is driven | |
568 | DrivenPkt.SyncOnDrive(); | |
569 | DrivenPkt.PktDisplay(RTYP_DEBUG_1, "Driving Transaction"); | |
570 | } | |
571 | ||
572 | // This task will disable the transactor | |
573 | task XactorManager::DisableManager() { | |
574 | _XactorCtrl.SetDisableFlag(1'b1); | |
575 | } | |
576 | ||
577 | // This task will enable the transactor | |
578 | task XactorManager::EnableManager() { | |
579 | _XactorCtrl.SetDisableFlag(1'b0); | |
580 | trigger(ONE_BLAST, _XactorCtrl.GetEnableEvent()); | |
581 | } | |
582 | ||
583 | // This task will flush the Drive Fifo | |
584 | task XactorManager::FlushDriveFifo() { | |
585 | integer FifoCount; | |
586 | XactorBasePacket JunkPacket; | |
587 | ||
588 | FifoCount = mailbox_get(NO_WAIT, DriveFifo); | |
589 | while(FifoCount > 0) { | |
590 | FifoCount = mailbox_get(NO_WAIT, DriveFifo, JunkPacket); | |
591 | } | |
592 | } | |
593 | ||
594 | // This task will reset the transactor | |
595 | task XactorManager::ResetManager() { | |
596 | // Reset the two data structures and flush the Drive Fifo | |
597 | fork { | |
598 | semaphore_get(WAIT, _XactorCtrl.ExpectDataStructSemaphore, 1); | |
599 | ExpectDataStruct.Reset(); | |
600 | semaphore_put(_XactorCtrl.ExpectDataStructSemaphore, 1); | |
601 | } | |
602 | { | |
603 | semaphore_get(WAIT, _XactorCtrl.XExpectDataStructSemaphore, 1); | |
604 | XExpectDataStruct.Reset(); | |
605 | semaphore_put(_XactorCtrl.XExpectDataStructSemaphore, 1); | |
606 | } | |
607 | { | |
608 | semaphore_get(WAIT, _XactorCtrl.DriveFifoSemaphore, 1); | |
609 | FlushDriveFifo(); | |
610 | semaphore_put(_XactorCtrl.DriveFifoSemaphore, 1); | |
611 | } | |
612 | join none | |
613 | } | |
614 | ||
615 |