/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package vta.dpi

import chisel3._
import chisel3.util._
import chisel3.experimental.IntParam
import vta.util.config._
import vta.interface.axi._
import vta.shell._

/** Memory DPI parameters */
case class VTAMemDPIParams(
    dpiDelay  : Int,
    dpiLenBits: Int,
    dpiAddrBits: Int,
    dpiDataBits: Int,
    dpiTagBits: Int
) {}
case object DpiKey extends Field[VTAMemDPIParams]

/** Memory master interface.
 *
 * This interface is tipically used by the Accelerator
 */

class MemRequest(implicit val p: Parameters) extends Bundle {
  val len =   (UInt(p(ShellKey).memParams.dataBits.W))
  val addr = (UInt(p(ShellKey).memParams.addrBits.W))
  val id = (UInt(p(ShellKey).memParams.idBits.W))
}

class VTAMemDPIData(implicit val p: Parameters) extends Bundle {
  val data = UInt(p(ShellKey).memParams.dataBits.W)
  val id   = UInt(p(ShellKey).memParams.idBits.W)
}

class VTAMemDPIWrData(implicit val p: Parameters) extends Bundle {
  val data = UInt(p(ShellKey).memParams.dataBits.W)
  val strb = UInt((p(ShellKey).memParams.dataBits/8).W)
}


class VTAMemDPIMaster(implicit val p: Parameters) extends Bundle {
  val req = new Bundle {
    val ar_valid = Output(Bool())
    val ar_len =   Output(UInt(p(ShellKey).memParams.lenBits.W))
    val ar_addr = Output(UInt(p(ShellKey).memParams.addrBits.W))
    val ar_id   = Output(UInt(p(ShellKey).memParams.idBits.W))
    val aw_valid = Output(Bool())
    val aw_addr = Output(UInt(p(ShellKey).memParams.addrBits.W))
    val aw_len  = Output(UInt(p(ShellKey).memParams.lenBits.W))
  }
  val wr = ValidIO(new VTAMemDPIWrData)
  val rd = Flipped(Decoupled(new VTAMemDPIData))
}

/** Memory client interface.
 *
 * This interface is tipically used by the Host
 */
class VTAMemDPIClient(implicit val p: Parameters) extends Bundle {
  val req = new Bundle {
    val ar_valid = Input(Bool())
    val ar_len =   Input(UInt(p(ShellKey).memParams.lenBits.W))
    val ar_addr = Input(UInt(p(ShellKey).memParams.addrBits.W))
    val ar_id   = Input(UInt(p(ShellKey).memParams.idBits.W))
    val aw_valid = Input(Bool())
    val aw_addr = Input(UInt(p(ShellKey).memParams.addrBits.W))
    val aw_len  = Input(UInt(p(ShellKey).memParams.lenBits.W))
  }
  val wr = Flipped(ValidIO(new VTAMemDPIWrData))
  val rd = (Decoupled(new VTAMemDPIData))
}

/** Memory DPI module.
 *
 * Wrapper for Memory Verilog DPI module.
 */
class VTAMemDPI(implicit val p: Parameters) extends BlackBox(
  Map(
    "LEN_BITS" -> IntParam(p(ShellKey).memParams.lenBits),
    "ADDR_BITS" -> IntParam(p(ShellKey).memParams.addrBits),
    "DATA_BITS" -> IntParam(p(ShellKey).memParams.dataBits))) with HasBlackBoxResource {

  val io = IO(new Bundle {
    val clock = Input(Clock())
    val reset = Input(Reset())
    val dpi = new VTAMemDPIClient
  })
  addResource("/verilog/VTAMemDPI.v")
}

class VTAMemDPIToAXI(debug: Boolean = true)(implicit val p: Parameters) extends Module {
  val io = IO(new Bundle {
    val dpi = new VTAMemDPIMaster
    val axi = new AXIClient(p(ShellKey).memParams)
  })
  //Read request interface for sw memory manager
  val ar_valid = RegInit(false.B)
  val ar_len = RegInit(0.U.asTypeOf(chiselTypeOf(io.dpi.req.ar_len)))
  val ar_addr = RegInit(0.U.asTypeOf(chiselTypeOf(io.dpi.req.ar_addr)))
  val ar_id   = RegInit(0.U.asTypeOf(chiselTypeOf(io.dpi.req.ar_len)))
  val rd_data = RegInit(0.U.asTypeOf(chiselTypeOf(io.dpi.rd.bits.data)))
  val rIdle :: readData :: Nil = Enum(2)
  val rstate = RegInit(rIdle)
  //Write request interface for sw memomry manager
  val aw_valid = RegInit(false.B)
  val aw_len = RegInit(0.U.asTypeOf(chiselTypeOf(io.dpi.req.aw_len)))
  val aw_addr = RegInit(0.U.asTypeOf(chiselTypeOf(io.dpi.req.aw_addr)))
  val wIdle :: writeAddress :: writeData :: writeResponse :: Nil = Enum(4)
  val wstate = RegInit(wIdle)
  //Read Interface to Memory Manager
  val counter = RegInit(0.U(32.W))
  val dpiDelay = 16.U
  val dpiReqQueue = Module(new Queue(new MemRequest, 256))
  dpiReqQueue.io.enq.valid     := io.axi.ar.valid  & dpiReqQueue.io.enq.ready
  dpiReqQueue.io.enq.bits.addr := io.axi.ar.bits.addr
  dpiReqQueue.io.enq.bits.len  := io.axi.ar.bits.len
  dpiReqQueue.io.enq.bits.id   := io.axi.ar.bits.id

