ruby: cleaning up RubyQueue and RubyNetwork dprintfs
[gem5.git] / src / mem / protocol / MOSI_SMP_directory_1level-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: MOSI_directory-dir.sm 1.14 04/09/07 13:52:52-05:00 mikem@maya.cs.wisc.edu $
32 */
33
34 machine(Directory, "MOSI Directory Optimized") {
35
36
37 MessageBuffer forwardedRequestFromDir, network="To", virtual_network="1", ordered="true";
38 MessageBuffer responseFromDir, network="To", virtual_network="2", ordered="false";
39 MessageBuffer requestToDir, network="From", virtual_network="0", ordered="false";
40
41 // STATES
42 enumeration(State, desc="Directory states", default="Directory_State_I") {
43 // Base states
44 I, desc="Idle";
45 S, desc="Shared";
46 O, desc="Owned";
47 M, desc="Modified", format="!b";
48 }
49
50 // Events
51 enumeration(Event, desc="Directory events") {
52 GETS, desc="A GETS arrives";
53 GETX_Owner, desc="A GETX arrives, requestor is owner";
54 GETX_NotOwner, desc="A GETX arrives, requestor is not owner";
55 PUTX_Owner, "PUTX (requestor is owner)", desc="A PUTX arrives, requestor is owner";
56 PUTX_NotOwner, "PUTX (requestor not owner)",desc="A PUTX arrives, requestor is not owner";
57 }
58
59 // TYPES
60
61 // DirectoryEntry
62 structure(Entry, desc="...") {
63 State DirectoryState, desc="Directory state";
64 NetDest Sharers, desc="Set of sharers";
65 bool DirOwner, default="true", desc="Is dir owner?";
66 MachineID ProcOwner, desc="Processor owner";
67 DataBlock DataBlk, desc="data for the block";
68 }
69
70 external_type(DirectoryMemory) {
71 Entry lookup(Address);
72 bool isPresent(Address);
73 }
74
75 // ** OBJECTS **
76
77 DirectoryMemory directory, constructor_hack="i";
78
79 State getState(Address addr) {
80 if (directory.isPresent(addr)) {
81 return directory[addr].DirectoryState;
82 }
83 return State:I;
84 }
85
86 void setState(Address addr, State state) {
87 if (directory.isPresent(addr)) {
88 directory[addr].DirectoryState := state;
89 }
90 }
91
92 // ** OUT_PORTS **
93 out_port(forwardedRequestNetwork_out, RequestMsg, forwardedRequestFromDir);
94 out_port(responseNetwork_out, ResponseMsg, responseFromDir);
95
96 // ** IN_PORTS **
97
98 in_port(requestNetwork_in, RequestMsg, requestToDir) {
99 if (requestNetwork_in.isReady()) {
100 peek(requestNetwork_in, RequestMsg) {
101 if (in_msg.Type == CoherenceRequestType:GETS) {
102 trigger(Event:GETS, in_msg.Address);
103 } else if (in_msg.Type == CoherenceRequestType:GETX) {
104 if(directory[in_msg.Address].DirOwner == false && in_msg.Requestor == directory[in_msg.Address].ProcOwner) {
105 trigger(Event:GETX_Owner, in_msg.Address);
106 } else {
107 trigger(Event:GETX_NotOwner, in_msg.Address);
108 }
109 } else if (in_msg.Type == CoherenceRequestType:PUTX) {
110 if (directory[in_msg.Address].DirOwner == false && in_msg.Requestor == directory[in_msg.Address].ProcOwner) {
111 trigger(Event:PUTX_Owner, in_msg.Address);
112 } else {
113 trigger(Event:PUTX_NotOwner, in_msg.Address);
114 }
115 } else {
116 error("Invalid message");
117 }
118 }
119 }
120 }
121
122
123 // Actions
124
125 // a_addRequestorToSharers
126
127 action(a_addRequestorToSharers, "a", desc="Add requestor to list of sharers") {
128 peek(requestNetwork_in, RequestMsg) {
129 directory[address].Sharers.add(in_msg.Requestor);
130 DEBUG_EXPR(directory[address].Sharers);
131 }
132 }
133
134 // b_dataToRequestor
135
136 action(b_dataToRequestor, "b", desc="Send data to requestor") {
137 peek(requestNetwork_in, RequestMsg) {
138 enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
139 out_msg.Address := address;
140 out_msg.Type := CoherenceResponseType:DATA;
141 out_msg.Sender := machineID;
142 out_msg.SenderMachine := MachineType:Directory;
143 if(in_msg.Type == CoherenceRequestType:GETX) {
144 out_msg.NumPendingAcks := directory[address].Sharers.count();
145 } else {
146 out_msg.NumPendingAcks := 0; // don't need to send pending ack count to GETS requestor
147 }
148 out_msg.Destination.add(in_msg.Requestor);
149 out_msg.DestMachine := MachineType:L1Cache;
150 out_msg.DataBlk := directory[address].DataBlk;
151 DEBUG_EXPR(out_msg.NumPendingAcks);
152 DEBUG_EXPR(out_msg.Destination);
153 out_msg.MessageSize := MessageSizeType:Data;
154 }
155 }
156 }
157
158 // d_forwardRequestToOwner
159
160 action(d_forwardRequestToOwner, "d", desc="Forward request to owner") {
161 peek(requestNetwork_in, RequestMsg) {
162 enqueue(forwardedRequestNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
163 out_msg.Address := address;
164 out_msg.Type := in_msg.Type;
165 out_msg.Requestor := in_msg.Requestor;
166 out_msg.Destination.add(directory[address].ProcOwner);
167 DEBUG_EXPR(out_msg.Destination);
168
169 if(in_msg.Type == CoherenceRequestType:GETX) {
170 out_msg.NumPendingAcks := directory[address].Sharers.count();
171 } else {
172 out_msg.NumPendingAcks := 0; // don't need to send pending ack count to GETS requestor
173 }
174 out_msg.MessageSize := MessageSizeType:Control;
175 }
176 }
177 }
178
179 action(f_setOwnerToRequestor, "f", desc="Set owner equal to requestor") {
180 peek(requestNetwork_in, RequestMsg) {
181 directory[address].ProcOwner := in_msg.Requestor;
182 directory[address].DirOwner := false;
183 }
184 DEBUG_EXPR(directory[address].ProcOwner);
185 }
186
187 action(g_clearSharers, "g", desc="Clear list of sharers") {
188 directory[address].Sharers.clear();
189 }
190
191 // currently done via multicast message
192
193 action(h_invToSharers, "h", desc="Send INVs to all sharers") {
194 peek(requestNetwork_in, RequestMsg) {
195 if(directory[address].Sharers.count() != 0){
196 enqueue(forwardedRequestNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
197 out_msg.Address := address;
198 out_msg.Type := CoherenceRequestType:INV;
199 out_msg.Requestor := in_msg.Requestor;
200 out_msg.Destination := directory[address].Sharers;
201 out_msg.MessageSize := MessageSizeType:Control;
202 }
203 }
204 }
205 DEBUG_EXPR(directory[address].Sharers);
206 }
207
208 action(j_popIncomingRequestQueue, "j", desc="Pop incoming request queue") {
209 requestNetwork_in.dequeue();
210 }
211
212 action(l_writeRequestDataToMemory, "l", desc="Write PUTX/DWN data to memory") {
213 peek(requestNetwork_in, RequestMsg) {
214 directory[in_msg.Address].DataBlk := in_msg.DataBlk;
215 DEBUG_EXPR(in_msg.Address);
216 DEBUG_EXPR(in_msg.DataBlk);
217 }
218 }
219
220 action(n_writebackAckToRequestor, "n", desc="Send WB_ack to requestor") {
221 peek(requestNetwork_in, RequestMsg) {
222 // This needs to be DIRECTORY_LATENCY to keep the queue fifo
223 enqueue(forwardedRequestNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
224 out_msg.Address := address;
225 out_msg.Type := CoherenceRequestType:WB_ACK;
226 out_msg.Requestor := machineID;
227 out_msg.Destination.add(in_msg.Requestor);
228 out_msg.MessageSize := MessageSizeType:Control;
229 }
230 }
231 }
232
233 action(p_clearOwner, "p", desc="Clear owner") {
234 directory[address].DirOwner := true; // set owner equal to dir
235 }
236
237 action(r_addOwnerToSharers, "r", desc="Add owner to list of sharers") {
238 directory[address].Sharers.add(directory[address].ProcOwner);
239 }
240
241 action(t_removeOwnerFromSharers, "t", desc="Remove owner from list of sharers") {
242 directory[address].Sharers.remove(directory[address].ProcOwner);
243 }
244
245 action(u_removeRequestorFromSharers, "u", desc="Remove requestor from list of sharers") {
246 peek(requestNetwork_in, RequestMsg) {
247 directory[address].Sharers.remove(in_msg.Requestor);
248 }
249 }
250
251 // TRANSITIONS
252
253 transition({I, S, M, O}, PUTX_NotOwner) {
254 n_writebackAckToRequestor;
255 j_popIncomingRequestQueue;
256 }
257
258 // Transitions from Idle
259 transition(I, GETS, S) {
260 a_addRequestorToSharers;
261 b_dataToRequestor;
262 j_popIncomingRequestQueue;
263 }
264
265 transition(I, GETX_NotOwner, M) {
266 f_setOwnerToRequestor;
267 b_dataToRequestor;
268 j_popIncomingRequestQueue;
269 }
270
271 // Transitions from Shared
272 transition(S, GETS) {
273 a_addRequestorToSharers;
274 b_dataToRequestor;
275 j_popIncomingRequestQueue;
276 }
277
278 transition(S, GETX_NotOwner, M) {
279 u_removeRequestorFromSharers;
280 b_dataToRequestor;
281 f_setOwnerToRequestor;
282 h_invToSharers;
283 g_clearSharers;
284 j_popIncomingRequestQueue;
285 }
286
287 // Transitions from Owned
288 transition(O, GETS) {
289 a_addRequestorToSharers;
290 d_forwardRequestToOwner;
291 j_popIncomingRequestQueue;
292 }
293
294 transition(O, {GETX_NotOwner, GETX_Owner}, M) {
295 u_removeRequestorFromSharers;
296 t_removeOwnerFromSharers;
297 d_forwardRequestToOwner;
298 f_setOwnerToRequestor;
299 h_invToSharers;
300 g_clearSharers;
301 j_popIncomingRequestQueue;
302 }
303
304 transition(O, PUTX_Owner, S) {
305 u_removeRequestorFromSharers;
306 l_writeRequestDataToMemory;
307 n_writebackAckToRequestor;
308 p_clearOwner;
309 j_popIncomingRequestQueue;
310 }
311
312
313 // Transitions from Modified
314 transition(M, GETS, O) {
315 a_addRequestorToSharers;
316 r_addOwnerToSharers;
317 d_forwardRequestToOwner;
318 j_popIncomingRequestQueue;
319 }
320
321 transition(M, GETX_NotOwner) {
322 d_forwardRequestToOwner;
323 f_setOwnerToRequestor;
324 j_popIncomingRequestQueue;
325 }
326
327 transition(M, PUTX_Owner, I) {
328 l_writeRequestDataToMemory;
329 n_writebackAckToRequestor;
330 p_clearOwner;
331 j_popIncomingRequestQueue;
332 }
333 }