/*
 * Copyright (c) 2009 Advanced Micro Devices, Inc.
 * 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.
 *
 *
 * Authors: Brad Beckmann
 *          Tushar Krishna
 */


machine(Directory, "Network_test Directory")
:
{

  MessageBuffer requestToDir, network="From", virtual_network="0", ordered="false", vnet_type = "request";
  MessageBuffer forwardToDir, network="From", virtual_network="1", ordered="false", vnet_type = "forward";
  MessageBuffer responseToDir, network="From", virtual_network="2", ordered="false", vnet_type = "response";

  // STATES
  state_declaration(State, desc="Directory states", default="Directory_State_I") {
    // Base states
    I, AccessPermission:Invalid, desc="Invalid";
  }

  // Events
  enumeration(Event, desc="Directory events") {
    // processor requests
    Receive_Request, desc="Receive Message";
    Receive_Forward, desc="Receive Message";
    Receive_Response, desc="Receive Message";
  }

  // TYPES
  // DirectoryEntry
  structure(Entry, desc="...", interface="AbstractEntry") {
    State DirectoryState,          desc="Directory state";
    DataBlock DataBlk,             desc="data for the block";
  }

  // ** OBJECTS **
  State getState(Address addr) {
    return State:I;
  }

  void setState(Address addr, State state) {

  }

  AccessPermission getAccessPermission(Address addr) {
    return AccessPermission:NotPresent;
  }

  void setAccessPermission(Address addr, State state) {
  }

  DataBlock getDataBlock(Address addr), return_by_ref="yes" {
    error("Network Test does not support get data block.");
  }

  // ** IN_PORTS **

  in_port(requestQueue_in, RequestMsg, requestToDir) {
    if (requestQueue_in.isReady()) {
      peek(requestQueue_in, RequestMsg) {
        if (in_msg.Type == CoherenceRequestType:MSG) {
          trigger(Event:Receive_Request, in_msg.Address);
        } else {
          error("Invalid message");
        }
      }
    }
  }
  in_port(forwardQueue_in, RequestMsg, forwardToDir) {
    if (forwardQueue_in.isReady()) {
      peek(forwardQueue_in, RequestMsg) {
        if (in_msg.Type == CoherenceRequestType:MSG) {
          trigger(Event:Receive_Forward, in_msg.Address);
        } else {
          error("Invalid message");
        }
      }
    }
  }
  in_port(responseQueue_in, RequestMsg, responseToDir) {
    if (responseQueue_in.isReady()) {
      peek(responseQueue_in, RequestMsg) {
        if (in_msg.Type == CoherenceRequestType:MSG) {
          trigger(Event:Receive_Response, in_msg.Address);
        } else {
          error("Invalid message");
        }
      }
    }
  }

  // Actions

  action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
    requestQueue_in.dequeue();
  }

  action(f_popIncomingForwardQueue, "f", desc="Pop incoming forward queue") {
    forwardQueue_in.dequeue();
  }

  action(r_popIncomingResponseQueue, "r", desc="Pop incoming response queue") {
    responseQueue_in.dequeue();
  }

  // TRANSITIONS

  // The directory simply drops the received packets.
  // The goal of Network_test is only to track network stats.

  transition(I, Receive_Request) {
    i_popIncomingRequestQueue;
  }
  transition(I, Receive_Forward) {
    f_popIncomingForwardQueue;
  }
  transition(I, Receive_Response) {
    r_popIncomingResponseQueue;
  }
}
