/*
 * Copyright (c) 2021 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


////////////////////////////////////////////////////////////////////////////
// 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
}



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.actions.push(Event:SendCompUCRespStale);
    tbe.actions.push(Event:WaitCompAck);
    tbe.is_stale := false;
  } else {
    // must be the only one in sharers map
    assert(tbe.dir_sharers.count() == 1);
    assert(tbe.dataUnique);

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

    // similar to Initiate_MaitainCoherence; writeback if the owner has data as
    // clean data and we have it dirty and cannot keep it
    bool fill_pipeline := tbe.dataValid && tbe.dataDirty;
    bool req_has_dirty := tbe.dir_ownerExists && (tbe.dir_owner == tbe.requestor);
    if (tbe.dataValid && tbe.dataDirty && tbe.dataToBeInvalid &&
        (req_has_dirty == false)) {
      fill_pipeline := false;
      if (is_HN) {
        tbe.actions.push(Event:SendWriteNoSnp);
      } else {
        tbe.actions.push(Event:SendWriteClean);
      }
      tbe.actions.push(Event:WriteBEPipe);
      tbe.actions.push(Event:SendWBData);
    }

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

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


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="") {
  if (comp_wu) {
    tbe.actions.push(Event:SendDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendWriteUnique);
    tbe.actions.pushNB(Event:SendComp_WU);
  } else {
    tbe.actions.push(Event:SendCompDBIDResp_WU);
    tbe.actions.pushNB(Event:WriteFEPipe);
    tbe.actions.pushNB(Event:SendWriteUnique);
  }
  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="") {
  tbe.actions.push(Event:SendCompIResp);

  assert(tbe.dir_sharers.isElement(tbe.requestor));
  assert((tbe.dir_ownerExists == false) || (tbe.dir_owner != tbe.requestor));
  tbe.dir_sharers.remove(tbe.requestor);

  if ((is_HN == false) && (tbe.dir_sharers.count() == 0) &&
      (tbe.dataValid == false)) {
    tbe.actions.push(Event:SendEvict);
  }

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

action(Initiate_MaitainCoherence, 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) {
    if (is_HN) {
      if (tbe.dataDirty && (tbe.dataMaybeDirtyUpstream == false)) {
        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)) {
        tbe.actions.push(Event:SendWriteBackOrWriteEvict);
        tbe.actions.push(Event:WriteBEPipe);
        tbe.actions.push(Event:SendWBData);
      } else if ((tbe.dir_sharers.isEmpty() == false) && tbe.dataDirty &&
                 (tbe.dataMaybeDirtyUpstream == false)) {
        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);
  assert(tbe.dataMaybeDirtyUpstream == false);

  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.pendReqType != 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.pendReqType != 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;
        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;
      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 (is_rd_once) {
    tbe.snd_msgType := CHIDataType:CompData_I;
  } else if (tbe.dataToBeInvalid) {
    // We will drop the data so propagate it's coherent state upstream
    if (tbe.dataUnique && tbe.dataDirty) {
      tbe.snd_msgType := CHIDataType:CompData_UD_PD;
    } else if (tbe.dataUnique) {
      tbe.snd_msgType := CHIDataType:CompData_UC;
    } else if (tbe.dataDirty) {
      if (is_rd_nsd) {
        tbe.snd_msgType := CHIDataType:CompData_SC;
      } else {
        tbe.snd_msgType := CHIDataType:CompData_SD_PD;
      }
    } else {
      tbe.snd_msgType := CHIDataType:CompData_SC;
    }
  } else if (is_rd_unique ||
             (is_rd_shared && tbe.dataUnique &&
              fwd_unique_on_readshared && (tbe.dir_ownerExists == false))) {
    // propagates dirtyness
    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) {
    // still keeping a copy so can send as SC
    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));
  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);
}
