gem5/src/mem/protocol/Network_test-cache.sm

219 lines
7.1 KiB
Text
Raw Normal View History

/*
* Copyright (c) 2009 Advanced Micro Devices, Inc.
* 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.
*
*
* Authors: Brad Beckmann
* Tushar Krishna
*/
machine(L1Cache, "Network_test L1 Cache")
: Sequencer * sequencer,
int issue_latency = 2
{
// NETWORK BUFFERS
MessageBuffer requestFromCache, network="To", virtual_network="0", ordered="false", vnet_type = "request";
MessageBuffer forwardFromCache, network="To", virtual_network="1", ordered="false", vnet_type = "forward";
MessageBuffer responseFromCache, network="To", virtual_network="2", ordered="false", vnet_type = "response";
// STATES
state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
I, AccessPermission:Invalid, desc="Not Present/Invalid";
}
// EVENTS
enumeration(Event, desc="Cache events") {
// From processor
Request, desc="Request from Network_test";
Forward, desc="Forward from Network_test";
Response, desc="Response from Network_test";
}
// STRUCTURE DEFINITIONS
MessageBuffer mandatoryQueue, ordered="false";
DataBlock dummyData;
// CacheEntry
structure(Entry, desc="...", interface="AbstractCacheEntry") {
State CacheState, desc="cache state";
DataBlock DataBlk, desc="Data in the block";
}
// TBE fields
structure(TBE, desc="...") {
State TBEState, desc="Transient state";
DataBlock DataBlk, desc="data for the block, required for concurrent writebacks";
}
structure(TBETable, external="yes") {
TBE lookup(Address);
void allocate(Address);
void deallocate(Address);
bool isPresent(Address);
}
// STRUCTURES
TBETable TBEs, template_hack="<L1Cache_TBE>";
// FUNCTIONS
// cpu/testers/networktest/networktest.cc generates packets of the type
// ReadReq, INST_FETCH, and WriteReq.
// These are converted to LD, IFETCH and ST by mem/ruby/system/RubyPort.cc.
// These are then sent to the sequencer, which sends them here.
// Network_test-cache.sm tags LD, IFETCH and ST as Request, Forward,
// and Response Events respectively, which are then injected into
// virtual networks 0, 1 and 2 respectively.
// This models traffic of different types within the network.
//
// Note that requests and forwards are MessageSizeType:Control,
// while responses are MessageSizeType:Data.
//
Event mandatory_request_type_to_event(RubyRequestType type) {
if (type == RubyRequestType:LD) {
return Event:Request;
} else if (type == RubyRequestType:IFETCH) {
return Event:Forward;
} else if (type == RubyRequestType:ST) {
return Event:Response;
} else {
error("Invalid RubyRequestType");
}
}
State getState(TBE tbe, Entry cache_entry, Address addr) {
return State:I;
}
void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
}
Entry getCacheEntry(Address address), return_by_pointer="yes" {
return OOD;
}
// NETWORK PORTS
out_port(requestNetwork_out, RequestMsg, requestFromCache);
out_port(forwardNetwork_out, RequestMsg, forwardFromCache);
out_port(responseNetwork_out, RequestMsg, responseFromCache);
// Mandatory Queue
in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...") {
if (mandatoryQueue_in.isReady()) {
peek(mandatoryQueue_in, RubyRequest) {
trigger(mandatory_request_type_to_event(in_msg.Type),
in_msg.LineAddress,
getCacheEntry(in_msg.LineAddress),
TBEs[in_msg.LineAddress]);
}
}
}
// ACTIONS
// The destination directory of the packets is embedded in the address
// map_Address_to_Directory is used to retrieve it.
action(a_issueRequest, "a", desc="Issue a request") {
enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:MSG;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
//out_msg.Destination := broadcast(MachineType:Directory);
out_msg.MessageSize := MessageSizeType:Control;
}
}
action(b_issueForward, "b", desc="Issue a forward") {
enqueue(forwardNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:MSG;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.MessageSize := MessageSizeType:Control;
}
}
action(c_issueResponse, "c", desc="Issue a response") {
enqueue(responseNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:MSG;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.MessageSize := MessageSizeType:Data;
}
}
action(m_popMandatoryQueue, "m", desc="Pop the mandatory request queue") {
mandatoryQueue_in.dequeue();
}
action(r_load_hit, "r", desc="Notify sequencer the load completed.") {
sequencer.readCallback(address, dummyData);
}
action(s_store_hit, "s", desc="Notify sequencer that store completed.") {
sequencer.writeCallback(address, dummyData);
}
// TRANSITIONS
// sequencer hit call back is performed after injecting the packets.
// The goal of the Network_test protocol is only to inject packets into
// the network, not to keep track of them via TBEs.
transition(I, Response) {
s_store_hit;
c_issueResponse;
m_popMandatoryQueue;
}
transition(I, Request) {
r_load_hit;
a_issueRequest;
m_popMandatoryQueue;
}
transition(I, Forward) {
r_load_hit;
b_issueForward;
m_popMandatoryQueue;
}
}