/*
 * Copyright (c) 2021-2022 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.
 */


////////////////////////////////////////////////////////////////////////////
// CHI-dvm-misc-node actions definitions
////////////////////////////////////////////////////////////////////////////

action(AllocateTBE_Request, desc="") {
  peek(reqInPort, CHIRequestMsg) {
    assert(in_msg.usesTxnId);
    assert(in_msg.txnId == address);
    assert(in_msg.is_local_pf == false);
    assert(in_msg.allowRetry);

    bool isNonSync := (in_msg.type == CHIRequestType:DvmOpNonSync);

    if (storDvmTBEs.areNSlotsAvailable(1, tbePartition(isNonSync))) {
      // reserve a slot for this request
      storDvmTBEs.incrementReserved(tbePartition(isNonSync));

      // Move request to rdy queue
      peek(reqInPort, CHIRequestMsg) {
        enqueue(reqRdyOutPort, CHIRequestMsg, allocation_latency) {
          out_msg := in_msg;
        }
      }

    } else {
      // we don't have resources to track this request; enqueue a retry
      enqueue(retryTriggerOutPort, RetryTriggerMsg, retry_ack_latency) {
        out_msg.txnId := in_msg.txnId;
        out_msg.event := Event:SendRetryAck;
        out_msg.retryDest := in_msg.requestor;

        RetryQueueEntry en;
        en.txnId := in_msg.txnId;
        en.retryDest := in_msg.requestor;
        en.isNonSync := isNonSync;
        storDvmTBEs.emplaceRetryEntry(en);
      }
    }
  }


  reqInPort.dequeue(clockEdge());
}

action(AllocateTBE_Request_WithCredit, desc="") {
  // TBE slot already reserved
  // Move request to rdy queue
  peek(reqInPort, CHIRequestMsg) {
    assert(in_msg.allowRetry == false);
    assert(in_msg.usesTxnId);
    enqueue(reqRdyOutPort, CHIRequestMsg, allocation_latency) {
      assert(in_msg.txnId == address);
      out_msg := in_msg;
    }
  }
  reqInPort.dequeue(clockEdge());
}

action(Initiate_Request_DVM, desc="") {
  bool was_retried := false;
  peek(reqRdyPort, CHIRequestMsg) {
    // "address" for DVM = transaction ID
    TBE tbe := allocateDvmRequestTBE(address, in_msg);
    set_tbe(tbe);
    // only a msg that was already retried doesn't allow a retry
    was_retried := in_msg.allowRetry == false;
  }

  // Last argument = false, so it isn't treated as a memory request
  incomingTransactionStart(address, curTransitionEvent(), State:Unallocated, was_retried, false);
}

action(Pop_ReqRdyQueue, desc="") {
  reqRdyPort.dequeue(clockEdge());
}


action(Receive_ReqDataResp, desc="") {
  assert(is_valid(tbe));
  assert(tbe.expected_req_resp.hasExpected());
  peek(datInPort, CHIDataMsg) {
    // Decrement pending
    if (tbe.expected_req_resp.receiveData(in_msg.type) == false) {
      error("Received unexpected message");
    }
    assert(!tbe.expected_req_resp.hasExpected());

    DPRINTF(RubyProtocol, "Misc Node has receieved NCBWrData\n");
    // Clear the "expected types" list to prepare for the snooping
    tbe.expected_snp_resp.clear(1);
    assert(!tbe.expected_snp_resp.hasExpected());

    // We don't actually use the data contents
  }
}

action(Pop_DataInQueue, desc="") {
  datInPort.dequeue(clockEdge());
}

action(Receive_SnpResp, desc="") {
  assert(tbe.expected_snp_resp.hasExpected());
  peek(rspInPort, CHIResponseMsg) {
    // Decrement pending
    if (tbe.expected_snp_resp.receiveResp(in_msg.type) == false) {
      error("Received unexpected message");
    }
    assert(in_msg.stale == false);
    // assert(in_msg.stale == tbe.is_stale);

    DPRINTF(RubyProtocol, "Misc Node has receieved SnpResp_I\n");

    assert(tbe.pendingTargets.isElement(in_msg.responder));
    tbe.pendingTargets.remove(in_msg.responder);
    tbe.receivedTargets.add(in_msg.responder);
  }
}
action(Pop_RespInQueue, desc="") {
  rspInPort.dequeue(clockEdge());
}

action(ProcessNextState, desc="") {
  assert(is_valid(tbe));
  processNextState(tbe);
}

