/*
 * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// CoherenceRequestType
enumeration(CoherenceRequestType, desc="...") {
  GETX,      desc="Get eXclusive";
  GETS,      desc="Get Shared";
  PUTX,      desc="Put eXclusive";
  WB_ACK,    desc="Writeback ack";
  WB_NACK,   desc="Writeback neg. ack";
  INV,       desc="Invalidation";
}

// CoherenceResponseType
enumeration(CoherenceResponseType, desc="...") {
  ACK,               desc="ACKnowledgment, responder doesn't have a copy";
  DATA,              desc="Data";
  DATA_EXCLUSIVE_CLEAN, desc="Data, no other processor has a copy, data is clean";
  DATA_EXCLUSIVE_DIRTY, desc="Data, no other processor has a copy, data is dirty";
  UNBLOCK,           desc="Unblock";
  UNBLOCK_EXCLUSIVE, desc="Unblock, we're in E/M";
  WRITEBACK_CLEAN,   desc="Clean writeback (no data)";
  WRITEBACK_DIRTY,   desc="Dirty writeback (contains data)";
  WRITEBACK,         desc="Generic writeback (contains data)";
}

// RequestMsg (and also forwarded requests)
structure(RequestMsg, desc="...", interface="Message") {
  Addr addr,             desc="Physical address for this request";
  CoherenceRequestType Type,   desc="Type of request (GetS, GetX, PutX, etc)";
  MachineID Requestor,            desc="Node who initiated the request";
  NetDest Destination,             desc="Multicast destination mask";
  DataBlock DataBlk,           desc="data for the cache line";
  MessageSizeType MessageSize, desc="size category of the message";

  bool functionalRead(Packet *pkt) {
    // Valid data block is only present in PUTX messages
    if (Type == CoherenceRequestType:PUTX) {
        return testAndRead(addr, DataBlk, pkt);
    }
    return false;
  }

  bool functionalWrite(Packet *pkt) {
    // No check on message type required since the protocol should read
    // data block from only those messages that contain valid data
    return testAndWrite(addr, DataBlk, pkt);
  }
}

// ResponseMsg (and also unblock requests)
structure(ResponseMsg, desc="...", interface="Message") {
  Addr addr,             desc="Physical address for this request";
  CoherenceResponseType Type,  desc="Type of response (Ack, Data, etc)";
  MachineID Sender,               desc="Node who sent the data";
  NetDest Destination,             desc="Node to whom the data is sent";
  DataBlock DataBlk,           desc="data for the cache line";
  bool Dirty,                  desc="Is the data dirty (different than memory)?";
  MessageSizeType MessageSize, desc="size category of the message";

  bool functionalRead(Packet *pkt) {
    // A check on message type should appear here so that only those
    // messages that contain data
    return testAndRead(addr, DataBlk, pkt);
  }

  bool functionalWrite(Packet *pkt) {
    // No check on message type required since the protocol should read
    // data block from only those messages that contain valid data
    return testAndWrite(addr, DataBlk, pkt);
  }
}

enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") {
  READ,          desc="Memory Read";
  WRITE,         desc="Memory Write";
  NULL,          desc="Invalid";
}

enumeration(DMAResponseType, desc="...", default="DMAResponseType_NULL") {
  DATA,          desc="DATA read";
  ACK,           desc="ACK write";
  NULL,          desc="Invalid";
}

structure(DMARequestMsg, desc="...", interface="Message") {
  DMARequestType Type,       desc="Request type (read/write)";
  Addr PhysicalAddress,   desc="Physical address for this request";
  Addr LineAddress,       desc="Line address for this request";
  MachineID Requestor,            desc="Node who initiated the request";
  NetDest Destination,       desc="Destination";
  DataBlock DataBlk,         desc="DataBlk attached to this request";
  int Len,                   desc="The length of the request";
  MessageSizeType MessageSize, desc="size category of the message";

  bool functionalRead(Packet *pkt) {
    return testAndRead(LineAddress, DataBlk, pkt);
  }

  bool functionalWrite(Packet *pkt) {
    return testAndWrite(LineAddress, DataBlk, pkt);
  }
}

structure(DMAResponseMsg, desc="...", interface="Message") {
  DMAResponseType Type,      desc="Response type (DATA/ACK)";
  Addr PhysicalAddress,   desc="Physical address for this request";
  Addr LineAddress,       desc="Line address for this request";
  NetDest Destination,       desc="Destination";
  DataBlock DataBlk,         desc="DataBlk attached to this request";
  MessageSizeType MessageSize, desc="size category of the message";

  bool functionalRead(Packet *pkt) {
    return testAndRead(LineAddress, DataBlk, pkt);
  }

  bool functionalWrite(Packet *pkt) {
    return testAndWrite(LineAddress, DataBlk, pkt);
  }
}
