+/*
+ * Copyright (c) 2009-2012 Mark D. Hill and David A. Wood
+ * Copyright (c) 2010-2012 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.
+ */
machine(L1Cache, "MI Example L1 Cache")
-: Sequencer * sequencer,
- CacheMemory * cacheMemory,
- int cache_response_latency = 12,
- int issue_latency = 2
+ : Sequencer * sequencer;
+ CacheMemory * cacheMemory;
+ Cycles cache_response_latency := 12;
+ Cycles issue_latency := 2;
+ bool send_evictions;
+
+ // NETWORK BUFFERS
+ MessageBuffer * requestFromCache, network="To", virtual_network="2",
+ ordered="true", vnet_type="request";
+ MessageBuffer * responseFromCache, network="To", virtual_network="4",
+ ordered="true", vnet_type="response";
+
+ MessageBuffer * forwardToCache, network="From", virtual_network="3",
+ ordered="true", vnet_type="forward";
+ MessageBuffer * responseToCache, network="From", virtual_network="4",
+ ordered="true", vnet_type="response";
{
-
- // NETWORK BUFFERS
- MessageBuffer requestFromCache, network="To", virtual_network="2", ordered="true", vnet_type="request";
- MessageBuffer responseFromCache, network="To", virtual_network="4", ordered="true", vnet_type="response";
-
- MessageBuffer forwardToCache, network="From", virtual_network="3", ordered="true", vnet_type="forward";
- MessageBuffer responseToCache, network="From", virtual_network="4", ordered="true", vnet_type="response";
-
// STATES
state_declaration(State, desc="Cache states") {
I, AccessPermission:Invalid, desc="Not Present/Invalid";
DataBlock DataBlk, desc="Data in the block";
}
-
// TBE fields
structure(TBE, desc="...") {
State TBEState, desc="Transient state";
// STRUCTURES
-
- TBETable TBEs, template_hack="<L1Cache_TBE>";
+ TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs";
// PROTOTYPES
void set_cache_entry(AbstractCacheEntry a);
void unset_cache_entry();
void set_tbe(TBE b);
void unset_tbe();
+ void profileMsgDelay(int virtualNetworkType, Cycles b);
Entry getCacheEntry(Address address), return_by_pointer="yes" {
return static_cast(Entry, "pointer", cacheMemory.lookup(address));
}
}
- GenericMachineType getNondirectHitMachType(MachineID sender) {
- if (machineIDToMachineType(sender) == MachineType:L1Cache) {
- //
- // NOTE direct local hits should not call this
- //
- return GenericMachineType:L1Cache_wCC;
- } else {
- return ConvertMachToGenericMach(machineIDToMachineType(sender));
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
}
- }
+ return getCacheEntry(addr).DataBlk;
+ }
// NETWORK PORTS
in_port(forwardRequestNetwork_in, RequestMsg, forwardToCache) {
if (forwardRequestNetwork_in.isReady()) {
- peek(forwardRequestNetwork_in, RequestMsg, block_on="Address") {
+ peek(forwardRequestNetwork_in, RequestMsg, block_on="Addr") {
- Entry cache_entry := getCacheEntry(in_msg.Address);
- TBE tbe := TBEs[in_msg.Address];
+ Entry cache_entry := getCacheEntry(in_msg.Addr);
+ TBE tbe := TBEs[in_msg.Addr];
if (in_msg.Type == CoherenceRequestType:GETX) {
- trigger(Event:Fwd_GETX, in_msg.Address, cache_entry, tbe);
+ trigger(Event:Fwd_GETX, in_msg.Addr, cache_entry, tbe);
}
else if (in_msg.Type == CoherenceRequestType:WB_ACK) {
- trigger(Event:Writeback_Ack, in_msg.Address, cache_entry, tbe);
+ trigger(Event:Writeback_Ack, in_msg.Addr, cache_entry, tbe);
}
else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
- trigger(Event:Writeback_Nack, in_msg.Address, cache_entry, tbe);
+ trigger(Event:Writeback_Nack, in_msg.Addr, cache_entry, tbe);
}
else if (in_msg.Type == CoherenceRequestType:INV) {
- trigger(Event:Inv, in_msg.Address, cache_entry, tbe);
+ trigger(Event:Inv, in_msg.Addr, cache_entry, tbe);
}
else {
error("Unexpected message");
in_port(responseNetwork_in, ResponseMsg, responseToCache) {
if (responseNetwork_in.isReady()) {
- peek(responseNetwork_in, ResponseMsg, block_on="Address") {
+ peek(responseNetwork_in, ResponseMsg, block_on="Addr") {
- Entry cache_entry := getCacheEntry(in_msg.Address);
- TBE tbe := TBEs[in_msg.Address];
+ Entry cache_entry := getCacheEntry(in_msg.Addr);
+ TBE tbe := TBEs[in_msg.Addr];
if (in_msg.Type == CoherenceResponseType:DATA) {
- trigger(Event:Data, in_msg.Address, cache_entry, tbe);
+ trigger(Event:Data, in_msg.Addr, cache_entry, tbe);
}
else {
error("Unexpected message");
// ACTIONS
action(a_issueRequest, "a", desc="Issue a request") {
- enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
- out_msg.Address := address;
+ enqueue(requestNetwork_out, RequestMsg, issue_latency) {
+ out_msg.Addr := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
}
action(b_issuePUT, "b", desc="Issue a PUT request") {
- enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
+ enqueue(requestNetwork_out, RequestMsg, issue_latency) {
assert(is_valid(cache_entry));
- out_msg.Address := address;
+ out_msg.Addr := address;
out_msg.Type := CoherenceRequestType:PUTX;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
}
}
-
action(e_sendData, "e", desc="Send data from cache to requestor") {
peek(forwardRequestNetwork_in, RequestMsg) {
- enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) {
+ enqueue(responseNetwork_out, ResponseMsg, cache_response_latency) {
assert(is_valid(cache_entry));
- out_msg.Address := address;
+ out_msg.Addr := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
action(ee_sendDataFromTBE, "\e", desc="Send data from TBE to requestor") {
peek(forwardRequestNetwork_in, RequestMsg) {
- enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) {
+ enqueue(responseNetwork_out, ResponseMsg, cache_response_latency) {
assert(is_valid(tbe));
- out_msg.Address := address;
+ out_msg.Addr := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
}
action(n_popResponseQueue, "n", desc="Pop the response queue") {
- profileMsgDelay(1, responseNetwork_in.dequeue_getDelayCycles());
+ profileMsgDelay(1, responseNetwork_in.dequeue());
}
action(o_popForwardedRequestQueue, "o", desc="Pop the forwarded request queue") {
- profileMsgDelay(2, forwardRequestNetwork_in.dequeue_getDelayCycles());
+ profileMsgDelay(2, forwardRequestNetwork_in.dequeue());
}
- action(p_profileMiss, "p", desc="Profile cache miss") {
- peek(mandatoryQueue_in, RubyRequest) {
- cacheMemory.profileMiss(in_msg);
- }
+ action(p_profileMiss, "pi", desc="Profile cache miss") {
+ ++cacheMemory.demand_misses;
+ }
+
+ action(p_profileHit, "ph", desc="Profile cache miss") {
+ ++cacheMemory.demand_hits;
}
action(r_load_hit, "r", desc="Notify sequencer the load completed.") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
- sequencer.readCallback(address,
- GenericMachineType:L1Cache,
- cache_entry.DataBlk);
+ sequencer.readCallback(address, cache_entry.DataBlk, false);
}
action(rx_load_hit, "rx", desc="External load completed.") {
peek(responseNetwork_in, ResponseMsg) {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
- sequencer.readCallback(address,
- getNondirectHitMachType(in_msg.Sender),
- cache_entry.DataBlk);
+ sequencer.readCallback(address, cache_entry.DataBlk, true,
+ machineIDToMachineType(in_msg.Sender));
}
}
action(s_store_hit, "s", desc="Notify sequencer that store completed.") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
- sequencer.writeCallback(address,
- GenericMachineType:L1Cache,
- cache_entry.DataBlk);
+ sequencer.writeCallback(address, cache_entry.DataBlk, false);
}
action(sx_store_hit, "sx", desc="External store completed.") {
peek(responseNetwork_in, ResponseMsg) {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
- sequencer.writeCallback(address,
- getNondirectHitMachType(in_msg.Sender),
- cache_entry.DataBlk);
+ sequencer.writeCallback(address, cache_entry.DataBlk, true,
+ machineIDToMachineType(in_msg.Sender));
}
}
}
}
+ action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") {
+ if (send_evictions) {
+ DPRINTF(RubySlicc, "Sending invalidation for %s to the CPU\n", address);
+ sequencer.evictionCallback(address);
+ }
+ }
action(v_allocateTBE, "v", desc="Allocate TBE") {
TBEs.allocate(address);
set_tbe(TBEs[address]);
}
-
action(w_deallocateTBE, "w", desc="Deallocate TBE") {
TBEs.deallocate(address);
unset_tbe();
// TRANSITIONS
- transition({IS, IM, MI, II}, {Load, Ifetch, Store, Replacement}) {
+ transition({IS, IM, MI, II, MII}, {Load, Ifetch, Store, Replacement}) {
z_stall;
}
transition(M, Store) {
s_store_hit;
+ p_profileHit;
m_popMandatoryQueue;
}
transition(M, {Load, Ifetch}) {
r_load_hit;
+ p_profileHit;
m_popMandatoryQueue;
}
transition(M, Fwd_GETX, I) {
e_sendData;
+ forward_eviction_to_cpu;
o_popForwardedRequestQueue;
}
v_allocateTBE;
b_issuePUT;
x_copyDataFromCacheToTBE;
+ forward_eviction_to_cpu;
h_deallocateL1CacheBlock;
}
o_popForwardedRequestQueue;
}
}
-