/*
 * 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(MachineType:L1Cache, "MI Example L1 Cache")
    : 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",
            vnet_type="request";
      MessageBuffer * responseFromCache, network="To", virtual_network="4",
            vnet_type="response";

      MessageBuffer * forwardToCache, network="From", virtual_network="3",
            vnet_type="forward";
      MessageBuffer * responseToCache, network="From", virtual_network="4",
            vnet_type="response";

      MessageBuffer * mandatoryQueue;
{
  // STATES
  state_declaration(State, desc="Cache states") {
    I, AccessPermission:Invalid, desc="Not Present/Invalid";
    II, AccessPermission:Busy, desc="Not Present/Invalid, issued PUT";
    M, AccessPermission:Read_Write, desc="Modified";
    MI, AccessPermission:Busy, desc="Modified, issued PUT";
    MII, AccessPermission:Busy, desc="Modified, issued PUTX, received nack";

    IS, AccessPermission:Busy, desc="Issued request for LOAD/IFETCH";
    IM, AccessPermission:Busy, desc="Issued request for STORE/ATOMIC";
  }

  // EVENTS
  enumeration(Event, desc="Cache events") {
    // From processor

    Load,       desc="Load request from processor";
    Ifetch,     desc="Ifetch request from processor";
    Store,      desc="Store request from processor";

    Data,       desc="Data from network";
    Fwd_GETX,        desc="Forward from network";

    Inv,        desc="Invalidate request from dir";

    Replacement,  desc="Replace a block";
    Writeback_Ack,   desc="Ack from the directory for a writeback";
    Writeback_Nack,   desc="Nack from the directory for a writeback";
  }

  // STRUCTURE DEFINITIONS
  // CacheEntry
  structure(Entry, desc="...", interface="AbstractCacheEntry") {
    State CacheState,        desc="cache state";
    bool Dirty,              desc="Is the data dirty (different than memory)?";
    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(Addr);
    void allocate(Addr);
    void deallocate(Addr);
    bool isPresent(Addr);
  }


  // STRUCTURES
  TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs";

  // PROTOTYPES
  Tick clockEdge();
  Cycles ticksToCycles(Tick t);
  void set_cache_entry(AbstractCacheEntry a);
  void unset_cache_entry();
  void set_tbe(TBE b);
  void unset_tbe();
  void profileMsgDelay(int virtualNetworkType, Cycles b);
  MachineID mapAddressToMachine(Addr addr, MachineType mtype);

  Entry getCacheEntry(Addr address), return_by_pointer="yes" {
    return static_cast(Entry, "pointer", cacheMemory.lookup(address));
  }

  // FUNCTIONS
  Event mandatory_request_type_to_event(RubyRequestType type) {
   if (type == RubyRequestType:LD) {
      return Event:Load;
    } else if (type == RubyRequestType:IFETCH) {
      return Event:Ifetch;
    } else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)) {
      return Event:Store;
    } else {
      error("Invalid RubyRequestType");
    }
  }

  State getState(TBE tbe, Entry cache_entry, Addr addr) {

    if (is_valid(tbe)) {
      return tbe.TBEState;
    }
    else if (is_valid(cache_entry)) {
      return cache_entry.CacheState;
    }
    else {
      return State:I;
    }
  }

  void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {

    if (is_valid(tbe)) {
      tbe.TBEState := state;
    }

    if (is_valid(cache_entry)) {
      cache_entry.CacheState := state;
    }
  }

  AccessPermission getAccessPermission(Addr addr) {
    TBE tbe := TBEs[addr];
    if(is_valid(tbe)) {
      return L1Cache_State_to_permission(tbe.TBEState);
    }

    Entry cache_entry := getCacheEntry(addr);
    if(is_valid(cache_entry)) {
      return L1Cache_State_to_permission(cache_entry.CacheState);
    }

    return AccessPermission:NotPresent;
  }

  void setAccessPermission(Entry cache_entry, Addr addr, State state) {
    if (is_valid(cache_entry)) {
      cache_entry.changePermission(L1Cache_State_to_permission(state));
    }
  }

  void functionalRead(Addr addr, Packet *pkt) {
    TBE tbe := TBEs[addr];
    if(is_valid(tbe)) {
      testAndRead(addr, tbe.DataBlk, pkt);
    } else {
      testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
    }
  }

  int functionalWrite(Addr addr, Packet *pkt) {
    int num_functional_writes := 0;

    TBE tbe := TBEs[addr];
    if(is_valid(tbe)) {
      num_functional_writes := num_functional_writes +
        testAndWrite(addr, tbe.DataBlk, pkt);
      return num_functional_writes;
    }

    num_functional_writes := num_functional_writes +
        testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
    return num_functional_writes;
  }

  // NETWORK PORTS

  out_port(requestNetwork_out, RequestMsg, requestFromCache);
  out_port(responseNetwork_out, ResponseMsg, responseFromCache);

  in_port(forwardRequestNetwork_in, RequestMsg, forwardToCache) {
    if (forwardRequestNetwork_in.isReady(clockEdge())) {
      peek(forwardRequestNetwork_in, RequestMsg, block_on="addr") {

        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.addr, cache_entry, tbe);
        }
        else if (in_msg.Type == CoherenceRequestType:WB_ACK) {
          trigger(Event:Writeback_Ack, in_msg.addr, cache_entry, tbe);
        }
        else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
          trigger(Event:Writeback_Nack, in_msg.addr, cache_entry, tbe);
        }
        else if (in_msg.Type == CoherenceRequestType:INV) {
          trigger(Event:Inv, in_msg.addr, cache_entry, tbe);
        }
        else {
          error("Unexpected message");
        }
      }
    }
  }

  in_port(responseNetwork_in, ResponseMsg, responseToCache) {
    if (responseNetwork_in.isReady(clockEdge())) {
      peek(responseNetwork_in, ResponseMsg, block_on="addr") {

        Entry cache_entry := getCacheEntry(in_msg.addr);
        TBE tbe := TBEs[in_msg.addr];

        if (in_msg.Type == CoherenceResponseType:DATA) {
          trigger(Event:Data, in_msg.addr, cache_entry, tbe);
        }
        else {
          error("Unexpected message");
        }
      }
    }
  }

    // Mandatory Queue
  in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...") {
    if (mandatoryQueue_in.isReady(clockEdge())) {
      peek(mandatoryQueue_in, RubyRequest, block_on="LineAddress") {

        Entry cache_entry := getCacheEntry(in_msg.LineAddress);
        if (is_invalid(cache_entry) &&
            cacheMemory.cacheAvail(in_msg.LineAddress) == false ) {
          // make room for the block
          trigger(Event:Replacement, cacheMemory.cacheProbe(in_msg.LineAddress),
                  getCacheEntry(cacheMemory.cacheProbe(in_msg.LineAddress)),
                  TBEs[cacheMemory.cacheProbe(in_msg.LineAddress)]);
        }
        else {
          trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
                  cache_entry, TBEs[in_msg.LineAddress]);
        }
      }
    }
  }

  // ACTIONS

  action(a_issueRequest, "a", desc="Issue a request") {
    enqueue(requestNetwork_out, RequestMsg, issue_latency) {
    out_msg.addr := address;
      out_msg.Type := CoherenceRequestType:GETX;
      out_msg.Requestor := machineID;
      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
      out_msg.MessageSize := MessageSizeType:Control;
    }
  }

  action(b_issuePUT, "b", desc="Issue a PUT request") {
    enqueue(requestNetwork_out, RequestMsg, issue_latency) {
      assert(is_valid(cache_entry));
      out_msg.addr := address;
      out_msg.Type := CoherenceRequestType:PUTX;
      out_msg.Requestor := machineID;
      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
      out_msg.DataBlk := cache_entry.DataBlk;
      out_msg.MessageSize := MessageSizeType:Data;
    }
  }

  action(e_sendData, "e", desc="Send data from cache to requestor") {
    peek(forwardRequestNetwork_in, RequestMsg) {
      enqueue(responseNetwork_out, ResponseMsg, cache_response_latency) {
        assert(is_valid(cache_entry));
        out_msg.addr := address;
        out_msg.Type := CoherenceResponseType:DATA;
        out_msg.Sender := machineID;
        out_msg.Destination.add(in_msg.Requestor);
        out_msg.DataBlk := cache_entry.DataBlk;
        out_msg.MessageSize := MessageSizeType:Response_Data;
      }
    }
  }

  action(ee_sendDataFromTBE, "\e", desc="Send data from TBE to requestor") {
    peek(forwardRequestNetwork_in, RequestMsg) {
      enqueue(responseNetwork_out, ResponseMsg, cache_response_latency) {
        assert(is_valid(tbe));
        out_msg.addr := address;
        out_msg.Type := CoherenceResponseType:DATA;
        out_msg.Sender := machineID;
        out_msg.Destination.add(in_msg.Requestor);
        out_msg.DataBlk := tbe.DataBlk;
        out_msg.MessageSize := MessageSizeType:Response_Data;
      }
    }
  }

  action(i_allocateL1CacheBlock, "i", desc="Allocate a cache block") {
    if (is_valid(cache_entry)) {
    } else {
      set_cache_entry(cacheMemory.allocate(address, new Entry));
    }
  }

  action(h_deallocateL1CacheBlock, "h", desc="deallocate a cache block") {
    if (is_valid(cache_entry)) {
      cacheMemory.deallocate(address);
      unset_cache_entry();
    }
  }

  action(m_popMandatoryQueue, "m", desc="Pop the mandatory request queue") {
    mandatoryQueue_in.dequeue(clockEdge());
  }

  action(n_popResponseQueue, "n", desc="Pop the response queue") {
    Tick delay := responseNetwork_in.dequeue(clockEdge());
    profileMsgDelay(1, ticksToCycles(delay));
  }

  action(o_popForwardedRequestQueue, "o", desc="Pop the forwarded request queue") {
    Tick delay := forwardRequestNetwork_in.dequeue(clockEdge());
    profileMsgDelay(2, ticksToCycles(delay));
  }

  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);
    cacheMemory.setMRU(cache_entry);
    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);
      cacheMemory.setMRU(cache_entry);
      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);
    cacheMemory.setMRU(cache_entry);
    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);
      cacheMemory.setMRU(cache_entry);
      sequencer.writeCallback(address, cache_entry.DataBlk, true,
                              machineIDToMachineType(in_msg.Sender));
    }
  }

  action(u_writeDataToCache, "u", desc="Write data to the cache") {
    peek(responseNetwork_in, ResponseMsg) {
      assert(is_valid(cache_entry));
      cache_entry.DataBlk := in_msg.DataBlk;
    }
  }

  action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") {
    if (send_evictions) {
      DPRINTF(RubySlicc, "Sending invalidation for %#x 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();
  }

  action(x_copyDataFromCacheToTBE, "x", desc="Copy data from cache to TBE") {
    assert(is_valid(cache_entry));
    assert(is_valid(tbe));
    tbe.DataBlk := cache_entry.DataBlk;
  }

  action(z_stall, "z", desc="stall") {
    // do nothing
  }

  // TRANSITIONS

  transition({IS, IM, MI, II, MII}, {Load, Ifetch, Store, Replacement}) {
    z_stall;
  }

  transition({IS, IM}, {Fwd_GETX, Inv}) {
    z_stall;
  }

  transition(MI, Inv) {
    o_popForwardedRequestQueue;
  }

  transition(M, Store) {
    s_store_hit;
    p_profileHit;
    m_popMandatoryQueue;
  }

  transition(M, {Load, Ifetch}) {
    r_load_hit;
    p_profileHit;
    m_popMandatoryQueue;
  }

  transition(I, Inv) {
    o_popForwardedRequestQueue;
  }

  transition(I, Store, IM) {
    v_allocateTBE;
    i_allocateL1CacheBlock;
    a_issueRequest;
    p_profileMiss;
    m_popMandatoryQueue;
  }

  transition(I, {Load, Ifetch}, IS) {
    v_allocateTBE;
    i_allocateL1CacheBlock;
    a_issueRequest;
    p_profileMiss;
    m_popMandatoryQueue;
  }

  transition(IS, Data, M) {
    u_writeDataToCache;
    rx_load_hit;
    w_deallocateTBE;
    n_popResponseQueue;
  }

  transition(IM, Data, M) {
    u_writeDataToCache;
    sx_store_hit;
    w_deallocateTBE;
    n_popResponseQueue;
  }

  transition(M, Fwd_GETX, I) {
    e_sendData;
    forward_eviction_to_cpu;
    o_popForwardedRequestQueue;
  }

  transition(I, Replacement) {
     h_deallocateL1CacheBlock;
  }

  transition(M, {Replacement,Inv},  MI) {
     v_allocateTBE;
     b_issuePUT;
     x_copyDataFromCacheToTBE;
     forward_eviction_to_cpu;
     h_deallocateL1CacheBlock;
  }

  transition(MI, Writeback_Ack, I) {
    w_deallocateTBE;
    o_popForwardedRequestQueue;
  }

  transition(MI, Fwd_GETX, II) {
    ee_sendDataFromTBE;
    o_popForwardedRequestQueue;
  }

  transition(MI, Writeback_Nack, MII) {
    o_popForwardedRequestQueue;
  }

  transition(MII, Fwd_GETX, I) {
    ee_sendDataFromTBE;
    w_deallocateTBE;
    o_popForwardedRequestQueue;
  }

  transition(II, Writeback_Nack, I) {
    w_deallocateTBE;
    o_popForwardedRequestQueue;
  }
}