// If ProcessNextState invokes a new action, it sets tbe.pendingAction.
// If you call ProcessNextState again without clearing this variable,
// nothing will happen. This Action clears the pending state, ensuring
// a new state is processed.
action(ProcessNextState_ClearPending, desc="") {
  assert(is_valid(tbe));
  clearPendingAction(tbe);
  processNextState(tbe);
}

action(Send_Comp, desc="") {
  assert(is_valid(tbe));
  Cycles latency := response_latency;
  CHIResponseType type := CHIResponseType:Comp;

  enqueue(rspOutPort, CHIResponseMsg, latency) {
    out_msg.addr := address;
    out_msg.type := type;
    out_msg.responder := machineID;
    out_msg.txnId := address;
    out_msg.usesTxnId := true;
    out_msg.Destination.add(tbe.requestor);
  }
  DPRINTF(RubyProtocol, "Misc Node Sending Comp (for either)\n");
}

action(Send_Comp_NonSync, desc="") {
  assert(is_valid(tbe));

  // In the NonSync case, if early_nonsync_comp is set then
  // we will have already sent a CompDBIDResp.
  // Thus, only send Comp if !early_nonsync_comp

  if (!early_nonsync_comp) {
    Cycles latency := response_latency;
    CHIResponseType type := CHIResponseType:Comp;
    enqueue(rspOutPort, CHIResponseMsg, latency) {
        out_msg.addr := address;
        out_msg.type := type;
        out_msg.responder := machineID;
        out_msg.txnId := address;
        out_msg.usesTxnId := true;
        out_msg.Destination.add(tbe.requestor);
    }
    DPRINTF(RubyProtocol, "Misc Node Sending TLBI Comp\n");
  }
}

// NOTICE a trigger event may wakeup another stalled trigger event so
// this is always called first in the transitions so we don't pop the
// wrong message
action(Pop_TriggerQueue, desc="") {
  triggerInPort.dequeue(clockEdge());
}

action(Pop_RetryTriggerQueue, desc="") {
  retryTriggerInPort.dequeue(clockEdge());
}

action(Finalize_DeallocateRequest, desc="") {
  assert(is_valid(tbe));
  assert(tbe.actions.empty());
  wakeupPendingReqs(tbe);
  wakeupPendingTgrs(tbe);

  DPRINTF(RubyProtocol, "Deallocating DVM request\n");
  deallocateDvmTBE(tbe);
  processRetryQueue();
  unset_tbe();

  // Last argument = false, so this isn't treated as a memory transaction
  incomingTransactionEnd(address, curTransitionNextState(), false);
}

action(Send_DvmNonSyncDBIDResp, desc="") {
  Cycles latency := response_latency;
  CHIResponseType type := CHIResponseType:DBIDResp;
  if (early_nonsync_comp) {
    type := CHIResponseType:CompDBIDResp;
  }
  enqueue(rspOutPort, CHIResponseMsg, latency) {
    out_msg.addr := address;
    out_msg.type := type;
    out_msg.responder := machineID;
    out_msg.txnId := address;
    out_msg.usesTxnId := true;
    out_msg.Destination.add(tbe.requestor);
  }
  tbe.expected_req_resp.clear(1);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:NCBWrData);
  tbe.expected_req_resp.setExpectedCount(1);
  DPRINTF(RubyProtocol, "Misc Node Sending TLBI DBIDResp\n");
}

action(Send_DvmSyncDBIDResp, desc="") {
  Cycles latency := response_latency;
  CHIResponseType type := CHIResponseType:DBIDResp;
  enqueue(rspOutPort, CHIResponseMsg, latency) {
    out_msg.addr := address;
    out_msg.type := type;
    out_msg.responder := machineID;
    out_msg.txnId := address;
    out_msg.usesTxnId := true;
    out_msg.Destination.add(tbe.requestor);
  }
  tbe.expected_req_resp.clear(1);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:NCBWrData);
  tbe.expected_req_resp.setExpectedCount(1);
  DPRINTF(RubyProtocol, "Misc Node Sending Sync DBIDResp\n");
}

action(Send_RetryAck, desc="") {
  peek(retryTriggerInPort, RetryTriggerMsg) {
    enqueue(rspOutPort, CHIResponseMsg, response_latency) {
      out_msg.txnId := in_msg.txnId;
      out_msg.usesTxnId := true;
      out_msg.type := CHIResponseType:RetryAck;
      out_msg.responder := machineID;
      out_msg.Destination.add(in_msg.retryDest);
    }
    DPRINTF(RubyProtocol, "Misc Node Sending RetryAck (for either)\n");
  }
}