  when(dpiReqQueue.io.deq.valid && counter < dpiDelay){
    counter := counter + 1.U
  }.elsewhen(dpiReqQueue.io.deq.valid && counter === dpiDelay){
    counter := counter
  }.otherwise{
    counter := 0.U
  }

  switch(rstate){
    is(rIdle){
      when(dpiReqQueue.io.deq.valid && dpiReqQueue.io.deq.bits.len =/=0.U && counter === dpiDelay){
        rstate := readData
      }
    }
    is(readData) {
      when(io.axi.r.ready && io.dpi.rd.valid && ar_len === 1.U) {
        rstate := rIdle
      }
    }
  }
  when(rstate === rIdle) {
    when(dpiReqQueue.io.deq.ready){
      ar_len :=  dpiReqQueue.io.deq.bits.len
      ar_addr := dpiReqQueue.io.deq.bits.addr
      ar_id   := dpiReqQueue.io.deq.bits.id
    }
  }
  .elsewhen(rstate === readData){
    when(io.axi.r.ready && io.dpi.rd.valid && ar_len =/= 0.U){
      ar_len := ar_len - 1.U
    }
  }
dpiReqQueue.io.deq.ready :=  ((dpiReqQueue.io.deq.valid && (rstate === rIdle)) && (counter === dpiDelay))
when(rstate === rIdle && dpiReqQueue.io.deq.valid){
  io.dpi.req.ar_len  := dpiReqQueue.io.deq.bits.len
  io.dpi.req.ar_addr := dpiReqQueue.io.deq.bits.addr
  io.dpi.req.ar_id   := dpiReqQueue.io.deq.bits.id
  io.dpi.req.ar_valid := dpiReqQueue.io.deq.ready
  }.otherwise{
    io.dpi.req.ar_len  := ar_len
    io.dpi.req.ar_addr := ar_addr
    io.dpi.req.ar_id   := ar_id
    io.dpi.req.ar_valid  := (dpiReqQueue.io.deq.ready)
  }
  io.axi.ar.ready := dpiReqQueue.io.enq.ready
  io.axi.r.valid := io.dpi.rd.valid
  io.axi.r.bits.data := io.dpi.rd.bits.data
  io.axi.r.bits.last := (ar_len === 0.U && io.dpi.rd.valid)
  io.axi.r.bits.resp := 0.U
  io.axi.r.bits.user := 0.U
  io.axi.r.bits.id := io.dpi.rd.bits.id
  io.dpi.rd.ready  := io.axi.r.ready

  //Write Request
  switch(wstate){
    is(wIdle){
      when(io.axi.aw.valid){
        wstate := writeAddress
      }
    }
    is(writeAddress) {
      when(io.axi.aw.valid) {
        wstate := writeData
      }
    }
    is(writeData) {
      when(io.axi.w.valid && io.axi.w.bits.last) {
        wstate := writeResponse
      }
    }
    is(writeResponse) {
      when(io.axi.b.ready) {
        wstate := wIdle
      }
    }
  }
  when(wstate === wIdle){
    when(io.axi.aw.valid){
      aw_len := io.axi.aw.bits.len
      aw_addr := io.axi.aw.bits.addr
    }
  }
  io.dpi.req.aw_addr := aw_addr
  io.dpi.req.aw_len  := aw_len
  io.dpi.req.aw_valid := RegNext(io.axi.aw.valid) & (wstate === writeAddress)
  io.axi.aw.ready := wstate === writeAddress
  io.dpi.wr.valid := wstate === writeData & io.axi.w.valid
  io.dpi.wr.bits.data := io.axi.w.bits.data
  io.dpi.wr.bits.strb := io.axi.w.bits.strb
  io.axi.w.ready := wstate === writeData

  io.axi.b.valid := wstate === writeResponse
  io.axi.b.bits.resp := 0.U
  io.axi.b.bits.user := 0.U
  io.axi.b.bits.id := 0.U
}
