ruby: slicc: have a static MachineType
[gem5.git] / src / mem / protocol / MESI_Three_Level-L1cache.sm
1 /*
2 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 machine(MachineType:L1Cache, "MESI Directory L1 Cache CMP")
30 : CacheMemory * cache;
31 int l2_select_num_bits;
32 Cycles l1_request_latency := 2;
33 Cycles l1_response_latency := 2;
34 Cycles to_l2_latency := 1;
35
36 // Message Buffers between the L1 and the L0 Cache
37 // From the L1 cache to the L0 cache
38 MessageBuffer * bufferToL0, network="To";
39
40 // From the L0 cache to the L1 cache
41 MessageBuffer * bufferFromL0, network="From";
42
43 // Message queue from this L1 cache TO the network / L2
44 MessageBuffer * requestToL2, network="To", virtual_network="0",
45 vnet_type="request";
46
47 MessageBuffer * responseToL2, network="To", virtual_network="1",
48 vnet_type="response";
49 MessageBuffer * unblockToL2, network="To", virtual_network="2",
50 vnet_type="unblock";
51
52 // To this L1 cache FROM the network / L2
53 MessageBuffer * requestFromL2, network="From", virtual_network="2",
54 vnet_type="request";
55 MessageBuffer * responseFromL2, network="From", virtual_network="1",
56 vnet_type="response";
57
58 {
59 // STATES
60 state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
61 // Base states
62 I, AccessPermission:Invalid, desc="a L1 cache entry Idle";
63 S, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
64 SS, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
65 E, AccessPermission:Read_Only, desc="a L1 cache entry Exclusive";
66 EE, AccessPermission:Read_Write, desc="a L1 cache entry Exclusive";
67 M, AccessPermission:Maybe_Stale, desc="a L1 cache entry Modified", format="!b";
68 MM, AccessPermission:Read_Write, desc="a L1 cache entry Modified", format="!b";
69
70 // Transient States
71 IS, AccessPermission:Busy, desc="L1 idle, issued GETS, have not seen response yet";
72 IM, AccessPermission:Busy, desc="L1 idle, issued GETX, have not seen response yet";
73 SM, AccessPermission:Read_Only, desc="L1 idle, issued GETX, have not seen response yet";
74 M_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK";
75 SINK_WB_ACK, AccessPermission:Busy, desc="This is to sink WB_Acks from L2";
76
77 // For all of the following states, invalidate
78 // message has been sent to L0 cache. The response
79 // from the L0 cache has not been seen yet.
80 S_IL0, AccessPermission:Busy;
81 E_IL0, AccessPermission:Busy;
82 M_IL0, AccessPermission:Busy;
83 MM_IL0, AccessPermission:Read_Write;
84 SM_IL0, AccessPermission:Busy;
85 }
86
87 // EVENTS
88 enumeration(Event, desc="Cache events") {
89 // Requests from the L0 cache
90 Load, desc="Load request";
91 Store, desc="Store request";
92 WriteBack, desc="Writeback request";
93
94 // Responses from the L0 Cache
95 // L0 cache received the invalidation message
96 // and has sent the data.
97 L0_DataAck;
98
99 Inv, desc="Invalidate request from L2 bank";
100
101 // internal generated request
102 // Invalidate the line in L0 due to own requirements
103 L0_Invalidate_Own;
104 // Invalidate the line in L0 due to some other cache's requirements
105 L0_Invalidate_Else;
106 // Invalidate the line in the cache due to some one else / space needs.
107 L1_Replacement;
108
109 // other requests
110 Fwd_GETX, desc="GETX from other processor";
111 Fwd_GETS, desc="GETS from other processor";
112
113 Data, desc="Data for processor";
114 Data_Exclusive, desc="Data for processor";
115 DataS_fromL1, desc="data for GETS request, need to unblock directory";
116 Data_all_Acks, desc="Data for processor, all acks";
117
118 L0_Ack, desc="Ack for processor";
119 Ack, desc="Ack for processor";
120 Ack_all, desc="Last ack for processor";
121
122 WB_Ack, desc="Ack for replacement";
123 }
124
125 // TYPES
126
127 // CacheEntry
128 structure(Entry, desc="...", interface="AbstractCacheEntry" ) {
129 State CacheState, desc="cache state";
130 DataBlock DataBlk, desc="data for the block";
131 bool Dirty, default="false", desc="data is dirty";
132 }
133
134 // TBE fields
135 structure(TBE, desc="...") {
136 Addr addr, desc="Physical address for this TBE";
137 State TBEState, desc="Transient state";
138 DataBlock DataBlk, desc="Buffer for the data block";
139 bool Dirty, default="false", desc="data is dirty";
140 int pendingAcks, default="0", desc="number of pending acks";
141 }
142
143 structure(TBETable, external="yes") {
144 TBE lookup(Addr);
145 void allocate(Addr);
146 void deallocate(Addr);
147 bool isPresent(Addr);
148 }
149
150 TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs";
151
152 int l2_select_low_bit, default="RubySystem::getBlockSizeBits()";
153
154 Tick clockEdge();
155 Cycles ticksToCycles(Tick t);
156 void set_cache_entry(AbstractCacheEntry a);
157 void unset_cache_entry();
158 void set_tbe(TBE a);
159 void unset_tbe();
160 void wakeUpBuffers(Addr a);
161 void wakeUpAllBuffers(Addr a);
162 void profileMsgDelay(int virtualNetworkType, Cycles c);
163
164 // inclusive cache returns L1 entries only
165 Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
166 Entry cache_entry := static_cast(Entry, "pointer", cache[addr]);
167 return cache_entry;
168 }
169
170 State getState(TBE tbe, Entry cache_entry, Addr addr) {
171 if(is_valid(tbe)) {
172 return tbe.TBEState;
173 } else if (is_valid(cache_entry)) {
174 return cache_entry.CacheState;
175 }
176 return State:I;
177 }
178
179 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
180 // MUST CHANGE
181 if(is_valid(tbe)) {
182 tbe.TBEState := state;
183 }
184
185 if (is_valid(cache_entry)) {
186 cache_entry.CacheState := state;
187 }
188 }
189
190 AccessPermission getAccessPermission(Addr addr) {
191 TBE tbe := TBEs[addr];
192 if(is_valid(tbe)) {
193 DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(tbe.TBEState));
194 return L1Cache_State_to_permission(tbe.TBEState);
195 }
196
197 Entry cache_entry := getCacheEntry(addr);
198 if(is_valid(cache_entry)) {
199 DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(cache_entry.CacheState));
200 return L1Cache_State_to_permission(cache_entry.CacheState);
201 }
202
203 DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent);
204 return AccessPermission:NotPresent;
205 }
206
207 void functionalRead(Addr addr, Packet *pkt) {
208 TBE tbe := TBEs[addr];
209 if(is_valid(tbe)) {
210 testAndRead(addr, tbe.DataBlk, pkt);
211 } else {
212 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
213 }
214 }
215
216 int functionalWrite(Addr addr, Packet *pkt) {
217 int num_functional_writes := 0;
218
219 TBE tbe := TBEs[addr];
220 if(is_valid(tbe)) {
221 num_functional_writes := num_functional_writes +
222 testAndWrite(addr, tbe.DataBlk, pkt);
223 return num_functional_writes;
224 }
225
226 num_functional_writes := num_functional_writes +
227 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
228 return num_functional_writes;
229 }
230
231 void setAccessPermission(Entry cache_entry, Addr addr, State state) {
232 if (is_valid(cache_entry)) {
233 cache_entry.changePermission(L1Cache_State_to_permission(state));
234 }
235 }
236
237 Event mandatory_request_type_to_event(CoherenceClass type) {
238 if (type == CoherenceClass:GETS) {
239 return Event:Load;
240 } else if ((type == CoherenceClass:GETX) ||
241 (type == CoherenceClass:UPGRADE)) {
242 return Event:Store;
243 } else if (type == CoherenceClass:PUTX) {
244 return Event:WriteBack;
245 } else {
246 error("Invalid RequestType");
247 }
248 }
249
250 int getPendingAcks(TBE tbe) {
251 return tbe.pendingAcks;
252 }
253
254 bool inL0Cache(State state) {
255 if (state == State:S || state == State:E || state == State:M ||
256 state == State:S_IL0 || state == State:E_IL0 ||
257 state == State:M_IL0 || state == State:SM_IL0) {
258 return true;
259 }
260
261 return false;
262 }
263
264 out_port(requestNetwork_out, RequestMsg, requestToL2);
265 out_port(responseNetwork_out, ResponseMsg, responseToL2);
266 out_port(unblockNetwork_out, ResponseMsg, unblockToL2);
267 out_port(bufferToL0_out, CoherenceMsg, bufferToL0);
268
269 // Response From the L2 Cache to this L1 cache
270 in_port(responseNetwork_in, ResponseMsg, responseFromL2, rank = 3) {
271 if (responseNetwork_in.isReady(clockEdge())) {
272 peek(responseNetwork_in, ResponseMsg) {
273 assert(in_msg.Destination.isElement(machineID));
274
275 Entry cache_entry := getCacheEntry(in_msg.addr);
276 TBE tbe := TBEs[in_msg.addr];
277
278 if(in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
279 trigger(Event:Data_Exclusive, in_msg.addr, cache_entry, tbe);
280 } else if(in_msg.Type == CoherenceResponseType:DATA) {
281 if (getState(tbe, cache_entry, in_msg.addr) == State:IS &&
282 machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) {
283
284 trigger(Event:DataS_fromL1, in_msg.addr, cache_entry, tbe);
285
286 } else if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) {
287 trigger(Event:Data_all_Acks, in_msg.addr, cache_entry, tbe);
288 } else {
289 trigger(Event:Data, in_msg.addr, cache_entry, tbe);
290 }
291 } else if (in_msg.Type == CoherenceResponseType:ACK) {
292 if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) {
293 trigger(Event:Ack_all, in_msg.addr, cache_entry, tbe);
294 } else {
295 trigger(Event:Ack, in_msg.addr, cache_entry, tbe);
296 }
297 } else if (in_msg.Type == CoherenceResponseType:WB_ACK) {
298 trigger(Event:WB_Ack, in_msg.addr, cache_entry, tbe);
299 } else {
300 error("Invalid L1 response type");
301 }
302 }
303 }
304 }
305
306 // Request to this L1 cache from the shared L2
307 in_port(requestNetwork_in, RequestMsg, requestFromL2, rank = 2) {
308 if(requestNetwork_in.isReady(clockEdge())) {
309 peek(requestNetwork_in, RequestMsg) {
310 assert(in_msg.Destination.isElement(machineID));
311 Entry cache_entry := getCacheEntry(in_msg.addr);
312 TBE tbe := TBEs[in_msg.addr];
313
314 if (in_msg.Type == CoherenceRequestType:INV) {
315 if (is_valid(cache_entry) && inL0Cache(cache_entry.CacheState)) {
316 trigger(Event:L0_Invalidate_Else, in_msg.addr,
317 cache_entry, tbe);
318 } else {
319 trigger(Event:Inv, in_msg.addr, cache_entry, tbe);
320 }
321 } else if (in_msg.Type == CoherenceRequestType:GETX ||
322 in_msg.Type == CoherenceRequestType:UPGRADE) {
323 if (is_valid(cache_entry) && inL0Cache(cache_entry.CacheState)) {
324 trigger(Event:L0_Invalidate_Else, in_msg.addr,
325 cache_entry, tbe);
326 } else {
327 trigger(Event:Fwd_GETX, in_msg.addr, cache_entry, tbe);
328 }
329 } else if (in_msg.Type == CoherenceRequestType:GETS) {
330 if (is_valid(cache_entry) && inL0Cache(cache_entry.CacheState)) {
331 trigger(Event:L0_Invalidate_Else, in_msg.addr,
332 cache_entry, tbe);
333 } else {
334 trigger(Event:Fwd_GETS, in_msg.addr, cache_entry, tbe);
335 }
336 } else {
337 error("Invalid forwarded request type");
338 }
339 }
340 }
341 }
342
343 // Requests to this L1 cache from the L0 cache.
344 in_port(messageBufferFromL0_in, CoherenceMsg, bufferFromL0, rank = 0) {
345 if (messageBufferFromL0_in.isReady(clockEdge())) {
346 peek(messageBufferFromL0_in, CoherenceMsg) {
347 Entry cache_entry := getCacheEntry(in_msg.addr);
348 TBE tbe := TBEs[in_msg.addr];
349
350 if(in_msg.Class == CoherenceClass:INV_DATA) {
351 trigger(Event:L0_DataAck, in_msg.addr, cache_entry, tbe);
352 } else if (in_msg.Class == CoherenceClass:INV_ACK) {
353 trigger(Event:L0_Ack, in_msg.addr, cache_entry, tbe);
354 } else {
355 if (is_valid(cache_entry)) {
356 trigger(mandatory_request_type_to_event(in_msg.Class),
357 in_msg.addr, cache_entry, tbe);
358 } else {
359 if (cache.cacheAvail(in_msg.addr)) {
360 // L1 does't have the line, but we have space for it
361 // in the L1 let's see if the L2 has it
362 trigger(mandatory_request_type_to_event(in_msg.Class),
363 in_msg.addr, cache_entry, tbe);
364 } else {
365 // No room in the L1, so we need to make room in the L1
366 Entry victim_entry :=
367 getCacheEntry(cache.cacheProbe(in_msg.addr));
368 TBE victim_tbe := TBEs[cache.cacheProbe(in_msg.addr)];
369
370 if (is_valid(victim_entry) && inL0Cache(victim_entry.CacheState)) {
371 trigger(Event:L0_Invalidate_Own,
372 cache.cacheProbe(in_msg.addr),
373 victim_entry, victim_tbe);
374 } else {
375 trigger(Event:L1_Replacement,
376 cache.cacheProbe(in_msg.addr),
377 victim_entry, victim_tbe);
378 }
379 }
380 }
381 }
382 }
383 }
384 }
385
386 // ACTIONS
387 action(a_issueGETS, "a", desc="Issue GETS") {
388 peek(messageBufferFromL0_in, CoherenceMsg) {
389 enqueue(requestNetwork_out, RequestMsg, l1_request_latency) {
390 out_msg.addr := address;
391 out_msg.Type := CoherenceRequestType:GETS;
392 out_msg.Requestor := machineID;
393 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
394 l2_select_low_bit, l2_select_num_bits, clusterID));
395 DPRINTF(RubySlicc, "address: %#x, destination: %s\n",
396 address, out_msg.Destination);
397 out_msg.MessageSize := MessageSizeType:Control;
398 out_msg.AccessMode := in_msg.AccessMode;
399 }
400 }
401 }
402
403 action(b_issueGETX, "b", desc="Issue GETX") {
404 peek(messageBufferFromL0_in, CoherenceMsg) {
405 enqueue(requestNetwork_out, RequestMsg, l1_request_latency) {
406 out_msg.addr := address;
407 out_msg.Type := CoherenceRequestType:GETX;
408 out_msg.Requestor := machineID;
409 DPRINTF(RubySlicc, "%s\n", machineID);
410 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
411 l2_select_low_bit, l2_select_num_bits, clusterID));
412 DPRINTF(RubySlicc, "address: %#x, destination: %s\n",
413 address, out_msg.Destination);
414 out_msg.MessageSize := MessageSizeType:Control;
415 out_msg.AccessMode := in_msg.AccessMode;
416 }
417 }
418 }
419
420 action(c_issueUPGRADE, "c", desc="Issue GETX") {
421 peek(messageBufferFromL0_in, CoherenceMsg) {
422 enqueue(requestNetwork_out, RequestMsg, l1_request_latency) {
423 out_msg.addr := address;
424 out_msg.Type := CoherenceRequestType:UPGRADE;
425 out_msg.Requestor := machineID;
426 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
427 l2_select_low_bit, l2_select_num_bits, clusterID));
428 DPRINTF(RubySlicc, "address: %#x, destination: %s\n",
429 address, out_msg.Destination);
430 out_msg.MessageSize := MessageSizeType:Control;
431 out_msg.AccessMode := in_msg.AccessMode;
432 }
433 }
434 }
435
436 action(d_sendDataToRequestor, "d", desc="send data to requestor") {
437 peek(requestNetwork_in, RequestMsg) {
438 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
439 assert(is_valid(cache_entry));
440 out_msg.addr := address;
441 out_msg.Type := CoherenceResponseType:DATA;
442 out_msg.DataBlk := cache_entry.DataBlk;
443 out_msg.Dirty := cache_entry.Dirty;
444 out_msg.Sender := machineID;
445 out_msg.Destination.add(in_msg.Requestor);
446 out_msg.MessageSize := MessageSizeType:Response_Data;
447 }
448 }
449 }
450
451 action(d2_sendDataToL2, "d2", desc="send data to the L2 cache because of M downgrade") {
452 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
453 assert(is_valid(cache_entry));
454 out_msg.addr := address;
455 out_msg.Type := CoherenceResponseType:DATA;
456 out_msg.DataBlk := cache_entry.DataBlk;
457 out_msg.Dirty := cache_entry.Dirty;
458 out_msg.Sender := machineID;
459 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
460 l2_select_low_bit, l2_select_num_bits, clusterID));
461 out_msg.MessageSize := MessageSizeType:Response_Data;
462 }
463 }
464
465 action(dt_sendDataToRequestor_fromTBE, "dt", desc="send data to requestor") {
466 peek(requestNetwork_in, RequestMsg) {
467 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
468 assert(is_valid(tbe));
469 out_msg.addr := address;
470 out_msg.Type := CoherenceResponseType:DATA;
471 out_msg.DataBlk := tbe.DataBlk;
472 out_msg.Dirty := tbe.Dirty;
473 out_msg.Sender := machineID;
474 out_msg.Destination.add(in_msg.Requestor);
475 out_msg.MessageSize := MessageSizeType:Response_Data;
476 }
477 }
478 }
479
480 action(d2t_sendDataToL2_fromTBE, "d2t", desc="send data to the L2 cache") {
481 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
482 assert(is_valid(tbe));
483 out_msg.addr := address;
484 out_msg.Type := CoherenceResponseType:DATA;
485 out_msg.DataBlk := tbe.DataBlk;
486 out_msg.Dirty := tbe.Dirty;
487 out_msg.Sender := machineID;
488 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
489 l2_select_low_bit, l2_select_num_bits, clusterID));
490 out_msg.MessageSize := MessageSizeType:Response_Data;
491 }
492 }
493
494 action(e_sendAckToRequestor, "e", desc="send invalidate ack to requestor (could be L2 or L1)") {
495 peek(requestNetwork_in, RequestMsg) {
496 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
497 out_msg.addr := address;
498 out_msg.Type := CoherenceResponseType:ACK;
499 out_msg.Sender := machineID;
500 out_msg.Destination.add(in_msg.Requestor);
501 out_msg.MessageSize := MessageSizeType:Response_Control;
502 }
503 }
504 }
505
506 action(f_sendDataToL2, "f", desc="send data to the L2 cache") {
507 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
508 assert(is_valid(cache_entry));
509 out_msg.addr := address;
510 out_msg.Type := CoherenceResponseType:DATA;
511 out_msg.DataBlk := cache_entry.DataBlk;
512 out_msg.Dirty := cache_entry.Dirty;
513 out_msg.Sender := machineID;
514 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
515 l2_select_low_bit, l2_select_num_bits, clusterID));
516 out_msg.MessageSize := MessageSizeType:Writeback_Data;
517 }
518 }
519
520 action(ft_sendDataToL2_fromTBE, "ft", desc="send data to the L2 cache") {
521 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
522 assert(is_valid(tbe));
523 out_msg.addr := address;
524 out_msg.Type := CoherenceResponseType:DATA;
525 out_msg.DataBlk := tbe.DataBlk;
526 out_msg.Dirty := tbe.Dirty;
527 out_msg.Sender := machineID;
528 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
529 l2_select_low_bit, l2_select_num_bits, clusterID));
530 out_msg.MessageSize := MessageSizeType:Writeback_Data;
531 }
532 }
533
534 action(fi_sendInvAck, "fi", desc="send data to the L2 cache") {
535 peek(requestNetwork_in, RequestMsg) {
536 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
537 out_msg.addr := address;
538 out_msg.Type := CoherenceResponseType:ACK;
539 out_msg.Sender := machineID;
540 out_msg.Destination.add(in_msg.Requestor);
541 out_msg.MessageSize := MessageSizeType:Response_Control;
542 out_msg.AckCount := 1;
543 }
544 }
545 }
546
547 action(forward_eviction_to_L0, "\cc", desc="sends eviction information to the processor") {
548 enqueue(bufferToL0_out, CoherenceMsg, l1_request_latency) {
549 out_msg.addr := address;
550 out_msg.Class := CoherenceClass:INV;
551 out_msg.Sender := machineID;
552 out_msg.Dest := createMachineID(MachineType:L0Cache, version);
553 out_msg.MessageSize := MessageSizeType:Control;
554 }
555 }
556
557 action(g_issuePUTX, "g", desc="send data to the L2 cache") {
558 enqueue(requestNetwork_out, RequestMsg, l1_response_latency) {
559 assert(is_valid(cache_entry));
560 out_msg.addr := address;
561 out_msg.Type := CoherenceRequestType:PUTX;
562 out_msg.Dirty := cache_entry.Dirty;
563 out_msg.Requestor:= machineID;
564 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
565 l2_select_low_bit, l2_select_num_bits, clusterID));
566 if (cache_entry.Dirty) {
567 out_msg.MessageSize := MessageSizeType:Writeback_Data;
568 out_msg.DataBlk := cache_entry.DataBlk;
569 } else {
570 out_msg.MessageSize := MessageSizeType:Writeback_Control;
571 }
572 }
573 }
574
575 action(j_sendUnblock, "j", desc="send unblock to the L2 cache") {
576 enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) {
577 out_msg.addr := address;
578 out_msg.Type := CoherenceResponseType:UNBLOCK;
579 out_msg.Sender := machineID;
580 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
581 l2_select_low_bit, l2_select_num_bits, clusterID));
582 out_msg.MessageSize := MessageSizeType:Response_Control;
583 DPRINTF(RubySlicc, "%#x\n", address);
584 }
585 }
586
587 action(jj_sendExclusiveUnblock, "\j", desc="send unblock to the L2 cache") {
588 enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) {
589 out_msg.addr := address;
590 out_msg.Type := CoherenceResponseType:EXCLUSIVE_UNBLOCK;
591 out_msg.Sender := machineID;
592 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
593 l2_select_low_bit, l2_select_num_bits, clusterID));
594 out_msg.MessageSize := MessageSizeType:Response_Control;
595 DPRINTF(RubySlicc, "%#x\n", address);
596
597 }
598 }
599
600 action(h_data_to_l0, "h", desc="If not prefetch, send data to the L0 cache.") {
601 enqueue(bufferToL0_out, CoherenceMsg, l1_response_latency) {
602 assert(is_valid(cache_entry));
603
604 out_msg.addr := address;
605 out_msg.Class := CoherenceClass:DATA;
606 out_msg.Sender := machineID;
607 out_msg.Dest := createMachineID(MachineType:L0Cache, version);
608 out_msg.DataBlk := cache_entry.DataBlk;
609 out_msg.MessageSize := MessageSizeType:Response_Data;
610 }
611 }
612
613 action(hh_xdata_to_l0, "\h", desc="If not prefetch, notify sequencer that store completed.") {
614 enqueue(bufferToL0_out, CoherenceMsg, l1_response_latency) {
615 assert(is_valid(cache_entry));
616
617 out_msg.addr := address;
618 out_msg.Class := CoherenceClass:DATA_EXCLUSIVE;
619 out_msg.Sender := machineID;
620 out_msg.Dest := createMachineID(MachineType:L0Cache, version);
621 out_msg.DataBlk := cache_entry.DataBlk;
622 out_msg.Dirty := cache_entry.Dirty;
623 out_msg.MessageSize := MessageSizeType:Response_Data;
624
625 //cache_entry.Dirty := true;
626 }
627 }
628
629 action(i_allocateTBE, "i", desc="Allocate TBE (number of invalidates=0)") {
630 check_allocate(TBEs);
631 assert(is_valid(cache_entry));
632 TBEs.allocate(address);
633 set_tbe(TBEs[address]);
634 tbe.Dirty := cache_entry.Dirty;
635 tbe.DataBlk := cache_entry.DataBlk;
636 }
637
638 action(k_popL0RequestQueue, "k", desc="Pop mandatory queue.") {
639 messageBufferFromL0_in.dequeue(clockEdge());
640 }
641
642 action(l_popL2RequestQueue, "l",
643 desc="Pop incoming request queue and profile the delay within this virtual network") {
644 Tick delay := requestNetwork_in.dequeue(clockEdge());
645 profileMsgDelay(2, ticksToCycles(delay));
646 }
647
648 action(o_popL2ResponseQueue, "o",
649 desc="Pop Incoming Response queue and profile the delay within this virtual network") {
650 Tick delay := responseNetwork_in.dequeue(clockEdge());
651 profileMsgDelay(1, ticksToCycles(delay));
652 }
653
654 action(s_deallocateTBE, "s", desc="Deallocate TBE") {
655 TBEs.deallocate(address);
656 unset_tbe();
657 }
658
659 action(u_writeDataFromL0Request, "ureql0", desc="Write data to cache") {
660 peek(messageBufferFromL0_in, CoherenceMsg) {
661 assert(is_valid(cache_entry));
662 if (in_msg.Dirty) {
663 cache_entry.DataBlk := in_msg.DataBlk;
664 cache_entry.Dirty := in_msg.Dirty;
665 }
666 }
667 }
668
669 action(u_writeDataFromL2Response, "uresl2", desc="Write data to cache") {
670 peek(responseNetwork_in, ResponseMsg) {
671 assert(is_valid(cache_entry));
672 cache_entry.DataBlk := in_msg.DataBlk;
673 }
674 }
675
676 action(u_writeDataFromL0Response, "uresl0", desc="Write data to cache") {
677 peek(messageBufferFromL0_in, CoherenceMsg) {
678 assert(is_valid(cache_entry));
679 if (in_msg.Dirty) {
680 cache_entry.DataBlk := in_msg.DataBlk;
681 cache_entry.Dirty := in_msg.Dirty;
682 }
683 }
684 }
685
686 action(q_updateAckCount, "q", desc="Update ack count") {
687 peek(responseNetwork_in, ResponseMsg) {
688 assert(is_valid(tbe));
689 tbe.pendingAcks := tbe.pendingAcks - in_msg.AckCount;
690 APPEND_TRANSITION_COMMENT(in_msg.AckCount);
691 APPEND_TRANSITION_COMMENT(" p: ");
692 APPEND_TRANSITION_COMMENT(tbe.pendingAcks);
693 }
694 }
695
696 action(ff_deallocateCacheBlock, "\f",
697 desc="Deallocate L1 cache block.") {
698 if (cache.isTagPresent(address)) {
699 cache.deallocate(address);
700 }
701 unset_cache_entry();
702 }
703
704 action(oo_allocateCacheBlock, "\o", desc="Set cache tag equal to tag of block B.") {
705 if (is_invalid(cache_entry)) {
706 set_cache_entry(cache.allocate(address, new Entry));
707 }
708 }
709
710 action(z0_stallAndWaitL0Queue, "\z0", desc="recycle L0 request queue") {
711 stall_and_wait(messageBufferFromL0_in, address);
712 }
713
714 action(z2_stallAndWaitL2Queue, "\z2", desc="recycle L2 request queue") {
715 stall_and_wait(requestNetwork_in, address);
716 }
717
718 action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
719 wakeUpAllBuffers(address);
720 }
721
722 action(uu_profileMiss, "\um", desc="Profile the demand miss") {
723 ++cache.demand_misses;
724 }
725
726 action(uu_profileHit, "\uh", desc="Profile the demand hit") {
727 ++cache.demand_hits;
728 }
729
730
731 //*****************************************************
732 // TRANSITIONS
733 //*****************************************************
734
735 // Transitions for Load/Store/Replacement/WriteBack from transient states
736 transition({IS, IM, M_I, SM, SINK_WB_ACK, S_IL0, M_IL0, E_IL0, MM_IL0},
737 {Load, Store, L1_Replacement}) {
738 z0_stallAndWaitL0Queue;
739 }
740
741 transition(I, Load, IS) {
742 oo_allocateCacheBlock;
743 i_allocateTBE;
744 a_issueGETS;
745 uu_profileMiss;
746 k_popL0RequestQueue;
747 }
748
749 transition(I, Store, IM) {
750 oo_allocateCacheBlock;
751 i_allocateTBE;
752 b_issueGETX;
753 uu_profileMiss;
754 k_popL0RequestQueue;
755 }
756
757 transition(I, Inv) {
758 fi_sendInvAck;
759 l_popL2RequestQueue;
760 }
761
762 // Transitions from Shared
763 transition({S,SS}, Load, S) {
764 h_data_to_l0;
765 uu_profileHit;
766 k_popL0RequestQueue;
767 }
768
769 transition(EE, Load, E) {
770 hh_xdata_to_l0;
771 uu_profileHit;
772 k_popL0RequestQueue;
773 }
774
775 transition(MM, Load, M) {
776 hh_xdata_to_l0;
777 uu_profileHit;
778 k_popL0RequestQueue;
779 }
780
781 transition({S,SS}, Store, SM) {
782 i_allocateTBE;
783 c_issueUPGRADE;
784 uu_profileMiss;
785 k_popL0RequestQueue;
786 }
787
788 transition(SS, L1_Replacement, I) {
789 ff_deallocateCacheBlock;
790 }
791
792 transition(S, {L0_Invalidate_Own, L0_Invalidate_Else}, S_IL0) {
793 forward_eviction_to_L0;
794 }
795
796 transition(SS, Inv, I) {
797 fi_sendInvAck;
798 ff_deallocateCacheBlock;
799 l_popL2RequestQueue;
800 }
801
802 // Transitions from Exclusive
803
804 transition({EE,MM}, Store, M) {
805 hh_xdata_to_l0;
806 uu_profileHit;
807 k_popL0RequestQueue;
808 }
809
810 transition(EE, L1_Replacement, M_I) {
811 // silent E replacement??
812 i_allocateTBE;
813 g_issuePUTX; // send data, but hold in case forwarded request
814 ff_deallocateCacheBlock;
815 }
816
817 transition(EE, Inv, I) {
818 // don't send data
819 fi_sendInvAck;
820 ff_deallocateCacheBlock;
821 l_popL2RequestQueue;
822 }
823
824 transition(EE, Fwd_GETX, I) {
825 d_sendDataToRequestor;
826 ff_deallocateCacheBlock;
827 l_popL2RequestQueue;
828 }
829
830 transition(EE, Fwd_GETS, SS) {
831 d_sendDataToRequestor;
832 d2_sendDataToL2;
833 l_popL2RequestQueue;
834 }
835
836 transition(E, {L0_Invalidate_Own, L0_Invalidate_Else}, E_IL0) {
837 forward_eviction_to_L0;
838 }
839
840 // Transitions from Modified
841 transition(MM, L1_Replacement, M_I) {
842 i_allocateTBE;
843 g_issuePUTX; // send data, but hold in case forwarded request
844 ff_deallocateCacheBlock;
845 }
846
847 transition({M,E}, WriteBack, MM) {
848 u_writeDataFromL0Request;
849 k_popL0RequestQueue;
850 }
851
852 transition(M_I, WB_Ack, I) {
853 s_deallocateTBE;
854 o_popL2ResponseQueue;
855 ff_deallocateCacheBlock;
856 kd_wakeUpDependents;
857 }
858
859 transition(MM, Inv, I) {
860 f_sendDataToL2;
861 ff_deallocateCacheBlock;
862 l_popL2RequestQueue;
863 }
864
865 transition(M_I, Inv, SINK_WB_ACK) {
866 ft_sendDataToL2_fromTBE;
867 l_popL2RequestQueue;
868 }
869
870 transition(MM, Fwd_GETX, I) {
871 d_sendDataToRequestor;
872 ff_deallocateCacheBlock;
873 l_popL2RequestQueue;
874 }
875
876 transition(MM, Fwd_GETS, SS) {
877 d_sendDataToRequestor;
878 d2_sendDataToL2;
879 l_popL2RequestQueue;
880 }
881
882 transition(M, {L0_Invalidate_Own, L0_Invalidate_Else}, M_IL0) {
883 forward_eviction_to_L0;
884 }
885
886 transition(M_I, Fwd_GETX, SINK_WB_ACK) {
887 dt_sendDataToRequestor_fromTBE;
888 l_popL2RequestQueue;
889 }
890
891 transition(M_I, Fwd_GETS, SINK_WB_ACK) {
892 dt_sendDataToRequestor_fromTBE;
893 d2t_sendDataToL2_fromTBE;
894 l_popL2RequestQueue;
895 }
896
897 // Transitions from IS
898 transition(IS, Data_all_Acks, S) {
899 u_writeDataFromL2Response;
900 h_data_to_l0;
901 s_deallocateTBE;
902 o_popL2ResponseQueue;
903 kd_wakeUpDependents;
904 }
905
906 transition(IS, DataS_fromL1, S) {
907 u_writeDataFromL2Response;
908 j_sendUnblock;
909 h_data_to_l0;
910 s_deallocateTBE;
911 o_popL2ResponseQueue;
912 kd_wakeUpDependents;
913 }
914
915 // directory is blocked when sending exclusive data
916 transition(IS, Data_Exclusive, E) {
917 u_writeDataFromL2Response;
918 hh_xdata_to_l0;
919 jj_sendExclusiveUnblock;
920 s_deallocateTBE;
921 o_popL2ResponseQueue;
922 kd_wakeUpDependents;
923 }
924
925 // Transitions from IM
926 transition({IM,SM}, Inv, IM) {
927 fi_sendInvAck;
928 l_popL2RequestQueue;
929 }
930
931 transition(IM, Data, SM) {
932 u_writeDataFromL2Response;
933 q_updateAckCount;
934 o_popL2ResponseQueue;
935 }
936
937 transition(IM, Data_all_Acks, M) {
938 u_writeDataFromL2Response;
939 hh_xdata_to_l0;
940 jj_sendExclusiveUnblock;
941 s_deallocateTBE;
942 o_popL2ResponseQueue;
943 kd_wakeUpDependents;
944 }
945
946 transition({SM, IM}, Ack) {
947 q_updateAckCount;
948 o_popL2ResponseQueue;
949 }
950
951 transition(SM, Ack_all, M) {
952 jj_sendExclusiveUnblock;
953 hh_xdata_to_l0;
954 s_deallocateTBE;
955 o_popL2ResponseQueue;
956 kd_wakeUpDependents;
957 }
958
959 transition(SM, L0_Invalidate_Else, SM_IL0) {
960 forward_eviction_to_L0;
961 }
962
963 transition(SINK_WB_ACK, Inv){
964 fi_sendInvAck;
965 l_popL2RequestQueue;
966 }
967
968 transition(SINK_WB_ACK, WB_Ack, I){
969 s_deallocateTBE;
970 o_popL2ResponseQueue;
971 ff_deallocateCacheBlock;
972 kd_wakeUpDependents;
973 }
974
975 transition({M_IL0, E_IL0}, WriteBack, MM_IL0) {
976 u_writeDataFromL0Request;
977 k_popL0RequestQueue;
978 kd_wakeUpDependents;
979 }
980
981 transition({M_IL0, E_IL0}, L0_DataAck, MM) {
982 u_writeDataFromL0Response;
983 k_popL0RequestQueue;
984 kd_wakeUpDependents;
985 }
986
987 transition({M_IL0, MM_IL0}, L0_Ack, MM) {
988 k_popL0RequestQueue;
989 kd_wakeUpDependents;
990 }
991
992 transition(E_IL0, L0_Ack, EE) {
993 k_popL0RequestQueue;
994 kd_wakeUpDependents;
995 }
996
997 transition(S_IL0, L0_Ack, SS) {
998 k_popL0RequestQueue;
999 kd_wakeUpDependents;
1000 }
1001
1002 transition(SM_IL0, L0_Ack, IM) {
1003 k_popL0RequestQueue;
1004 kd_wakeUpDependents;
1005 }
1006
1007 transition({S_IL0, M_IL0, E_IL0, SM_IL0, SM}, L0_Invalidate_Own) {
1008 z0_stallAndWaitL0Queue;
1009 }
1010
1011 transition({S_IL0, M_IL0, E_IL0, SM_IL0}, L0_Invalidate_Else) {
1012 z2_stallAndWaitL2Queue;
1013 }
1014
1015 transition({IS, S_IL0, M_IL0, E_IL0, MM_IL0}, {Inv, Fwd_GETX, Fwd_GETS}) {
1016 z2_stallAndWaitL2Queue;
1017 }
1018 }