3 * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
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.
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.
31 * $Id: MOSI_directory-dir.sm 1.14 04/09/07 13:52:52-05:00 mikem@maya.cs.wisc.edu $
34 machine(Directory, "MOSI Directory Optimized") {
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";
42 enumeration(State, desc="Directory states", default="Directory_State_I") {
47 M, desc="Modified", format="!b";
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";
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";
70 external_type(DirectoryMemory) {
71 Entry lookup(Address);
72 bool isPresent(Address);
77 DirectoryMemory directory, constructor_hack="i";
79 State getState(Address addr) {
80 if (directory.isPresent(addr)) {
81 return directory[addr].DirectoryState;
86 void setState(Address addr, State state) {
87 if (directory.isPresent(addr)) {
88 directory[addr].DirectoryState := state;
93 out_port(forwardedRequestNetwork_out, RequestMsg, forwardedRequestFromDir);
94 out_port(responseNetwork_out, ResponseMsg, responseFromDir);
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);
107 trigger(Event:GETX_NotOwner, in_msg.Address);
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);
113 trigger(Event:PUTX_NotOwner, in_msg.Address);
116 error("Invalid message");
125 // a_addRequestorToSharers
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);
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();
146 out_msg.NumPendingAcks := 0; // don't need to send pending ack count to GETS requestor
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;
158 // d_forwardRequestToOwner
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);
169 if(in_msg.Type == CoherenceRequestType:GETX) {
170 out_msg.NumPendingAcks := directory[address].Sharers.count();
172 out_msg.NumPendingAcks := 0; // don't need to send pending ack count to GETS requestor
174 out_msg.MessageSize := MessageSizeType:Control;
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;
184 DEBUG_EXPR(directory[address].ProcOwner);
187 action(g_clearSharers, "g", desc="Clear list of sharers") {
188 directory[address].Sharers.clear();
191 // currently done via multicast message
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;
205 DEBUG_EXPR(directory[address].Sharers);
208 action(j_popIncomingRequestQueue, "j", desc="Pop incoming request queue") {
209 requestNetwork_in.dequeue();
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);
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;
233 action(p_clearOwner, "p", desc="Clear owner") {
234 directory[address].DirOwner := true; // set owner equal to dir
237 action(r_addOwnerToSharers, "r", desc="Add owner to list of sharers") {
238 directory[address].Sharers.add(directory[address].ProcOwner);
241 action(t_removeOwnerFromSharers, "t", desc="Remove owner from list of sharers") {
242 directory[address].Sharers.remove(directory[address].ProcOwner);
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);
253 transition({I, S, M, O}, PUTX_NotOwner) {
254 n_writebackAckToRequestor;
255 j_popIncomingRequestQueue;
258 // Transitions from Idle
259 transition(I, GETS, S) {
260 a_addRequestorToSharers;
262 j_popIncomingRequestQueue;
265 transition(I, GETX_NotOwner, M) {
266 f_setOwnerToRequestor;
268 j_popIncomingRequestQueue;
271 // Transitions from Shared
272 transition(S, GETS) {
273 a_addRequestorToSharers;
275 j_popIncomingRequestQueue;
278 transition(S, GETX_NotOwner, M) {
279 u_removeRequestorFromSharers;
281 f_setOwnerToRequestor;
284 j_popIncomingRequestQueue;
287 // Transitions from Owned
288 transition(O, GETS) {
289 a_addRequestorToSharers;
290 d_forwardRequestToOwner;
291 j_popIncomingRequestQueue;
294 transition(O, {GETX_NotOwner, GETX_Owner}, M) {
295 u_removeRequestorFromSharers;
296 t_removeOwnerFromSharers;
297 d_forwardRequestToOwner;
298 f_setOwnerToRequestor;
301 j_popIncomingRequestQueue;
304 transition(O, PUTX_Owner, S) {
305 u_removeRequestorFromSharers;
306 l_writeRequestDataToMemory;
307 n_writebackAckToRequestor;
309 j_popIncomingRequestQueue;
313 // Transitions from Modified
314 transition(M, GETS, O) {
315 a_addRequestorToSharers;
317 d_forwardRequestToOwner;
318 j_popIncomingRequestQueue;
321 transition(M, GETX_NotOwner) {
322 d_forwardRequestToOwner;
323 f_setOwnerToRequestor;
324 j_popIncomingRequestQueue;
327 transition(M, PUTX_Owner, I) {
328 l_writeRequestDataToMemory;
329 n_writebackAckToRequestor;
331 j_popIncomingRequestQueue;