2 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood
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.
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.
29 machine(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;
36 // Message Buffers between the L1 and the L0 Cache
37 // From the L1 cache to the L0 cache
38 MessageBuffer * bufferToL0, network="To";
40 // From the L0 cache to the L1 cache
41 MessageBuffer * bufferFromL0, network="From";
43 // Message queue from this L1 cache TO the network / L2
44 MessageBuffer * requestToL2, network="To", virtual_network="0",
47 MessageBuffer * responseToL2, network="To", virtual_network="1",
49 MessageBuffer * unblockToL2, network="To", virtual_network="2",
52 // To this L1 cache FROM the network / L2
53 MessageBuffer * requestFromL2, network="From", virtual_network="2",
55 MessageBuffer * responseFromL2, network="From", virtual_network="1",
60 state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
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";
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";
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;
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";
94 // Responses from the L0 Cache
95 // L0 cache received the invalidation message
96 // and has sent the data.
99 Inv, desc="Invalidate request from L2 bank";
101 // internal generated request
102 // Invalidate the line in L0 due to own requirements
104 // Invalidate the line in L0 due to some other cache's requirements
106 // Invalidate the line in the cache due to some one else / space needs.
110 Fwd_GETX, desc="GETX from other processor";
111 Fwd_GETS, desc="GETS from other processor";
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";
118 L0_Ack, desc="Ack for processor";
119 Ack, desc="Ack for processor";
120 Ack_all, desc="Last ack for processor";
122 WB_Ack, desc="Ack for replacement";
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";
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";
143 structure(TBETable, external="yes") {
146 void deallocate(Addr);
147 bool isPresent(Addr);
150 TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs";
152 int l2_select_low_bit, default="RubySystem::getBlockSizeBits()";
155 Cycles ticksToCycles(Tick t);
156 void set_cache_entry(AbstractCacheEntry a);
157 void unset_cache_entry();
160 void wakeUpBuffers(Addr a);
161 void wakeUpAllBuffers(Addr a);
162 void profileMsgDelay(int virtualNetworkType, Cycles c);
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]);
170 State getState(TBE tbe, Entry cache_entry, Addr addr) {
173 } else if (is_valid(cache_entry)) {
174 return cache_entry.CacheState;
179 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
182 tbe.TBEState := state;
185 if (is_valid(cache_entry)) {
186 cache_entry.CacheState := state;
190 AccessPermission getAccessPermission(Addr addr) {
191 TBE tbe := TBEs[addr];
193 DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(tbe.TBEState));
194 return L1Cache_State_to_permission(tbe.TBEState);
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);
203 DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent);
204 return AccessPermission:NotPresent;
207 void functionalRead(Addr addr, Packet *pkt) {
208 TBE tbe := TBEs[addr];
210 testAndRead(addr, tbe.DataBlk, pkt);
212 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
216 int functionalWrite(Addr addr, Packet *pkt) {
217 int num_functional_writes := 0;
219 TBE tbe := TBEs[addr];
221 num_functional_writes := num_functional_writes +
222 testAndWrite(addr, tbe.DataBlk, pkt);
223 return num_functional_writes;
226 num_functional_writes := num_functional_writes +
227 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
228 return num_functional_writes;
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));
237 Event mandatory_request_type_to_event(CoherenceClass type) {
238 if (type == CoherenceClass:GETS) {
240 } else if ((type == CoherenceClass:GETX) ||
241 (type == CoherenceClass:UPGRADE)) {
243 } else if (type == CoherenceClass:PUTX) {
244 return Event:WriteBack;
246 error("Invalid RequestType");
250 int getPendingAcks(TBE tbe) {
251 return tbe.pendingAcks;
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) {
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);
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));
275 Entry cache_entry := getCacheEntry(in_msg.addr);
276 TBE tbe := TBEs[in_msg.addr];
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) {
284 trigger(Event:DataS_fromL1, in_msg.addr, cache_entry, tbe);
286 } else if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) {
287 trigger(Event:Data_all_Acks, in_msg.addr, cache_entry, tbe);
289 trigger(Event:Data, in_msg.addr, cache_entry, tbe);
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);
295 trigger(Event:Ack, in_msg.addr, cache_entry, tbe);
297 } else if (in_msg.Type == CoherenceResponseType:WB_ACK) {
298 trigger(Event:WB_Ack, in_msg.addr, cache_entry, tbe);
300 error("Invalid L1 response type");
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];
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,
319 trigger(Event:Inv, in_msg.addr, cache_entry, tbe);
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,
327 trigger(Event:Fwd_GETX, in_msg.addr, cache_entry, tbe);
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,
334 trigger(Event:Fwd_GETS, in_msg.addr, cache_entry, tbe);
337 error("Invalid forwarded request type");
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];
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);
355 if (is_valid(cache_entry)) {
356 trigger(mandatory_request_type_to_event(in_msg.Class),
357 in_msg.addr, cache_entry, tbe);
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);
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)];
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);
375 trigger(Event:L1_Replacement,
376 cache.cacheProbe(in_msg.addr),
377 victim_entry, victim_tbe);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
570 out_msg.MessageSize := MessageSizeType:Writeback_Control;
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);
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);
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));
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;
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));
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;
625 //cache_entry.Dirty := true;
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;
638 action(k_popL0RequestQueue, "k", desc="Pop mandatory queue.") {
639 messageBufferFromL0_in.dequeue(clockEdge());
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));
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));
654 action(s_deallocateTBE, "s", desc="Deallocate TBE") {
655 TBEs.deallocate(address);
659 action(u_writeDataFromL0Request, "ureql0", desc="Write data to cache") {
660 peek(messageBufferFromL0_in, CoherenceMsg) {
661 assert(is_valid(cache_entry));
663 cache_entry.DataBlk := in_msg.DataBlk;
664 cache_entry.Dirty := in_msg.Dirty;
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;
676 action(u_writeDataFromL0Response, "uresl0", desc="Write data to cache") {
677 peek(messageBufferFromL0_in, CoherenceMsg) {
678 assert(is_valid(cache_entry));
680 cache_entry.DataBlk := in_msg.DataBlk;
681 cache_entry.Dirty := in_msg.Dirty;
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);
696 action(ff_deallocateCacheBlock, "\f",
697 desc="Deallocate L1 cache block.") {
698 if (cache.isTagPresent(address)) {
699 cache.deallocate(address);
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));
710 action(z0_stallAndWaitL0Queue, "\z0", desc="recycle L0 request queue") {
711 stall_and_wait(messageBufferFromL0_in, address);
714 action(z2_stallAndWaitL2Queue, "\z2", desc="recycle L2 request queue") {
715 stall_and_wait(requestNetwork_in, address);
718 action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
719 wakeUpAllBuffers(address);
722 action(uu_profileMiss, "\um", desc="Profile the demand miss") {
723 ++cache.demand_misses;
726 action(uu_profileHit, "\uh", desc="Profile the demand hit") {
731 //*****************************************************
733 //*****************************************************
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;
741 transition(I, Load, IS) {
742 oo_allocateCacheBlock;
749 transition(I, Store, IM) {
750 oo_allocateCacheBlock;
762 // Transitions from Shared
763 transition({S,SS}, Load, S) {
769 transition(EE, Load, E) {
775 transition(MM, Load, M) {
781 transition({S,SS}, Store, SM) {
788 transition(SS, L1_Replacement, I) {
789 ff_deallocateCacheBlock;
792 transition(S, {L0_Invalidate_Own, L0_Invalidate_Else}, S_IL0) {
793 forward_eviction_to_L0;
796 transition(SS, Inv, I) {
798 ff_deallocateCacheBlock;
802 // Transitions from Exclusive
804 transition({EE,MM}, Store, M) {
810 transition(EE, L1_Replacement, M_I) {
811 // silent E replacement??
813 g_issuePUTX; // send data, but hold in case forwarded request
814 ff_deallocateCacheBlock;
817 transition(EE, Inv, I) {
820 ff_deallocateCacheBlock;
824 transition(EE, Fwd_GETX, I) {
825 d_sendDataToRequestor;
826 ff_deallocateCacheBlock;
830 transition(EE, Fwd_GETS, SS) {
831 d_sendDataToRequestor;
836 transition(E, {L0_Invalidate_Own, L0_Invalidate_Else}, E_IL0) {
837 forward_eviction_to_L0;
840 // Transitions from Modified
841 transition(MM, L1_Replacement, M_I) {
843 g_issuePUTX; // send data, but hold in case forwarded request
844 ff_deallocateCacheBlock;
847 transition({M,E}, WriteBack, MM) {
848 u_writeDataFromL0Request;
852 transition(M_I, WB_Ack, I) {
854 o_popL2ResponseQueue;
855 ff_deallocateCacheBlock;
859 transition(MM, Inv, I) {
861 ff_deallocateCacheBlock;
865 transition(M_I, Inv, SINK_WB_ACK) {
866 ft_sendDataToL2_fromTBE;
870 transition(MM, Fwd_GETX, I) {
871 d_sendDataToRequestor;
872 ff_deallocateCacheBlock;
876 transition(MM, Fwd_GETS, SS) {
877 d_sendDataToRequestor;
882 transition(M, {L0_Invalidate_Own, L0_Invalidate_Else}, M_IL0) {
883 forward_eviction_to_L0;
886 transition(M_I, Fwd_GETX, SINK_WB_ACK) {
887 dt_sendDataToRequestor_fromTBE;
891 transition(M_I, Fwd_GETS, SINK_WB_ACK) {
892 dt_sendDataToRequestor_fromTBE;
893 d2t_sendDataToL2_fromTBE;
897 // Transitions from IS
898 transition(IS, Data_all_Acks, S) {
899 u_writeDataFromL2Response;
902 o_popL2ResponseQueue;
906 transition(IS, DataS_fromL1, S) {
907 u_writeDataFromL2Response;
911 o_popL2ResponseQueue;
915 // directory is blocked when sending exclusive data
916 transition(IS, Data_Exclusive, E) {
917 u_writeDataFromL2Response;
919 jj_sendExclusiveUnblock;
921 o_popL2ResponseQueue;
925 // Transitions from IM
926 transition({IM,SM}, Inv, IM) {
931 transition(IM, Data, SM) {
932 u_writeDataFromL2Response;
934 o_popL2ResponseQueue;
937 transition(IM, Data_all_Acks, M) {
938 u_writeDataFromL2Response;
940 jj_sendExclusiveUnblock;
942 o_popL2ResponseQueue;
946 transition({SM, IM}, Ack) {
948 o_popL2ResponseQueue;
951 transition(SM, Ack_all, M) {
952 jj_sendExclusiveUnblock;
955 o_popL2ResponseQueue;
959 transition(SM, L0_Invalidate_Else, SM_IL0) {
960 forward_eviction_to_L0;
963 transition(SINK_WB_ACK, Inv){
968 transition(SINK_WB_ACK, WB_Ack, I){
970 o_popL2ResponseQueue;
971 ff_deallocateCacheBlock;
975 transition({M_IL0, E_IL0}, WriteBack, MM_IL0) {
976 u_writeDataFromL0Request;
981 transition({M_IL0, E_IL0}, L0_DataAck, MM) {
982 u_writeDataFromL0Response;
987 transition({M_IL0, MM_IL0}, L0_Ack, MM) {
992 transition(E_IL0, L0_Ack, EE) {
997 transition(S_IL0, L0_Ack, SS) {
1002 transition(SM_IL0, L0_Ack, IM) {
1003 k_popL0RequestQueue;
1004 kd_wakeUpDependents;
1007 transition({S_IL0, M_IL0, E_IL0, SM_IL0, SM}, L0_Invalidate_Own) {
1008 z0_stallAndWaitL0Queue;
1011 transition({S_IL0, M_IL0, E_IL0, SM_IL0}, L0_Invalidate_Else) {
1012 z2_stallAndWaitL2Queue;
1015 transition({IS, S_IL0, M_IL0, E_IL0, MM_IL0}, {Inv, Fwd_GETX, Fwd_GETS}) {
1016 z2_stallAndWaitL2Queue;