/*
 * 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="NetworkMessage") {
  Address 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="NetworkMessage") {
  Address 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="NetworkMessage") {
  DMARequestType Type,       desc="Request type (read/write)";
  Address PhysicalAddress,   desc="Physical address for this request";
  Address 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="NetworkMessage") {
  DMAResponseType Type,      desc="Response type (DATA/ACK)";
  Address PhysicalAddress,   desc="Physical address for this request";
  Address 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);
  }
}
