/*
 * Copyright (c) 1999-2008 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.
 */


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, DMARequestMsg, 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, DMAResponseMsg, responseFromDir, desc="...") {
    if (dmaResponseQueue_in.isReady(clockEdge())) {
      peek( dmaResponseQueue_in, DMAResponseMsg) {
        if (in_msg.Type == DMAResponseType:ACK) {
          trigger(Event:Ack, in_msg.LineAddress, TBEs[in_msg.LineAddress]);
        } else if (in_msg.Type == DMAResponseType:DATA) {
          trigger(Event:Data, in_msg.LineAddress, TBEs[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(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, 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(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, DMAResponseMsg) {
        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;
  }

}
