// Copyright 2025 Google LLC
//
// Licensed 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 bus

import chisel3._
import chisel3.util._
import common.KelvinRRArbiter

import kelvin.Parameters

/**
  * Axi2TLUL: A Chisel module that serves as a bridge between an AXI4 master
  * and a TileLink-UL slave.
  *
  * This module translates AXI read and write transactions into TileLink Get and Put
  * operations, respectively. It uses a dataflow approach with queues to manage
  * the protocol conversion.
  *
  * Note: This implementation handles single-beat AXI transactions (len=0). AXI
  * bursting would require more complex logic to be added.
  *
  * @param p The Kelvin parameters.
  */
class Axi2TLUL[A_USER <: Data, D_USER <: Data](p: Parameters, userAGen: () => A_USER, userDGen: () => D_USER) extends Module {
  val tlul_p = new TLULParameters(p)
  val io = IO(new Bundle {
    val axi = Flipped(new AxiMasterIO(p.axi2AddrBits, p.axi2DataBits, p.axi2IdBits))
    val tl_a = Decoupled(new TileLink_A_ChannelBase(tlul_p, userAGen)) // TileLink Output
    val tl_d = Flipped(Decoupled(new TileLink_D_ChannelBase(tlul_p, userDGen))) // TileLink Input
  })

  assert(io.axi.read.addr.bits.len === 0.U || !io.axi.read.addr.valid, "Axi2TLUL: AXI read bursts not supported")
  assert(io.axi.write.addr.bits.len === 0.U || !io.axi.write.addr.valid, "Axi2TLUL: AXI write bursts not supported")

  val read_addr_q = Queue(io.axi.read.addr, entries = 2)
  val write_addr_q = Queue(io.axi.write.addr, entries = 2)
  val write_data_q = Queue(io.axi.write.data, entries = 2)

  private def axiToTl(addr: AxiAddress, data: Option[AxiWriteData]): TileLink_A_ChannelBase[A_USER] = {
    val tl_a = Wire(new TileLink_A_ChannelBase(tlul_p, userAGen))
    tl_a.opcode  := data.map(_ => TLULOpcodesA.PutFullData.asUInt).getOrElse(TLULOpcodesA.Get.asUInt)
    tl_a.param   := 0.U
    tl_a.address := addr.addr
    tl_a.source  := addr.id
    tl_a.size    := addr.size
    tl_a.mask    := data.map(_.strb).getOrElse(0.U(tlul_p.w.W))
    tl_a.data    := data.map(_.data).getOrElse(0.U((8 * p.axi2DataBits).W))
    tl_a.user    := 0.U.asTypeOf(io.tl_a.bits.user)
    tl_a
  }

  val read_stream = read_addr_q.map(axiToTl(_, None))

  val write_stream = Wire(Decoupled(new TileLink_A_ChannelBase(tlul_p, userAGen)))
  write_stream.valid := write_addr_q.valid && write_data_q.valid
  write_stream.bits  := axiToTl(write_addr_q.bits, Some(write_data_q.bits))

  // Reads are given higher priority.
  val arb = Module(new KelvinRRArbiter(new TileLink_A_ChannelBase(tlul_p, userAGen), 2))
  arb.io.in(0) <> read_stream
  arb.io.in(1) <> write_stream
  io.tl_a <> arb.io.out

  write_addr_q.ready := write_stream.fire
  write_data_q.ready := write_stream.fire

  val d_is_write = io.tl_d.bits.opcode === TLULOpcodesD.AccessAck.asUInt
  val d_is_read = io.tl_d.bits.opcode === TLULOpcodesD.AccessAckData.asUInt

  io.axi.write.resp.valid := io.tl_d.valid && d_is_write
  io.axi.write.resp.bits.id := io.tl_d.bits.source
  io.axi.write.resp.bits.resp := Mux(io.tl_d.bits.error, AxiResponseType.SLVERR.asUInt, AxiResponseType.OKAY.asUInt)

  io.axi.read.data.valid := io.tl_d.valid && d_is_read
  io.axi.read.data.bits.id := io.tl_d.bits.source
  io.axi.read.data.bits.data := io.tl_d.bits.data
  io.axi.read.data.bits.resp := Mux(io.tl_d.bits.error, AxiResponseType.SLVERR.asUInt, AxiResponseType.OKAY.asUInt)
  io.axi.read.data.bits.last := true.B

  io.tl_d.ready := Mux(d_is_read, io.axi.read.data.ready, io.axi.write.resp.ready)
}

import _root_.circt.stage.{ChiselStage,FirtoolOption}
import chisel3.stage.ChiselGeneratorAnnotation
import scala.annotation.nowarn

@nowarn
object EmitAxi2TLUL extends App {
  val p = Parameters()
  (new ChiselStage).execute(
    Array("--target", "systemverilog") ++ args,
    Seq(ChiselGeneratorAnnotation(() => new Axi2TLUL(p, () => new NoUser, () => new NoUser))) ++ Seq(FirtoolOption("-enable-layers=Verification"))
  )
}
