/*
 * Copyright (c) 2021 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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.
 */

// Outbound port definitions

out_port(reqOutPort, CHIRequestMsg, reqOut);
out_port(snpOutPort, CHIRequestMsg, snpOut);
out_port(rspOutPort, CHIResponseMsg, rspOut);
out_port(datOutPort, CHIDataMsg, datOut);
out_port(triggerOutPort, TriggerMsg, triggerQueue);
out_port(retryTriggerOutPort, RetryTriggerMsg, retryTriggerQueue);
out_port(replTriggerOutPort, TriggerMsg, replTriggerQueue);
out_port(reqRdyOutPort, CHIRequestMsg, reqRdy);
out_port(snpRdyOutPort, CHIRequestMsg, snpRdy);


// Include helper functions here. Some of them require the outports to be
// already defined
// Notice 'processNextState' and 'wakeupPending*' functions are defined after
// the required input ports. Currently the SLICC compiler does not support
// separate declaration and definition of functions in the .sm files.
include "CHI-cache-funcs.sm";


// Inbound port definitions and internal triggers queues
// Notice we never stall input ports connected to the network
// Incoming data and responses are always consumed.
// Incoming requests/snoop are moved to the respective internal rdy queue
// if a TBE can be allocated, or retried otherwise.

// Trigger events from the UD_T state
in_port(useTimerTable_in, Addr, useTimerTable, rank=11) {
  if (useTimerTable_in.isReady(clockEdge())) {
      Addr readyAddress := useTimerTable.nextAddress();
      trigger(Event:UseTimeout, readyAddress, getCacheEntry(readyAddress),
              getCurrentActiveTBE(readyAddress));
  }
}


// Response
in_port(rspInPort, CHIResponseMsg, rspIn, rank=10,
        rsc_stall_handler=rspInPort_rsc_stall_handler) {
  if (rspInPort.isReady(clockEdge())) {
    printResources();
    peek(rspInPort, CHIResponseMsg) {
      TBE tbe := getCurrentActiveTBE(in_msg.addr);
      trigger(respToEvent(in_msg.type, tbe), in_msg.addr,
              getCacheEntry(in_msg.addr), tbe);
    }
  }
}
bool rspInPort_rsc_stall_handler() {
  error("rspInPort must never stall\n");
  return false;
}


// Data
in_port(datInPort, CHIDataMsg, datIn, rank=9,
        rsc_stall_handler=datInPort_rsc_stall_handler) {
  if (datInPort.isReady(clockEdge())) {
    printResources();
    peek(datInPort, CHIDataMsg) {
      int received := in_msg.bitMask.count();
      assert((received <= data_channel_size) && (received > 0));
      trigger(dataToEvent(in_msg.type), in_msg.addr,
              getCacheEntry(in_msg.addr), getCurrentActiveTBE(in_msg.addr));
    }
  }
}
bool datInPort_rsc_stall_handler() {
  error("datInPort must never stall\n");
  return false;
}


// Snoops with an allocated TBE
in_port(snpRdyPort, CHIRequestMsg, snpRdy, rank=8,
        rsc_stall_handler=snpRdyPort_rsc_stall_handler) {
  if (snpRdyPort.isReady(clockEdge())) {
    printResources();
    peek(snpRdyPort, CHIRequestMsg) {
      assert(in_msg.allowRetry == false);
      TBE tbe := getCurrentActiveTBE(in_msg.addr);
      if (is_valid(tbe) && tbe.hasUseTimeout) {
        // we may be in the BUSY_INTR waiting for a cache block, but if
        // the timeout is set the snoop must still wait, so trigger the
        // stall form here to prevent creating other states
        trigger(Event:SnpStalled, in_msg.addr,
                getCacheEntry(in_msg.addr), tbe);
      } else {
        trigger(snpToEvent(in_msg.type), in_msg.addr,
                getCacheEntry(in_msg.addr), tbe);
      }
    }
  }
}
bool snpRdyPort_rsc_stall_handler() {
  error("snpRdyPort must never stall\n");
  return false;
}
void wakeupPendingSnps(TBE tbe) {
  if (tbe.wakeup_pending_snp) {
    Addr addr := tbe.addr;
    wakeup_port(snpRdyPort, addr);
    tbe.wakeup_pending_snp := false;
  }
}


// Incoming snoops
// Not snoops are not retried, so the snoop channel is stalled if no
// Snp TBEs available
in_port(snpInPort, CHIRequestMsg, snpIn, rank=7) {
  if (snpInPort.isReady(clockEdge())) {
    assert(is_HN == false);
    printResources();
    peek(snpInPort, CHIRequestMsg) {
      assert(in_msg.allowRetry == false);
      trigger(Event:AllocSnoop, in_msg.addr,
              getCacheEntry(in_msg.addr), getCurrentActiveTBE(in_msg.addr));
    }
  }
}


