mem-cache: Create an address aware TempCacheBlk
[gem5.git] / src / mem / protocol / GPU_RfO-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
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 * Authors: Lisa Hsu
34 */
35
36 machine(MachineType:TCC, "TCC Cache")
37 : CacheMemory * L2cache;
38 WireBuffer * w_reqToTCCDir;
39 WireBuffer * w_respToTCCDir;
40 WireBuffer * w_TCCUnblockToTCCDir;
41 WireBuffer * w_reqToTCC;
42 WireBuffer * w_probeToTCC;
43 WireBuffer * w_respToTCC;
44 int TCC_select_num_bits;
45 Cycles l2_request_latency := 1;
46 Cycles l2_response_latency := 20;
47
48 // To the general response network
49 MessageBuffer * responseFromTCC, network="To", virtual_network="3", vnet_type="response";
50
51 // From the general response network
52 MessageBuffer * responseToTCC, network="From", virtual_network="3", vnet_type="response";
53
54 {
55 // EVENTS
56 enumeration(Event, desc="TCC Events") {
57 // Requests coming from the Cores
58 RdBlk, desc="CPU RdBlk event";
59 RdBlkM, desc="CPU RdBlkM event";
60 RdBlkS, desc="CPU RdBlkS event";
61 CtoD, desc="Change to Dirty request";
62 WrVicBlk, desc="L1 Victim (dirty)";
63 WrVicBlkShared, desc="L1 Victim (dirty)";
64 ClVicBlk, desc="L1 Victim (clean)";
65 ClVicBlkShared, desc="L1 Victim (clean)";
66
67 CPUData, desc="WB data from CPU";
68 CPUDataShared, desc="WB data from CPU, NBReqShared 1";
69 StaleWB, desc="Stale WB, No data";
70
71 L2_Repl, desc="L2 Replacement";
72
73 // Probes
74 PrbInvData, desc="Invalidating probe, return dirty data";
75 PrbInv, desc="Invalidating probe, no need to return data";
76 PrbShrData, desc="Downgrading probe, return data";
77
78 // Coming from Memory Controller
79 WBAck, desc="ack from memory";
80
81 CancelWB, desc="Cancel WB from L2";
82 }
83
84 // STATES
85 state_declaration(State, desc="TCC State", default="TCC_State_I") {
86 M, AccessPermission:Read_Write, desc="Modified"; // No other cache has copy, memory stale
87 O, AccessPermission:Read_Only, desc="Owned"; // Correct most recent copy, others may exist in S
88 E, AccessPermission:Read_Write, desc="Exclusive"; // Correct, most recent, and only copy (and == Memory)
89 S, AccessPermission:Read_Only, desc="Shared"; // Correct, most recent. If no one in O, then == Memory
90 I, AccessPermission:Invalid, desc="Invalid";
91
92 I_M, AccessPermission:Busy, desc="Invalid, received WrVicBlk, sent Ack, waiting for Data";
93 I_O, AccessPermission:Busy, desc="Invalid, received WrVicBlk, sent Ack, waiting for Data";
94 I_E, AccessPermission:Busy, desc="Invalid, receive ClVicBlk, sent Ack, waiting for Data";
95 I_S, AccessPermission:Busy, desc="Invalid, receive ClVicBlk, sent Ack, waiting for Data";
96 S_M, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to M";
97 S_O, AccessPermission:Busy, desc="received WrVicBlkShared, sent Ack, waiting for Data, then go to O";
98 S_E, AccessPermission:Busy, desc="Shared, received ClVicBlk, sent Ack, waiting for Data, then go to E";
99 S_S, AccessPermission:Busy, desc="Shared, received ClVicBlk, sent Ack, waiting for Data, then go to S";
100 E_M, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to O";
101 E_O, AccessPermission:Busy, desc="received WrVicBlkShared, sent Ack, waiting for Data, then go to O";
102 E_E, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to O";
103 E_S, AccessPermission:Busy, desc="Shared, received WrVicBlk, sent Ack, waiting for Data";
104 O_M, AccessPermission:Busy, desc="...";
105 O_O, AccessPermission:Busy, desc="...";
106 O_E, AccessPermission:Busy, desc="...";
107 M_M, AccessPermission:Busy, desc="...";
108 M_O, AccessPermission:Busy, desc="...";
109 M_E, AccessPermission:Busy, desc="...";
110 M_S, AccessPermission:Busy, desc="...";
111 D_I, AccessPermission:Invalid, desc="drop WB data on the floor when receive";
112 MOD_I, AccessPermission:Busy, desc="drop WB data on the floor, waiting for WBAck from Mem";
113 MO_I, AccessPermission:Busy, desc="M or O, received L2_Repl, waiting for WBAck from Mem";
114 ES_I, AccessPermission:Busy, desc="E or S, received L2_Repl, waiting for WBAck from Mem";
115 I_C, AccessPermission:Invalid, desc="sent cancel, just waiting to receive mem wb ack so nothing gets confused";
116 }
117
118 enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
119 DataArrayRead, desc="Read the data array";
120 DataArrayWrite, desc="Write the data array";
121 TagArrayRead, desc="Read the data array";
122 TagArrayWrite, desc="Write the data array";
123 }
124
125
126 // STRUCTURES
127
128 structure(Entry, desc="...", interface="AbstractCacheEntry") {
129 State CacheState, desc="cache state";
130 bool Dirty, desc="Is the data dirty (diff from memory?)";
131 DataBlock DataBlk, desc="Data for the block";
132 }
133
134 structure(TBE, desc="...") {
135 State TBEState, desc="Transient state";
136 DataBlock DataBlk, desc="data for the block";
137 bool Dirty, desc="Is the data dirty?";
138 bool Shared, desc="Victim hit by shared probe";
139 MachineID From, desc="Waiting for writeback from...";
140 }
141
142 structure(TBETable, external="yes") {
143 TBE lookup(Addr);
144 void allocate(Addr);
145 void deallocate(Addr);
146 bool isPresent(Addr);
147 }
148
149 TBETable TBEs, template="<TCC_TBE>", constructor="m_number_of_TBEs";
150 int TCC_select_low_bit, default="RubySystem::getBlockSizeBits()";
151
152 void set_cache_entry(AbstractCacheEntry b);
153 void unset_cache_entry();
154 void set_tbe(TBE b);
155 void unset_tbe();
156 void wakeUpAllBuffers();
157 void wakeUpBuffers(Addr a);
158
159
160 // FUNCTION DEFINITIONS
161 Tick clockEdge();
162 Tick cyclesToTicks(Cycles c);
163
164 Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
165 return static_cast(Entry, "pointer", L2cache.lookup(addr));
166 }
167
168 DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
169 return getCacheEntry(addr).DataBlk;
170 }
171
172 bool presentOrAvail(Addr addr) {
173 return L2cache.isTagPresent(addr) || L2cache.cacheAvail(addr);
174 }
175
176 State getState(TBE tbe, Entry cache_entry, Addr addr) {
177 if (is_valid(tbe)) {
178 return tbe.TBEState;
179 } else if (is_valid(cache_entry)) {
180 return cache_entry.CacheState;
181 }
182 return State:I;
183 }
184
185 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
186 if (is_valid(tbe)) {
187 tbe.TBEState := state;
188 }
189
190 if (is_valid(cache_entry)) {
191 cache_entry.CacheState := state;
192 }
193 }
194
195 AccessPermission getAccessPermission(Addr addr) {
196 TBE tbe := TBEs.lookup(addr);
197 if(is_valid(tbe)) {
198 return TCC_State_to_permission(tbe.TBEState);
199 }
200
201 Entry cache_entry := getCacheEntry(addr);
202 if(is_valid(cache_entry)) {
203 return TCC_State_to_permission(cache_entry.CacheState);
204 }
205
206 return AccessPermission:NotPresent;
207 }
208
209 void setAccessPermission(Entry cache_entry, Addr addr, State state) {
210 if (is_valid(cache_entry)) {
211 cache_entry.changePermission(TCC_State_to_permission(state));
212 }
213 }
214
215 void functionalRead(Addr addr, Packet *pkt) {
216 TBE tbe := TBEs.lookup(addr);
217 if(is_valid(tbe)) {
218 testAndRead(addr, tbe.DataBlk, pkt);
219 } else {
220 functionalMemoryRead(pkt);
221 }
222 }
223
224 int functionalWrite(Addr addr, Packet *pkt) {
225 int num_functional_writes := 0;
226
227 TBE tbe := TBEs.lookup(addr);
228 if(is_valid(tbe)) {
229 num_functional_writes := num_functional_writes +
230 testAndWrite(addr, tbe.DataBlk, pkt);
231 }
232
233 num_functional_writes := num_functional_writes + functionalMemoryWrite(pkt);
234 return num_functional_writes;
235 }
236
237 void recordRequestType(RequestType request_type, Addr addr) {
238 if (request_type == RequestType:DataArrayRead) {
239 L2cache.recordRequestType(CacheRequestType:DataArrayRead, addr);
240 } else if (request_type == RequestType:DataArrayWrite) {
241 L2cache.recordRequestType(CacheRequestType:DataArrayWrite, addr);
242 } else if (request_type == RequestType:TagArrayRead) {
243 L2cache.recordRequestType(CacheRequestType:TagArrayRead, addr);
244 } else if (request_type == RequestType:TagArrayWrite) {
245 L2cache.recordRequestType(CacheRequestType:TagArrayWrite, addr);
246 }
247 }
248
249 bool checkResourceAvailable(RequestType request_type, Addr addr) {
250 if (request_type == RequestType:DataArrayRead) {
251 return L2cache.checkResourceAvailable(CacheResourceType:DataArray, addr);
252 } else if (request_type == RequestType:DataArrayWrite) {
253 return L2cache.checkResourceAvailable(CacheResourceType:DataArray, addr);
254 } else if (request_type == RequestType:TagArrayRead) {
255 return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr);
256 } else if (request_type == RequestType:TagArrayWrite) {
257 return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr);
258 } else {
259 error("Invalid RequestType type in checkResourceAvailable");
260 return true;
261 }
262 }
263
264
265
266 // OUT PORTS
267 out_port(w_requestNetwork_out, CPURequestMsg, w_reqToTCCDir);
268 out_port(w_TCCResp_out, ResponseMsg, w_respToTCCDir);
269 out_port(responseNetwork_out, ResponseMsg, responseFromTCC);
270 out_port(w_unblockNetwork_out, UnblockMsg, w_TCCUnblockToTCCDir);
271
272 // IN PORTS
273 in_port(TDResponse_in, ResponseMsg, w_respToTCC) {
274 if (TDResponse_in.isReady(clockEdge())) {
275 peek(TDResponse_in, ResponseMsg) {
276 Entry cache_entry := getCacheEntry(in_msg.addr);
277 TBE tbe := TBEs.lookup(in_msg.addr);
278 if (in_msg.Type == CoherenceResponseType:TDSysWBAck) {
279 trigger(Event:WBAck, in_msg.addr, cache_entry, tbe);
280 }
281 else {
282 DPRINTF(RubySlicc, "%s\n", in_msg);
283 error("Error on TDResponse Type");
284 }
285 }
286 }
287 }
288
289 // Response Network
290 in_port(responseNetwork_in, ResponseMsg, responseToTCC) {
291 if (responseNetwork_in.isReady(clockEdge())) {
292 peek(responseNetwork_in, ResponseMsg) {
293 Entry cache_entry := getCacheEntry(in_msg.addr);
294 TBE tbe := TBEs.lookup(in_msg.addr);
295 if (in_msg.Type == CoherenceResponseType:CPUData) {
296 if (in_msg.NbReqShared) {
297 trigger(Event:CPUDataShared, in_msg.addr, cache_entry, tbe);
298 } else {
299 trigger(Event:CPUData, in_msg.addr, cache_entry, tbe);
300 }
301 } else if (in_msg.Type == CoherenceResponseType:StaleNotif) {
302 trigger(Event:StaleWB, in_msg.addr, cache_entry, tbe);
303 } else {
304 DPRINTF(RubySlicc, "%s\n", in_msg);
305 error("Error on TDResponse Type");
306 }
307 }
308 }
309 }
310
311 // probe network
312 in_port(probeNetwork_in, TDProbeRequestMsg, w_probeToTCC) {
313 if (probeNetwork_in.isReady(clockEdge())) {
314 peek(probeNetwork_in, TDProbeRequestMsg) {
315 Entry cache_entry := getCacheEntry(in_msg.addr);
316 TBE tbe := TBEs.lookup(in_msg.addr);
317 if (in_msg.Type == ProbeRequestType:PrbInv) {
318 if (in_msg.ReturnData) {
319 trigger(Event:PrbInvData, in_msg.addr, cache_entry, tbe);
320 } else {
321 trigger(Event:PrbInv, in_msg.addr, cache_entry, tbe);
322 }
323 } else if (in_msg.Type == ProbeRequestType:PrbDowngrade) {
324 if (in_msg.ReturnData) {
325 trigger(Event:PrbShrData, in_msg.addr, cache_entry, tbe);
326 } else {
327 error("Don't think I should get any of these");
328 }
329 }
330 }
331 }
332 }
333
334 // Request Network
335 in_port(requestNetwork_in, CPURequestMsg, w_reqToTCC) {
336 if (requestNetwork_in.isReady(clockEdge())) {
337 peek(requestNetwork_in, CPURequestMsg) {
338 assert(in_msg.Destination.isElement(machineID));
339 Entry cache_entry := getCacheEntry(in_msg.addr);
340 TBE tbe := TBEs.lookup(in_msg.addr);
341 if (in_msg.Type == CoherenceRequestType:RdBlk) {
342 trigger(Event:RdBlk, in_msg.addr, cache_entry, tbe);
343 } else if (in_msg.Type == CoherenceRequestType:RdBlkS) {
344 trigger(Event:RdBlkS, in_msg.addr, cache_entry, tbe);
345 } else if (in_msg.Type == CoherenceRequestType:RdBlkM) {
346 trigger(Event:RdBlkM, in_msg.addr, cache_entry, tbe);
347 } else if (in_msg.Type == CoherenceRequestType:VicClean) {
348 if (presentOrAvail(in_msg.addr)) {
349 if (in_msg.Shared) {
350 trigger(Event:ClVicBlkShared, in_msg.addr, cache_entry, tbe);
351 } else {
352 trigger(Event:ClVicBlk, in_msg.addr, cache_entry, tbe);
353 }
354 } else {
355 Addr victim := L2cache.cacheProbe(in_msg.addr);
356 trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
357 }
358 } else if (in_msg.Type == CoherenceRequestType:VicDirty) {
359 if (presentOrAvail(in_msg.addr)) {
360 if (in_msg.Shared) {
361 trigger(Event:WrVicBlkShared, in_msg.addr, cache_entry, tbe);
362 } else {
363 trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe);
364 }
365 } else {
366 Addr victim := L2cache.cacheProbe(in_msg.addr);
367 trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
368 }
369 } else {
370 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
371 }
372 }
373 }
374 }
375
376 // BEGIN ACTIONS
377
378 action(i_invL2, "i", desc="invalidate TCC cache block") {
379 if (is_valid(cache_entry)) {
380 L2cache.deallocate(address);
381 }
382 unset_cache_entry();
383 }
384
385 action(rm_sendResponseM, "rm", desc="send Modified response") {
386 peek(requestNetwork_in, CPURequestMsg) {
387 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) {
388 out_msg.addr := address;
389 out_msg.Type := CoherenceResponseType:TDSysResp;
390 out_msg.Sender := machineID;
391 out_msg.Destination.add(in_msg.Requestor);
392 out_msg.DataBlk := cache_entry.DataBlk;
393 out_msg.MessageSize := MessageSizeType:Response_Data;
394 out_msg.Dirty := cache_entry.Dirty;
395 out_msg.State := CoherenceState:Modified;
396 DPRINTF(RubySlicc, "%s\n", out_msg);
397 }
398 }
399 }
400
401 action(rs_sendResponseS, "rs", desc="send Shared response") {
402 peek(requestNetwork_in, CPURequestMsg) {
403 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) {
404 out_msg.addr := address;
405 out_msg.Type := CoherenceResponseType:TDSysResp;
406 out_msg.Sender := machineID;
407 out_msg.Destination.add(in_msg.Requestor);
408 out_msg.DataBlk := cache_entry.DataBlk;
409 out_msg.MessageSize := MessageSizeType:Response_Data;
410 out_msg.Dirty := cache_entry.Dirty;
411 out_msg.State := CoherenceState:Shared;
412 DPRINTF(RubySlicc, "%s\n", out_msg);
413 }
414 }
415 }
416
417
418 action(r_requestToTD, "r", desc="Miss in L2, pass on") {
419 peek(requestNetwork_in, CPURequestMsg) {
420 enqueue(w_requestNetwork_out, CPURequestMsg, l2_request_latency) {
421 out_msg.addr := address;
422 out_msg.Type := in_msg.Type;
423 out_msg.Requestor := in_msg.Requestor;
424 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
425 TCC_select_low_bit, TCC_select_num_bits));
426 out_msg.Shared := false; // unneeded for this request
427 out_msg.MessageSize := in_msg.MessageSize;
428 DPRINTF(RubySlicc, "%s\n", out_msg);
429 }
430 }
431 }
432
433 action(t_allocateTBE, "t", desc="allocate TBE Entry") {
434 TBEs.allocate(address);
435 set_tbe(TBEs.lookup(address));
436 if (is_valid(cache_entry)) {
437 tbe.DataBlk := cache_entry.DataBlk; // Data only for WBs
438 tbe.Dirty := cache_entry.Dirty;
439 }
440 tbe.From := machineID;
441 }
442
443 action(dt_deallocateTBE, "dt", desc="deallocate TBE Entry") {
444 TBEs.deallocate(address);
445 unset_tbe();
446 }
447
448 action(vc_vicClean, "vc", desc="Victimize Clean L2 data") {
449 enqueue(w_requestNetwork_out, CPURequestMsg, l2_request_latency) {
450 out_msg.addr := address;
451 out_msg.Type := CoherenceRequestType:VicClean;
452 out_msg.Requestor := machineID;
453 out_msg.DataBlk := cache_entry.DataBlk;
454 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
455 TCC_select_low_bit, TCC_select_num_bits));
456 out_msg.MessageSize := MessageSizeType:Response_Data;
457 }
458 }
459
460 action(vd_vicDirty, "vd", desc="Victimize dirty L2 data") {
461 enqueue(w_requestNetwork_out, CPURequestMsg, l2_request_latency) {
462 out_msg.addr := address;
463 out_msg.Type := CoherenceRequestType:VicDirty;
464 out_msg.Requestor := machineID;
465 out_msg.DataBlk := cache_entry.DataBlk;
466 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
467 TCC_select_low_bit, TCC_select_num_bits));
468 out_msg.MessageSize := MessageSizeType:Response_Data;
469 }
470 }
471
472 action(w_sendResponseWBAck, "w", desc="send WB Ack") {
473 peek(requestNetwork_in, CPURequestMsg) {
474 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) {
475 out_msg.addr := address;
476 out_msg.Type := CoherenceResponseType:TDSysWBAck;
477 out_msg.Destination.add(in_msg.Requestor);
478 out_msg.Sender := machineID;
479 out_msg.MessageSize := MessageSizeType:Writeback_Control;
480 }
481 }
482 }
483
484 action(pi_sendProbeResponseInv, "pi", desc="send probe ack inv, no data") {
485 enqueue(w_TCCResp_out, ResponseMsg, l2_request_latency) {
486 out_msg.addr := address;
487 out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC and CPUs respond in same way to probes
488 out_msg.Sender := machineID;
489 // will this always be ok? probably not for multisocket
490 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
491 TCC_select_low_bit, TCC_select_num_bits));
492 out_msg.Dirty := false;
493 out_msg.Hit := false;
494 out_msg.Ntsl := true;
495 out_msg.State := CoherenceState:NA;
496 out_msg.MessageSize := MessageSizeType:Response_Control;
497 }
498 }
499
500 action(ph_sendProbeResponseHit, "ph", desc="send probe ack, no data") {
501 enqueue(w_TCCResp_out, ResponseMsg, l2_request_latency) {
502 out_msg.addr := address;
503 out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC and CPUs respond in same way to probes
504 out_msg.Sender := machineID;
505 // will this always be ok? probably not for multisocket
506 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
507 TCC_select_low_bit, TCC_select_num_bits));
508 out_msg.Dirty := false;
509 out_msg.Hit := true;
510 out_msg.Ntsl := false;
511 out_msg.State := CoherenceState:NA;
512 out_msg.MessageSize := MessageSizeType:Response_Control;
513 }
514 }
515
516 action(pm_sendProbeResponseMiss, "pm", desc="send probe ack, no data") {
517 enqueue(w_TCCResp_out, ResponseMsg, l2_request_latency) {
518 out_msg.addr := address;
519 out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC and CPUs respond in same way to probes
520 out_msg.Sender := machineID;
521 // will this always be ok? probably not for multisocket
522 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
523 TCC_select_low_bit, TCC_select_num_bits));
524 out_msg.Dirty := false;
525 out_msg.Hit := false;
526 out_msg.Ntsl := false;
527 out_msg.State := CoherenceState:NA;
528 out_msg.MessageSize := MessageSizeType:Response_Control;
529 }
530 }
531
532 action(pd_sendProbeResponseData, "pd", desc="send probe ack, with data") {
533 enqueue(w_TCCResp_out, ResponseMsg, l2_request_latency) {
534 out_msg.addr := address;
535 out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC and CPUs respond in same way to probes
536 out_msg.Sender := machineID;
537 // will this always be ok? probably not for multisocket
538 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
539 TCC_select_low_bit, TCC_select_num_bits));
540 out_msg.DataBlk := cache_entry.DataBlk;
541 //assert(cache_entry.Dirty); Not needed in TCC where TCC can supply clean data
542 out_msg.Dirty := cache_entry.Dirty;
543 out_msg.Hit := true;
544 out_msg.State := CoherenceState:NA;
545 out_msg.MessageSize := MessageSizeType:Response_Data;
546 }
547 }
548
549 action(pdt_sendProbeResponseDataFromTBE, "pdt", desc="send probe ack with data") {
550 enqueue(w_TCCResp_out, ResponseMsg, l2_request_latency) {
551 out_msg.addr := address;
552 out_msg.Type := CoherenceResponseType:CPUPrbResp;
553 out_msg.Sender := machineID;
554 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
555 TCC_select_low_bit, TCC_select_num_bits));
556 out_msg.DataBlk := tbe.DataBlk;
557 //assert(tbe.Dirty);
558 out_msg.Dirty := tbe.Dirty;
559 out_msg.Hit := true;
560 out_msg.MessageSize := MessageSizeType:Response_Data;
561 out_msg.State := CoherenceState:NA;
562 DPRINTF(RubySlicc, "%s\n", out_msg);
563 }
564 }
565
566 action(mc_cancelMemWriteback, "mc", desc="send writeback cancel to memory") {
567 enqueue(w_requestNetwork_out, CPURequestMsg, l2_request_latency) {
568 out_msg.addr := address;
569 out_msg.Type := CoherenceRequestType:WrCancel;
570 out_msg.Requestor := machineID;
571 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
572 TCC_select_low_bit, TCC_select_num_bits));
573 out_msg.MessageSize := MessageSizeType:Request_Control;
574 }
575 }
576
577 action(a_allocateBlock, "a", desc="allocate TCC block") {
578 if (is_invalid(cache_entry)) {
579 set_cache_entry(L2cache.allocate(address, new Entry));
580 }
581 }
582
583 action(d_writeData, "d", desc="write data to TCC") {
584 peek(responseNetwork_in, ResponseMsg) {
585 if (in_msg.Dirty) {
586 cache_entry.Dirty := in_msg.Dirty;
587 }
588 cache_entry.DataBlk := in_msg.DataBlk;
589 DPRINTF(RubySlicc, "Writing to TCC: %s\n", in_msg);
590 }
591 }
592
593 action(rd_copyDataFromRequest, "rd", desc="write data to TCC") {
594 peek(requestNetwork_in, CPURequestMsg) {
595 cache_entry.DataBlk := in_msg.DataBlk;
596 cache_entry.Dirty := true;
597 }
598 }
599
600 action(f_setFrom, "f", desc="set who WB is expected to come from") {
601 peek(requestNetwork_in, CPURequestMsg) {
602 tbe.From := in_msg.Requestor;
603 }
604 }
605
606 action(rf_resetFrom, "rf", desc="reset From") {
607 tbe.From := machineID;
608 }
609
610 action(wb_data, "wb", desc="write back data") {
611 enqueue(w_TCCResp_out, ResponseMsg, l2_request_latency) {
612 out_msg.addr := address;
613 out_msg.Type := CoherenceResponseType:CPUData;
614 out_msg.Sender := machineID;
615 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
616 TCC_select_low_bit, TCC_select_num_bits));
617 out_msg.DataBlk := tbe.DataBlk;
618 out_msg.Dirty := tbe.Dirty;
619 if (tbe.Shared) {
620 out_msg.NbReqShared := true;
621 } else {
622 out_msg.NbReqShared := false;
623 }
624 out_msg.State := CoherenceState:Shared; // faux info
625 out_msg.MessageSize := MessageSizeType:Writeback_Data;
626 DPRINTF(RubySlicc, "%s\n", out_msg);
627 }
628 }
629
630 action(wt_writeDataToTBE, "wt", desc="write WB data to TBE") {
631 peek(responseNetwork_in, ResponseMsg) {
632 tbe.DataBlk := in_msg.DataBlk;
633 tbe.Dirty := in_msg.Dirty;
634 }
635 }
636
637 action(uo_sendUnblockOwner, "uo", desc="state changed to E, M, or O, unblock") {
638 enqueue(w_unblockNetwork_out, UnblockMsg, l2_request_latency) {
639 out_msg.addr := address;
640 out_msg.Sender := machineID;
641 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
642 TCC_select_low_bit, TCC_select_num_bits));
643 out_msg.MessageSize := MessageSizeType:Unblock_Control;
644 out_msg.currentOwner := true;
645 out_msg.valid := true;
646 DPRINTF(RubySlicc, "%s\n", out_msg);
647 }
648 }
649
650 action(us_sendUnblockSharer, "us", desc="state changed to S , unblock") {
651 enqueue(w_unblockNetwork_out, UnblockMsg, l2_request_latency) {
652 out_msg.addr := address;
653 out_msg.Sender := machineID;
654 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
655 TCC_select_low_bit, TCC_select_num_bits));
656 out_msg.MessageSize := MessageSizeType:Unblock_Control;
657 out_msg.currentOwner := false;
658 out_msg.valid := true;
659 DPRINTF(RubySlicc, "%s\n", out_msg);
660 }
661 }
662
663 action(un_sendUnblockNotValid, "un", desc="state changed toI, unblock") {
664 enqueue(w_unblockNetwork_out, UnblockMsg, l2_request_latency) {
665 out_msg.addr := address;
666 out_msg.Sender := machineID;
667 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCCdir,
668 TCC_select_low_bit, TCC_select_num_bits));
669 out_msg.MessageSize := MessageSizeType:Unblock_Control;
670 out_msg.currentOwner := false;
671 out_msg.valid := false;
672 DPRINTF(RubySlicc, "%s\n", out_msg);
673 }
674 }
675
676 action(ut_updateTag, "ut", desc="update Tag (i.e. set MRU)") {
677 L2cache.setMRU(address);
678 }
679
680 action(p_popRequestQueue, "p", desc="pop request queue") {
681 requestNetwork_in.dequeue(clockEdge());
682 }
683
684 action(pr_popResponseQueue, "pr", desc="pop response queue") {
685 responseNetwork_in.dequeue(clockEdge());
686 }
687
688 action(pn_popTDResponseQueue, "pn", desc="pop TD response queue") {
689 TDResponse_in.dequeue(clockEdge());
690 }
691
692 action(pp_popProbeQueue, "pp", desc="pop probe queue") {
693 probeNetwork_in.dequeue(clockEdge());
694 }
695
696 action(zz_recycleRequestQueue, "\z", desc="recycle request queue") {
697 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
698 }
699
700
701 // END ACTIONS
702
703 // BEGIN TRANSITIONS
704
705 // transitions from base
706
707 transition({I, I_C}, {RdBlk, RdBlkS, RdBlkM, CtoD}){TagArrayRead} {
708 // TCCdir already knows that the block is not here. This is to allocate and get the block.
709 r_requestToTD;
710 p_popRequestQueue;
711 }
712
713 // check
714 transition({M, O}, RdBlk, O){TagArrayRead, TagArrayWrite} {
715 rs_sendResponseS;
716 ut_updateTag;
717 // detect 2nd chancing
718 p_popRequestQueue;
719 }
720
721 //check
722 transition({E, S}, RdBlk, S){TagArrayRead, TagArrayWrite} {
723 rs_sendResponseS;
724 ut_updateTag;
725 // detect 2nd chancing
726 p_popRequestQueue;
727 }
728
729 // check
730 transition({M, O}, RdBlkS, O){TagArrayRead, TagArrayWrite} {
731 rs_sendResponseS;
732 ut_updateTag;
733 // detect 2nd chance sharing
734 p_popRequestQueue;
735 }
736
737 //check
738 transition({E, S}, RdBlkS, S){TagArrayRead, TagArrayWrite} {
739 rs_sendResponseS;
740 ut_updateTag;
741 // detect 2nd chance sharing
742 p_popRequestQueue;
743 }
744
745 // check
746 transition(M, RdBlkM, I){TagArrayRead, TagArrayWrite} {
747 rm_sendResponseM;
748 i_invL2;
749 p_popRequestQueue;
750 }
751
752 //check
753 transition(E, RdBlkM, I){TagArrayRead, TagArrayWrite} {
754 rm_sendResponseM;
755 i_invL2;
756 p_popRequestQueue;
757 }
758
759 // check
760 transition({I}, WrVicBlk, I_M){TagArrayRead} {
761 a_allocateBlock;
762 t_allocateTBE;
763 f_setFrom;
764 w_sendResponseWBAck;
765 p_popRequestQueue;
766 }
767
768 transition(I_C, {WrVicBlk, WrVicBlkShared, ClVicBlk, ClVicBlkShared}) {
769 zz_recycleRequestQueue;
770 }
771
772 //check
773 transition({I}, WrVicBlkShared, I_O) {TagArrayRead}{
774 a_allocateBlock;
775 t_allocateTBE;
776 f_setFrom;
777 // rd_copyDataFromRequest;
778 w_sendResponseWBAck;
779 p_popRequestQueue;
780 }
781
782 //check
783 transition(S, WrVicBlkShared, S_O){TagArrayRead} {
784 t_allocateTBE;
785 f_setFrom;
786 w_sendResponseWBAck;
787 p_popRequestQueue;
788 }
789
790 // a stale writeback
791 transition(S, WrVicBlk, S_S){TagArrayRead} {
792 t_allocateTBE;
793 f_setFrom;
794 w_sendResponseWBAck;
795 p_popRequestQueue;
796 }
797
798 // a stale writeback
799 transition(E, WrVicBlk, E_E){TagArrayRead} {
800 t_allocateTBE;
801 f_setFrom;
802 w_sendResponseWBAck;
803 p_popRequestQueue;
804 }
805
806 // a stale writeback
807 transition(E, WrVicBlkShared, E_E){TagArrayRead} {
808 t_allocateTBE;
809 f_setFrom;
810 w_sendResponseWBAck;
811 p_popRequestQueue;
812 }
813
814 // a stale writeback
815 transition(O, WrVicBlk, O_O){TagArrayRead} {
816 t_allocateTBE;
817 f_setFrom;
818 w_sendResponseWBAck;
819 p_popRequestQueue;
820 }
821
822 // a stale writeback
823 transition(O, WrVicBlkShared, O_O){TagArrayRead} {
824 t_allocateTBE;
825 f_setFrom;
826 w_sendResponseWBAck;
827 p_popRequestQueue;
828 }
829
830 // a stale writeback
831 transition(M, WrVicBlk, M_M){TagArrayRead} {
832 t_allocateTBE;
833 f_setFrom;
834 w_sendResponseWBAck;
835 p_popRequestQueue;
836 }
837
838 // a stale writeback
839 transition(M, WrVicBlkShared, M_O){TagArrayRead} {
840 t_allocateTBE;
841 f_setFrom;
842 w_sendResponseWBAck;
843 p_popRequestQueue;
844 }
845
846 //check
847 transition({I}, ClVicBlk, I_E){TagArrayRead} {
848 t_allocateTBE;
849 f_setFrom;
850 a_allocateBlock;
851 w_sendResponseWBAck;
852 p_popRequestQueue;
853 }
854
855 transition({I}, ClVicBlkShared, I_S){TagArrayRead} {
856 t_allocateTBE;
857 f_setFrom;
858 a_allocateBlock;
859 w_sendResponseWBAck;
860 p_popRequestQueue;
861 }
862
863 //check
864 transition(S, ClVicBlkShared, S_S){TagArrayRead} {
865 t_allocateTBE;
866 f_setFrom;
867 w_sendResponseWBAck;
868 p_popRequestQueue;
869 }
870
871 // a stale writeback
872 transition(E, ClVicBlk, E_E){TagArrayRead} {
873 t_allocateTBE;
874 f_setFrom;
875 w_sendResponseWBAck;
876 p_popRequestQueue;
877 }
878
879 // a stale writeback
880 transition(E, ClVicBlkShared, E_S){TagArrayRead} {
881 t_allocateTBE;
882 f_setFrom;
883 w_sendResponseWBAck;
884 p_popRequestQueue;
885 }
886
887 // a stale writeback
888 transition(O, ClVicBlk, O_O){TagArrayRead} {
889 t_allocateTBE;
890 f_setFrom;
891 w_sendResponseWBAck;
892 p_popRequestQueue;
893 }
894
895 // check. Original L3 ahd it going from O to O_S. Something can go from O to S only on writeback.
896 transition(O, ClVicBlkShared, O_O){TagArrayRead} {
897 t_allocateTBE;
898 f_setFrom;
899 w_sendResponseWBAck;
900 p_popRequestQueue;
901 }
902
903 // a stale writeback
904 transition(M, ClVicBlk, M_E){TagArrayRead} {
905 t_allocateTBE;
906 f_setFrom;
907 w_sendResponseWBAck;
908 p_popRequestQueue;
909 }
910
911 // a stale writeback
912 transition(M, ClVicBlkShared, M_S){TagArrayRead} {
913 t_allocateTBE;
914 f_setFrom;
915 w_sendResponseWBAck;
916 p_popRequestQueue;
917 }
918
919
920 transition({MO_I}, {RdBlk, RdBlkS, RdBlkM, CtoD}) {
921 a_allocateBlock;
922 t_allocateTBE;
923 f_setFrom;
924 r_requestToTD;
925 p_popRequestQueue;
926 }
927
928 transition(MO_I, {WrVicBlkShared, WrVicBlk, ClVicBlk, ClVicBlkShared}, MOD_I) {
929 f_setFrom;
930 w_sendResponseWBAck;
931 p_popRequestQueue;
932 }
933
934 transition(I_M, CPUData, M){TagArrayWrite} {
935 uo_sendUnblockOwner;
936 dt_deallocateTBE;
937 d_writeData;
938 pr_popResponseQueue;
939 }
940
941 transition(I_M, CPUDataShared, O){TagArrayWrite, DataArrayWrite} {
942 uo_sendUnblockOwner;
943 dt_deallocateTBE;
944 d_writeData;
945 pr_popResponseQueue;
946 }
947
948 transition(I_O, {CPUData, CPUDataShared}, O){TagArrayWrite, DataArrayWrite} {
949 uo_sendUnblockOwner;
950 dt_deallocateTBE;
951 d_writeData;
952 pr_popResponseQueue;
953 }
954
955 transition(I_E, CPUData, E){TagArrayWrite, DataArrayWrite} {
956 uo_sendUnblockOwner;
957 dt_deallocateTBE;
958 d_writeData;
959 pr_popResponseQueue;
960 }
961
962 transition(I_E, CPUDataShared, S){TagArrayWrite, DataArrayWrite} {
963 us_sendUnblockSharer;
964 dt_deallocateTBE;
965 d_writeData;
966 pr_popResponseQueue;
967 }
968
969 transition(I_S, {CPUData, CPUDataShared}, S){TagArrayWrite, DataArrayWrite} {
970 us_sendUnblockSharer;
971 dt_deallocateTBE;
972 d_writeData;
973 pr_popResponseQueue;
974 }
975
976 transition(S_M, CPUDataShared, O){TagArrayWrite, DataArrayWrite} {
977 uo_sendUnblockOwner;
978 dt_deallocateTBE;
979 d_writeData;
980 ut_updateTag; // update tag on writeback hits.
981 pr_popResponseQueue;
982 }
983
984 transition(S_O, {CPUData, CPUDataShared}, O){TagArrayWrite, DataArrayWrite} {
985 uo_sendUnblockOwner;
986 dt_deallocateTBE;
987 d_writeData;
988 ut_updateTag; // update tag on writeback hits.
989 pr_popResponseQueue;
990 }
991
992 transition(S_E, CPUDataShared, S){TagArrayWrite, DataArrayWrite} {
993 us_sendUnblockSharer;
994 dt_deallocateTBE;
995 d_writeData;
996 ut_updateTag; // update tag on writeback hits.
997 pr_popResponseQueue;
998 }
999
1000 transition(S_S, {CPUData, CPUDataShared}, S){TagArrayWrite, DataArrayWrite} {
1001 us_sendUnblockSharer;
1002 dt_deallocateTBE;
1003 d_writeData;
1004 ut_updateTag; // update tag on writeback hits.
1005 pr_popResponseQueue;
1006 }
1007
1008 transition(O_E, CPUDataShared, O){TagArrayWrite, DataArrayWrite} {
1009 uo_sendUnblockOwner;
1010 dt_deallocateTBE;
1011 d_writeData;
1012 ut_updateTag; // update tag on writeback hits.
1013 pr_popResponseQueue;
1014 }
1015
1016 transition(O_O, {CPUData, CPUDataShared}, O){TagArrayWrite, DataArrayWrite} {
1017 uo_sendUnblockOwner;
1018 dt_deallocateTBE;
1019 d_writeData;
1020 ut_updateTag; // update tag on writeback hits.
1021 pr_popResponseQueue;
1022 }
1023
1024 transition({D_I}, {CPUData, CPUDataShared}, I){TagArrayWrite} {
1025 un_sendUnblockNotValid;
1026 dt_deallocateTBE;
1027 pr_popResponseQueue;
1028 }
1029
1030 transition(MOD_I, {CPUData, CPUDataShared}, MO_I) {
1031 un_sendUnblockNotValid;
1032 rf_resetFrom;
1033 pr_popResponseQueue;
1034 }
1035
1036 transition({O,S,I}, CPUData) {
1037 pr_popResponseQueue;
1038 }
1039
1040 transition({M, O}, L2_Repl, MO_I){TagArrayRead, DataArrayRead} {
1041 t_allocateTBE;
1042 vd_vicDirty;
1043 i_invL2;
1044 }
1045
1046 transition({E, S,}, L2_Repl, ES_I){TagArrayRead, DataArrayRead} {
1047 t_allocateTBE;
1048 vc_vicClean;
1049 i_invL2;
1050 }
1051
1052 transition({I_M, I_O, S_M, S_O, E_M, E_O}, L2_Repl) {
1053 zz_recycleRequestQueue;
1054 }
1055
1056 transition({O_M, O_O, O_E, M_M, M_O, M_E, M_S}, L2_Repl) {
1057 zz_recycleRequestQueue;
1058 }
1059
1060 transition({I_E, I_S, S_E, S_S, E_E, E_S}, L2_Repl) {
1061 zz_recycleRequestQueue;
1062 }
1063
1064 transition({M, O}, PrbInvData, I){TagArrayRead, TagArrayWrite} {
1065 pd_sendProbeResponseData;
1066 i_invL2;
1067 pp_popProbeQueue;
1068 }
1069
1070 transition(I, PrbInvData){TagArrayRead, TagArrayWrite} {
1071 pi_sendProbeResponseInv;
1072 pp_popProbeQueue;
1073 }
1074
1075 transition({E, S}, PrbInvData, I){TagArrayRead, TagArrayWrite} {
1076 pd_sendProbeResponseData;
1077 i_invL2;
1078 pp_popProbeQueue;
1079 }
1080
1081 transition({M, O, E, S, I}, PrbInv, I){TagArrayRead, TagArrayWrite} {
1082 pi_sendProbeResponseInv;
1083 i_invL2; // nothing will happen in I
1084 pp_popProbeQueue;
1085 }
1086
1087 transition({M, O}, PrbShrData, O){TagArrayRead, TagArrayWrite} {
1088 pd_sendProbeResponseData;
1089 pp_popProbeQueue;
1090 }
1091
1092 transition({E, S}, PrbShrData, S){TagArrayRead, TagArrayWrite} {
1093 pd_sendProbeResponseData;
1094 pp_popProbeQueue;
1095 }
1096
1097 transition(I, PrbShrData){TagArrayRead} {
1098 pm_sendProbeResponseMiss;
1099 pp_popProbeQueue;
1100 }
1101
1102 transition(MO_I, PrbInvData, I_C) {
1103 pdt_sendProbeResponseDataFromTBE;
1104 pp_popProbeQueue;
1105 }
1106
1107 transition(ES_I, PrbInvData, I_C) {
1108 pi_sendProbeResponseInv;
1109 pp_popProbeQueue;
1110 }
1111
1112 transition({ES_I,MO_I}, PrbInv, I_C) {
1113 pi_sendProbeResponseInv;
1114 pp_popProbeQueue;
1115 }
1116
1117 transition({ES_I, MO_I}, PrbShrData) {
1118 pdt_sendProbeResponseDataFromTBE;
1119 pp_popProbeQueue;
1120 }
1121
1122 transition(I_C, {PrbInvData, PrbInv}) {
1123 pi_sendProbeResponseInv;
1124 pp_popProbeQueue;
1125 }
1126
1127 transition(I_C, PrbShrData) {
1128 pm_sendProbeResponseMiss;
1129 pp_popProbeQueue;
1130 }
1131
1132 transition(MOD_I, WBAck, D_I) {
1133 pn_popTDResponseQueue;
1134 }
1135
1136 transition(MO_I, WBAck, I){TagArrayWrite} {
1137 dt_deallocateTBE;
1138 pn_popTDResponseQueue;
1139 }
1140
1141 // this can only be a spurious CPUData from a shared block.
1142 transition(MO_I, CPUData) {
1143 pr_popResponseQueue;
1144 }
1145
1146 transition(ES_I, WBAck, I){TagArrayWrite} {
1147 dt_deallocateTBE;
1148 pn_popTDResponseQueue;
1149 }
1150
1151 transition(I_C, {WBAck}, I){TagArrayWrite} {
1152 dt_deallocateTBE;
1153 pn_popTDResponseQueue;
1154 }
1155
1156 transition({I_M, I_O, I_E, I_S}, StaleWB, I){TagArrayWrite} {
1157 un_sendUnblockNotValid;
1158 dt_deallocateTBE;
1159 i_invL2;
1160 pr_popResponseQueue;
1161 }
1162
1163 transition({S_S, S_O, S_M, S_E}, StaleWB, S){TagArrayWrite} {
1164 us_sendUnblockSharer;
1165 dt_deallocateTBE;
1166 pr_popResponseQueue;
1167 }
1168
1169 transition({E_M, E_O, E_E, E_S}, StaleWB, E){TagArrayWrite} {
1170 uo_sendUnblockOwner;
1171 dt_deallocateTBE;
1172 pr_popResponseQueue;
1173 }
1174
1175 transition({O_M, O_O, O_E}, StaleWB, O){TagArrayWrite} {
1176 uo_sendUnblockOwner;
1177 dt_deallocateTBE;
1178 pr_popResponseQueue;
1179 }
1180
1181 transition({M_M, M_O, M_E, M_S}, StaleWB, M){TagArrayWrite} {
1182 uo_sendUnblockOwner;
1183 dt_deallocateTBE;
1184 pr_popResponseQueue;
1185 }
1186
1187 transition(D_I, StaleWB, I) {TagArrayWrite}{
1188 un_sendUnblockNotValid;
1189 dt_deallocateTBE;
1190 pr_popResponseQueue;
1191 }
1192
1193 transition(MOD_I, StaleWB, MO_I) {
1194 un_sendUnblockNotValid;
1195 rf_resetFrom;
1196 pr_popResponseQueue;
1197 }
1198
1199 }