114184Sgabeblack@google.com/*
214184Sgabeblack@google.com * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
314184Sgabeblack@google.com * All rights reserved.
414184Sgabeblack@google.com *
514184Sgabeblack@google.com * For use for simulation and test purposes only
614184Sgabeblack@google.com *
714184Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
814184Sgabeblack@google.com * modification, are permitted provided that the following conditions are met:
914184Sgabeblack@google.com *
1014184Sgabeblack@google.com * 1. Redistributions of source code must retain the above copyright notice,
1114184Sgabeblack@google.com * this list of conditions and the following disclaimer.
1214184Sgabeblack@google.com *
1314184Sgabeblack@google.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1414184Sgabeblack@google.com * this list of conditions and the following disclaimer in the documentation
1514184Sgabeblack@google.com * and/or other materials provided with the distribution.
1614184Sgabeblack@google.com *
1714184Sgabeblack@google.com * 3. Neither the name of the copyright holder nor the names of its
1814184Sgabeblack@google.com * contributors may be used to endorse or promote products derived from this
1914184Sgabeblack@google.com * software without specific prior written permission.
2014184Sgabeblack@google.com *
2114184Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2214184Sgabeblack@google.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2314184Sgabeblack@google.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2414184Sgabeblack@google.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2514184Sgabeblack@google.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2614184Sgabeblack@google.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2714184Sgabeblack@google.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2814184Sgabeblack@google.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2914184Sgabeblack@google.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3014184Sgabeblack@google.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3114184Sgabeblack@google.com * POSSIBILITY OF SUCH DAMAGE.
3214184Sgabeblack@google.com *
3314184Sgabeblack@google.com * Author: Blake Hechtman
3414184Sgabeblack@google.com */
3514184Sgabeblack@google.com
3614184Sgabeblack@google.commachine(MachineType:SQC, "GPU SQC (L1 I Cache)")
3714184Sgabeblack@google.com : Sequencer* sequencer;
3814184Sgabeblack@google.com   CacheMemory * L1cache;
3914184Sgabeblack@google.com   int TCC_select_num_bits;
4014184Sgabeblack@google.com   Cycles issue_latency := 80;  // time to send data down to TCC
4114184Sgabeblack@google.com   Cycles l2_hit_latency := 18; // for 1MB L2, 20 for 2MB
4214184Sgabeblack@google.com
4314184Sgabeblack@google.com  MessageBuffer * requestFromSQC, network="To", virtual_network="1", vnet_type="request";
4414184Sgabeblack@google.com
4514184Sgabeblack@google.com  MessageBuffer * probeToSQC, network="From", virtual_network="1", vnet_type="request";
4614184Sgabeblack@google.com  MessageBuffer * responseToSQC, network="From", virtual_network="3", vnet_type="response";
4714184Sgabeblack@google.com
4814184Sgabeblack@google.com  MessageBuffer * mandatoryQueue;
4914184Sgabeblack@google.com{
5014184Sgabeblack@google.com  state_declaration(State, desc="SQC Cache States", default="SQC_State_I") {
5114184Sgabeblack@google.com    I, AccessPermission:Invalid, desc="Invalid";
5214184Sgabeblack@google.com    V, AccessPermission:Read_Only, desc="Valid";
5314184Sgabeblack@google.com  }
5414184Sgabeblack@google.com
5514184Sgabeblack@google.com  enumeration(Event, desc="SQC Events") {
5614184Sgabeblack@google.com    // Core initiated
5714184Sgabeblack@google.com    Fetch,          desc="Fetch";
5814184Sgabeblack@google.com    // Mem sys initiated
5914184Sgabeblack@google.com    Repl,           desc="Replacing block from cache";
6014184Sgabeblack@google.com    Data,           desc="Received Data";
6114184Sgabeblack@google.com  }
6214184Sgabeblack@google.com
6314184Sgabeblack@google.com  enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
6414184Sgabeblack@google.com    DataArrayRead,    desc="Read the data array";
6514184Sgabeblack@google.com    DataArrayWrite,   desc="Write the data array";
6614184Sgabeblack@google.com    TagArrayRead,     desc="Read the data array";
6714184Sgabeblack@google.com    TagArrayWrite,    desc="Write the data array";
6814184Sgabeblack@google.com  }
6914184Sgabeblack@google.com
7014184Sgabeblack@google.com
7114184Sgabeblack@google.com  structure(Entry, desc="...", interface="AbstractCacheEntry") {
7214184Sgabeblack@google.com    State CacheState,           desc="cache state";
7314184Sgabeblack@google.com    bool Dirty,                 desc="Is the data dirty (diff than memory)?";
7414184Sgabeblack@google.com    DataBlock DataBlk,          desc="data for the block";
7514184Sgabeblack@google.com    bool FromL2, default="false", desc="block just moved from L2";
7614184Sgabeblack@google.com  }
7714184Sgabeblack@google.com
7814184Sgabeblack@google.com  structure(TBE, desc="...") {
7914184Sgabeblack@google.com    State TBEState,             desc="Transient state";
8014184Sgabeblack@google.com    DataBlock DataBlk,       desc="data for the block, required for concurrent writebacks";
8114184Sgabeblack@google.com    bool Dirty,              desc="Is the data dirty (different than memory)?";
8214184Sgabeblack@google.com    int NumPendingMsgs,      desc="Number of acks/data messages that this processor is waiting for";
8314184Sgabeblack@google.com    bool Shared,             desc="Victim hit by shared probe";
8414184Sgabeblack@google.com   }
8514184Sgabeblack@google.com
8614184Sgabeblack@google.com  structure(TBETable, external="yes") {
8714184Sgabeblack@google.com    TBE lookup(Addr);
8814184Sgabeblack@google.com    void allocate(Addr);
8914184Sgabeblack@google.com    void deallocate(Addr);
9014184Sgabeblack@google.com    bool isPresent(Addr);
9114184Sgabeblack@google.com  }
9214184Sgabeblack@google.com
9314184Sgabeblack@google.com  TBETable TBEs, template="<SQC_TBE>", constructor="m_number_of_TBEs";
9414184Sgabeblack@google.com  int TCC_select_low_bit, default="RubySystem::getBlockSizeBits()";
9514184Sgabeblack@google.com
9614184Sgabeblack@google.com  void set_cache_entry(AbstractCacheEntry b);
9714184Sgabeblack@google.com  void unset_cache_entry();
9814184Sgabeblack@google.com  void set_tbe(TBE b);
9914184Sgabeblack@google.com  void unset_tbe();
10014184Sgabeblack@google.com  void wakeUpAllBuffers();
10114184Sgabeblack@google.com  void wakeUpBuffers(Addr a);
10214184Sgabeblack@google.com  Cycles curCycle();
10314184Sgabeblack@google.com
10414184Sgabeblack@google.com  // Internal functions
10514184Sgabeblack@google.com  Tick clockEdge();
10614184Sgabeblack@google.com
10714184Sgabeblack@google.com  Entry getCacheEntry(Addr address), return_by_pointer="yes" {
10814184Sgabeblack@google.com    Entry cache_entry := static_cast(Entry, "pointer", L1cache.lookup(address));
10914184Sgabeblack@google.com    return cache_entry;
11014184Sgabeblack@google.com  }
11114184Sgabeblack@google.com
11214184Sgabeblack@google.com  DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
11314184Sgabeblack@google.com    TBE tbe := TBEs.lookup(addr);
11414184Sgabeblack@google.com    if(is_valid(tbe)) {
11514184Sgabeblack@google.com      return tbe.DataBlk;
11614184Sgabeblack@google.com    } else {
11714184Sgabeblack@google.com      return getCacheEntry(addr).DataBlk;
11814184Sgabeblack@google.com    }
11914184Sgabeblack@google.com  }
12014184Sgabeblack@google.com
12114184Sgabeblack@google.com  State getState(TBE tbe, Entry cache_entry, Addr addr) {
12214184Sgabeblack@google.com    if(is_valid(tbe)) {
12314184Sgabeblack@google.com      return tbe.TBEState;
12414184Sgabeblack@google.com    } else if (is_valid(cache_entry)) {
12514184Sgabeblack@google.com      return cache_entry.CacheState;
12614184Sgabeblack@google.com    }
12714184Sgabeblack@google.com    return State:I;
12814184Sgabeblack@google.com  }
12914184Sgabeblack@google.com
13014184Sgabeblack@google.com  void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
13114184Sgabeblack@google.com    if (is_valid(tbe)) {
13214184Sgabeblack@google.com      tbe.TBEState := state;
13314184Sgabeblack@google.com    }
13414184Sgabeblack@google.com
13514184Sgabeblack@google.com    if (is_valid(cache_entry)) {
13614184Sgabeblack@google.com      cache_entry.CacheState := state;
13714184Sgabeblack@google.com    }
13814184Sgabeblack@google.com  }
13914184Sgabeblack@google.com
14014184Sgabeblack@google.com  void functionalRead(Addr addr, Packet *pkt) {
14114184Sgabeblack@google.com    TBE tbe := TBEs.lookup(addr);
14214184Sgabeblack@google.com    if(is_valid(tbe)) {
14314184Sgabeblack@google.com      testAndRead(addr, tbe.DataBlk, pkt);
14414184Sgabeblack@google.com    } else {
14514184Sgabeblack@google.com      functionalMemoryRead(pkt);
14614184Sgabeblack@google.com    }
14714184Sgabeblack@google.com  }
14814184Sgabeblack@google.com
14914184Sgabeblack@google.com  int functionalWrite(Addr addr, Packet *pkt) {
15014184Sgabeblack@google.com    int num_functional_writes := 0;
15114184Sgabeblack@google.com
15214184Sgabeblack@google.com    TBE tbe := TBEs.lookup(addr);
15314184Sgabeblack@google.com    if(is_valid(tbe)) {
15414184Sgabeblack@google.com      num_functional_writes := num_functional_writes +
15514184Sgabeblack@google.com            testAndWrite(addr, tbe.DataBlk, pkt);
15614184Sgabeblack@google.com    }
15714184Sgabeblack@google.com
15814184Sgabeblack@google.com    num_functional_writes := num_functional_writes +
15914184Sgabeblack@google.com        functionalMemoryWrite(pkt);
16014184Sgabeblack@google.com    return num_functional_writes;
16114184Sgabeblack@google.com  }
16214184Sgabeblack@google.com
16314184Sgabeblack@google.com  AccessPermission getAccessPermission(Addr addr) {
16414184Sgabeblack@google.com    TBE tbe := TBEs.lookup(addr);
16514184Sgabeblack@google.com    if(is_valid(tbe)) {
16614184Sgabeblack@google.com      return SQC_State_to_permission(tbe.TBEState);
16714184Sgabeblack@google.com    }
16814184Sgabeblack@google.com
16914184Sgabeblack@google.com    Entry cache_entry := getCacheEntry(addr);
17014184Sgabeblack@google.com    if(is_valid(cache_entry)) {
17114184Sgabeblack@google.com      return SQC_State_to_permission(cache_entry.CacheState);
17214184Sgabeblack@google.com    }
17314184Sgabeblack@google.com
17414184Sgabeblack@google.com    return AccessPermission:NotPresent;
17514184Sgabeblack@google.com  }
17614184Sgabeblack@google.com
17714184Sgabeblack@google.com  void setAccessPermission(Entry cache_entry, Addr addr, State state) {
17814184Sgabeblack@google.com    if (is_valid(cache_entry)) {
17914184Sgabeblack@google.com      cache_entry.changePermission(SQC_State_to_permission(state));
18014184Sgabeblack@google.com    }
18114184Sgabeblack@google.com  }
18214184Sgabeblack@google.com
18314184Sgabeblack@google.com  void recordRequestType(RequestType request_type, Addr addr) {
18414184Sgabeblack@google.com    if (request_type == RequestType:DataArrayRead) {
18514184Sgabeblack@google.com        L1cache.recordRequestType(CacheRequestType:DataArrayRead, addr);
18614184Sgabeblack@google.com    } else if (request_type == RequestType:DataArrayWrite) {
18714184Sgabeblack@google.com        L1cache.recordRequestType(CacheRequestType:DataArrayWrite, addr);
18814184Sgabeblack@google.com    } else if (request_type == RequestType:TagArrayRead) {
18914184Sgabeblack@google.com        L1cache.recordRequestType(CacheRequestType:TagArrayRead, addr);
19014184Sgabeblack@google.com    } else if (request_type == RequestType:TagArrayWrite) {
19114184Sgabeblack@google.com        L1cache.recordRequestType(CacheRequestType:TagArrayWrite, addr);
19214184Sgabeblack@google.com    }
19314184Sgabeblack@google.com  }
19414184Sgabeblack@google.com
19514184Sgabeblack@google.com  bool checkResourceAvailable(RequestType request_type, Addr addr) {
19614184Sgabeblack@google.com    if (request_type == RequestType:DataArrayRead) {
19714184Sgabeblack@google.com      return L1cache.checkResourceAvailable(CacheResourceType:DataArray, addr);
19814184Sgabeblack@google.com    } else if (request_type == RequestType:DataArrayWrite) {
19914184Sgabeblack@google.com      return L1cache.checkResourceAvailable(CacheResourceType:DataArray, addr);
20014184Sgabeblack@google.com    } else if (request_type == RequestType:TagArrayRead) {
20114184Sgabeblack@google.com      return L1cache.checkResourceAvailable(CacheResourceType:TagArray, addr);
20214184Sgabeblack@google.com    } else if (request_type == RequestType:TagArrayWrite) {
20314184Sgabeblack@google.com      return L1cache.checkResourceAvailable(CacheResourceType:TagArray, addr);
20414184Sgabeblack@google.com    } else {
20514184Sgabeblack@google.com      error("Invalid RequestType type in checkResourceAvailable");
20614184Sgabeblack@google.com      return true;
20714184Sgabeblack@google.com    }
20814184Sgabeblack@google.com  }
20914184Sgabeblack@google.com
21014184Sgabeblack@google.com  // Out Ports
21114184Sgabeblack@google.com
21214184Sgabeblack@google.com  out_port(requestNetwork_out, CPURequestMsg, requestFromSQC);
21314184Sgabeblack@google.com
21414184Sgabeblack@google.com  // In Ports
21514184Sgabeblack@google.com
21614184Sgabeblack@google.com  in_port(responseToSQC_in, ResponseMsg, responseToSQC) {
21714184Sgabeblack@google.com    if (responseToSQC_in.isReady(clockEdge())) {
21814184Sgabeblack@google.com      peek(responseToSQC_in, ResponseMsg, block_on="addr") {
21914184Sgabeblack@google.com
22014184Sgabeblack@google.com        Entry cache_entry := getCacheEntry(in_msg.addr);
22114184Sgabeblack@google.com        TBE tbe := TBEs.lookup(in_msg.addr);
22214184Sgabeblack@google.com
22314184Sgabeblack@google.com        if (in_msg.Type == CoherenceResponseType:TDSysResp) {
22414184Sgabeblack@google.com          if (is_valid(cache_entry) || L1cache.cacheAvail(in_msg.addr)) {
22514184Sgabeblack@google.com            trigger(Event:Data, in_msg.addr, cache_entry, tbe);
22614184Sgabeblack@google.com          } else {
22714184Sgabeblack@google.com            Addr victim := L1cache.cacheProbe(in_msg.addr);
22814184Sgabeblack@google.com            trigger(Event:Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
22914184Sgabeblack@google.com          }
23014184Sgabeblack@google.com        } else {
23114184Sgabeblack@google.com          error("Unexpected Response Message to Core");
23214184Sgabeblack@google.com        }
23314184Sgabeblack@google.com      }
23414184Sgabeblack@google.com    }
23514184Sgabeblack@google.com  }
23614184Sgabeblack@google.com
23714184Sgabeblack@google.com  in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...") {
23814184Sgabeblack@google.com    if (mandatoryQueue_in.isReady(clockEdge())) {
23914184Sgabeblack@google.com      peek(mandatoryQueue_in, RubyRequest, block_on="LineAddress") {
24014184Sgabeblack@google.com        Entry cache_entry := getCacheEntry(in_msg.LineAddress);
24114184Sgabeblack@google.com        TBE tbe := TBEs.lookup(in_msg.LineAddress);
24214184Sgabeblack@google.com
24314184Sgabeblack@google.com        assert(in_msg.Type == RubyRequestType:IFETCH);
24414184Sgabeblack@google.com        trigger(Event:Fetch, in_msg.LineAddress, cache_entry, tbe);
24514184Sgabeblack@google.com      }
24614184Sgabeblack@google.com    }
24714184Sgabeblack@google.com  }
24814184Sgabeblack@google.com
24914184Sgabeblack@google.com  // Actions
25014184Sgabeblack@google.com
25114184Sgabeblack@google.com  action(ic_invCache, "ic", desc="invalidate cache") {
25214184Sgabeblack@google.com    if(is_valid(cache_entry)) {
25314184Sgabeblack@google.com      L1cache.deallocate(address);
25414184Sgabeblack@google.com    }
25514184Sgabeblack@google.com    unset_cache_entry();
25614184Sgabeblack@google.com  }
25714184Sgabeblack@google.com
25814184Sgabeblack@google.com  action(nS_issueRdBlkS, "nS", desc="Issue RdBlkS") {
25914184Sgabeblack@google.com    enqueue(requestNetwork_out, CPURequestMsg, issue_latency) {
26014184Sgabeblack@google.com      out_msg.addr := address;
26114184Sgabeblack@google.com      out_msg.Type := CoherenceRequestType:RdBlk;
26214184Sgabeblack@google.com      out_msg.Requestor := machineID;
26314184Sgabeblack@google.com      out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
26414184Sgabeblack@google.com                              TCC_select_low_bit, TCC_select_num_bits));
26514184Sgabeblack@google.com      out_msg.MessageSize := MessageSizeType:Request_Control;
26614184Sgabeblack@google.com      out_msg.InitialRequestTime := curCycle();
26714184Sgabeblack@google.com    }
26814184Sgabeblack@google.com  }
26914184Sgabeblack@google.com
27014184Sgabeblack@google.com  action(a_allocate, "a", desc="allocate block") {
27114184Sgabeblack@google.com    if (is_invalid(cache_entry)) {
27214184Sgabeblack@google.com      set_cache_entry(L1cache.allocate(address, new Entry));
27314184Sgabeblack@google.com    }
27414184Sgabeblack@google.com  }
27514184Sgabeblack@google.com
27614184Sgabeblack@google.com  action(p_popMandatoryQueue, "pm", desc="Pop Mandatory Queue") {
27714184Sgabeblack@google.com    mandatoryQueue_in.dequeue(clockEdge());
27814184Sgabeblack@google.com  }
27914184Sgabeblack@google.com
28014184Sgabeblack@google.com  action(pr_popResponseQueue, "pr", desc="Pop Response Queue") {
28114184Sgabeblack@google.com    responseToSQC_in.dequeue(clockEdge());
28214184Sgabeblack@google.com  }
28314184Sgabeblack@google.com
28414184Sgabeblack@google.com  action(l_loadDone, "l", desc="local load done") {
28514184Sgabeblack@google.com    assert(is_valid(cache_entry));
28614184Sgabeblack@google.com    sequencer.readCallback(address, cache_entry.DataBlk, false, MachineType:L1Cache);
28714184Sgabeblack@google.com    APPEND_TRANSITION_COMMENT(cache_entry.DataBlk);
28814184Sgabeblack@google.com  }
28914184Sgabeblack@google.com
29014184Sgabeblack@google.com  action(w_writeCache, "w", desc="write data to cache") {
29114184Sgabeblack@google.com    peek(responseToSQC_in, ResponseMsg) {
29214184Sgabeblack@google.com      assert(is_valid(cache_entry));
29314184Sgabeblack@google.com      cache_entry.DataBlk := in_msg.DataBlk;
29414184Sgabeblack@google.com      cache_entry.Dirty := false;
29514184Sgabeblack@google.com    }
29614184Sgabeblack@google.com  }
29714184Sgabeblack@google.com
29814184Sgabeblack@google.com  // Transitions
29914184Sgabeblack@google.com
30014184Sgabeblack@google.com  // transitions from base
30114184Sgabeblack@google.com  transition({I, V}, Repl, I) {TagArrayRead, TagArrayWrite} {
30214184Sgabeblack@google.com    ic_invCache
30314184Sgabeblack@google.com  }
30414184Sgabeblack@google.com
30514184Sgabeblack@google.com  transition(I, Data, V) {TagArrayRead, TagArrayWrite, DataArrayRead} {
30614184Sgabeblack@google.com    a_allocate;
30714184Sgabeblack@google.com    w_writeCache
30814184Sgabeblack@google.com    l_loadDone;
30914184Sgabeblack@google.com    pr_popResponseQueue;
31014184Sgabeblack@google.com  }
31114184Sgabeblack@google.com
31214184Sgabeblack@google.com  transition(I, Fetch) {TagArrayRead, TagArrayWrite} {
31314184Sgabeblack@google.com    nS_issueRdBlkS;
31414184Sgabeblack@google.com    p_popMandatoryQueue;
31514184Sgabeblack@google.com  }
31614184Sgabeblack@google.com
31714184Sgabeblack@google.com  // simple hit transitions
31814184Sgabeblack@google.com  transition(V, Fetch) {TagArrayRead, DataArrayRead} {
31914184Sgabeblack@google.com    l_loadDone;
32014184Sgabeblack@google.com    p_popMandatoryQueue;
32114184Sgabeblack@google.com  }
32214184Sgabeblack@google.com}
323