ruby: cleaning up RubyQueue and RubyNetwork dprintfs
[gem5.git] / src / mem / protocol / MSI_MOSI_CMP_directory-dir.sm
1
2 /*
3 * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * $Id$
32 */
33
34 machine(Directory, "MOSI Directory Optimized") {
35
36 // ** OUT QUEUES **
37 MessageBuffer dummyFrom0, network="To", virtual_network="0", ordered="false"; // dummy buffer that shouldn't be used
38 MessageBuffer dummyFrom1, network="To", virtual_network="1", ordered="false"; // dummy buffer that shouldn't be used
39 // Dir -> mod-L2 bank - Must be true for the 'opt' and 'GS' protocols BE CAREFUL HERE!!!
40 MessageBuffer forwardedRequestFromDir, network="To", virtual_network="2", ordered="true";
41 MessageBuffer responseFromDir, network="To", virtual_network="3", ordered="false"; // Dir -> mod-L2 bank
42 MessageBuffer dummyFrom4, network="To", virtual_network="4", ordered="false"; // dummy buffer that shouldn't be used
43
44 // ** IN QUEUES **
45 MessageBuffer dummyTo0, network="From", virtual_network="0", ordered="false"; // dummy buffer that shouldn't be used
46 MessageBuffer requestToDir, network="From", virtual_network="1", ordered="false"; // a mod-L2 bank -> this Dir
47 MessageBuffer dummyTo2, network="From", virtual_network="2", ordered="false"; // dummy buffer that shouldn't be used
48 MessageBuffer dummyTo3, network="From", virtual_network="3", ordered="false"; // dummy buffer that shouldn't be used
49 MessageBuffer finalAckToDir, network="From", virtual_network="4", ordered="false"; // a mod-L2 bank -> this Dir
50
51 // STATES
52 enumeration(State, desc="Directory states", default="Directory_State_NP") {
53 // Base states
54 NP, desc="Not present";
55 I, desc="Idle";
56 S, desc="Shared";
57 O, desc="Owned";
58 M, desc="Modified", format="!b";
59 OO, desc="transient state of O->GetS/GetInstr->O";
60 OM, desc="transient state of O->GetX->M";
61 MO, desc="transient state of M->GetS/GetInstr->O";
62 MM, desc="transient state of M->GetX->M";
63 }
64
65 // Events
66 enumeration(Event, desc="Directory events") {
67 GETS, desc="A GETS arrives";
68 GET_INSTR, desc="";
69 GETX_Owner, desc="A GETX arrives, requestor is owner";
70 GETX_NotOwner, desc="A GETX arrives, requestor is not owner";
71 PUTX_Owner, "PUTX (requestor is owner)", desc="A PUTX arrives, requestor is owner";
72 PUTX_NotOwner, "PUTX (requestor not owner)",desc="A PUTX arrives, requestor is not owner";
73 FinalAck, desc="";
74 }
75
76 // TYPES
77
78 // DirectoryEntry
79 structure(Entry, desc="...") {
80 State DirectoryState, desc="Directory state";
81 Set Sharers, desc="Set of sharers - must be L2 caches"; // Note this is a Set and not a NetDest for space concerns
82 bool DirOwner, default="true", desc="Is dir owner?";
83 NodeID ProcOwner, default="0", desc="Processor owner"; // Note this is an int for space concerns
84 DataBlock DataBlk, desc="data for the block";
85 }
86
87 external_type(DirectoryMemory) {
88 Entry lookup(Address);
89 bool isPresent(Address);
90 }
91
92 // ** OBJECTS **
93
94 DirectoryMemory directory, constructor_hack="i";
95
96 State getState(Address addr) {
97 if (directory.isPresent(addr)) {
98 return directory[addr].DirectoryState;
99 }
100 return State:NP;
101 }
102
103 std::string getDirStateStr(Address addr) {
104 return Directory_State_to_string(getState(addr));
105 }
106
107 std::string getRequestTypeStr(CoherenceRequestType type) {
108 return CoherenceRequestType_to_string(type);
109 }
110
111 void setState(Address addr, State state) {
112 if (directory.isPresent(addr)) {
113 DEBUG_EXPR(addr);
114 DEBUG_EXPR(directory[addr].DirectoryState);
115 directory[addr].DirectoryState := state;
116 DEBUG_EXPR(directory[addr].DirectoryState);
117 DEBUG_EXPR(state);
118 }
119 }
120
121 // ** OUT_PORTS **
122 out_port(forwardedRequestNetwork_out, RequestMsg, forwardedRequestFromDir);
123 out_port(responseNetwork_out, ResponseMsg, responseFromDir);
124 out_port(ownRequestQueue_out, RequestMsg, requestToDir);
125
126 // ** IN_PORTS **
127 in_port(dummyTo0_in, RequestMsg, dummyTo0) {
128 if (dummyTo0_in.isReady()) {
129 peek(dummyTo0_in, RequestMsg) {
130 DEBUG_EXPR(in_msg.Address);
131 DEBUG_EXPR(id);
132 DEBUG_EXPR(in_msg.Type);
133 DEBUG_EXPR(getState(in_msg.Address));
134 DEBUG_EXPR(in_msg.RequestorMachId);
135 }
136 error("dummyTo0 port should not be used");
137 }
138 }
139 in_port(dummyTo2_in, RequestMsg, dummyTo2) {
140 if (dummyTo2_in.isReady()) {
141 peek(dummyTo2_in, RequestMsg) {
142 DEBUG_EXPR(in_msg.Address);
143 DEBUG_EXPR(id);
144 DEBUG_EXPR(in_msg.Type);
145 DEBUG_EXPR(getState(in_msg.Address));
146 DEBUG_EXPR(in_msg.RequestorMachId);
147 }
148 error("dummyTo2 port should not be used");
149 }
150 }
151
152 in_port(dummyTo3_in, RequestMsg, dummyTo3) {
153 if (dummyTo3_in.isReady()) {
154 peek(dummyTo3_in, RequestMsg) {
155 DEBUG_EXPR(in_msg.Address);
156 DEBUG_EXPR(id);
157 DEBUG_EXPR(in_msg.Type);
158 DEBUG_EXPR(getState(in_msg.Address));
159 DEBUG_EXPR(in_msg.RequestorMachId);
160 }
161 error("dummyTo3 port should not be used");
162 }
163 }
164
165 in_port(finalAckNetwork_in, ResponseMsg, finalAckToDir){
166 if(finalAckNetwork_in.isReady()){
167 peek(finalAckNetwork_in, ResponseMsg){
168 assert(in_msg.Destination.isElement(machineID));
169 if(in_msg.Type == CoherenceResponseType:FINALACK){
170 trigger(Event:FinalAck, in_msg.Address);
171 } else {
172 error("Invalid message");
173 }
174 }
175 }
176 }
177
178 in_port(requestNetwork_in, RequestMsg, requestToDir) {
179 if (requestNetwork_in.isReady()) {
180 peek(requestNetwork_in, RequestMsg) {
181 assert(in_msg.Destination.isElement(machineID));
182 if (in_msg.Type == CoherenceRequestType:GETS) {
183 trigger(Event:GETS, in_msg.Address);
184 } else if (in_msg.Type == CoherenceRequestType:GET_INSTR) {
185 trigger(Event:GET_INSTR, in_msg.Address);
186 } else if (in_msg.Type == CoherenceRequestType:GETX) {
187 if(directory[in_msg.Address].DirOwner == false &&
188 L2CacheMachIDToChipID(in_msg.RequestorMachId) == directory[in_msg.Address].ProcOwner) {
189 trigger(Event:GETX_Owner, in_msg.Address);
190 } else {
191 trigger(Event:GETX_NotOwner, in_msg.Address);
192 }
193 } else if (in_msg.Type == CoherenceRequestType:PUTX) {
194 if (directory[in_msg.Address].DirOwner == false &&
195 L2CacheMachIDToChipID(in_msg.RequestorMachId) == directory[in_msg.Address].ProcOwner) {
196 trigger(Event:PUTX_Owner, in_msg.Address);
197 } else {
198 trigger(Event:PUTX_NotOwner, in_msg.Address);
199 }
200 } else {
201 error("Invalid message");
202 }
203 }
204 }
205 }
206
207
208 // Actions
209
210 // a_addRequestorToSharers
211
212 action(a_addRequestorToSharers, "a", desc="Add requestor to list of sharers") {
213 peek(requestNetwork_in, RequestMsg) {
214 directory[address].Sharers.add(L2CacheMachIDToChipID(in_msg.RequestorMachId));
215 DEBUG_EXPR(directory[address].Sharers);
216 }
217 }
218
219 // b_dataToRequestor
220
221 action(b_dataToRequestor, "b", desc="Send data to requestor") {
222 peek(requestNetwork_in, RequestMsg) {
223 enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
224 out_msg.Address := address;
225 out_msg.Type := CoherenceResponseType:DATA;
226 out_msg.SenderMachId := machineID;
227 if(in_msg.Type == CoherenceRequestType:GETX) {
228 DEBUG_EXPR(directory[address].Sharers);
229 DEBUG_EXPR(directory[address].Sharers.count());
230 out_msg.NumPendingExtAcks := directory[address].Sharers.count();
231 } else {
232 out_msg.NumPendingExtAcks := 0; // don't need to send pending ack count to GETS requestor
233 }
234 out_msg.Destination.add(in_msg.RequestorMachId);
235 out_msg.DataBlk := directory[address].DataBlk;
236 DEBUG_EXPR(out_msg.Address);
237 DEBUG_EXPR(out_msg.DataBlk);
238 DEBUG_EXPR(out_msg.NumPendingExtAcks);
239 DEBUG_EXPR(out_msg.Destination);
240 out_msg.MessageSize := MessageSizeType:Data;
241 }
242 }
243 }
244
245 // d_forwardRequestToOwner
246
247 action(d_forwardRequestToOwner, "d", desc="Forward request to owner") {
248 peek(requestNetwork_in, RequestMsg) {
249 enqueue(forwardedRequestNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
250 out_msg.Address := address;
251 out_msg.Type := in_msg.Type;
252 out_msg.RequestorMachId := in_msg.RequestorMachId;
253 out_msg.Destination.add(map_L2ChipId_to_L2Cache(out_msg.Address, directory[address].ProcOwner));
254 DEBUG_EXPR(out_msg.Destination);
255
256 if(in_msg.Type == CoherenceRequestType:GETX) {
257 out_msg.NumPendingExtAcks := directory[address].Sharers.count();
258 } else {
259 out_msg.NumPendingExtAcks := 0; // don't need to send pending ack count to GETS requestor
260 }
261 out_msg.MessageSize := MessageSizeType:Control;
262 DEBUG_EXPR(out_msg.Address);
263 DEBUG_EXPR(out_msg.NumPendingExtAcks);
264 DEBUG_EXPR(out_msg.Destination);
265 }
266 }
267 }
268
269 action(f_setOwnerToRequestor, "f", desc="Set owner equal to requestor") {
270 peek(requestNetwork_in, RequestMsg) {
271 directory[address].ProcOwner := L2CacheMachIDToChipID(in_msg.RequestorMachId);
272 directory[address].DirOwner := false;
273 }
274 DEBUG_EXPR(directory[address].ProcOwner);
275 }
276
277 action(g_clearSharers, "g", desc="Clear list of sharers") {
278 directory[address].Sharers.clear();
279 }
280
281 // currently done via multicast message
282
283 action(h_invToSharers, "h", desc="Send INVs to all sharers") {
284 peek(requestNetwork_in, RequestMsg) {
285 DEBUG_EXPR(directory[address].Sharers.count());
286 if(directory[address].Sharers.count() != 0){
287 enqueue(forwardedRequestNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
288 out_msg.Address := address;
289 out_msg.Type := CoherenceRequestType:INV;
290 out_msg.RequestorMachId := in_msg.RequestorMachId;
291 DEBUG_EXPR(directory[address].Sharers);
292 out_msg.Destination := getMultiStaticL2BankNetDest(address, directory[address].Sharers);
293 out_msg.MessageSize := MessageSizeType:Control;
294 }
295 }
296 }
297 DEBUG_EXPR(directory[address].Sharers);
298 }
299
300 action(j_popIncomingRequestQueue, "j", desc="Pop incoming request queue") {
301 profileMsgDelay(1, requestNetwork_in.dequeue_getDelayCycles());
302 }
303
304 action(l_writeRequestDataToMemory, "l", desc="Write PUTX/DWN data to memory") {
305 peek(requestNetwork_in, RequestMsg) {
306 directory[in_msg.Address].DataBlk := in_msg.DataBlk;
307 DEBUG_EXPR(in_msg.Address);
308 DEBUG_EXPR(in_msg.DataBlk);
309 }
310 }
311
312 action(n_writebackAckToRequestor, "n", desc="Send WB_ack to requestor") {
313 peek(requestNetwork_in, RequestMsg) {
314 // This needs to be DIRECTORY_LATENCY to keep the queue fifo
315 enqueue(forwardedRequestNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
316 out_msg.Address := address;
317 out_msg.Type := CoherenceRequestType:WB_ACK;
318 out_msg.RequestorMachId := machineID;
319 out_msg.Destination.add(in_msg.RequestorMachId);
320 out_msg.MessageSize := MessageSizeType:Control;
321 }
322 }
323 }
324
325 action(m_forwardExclusiveRequestToOwner, "m", desc="Send EXE_ack to requestor") {
326 peek(requestNetwork_in, RequestMsg) {
327 // This needs to be DIRECTORY_LATENCY to keep the queue fifo
328 enqueue(forwardedRequestNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
329 out_msg.Address := address;
330 out_msg.Type := CoherenceRequestType:EXE_ACK;
331 out_msg.RequestorMachId := machineID;
332 out_msg.Destination.add(in_msg.RequestorMachId);
333 out_msg.MessageSize := MessageSizeType:Control;
334 }
335 }
336 }
337
338 action(uu_profile, "u/", desc="Profile this transition.") {
339 peek(requestNetwork_in, RequestMsg) {
340 profile_request(in_msg.L1CacheStateStr, in_msg.L2CacheStateStr, getDirStateStr(address), getRequestTypeStr(in_msg.Type));
341 }
342 }
343
344 action(p_clearOwner, "p", desc="Clear owner") {
345 directory[address].DirOwner := true; // set owner equal to dir
346 }
347
348 action(r_addOwnerToSharers, "r", desc="Add owner to list of sharers") {
349 DEBUG_EXPR(directory[address].ProcOwner);
350 directory[address].Sharers.add(directory[address].ProcOwner);
351 DEBUG_EXPR(directory[address].Sharers);
352 }
353
354 action(t_removeOwnerFromSharers, "t", desc="Remove owner from list of sharers") {
355 DEBUG_EXPR(directory[address].ProcOwner);
356 directory[address].Sharers.remove(directory[address].ProcOwner);
357 DEBUG_EXPR(directory[address].Sharers);
358 }
359
360 action(u_removeRequestorFromSharers, "u", desc="Remove requestor from list of sharers") {
361 peek(requestNetwork_in, RequestMsg) {
362 DEBUG_EXPR(in_msg.RequestorMachId);
363 directory[address].Sharers.remove(L2CacheMachIDToChipID(in_msg.RequestorMachId));
364 DEBUG_EXPR(directory[address].Sharers);
365 }
366 }
367
368 action(x_recycleRequest, "x", desc=""){
369 peek(requestNetwork_in, RequestMsg) {
370 enqueue(ownRequestQueue_out, RequestMsg, latency="RECYCLE_LATENCY"){
371 out_msg := in_msg;
372 }
373 }
374 }
375
376 action(hh_popFinalAckQueue, "\h", desc=""){
377 profileMsgDelay(4, finalAckNetwork_in.dequeue_getDelayCycles());
378 }
379
380 //action(z_stall, "z", desc=""){
381 //}
382
383 // TRANSITIONS
384
385 transition({OM,MM}, FinalAck, M){
386 hh_popFinalAckQueue;
387 }
388 transition({OO,MO}, FinalAck, O){
389 hh_popFinalAckQueue;
390 }
391
392 transition({OO, OM, MO, MM}, {GETS, GET_INSTR, GETX_Owner, GETX_NotOwner, PUTX_Owner}){
393 x_recycleRequest;
394 j_popIncomingRequestQueue;
395 // z_stall;
396 }
397
398 // ---------------------------
399
400 transition({NP, I, S, M, O, OO, OM, MO, MM}, PUTX_NotOwner) {
401 uu_profile;
402 n_writebackAckToRequestor;
403 j_popIncomingRequestQueue;
404 }
405
406 // Transitions from Idle
407 transition({NP,I}, {GETS,GET_INSTR}, S) {
408 uu_profile;
409 a_addRequestorToSharers;
410 b_dataToRequestor;
411 j_popIncomingRequestQueue;
412 }
413
414 transition({NP,I}, GETX_NotOwner, M) {
415 uu_profile;
416 f_setOwnerToRequestor;
417 b_dataToRequestor;
418 j_popIncomingRequestQueue;
419 }
420
421 // Transitions from Shared
422 transition(S, {GETS,GET_INSTR}) {
423 uu_profile;
424 a_addRequestorToSharers;
425 b_dataToRequestor;
426 j_popIncomingRequestQueue;
427 }
428
429 transition(S, GETX_NotOwner, M) {
430 uu_profile;
431 u_removeRequestorFromSharers;
432 b_dataToRequestor;
433 f_setOwnerToRequestor;
434 h_invToSharers;
435 g_clearSharers;
436 j_popIncomingRequestQueue;
437 }
438
439 // Transitions from Owned
440 transition(O, {GETS,GET_INSTR}, OO) {
441 uu_profile;
442 a_addRequestorToSharers;
443 d_forwardRequestToOwner;
444 j_popIncomingRequestQueue;
445 }
446
447 transition(O, {GETX_NotOwner, GETX_Owner}, OM) {
448 uu_profile;
449 u_removeRequestorFromSharers;
450 t_removeOwnerFromSharers;
451 d_forwardRequestToOwner;
452 f_setOwnerToRequestor;
453 h_invToSharers;
454 g_clearSharers;
455 j_popIncomingRequestQueue;
456 }
457
458 transition(O, PUTX_Owner, S) {
459 uu_profile;
460 u_removeRequestorFromSharers;
461 l_writeRequestDataToMemory;
462 n_writebackAckToRequestor;
463 p_clearOwner;
464 j_popIncomingRequestQueue;
465 }
466
467
468 // Transitions from Modified
469 transition(M, {GETS,GET_INSTR}, MO) {
470 uu_profile;
471 a_addRequestorToSharers;
472 r_addOwnerToSharers;
473 d_forwardRequestToOwner;
474 j_popIncomingRequestQueue;
475 }
476
477 transition(M, GETX_NotOwner, MM) {
478 uu_profile;
479 d_forwardRequestToOwner;
480 f_setOwnerToRequestor;
481 j_popIncomingRequestQueue;
482 }
483
484 transition(M, GETX_Owner) {
485 uu_profile;
486 m_forwardExclusiveRequestToOwner;
487 j_popIncomingRequestQueue;
488 }
489
490 transition(M, PUTX_Owner, I) {
491 uu_profile;
492 l_writeRequestDataToMemory;
493 n_writebackAckToRequestor;
494 p_clearOwner;
495 j_popIncomingRequestQueue;
496 }
497 }