diff options
Diffstat (limited to 'src/mem/protocol/MOSI_SMP_bcast_m-dir.sm')
-rw-r--r-- | src/mem/protocol/MOSI_SMP_bcast_m-dir.sm | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/src/mem/protocol/MOSI_SMP_bcast_m-dir.sm b/src/mem/protocol/MOSI_SMP_bcast_m-dir.sm new file mode 100644 index 000000000..e241ea25c --- /dev/null +++ b/src/mem/protocol/MOSI_SMP_bcast_m-dir.sm @@ -0,0 +1,345 @@ + +/* + * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +machine(Directory, "MOSI Broadcast Optimized") { + + + MessageBuffer addressFromDir, network="To", virtual_network="0", ordered="true"; + MessageBuffer dataFromDir, network="To", virtual_network="1", ordered="false"; + + MessageBuffer addressToDir, network="From", virtual_network="0", ordered="true"; + MessageBuffer dataToDir, network="From", virtual_network="1", ordered="false"; + + + enumeration(State, desc="Directory states", default="Directory_State_C") { + C, desc="Cold - no processor has requested this line"; + I, desc="Idle"; + S, desc="Shared"; + SS, desc="Shared, 2 or more shares"; + OS, desc="Owned by a cache"; + OSS, desc="Owned by a cache, present in at least 3 caches"; + M, desc="Modified", format="!b"; + } + + // ** EVENTS ** + + enumeration(Event, desc="Directory events") { + // From Address network + OtherAddress, desc="We saw an address msg to someone else"; + GETS, desc="A GETS arrives"; + GET_INSTR, desc="A GETInstr arrives"; + GETX, desc="A GETX arrives", format="!r"; + PUTX_Owner, desc="A PUTX arrives, requestor is owner"; + PUTX_NotOwner, desc="A PUTX arrives, requestor is not owner", format="!r"; + Memory_Data, desc="Fetched data from memory arrives"; + Memory_Ack, desc="Writeback Ack from memory arrives"; + } + + // TYPES + + // DirectoryEntry + structure(Entry, desc="...") { + State DirectoryState, desc="Directory state"; + bool DirOwner, default="true", desc="Is dir owner?"; + MachineID ProcOwner, desc="Processor Owner"; + DataBlock DataBlk, desc="data for the block"; + } + + external_type(DirectoryMemory) { + Entry lookup(Address); + bool isPresent(Address); + } + + // to simulate detailed DRAM + external_type(MemoryControl, inport="yes", outport="yes") { + + } + + // ** OBJECTS ** + + DirectoryMemory directory, constructor_hack="i"; + MemoryControl memBuffer, constructor_hack="i"; + + void profile_request(int cache_state, State directory_state, GenericRequestType request_type); + + State getState(Address addr) { + if (directory.isPresent(addr)) { + return directory[addr].DirectoryState; + } + return State:C; + } + + void setState(Address addr, State state) { + if (directory.isPresent(addr)) { + directory[addr].DirectoryState := state; + } + } + + // ** OUT_PORTS ** + + out_port(dataNetwork_out, DataMsg, dataFromDir); + out_port(addressNetwork_out, AddressMsg, addressFromDir); + out_port(memQueue_out, MemoryMsg, memBuffer); + + + // ** IN_PORTS ** + + // Address Network + in_port(addressNetwork_in, AddressMsg, addressToDir) { + if (addressNetwork_in.isReady()) { + peek(addressNetwork_in, AddressMsg) { + if(map_Address_to_Directory(in_msg.Address) != machineID) { + trigger(Event:OtherAddress, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:GETS) { + trigger(Event:GETS, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:GET_INSTR) { + trigger(Event:GET_INSTR, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:GETX) { + trigger(Event:GETX, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:PUTX) { + if (in_msg.Requestor == directory[in_msg.Address].ProcOwner && directory[in_msg.Address].DirOwner == false) { + trigger(Event:PUTX_Owner, in_msg.Address); + } else { + trigger(Event:PUTX_NotOwner, in_msg.Address); + } + } else { + error("unexpected message"); + } + } + } + } + + // off-chip memory request/response is done + in_port(memQueue_in, MemoryMsg, memBuffer) { + if (memQueue_in.isReady()) { + peek(memQueue_in, MemoryMsg) { + if (in_msg.Type == MemoryRequestType:MEMORY_READ) { + trigger(Event:Memory_Data, in_msg.Address); + } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { + trigger(Event:Memory_Ack, in_msg.Address); + } else { + DEBUG_EXPR(in_msg.Type); + error("Invalid message"); + } + } + } + } + + // *** ACTIONS *** + + action(d_sendDataMsg, "d", desc="Send data message to requestor") { + peek(memQueue_in, MemoryMsg) { + enqueue(dataNetwork_out, DataMsg, latency="1") { + out_msg.Address := in_msg.Address; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.OriginalRequestorMachId); + out_msg.DestMachine := MachineType:L1Cache; + //out_msg.DataBlk := directory[in_msg.Address].DataBlk; + out_msg.DataBlk := in_msg.DataBlk; + out_msg.MessageSize := MessageSizeType:Data; + DEBUG_EXPR(in_msg.OriginalRequestorMachId); + DEBUG_EXPR(out_msg.DataBlk); + } + } + } + + action(j_popAddressQueue, "j", desc="Pop address queue.") { + addressNetwork_in.dequeue(); + } + + action(l_popMemQueue, "q", desc="Pop off-chip request queue") { + memQueue_in.dequeue(); + } + + action(p_profile, "p", desc="Profile this transition.") { + peek(addressNetwork_in, AddressMsg) { + profile_request(in_msg.CacheState, getState(address), convertToGenericType(in_msg.Type)); + } + } + + action(m_setOwnerRequestor, "m", desc="Set owner = requestor") { + peek(addressNetwork_in, AddressMsg) { + directory[in_msg.Address].ProcOwner := in_msg.Requestor; + directory[in_msg.Address].DirOwner := false; + } + } + + action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { + peek(addressNetwork_in, AddressMsg) { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_READ; + out_msg.Sender := machineID; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.DataBlk := directory[in_msg.Address].DataBlk; + out_msg.MessageSize := in_msg.MessageSize; + //out_msg.Prefetch := in_msg.Prefetch; + DEBUG_EXPR(out_msg); + } + } + } + + action(qw_queueMemoryWBRequest, "qw", desc="Queue off-chip writeback request") { + peek(addressNetwork_in, AddressMsg) { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + out_msg.Sender := machineID; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.DataBlk := in_msg.DataBlk; + out_msg.MessageSize := in_msg.MessageSize; + //out_msg.Prefetch := in_msg.Prefetch; + DEBUG_EXPR(out_msg); + } + } + } + + action(r_writeDataFromRequest, "r", desc="Write request data to memory") { + peek(addressNetwork_in, AddressMsg) { + directory[in_msg.Address].DataBlk := in_msg.DataBlk; + DEBUG_EXPR(in_msg.Address); + DEBUG_EXPR(in_msg.DataBlk); + } + } + + action(x_setOwnerToDirectory, "x", desc="Set owner equal to the directory"){ + peek(addressNetwork_in, AddressMsg) { + directory[in_msg.Address].DirOwner := true; + } + } + + // TRANSITIONS + + // Ignore all address and data messages not bound for us + transition(C, OtherAddress) { + j_popAddressQueue; + } + + // PUTX_NotOwner Transitions + transition({I, S, SS, OS, OSS, M}, PUTX_NotOwner) { + p_profile; + j_popAddressQueue; + } + + // Transitions from Idle + transition({C, I}, {GETS,GET_INSTR}, S) { + //d_sendDataMsg; + qf_queueMemoryFetchRequest; + p_profile; + j_popAddressQueue; + } + + transition({C, I}, GETX, M) { + //d_sendDataMsg; + qf_queueMemoryFetchRequest; + m_setOwnerRequestor; + p_profile; + j_popAddressQueue + } + + // Transitions from Shared + transition({S, SS}, {GETS,GET_INSTR}, SS) { + //d_sendDataMsg; + qf_queueMemoryFetchRequest; + p_profile; + j_popAddressQueue; + } + + transition({S, SS}, GETX, M) { + //d_sendDataMsg; + qf_queueMemoryFetchRequest; + m_setOwnerRequestor; + p_profile; + j_popAddressQueue; + } + + // Transitions from Owned + transition({OS, OSS}, {GETS,GET_INSTR}, OSS) { + p_profile; + j_popAddressQueue; + } + + transition({OS, OSS}, GETX, M) { + m_setOwnerRequestor; + p_profile; + j_popAddressQueue; + } + + transition(OS, PUTX_Owner, S) { + x_setOwnerToDirectory; + r_writeDataFromRequest; + qw_queueMemoryWBRequest; + p_profile; + j_popAddressQueue; + } + + transition(OSS, PUTX_Owner, SS) { + x_setOwnerToDirectory; + r_writeDataFromRequest; + qw_queueMemoryWBRequest; + p_profile; + j_popAddressQueue; + } + + // Transitions from Modified + transition(M, {GETS,GET_INSTR}, OS) { + p_profile; + j_popAddressQueue; + } + + transition(M, GETX) { + m_setOwnerRequestor; + p_profile; + j_popAddressQueue; + } + + transition(M, PUTX_Owner, I) { + x_setOwnerToDirectory; + r_writeDataFromRequest; + qw_queueMemoryWBRequest; + p_profile; + j_popAddressQueue; + } + + transition({C, I, S, SS, OS, OSS, M}, Memory_Data) { + d_sendDataMsg; + l_popMemQueue; + } + + transition({C, I, S, SS, OS, OSS, M}, Memory_Ack) { + //a_sendAck; + l_popMemQueue; + } + +} |