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