/*
 * Copyright (c) 2009-2012 Mark D. Hill and David A. Wood
 * Copyright (c) 2010-2012 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.
 */

machine(DMA, "DMA Controller") 
    : DMASequencer * dma_sequencer;
      Cycles request_latency := 6;

      MessageBuffer * responseFromDir, network="From", virtual_network="1",
            ordered="true", vnet_type="response";
      MessageBuffer * requestToDir, network="To", virtual_network="0",
            ordered="false", vnet_type="request";
{
  state_declaration(State, desc="DMA states", default="DMA_State_READY") {
    READY, AccessPermission:Invalid, desc="Ready to accept a new request";
    BUSY_RD, AccessPermission:Busy, desc="Busy: currently processing a request";
    BUSY_WR, AccessPermission:Busy, desc="Busy: currently processing a request";
  }

  enumeration(Event, desc="DMA events") {
    ReadRequest,  desc="A new read request";
    WriteRequest, desc="A new write request";
    Data,         desc="Data from a DMA memory read";
    Ack,          desc="DMA write to memory completed";
  }

  MessageBuffer mandatoryQueue, ordered="false";
  State cur_state;

  State getState(Address addr) {
    return cur_state;
  }
  void setState(Address addr, State state) {
  cur_state := state;
  }

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

  void setAccessPermission(Address addr, State state) {
  }

  void functionalRead(Address addr, Packet *pkt) {
    error("DMA does not support functional read.");
  }

  int functionalWrite(Address addr, Packet *pkt) {
    error("DMA does not support functional write.");
  }

  out_port(requestToDir_out, DMARequestMsg, requestToDir, desc="...");

  in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
    if (dmaRequestQueue_in.isReady()) {
      peek(dmaRequestQueue_in, SequencerMsg) {
        if (in_msg.Type == SequencerRequestType:LD ) {
          trigger(Event:ReadRequest, in_msg.LineAddress);
        } else if (in_msg.Type == SequencerRequestType:ST) {
          trigger(Event:WriteRequest, in_msg.LineAddress);
        } else {
          error("Invalid request type");
        }
      }
    }
  }

  in_port(dmaResponseQueue_in, DMAResponseMsg, responseFromDir, desc="...") {
    if (dmaResponseQueue_in.isReady()) {
      peek( dmaResponseQueue_in, DMAResponseMsg) {
        if (in_msg.Type == DMAResponseType:ACK) {
          trigger(Event:Ack, in_msg.LineAddress);
        } else if (in_msg.Type == DMAResponseType:DATA) {
          trigger(Event:Data, in_msg.LineAddress);
        } else {
          error("Invalid response type");
        }
      }
    }
  }

  action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") {
    peek(dmaRequestQueue_in, SequencerMsg) {
      enqueue(requestToDir_out, DMARequestMsg, request_latency) {
        out_msg.PhysicalAddress := in_msg.PhysicalAddress;
        out_msg.LineAddress := in_msg.LineAddress; 
        out_msg.Type := DMARequestType:READ;
        out_msg.Requestor := machineID;
        out_msg.DataBlk := in_msg.DataBlk;
        out_msg.Len := in_msg.Len;
        out_msg.Destination.add(map_Address_to_Directory(address));
        out_msg.MessageSize := MessageSizeType:Writeback_Control;
      }
    }
  }

  action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") {
    peek(dmaRequestQueue_in, SequencerMsg) {
      enqueue(requestToDir_out, DMARequestMsg, request_latency) {
          out_msg.PhysicalAddress := in_msg.PhysicalAddress;
          out_msg.LineAddress := in_msg.LineAddress; 
          out_msg.Type := DMARequestType:WRITE;
          out_msg.Requestor := machineID;
          out_msg.DataBlk := in_msg.DataBlk;
          out_msg.Len := in_msg.Len;
          out_msg.Destination.add(map_Address_to_Directory(address));
          out_msg.MessageSize := MessageSizeType:Writeback_Control;
        }
      }
  }

  action(a_ackCallback, "a", desc="Notify dma controller that write request completed") {
    peek (dmaResponseQueue_in, DMAResponseMsg) {
      dma_sequencer.ackCallback();
    }
  }

  action(d_dataCallback, "d", desc="Write data to dma sequencer") {
    peek (dmaResponseQueue_in, DMAResponseMsg) {
      dma_sequencer.dataCallback(in_msg.DataBlk);
    }
  }

  action(p_popRequestQueue, "p", desc="Pop request queue") {
    dmaRequestQueue_in.dequeue();
  }

  action(p_popResponseQueue, "\p", desc="Pop request queue") {
    dmaResponseQueue_in.dequeue();
  }

  transition(READY, ReadRequest, BUSY_RD) {
    s_sendReadRequest;
    p_popRequestQueue;
  }

  transition(READY, WriteRequest, BUSY_WR) {
    s_sendWriteRequest;
    p_popRequestQueue;
  }

  transition(BUSY_RD, Data, READY) {
    d_dataCallback;
    p_popResponseQueue;
  }

  transition(BUSY_WR, Ack, READY) {
    a_ackCallback;
    p_popResponseQueue;
  }
}