// Retry action triggers
// These are handled before other triggers since a retried request should
// be enqueued ahead of a new request
// TODO: consider moving DoRetry to the triggerQueue
in_port(retryTriggerInPort, RetryTriggerMsg, retryTriggerQueue, rank=6,
        rsc_stall_handler=retryTriggerInPort_rsc_stall_handler) {
  if (retryTriggerInPort.isReady(clockEdge())) {
    printResources();
    peek(retryTriggerInPort, RetryTriggerMsg) {
      Event ev := in_msg.event;
      TBE tbe := getCurrentActiveTBE(in_msg.addr);
      assert((ev == Event:SendRetryAck) || (ev == Event:SendPCrdGrant) ||
              (ev == Event:DoRetry));
      if (ev == Event:DoRetry) {
        assert(is_valid(tbe));
        if (tbe.is_req_hazard || tbe.is_repl_hazard) {
          ev := Event:DoRetry_Hazard;
        }
      }
      trigger(ev, in_msg.addr, getCacheEntry(in_msg.addr), tbe);
    }
  }
}
bool retryTriggerInPort_rsc_stall_handler() {
  DPRINTF(RubySlicc, "Retry trigger queue resource stall\n");
  retryTriggerInPort.recycle(clockEdge(), cyclesToTicks(stall_recycle_lat));
  return true;
}


// Action triggers
in_port(triggerInPort, TriggerMsg, triggerQueue, rank=5,
        rsc_stall_handler=triggerInPort_rsc_stall_handler) {
  if (triggerInPort.isReady(clockEdge())) {
    printResources();
    peek(triggerInPort, TriggerMsg) {
      TBE tbe := getCurrentActiveTBE(in_msg.addr);
      assert(is_valid(tbe));
      if (in_msg.from_hazard != (tbe.is_req_hazard || tbe.is_repl_hazard)) {
        // possible when handling a snoop hazard and an action from the
        // the initial transaction got woken up. Stall the action until the
        // hazard ends
        assert(in_msg.from_hazard == false);
        assert(tbe.is_req_hazard || tbe.is_repl_hazard);
        trigger(Event:ActionStalledOnHazard, in_msg.addr,
                getCacheEntry(in_msg.addr), tbe);
      } else {
        trigger(tbe.pendAction, in_msg.addr, getCacheEntry(in_msg.addr), tbe);
      }
    }
  }
}
bool triggerInPort_rsc_stall_handler() {
  DPRINTF(RubySlicc, "Trigger queue resource stall\n");
  triggerInPort.recycle(clockEdge(), cyclesToTicks(stall_recycle_lat));
  return true;
}
void wakeupPendingTgrs(TBE tbe) {
  if (tbe.wakeup_pending_tgr) {
    Addr addr := tbe.addr;
    wakeup_port(triggerInPort, addr);
    tbe.wakeup_pending_tgr := false;
  }
}


// internally triggered evictions
// no stall handler for this one since it doesn't make sense try the next
// request when out of TBEs
in_port(replTriggerInPort, ReplacementMsg, replTriggerQueue, rank=4) {
  if (replTriggerInPort.isReady(clockEdge())) {
    printResources();
    peek(replTriggerInPort, ReplacementMsg) {
      TBE tbe := getCurrentActiveTBE(in_msg.addr);
      CacheEntry cache_entry := getCacheEntry(in_msg.addr);
      Event trigger := Event:null;
      if (is_valid(cache_entry) &&
          ((upstreamHasUnique(cache_entry.state) && dealloc_backinv_unique) ||
          (upstreamHasShared(cache_entry.state) && dealloc_backinv_shared))) {
        trigger := Event:Global_Eviction;
      } else {
        if (is_HN) {
          trigger := Event:LocalHN_Eviction;
        } else {
          trigger := Event:Local_Eviction;
        }
      }
      trigger(trigger, in_msg.addr, cache_entry, tbe);
    }
  }
}