action(Send_PCrdGrant, desc="") {
  peek(retryTriggerInPort, RetryTriggerMsg) {
    enqueue(rspOutPort, CHIResponseMsg, response_latency) {
      out_msg.txnId := in_msg.txnId;
      out_msg.usesTxnId := true;
      out_msg.type := CHIResponseType:PCrdGrant;
      out_msg.responder := machineID;
      out_msg.Destination.add(in_msg.retryDest);
    }
    DPRINTF(RubyProtocol, "Misc Node Sending PCrdGrant (for either)\n");
  }
}

action(Send_DvmSnoop_P1, desc="") {
  Cycles latency := response_latency;

  CHIRequestType type := CHIRequestType:SnpDvmOpSync_P1;
  if (tbe.isNonSync) {
    type := CHIRequestType:SnpDvmOpNonSync_P1;
  }

  assert(tbe.notSentTargets.count() > 0);
  MachineID target := tbe.notSentTargets.smallestElement();

  enqueue(snpOutPort, CHIRequestMsg, latency) {
    prepareRequest(tbe, type, out_msg);
    DPRINTF(RubyProtocol, "Misc Node Sending %d to %d\n", type, target);

    out_msg.usesTxnId := true;
    out_msg.txnId := tbe.txnId; // for DVM TBEs addr = txnId
    out_msg.allowRetry := false;
    out_msg.Destination.clear();
    out_msg.Destination.add(target);

    out_msg.dataToFwdRequestor := false;
  }

  tbe.actions.pushNB(Event:DvmSendNextMessage_P2);
  tbe.delayNextAction := curTick() + cyclesToTicks(intToCycles(1));

  // We are no longer waiting on other transaction activity
  tbe.waiting_on_other_txns := false;
}

action(Send_DvmSnoop_P2, desc="") {
  Cycles latency := response_latency;

  CHIRequestType type := CHIRequestType:SnpDvmOpSync_P2;
  if (tbe.isNonSync) {
    type := CHIRequestType:SnpDvmOpNonSync_P2;
  }

  assert(tbe.notSentTargets.count() > 0);
  MachineID target := tbe.notSentTargets.smallestElement();

  enqueue(snpOutPort, CHIRequestMsg, latency) {
    prepareRequest(tbe, type, out_msg);
    DPRINTF(RubyProtocol, "Misc Node Sending %d to %d\n", type, target);

    out_msg.usesTxnId := true;
    out_msg.txnId := tbe.txnId; // for DVM TBEs addr = txnId
    out_msg.allowRetry := false;
    out_msg.Destination.clear();
    out_msg.Destination.add(target);

    out_msg.dataToFwdRequestor := false;
  }

  // Expect a SnpResp_I now we have sent both
  tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_I);
  tbe.expected_snp_resp.addExpectedCount(1);

  // Pop the target we just completed off the list
  tbe.notSentTargets.remove(target);
  tbe.pendingTargets.add(target);
  // If we have more targets, enqueue another send
  if (tbe.notSentTargets.count() > 0) {
    tbe.actions.pushNB(Event:DvmSendNextMessage_P1);
  } else {
    // otherwise enqueue a DvmFinishDistributing, then a blocking DvmFinishWaiting
    // DvmFinishDistributing will be called immediately,
    // DvmFinishWaiting will be called once all responses are received
    tbe.actions.pushNB(Event:DvmFinishDistributing);
    tbe.actions.push(Event:DvmFinishWaiting);
  }
  tbe.delayNextAction := curTick() + cyclesToTicks(intToCycles(1));
}

action(Enqueue_UpdatePendingOps, desc="") {
  // The next time updatePendingOps runs
  // it will check this variable and decide
  // to actually check for a new sender
  DPRINTF(RubyProtocol, "Enqueue_UpdatePendingOps from %016x\n", address);
  needsToCheckPendingOps := true;
  // Schedule a generic event to make sure we wake up
  // on the next tick
  scheduleEvent(intToCycles(1));
}

action(Profile_OutgoingEnd_DVM, desc="") {
  assert(is_valid(tbe));
  // Outgoing transactions = time to send all snoops
  // Is never rejected by recipient => never received retry ack
  bool rcvdRetryAck := false;
  outgoingTransactionEnd(address, rcvdRetryAck, false);
}
