/*
 * 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(MachineType:DMA, "DMA Controller")
: DMASequencer * dma_sequencer;
  Cycles request_latency := 6;

  MessageBuffer * responseFromDir, network="From", virtual_network="1",
        vnet_type="response";
  MessageBuffer * requestToDir, network="To", virtual_network="0",
        vnet_type="request";
  MessageBuffer * mandatoryQueue;
{
  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";
  }

  structure(TBE, desc="...") {
    State TBEState,    desc="Transient state";
    DataBlock DataBlk, desc="Data";
  }

  structure(TBETable, external = "yes") {
    TBE lookup(Addr);
    void allocate(Addr);
    void deallocate(Addr);
    bool isPresent(Addr);
  }

  void set_tbe(TBE b);
  void unset_tbe();
  void wakeUpAllBuffers();

  TBETable TBEs, template="<DMA_TBE>", constructor="m_number_of_TBEs";

  Tick clockEdge();
  MachineID mapAddressToMachine(Addr addr, MachineType mtype);

  State getState(TBE tbe, Addr addr) {
    if (is_valid(tbe)) {
        return tbe.TBEState;
    } else {
        return State:READY;
    }
  }

  void setState(TBE tbe, Addr addr, State state) {
    if (is_valid(tbe)) {
        tbe.TBEState := state;
    }
  }

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

  void setAccessPermission(Addr addr, State state) {
  }

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

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

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

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

  in_port(dmaResponseQueue_in, ResponseMsg, responseFromDir, desc="...") {
    if (dmaResponseQueue_in.isReady(clockEdge())) {
      peek( dmaResponseQueue_in, ResponseMsg) {
        if (in_msg.Type == CoherenceResponseType:ACK) {
          trigger(Event:Ack, makeLineAddress(in_msg.addr),
                  TBEs[makeLineAddress(in_msg.addr)]);
        } else if (in_msg.Type == CoherenceResponseType:DATA) {
          trigger(Event:Data, makeLineAddress(in_msg.addr),
                  TBEs[makeLineAddress(in_msg.addr)]);
        } else {
          error("Invalid response type");
        }
      }
    }
  }

  action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") {
    peek(dmaRequestQueue_in, SequencerMsg) {
      enqueue(requestToDir_out, RequestMsg, request_latency) {
        out_msg.addr := in_msg.PhysicalAddress;
        out_msg.Type := CoherenceRequestType:DMA_READ;
        out_msg.Requestor := machineID;
        out_msg.DataBlk := in_msg.DataBlk;
        out_msg.Len := in_msg.Len;
        out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
        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, RequestMsg, request_latency) {
          out_msg.addr := in_msg.PhysicalAddress;
          out_msg.Type := CoherenceRequestType:DMA_WRITE;
          out_msg.Requestor := machineID;
          out_msg.DataBlk := in_msg.DataBlk;
          out_msg.Len := in_msg.Len;
          out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
          out_msg.MessageSize := MessageSizeType:Writeback_Control;
        }
      }
  }

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

  action(d_dataCallback, "d", desc="Write data to dma sequencer") {
    dma_sequencer.dataCallback(tbe.DataBlk, address);
  }

  action(t_updateTBEData, "t", desc="Update TBE Data") {
    assert(is_valid(tbe));
    peek( dmaResponseQueue_in, ResponseMsg) {
        tbe.DataBlk := in_msg.DataBlk;
    }
  }

  action(v_allocateTBE, "v", desc="Allocate TBE entry") {
    TBEs.allocate(address);
    set_tbe(TBEs[address]);
  }

  action(w_deallocateTBE, "w", desc="Deallocate TBE entry") {
    TBEs.deallocate(address);
    unset_tbe();
  }

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

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

  action(zz_stallAndWaitRequestQueue, "zz", desc="...") {
    stall_and_wait(dmaRequestQueue_in, address);
  }

  action(wkad_wakeUpAllDependents, "wkad", desc="wake-up all dependents") {
    wakeUpAllBuffers();
  }

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

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

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

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

  transition({BUSY_RD,BUSY_WR}, {ReadRequest,WriteRequest}) {
     zz_stallAndWaitRequestQueue;
  }

}