// Requests with an allocated TBE
in_port(reqRdyPort, CHIRequestMsg, reqRdy, rank=3,
        rsc_stall_handler=reqRdyPort_rsc_stall_handler) {
  if (reqRdyPort.isReady(clockEdge())) {
    printResources();
    peek(reqRdyPort, CHIRequestMsg) {
      CacheEntry cache_entry := getCacheEntry(in_msg.addr);
      TBE tbe := getCurrentActiveTBE(in_msg.addr);

      DirEntry dir_entry := getDirEntry(in_msg.addr);

      // Special case for possibly stale writebacks or evicts
      if (in_msg.type == CHIRequestType:WriteBackFull) {
        if (is_invalid(dir_entry) || (dir_entry.ownerExists == false) ||
            (dir_entry.owner != in_msg.requestor)) {
          trigger(Event:WriteBackFull_Stale, in_msg.addr, cache_entry, tbe);
        }
      } else if (in_msg.type == CHIRequestType:WriteEvictFull) {
        if (is_invalid(dir_entry) || (dir_entry.ownerExists == false) ||
            (dir_entry.ownerIsExcl == false) || (dir_entry.owner != in_msg.requestor)) {
          trigger(Event:WriteEvictFull_Stale, in_msg.addr, cache_entry, tbe);
        }
      } else if (in_msg.type == CHIRequestType:WriteCleanFull) {
        if (is_invalid(dir_entry) || (dir_entry.ownerExists == false) ||
            (dir_entry.ownerIsExcl == false) || (dir_entry.owner != in_msg.requestor)) {
          trigger(Event:WriteCleanFull_Stale, in_msg.addr, cache_entry, tbe);
        }
      } else if (in_msg.type == CHIRequestType:Evict) {
        if (is_invalid(dir_entry) ||
            (dir_entry.sharers.isElement(in_msg.requestor) == false)) {
          trigger(Event:Evict_Stale, in_msg.addr, cache_entry, tbe);
        }
      }

      // Normal request path
      trigger(reqToEvent(in_msg.type, in_msg.is_local_pf), in_msg.addr, cache_entry, tbe);
    }
  }
}
bool reqRdyPort_rsc_stall_handler() {
  DPRINTF(RubySlicc, "ReqRdy queue resource stall\n");
  reqRdyPort.recycle(clockEdge(), cyclesToTicks(stall_recycle_lat));
  return true;
}
void wakeupPendingReqs(TBE tbe) {
  if (tbe.wakeup_pending_req) {
    Addr addr := tbe.addr;
    wakeup_port(reqRdyPort, addr);
    tbe.wakeup_pending_req := false;
  }
}


// Incoming new requests
in_port(reqInPort, CHIRequestMsg, reqIn, rank=2,
        rsc_stall_handler=reqInPort_rsc_stall_handler) {
  if (reqInPort.isReady(clockEdge())) {
    printResources();
    peek(reqInPort, CHIRequestMsg) {
      if (in_msg.allowRetry) {
        trigger(Event:AllocRequest, in_msg.addr,
              getCacheEntry(in_msg.addr), getCurrentActiveTBE(in_msg.addr));
      } else {
        trigger(Event:AllocRequestWithCredit, in_msg.addr,
              getCacheEntry(in_msg.addr), getCurrentActiveTBE(in_msg.addr));
      }
    }
  }
}
bool reqInPort_rsc_stall_handler() {
  error("reqInPort must never stall\n");
  return false;
}


// Incoming new sequencer requests
in_port(seqInPort, RubyRequest, mandatoryQueue, rank=1) {
  if (seqInPort.isReady(clockEdge())) {
    printResources();
    peek(seqInPort, RubyRequest) {
      trigger(Event:AllocSeqRequest, in_msg.LineAddress,
              getCacheEntry(in_msg.LineAddress),
              getCurrentActiveTBE(in_msg.LineAddress));
    }
  }
}


// Incoming new prefetch requests
in_port(pfInPort, RubyRequest, prefetchQueue, rank=0) {
  if (pfInPort.isReady(clockEdge())) {
    printResources();
    peek(pfInPort, RubyRequest) {
      trigger(Event:AllocPfRequest, in_msg.LineAddress,
              getCacheEntry(in_msg.LineAddress),
              getCurrentActiveTBE(in_msg.LineAddress));
    }
  }
}

void processNextState(Addr address, TBE tbe, CacheEntry cache_entry) {
  assert(is_valid(tbe));
  DPRINTF(RubySlicc, "GoToNextState expected_req_resp=%d expected_snp_resp=%d snd_pendEv=%d snd_pendBytes=%d\n",
                      tbe.expected_req_resp.expected(),
                      tbe.expected_snp_resp.expected(),
                      tbe.snd_pendEv, tbe.snd_pendBytes.count());

  // if no pending trigger and not expecting to receive anything, enqueue
  // next
  bool has_nb_trigger := (tbe.actions.empty() == false) &&
                          tbe.actions.frontNB() &&
                          (tbe.snd_pendEv == false);
  int expected_msgs := tbe.expected_req_resp.expected() +
                        tbe.expected_snp_resp.expected() +
                        tbe.snd_pendBytes.count();
  if ((tbe.pendAction == Event:null) && ((expected_msgs == 0) || has_nb_trigger)) {
    Cycles trigger_latency := intToCycles(0);
    if (tbe.delayNextAction > curTick()) {
      trigger_latency := ticksToCycles(tbe.delayNextAction) -
                          ticksToCycles(curTick());
      tbe.delayNextAction := intToTick(0);
    }

    tbe.pendAction := Event:null;
    if (tbe.actions.empty()) {
      // time to go to the final state
      tbe.pendAction := Event:Final;
    } else {
      tbe.pendAction := tbe.actions.front();
      tbe.actions.pop();
    }
    assert(tbe.pendAction != Event:null);
    enqueue(triggerOutPort, TriggerMsg, trigger_latency) {
      out_msg.addr := tbe.addr;
      out_msg.from_hazard := tbe.is_req_hazard || tbe.is_repl_hazard;
    }
  }

  printTBEState(tbe);

  // we might be going to BUSY_INTERRUPTABLE so wakeup pending snoops
  // if any
  wakeupPendingSnps(tbe);
}
