/*
 * 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-cache actions definitions
////////////////////////////////////////////////////////////////////////////

action(AllocateTBE_Request, desc="") {
  if (storTBEs.areNSlotsAvailable(1)) {
    // reserve a slot for this request
    storTBEs.incrementReserved();

    // Move request to rdy queue
    peek(reqInPort, CHIRequestMsg) {
      enqueue(reqRdyOutPort, CHIRequestMsg, allocation_latency) {
        assert(in_msg.addr == address);
        assert(in_msg.is_local_pf == false);
        out_msg := in_msg;
      }
    }

  } else {
    // we don't have resources to track this request; enqueue a retry
    peek(reqInPort, CHIRequestMsg) {
      assert(in_msg.allowRetry);
      enqueue(retryTriggerOutPort, RetryTriggerMsg, 0) {
        out_msg.addr := in_msg.addr;
        out_msg.usesTxnId := false;
        out_msg.event := Event:SendRetryAck;
        out_msg.retryDest := in_msg.requestor;
        retryQueue.emplace(in_msg.addr,false,in_msg.requestor);
      }
    }
  }

  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);
    enqueue(reqRdyOutPort, CHIRequestMsg, allocation_latency) {
      assert(in_msg.addr == address);
      out_msg := in_msg;
    }
  }
  reqInPort.dequeue(clockEdge());
}

action(AllocateTBE_Snoop, desc="") {
  // No retry for snoop requests; just create resource stall
  check_allocate(storSnpTBEs);

  storSnpTBEs.incrementReserved();

  // Move request to rdy queue
  peek(snpInPort, CHIRequestMsg) {
    enqueue(snpRdyOutPort, CHIRequestMsg, allocation_latency) {
      assert(in_msg.addr == address);
      out_msg := in_msg;
    }

    // also remove snoop source from waiting retry destinations to prevent
    // deadlocks in which this snoop is blocked by a transaction that needs to
    // send a request to the snoop destination before going to BUSY_INTR,
    // but the destination needs the snoop to complete before sending retry
    // credit
    destsWaitingRetry.remove(in_msg.requestor);
  }
  snpInPort.dequeue(clockEdge());
}

action(AllocateTBE_DvmSnoop, desc="") {
  // No retry for snoop requests; just create resource stall
  check_allocate(storDvmSnpTBEs);

  storDvmSnpTBEs.incrementReserved();

  // Move request to rdy queue
  peek(snpInPort, CHIRequestMsg) {
    enqueue(snpRdyOutPort, CHIRequestMsg, allocation_latency) {
      assert(in_msg.usesTxnId);
      assert(in_msg.addr == address);
      out_msg := in_msg;
    }
  }
  snpInPort.dequeue(clockEdge());
}

action(AllocateTBE_SeqRequest, desc="") {
  // No retry for sequencer requests; just create resource stall
  check_allocate(storTBEs);

  // reserve a slot for this request
  storTBEs.incrementReserved();

  // Move request to rdy queue
  peek(seqInPort, RubyRequest) {
    enqueue(reqRdyOutPort, CHIRequestMsg, allocation_latency) {
      out_msg.addr := in_msg.LineAddress;
      assert((in_msg.Size > 0) && (in_msg.Size <= blockSize));
      out_msg.accAddr := in_msg.PhysicalAddress;
      out_msg.accSize := in_msg.Size;
      out_msg.requestor := machineID;
      out_msg.fwdRequestor := machineID;
      out_msg.seqReq := in_msg.getRequestPtr();
      out_msg.isSeqReqValid := true;
      assert(in_msg.Prefetch == PrefetchBit:No);
      out_msg.is_local_pf := false;
      out_msg.is_remote_pf := false;

      if ((in_msg.Type == RubyRequestType:LD) ||
          (in_msg.Type == RubyRequestType:IFETCH)) {
        out_msg.type := CHIRequestType:Load;
      } else  if (in_msg.Type == RubyRequestType:ST) {
        if (in_msg.Size == blockSize) {
          out_msg.type := CHIRequestType:StoreLine;
        } else {
          out_msg.type := CHIRequestType:Store;
        }
      } else {
        error("Invalid RubyRequestType");
      }
    }
  }
  seqInPort.dequeue(clockEdge());
}

action(AllocateTBE_SeqDvmRequest, desc="") {
  // No retry for sequencer requests; just create resource stall
  check_allocate(storDvmTBEs);

  // reserve a slot for this request
  storDvmTBEs.incrementReserved();

  // Move request to rdy queue
  peek(seqInPort, RubyRequest) {
    enqueue(reqRdyOutPort, CHIRequestMsg, allocation_latency) {
      // DVM operations do not relate to memory addresses
      // Use the DVM transaction ID instead
      out_msg.usesTxnId := true;
      out_msg.txnId := in_msg.tlbiTransactionUid;

      // TODO - zero these out?
      out_msg.addr := in_msg.tlbiTransactionUid;
      out_msg.accAddr := in_msg.tlbiTransactionUid;
      out_msg.accSize := blockSize;
      assert(in_msg.Prefetch == PrefetchBit:No);
      out_msg.is_local_pf := false;
      out_msg.is_remote_pf := false;

      out_msg.requestor := machineID;
      out_msg.fwdRequestor := machineID;
      out_msg.seqReq := in_msg.getRequestPtr();
      out_msg.isSeqReqValid := true;


      if (in_msg.Type == RubyRequestType:TLBI) {
        out_msg.type := CHIRequestType:DvmTlbi_Initiate;
      } else if (in_msg.Type == RubyRequestType:TLBI_SYNC) {
        out_msg.type := CHIRequestType:DvmSync_Initiate;
      } else if (in_msg.Type == RubyRequestType:TLBI_EXT_SYNC_COMP) {
        out_msg.type := CHIRequestType:DvmSync_ExternCompleted;
      } else {
        error("Invalid RubyRequestType");
      }
    }
  }
  seqInPort.dequeue(clockEdge());
}

action(AllocateTBE_PfRequest, desc="Allocate TBE for prefetch request") {
  // No retry for prefetch requests; just create resource stall
  check_allocate(storTBEs);

  // reserve a slot for this request
  storTBEs.incrementReserved();

  // Move request to rdy queue
  peek(pfInPort, RubyRequest) {
    enqueue(reqRdyOutPort, CHIRequestMsg, 0) {
      out_msg.addr := in_msg.LineAddress;
      assert((in_msg.Size > 0) && (in_msg.Size <= blockSize));
      out_msg.accAddr := in_msg.PhysicalAddress;
      out_msg.accSize := in_msg.Size;
      out_msg.requestor := machineID;
      out_msg.fwdRequestor := machineID;
      out_msg.seqReq := in_msg.getRequestPtr();
      out_msg.isSeqReqValid := true;
      assert(in_msg.Prefetch != PrefetchBit:No);
      out_msg.is_local_pf := true;
      out_msg.is_remote_pf := false;

      if (in_msg.Type == RubyRequestType:LD) {
        out_msg.type := CHIRequestType:Load;
      } else if (in_msg.Type == RubyRequestType:ST) {
        error("CHI is not supporting prefetch store requests");
      } else {
        error("Invalid RubyRequestType");
      }
    }
  }
  pfInPort.dequeue(clockEdge());
}

action(Initiate_Request, desc="") {
  State initial := getState(tbe, cache_entry, address);
  bool was_retried := false;
  peek(reqRdyPort, CHIRequestMsg) {
    set_tbe(allocateRequestTBE(address, in_msg));
    // only a msg that was already retried doesn't allow a retry
    was_retried := in_msg.allowRetry == false;
  }
  DirEntry dir_entry := getDirEntry(address);
  copyCacheAndDir(cache_entry, dir_entry, tbe, initial);

  tbe.use_DMT := is_HN && enable_DMT;
  tbe.use_DCT := enable_DCT;

  bool alloc_entry := needCacheEntry(tbe.reqType,
                                     cache_entry, dir_entry,
                                     tbe.is_local_pf);
  bool dealloc_entry := needDeallocCacheEntry(tbe.reqType);
  assert((alloc_entry && dealloc_entry) == false);

  // always drops any data when not caching it or when this transaction
  // requires deallocation
  tbe.dataToBeInvalid := dealloc_entry ||
                         (is_invalid(cache_entry) && (alloc_entry == false));
  tbe.doCacheFill := alloc_entry || is_valid(cache_entry);

  // model the initial tag array read
  tbe.actions.pushNB(Event:TagArrayRead);

  incomingTransactionStart(address, curTransitionEvent(), initial, was_retried);
}

action(Initiate_Request_DVM, desc="") {
  peek(reqRdyPort, CHIRequestMsg) {
    // "address" for DVM = transaction ID
    TBE tbe := allocateDvmRequestTBE(address, in_msg);
    set_tbe(tbe);
  }
}

action(Initiate_Request_Stale, desc="") {
  State initial := getState(tbe, cache_entry, address);
  bool was_retried := false;
  peek(reqRdyPort, CHIRequestMsg) {
    set_tbe(allocateRequestTBE(address, in_msg));
    was_retried := in_msg.allowRetry == false;
  }
  copyCacheAndDir(cache_entry, getDirEntry(address), tbe, initial);

  // usually we consider data locally invalid on RU states even if we
  // have a copy; so it override it to valid so we can comeback to UD_RU/UC_RU
  // at the end of this transaction
  if (tbe.dir_ownerExists && tbe.dir_ownerIsExcl && is_valid(cache_entry)) {
    // treat the data we got from the cache as valid
    tbe.dataBlk := cache_entry.DataBlk;
    tbe.dataBlkValid.fillMask();
    tbe.dataValid := true;
  }

  incomingTransactionStart(address, curTransitionEvent(), initial, was_retried);
}

action(Initiate_Snoop, desc="") {
  State initial := getState(tbe, cache_entry, address);
  peek(snpRdyPort, CHIRequestMsg) {
    set_tbe(allocateSnoopTBE(address, in_msg));
  }
  copyCacheAndDir(cache_entry, getDirEntry(address), tbe, initial);

  // if we end up with valid data drop it if no entry allocated
  tbe.dataToBeInvalid := is_invalid(cache_entry);

  // model the initial tag array read
  tbe.actions.pushNB(Event:TagArrayRead);

  incomingTransactionStart(address, curTransitionEvent(), initial, false);
}

action(Initiate_Snoop_Hazard, desc="") {
  assert(is_valid(tbe));
  assert(tbe.is_req_tbe || tbe.is_repl_tbe);

  // Switch to the new snoop TBE
  TBE prev_tbe := tbe;
  peek(snpRdyPort, CHIRequestMsg) {
    set_tbe(allocateSnoopTBE(address, in_msg));
  }
  assert(tbe.is_snp_tbe);
  if (prev_tbe.is_req_tbe) {
    assert(prev_tbe.is_repl_tbe == false);
    tbe.is_req_hazard := true;
  } else {
    assert(prev_tbe.is_repl_tbe);
    tbe.is_repl_hazard := true;
  }

  // Use state from prev TBE
  tbe.pendReqType := prev_tbe.pendReqType;
  copyCacheAndDirTBEs(prev_tbe, tbe);
  tbe.wakeup_pending_req := prev_tbe.wakeup_pending_req;
  tbe.wakeup_pending_snp := prev_tbe.wakeup_pending_snp;
  tbe.wakeup_pending_tgr := prev_tbe.wakeup_pending_tgr;
}

action(RestoreFromHazard, desc="") {
  TBE hazard_tbe := getHazardTBE(tbe);

  // update
  setDataToBeStates(tbe);

  copyCacheAndDirTBEs(tbe, hazard_tbe);
  hazard_tbe.wakeup_pending_req := tbe.wakeup_pending_req;
  hazard_tbe.wakeup_pending_snp := tbe.wakeup_pending_snp;
  hazard_tbe.wakeup_pending_tgr := tbe.wakeup_pending_tgr;

  deallocateSnpTBE(tbe);
  set_tbe(hazard_tbe);

  // if the pending request is a WB or Evict then it becomes a stale request
  // if data is no longer in the expected state
  if (tbe.pendReqType == CHIRequestType:WriteBackFull) {
    tbe.is_stale := (tbe.dataValid && tbe.dataDirty) == false;
  } else if (tbe.pendReqType == CHIRequestType:WriteCleanFull) {
    tbe.is_stale := (tbe.dataValid && tbe.dataDirty) == false;
  } else if (hazard_tbe.pendReqType == CHIRequestType:WriteEvictFull) {
    tbe.is_stale := (tbe.dataValid && tbe.dataUnique) == false;
  } else if (hazard_tbe.pendReqType == CHIRequestType:Evict) {
    tbe.is_stale := tbe.dataValid == false;
  } else if (hazard_tbe.pendReqType == CHIRequestType:CleanUnique) {
    tbe.is_stale := tbe.dataValid == false;
  }

  // a pending action from the original request may have been stalled during
  // the hazard and needs to wakeup up now
  wakeupPendingTgrs(tbe);
}

action(Initiate_Replacement, desc="") {
  assert(is_invalid(tbe));
  State initial := getState(tbe, cache_entry, address);
  if (unify_repl_TBEs) {
    peek(replTriggerInPort, ReplacementMsg) {
      set_tbe(allocateReplacementTBEOnSlot(address, in_msg.slot));
      DPRINTF(RubySlicc, "Allocated replacement TBE on slot %d\n", tbe.storSlot);
    }
  } else {
    set_tbe(allocateReplacementTBE(address));
    DPRINTF(RubySlicc, "Allocated replacement TBE on new slot %d\n", tbe.storSlot);
  }
  copyCacheAndDir(cache_entry, getDirEntry(address), tbe, initial);

  // model the initial tag array read
  tbe.actions.pushNB(Event:TagArrayRead);

  incomingTransactionStart(address, curTransitionEvent(), initial, false);
}



action(StallRequest, desc="") {
  // was stalled because of an existing request
  assert(is_valid(tbe));
  assert(tbe.addr == address);
  // tracks pending
  tbe.wakeup_pending_req := true;
  stall_and_wait(reqRdyPort, address);
}

action(StallSnoop, desc="") {
  // was stalled because of an existing request
  assert(is_valid(tbe));
  assert(tbe.addr == address);
  // tracks pending
  tbe.wakeup_pending_snp := true;
  stall_and_wait(snpRdyPort, address);
}

action(StallLocalEviction, desc="") {
  // was stalled because of an existing request
  assert(is_valid(tbe));
  assert(tbe.addr == address);

  // Just pop the queue and When this transaction finishes wake-up the original
  // msgs that caused this eviction
  tbe.wakeup_pending_tgr := true;
  replTriggerInPort.dequeue(clockEdge());
}

action(StallSnoop_NoTBE, desc="") {
  stall_and_wait(snpRdyPort, address);
}

action(StallActionOnHazard, desc="") {
  assert(is_valid(tbe));
  assert(tbe.is_req_hazard || tbe.is_repl_hazard);
  tbe.wakeup_pending_tgr := true;
  stall_and_wait(triggerInPort, address);
}

action(Initiate_ReadShared_Miss, desc="") {
  tbe.actions.push(Event:ReadMissPipe);
  if (is_HN && tbe.use_DMT) {
    tbe.requestorToBeExclusiveOwner := true;
    tbe.dataMaybeDirtyUpstream := true; // SNF always replies with CompData_UC
    if (enable_DMT_early_dealloc) {
      tbe.actions.push(Event:SendRespSepData);
    }
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendReadNoSnpDMT);
  } else if (is_HN) {
    tbe.actions.push(Event:SendReadNoSnp);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  } else {
    tbe.actions.push(Event:SendReadShared);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  }
  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_ReadShared_Hit, desc="") {
  tbe.actions.push(Event:ReadHitPipe);
  tbe.actions.push(Event:DataArrayRead);
  tbe.actions.push(Event:WaitCompAck);
  tbe.actions.pushNB(Event:SendCompData);
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_ReadShared_HitUpstream, desc="") {
  tbe.actions.push(Event:ReadMissPipe);
  if (tbe.use_DCT) {
    tbe.actions.push(Event:SendSnpSharedFwdToOwner);
    tbe.actions.pushNB(Event:WaitCompAck);
    tbe.updateDirOnCompAck := false;
  } else {
    tbe.actions.push(Event:SendSnpShared);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  }
  tbe.actions.push(Event:MaintainCoherence);
}

action(Initiate_ReadShared_HitUpstream_NoOwner, desc="") {
  tbe.actions.push(Event:ReadMissPipe);
  if (tbe.use_DCT) {
    tbe.actions.push(Event:SendSnpSharedFwdToSharer);
    tbe.actions.pushNB(Event:WaitCompAck);
    tbe.updateDirOnCompAck := false;
  } else {
    tbe.actions.push(Event:SendSnpOnce);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  }
  tbe.actions.push(Event:MaintainCoherence);
}


action(Initiate_ReadOnce_Miss, desc="") {
  // drop at the end if not doing a fill
  tbe.dataToBeInvalid := tbe.doCacheFill == false;

  tbe.actions.push(Event:ReadMissPipe);
  if (is_HN && tbe.use_DMT) {
    assert(is_invalid(cache_entry));
    tbe.requestorToBeExclusiveOwner := true;
    tbe.dataMaybeDirtyUpstream := true; // SNF always replies with CompData_UC
    if (enable_DMT_early_dealloc) {
      tbe.actions.push(Event:SendRespSepData);
    }
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendReadNoSnpDMT);
  } else if (is_HN) {
    tbe.actions.push(Event:SendReadNoSnp);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  } else {
    // if not allocating an entry send a ReadOnce
    if (tbe.dataToBeInvalid) {
      tbe.actions.push(Event:SendReadOnce);
    } else {
      tbe.actions.push(Event:SendReadShared);
    }
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  }

  tbe.updateDirOnCompAck := false;

  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_ReadOnce_Hit, desc="") {
  tbe.actions.push(Event:ReadHitPipe);
  tbe.actions.push(Event:DataArrayRead);
  tbe.actions.push(Event:WaitCompAck);
  tbe.actions.pushNB(Event:SendCompData);
  tbe.updateDirOnCompAck := false;
}

action(Initiate_ReadOnce_HitUpstream, desc="") {
  tbe.actions.push(Event:ReadMissPipe);
  if (tbe.use_DCT) {
    tbe.actions.push(Event:SendSnpOnceFwd);
    tbe.actions.pushNB(Event:WaitCompAck);
  } else {
    tbe.actions.push(Event:SendSnpOnce);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  }
  tbe.updateDirOnCompAck := false;
  // no need to update or access tags/data on ReadOnce served from upstream

  if (is_invalid(cache_entry)) {
    // if we receive data, invalidate at the end so it can be dropped
    tbe.dataToBeInvalid := true;
  } else if (tbe.dataValid == false) {
    // possible on UD_RU,UC_RU where cache_entry valid but tbe.dataValid == false
    // this prevents going to RU if no data is received from snoop
    tbe.dataValid := true;
  }
}



action(Initiate_ReadUnique_Miss, desc="") {
  tbe.actions.push(Event:ReadMissPipe);
  if (is_HN && tbe.use_DMT) {
    tbe.requestorToBeExclusiveOwner := true;
    tbe.dataMaybeDirtyUpstream := true; // SNF always replies with CompData_UC
    if (enable_DMT_early_dealloc) {
      tbe.actions.push(Event:SendRespSepData);
    }
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendReadNoSnpDMT);
  } else if (is_HN) {
    tbe.actions.push(Event:SendReadNoSnp);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  } else {
    tbe.actions.push(Event:SendReadUnique);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  }
  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_ReadUnique_AutoUpgrade, desc="") {
  assert(is_HN);
  tbe.dataUnique := true;
}

action(Initiate_ReadUnique_Upgrade, desc="") {
  // must use the transitions with auto upgrade otherwise
  assert(is_HN == false);
  assert(tbe.use_DCT == false);
  assert((tbe.dataValid && tbe.dataUnique) == false);
  assert((tbe.dir_ownerExists && tbe.dir_ownerIsExcl) == false);

  tbe.actions.push(Event:ReadMissPipe);
  if (tbe.dataMaybeDirtyUpstream) {
    tbe.actions.push(Event:SendSnpUnique);
  } else if (tbe.dir_sharers.count() > 0) {
    // no one will send us data unless we explicitly ask
    tbe.actions.push(Event:SendSnpUniqueRetToSrc);
  } else {
    assert(tbe.dataValid);
  }
  // then attempt to upgrade our data
  tbe.actions.push(Event:SendCleanUnique);
  tbe.actions.push(Event:CheckUpgrade_FromRU);

  // send up the upgraded data or fresh data if we failed, see CheckUpgrade_FromRU
  tbe.actions.push(Event:WaitCompAck);
  tbe.actions.pushNB(Event:SendCompData);
  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_ReadUnique_Hit, desc="") {
  tbe.actions.push(Event:ReadHitPipe);
  tbe.actions.push(Event:DataArrayRead);
  tbe.actions.push(Event:WaitCompAck);
  tbe.actions.pushNB(Event:SendCompData);
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_ReadUnique_HitUpstream, desc="") {
  tbe.actions.push(Event:ReadMissPipe);
  // SnpUniqueFwd can be used only if the line is cached at a single
  // requester; so force it off if that's the case
  tbe.use_DCT := tbe.use_DCT && (tbe.dir_sharers.count() == 1) &&
                 (tbe.dir_sharers.isElement(tbe.requestor) == false);
  if (tbe.use_DCT) {
    tbe.actions.push(Event:SendSnpUniqueFwd);
    tbe.actions.pushNB(Event:WaitCompAck);
    tbe.updateDirOnCompAck := false;
  } else if (tbe.dataMaybeDirtyUpstream) {
    tbe.actions.push(Event:SendSnpUnique);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  } else {
    // no one will send us data unless we explicitly ask
    tbe.actions.push(Event:SendSnpUniqueRetToSrc);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.pushNB(Event:SendCompData);
  }
  // just tag update since data any data would become stale
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_ReadUnique_Hit_InvUpstream, desc="") {
  tbe.actions.push(Event:ReadHitPipe);
  tbe.actions.push(Event:SendSnpCleanInvalid);
  tbe.actions.pushNB(Event:DataArrayRead);
  tbe.actions.push(Event:WaitCompAck);
  tbe.actions.pushNB(Event:SendCompData);
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_CleanUnique, desc="") {
  tbe.actions.push(Event:ReadMissPipe); // TODO need another latency pipe ??

  // invalidates everyone except requestor
  if (tbe.dir_sharers.count() > 1) {
    tbe.actions.push(Event:SendSnpCleanInvalidNoReq);
  }
  // auto upgrade if HN
  tbe.dataUnique := tbe.dataUnique || is_HN;
  // get unique permission
  if (tbe.dataUnique == false) {
    tbe.actions.push(Event:SendCleanUnique);
    tbe.actions.push(Event:CheckUpgrade_FromCU);
  }
  // next actions will depend on the data state after snoops+CleanUnique
  tbe.actions.push(Event:FinishCleanUnique);
}

action(Initiate_CleanUnique_Stale, desc="") {
  // requestor don't have the line anymore; send response but don't update the
  // directory on CompAck. The requestor knows we are not tracking it and will
  // send a ReadUnique later
  tbe.actions.push(Event:SendCompUCRespStale);
  tbe.actions.push(Event:WaitCompAck);
  tbe.updateDirOnCompAck := false;
}

action(Finish_CleanUnique, desc="") {
  // This is should be executed at the end of a transaction
  assert(tbe.actions.empty());

  // everyone may have been hit by an invalidation so check again
  if (tbe.dir_sharers.isElement(tbe.requestor) == false) {
    tbe.updateDirOnCompAck := false;
    assert(tbe.dataValid == false);
    assert(tbe.is_stale);
    tbe.is_stale := false;
    tbe.actions.push(Event:SendCompUCRespStale);
    tbe.actions.push(Event:WaitCompAck);
    tbe.actions.push(Event:TagArrayWrite);
  } else {
    // must be the only one in sharers map
    assert(tbe.dir_sharers.count() == 1);
    assert(tbe.dataUnique);

    // needed by UpdateDirState_FromReqResp triggered by the expected CompAck
    tbe.dataMaybeDirtyUpstream := true;
    tbe.requestorToBeExclusiveOwner := true;
    tbe.dir_ownerExists := false;

    tbe.actions.push(Event:SendCompUCResp);
    tbe.actions.push(Event:WaitCompAck);

    // Ensure we writeback or update the cache if the owner has data as
    // clean data and we have it dirty.
    // MaintainCoherence queues the TagArrayWrite
    tbe.actions.push(Event:MaintainCoherence);
  }
}


action(Initiate_LoadHit, desc="") {
  // Local prefetch requests do not read data array
  if (tbe.is_local_pf == false) {
    tbe.actions.push(Event:DataArrayRead);
  }
  tbe.actions.push(Event:LoadHit);
}

action(Initiate_LoadMiss, desc="") {
  if (tbe.doCacheFill) {
    tbe.actions.push(Event:SendReadShared);
    tbe.actions.push(Event:CheckCacheFill);
    tbe.actions.push(Event:TagArrayWrite);
  } else {
    tbe.actions.push(Event:SendReadOnce);
    tbe.dataToBeInvalid := true;
  }
}



action(Initiate_StoreHit, desc="") {
  tbe.actions.push(Event:DataArrayRead);
  tbe.actions.push(Event:StoreHit);
  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_StoreMiss, desc="") {
  if (tbe.doCacheFill) {
    tbe.actions.push(Event:SendReadUnique);
    tbe.actions.push(Event:CheckCacheFill);
    tbe.actions.push(Event:TagArrayWrite);
  } else {
    tbe.actions.push(Event:SendWriteUnique);
    tbe.actions.push(Event:SendWUDataCB);
    tbe.dataToBeInvalid := true;
  }
}

action(Initiate_StoreUpgrade, desc="") {
  assert(tbe.dataValid);
  assert(is_valid(cache_entry));
  tbe.actions.push(Event:SendCleanUnique);
  tbe.actions.push(Event:CheckUpgrade_FromStore);
  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_WriteUnique_LocalWrite, desc="") {
  // auto-upgrade if hn but state was not unique
  assert(is_HN || tbe.dataUnique);
  tbe.dataUnique := true;
  if (tbe.dir_sharers.count() > 0) {
    tbe.actions.push(Event:SendSnpCleanInvalid);
  }
  if (comp_wu) {
    tbe.actions.push(Event:SendDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendComp_WU);
  } else {
    tbe.actions.push(Event:SendCompDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
  }
  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_WriteUnique_LocalWrite_AfterUpgrade, desc="") {
  assert(is_HN == false);
  assert((tbe.dataValid && tbe.dataUnique) == false);
  tbe.actions.push(Event:SendReadUnique);
  if (comp_wu) {
    tbe.actions.push(Event:SendDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendComp_WU);
  } else {
    tbe.actions.push(Event:SendCompDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
  }
  tbe.actions.push(Event:CheckCacheFill);
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_WriteUnique_Writeback, desc="") {
  assert(is_HN);
  assert(tbe.dir_sharers.count() > 0);
  tbe.actions.push(Event:SendSnpUnique);
  if (comp_wu) {
    tbe.actions.push(Event:SendDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendWriteNoSnp);
    tbe.actions.pushNB(Event:SendComp_WU);
  } else {
    tbe.actions.push(Event:SendCompDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendWriteNoSnp);
  }
  tbe.actions.push(Event:WriteBEPipe);
  tbe.actions.push(Event:SendWBData);
  tbe.dataToBeInvalid := true;
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_WriteUnique_PartialWrite, desc="") {
  assert(is_HN);
  if (tbe.dir_sharers.count() > 0) {
    tbe.actions.push(Event:SendSnpCleanInvalid);
  }
  if (comp_wu) {
    tbe.actions.push(Event:SendDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendWriteNoSnpPartial);
    tbe.actions.pushNB(Event:SendComp_WU);
  } else {
    tbe.actions.push(Event:SendCompDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendWriteNoSnpPartial);
  }
  tbe.actions.push(Event:WriteBEPipe);
  tbe.actions.push(Event:SendWUData);
  tbe.dataToBeInvalid := true;

  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_WriteUnique_Forward, desc="") {
  tbe.actions.push(Event:WriteFEPipe);
  tbe.actions.push(Event:SendWriteUnique);
  tbe.actions.push(Event:SendCompDBIDResp_WU);
  tbe.actions.push(Event:WriteBEPipe);
  tbe.actions.push(Event:SendWUData);
  tbe.dataToBeInvalid := true;
  tbe.actions.pushNB(Event:TagArrayWrite);
}



action(Initiate_CopyBack, desc="") {
  // expect to receive this data after Send_CompDBIDResp
  if (tbe.reqType == CHIRequestType:WriteBackFull) {
    tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_UD_PD);
    tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_SD_PD);
  } else if (tbe.reqType == CHIRequestType:WriteEvictFull) {
    assert(tbe.reqType == CHIRequestType:WriteEvictFull);
    tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_UC);
    tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_SC);
  } else {
    assert(tbe.reqType == CHIRequestType:WriteCleanFull);
    tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_UD_PD);
    tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_SD_PD);
  }
  tbe.expected_req_resp.setExpectedCount(1);

  tbe.actions.pushNB(Event:SendCompDBIDResp);
  tbe.actions.pushNB(Event:WriteFEPipe);
  tbe.actions.push(Event:MaintainCoherence);
  // MaintainCoherence queues the Tag/Data updates
}

action(Initiate_CopyBack_Stale, desc="") {
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_SC);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CBWrData_I);
  tbe.expected_req_resp.setExpectedCount(1);

  tbe.actions.pushNB(Event:SendCompDBIDRespStale);
  tbe.actions.pushNB(Event:WriteFEPipe);
  tbe.actions.push(Event:FinishCopyBack_Stale);

  assert((tbe.dir_ownerExists == false) || (tbe.dir_owner != tbe.requestor));
}

action(Finish_CopyBack_Stale, desc="") {
  // if it was the last known sharer and we don't have the data do the same
  // the Initiate_Evict
  if ((is_HN == false) && (tbe.dir_sharers.count() == 0) &&
      tbe.dir_sharers.isElement(tbe.requestor) && (tbe.dataValid == false)) {
    tbe.actions.push(Event:SendEvict);
  }
}

action(Initiate_Evict, desc="") {
  if ((is_HN == false) && (tbe.dir_sharers.count() == 1) &&
      (tbe.dataValid == false)) {
    // last sharer and we also don't have a copy the line, so we also need to
    // send an eviction downstream
    if (tbe.dataUnique) {
      // we need to send a WriteEvictFull so need the upstream data before
      // we ack the evict
      tbe.actions.push(Event:SendSnpOnce);
      tbe.actions.push(Event:SendCompIResp);
      tbe.actions.push(Event:SendWriteBackOrWriteEvict);
      tbe.actions.push(Event:WriteBEPipe);
      tbe.actions.push(Event:SendWBData);
    } else {
      tbe.actions.push(Event:SendCompIResp);
      tbe.actions.push(Event:SendEvict);
    }
  } else {
    tbe.actions.push(Event:SendCompIResp);
  }
  tbe.actions.push(Event:TagArrayWrite);
}

action(Initiate_MaintainCoherence, desc="") {
  // issue a copy back if necessary to maintain coherence for data we are
  // droping. This is should be executed at the end of a transaction
  assert(tbe.actions.empty());
  // go through either the fill or the writeback pipeline
  if (tbe.dataValid && tbe.dataToBeInvalid) {
    // we don't need to WB if the upstream is SD, because the
    // owner is responsible for the WB
    bool has_non_ex_owner := tbe.dir_ownerExists && !tbe.dir_ownerIsExcl;
    if (is_HN) {
      if (tbe.dataDirty && !has_non_ex_owner) {
        tbe.actions.push(Event:SendWriteNoSnp);
        tbe.actions.push(Event:WriteBEPipe);
        tbe.actions.push(Event:SendWBData);
      }
    } else {
      if (tbe.dir_sharers.isEmpty() && (tbe.dataDirty || tbe.dataUnique)) {
        assert(!has_non_ex_owner);
        tbe.actions.push(Event:SendWriteBackOrWriteEvict);
        tbe.actions.push(Event:WriteBEPipe);
        tbe.actions.push(Event:SendWBData);
      } else if (tbe.dataDirty && !has_non_ex_owner) {
        assert(!tbe.dir_sharers.isEmpty());
        tbe.actions.push(Event:SendWriteClean);
        tbe.actions.push(Event:WriteBEPipe);
        tbe.actions.push(Event:SendWBData);
      }
    }
  } else if (tbe.dataValid) {
    tbe.actions.push(Event:CheckCacheFill);
  }
  tbe.actions.push(Event:TagArrayWrite);
}



// Too many common stuff between SnpUnique/SnpUniqueFwd/SnpCleanInvalid
// so do one action for all of them here
action(Initiate_InvalidationSnoop, desc="") {
  tbe.actions.push(Event:SnpInvPipe);
  // Propagate a snoop upwards depending on the type
  if (tbe.dir_sharers.count() > 0) {
    if ((tbe.reqType == CHIRequestType:SnpUniqueFwd) ||
        (tbe.reqType == CHIRequestType:SnpUnique)) {
      if ((tbe.snpNeedsData && (tbe.dataMaybeDirtyUpstream == false)) ||
          (tbe.dataValid == false)) {
        tbe.actions.push(Event:SendSnpUniqueRetToSrc);
      } else {
        tbe.actions.push(Event:SendSnpUnique);
      }
    } else {
      assert(tbe.reqType == CHIRequestType:SnpCleanInvalid);
      tbe.actions.push(Event:SendSnpCleanInvalid);
    }
  }

  if (tbe.reqType == CHIRequestType:SnpUniqueFwd) {
    tbe.actions.push(Event:SendSnpUniqueFwdCompData);
  } else {
    tbe.actions.push(Event:SendInvSnpResp);
  }

  if(tbe.is_req_hazard || tbe.is_repl_hazard) {
    tbe.actions.push(Event:RestoreFromHazard);
  } else {
    tbe.actions.pushNB(Event:TagArrayWrite);
  }

  tbe.dataToBeInvalid := true;
}

action(Initiate_SnpShared, desc="") {
  // Handles both SnpShared,SnpSharedFwd,SnpNotSharedDirtyFwd
  tbe.actions.push(Event:SnpSharedPipe);
  if (tbe.dir_ownerExists) {
    assert(tbe.dataMaybeDirtyUpstream);
    tbe.actions.push(Event:SendSnpShared);
  } else if (tbe.dataValid == false) {
    // must get a copy of shared data upstream
    assert(tbe.dataMaybeDirtyUpstream == false);
    assert(tbe.dir_sharers.count() > 0);
    tbe.actions.push(Event:SendSnpOnce);
  } else {
    tbe.actions.push(Event:DataArrayRead);
  }

  if (tbe.reqType == CHIRequestType:SnpSharedFwd) {
    tbe.actions.push(Event:SendSnpSharedFwdCompData);
  } else if (tbe.reqType == CHIRequestType:SnpNotSharedDirtyFwd) {
    tbe.actions.push(Event:SendSnpNotSharedDirtyFwdCompData);
  } else {
    assert(tbe.reqType == CHIRequestType:SnpShared);
    tbe.actions.push(Event:SendSnpData);
  }
  if (tbe.is_req_hazard || tbe.is_repl_hazard) {
    tbe.actions.push(Event:RestoreFromHazard);
  } else {
    tbe.actions.pushNB(Event:TagArrayWrite);
  }
  tbe.dataToBeSharedClean := true;
}

action(Initiate_SnpOnce, desc="") {
  tbe.actions.push(Event:SnpOncePipe);
  if (tbe.dataValid == false) {
    assert(tbe.dir_sharers.count() > 0);
    tbe.actions.push(Event:SendSnpOnce);
  } else {
    tbe.actions.push(Event:DataArrayRead);
  }

  if (tbe.reqType == CHIRequestType:SnpOnceFwd) {
    tbe.actions.push(Event:SendSnpOnceFwdCompData);
  } else {
    assert(tbe.reqType == CHIRequestType:SnpOnce);
    assert(tbe.snpNeedsData);
    tbe.actions.push(Event:SendSnpData);
  }

  if (tbe.is_req_hazard || tbe.is_repl_hazard) {
    tbe.actions.push(Event:RestoreFromHazard);
  } else {
    tbe.actions.pushNB(Event:TagArrayWrite);
  }
}



action(Initiate_Replacement_Evict_BackInvalidte, desc="") {
  assert(is_HN == false);
  tbe.actions.push(Event:SendSnpCleanInvalid);
  tbe.actions.push(Event:SendEvict);
  tbe.dataToBeInvalid := true;
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_Replacement_Evict, desc="") {
  assert(is_HN == false);
  assert(tbe.dir_sharers.isEmpty());
  tbe.actions.push(Event:SendEvict);
  tbe.dataToBeInvalid := true;
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_Replacement_JustDrop, desc="") {
  tbe.dataToBeInvalid := true;
  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_Replacement_WB_BackInvalidate, desc="") {
  assert(tbe.dataDirty || tbe.dataUnique || tbe.dataMaybeDirtyUpstream);
  tbe.actions.push(Event:SendSnpCleanInvalid);
  tbe.actions.push(Event:WriteFEPipe);
  if (is_HN) {
    if (tbe.dataDirty || tbe.dataMaybeDirtyUpstream) {
      tbe.actions.push(Event:SendWriteNoSnp);
    }
  } else {
    tbe.actions.push(Event:SendWriteBackOrWriteEvict);
  }
  tbe.actions.pushNB(Event:DataArrayRead);
  tbe.actions.push(Event:WriteBEPipe);
  tbe.actions.push(Event:SendWBData);
  tbe.dataToBeInvalid := true;

  tbe.actions.pushNB(Event:TagArrayWrite);
}

action(Initiate_Replacement_WB, desc="") {
  tbe.actions.push(Event:WriteFEPipe);
  if (is_HN) {
    assert(tbe.dataDirty);
    tbe.actions.push(Event:SendWriteNoSnp);
  } else if (tbe.dir_sharers.isEmpty()) {
    assert(tbe.dataDirty || tbe.dataUnique);
    tbe.actions.push(Event:SendWriteBackOrWriteEvict);
  } else {
    assert(tbe.dataDirty);
    tbe.actions.push(Event:SendWriteClean);
  }
  tbe.actions.pushNB(Event:DataArrayRead);
  tbe.actions.push(Event:WriteBEPipe);
  tbe.actions.push(Event:SendWBData);
  tbe.dataToBeInvalid := true;
  tbe.actions.pushNB(Event:TagArrayWrite);
}



action(Send_ReadShared, desc="") {
  assert(is_HN == false);
  assert(tbe.dataValid == false);

  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:DataSepResp_UC);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_UC);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_UD_PD);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_SC);
  if (allow_SD) {
    tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_SD_PD);
  }
  // NOTE: the first CompData received counts as RespSepData
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:RespSepData);
  tbe.expected_req_resp.setExpectedCount(2);
  tbe.dataBlkValid.clear();

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    if (allow_SD) {
      prepareRequest(tbe, CHIRequestType:ReadShared, out_msg);
    } else {
      prepareRequest(tbe, CHIRequestType:ReadNotSharedDirty, out_msg);
    }
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    out_msg.dataToFwdRequestor := false;
    allowRequestRetry(tbe, out_msg);
  }
}

action(Send_ReadNoSnp, desc="") {
  assert(is_HN);
  assert(tbe.use_DMT == false);

  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_UC);
  // NOTE: the first CompData received counts as RespSepData
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:RespSepData);
  tbe.expected_req_resp.setExpectedCount(2);
  tbe.dataBlkValid.clear();
  outgoingTransactionStart(address, curTransitionEvent());

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:ReadNoSnp, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    out_msg.dataToFwdRequestor := false;
    allowRequestRetry(tbe, out_msg);
  }
}

action(Send_ReadNoSnpDMT, desc="") {
  assert(is_HN);
  assert(tbe.use_DMT);

  CHIRequestType req := CHIRequestType:ReadNoSnp;
  if (enable_DMT_early_dealloc) {
    req := CHIRequestType:ReadNoSnpSep;
    tbe.expected_req_resp.addExpectedRespType(CHIResponseType:ReadReceipt);
    tbe.expected_req_resp.addExpectedCount(1);
  }

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, req, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    out_msg.dataToFwdRequestor := true;
    allowRequestRetry(tbe, out_msg);
  }
}

action(Send_ReadOnce, desc="") {
  assert(is_HN == false);
  assert(tbe.dataValid == false);

  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:DataSepResp_UC);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_UC);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_I);
  // NOTE: the first CompData received counts as RespSepData
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:RespSepData);
  tbe.expected_req_resp.setExpectedCount(2);
  tbe.dataBlkValid.clear();

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:ReadOnce, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    out_msg.dataToFwdRequestor := false;
    allowRequestRetry(tbe, out_msg);
  }
}

action(Send_ReadUnique, desc="") {
  assert((tbe.dataValid && tbe.dataUnique) == false);

  assert(tbe.expected_req_resp.hasExpected() == false);
  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:DataSepResp_UC);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_UC);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_UD_PD);
  // NOTE: the first CompData received counts as RespSepData
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:RespSepData);
  tbe.expected_req_resp.setExpectedCount(2);

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:ReadUnique, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    out_msg.dataToFwdRequestor := false;
    allowRequestRetry(tbe, out_msg);
  }
}

action(Send_CleanUnique, desc="") {
  assert(tbe.dataValid || (tbe.dir_sharers.count() > 0));
  assert(tbe.dataUnique == false);

  assert(tbe.expected_req_resp.hasExpected() == false);
  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:Comp_UC);
  tbe.expected_req_resp.setExpectedCount(1);

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:CleanUnique, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    allowRequestRetry(tbe, out_msg);
  }
}

action(Send_Evict, desc="") {
  assert(is_valid(tbe));
  assert(is_HN == false);
  assert(tbe.expected_req_resp.hasExpected() == false);
  clearExpectedReqResp(tbe);
  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:Evict, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    allowRequestRetry(tbe, out_msg);
  }
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:Comp_I);
  tbe.expected_req_resp.setExpectedCount(1);
}

action(Send_InvSnpResp, desc="") {
  assert(is_valid(tbe));
  assert(tbe.dataMaybeDirtyUpstream == false);
  if (tbe.dataDirty || tbe.snpNeedsData ||
      (tbe.dataUnique && (tbe.reqType == CHIRequestType:SnpUnique))) {
    tbe.actions.pushFront(Event:SendSnpData);
  } else {
    tbe.actions.pushFront(Event:SendSnpIResp);
  }
}

action(Send_WriteBackOrWriteEvict, desc="") {
  assert(is_valid(tbe));
  assert(tbe.dataBlkValid.isFull());
  assert(tbe.dataValid);
  assert(is_HN == false);

  assert(tbe.dataUnique || tbe.dataDirty);
  assert(tbe.dir_sharers.isEmpty());

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    if (tbe.dataDirty) {
      prepareRequest(tbe, CHIRequestType:WriteBackFull, out_msg);
    } else {
      prepareRequest(tbe, CHIRequestType:WriteEvictFull, out_msg);
    }
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    allowRequestRetry(tbe, out_msg);
  }
  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompDBIDResp);
  tbe.expected_req_resp.setExpectedCount(1);
}

action(Send_WriteCleanFull, desc="") {
  assert(is_valid(tbe));
  assert(tbe.dataBlkValid.isFull());
  assert(tbe.dataValid);
  assert(is_HN == false);
  assert(tbe.dataDirty);

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:WriteCleanFull, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    allowRequestRetry(tbe, out_msg);
  }
  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompDBIDResp);
  tbe.expected_req_resp.setExpectedCount(1);
}

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

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:WriteNoSnp, out_msg);
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    allowRequestRetry(tbe, out_msg);
  }
  // allow to expect this on top of data coming from upstream;
  // so addExpectedCount
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompDBIDResp);
  tbe.expected_req_resp.addExpectedCount(1);
}

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

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:WriteNoSnpPtl, out_msg);
    out_msg.accAddr := tbe.accAddr;
    out_msg.accSize := tbe.accSize;
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    allowRequestRetry(tbe, out_msg);
  }
  // allow to expect this on top of data coming from upstream;
  // so addExpectedCount
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompDBIDResp);
  tbe.expected_req_resp.addExpectedCount(1);
}

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

  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    if (tbe.accSize == blockSize) {
      prepareRequest(tbe, CHIRequestType:WriteUniqueFull, out_msg);
    } else {
      prepareRequest(tbe, CHIRequestType:WriteUniquePtl, out_msg);
      out_msg.accAddr := tbe.accAddr;
      out_msg.accSize := tbe.accSize;
    }
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
    allowRequestRetry(tbe, out_msg);
  }
  // allow to expect this on top of data coming from upstream;
  // so addExpectedCount
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompDBIDResp);
  // if receive only DBIDResp then will expect Comp later
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:DBIDResp);
  tbe.expected_req_resp.addExpectedCount(1);
}

action(Send_SnpCleanInvalid, desc="") {
  assert(is_valid(tbe));
  assert(tbe.expected_snp_resp.hasExpected() == false);
  // at least one sharer or owner othrwise should not execute this
  assert(tbe.dir_sharers.count() > 0);
  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpCleanInvalid, out_msg);
    out_msg.Destination.addNetDest(tbe.dir_sharers);
    out_msg.retToSrc := false;
  }
  setExpectedForInvSnoop(tbe, false);
}

action(Send_SnpCleanInvalid_NoReq, desc="") {
  assert(is_valid(tbe));
  assert(tbe.expected_snp_resp.hasExpected() == false);
  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpCleanInvalid, out_msg);
    out_msg.Destination.addNetDest(tbe.dir_sharers);
    out_msg.Destination.remove(tbe.requestor);
    // at least one sharer other than requestor
    assert(out_msg.Destination.count() > 0);
    out_msg.retToSrc := false;
    setExpectedForInvSnoop(tbe, false);
    tbe.expected_snp_resp.setExpectedCount(out_msg.Destination.count());
  }
}

action(Send_SnpUnique, desc="") {
  assert(is_valid(tbe));
  // at least one sharer or owner othrwise should not execute this
  assert(tbe.dir_sharers.count() > 0);

  setExpectedForInvSnoop(tbe, true);

  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpUnique, out_msg);
    out_msg.Destination.addNetDest(tbe.dir_sharers);
    out_msg.retToSrc := false;
  }
}

action(Send_SnpUnique_RetToSrc, desc="") {
  assert(is_valid(tbe));
  // at least one sharer or owner othrwise should not execute this
  assert(tbe.dir_sharers.count() > 0);

  setExpectedForInvSnoop(tbe, true);

  MachineID dest;
  if (tbe.dir_ownerExists) {
    dest := tbe.dir_owner;
  } else {
    // TODO should be random or the closest one
    dest := tbe.dir_sharers.smallestElement();
  }
  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpUnique, out_msg);
    out_msg.Destination.add(dest);
    out_msg.retToSrc := true;
  }
  // if other sharers send with retToSrc=false to others
  if (tbe.dir_sharers.count() > 1) {
    enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
      prepareRequest(tbe, CHIRequestType:SnpUnique, out_msg);
      out_msg.Destination.addNetDest(tbe.dir_sharers);
      out_msg.Destination.remove(dest);
      out_msg.retToSrc := false;
    }
  }
}

action(Send_SnpUniqueFwd, desc="") {
  assert(is_valid(tbe));
  // single sharer or owner otherwise should not execute this
  assert(tbe.dir_sharers.count() == 1);

  assert(tbe.expected_snp_resp.expected() == 0);
  clearExpectedSnpResp(tbe);
  tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_I_Fwded_UC);
  tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_I_Fwded_UD_PD);
  tbe.expected_snp_resp.addExpectedCount(1);

  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpUniqueFwd, out_msg);
    out_msg.Destination.addNetDest(tbe.dir_sharers);
    out_msg.retToSrc := false;
  }
}

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

  // only sent to a dirty or exclusive snoopee
  assert(tbe.dataMaybeDirtyUpstream);
  assert(tbe.dir_ownerExists);
  assert(tbe.dir_sharers.count() > 0);

  assert(tbe.expected_snp_resp.expected() == 0);
  clearExpectedSnpResp(tbe);
  tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC);
  tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC_PD);
  tbe.expected_snp_resp.setExpectedCount(1);

  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpShared, out_msg);
    out_msg.Destination.add(tbe.dir_owner);
    out_msg.retToSrc := false;
  }
}

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

  // the dirty snoopee must go to SC and send data
  assert(tbe.dataMaybeDirtyUpstream);
  assert(tbe.dir_ownerExists);
  assert(tbe.dir_sharers.count() > 0);

  assert(tbe.expected_snp_resp.expected() == 0);
  clearExpectedSnpResp(tbe);

  bool allowFwdSD := tbe.reqType != CHIRequestType:ReadNotSharedDirty;

  // get us a copy if we have allocated a cache entry for this block
  bool retToSrc := tbe.doCacheFill && (tbe.dataToBeInvalid == false);

  if (allowFwdSD) {
    if (retToSrc) {
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC_Fwded_SC);
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC_Fwded_SD_PD);
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_I_Fwded_SC);
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_I_Fwded_SD_PD);
    } else {
      tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_SC_Fwded_SC);
      tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_SC_Fwded_SD_PD);
    }
  } else {
    if (retToSrc) {
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC_Fwded_SC);
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_I_Fwded_SC);
    } else {
      tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_SC_Fwded_SC);
    }
    tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC_PD_Fwded_SC);
    tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_I_PD_Fwded_SC);
  }
  tbe.expected_snp_resp.addExpectedCount(1);

  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    if (allowFwdSD) {
      prepareRequest(tbe, CHIRequestType:SnpSharedFwd, out_msg);
    } else {
      prepareRequest(tbe, CHIRequestType:SnpNotSharedDirtyFwd, out_msg);
    }
    out_msg.Destination.add(tbe.dir_owner);
    out_msg.retToSrc := retToSrc;
  }
}

action(Send_SnpSharedFwd_ToSharer, desc="") {
  assert(is_valid(tbe));
  // send to onde of the sharers with shared clean data
  assert(tbe.dataMaybeDirtyUpstream == false);
  assert(tbe.dir_ownerExists == false);
  assert(tbe.dir_sharers.count() > 0);

  assert(tbe.expected_snp_resp.expected() == 0);
  clearExpectedSnpResp(tbe);
  // if we have a block allocated for this line, asks snoopee to forward
  // data to us as well
  bool retToSrc := tbe.doCacheFill;
  if (retToSrc) {
    tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC_Fwded_SC);
  } else {
    tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_SC_Fwded_SC);
  }
  tbe.expected_snp_resp.addExpectedCount(1);

  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpSharedFwd, out_msg);
    // TODO should be random or the closest one to the fwd dest
    out_msg.Destination.add(tbe.dir_sharers.smallestElement());
    out_msg.retToSrc := retToSrc;
  }
}

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

  // send to one of the sharers or owner to get a copy of the line
  assert(tbe.dir_sharers.count() > 0);

  assert(tbe.expected_snp_resp.expected() == 0);
  clearExpectedSnpResp(tbe);

  if (tbe.dir_ownerExists) {
    if (tbe.dir_ownerIsExcl) {
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_UC);
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_UD);
    } else {
      tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SD);
    }
  } else {
    tbe.expected_snp_resp.addExpectedDataType(CHIDataType:SnpRespData_SC);
  }
  tbe.expected_snp_resp.addExpectedCount(1);

  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpOnce, out_msg);
    if (tbe.dir_ownerExists) {
      out_msg.Destination.add(tbe.dir_owner);
    } else {
      // TODO should be random or the closest one
      out_msg.Destination.add(tbe.dir_sharers.smallestElement());
    }
    out_msg.retToSrc := true;
  }
}

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

  // send to one of the sharers or owner to get a copy of the line
  assert(tbe.dir_sharers.count() > 0);

  assert(tbe.expected_snp_resp.expected() == 0);
  clearExpectedSnpResp(tbe);

  if (tbe.dir_ownerExists) {
    if (tbe.dir_ownerIsExcl) {
      tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_UC_Fwded_I);
      tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_UD_Fwded_I);
    } else {
      tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_SD_Fwded_I);
    }
  } else {
    tbe.expected_snp_resp.addExpectedRespType(CHIResponseType:SnpResp_SC_Fwded_I);
  }
  tbe.expected_snp_resp.addExpectedCount(1);

  enqueue(snpOutPort, CHIRequestMsg, snoop_latency) {
    prepareRequest(tbe, CHIRequestType:SnpOnceFwd, out_msg);
    if (tbe.dir_ownerExists) {
      out_msg.Destination.add(tbe.dir_owner);
    } else {
      // TODO should be random or the closest one
      out_msg.Destination.add(tbe.dir_sharers.smallestElement());
    }
    out_msg.retToSrc := false;
  }
}


action(ExpectNCBWrData, desc="") {
  // Expected data
  int num_msgs := tbe.accSize / data_channel_size;
  if ((tbe.accSize % data_channel_size) != 0) {
    num_msgs := num_msgs + 1;
  }
  tbe.expected_req_resp.clear(num_msgs);
  tbe.expected_req_resp.addExpectedDataType(CHIDataType:NCBWrData);
  tbe.expected_req_resp.setExpectedCount(1);

  // Clear the mask bits we expect to receive
  tbe.dataBlkValid.setMask(addressOffset(tbe.accAddr, tbe.addr), tbe.accSize, false);
}

action(ExpectCompAck, desc="") {
  assert(is_valid(tbe));
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompAck);
  tbe.expected_req_resp.addExpectedCount(1);
}

action(ExpectComp, desc="") {
  assert(is_valid(tbe));
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:Comp);
  tbe.expected_req_resp.addExpectedCount(1);
}

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");
    }
    // Copy data to tbe only if we didn't have valid data or the received
    // data is dirty
    if ((tbe.dataBlkValid.isFull() == false) ||
        (in_msg.type == CHIDataType:CompData_UD_PD) ||
        (in_msg.type == CHIDataType:CompData_SD_PD) ||
        (in_msg.type == CHIDataType:CBWrData_UD_PD) ||
        (in_msg.type == CHIDataType:CBWrData_SD_PD) ||
        (in_msg.type == CHIDataType:NCBWrData)) {
      // clear mask if started to receive new data
      if(tbe.dataBlkValid.isFull()){
        tbe.dataBlkValid.clear();
      }
      tbe.dataBlk.copyPartial(in_msg.dataBlk, in_msg.bitMask);
      assert(tbe.dataBlkValid.isOverlap(in_msg.bitMask) == false);
      tbe.dataBlkValid.orMask(in_msg.bitMask);
    }
  }
}

action(Receive_RespSepDataFromCompData, desc="") {
  assert(is_valid(tbe));
  assert(tbe.expected_req_resp.hasExpected());
  // check if a previous CompData msg already counted as a RespSepData
  if (tbe.expected_req_resp.receivedRespType(CHIResponseType:RespSepData) == false) {
    if (tbe.expected_req_resp.receiveResp(CHIResponseType:RespSepData) == false) {
      error("Received unexpected message");
    }
    if (is_HN == false) {
      // must now ack the responder
      tbe.actions.pushFrontNB(Event:SendCompAck);
    }
  }
}

action(Receive_RespSepData, desc="") {
  assert(is_valid(tbe));
  assert(tbe.expected_req_resp.hasExpected());
  if (tbe.expected_req_resp.receiveResp(CHIResponseType:RespSepData) == false) {
    error("Received unexpected message");
  }
  if (is_HN == false) {
      // must now ack the responder
      tbe.actions.pushFrontNB(Event:SendCompAck);
  }
}

action(Receive_ReadReceipt, desc="") {
  assert(is_valid(tbe));
  assert(tbe.expected_req_resp.hasExpected());
  if (tbe.expected_req_resp.receiveResp(CHIResponseType:ReadReceipt) == false) {
    error("Received unexpected message");
  }
}

action(Receive_SnpDataResp, desc="") {
  assert(is_valid(tbe));
  assert(tbe.expected_snp_resp.hasExpected());
  peek(datInPort, CHIDataMsg) {
    // Decrement pending
    if (tbe.expected_snp_resp.receiveData(in_msg.type) == false) {
      error("Received unexpected message");
    }
    // Copy data to tbe only if we didn't have valid data or the received
    // data is dirty
    if ((tbe.dataBlkValid.isFull() == false) ||
        (in_msg.type == CHIDataType:SnpRespData_I_PD) ||
        (in_msg.type == CHIDataType:SnpRespData_SC_PD) ||
        (in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SD_PD) ||
        (in_msg.type == CHIDataType:SnpRespData_SC_PD_Fwded_SC) ||
        (in_msg.type == CHIDataType:SnpRespData_I_Fwded_SD_PD) ||
        (in_msg.type == CHIDataType:SnpRespData_I_PD_Fwded_SC)) {
      // clear mask if started to receive new data
      if(tbe.dataBlkValid.isFull()){
        tbe.dataBlkValid.clear();
      }
      tbe.dataBlk.copyPartial(in_msg.dataBlk, in_msg.bitMask);
      assert(tbe.dataBlkValid.isOverlap(in_msg.bitMask) == false);
      tbe.dataBlkValid.orMask(in_msg.bitMask);
    }
  }
}

action(UpdateDirState_FromReqDataResp, desc="") {
  assert(is_valid(tbe));
  // only perform the update once we received all chunks
  if (tbe.expected_req_resp.hasReceivedData()) {
    assert(tbe.dataBlkValid.isFull());
    peek(datInPort, CHIDataMsg) {

      if (in_msg.type == CHIDataType:CBWrData_UC) {
        assert(tbe.dir_ownerExists && tbe.dir_ownerIsExcl && (tbe.dir_owner == in_msg.responder));
        assert(tbe.dir_sharers.isElement(in_msg.responder));
        tbe.dir_ownerExists := false;
        tbe.dir_ownerIsExcl := false;
        tbe.dir_sharers.remove(in_msg.responder);

      } else if (in_msg.type == CHIDataType:CBWrData_UD_PD) {
        assert(tbe.dir_ownerExists && tbe.dir_ownerIsExcl && (tbe.dir_owner == in_msg.responder));
        assert(tbe.dir_sharers.isElement(in_msg.responder));
        if (tbe.reqType != CHIRequestType:WriteCleanFull) {
          tbe.dir_ownerExists := false;
          tbe.dir_ownerIsExcl := false;
          tbe.dir_sharers.remove(in_msg.responder);
        }

      } else if (in_msg.type == CHIDataType:CBWrData_SC) {
        assert((tbe.dir_ownerExists == false) || (tbe.dir_owner != in_msg.responder));
        // Do not remove the responder in case of stale WriteCleanFull
        if (tbe.reqType != CHIRequestType:WriteCleanFull) {
          tbe.dir_sharers.remove(in_msg.responder);
        }

      } else if (in_msg.type == CHIDataType:CBWrData_SD_PD) {
        assert(tbe.dir_ownerExists && (tbe.dir_ownerIsExcl == false) && (tbe.dir_owner == in_msg.responder));
        assert(tbe.dir_sharers.isElement(in_msg.responder));
        tbe.dir_ownerExists := false;
        tbe.dir_ownerIsExcl := false;
        if (tbe.reqType != CHIRequestType:WriteCleanFull) {
          tbe.dir_sharers.remove(in_msg.responder);
        }

      } else if (in_msg.type == CHIDataType:CBWrData_I) {
        // nothing to do here; just check
        assert((tbe.dir_ownerExists == false) || (tbe.dir_owner != in_msg.responder));
        assert(tbe.dir_sharers.isElement(in_msg.responder) == false);

      } else {
        error("Unsuported data type");
      }
    }
  }
  printTBEState(tbe);
}

action(UpdateDirState_FromSnpDataResp, desc="") {
  assert(is_valid(tbe));
  // only perform the update once we received all chunks
  if (tbe.expected_snp_resp.hasReceivedData()) {
    assert(tbe.dataBlkValid.isFull());
    peek(datInPort, CHIDataMsg) {

      if (in_msg.type == CHIDataType:SnpRespData_I) {
        assert(tbe.dir_sharers.isElement(in_msg.responder));
        tbe.dir_ownerExists := false;
        tbe.dir_ownerIsExcl := false;
        tbe.dir_sharers.remove(in_msg.responder);

      } else if (in_msg.type == CHIDataType:SnpRespData_I_PD) {
        assert(tbe.dir_ownerExists && (tbe.dir_owner == in_msg.responder));
        assert(tbe.dir_sharers.isElement(in_msg.responder));
        tbe.dir_ownerExists := false;
        tbe.dir_ownerIsExcl := false;
        tbe.dir_sharers.remove(in_msg.responder);

      } else if ((in_msg.type == CHIDataType:SnpRespData_SC_PD) ||
                 (in_msg.type == CHIDataType:SnpRespData_SC) ||
                 (in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SC) ||
                 (in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SD_PD) ||
                 (in_msg.type == CHIDataType:SnpRespData_SC_PD_Fwded_SC)) {
        // the owner must have been the responder, if there was one
        assert((tbe.dir_ownerExists == false) ||
             (tbe.dir_ownerExists && (tbe.dir_owner == in_msg.responder)));
        assert(tbe.dir_sharers.isElement(in_msg.responder));
        tbe.dir_ownerExists := false;
        tbe.dir_ownerIsExcl := false;
        if ((in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SC) ||
            (in_msg.type == CHIDataType:SnpRespData_SC_PD_Fwded_SC) ||
            (in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SD_PD)) {
          tbe.dir_sharers.add(tbe.requestor);
        }
        if (in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SD_PD) {
          tbe.dir_ownerExists := true;
          tbe.dir_owner := tbe.requestor;
        }

      } else if ((in_msg.type == CHIDataType:SnpRespData_I_Fwded_SD_PD) ||
                 (in_msg.type == CHIDataType:SnpRespData_I_PD_Fwded_SC) ||
                 (in_msg.type == CHIDataType:SnpRespData_I_Fwded_SC)) {
        // the owner must have been the responder, if there was one
        assert((tbe.dir_ownerExists == false) ||
             (tbe.dir_ownerExists && (tbe.dir_owner == in_msg.responder)));
        assert(tbe.dir_sharers.isElement(in_msg.responder));
        tbe.dir_ownerExists := false;
        tbe.dir_ownerIsExcl := false;
        tbe.dir_sharers.remove(in_msg.responder);
        tbe.dir_sharers.add(tbe.requestor);
        if (in_msg.type == CHIDataType:SnpRespData_I_Fwded_SD_PD) {
          tbe.dir_ownerExists := true;
          tbe.dir_owner := tbe.requestor;
        }

      } else if ((in_msg.type == CHIDataType:SnpRespData_SD) ||
                 (in_msg.type == CHIDataType:SnpRespData_UC) ||
                 (in_msg.type == CHIDataType:SnpRespData_UD)) {
        // expected only in response to a SnpOnce; just do some checks
        // also may get SnpRespData_SC, but handled properly above
        assert(tbe.dir_ownerExists && (tbe.dir_owner == in_msg.responder));
        assert(tbe.dir_sharers.isElement(in_msg.responder));

      } else {
        error("Unsuported data type");
      }
    }
  }
  printTBEState(tbe);
}

action(UpdateDataState_FromReqDataResp, desc="") {
  assert(is_valid(tbe));
  // only perform the update once we received all chunks
  if (tbe.expected_req_resp.hasReceivedData()) {
    assert(tbe.dataBlkValid.isFull());
    peek(datInPort, CHIDataMsg) {

      if ((in_msg.type == CHIDataType:CompData_UC) ||
          (in_msg.type == CHIDataType:DataSepResp_UC)) {
        assert(tbe.dataUnique == false);
        assert((tbe.dataValid && tbe.dataDirty) == false);
        tbe.dataDirty := false;
        tbe.dataUnique := true;
        tbe.dataValid := true;
        assert(tbe.dataMaybeDirtyUpstream == false);

      } else if (in_msg.type == CHIDataType:CompData_UD_PD) {
        assert(tbe.dataUnique == false);
        assert((tbe.dataValid && tbe.dataDirty) == false);
        tbe.dataDirty := true;
        tbe.dataUnique := true;
        tbe.dataValid := true;
        assert(tbe.dataMaybeDirtyUpstream == false);

      } else if (in_msg.type == CHIDataType:CompData_SC) {
        assert(tbe.dataUnique == false);
        assert((tbe.dataValid && tbe.dataDirty) == false);
        tbe.dataDirty := false;
        tbe.dataUnique := false;
        tbe.dataValid := true;
        assert(tbe.dataMaybeDirtyUpstream == false);

      } else if (in_msg.type == CHIDataType:CompData_SD_PD) {
        assert(tbe.dataUnique == false);
        assert((tbe.dataValid && tbe.dataDirty) == false);
        tbe.dataDirty := true;
        tbe.dataUnique := false;
        tbe.dataValid := true;
        assert(tbe.dataMaybeDirtyUpstream == false);

      } else if (in_msg.type == CHIDataType:CompData_I) {
        tbe.dataValid := true;
        tbe.dataToBeInvalid := true;
        assert(tbe.dataMaybeDirtyUpstream == false);

      } else if (in_msg.type == CHIDataType:CBWrData_UC) {
        assert(tbe.dataUnique);
        tbe.dataMaybeDirtyUpstream := false;
        tbe.dataValid := true;

      } else if (in_msg.type == CHIDataType:CBWrData_SC) {
        // stale WB, nothing to do ??

      } else if (in_msg.type == CHIDataType:CBWrData_UD_PD) {
        assert(tbe.dataUnique);
        tbe.dataDirty := true;
        tbe.dataValid := true;
        if (tbe.reqType == CHIRequestType:WriteCleanFull) {
          // upstream data can still be UC if this is a WriteCleanFull
          assert(tbe.dir_ownerExists && tbe.dir_ownerIsExcl);
          tbe.dataMaybeDirtyUpstream := true;
        } else {
          tbe.dataMaybeDirtyUpstream := false;
        }

      } else if (in_msg.type == CHIDataType:CBWrData_SD_PD) {
        tbe.dataDirty := true;
        tbe.dataValid := true;
        tbe.dataMaybeDirtyUpstream := false;

      } else if (in_msg.type == CHIDataType:CBWrData_I) {
        // stale WB, nothing to do ??

      } else {
        error("Unsuported data type");
      }
    }
  }
  printTBEState(tbe);
}

action(UpdateDataState_FromWUDataResp, desc="") {
  assert(is_valid(tbe));
  if (tbe.expected_req_resp.hasReceivedData()) {
    assert(tbe.dataBlkValid.test(addressOffset(tbe.accAddr, tbe.addr)));
    assert(tbe.dataBlkValid.test(addressOffset(tbe.accAddr, tbe.addr)
                                  + tbe.accSize - 1));
    peek(datInPort, CHIDataMsg) {
      assert(in_msg.type == CHIDataType:NCBWrData);
      tbe.dataDirty := true;
      if (tbe.reqType == CHIRequestType:WriteUniquePtl) {
        // we are just updating any valid data we already had
        tbe.dataValid := tbe.dataValid || (tbe.accSize == blockSize);
      } else {
        tbe.dataValid := tbe.accSize == blockSize;
      }
    }
  }
  printTBEState(tbe);
}

action(UpdateDataState_FromCUResp, desc="") {
  assert(is_valid(tbe));
  peek(rspInPort, CHIResponseMsg) {
    assert(in_msg.type == CHIResponseType:Comp_UC);
    assert(tbe.dataUnique == false);
    tbe.dataUnique := tbe.dataValid || (tbe.dir_sharers.count() > 0);
    // self and upstream may have been invalidated while waiting for this
    // expect to follow up with a ReadUnique
  }
  printTBEState(tbe);
}

action(UpdateDataState_FromSnpDataResp, desc="") {
  assert(is_valid(tbe));
  // only perform the update once we received all chunks
  if (tbe.expected_snp_resp.hasReceivedData()) {
    assert(tbe.dataBlkValid.isFull());
    peek(datInPort, CHIDataMsg) {

      if ((in_msg.type == CHIDataType:SnpRespData_I_PD) ||
          (in_msg.type == CHIDataType:SnpRespData_SC_PD) ||
          (in_msg.type == CHIDataType:SnpRespData_SC_PD_Fwded_SC) ||
          (in_msg.type == CHIDataType:SnpRespData_I_PD_Fwded_SC)) {
        tbe.dataDirty := true;
        tbe.dataValid := true;
        tbe.dataMaybeDirtyUpstream := false;

      } else if ((in_msg.type == CHIDataType:SnpRespData_SD) ||
                 (in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SD_PD) ||
                 (in_msg.type == CHIDataType:SnpRespData_I_Fwded_SD_PD)) {
        tbe.dataDirty := true;
        tbe.dataValid := true;
        tbe.dataMaybeDirtyUpstream := true;

      } else if ((in_msg.type == CHIDataType:SnpRespData_I) ||
                 (in_msg.type == CHIDataType:SnpRespData_SC) ||
                 (in_msg.type == CHIDataType:SnpRespData_SC_Fwded_SC) ||
                 (in_msg.type == CHIDataType:SnpRespData_I_Fwded_SC)) {
        tbe.dataValid := true;
        tbe.dataMaybeDirtyUpstream := false;

      } else if ((in_msg.type == CHIDataType:SnpRespData_UC) ||
                 (in_msg.type == CHIDataType:SnpRespData_UD)) {
        tbe.dataValid := true;
        tbe.dataUnique := true;
        tbe.dataMaybeDirtyUpstream := true;
        if (in_msg.type == CHIDataType:SnpRespData_UD){
          tbe.dataDirty := true;
        }

      } else {
        error("Unsuported data type");
      }
    }
  }
  printTBEState(tbe);
}

action(UpdateDirState_FromReqResp, desc="") {
  peek(rspInPort, CHIResponseMsg) {
    if ((in_msg.type == CHIResponseType:CompAck) && tbe.updateDirOnCompAck) {
      assert(tbe.requestor == in_msg.responder);

      tbe.dir_sharers.add(in_msg.responder);

      if (tbe.requestorToBeOwner) {
        assert(tbe.dataMaybeDirtyUpstream);
        assert(tbe.dir_ownerExists == false);
        assert(tbe.requestorToBeExclusiveOwner == false);
        tbe.dir_owner := in_msg.responder;
        tbe.dir_ownerExists := true;
        tbe.dir_ownerIsExcl := false;

      } else if (tbe.requestorToBeExclusiveOwner) {
        assert(tbe.dataMaybeDirtyUpstream);
        assert(tbe.dir_ownerExists == false);
        assert(tbe.dir_sharers.count() == 1);
        tbe.dir_owner := in_msg.responder;
        tbe.dir_ownerExists := true;
        tbe.dir_ownerIsExcl := true;
      }
    }
  }
  printTBEState(tbe);
}

action(UpdateDirState_FromSnpResp, desc="") {
  peek(rspInPort, CHIResponseMsg) {

    if (in_msg.type == CHIResponseType:SnpResp_I) {
      // must have been a known sharer otherwise we would receive data
      assert(tbe.dir_sharers.isElement(in_msg.responder));
      tbe.dir_sharers.remove(in_msg.responder);
      if (tbe.dir_ownerExists && (tbe.dir_owner == in_msg.responder)){
        tbe.dir_ownerExists := false;
      }

    } else if (in_msg.type == CHIResponseType:SnpResp_SC) {
      // expected from a sharer that already has it in shared state
      assert(tbe.dir_sharers.isElement(in_msg.responder));
      assert((tbe.dir_ownerExists == false) || (tbe.dir_owner != in_msg.responder));

    } else if ((in_msg.type == CHIResponseType:SnpResp_SC_Fwded_SC) ||
               (in_msg.type == CHIResponseType:SnpResp_SC_Fwded_SD_PD)) {
      // the SnpSharedFwd must have been sent to the owner if there was one
      assert((tbe.dir_ownerExists == false) ||
             (tbe.dir_ownerExists && (tbe.dir_owner == in_msg.responder)));
      assert(tbe.dir_sharers.isElement(in_msg.responder));
      tbe.dir_ownerExists := false;
      tbe.dir_ownerIsExcl := false;
      tbe.dir_sharers.add(tbe.requestor);
      if (in_msg.type == CHIResponseType:SnpResp_SC_Fwded_SD_PD) {
        // Requestor is new owner
        tbe.dir_ownerExists := true;
        tbe.dir_owner := tbe.requestor;
      }

    } else if ((in_msg.type == CHIResponseType:SnpResp_I_Fwded_UC) ||
               (in_msg.type == CHIResponseType:SnpResp_I_Fwded_UD_PD)) {
      // must have been a single sharer that received SnpUniqueFwd
      assert(tbe.dir_sharers.isElement(in_msg.responder));
      assert(tbe.dir_sharers.count() == 1);
      tbe.dir_sharers.remove(in_msg.responder);
      // requestor is the new owner
      tbe.dir_sharers.add(tbe.requestor);
      tbe.dir_ownerExists := true;
      tbe.dir_ownerIsExcl := true;
      tbe.dir_owner := tbe.requestor;

    } else if ((in_msg.type == CHIResponseType:SnpResp_UC_Fwded_I) ||
               (in_msg.type == CHIResponseType:SnpResp_UD_Fwded_I) ||
               (in_msg.type == CHIResponseType:SnpResp_SD_Fwded_I)) {
      // SnpSharedFwd; just confirm
      assert(tbe.dir_sharers.isElement(in_msg.responder));
      assert(tbe.dir_ownerExists && (tbe.dir_owner == in_msg.responder));

    } else if (in_msg.type == CHIResponseType:SnpResp_SC_Fwded_I) {
      // SnpSharedFwd; just confirm
      assert(tbe.dir_sharers.isElement(in_msg.responder));
      assert((tbe.dir_ownerExists == false) || (tbe.dir_owner != in_msg.responder));
    }

    tbe.dataMaybeDirtyUpstream := tbe.dir_ownerExists;

  }
  printTBEState(tbe);
}

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

action(Receive_ReqResp_WUNeedComp, desc="") {
  tbe.defer_expected_comp := true;
}

action(Receive_ReqResp_WUComp, desc="") {
  if (tbe.defer_expected_comp) {
    tbe.defer_expected_comp := false;
  } else if (tbe.expected_req_resp.receiveResp(CHIResponseType:Comp) == false) {
    error("Received unexpected message");
  }
}

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 == tbe.is_stale);
  }
}

action(Receive_RetryAck, desc="") {
  assert(is_valid(tbe));
  assert(tbe.pendReqAllowRetry);
  assert(tbe.rcvdRetryAck == false);
  tbe.rcvdRetryAck := true;
  destsWaitingRetry.addNetDest(tbe.pendReqDest);
  enqueueDoRetry(tbe);
}

action(Receive_PCrdGrant, desc="") {
  assert(tbe.pendReqAllowRetry);
  assert(tbe.rcvdRetryCredit == false);
  tbe.rcvdRetryCredit := true;
  enqueueDoRetry(tbe);
}

action(Send_Retry, desc="") {
  assert(tbe.pendReqAllowRetry);
  assert(tbe.rcvdRetryCredit);
  assert(tbe.rcvdRetryAck);
  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequestRetry(tbe, out_msg);
  }
}

action(Send_Retry_DVM, desc="") {
  assert(tbe.pendReqAllowRetry);
  assert(tbe.rcvdRetryCredit);
  assert(tbe.rcvdRetryAck);
  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequestRetryDVM(tbe, out_msg);
  }
  destsWaitingRetry.removeNetDest(tbe.pendReqDest);
}

action(Receive_RetryAck_Hazard, desc="") {
  TBE hazard_tbe := getHazardTBE(tbe);
  assert(hazard_tbe.pendReqAllowRetry);
  assert(hazard_tbe.rcvdRetryAck == false);
  hazard_tbe.rcvdRetryAck := true;
  destsWaitingRetry.addNetDest(hazard_tbe.pendReqDest);
  enqueueDoRetry(hazard_tbe);
}

action(Receive_PCrdGrant_Hazard, desc="") {
  TBE hazard_tbe := getHazardTBE(tbe);
  assert(hazard_tbe.pendReqAllowRetry);
  assert(hazard_tbe.rcvdRetryCredit == false);
  hazard_tbe.rcvdRetryCredit := true;
  enqueueDoRetry(hazard_tbe);
}

action(Send_Retry_Hazard, desc="") {
  TBE hazard_tbe := getHazardTBE(tbe);
  assert(hazard_tbe.pendReqAllowRetry);
  assert(hazard_tbe.rcvdRetryCredit);
  assert(hazard_tbe.rcvdRetryAck);
  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequestRetry(hazard_tbe, out_msg);
  }
}

action(Send_CompData, desc="") {
  assert(is_valid(tbe));
  assert(tbe.dataValid);

  bool is_rd_once := tbe.reqType == CHIRequestType:ReadOnce;
  bool is_rd_shared := (tbe.reqType == CHIRequestType:ReadShared) ||
                       (tbe.reqType == CHIRequestType:ReadNotSharedDirty);
  bool is_rd_nsd := tbe.reqType == CHIRequestType:ReadNotSharedDirty;
  bool is_rd_unique := tbe.reqType == CHIRequestType:ReadUnique;

  // if the config allows (or not caching the data) and line has no sharers
  bool snd_unique_on_rs := (fwd_unique_on_readshared || tbe.dataToBeInvalid)
                          && tbe.dataUnique && tbe.dir_sharers.isEmpty();
  // if the request type allows and we won't be caching the data
  bool snd_dirty_on_rs := is_rd_shared && !is_rd_nsd && tbe.dataToBeInvalid;

  if (is_rd_once) {
    tbe.snd_msgType := CHIDataType:CompData_I;
  } else if (is_rd_unique || (is_rd_shared && snd_unique_on_rs)) {
    assert(tbe.dataUnique);
    if (tbe.dataDirty) {
      tbe.snd_msgType := CHIDataType:CompData_UD_PD;
    } else {
      tbe.snd_msgType := CHIDataType:CompData_UC;
    }
  } else if (is_rd_shared) {
    if (tbe.dataDirty && snd_dirty_on_rs) {
      tbe.snd_msgType := CHIDataType:CompData_SD_PD;
    } else {
      // notice the MaintainCoherence will send WriteClean if the line
      // is dirty and we won't be caching the data
      tbe.snd_msgType := CHIDataType:CompData_SC;
    }
  } else {
    error("Invalid request type");
  }

  tbe.dataMaybeDirtyUpstream := tbe.dataMaybeDirtyUpstream ||
                            (tbe.snd_msgType == CHIDataType:CompData_UD_PD) ||
                            (tbe.snd_msgType == CHIDataType:CompData_SD_PD) ||
                            (tbe.snd_msgType == CHIDataType:CompData_UC);
  tbe.requestorToBeExclusiveOwner := tbe.requestorToBeExclusiveOwner ||
                            (tbe.snd_msgType == CHIDataType:CompData_UD_PD) ||
                            (tbe.snd_msgType == CHIDataType:CompData_UC);
  tbe.requestorToBeOwner := tbe.requestorToBeOwner ||
                            (tbe.snd_msgType == CHIDataType:CompData_SD_PD);

  tbe.snd_destination := tbe.requestor;
  setupPendingSend(tbe);
  printTBEState(tbe);
}

action(Send_WBData, desc="") {
  assert(is_valid(tbe));
  if (is_HN) {
    assert(tbe.dataBlkValid.isFull());
    assert(tbe.dataDirty);
    assert(tbe.dataValid);
    tbe.snd_msgType := CHIDataType:NCBWrData;
  } else {
    if (tbe.dataValid == false) {
      // only possible when the WB was made stale by a snoop
      assert(tbe.is_stale);
      tbe.dataBlkValid.fillMask();
      tbe.snd_msgType := CHIDataType:CBWrData_I;
    } else if (tbe.dataUnique) {
      assert(tbe.dataBlkValid.isFull());
      if (tbe.dataDirty) {
        tbe.snd_msgType := CHIDataType:CBWrData_UD_PD;
      } else {
        tbe.snd_msgType := CHIDataType:CBWrData_UC;
      }
    } else {
      assert(tbe.dataBlkValid.isFull());
      if (tbe.dataDirty) {
        tbe.snd_msgType := CHIDataType:CBWrData_SD_PD;
      } else {
        tbe.snd_msgType := CHIDataType:CBWrData_SC;
      }
    }
  }
  tbe.snd_destination := mapAddressToDownstreamMachine(tbe.addr);
  setupPendingSend(tbe);
}

action(Send_WUData, desc="") {
  assert(is_valid(tbe));
  assert(tbe.dataBlkValid.count() > 0);
  tbe.snd_msgType := CHIDataType:NCBWrData;
  tbe.snd_destination := mapAddressToDownstreamMachine(tbe.addr);
  setupPendingPartialSend(tbe);
}

action(CheckWUComp, desc="") {
  assert(is_valid(tbe));
  if (tbe.defer_expected_comp) {
    tbe.defer_expected_comp := false;
    tbe.expected_req_resp.addExpectedCount(1);
    tbe.expected_req_resp.addExpectedRespType(CHIResponseType:Comp);
  }
}

action(Send_SnpRespData, desc="") {
  assert(is_HN == false);
  assert(is_valid(tbe));
  assert(tbe.dataBlkValid.isFull());
  assert(tbe.dataValid);

  assert(tbe.snpNeedsData ||
         (tbe.dataDirty && (tbe.reqType == CHIRequestType:SnpCleanInvalid)) ||
         ((tbe.dataDirty || tbe.dataUnique) && (tbe.reqType == CHIRequestType:SnpShared)) ||
         ((tbe.dataDirty || tbe.dataUnique) && (tbe.reqType == CHIRequestType:SnpUnique)));

  if (tbe.dataToBeInvalid) {
    assert(tbe.dataMaybeDirtyUpstream == false);
    if (tbe.dataDirty) {
      tbe.snd_msgType := CHIDataType:SnpRespData_I_PD;
    } else {
      tbe.snd_msgType := CHIDataType:SnpRespData_I;
    }
  } else if (tbe.dataToBeSharedClean) {
    assert(tbe.dataMaybeDirtyUpstream == false);
    if (tbe.dataDirty) {
      tbe.snd_msgType := CHIDataType:SnpRespData_SC_PD;
    } else {
      tbe.snd_msgType := CHIDataType:SnpRespData_SC;
    }
  } else {
    assert(tbe.reqType == CHIRequestType:SnpOnce);
    if (tbe.dataDirty && tbe.dataUnique) {
      tbe.snd_msgType := CHIDataType:SnpRespData_UD;
    } else if (tbe.dataDirty) {
      tbe.snd_msgType := CHIDataType:SnpRespData_SD;
    } else if (tbe.dataUnique) {
      tbe.snd_msgType := CHIDataType:SnpRespData_UC;
    } else {
      tbe.snd_msgType := CHIDataType:SnpRespData_SC;
    }
  }

  tbe.snd_destination := tbe.requestor;
  setupPendingSend(tbe);
}

action(Send_CompData_SnpUniqueFwd, desc="") {
  assert(tbe.dataValid);
  assert(tbe.dataToBeInvalid);
  assert(tbe.dataMaybeDirtyUpstream == false);

  if (tbe.dataDirty) {
    tbe.fwdedState := State:UD;
    tbe.snd_msgType := CHIDataType:CompData_UD_PD;
  } else {
    tbe.fwdedState := State:UC;
    tbe.snd_msgType := CHIDataType:CompData_UC;
  }
  tbe.actions.pushFront(Event:SendSnpFwdedResp);

  tbe.snd_destination := tbe.fwdRequestor;
  setupPendingSend(tbe);
}

action(Send_CompData_SnpSharedFwd, desc="") {
  assert(tbe.dataValid);
  assert(tbe.dataToBeSharedClean);
  assert(tbe.dataMaybeDirtyUpstream == false);

  if (tbe.dataDirty) {
    tbe.fwdedState := State:SD;
    tbe.snd_msgType := CHIDataType:CompData_SD_PD;
  } else {
    tbe.fwdedState := State:SC;
    tbe.snd_msgType := CHIDataType:CompData_SC;
  }
  if (tbe.snpNeedsData) {
    tbe.actions.pushFront(Event:SendSnpFwdedData);
  } else {
    tbe.actions.pushFront(Event:SendSnpFwdedResp);
  }

  tbe.snd_destination := tbe.fwdRequestor;
  setupPendingSend(tbe);
}

action(Send_CompData_SnpNSDFwd, desc="") {
  assert(tbe.dataValid);
  assert(tbe.dataToBeSharedClean);
  assert(tbe.dataMaybeDirtyUpstream == false);

  tbe.snd_msgType := CHIDataType:CompData_SC;
  tbe.fwdedState := State:SC;
  if (tbe.dataDirty || tbe.snpNeedsData) {
    tbe.actions.pushFront(Event:SendSnpFwdedData);
  } else {
    tbe.actions.pushFront(Event:SendSnpFwdedResp);
  }

  tbe.snd_destination := tbe.fwdRequestor;
  setupPendingSend(tbe);
}

action(Send_CompData_SnpOnceFwd, desc="") {
  assert(tbe.dataValid);

  tbe.fwdedState := State:I;
  tbe.snd_msgType := CHIDataType:CompData_I;
  tbe.actions.pushFront(Event:SendSnpFwdedResp);

  tbe.snd_destination := tbe.fwdRequestor;
  setupPendingSend(tbe);
}

action(Send_SnpRespDataFwded, desc="") {
  assert(tbe.dataValid);

  // right only using this for the SnpShared/SnpNSD, so check
  assert(tbe.dataToBeSharedClean);
  assert(tbe.dataMaybeDirtyUpstream == false);

  // We have the data (locally or upstream) or are dropping it
  bool keepData := (tbe.dir_sharers.count() > 0) ||
                   (tbe.dataToBeInvalid == false);

  if (keepData) {
    if (tbe.fwdedState == State:SD) {
      tbe.snd_msgType := CHIDataType:SnpRespData_SC_Fwded_SD_PD;
    } else if (tbe.dataDirty && (tbe.fwdedState == State:SC)) {
      tbe.snd_msgType := CHIDataType:SnpRespData_SC_PD_Fwded_SC;
    } else {
      tbe.snd_msgType := CHIDataType:SnpRespData_SC_Fwded_SC;
    }
  } else {
    if (tbe.fwdedState == State:SD) {
      tbe.snd_msgType := CHIDataType:SnpRespData_I_Fwded_SD_PD;
    } else if (tbe.dataDirty && (tbe.fwdedState == State:SC)) {
      tbe.snd_msgType := CHIDataType:SnpRespData_I_PD_Fwded_SC;
    } else {
      tbe.snd_msgType := CHIDataType:SnpRespData_I_Fwded_SC;
    }
  }

  tbe.snd_destination := tbe.requestor;
  setupPendingSend(tbe);
}

action(Send_FwdSnpResp, desc="") {
  assert(is_valid(tbe));
  assert(tbe.dataValid);

  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);

    // We have the data (locally or upstream) or are dropping it
    bool keepData := (tbe.dir_sharers.count() > 0) ||
                     (tbe.dataToBeInvalid == false);

    if (keepData && tbe.dataToBeSharedClean) {
      assert((tbe.reqType == CHIRequestType:SnpSharedFwd) ||
             (tbe.reqType == CHIRequestType:SnpNotSharedDirtyFwd));
      assert(tbe.dataMaybeDirtyUpstream == false);
      if (tbe.fwdedState == State:SD) {
        out_msg.type := CHIResponseType:SnpResp_SC_Fwded_SD_PD;
      } else {
        assert(tbe.fwdedState == State:SC);
        out_msg.type := CHIResponseType:SnpResp_SC_Fwded_SC;
      }

    } else if (keepData) {
      assert(tbe.reqType == CHIRequestType:SnpOnceFwd);
      assert(tbe.fwdedState == State:I);
      if (tbe.dataUnique && (tbe.dataDirty || tbe.dataMaybeDirtyUpstream)) {
        out_msg.type := CHIResponseType:SnpResp_UD_Fwded_I;
      } else if (tbe.dataUnique) {
        out_msg.type := CHIResponseType:SnpResp_UC_Fwded_I;
      } else if (tbe.dataDirty || tbe.dataMaybeDirtyUpstream) {
        out_msg.type := CHIResponseType:SnpResp_SD_Fwded_I;
      } else {
        out_msg.type := CHIResponseType:SnpResp_SC_Fwded_I;
      }

    } else {
      assert(tbe.reqType == CHIRequestType:SnpUniqueFwd);
      assert(tbe.dataMaybeDirtyUpstream == false);
      if (tbe.fwdedState == State:UD) {
        out_msg.type := CHIResponseType:SnpResp_I_Fwded_UD_PD;
      } else {
        assert(tbe.fwdedState == State:UC);
        out_msg.type := CHIResponseType:SnpResp_I_Fwded_UC;
      }
    }
  }
}

action(Send_Data, desc="") {
  assert(tbe.snd_pendEv);
  assert(tbe.snd_pendBytes.count() > 0);
  tbe.snd_pendEv := false;
  enqueue(datOutPort, CHIDataMsg, data_latency) {
    out_msg.addr := tbe.addr;
    out_msg.type := tbe.snd_msgType;

    int offset := tbe.snd_pendBytes.firstBitSet(true);
    assert(offset < blockSize);
    int range := tbe.snd_pendBytes.firstBitSet(false, offset) - offset;
    assert((range > 0) && (range <= blockSize));
    if (range > data_channel_size) {
      range := data_channel_size;
    }
    tbe.snd_pendBytes.setMask(offset, range, false);

    out_msg.dataBlk := tbe.dataBlk;
    out_msg.bitMask.setMask(offset, range);

    out_msg.responder := machineID;

    out_msg.Destination.add(tbe.snd_destination);
  }

  // send next chunk (if any) next cycle
  scheduleSendData(tbe, 1);
}

action(Send_RespSepData, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:RespSepData;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
  }
}

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

  // Used to ack Evict request
  assert(tbe.dir_sharers.isElement(tbe.requestor));
  assert((tbe.dir_ownerExists == false) || (tbe.dir_owner != tbe.requestor));

  tbe.dir_sharers.remove(tbe.requestor);

  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:Comp_I;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
  }
}

action(Send_CompUC, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:Comp_UC;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
  }
}

action(Send_CompUC_Stale, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:Comp_UC;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
    // We don't know if this is a stale clean unique or a bug, so flag the
    // reponse so the requestor can make further checks
    out_msg.stale := true;
  }
}

action(Send_CompAck, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:CompAck;
    out_msg.responder := machineID;
    out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
  }
}

action(Send_CompI_Stale, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:Comp_I;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
    // We don't know if this is a stale writeback or a bug, so flag the
    // reponse so the requestor can make further checks
    out_msg.stale := true;
  }
}

action(Send_CompDBIDResp, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:CompDBIDResp;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
  }
}

action(Send_CompDBIDResp_Stale, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:CompDBIDResp;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
    // We don't know if this is a stale writeback or a bug, so flag the
    // reponse so the requestor can make further checks
    out_msg.stale := true;
  }
}

action(Send_DBIDResp, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:DBIDResp;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
  }
}

action(Send_Comp_WU, desc="") {
  assert(is_valid(tbe));
  enqueue(rspOutPort, CHIResponseMsg, comp_wu_latency + response_latency) {
    out_msg.addr := address;
    out_msg.type := CHIResponseType:Comp;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
  }
}

action(Send_SnpRespI, desc="") {
  enqueue(rspOutPort, CHIResponseMsg, response_latency) {
    out_msg.addr := address;
    if (tbe.is_dvm_tbe || tbe.is_dvm_snp_tbe) {
      out_msg.usesTxnId := true;
      out_msg.txnId := tbe.addr;
    }
    out_msg.type := CHIResponseType:SnpResp_I;
    out_msg.responder := machineID;
    out_msg.Destination.add(tbe.requestor);
  }
}

action(Send_RetryAck, desc="") {
  peek(retryTriggerInPort, RetryTriggerMsg) {
    enqueue(rspOutPort, CHIResponseMsg, response_latency) {
      out_msg.addr := in_msg.addr;
      out_msg.usesTxnId := in_msg.usesTxnId;
      out_msg.type := CHIResponseType:RetryAck;
      out_msg.responder := machineID;
      out_msg.Destination.add(in_msg.retryDest);
    }
  }
}

action(Send_PCrdGrant, desc="") {
  peek(retryTriggerInPort, RetryTriggerMsg) {
    enqueue(rspOutPort, CHIResponseMsg, response_latency) {
      out_msg.addr := in_msg.addr;
      out_msg.usesTxnId := in_msg.usesTxnId;
      out_msg.type := CHIResponseType:PCrdGrant;
      out_msg.responder := machineID;
      out_msg.Destination.add(in_msg.retryDest);
    }
  }
}

// Note on CheckUpgrade_FromStoreOrRU/CheckUpgrade_FromCU
// We will always get Comp_UC; but if our data is invalidated before
// Comp_UC we would need to go to UCE. Since we don't use the UCE state
// we remain in the transient state and follow-up with ReadUnique.
// Note this assumes the responder knows we have invalid data when sending
// us Comp_UC and does not register us as owner.

action(CheckUpgrade_FromStoreOrRU, desc="") {
  assert(is_HN == false);
  if (tbe.dataUnique) {
    // success, just send CompAck next
    assert(tbe.dataValid);
  } else {
    // will need to get data instead
    tbe.actions.pushFront(Event:SendReadUnique);
    // we must have received an invalidation snoop that marked
    // the req as stale
    assert(tbe.is_stale);
    tbe.is_stale := false;
  }
  tbe.actions.pushFront(Event:SendCompAck);
}

action(CheckUpgrade_FromCU, desc="") {
  assert(is_HN == false);
  if (tbe.dataUnique == false) {
    // actually failed, so just cancel the directory update
    assert(tbe.dir_sharers.isElement(tbe.requestor) == false);
    tbe.requestorToBeExclusiveOwner := false;
    tbe.updateDirOnCompAck := false;
  }
  // otherwise nothing else to do here other than acking the CleanUnique
  tbe.actions.pushFront(Event:SendCompAck);
}


action(Finalize_UpdateCacheFromTBE, desc="") {
  assert(is_valid(tbe));
  State final := tbe.finalState;
  if ((final == State:UD_RSC) || (final == State:SD_RSC) || (final == State:UC_RSC) ||
      (final == State:SC_RSC) || (final == State:UD)     || (final == State:UD_T) ||
      (final == State:SD)     || (final == State:UC)     || (final == State:SC) ||
      (final == State:UC_RU)  || (final == State:UD_RU)  || (final == State:UD_RSD) ||
      (final == State:SD_RSD)) {
    assert(tbe.dataBlkValid.isFull());
    assert(tbe.dataValid);
    assert(is_valid(cache_entry));
    cache_entry.DataBlk := tbe.dataBlk;
    DPRINTF(RubySlicc, "Cached data %s pfb %s\n", tbe.dataBlk, cache_entry.HWPrefetched);
  } else {
    // make sure only deallocate the cache entry if data is invalid
    assert(tbe.dataValid == false);
    if (is_valid(cache_entry)) {
      cache.deallocate(address);
      unset_cache_entry();
    }
  }
}

action(Finalize_UpdateDirectoryFromTBE, desc="") {
  assert(is_valid(tbe));
  State final := tbe.finalState;
  if ((final == State:UD_RSC) || (final == State:SD_RSC) || (final == State:UC_RSC) ||
      (final == State:SC_RSC) || (final == State:UC_RU)  || (final == State:UD_RU) ||
      (final == State:UD_RSD) || (final == State:SD_RSD) || (final == State:RU) ||
      (final == State:RSC)    || (final == State:RSD)    || (final == State:RUSD) ||
      (final == State:RUSC)) {
    DirEntry dir_entry := getDirEntry(address);
    assert(is_valid(dir_entry));
    assert(tbe.dir_sharers.count() > 0);
    dir_entry.ownerExists := tbe.dir_ownerExists;
    dir_entry.ownerIsExcl := tbe.dir_ownerIsExcl;
    dir_entry.owner := tbe.dir_owner;
    dir_entry.sharers := tbe.dir_sharers;
  } else {
    assert((tbe.dir_ownerExists == false) && tbe.dir_sharers.isEmpty());
    if(directory.isTagPresent(address)) {
      directory.deallocate(address);
    }
  }
}

action(Deallocate_CacheBlock, desc="") {
  assert(is_valid(cache_entry));
  cache.deallocate(address);
  unset_cache_entry();
}

action(Allocate_DirEntry, desc="") {
  assert(directory.isTagPresent(address) == false);
  directory.allocate(address);
}

action(Deallocate_DirEntry, desc="") {
  assert(directory.isTagPresent(address));
  directory.deallocate(address);
}

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

  // only perform the write if we have valid data and need to write
  bool need_fill := tbe.dataValid && (tbe.dataToBeInvalid == false) && tbe.doCacheFill;
  bool execute_next := true;

  if (need_fill && is_valid(cache_entry)) {
    // can write
    tbe.actions.pushFront(Event:DataArrayWrite);
    tbe.actions.pushFront(Event:FillPipe);

  } else if (need_fill && cache.cacheAvail(address)) {
    // don't have a cache block, but there is space to allocate one
    set_cache_entry(cache.allocate(address, new CacheEntry));
    tbe.actions.pushFront(Event:DataArrayWriteOnFill);
    tbe.actions.pushFront(Event:FillPipe);

  } else if (need_fill) {
    // performs a cache block replacement. CheckCacheFill executes again
    // after the replacement
    execute_next := false;

    // pick a victim to deallocate
    Addr victim_addr := cache.cacheProbe(address);
    CacheEntry victim_entry := getCacheEntry(victim_addr);
    assert(is_valid(victim_entry));
    TBE victim_tbe := getCurrentActiveTBE(victim_addr);

    // The `is_valid(victim_entry)` condition here is to avoid an unused
    // variable error when compiling to gem5.fast.
    if (is_invalid(victim_tbe) && is_valid(victim_entry)) {
      DPRINTF(RubySlicc, "Eviction for %#x victim: %#x state=%s\n",
                          address, victim_addr, victim_entry.state);
      enqueue(replTriggerOutPort, ReplacementMsg, 0) {
        out_msg.addr := victim_addr;
        out_msg.from_addr := address;
        if (unify_repl_TBEs) {
          out_msg.slot := tbe.storSlot;
          DPRINTF(RubySlicc, "Reusing slot %d\n", out_msg.slot);
        }
      }
    } else {
      DPRINTF(RubySlicc, "Eviction for %#x victim: %#x state=%s\n",
                          address, victim_addr, victim_tbe.state);
      // just wait until the transaction finishes to try again
      victim_tbe.wakeup_pending_tgr := true;
    }

    // wait until we can deallocate the victim_addr
    stall_and_wait(triggerInPort, victim_addr);
  }

  // only do the usual Pop_TriggerQueue+ProcessNextState if we have a block
  if (execute_next) {
    triggerInPort.dequeue(clockEdge());
    clearPendingAction(tbe);
    processNextState(address, tbe, cache_entry);
  } else {
    wakeupPendingSnps(tbe); // might have stalled snoops that can execute now
  }
}


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

  if (tbe.is_req_tbe) {
    deallocateReqTBE(tbe);
    processRetryQueue();

  } else if (tbe.is_snp_tbe) {
    deallocateSnpTBE(tbe);

  } else {
    deallocateReplacementTBE(tbe);
    if (unify_repl_TBEs) {
      processRetryQueue();
    }
  }
  unset_tbe();

  incomingTransactionEnd(address, curTransitionNextState());
}

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

  // Don't call processRetryQueue() because DVM ops don't interact with the retry queue

  assert(tbe.is_dvm_tbe);
  deallocateDvmTBE(tbe);
  unset_tbe();
}

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

  // Don't call processRetryQueue() because DVM ops don't interact with the retry queue

  assert(tbe.is_dvm_snp_tbe);
  deallocateDvmSnoopTBE(tbe);
  unset_tbe();

  // Last argument = false, so it uses a "unique ID" rather than an address
  incomingTransactionEnd(address, curTransitionNextState(), false);
}

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

action(Pop_RespInQueue, desc="") {
  rspInPort.dequeue(clockEdge());
}

action(Pop_SnoopRdyQueue, desc="") {
  snpRdyPort.dequeue(clockEdge());
}

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

// 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_ReplTriggerQueue, desc="") {
  replTriggerInPort.dequeue(clockEdge());
  // wakeup the transaction that triggered this eviction
  wakeup_port(triggerInPort, address);
}

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

action(Pop_SnpInPort, desc="") {
  snpInPort.dequeue(clockEdge());
}
action(Pop_SeqInPort, desc="") {
  seqInPort.dequeue(clockEdge());
}

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

action(ProcessNextState_ClearPending, desc="") {
  assert(is_valid(tbe));
  clearPendingAction(tbe);
  processNextState(address, tbe, cache_entry);
}

action(Callback_LoadHit, desc="") {
  assert(is_valid(tbe));
  assert(tbe.reqType == CHIRequestType:Load);
  if (tbe.is_local_pf == false) {
    assert(tbe.dataValid);
    DPRINTF(RubySlicc, "Read data %s\n", tbe.dataBlk);
    sequencer.readCallback(tbe.addr, tbe.dataBlk, false);
  }
}

action(Callback_StoreHit, desc="") {
  assert(is_valid(tbe));
  assert((tbe.reqType == CHIRequestType:StoreLine) ||
         (tbe.reqType == CHIRequestType:Store));
  if (tbe.is_local_pf == false) {
    assert(tbe.dataValid);
    DPRINTF(RubySlicc, "Write before %s\n", tbe.dataBlk);
    sequencer.writeCallback(tbe.addr, tbe.dataBlk, false);
    DPRINTF(RubySlicc, "Write after %s\n", tbe.dataBlk);
    tbe.dataDirty := true;
  }
}

action(Callback_ExpressPrefetchHit, desc="") {
  // have not allocated TBE, but must clear the reservation
  assert(is_invalid(tbe));
  storTBEs.decrementReserved();
  assert(storTBEs.areNSlotsAvailable(1));
  assert(use_prefetcher);

  cache.profilePrefetchHit();
  peek(reqRdyPort, CHIRequestMsg) {
    assert(in_msg.is_local_pf);
    notifyPfComplete(in_msg.addr);
  }
}

// This is called everytime a data message is received but only goes
// though once all the blocks are present (tbe.dataValid)
// NOTE: should create a separate trigger for this callback ?
action(Callback_Miss, desc="") {
  assert(is_valid(tbe));
  if (tbe.dataValid && tbe.is_local_pf) {
    assert(use_prefetcher);
    notifyPfComplete(tbe.addr);

  } else if (tbe.dataValid && (tbe.reqType == CHIRequestType:Load)) {
    DPRINTF(RubySlicc, "Read data %s\n", tbe.dataBlk);
    sequencer.readCallback(tbe.addr, tbe.dataBlk, true);

  } else if (tbe.dataValid && ((tbe.reqType == CHIRequestType:Store) ||
                               (tbe.reqType == CHIRequestType:StoreLine))) {
    DPRINTF(RubySlicc, "Write before %s\n", tbe.dataBlk);
    sequencer.writeCallback(tbe.addr, tbe.dataBlk, true);
    DPRINTF(RubySlicc, "Write after %s\n", tbe.dataBlk);
    tbe.dataDirty := true;

    // sets a use time out for store misses to prevent LL/SC livelocks
    int use_timeout_latency := scLockLatency();
    if (use_timeout_latency > 0) {
      if (tbe.hasUseTimeout) {
        assert(useTimerTable.isSet(tbe.addr));
      } else {
        useTimerTable.set(
                tbe.addr,
                clockEdge() + cyclesToTicks(intToCycles(use_timeout_latency)));
        tbe.hasUseTimeout := true;
      }
      // also decay the timeout
      scLockDecayLatency();
    }
  }
}

action(Unset_Timeout_TBE, desc="") {
  assert(is_valid(tbe));
  assert(tbe.hasUseTimeout);
  assert(useTimerTable.isSet(tbe.addr));
  useTimerTable.unset(tbe.addr);
  tbe.hasUseTimeout := false;
  // A snoop may have been stalled without setting the TBE flag
  wakeup_port(snpRdyPort, address);
}

action(Unset_Timeout_Cache, desc="") {
  assert(useTimerTable.isSet(address));
  useTimerTable.unset(address);
  wakeup_port(snpRdyPort, address);
}

action(Callback_WriteUnique, desc="") {
  assert(is_valid(tbe));
  assert((tbe.is_local_pf || tbe.is_remote_pf) == false);
  assert((tbe.reqType == CHIRequestType:StoreLine) ||
         (tbe.reqType == CHIRequestType:Store));
  assert(tbe.dataValid == false);
  sequencer.writeUniqueCallback(tbe.addr, tbe.dataBlk);
  DPRINTF(RubySlicc, "WriteUnique data %s\n", tbe.dataBlk);
  // set mask; note data is never considered valid
  assert(tbe.dataBlkValid.isEmpty());
  tbe.dataBlkValid.setMask(addressOffset(tbe.accAddr, tbe.addr), tbe.accSize);
}

action(Profile_Miss, desc="") {
  assert(is_valid(tbe));
  bool is_demand := (tbe.is_local_pf || tbe.is_remote_pf) == false;
  bool is_remote_can_notify := tbe.is_remote_pf && upstream_prefetch_trains_prefetcher;
  if (is_demand) {
    cache.profileDemandMiss();
  } else {
    assert(use_prefetcher || tbe.is_remote_pf);
    cache.profilePrefetchMiss();
  }
  // notify prefetcher about this demand miss
  if (use_prefetcher && tbe.isSeqReqValid && (is_demand || is_remote_can_notify)) {
    bool is_read := false;
    if (isReadReqType(tbe.reqType)) {
      is_read := true;
    } else {
      assert(isWriteReqType(tbe.reqType));
    }

    // FIXME: this dataBlk is likely to have stale data. This should be fixed
    // if our prefetcher uses cached data to make prefetch decisions.
    notifyPfMiss(tbe.seqReq, is_read, tbe.dataBlk);
  }
}

action(Profile_Hit, desc="") {
  assert(is_valid(tbe));
  assert(is_valid(cache_entry));
  assert(tbe.dataValid);
  bool is_demand := (tbe.is_local_pf || tbe.is_remote_pf) == false;
  bool is_remote_can_notify := tbe.is_remote_pf && upstream_prefetch_trains_prefetcher;
  if (is_demand) {
    cache.profileDemandHit();
  } else {
    assert(use_prefetcher || tbe.is_remote_pf);
    cache.profilePrefetchHit();
  }
  // notify prefetcher about this demand hit
  if (use_prefetcher && tbe.isSeqReqValid && (is_demand || is_remote_can_notify)) {
    bool is_read := false;
    if (isReadReqType(tbe.reqType)) {
      is_read := true;
    } else {
      assert(isWriteReqType(tbe.reqType));
    }
    notifyPfHit(tbe.seqReq, is_read, tbe.dataBlk);

    cache_entry.HWPrefetched := false;
  }
}

action(Profile_Fill, desc="") {
  assert(is_valid(tbe));
  assert(is_valid(cache_entry));
  if (use_prefetcher && tbe.isSeqReqValid) {

    cache_entry.HWPrefetched := tbe.is_local_pf ||
                          (tbe.is_remote_pf &&
                            (upstream_prefetch_trains_prefetcher == false));

    // Prefetchers that use this info require notifications from both
    // demand and pf fills (unlike notifyPfHit/notifyPfMiss)
    notifyPfFill(tbe.seqReq, tbe.dataBlk, tbe.is_local_pf);
  }
}

action(Profile_Eviction, desc="") {
  if (sc_lock_enabled && sequencer.llscCheckMonitor(address)) {
    DPRINTF(LLSC, "Invalidating monitored address %#x\n", address);
    scLockIncLatency();
  }
  if (send_evictions) {
    DPRINTF(RubySlicc, "Sending invalidation for %#x to the sequencer\n", address);
    sequencer.evictionCallback(address);
  }
  if (use_prefetcher && is_valid(cache_entry)) {
    notifyPfEvict(address, cache_entry.HWPrefetched);
  }
}

action(Profile_OutgoingStart, desc="") {
  outgoingTransactionStart(address, curTransitionEvent());
}

action(Profile_OutgoingEnd_DataResp, desc="") {
  assert(is_valid(tbe));
  // completes once all data is received
  if (tbe.expected_req_resp.hasReceivedData()) {
    outgoingTransactionEnd(address, tbe.rcvdRetryAck);
  }
}

action(Profile_OutgoingEnd_DatalessResp, desc="") {
  assert(is_valid(tbe));
  outgoingTransactionEnd(address, tbe.rcvdRetryAck);
}

action(TagArrayRead, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(
                            tagLatency((tbe.reqType == CHIRequestType:Load) ||
                                      (tbe.reqType == CHIRequestType:Store) ||
                                      (tbe.reqType == CHIRequestType:StoreLine)));
}

action(TagArrayWrite, desc="") {
  assert(is_valid(tbe));
  // when hasUseTimeout is set the final state is UD_T, but adding a delay
  // between now and triggering Fin_UD_T may allow the timer to expire and then
  // we end up in the wrong state
  if (dealloc_wait_for_tag && (tbe.hasUseTimeout == false)) {
    tbe.delayNextAction := curTick() + cyclesToTicks(tagLatency(false));
  }
}

action(DataArrayRead, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(dataLatency());
}

action(DataArrayWrite, desc="") {
  assert(is_valid(tbe));
  assert(is_valid(cache_entry));
  assert(tbe.doCacheFill);
  if(wait_for_cache_wr) {
    tbe.delayNextAction := curTick() + cyclesToTicks(dataLatency());
  }
}

action(ReadHitPipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(read_hit_latency);
}

action(ReadMissPipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(read_miss_latency);
}

action(WriteFEPipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(write_fe_latency);
}

action(WriteBEPipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(write_be_latency);
}

action(FillPipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(fill_latency);
}

action(SnpSharedPipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(snp_latency);
}

action(SnpInvPipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(snp_latency + snp_inv_latency);
}

action(SnpOncePipe, desc="") {
  assert(is_valid(tbe));
  tbe.delayNextAction := curTick() + cyclesToTicks(snp_latency);
}

//////////////////////////////////
// DVM Actions

action(Send_DvmTlbi, desc="") {
  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:DvmOpNonSync, out_msg);
    DPRINTF(RubyProtocol, "Sending DvmOpNonSync to %d\n", getMiscNodeMachine());

    out_msg.usesTxnId := true;
    out_msg.txnId := tbe.addr; // for DVM TBEs addr = txnId

    out_msg.Destination.clear();
    out_msg.Destination.add(getMiscNodeMachine());
    out_msg.dataToFwdRequestor := false;

    // Don't set message size, we don't use the data inside the messages

    allowRequestRetry(tbe, out_msg);
  }

  // TLBIs can be ended early if the MN chooses to send CompDBIDResp.
  // Otherwise, the MN sends a plain DBIDResp, and then sends a Comp later.
  // => We add two possible response types, then add 1 to the count
  // e.g. "expect exactly 1 (CompDBIDResp OR DBIDResp)"
  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompDBIDResp);
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:DBIDResp);
  tbe.expected_req_resp.addExpectedCount(1);
  // If a plain DBIDResp is recieved, then Comp will be manually expected.
  // (expect_sep_wu_comp also sort of handles this, but it's WU specific,
  // and ProcessNextState doesn't respect it).

  // Push a value to the list of pending NonSyncs
  // The actual value doesn't matter, but we have to pick
  // a type which already has function signatures
  // e.g. TriggerQueue has push(Event) specified in SLICC but not push(addr)
  DPRINTF(RubyProtocol, "Pushing pending nonsync to blocklist %16x\n", tbe.addr);
  dvmPendingNonSyncsBlockingSync.push(Event:DvmTlbi_Initiate);
}

// Try to send a DVM Sync, but put it in the pending slot
// if there are pending Non-Syncs blocking it.
action(Try_Send_DvmSync, desc="") {
  if (dvmPendingNonSyncsBlockingSync.empty()){
    DPRINTF(RubyProtocol, "Nonsync queue is empty so %016x can proceed\n", tbe.addr);
    tbe.actions.push(Event:DvmSync_Send);
  } else {
    assert(!dvmHasPendingSyncOp);
    DPRINTF(RubyProtocol, "Nonsync queue is not empty so %016x is now pending\n", tbe.addr);
    dvmHasPendingSyncOp := true;
    dvmPendingSyncOp := address;
  }
}

// Try to send a DVM sync that was put in the pending slot
// due to pending Non-Syncs blocking it. Those Non-Syncs may not be
// blocking it anymore.
action(Try_Send_Pending_DvmSync, desc="") {
  // Pop an element off the list of pending NonSyncs
  // It won't necessarily be ours, but that doesn't matter.
  assert(!dvmPendingNonSyncsBlockingSync.empty());
  DPRINTF(RubyProtocol, "Popping nonsync from blocklist %16x\n", tbe.addr);
  dvmPendingNonSyncsBlockingSync.pop();

  if (dvmPendingNonSyncsBlockingSync.empty() && dvmHasPendingSyncOp) {
    DPRINTF(RubyProtocol, "Blocklist now empty, pending op %16x can proceed\n", dvmPendingSyncOp);
    TBE syncTBE := getDvmTBE(dvmPendingSyncOp);
    assert(is_valid(syncTBE));
    syncTBE.actions.push(Event:DvmSync_Send);

    dvmHasPendingSyncOp := false;
  }
}

action(Send_DvmSync, desc="") {
  enqueue(reqOutPort, CHIRequestMsg, request_latency) {
    prepareRequest(tbe, CHIRequestType:DvmOpSync, out_msg);
    DPRINTF(RubyProtocol, "Sending DvmOpSync to %d\n", getMiscNodeMachine());

    out_msg.usesTxnId := true;
    out_msg.txnId := tbe.addr; // for DVM TBEs addr = txnId

    out_msg.Destination.clear();
    out_msg.Destination.add(getMiscNodeMachine());
    out_msg.dataToFwdRequestor := false;

    // Don't set message size, we don't use the data inside the messages

    allowRequestRetry(tbe, out_msg);
  }

  clearExpectedReqResp(tbe);
  tbe.expected_req_resp.addExpectedRespType(CHIResponseType:DBIDResp);
  tbe.expected_req_resp.addExpectedCount(1);
  // Comp will be expected later
}

action(Send_DvmTlbi_NCBWrData, desc="") {
  enqueue(datOutPort, CHIDataMsg, data_latency) {
    out_msg.addr := tbe.addr;
    out_msg.type := CHIDataType:NCBWrData;

    out_msg.usesTxnId := true;
    out_msg.txnId := tbe.addr; // for DVM TBEs addr = txnId

    // Set dataBlk to all 0 - we don't actually use the contents
    out_msg.dataBlk.clear();
    // Data should be 8 bytes - this function is (offset, range)
    out_msg.bitMask.setMask(0, 8);

    out_msg.responder := machineID;

    out_msg.Destination.clear();
    out_msg.Destination.add(getMiscNodeMachine());
  }
}

action(Send_DvmSync_NCBWrData, desc="") {
  enqueue(datOutPort, CHIDataMsg, data_latency) {
    out_msg.addr := tbe.addr;
    out_msg.type := CHIDataType:NCBWrData;

    out_msg.usesTxnId := true;
    out_msg.txnId := tbe.addr; // for DVM TBEs addr = txnId

    // Set dataBlk to all 0 - we don't actually use the contents
    out_msg.dataBlk.clear();
    // Data should be 8 bytes - this function is (offset, range)
    // I assume the range is in bytes...
    out_msg.bitMask.setMask(0, 8);

    out_msg.responder := machineID;

    out_msg.Destination.clear();
    out_msg.Destination.add(getMiscNodeMachine());
  }
}

action(DvmTlbi_CompCallback, desc="") {
  assert(is_valid(tbe));
  assert(tbe.is_dvm_tbe);
  assert(tbe.reqType == CHIRequestType:DvmTlbi_Initiate);
  sequencer.unaddressedCallback(tbe.addr, RubyRequestType:TLBI);
}

action(DvmSync_CompCallback, desc="") {
  assert(is_valid(tbe));
  assert(tbe.is_dvm_tbe);
  assert(tbe.reqType == CHIRequestType:DvmSync_Initiate);
  sequencer.unaddressedCallback(tbe.addr, RubyRequestType:TLBI_SYNC);
}

//////////////////////////////////
// DVM Snoop Actions

action(Initiate_DvmSnoop, desc="") {
  // DvmSnoop cannot be retried
  bool was_retried := false;
  peek(snpRdyPort, CHIRequestMsg) {
    set_tbe(allocateDvmSnoopTBE(address, in_msg));
  }
  // Last argument = false, so it uses a "unique ID" rather than an address
  // "Incoming" transactions for DVM = time between receiving a Snooped DVM op
  // and sending the SnpResp_I
  incomingTransactionStart(address, curTransitionEvent(), State:I, was_retried, false);
}

action(DvmExtTlbi_EnqueueSnpResp, desc=""){
  tbe.delayNextAction := curTick() + cyclesToTicks(dvm_ext_tlbi_latency);
  tbe.actions.push(Event:SendSnpIResp);
}

action(DvmExtSync_TriggerCallback, desc=""){
  assert(is_valid(tbe));
  assert(tbe.is_dvm_snp_tbe);
  sequencer.unaddressedCallback(tbe.addr, RubyRequestType:TLBI_EXT_SYNC);
}

action(Profile_OutgoingStart_DVM, desc="") {
  outgoingTransactionStart(address, curTransitionEvent(), false);
}

action(Profile_OutgoingEnd_DVM, desc="") {
  assert(is_valid(tbe));
  outgoingTransactionEnd(address, tbe.rcvdRetryAck, false);
}
