gpu-compute: AMD's baseline GPU model
[gem5.git] / src / mem / protocol / GPU_VIPER-TCC.sm
1 /*
2 * Copyright (c) 2010-2015 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * For use for simulation and test purposes only
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Author: Blake Hechtman
34 */
35
36 machine(MachineType:TCC, "TCC Cache")
37 : CacheMemory * L2cache;
38 bool WB; /*is this cache Writeback?*/
39 Cycles l2_request_latency := 50;
40 Cycles l2_response_latency := 20;
41
42 // From the TCPs or SQCs
43 MessageBuffer * requestFromTCP, network="From", virtual_network="1", vnet_type="request";
44 // To the Cores. TCC deals only with TCPs/SQCs.
45 MessageBuffer * responseToCore, network="To", virtual_network="3", vnet_type="response";
46 // From the NB
47 MessageBuffer * probeFromNB, network="From", virtual_network="0", vnet_type="request";
48 MessageBuffer * responseFromNB, network="From", virtual_network="2", vnet_type="response";
49 // To the NB
50 MessageBuffer * requestToNB, network="To", virtual_network="0", vnet_type="request";
51 MessageBuffer * responseToNB, network="To", virtual_network="2", vnet_type="response";
52 MessageBuffer * unblockToNB, network="To", virtual_network="4", vnet_type="unblock";
53
54 MessageBuffer * triggerQueue;
55
56 {
57 // EVENTS
58 enumeration(Event, desc="TCC Events") {
59 // Requests coming from the Cores
60 RdBlk, desc="RdBlk event";
61 WrVicBlk, desc="L1 Write Through";
62 WrVicBlkBack, desc="L1 Write Through(dirty cache)";
63 Atomic, desc="Atomic Op";
64 AtomicDone, desc="AtomicOps Complete";
65 AtomicNotDone, desc="AtomicOps not Complete";
66 Data, desc="data messgae";
67 // Coming from this TCC
68 L2_Repl, desc="L2 Replacement";
69 // Probes
70 PrbInv, desc="Invalidating probe";
71 // Coming from Memory Controller
72 WBAck, desc="writethrough ack from memory";
73 }
74
75 // STATES
76 state_declaration(State, desc="TCC State", default="TCC_State_I") {
77 M, AccessPermission:Read_Write, desc="Modified(dirty cache only)";
78 W, AccessPermission:Read_Write, desc="Written(dirty cache only)";
79 V, AccessPermission:Read_Only, desc="Valid";
80 I, AccessPermission:Invalid, desc="Invalid";
81 IV, AccessPermission:Busy, desc="Waiting for Data";
82 WI, AccessPermission:Busy, desc="Waiting on Writethrough Ack";
83 A, AccessPermission:Busy, desc="Invalid waiting on atomici Data";
84 }
85
86 enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
87 DataArrayRead, desc="Read the data array";
88 DataArrayWrite, desc="Write the data array";
89 TagArrayRead, desc="Read the data array";
90 TagArrayWrite, desc="Write the data array";
91 }
92
93
94 // STRUCTURES
95
96 structure(Entry, desc="...", interface="AbstractCacheEntry") {
97 State CacheState, desc="cache state";
98 bool Dirty, desc="Is the data dirty (diff from memory?)";
99 DataBlock DataBlk, desc="Data for the block";
100 WriteMask writeMask, desc="Dirty byte mask";
101 }
102
103 structure(TBE, desc="...") {
104 State TBEState, desc="Transient state";
105 DataBlock DataBlk, desc="data for the block";
106 bool Dirty, desc="Is the data dirty?";
107 bool Shared, desc="Victim hit by shared probe";
108 MachineID From, desc="Waiting for writeback from...";
109 NetDest Destination, desc="Data destination";
110 int numAtomics, desc="number remaining atomics";
111 }
112
113 structure(TBETable, external="yes") {
114 TBE lookup(Addr);
115 void allocate(Addr);
116 void deallocate(Addr);
117 bool isPresent(Addr);
118 }
119
120 TBETable TBEs, template="<TCC_TBE>", constructor="m_number_of_TBEs";
121
122 void set_cache_entry(AbstractCacheEntry b);
123 void unset_cache_entry();
124 void set_tbe(TBE b);
125 void unset_tbe();
126 void wakeUpAllBuffers();
127 void wakeUpBuffers(Addr a);
128
129
130 // FUNCTION DEFINITIONS
131 Tick clockEdge();
132
133 Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
134 return static_cast(Entry, "pointer", L2cache.lookup(addr));
135 }
136
137 DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
138 return getCacheEntry(addr).DataBlk;
139 }
140
141 bool presentOrAvail(Addr addr) {
142 return L2cache.isTagPresent(addr) || L2cache.cacheAvail(addr);
143 }
144
145 State getState(TBE tbe, Entry cache_entry, Addr addr) {
146 if (is_valid(tbe)) {
147 return tbe.TBEState;
148 } else if (is_valid(cache_entry)) {
149 return cache_entry.CacheState;
150 }
151 return State:I;
152 }
153
154 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
155 if (is_valid(tbe)) {
156 tbe.TBEState := state;
157 }
158
159 if (is_valid(cache_entry)) {
160 cache_entry.CacheState := state;
161 }
162 }
163
164 void functionalRead(Addr addr, Packet *pkt) {
165 TBE tbe := TBEs.lookup(addr);
166 if(is_valid(tbe)) {
167 testAndRead(addr, tbe.DataBlk, pkt);
168 } else {
169 functionalMemoryRead(pkt);
170 }
171 }
172
173 int functionalWrite(Addr addr, Packet *pkt) {
174 int num_functional_writes := 0;
175
176 TBE tbe := TBEs.lookup(addr);
177 if(is_valid(tbe)) {
178 num_functional_writes := num_functional_writes +
179 testAndWrite(addr, tbe.DataBlk, pkt);
180 }
181
182 num_functional_writes := num_functional_writes +
183 functionalMemoryWrite(pkt);
184 return num_functional_writes;
185 }
186
187 AccessPermission getAccessPermission(Addr addr) {
188 TBE tbe := TBEs.lookup(addr);
189 if(is_valid(tbe)) {
190 return TCC_State_to_permission(tbe.TBEState);
191 }
192
193 Entry cache_entry := getCacheEntry(addr);
194 if(is_valid(cache_entry)) {
195 return TCC_State_to_permission(cache_entry.CacheState);
196 }
197
198 return AccessPermission:NotPresent;
199 }
200
201 void setAccessPermission(Entry cache_entry, Addr addr, State state) {
202 if (is_valid(cache_entry)) {
203 cache_entry.changePermission(TCC_State_to_permission(state));
204 }
205 }
206
207 void recordRequestType(RequestType request_type, Addr addr) {
208 if (request_type == RequestType:DataArrayRead) {
209 L2cache.recordRequestType(CacheRequestType:DataArrayRead, addr);
210 } else if (request_type == RequestType:DataArrayWrite) {
211 L2cache.recordRequestType(CacheRequestType:DataArrayWrite, addr);
212 } else if (request_type == RequestType:TagArrayRead) {
213 L2cache.recordRequestType(CacheRequestType:TagArrayRead, addr);
214 } else if (request_type == RequestType:TagArrayWrite) {
215 L2cache.recordRequestType(CacheRequestType:TagArrayWrite, addr);
216 }
217 }
218
219 bool checkResourceAvailable(RequestType request_type, Addr addr) {
220 if (request_type == RequestType:DataArrayRead) {
221 return L2cache.checkResourceAvailable(CacheResourceType:DataArray, addr);
222 } else if (request_type == RequestType:DataArrayWrite) {
223 return L2cache.checkResourceAvailable(CacheResourceType:DataArray, addr);
224 } else if (request_type == RequestType:TagArrayRead) {
225 return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr);
226 } else if (request_type == RequestType:TagArrayWrite) {
227 return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr);
228 } else {
229 error("Invalid RequestType type in checkResourceAvailable");
230 return true;
231 }
232 }
233
234
235 // ** OUT_PORTS **
236
237 // Three classes of ports
238 // Class 1: downward facing network links to NB
239 out_port(requestToNB_out, CPURequestMsg, requestToNB);
240 out_port(responseToNB_out, ResponseMsg, responseToNB);
241 out_port(unblockToNB_out, UnblockMsg, unblockToNB);
242
243 // Class 2: upward facing ports to GPU cores
244 out_port(responseToCore_out, ResponseMsg, responseToCore);
245
246 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
247 //
248 // request queue going to NB
249 //
250
251
252 // ** IN_PORTS **
253 in_port(triggerQueue_in, TiggerMsg, triggerQueue) {
254 if (triggerQueue_in.isReady(clockEdge())) {
255 peek(triggerQueue_in, TriggerMsg) {
256 TBE tbe := TBEs.lookup(in_msg.addr);
257 Entry cache_entry := getCacheEntry(in_msg.addr);
258 if (tbe.numAtomics == 0) {
259 trigger(Event:AtomicDone, in_msg.addr, cache_entry, tbe);
260 } else {
261 trigger(Event:AtomicNotDone, in_msg.addr, cache_entry, tbe);
262 }
263 }
264 }
265 }
266
267
268
269 in_port(responseFromNB_in, ResponseMsg, responseFromNB) {
270 if (responseFromNB_in.isReady(clockEdge())) {
271 peek(responseFromNB_in, ResponseMsg, block_on="addr") {
272 TBE tbe := TBEs.lookup(in_msg.addr);
273 Entry cache_entry := getCacheEntry(in_msg.addr);
274 if (in_msg.Type == CoherenceResponseType:NBSysResp) {
275 if(presentOrAvail(in_msg.addr)) {
276 trigger(Event:Data, in_msg.addr, cache_entry, tbe);
277 } else {
278 Addr victim := L2cache.cacheProbe(in_msg.addr);
279 trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
280 }
281 } else if (in_msg.Type == CoherenceResponseType:NBSysWBAck) {
282 trigger(Event:WBAck, in_msg.addr, cache_entry, tbe);
283 } else {
284 error("Unexpected Response Message to Core");
285 }
286 }
287 }
288 }
289
290 // Finally handling incoming requests (from TCP) and probes (from NB).
291 in_port(probeNetwork_in, NBProbeRequestMsg, probeFromNB) {
292 if (probeNetwork_in.isReady(clockEdge())) {
293 peek(probeNetwork_in, NBProbeRequestMsg) {
294 DPRINTF(RubySlicc, "%s\n", in_msg);
295 Entry cache_entry := getCacheEntry(in_msg.addr);
296 TBE tbe := TBEs.lookup(in_msg.addr);
297 trigger(Event:PrbInv, in_msg.addr, cache_entry, tbe);
298 }
299 }
300 }
301
302 in_port(coreRequestNetwork_in, CPURequestMsg, requestFromTCP, rank=0) {
303 if (coreRequestNetwork_in.isReady(clockEdge())) {
304 peek(coreRequestNetwork_in, CPURequestMsg) {
305 TBE tbe := TBEs.lookup(in_msg.addr);
306 Entry cache_entry := getCacheEntry(in_msg.addr);
307 if (in_msg.Type == CoherenceRequestType:WriteThrough) {
308 if(WB) {
309 if(presentOrAvail(in_msg.addr)) {
310 trigger(Event:WrVicBlkBack, in_msg.addr, cache_entry, tbe);
311 } else {
312 Addr victim := L2cache.cacheProbe(in_msg.addr);
313 trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
314 }
315 } else {
316 trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe);
317 }
318 } else if (in_msg.Type == CoherenceRequestType:Atomic) {
319 trigger(Event:Atomic, in_msg.addr, cache_entry, tbe);
320 } else if (in_msg.Type == CoherenceRequestType:RdBlk) {
321 trigger(Event:RdBlk, in_msg.addr, cache_entry, tbe);
322 } else {
323 DPRINTF(RubySlicc, "%s\n", in_msg);
324 error("Unexpected Response Message to Core");
325 }
326 }
327 }
328 }
329 // BEGIN ACTIONS
330
331 action(i_invL2, "i", desc="invalidate TCC cache block") {
332 if (is_valid(cache_entry)) {
333 L2cache.deallocate(address);
334 }
335 unset_cache_entry();
336 }
337
338 action(sd_sendData, "sd", desc="send Shared response") {
339 peek(coreRequestNetwork_in, CPURequestMsg) {
340 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) {
341 out_msg.addr := address;
342 out_msg.Type := CoherenceResponseType:TDSysResp;
343 out_msg.Sender := machineID;
344 out_msg.Destination.add(in_msg.Requestor);
345 out_msg.DataBlk := cache_entry.DataBlk;
346 out_msg.MessageSize := MessageSizeType:Response_Data;
347 out_msg.Dirty := false;
348 out_msg.State := CoherenceState:Shared;
349 DPRINTF(RubySlicc, "%s\n", out_msg);
350 }
351 }
352 }
353
354
355 action(sdr_sendDataResponse, "sdr", desc="send Shared response") {
356 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) {
357 out_msg.addr := address;
358 out_msg.Type := CoherenceResponseType:TDSysResp;
359 out_msg.Sender := machineID;
360 out_msg.Destination := tbe.Destination;
361 out_msg.DataBlk := cache_entry.DataBlk;
362 out_msg.MessageSize := MessageSizeType:Response_Data;
363 out_msg.Dirty := false;
364 out_msg.State := CoherenceState:Shared;
365 DPRINTF(RubySlicc, "%s\n", out_msg);
366 }
367 enqueue(unblockToNB_out, UnblockMsg, 1) {
368 out_msg.addr := address;
369 out_msg.Destination.add(map_Address_to_Directory(address));
370 out_msg.MessageSize := MessageSizeType:Unblock_Control;
371 DPRINTF(RubySlicc, "%s\n", out_msg);
372 }
373 }
374
375
376 action(rd_requestData, "r", desc="Miss in L2, pass on") {
377 if(tbe.Destination.count()==1){
378 peek(coreRequestNetwork_in, CPURequestMsg) {
379 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) {
380 out_msg.addr := address;
381 out_msg.Type := in_msg.Type;
382 out_msg.Requestor := machineID;
383 out_msg.Destination.add(map_Address_to_Directory(address));
384 out_msg.Shared := false; // unneeded for this request
385 out_msg.MessageSize := in_msg.MessageSize;
386 DPRINTF(RubySlicc, "%s\n", out_msg);
387 }
388 }
389 }
390 }
391
392 action(w_sendResponseWBAck, "w", desc="send WB Ack") {
393 peek(responseFromNB_in, ResponseMsg) {
394 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) {
395 out_msg.addr := address;
396 out_msg.Type := CoherenceResponseType:TDSysWBAck;
397 out_msg.Destination.clear();
398 out_msg.Destination.add(in_msg.WTRequestor);
399 out_msg.Sender := machineID;
400 out_msg.MessageSize := MessageSizeType:Writeback_Control;
401 }
402 }
403 }
404
405 action(swb_sendWBAck, "swb", desc="send WB Ack") {
406 peek(coreRequestNetwork_in, CPURequestMsg) {
407 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) {
408 out_msg.addr := address;
409 out_msg.Type := CoherenceResponseType:TDSysWBAck;
410 out_msg.Destination.clear();
411 out_msg.Destination.add(in_msg.Requestor);
412 out_msg.Sender := machineID;
413 out_msg.MessageSize := MessageSizeType:Writeback_Control;
414 }
415 }
416 }
417
418 action(ar_sendAtomicResponse, "ar", desc="send Atomic Ack") {
419 peek(responseFromNB_in, ResponseMsg) {
420 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) {
421 out_msg.addr := address;
422 out_msg.Type := CoherenceResponseType:TDSysResp;
423 out_msg.Destination.add(in_msg.WTRequestor);
424 out_msg.Sender := machineID;
425 out_msg.MessageSize := in_msg.MessageSize;
426 out_msg.DataBlk := in_msg.DataBlk;
427 }
428 }
429 }
430
431 action(a_allocateBlock, "a", desc="allocate TCC block") {
432 if (is_invalid(cache_entry)) {
433 set_cache_entry(L2cache.allocate(address, new Entry));
434 cache_entry.writeMask.clear();
435 }
436 }
437
438 action(t_allocateTBE, "t", desc="allocate TBE Entry") {
439 if (is_invalid(tbe)) {
440 check_allocate(TBEs);
441 TBEs.allocate(address);
442 set_tbe(TBEs.lookup(address));
443 tbe.Destination.clear();
444 tbe.numAtomics := 0;
445 }
446 if (coreRequestNetwork_in.isReady(clockEdge())) {
447 peek(coreRequestNetwork_in, CPURequestMsg) {
448 if(in_msg.Type == CoherenceRequestType:RdBlk || in_msg.Type == CoherenceRequestType:Atomic){
449 tbe.Destination.add(in_msg.Requestor);
450 }
451 }
452 }
453 }
454
455 action(dt_deallocateTBE, "dt", desc="Deallocate TBE entry") {
456 tbe.Destination.clear();
457 TBEs.deallocate(address);
458 unset_tbe();
459 }
460
461 action(wcb_writeCacheBlock, "wcb", desc="write data to TCC") {
462 peek(responseFromNB_in, ResponseMsg) {
463 cache_entry.DataBlk := in_msg.DataBlk;
464 DPRINTF(RubySlicc, "Writing to TCC: %s\n", in_msg);
465 }
466 }
467
468 action(wdb_writeDirtyBytes, "wdb", desc="write data to TCC") {
469 peek(coreRequestNetwork_in, CPURequestMsg) {
470 cache_entry.DataBlk.copyPartial(in_msg.DataBlk,in_msg.writeMask);
471 cache_entry.writeMask.orMask(in_msg.writeMask);
472 DPRINTF(RubySlicc, "Writing to TCC: %s\n", in_msg);
473 }
474 }
475
476 action(wt_writeThrough, "wt", desc="write back data") {
477 peek(coreRequestNetwork_in, CPURequestMsg) {
478 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) {
479 out_msg.addr := address;
480 out_msg.Requestor := machineID;
481 out_msg.WTRequestor := in_msg.Requestor;
482 out_msg.Destination.add(map_Address_to_Directory(address));
483 out_msg.MessageSize := MessageSizeType:Data;
484 out_msg.Type := CoherenceRequestType:WriteThrough;
485 out_msg.Dirty := true;
486 out_msg.DataBlk := in_msg.DataBlk;
487 out_msg.writeMask.orMask(in_msg.writeMask);
488 }
489 }
490 }
491
492 action(wb_writeBack, "wb", desc="write back data") {
493 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) {
494 out_msg.addr := address;
495 out_msg.Requestor := machineID;
496 out_msg.WTRequestor := machineID;
497 out_msg.Destination.add(map_Address_to_Directory(address));
498 out_msg.MessageSize := MessageSizeType:Data;
499 out_msg.Type := CoherenceRequestType:WriteThrough;
500 out_msg.Dirty := true;
501 out_msg.DataBlk := cache_entry.DataBlk;
502 out_msg.writeMask.orMask(cache_entry.writeMask);
503 }
504 }
505
506 action(at_atomicThrough, "at", desc="write back data") {
507 peek(coreRequestNetwork_in, CPURequestMsg) {
508 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) {
509 out_msg.addr := address;
510 out_msg.Requestor := machineID;
511 out_msg.WTRequestor := in_msg.Requestor;
512 out_msg.Destination.add(map_Address_to_Directory(address));
513 out_msg.MessageSize := MessageSizeType:Data;
514 out_msg.Type := CoherenceRequestType:Atomic;
515 out_msg.Dirty := true;
516 out_msg.writeMask.orMask(in_msg.writeMask);
517 }
518 }
519 }
520
521 action(pi_sendProbeResponseInv, "pi", desc="send probe ack inv, no data") {
522 enqueue(responseToNB_out, ResponseMsg, 1) {
523 out_msg.addr := address;
524 out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC, L3 respond in same way to probes
525 out_msg.Sender := machineID;
526 out_msg.Destination.add(map_Address_to_Directory(address));
527 out_msg.Dirty := false;
528 out_msg.Hit := false;
529 out_msg.Ntsl := true;
530 out_msg.State := CoherenceState:NA;
531 out_msg.MessageSize := MessageSizeType:Response_Control;
532 }
533 }
534 action(ut_updateTag, "ut", desc="update Tag (i.e. set MRU)") {
535 L2cache.setMRU(address);
536 }
537
538 action(p_popRequestQueue, "p", desc="pop request queue") {
539 coreRequestNetwork_in.dequeue(clockEdge());
540 }
541
542 action(pr_popResponseQueue, "pr", desc="pop response queue") {
543 responseFromNB_in.dequeue(clockEdge());
544 }
545
546 action(pp_popProbeQueue, "pp", desc="pop probe queue") {
547 probeNetwork_in.dequeue(clockEdge());
548 }
549
550 action(z_stall, "z", desc="stall") {
551 // built-in
552 }
553
554
555 action(ina_incrementNumAtomics, "ina", desc="inc num atomics") {
556 tbe.numAtomics := tbe.numAtomics + 1;
557 }
558
559
560 action(dna_decrementNumAtomics, "dna", desc="inc num atomics") {
561 tbe.numAtomics := tbe.numAtomics - 1;
562 if (tbe.numAtomics==0) {
563 enqueue(triggerQueue_out, TriggerMsg, 1) {
564 out_msg.addr := address;
565 out_msg.Type := TriggerType:AtomicDone;
566 }
567 }
568 }
569
570 action(ptr_popTriggerQueue, "ptr", desc="pop Trigger") {
571 triggerQueue_in.dequeue(clockEdge());
572 }
573
574 // END ACTIONS
575
576 // BEGIN TRANSITIONS
577 // transitions from base
578 // Assumptions for ArrayRead/Write
579 // TBE checked before tags
580 // Data Read/Write requires Tag Read
581
582 // Stalling transitions do NOT check the tag array...and if they do,
583 // they can cause a resource stall deadlock!
584
585 transition(WI, {RdBlk, WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} {
586 z_stall;
587 }
588 transition(A, {RdBlk, WrVicBlk, WrVicBlkBack}) { //TagArrayRead} {
589 z_stall;
590 }
591 transition(IV, {WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} {
592 z_stall;
593 }
594 transition({M, V}, RdBlk) {TagArrayRead, DataArrayRead} {
595 sd_sendData;
596 ut_updateTag;
597 p_popRequestQueue;
598 }
599 transition(W, RdBlk, WI) {TagArrayRead, DataArrayRead} {
600 t_allocateTBE;
601 wb_writeBack;
602 }
603
604 transition(I, RdBlk, IV) {TagArrayRead} {
605 t_allocateTBE;
606 rd_requestData;
607 p_popRequestQueue;
608 }
609
610 transition(IV, RdBlk) {
611 t_allocateTBE;
612 rd_requestData;
613 p_popRequestQueue;
614 }
615
616 transition({V, I},Atomic, A) {TagArrayRead} {
617 i_invL2;
618 t_allocateTBE;
619 at_atomicThrough;
620 ina_incrementNumAtomics;
621 p_popRequestQueue;
622 }
623
624 transition(A, Atomic) {
625 at_atomicThrough;
626 ina_incrementNumAtomics;
627 p_popRequestQueue;
628 }
629
630 transition({M, W}, Atomic, WI) {TagArrayRead} {
631 t_allocateTBE;
632 wb_writeBack;
633 }
634
635 transition(I, WrVicBlk) {TagArrayRead} {
636 wt_writeThrough;
637 p_popRequestQueue;
638 }
639
640 transition(V, WrVicBlk) {TagArrayRead, DataArrayWrite} {
641 ut_updateTag;
642 wdb_writeDirtyBytes;
643 wt_writeThrough;
644 p_popRequestQueue;
645 }
646
647 transition({V, M}, WrVicBlkBack, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
648 ut_updateTag;
649 swb_sendWBAck;
650 wdb_writeDirtyBytes;
651 p_popRequestQueue;
652 }
653
654 transition(W, WrVicBlkBack) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
655 ut_updateTag;
656 swb_sendWBAck;
657 wdb_writeDirtyBytes;
658 p_popRequestQueue;
659 }
660
661 transition(I, WrVicBlkBack, W) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
662 a_allocateBlock;
663 ut_updateTag;
664 swb_sendWBAck;
665 wdb_writeDirtyBytes;
666 p_popRequestQueue;
667 }
668
669 transition({W, M}, L2_Repl, WI) {TagArrayRead, DataArrayRead} {
670 t_allocateTBE;
671 wb_writeBack;
672 i_invL2;
673 }
674
675 transition({I, V}, L2_Repl, I) {TagArrayRead, TagArrayWrite} {
676 i_invL2;
677 }
678
679 transition({A, IV, WI}, L2_Repl) {
680 i_invL2;
681 }
682
683 transition({I, V}, PrbInv, I) {TagArrayRead, TagArrayWrite} {
684 pi_sendProbeResponseInv;
685 pp_popProbeQueue;
686 }
687
688 transition(M, PrbInv, W) {TagArrayRead, TagArrayWrite} {
689 pi_sendProbeResponseInv;
690 pp_popProbeQueue;
691 }
692
693 transition(W, PrbInv) {TagArrayRead} {
694 pi_sendProbeResponseInv;
695 pp_popProbeQueue;
696 }
697
698 transition({A, IV, WI}, PrbInv) {
699 pi_sendProbeResponseInv;
700 pp_popProbeQueue;
701 }
702
703 transition(IV, Data, V) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
704 a_allocateBlock;
705 ut_updateTag;
706 wcb_writeCacheBlock;
707 sdr_sendDataResponse;
708 pr_popResponseQueue;
709 dt_deallocateTBE;
710 }
711
712 transition(A, Data) {TagArrayRead, TagArrayWrite, DataArrayWrite} {
713 a_allocateBlock;
714 ar_sendAtomicResponse;
715 dna_decrementNumAtomics;
716 pr_popResponseQueue;
717 }
718
719 transition(A, AtomicDone, I) {TagArrayRead, TagArrayWrite} {
720 dt_deallocateTBE;
721 ptr_popTriggerQueue;
722 }
723
724 transition(A, AtomicNotDone) {TagArrayRead} {
725 ptr_popTriggerQueue;
726 }
727
728 //M,W should not see WBAck as the cache is in WB mode
729 //WBAcks do not need to check tags
730 transition({I, V, IV, A}, WBAck) {
731 w_sendResponseWBAck;
732 pr_popResponseQueue;
733 }
734
735 transition(WI, WBAck,I) {
736 dt_deallocateTBE;
737 pr_popResponseQueue;
738 }
739 }