// Copyright 2023 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 matcha

import chisel3._
import chisel3.util._

import bus.KelvinMemIO
import common._
import java.nio.file.{Paths, Files, StandardOpenOption}
import java.nio.charset.{StandardCharsets}
import _root_.circt.stage.ChiselStage

object Kelvin {
  def apply(p: kelvin.Parameters): Kelvin = {
    return Module(new Kelvin(p, moduleName = "Kelvin"))
  }
}

class Kelvin(p: kelvin.Parameters, moduleName: String) extends RawModule {
  override val desiredName = moduleName
  // IO ports. (RawModule removes default[clock, reset])
  val clk_i  = IO(Input(Clock()))
  val rst_ni = IO(Input(AsyncReset()))

  val mem = IO(new KelvinMemIO(p))

  val clk_freeze = IO(Input(Bool()))
  val ml_reset   = IO(Input(Bool()))
  val pc_start   = IO(Input(UInt(32.W)))
  val volt_sel   = IO(Input(Bool()))
  val debug_req  = IO(Input(Bool()))

  val finish   = IO(Output(Bool()))
  val host_req = IO(Output(Bool()))
  val fault    = IO(Output(Bool()))

  val slog = IO(new kelvin.SLogIO(p))

  // ---------------------------------------------------------------------------
  // Gated Clock.
  val cg = Module(new kelvin.ClockGate())
  cg.io.clk_i  := clk_i
  cg.io.enable := !clk_freeze
  val clk_g = cg.io.clk_o

  // ---------------------------------------------------------------------------
  // Reset inverter and synchronizer.
  //
  // Most registers in the design are loaded by literals and it is safe to use
  // rst_i directly. However some registers {fetch.instAddr} load from io ports
  // or use "reset.asBool" to initialize state which infers synchronous resets.
  // This hybrid design allows for interfaces to reset immediately on reset
  // assertion while ensuring all internal state will eventually be reset
  // correctly before usage.
  val rst_i = (!rst_ni.asBool || ml_reset).asAsyncReset
  val rst_core = Wire(Bool())

  withClockAndReset(clk_i, rst_i) {
    val rst_q1 = RegInit(true.B)
    val rst_q2 = RegInit(true.B)
    rst_q1 := false.B
    rst_q2 := rst_q1
    rst_core := rst_q2
  }

  // ---------------------------------------------------------------------------
  // Connect clock and reset.
  withClockAndReset(clk_g, rst_core.asAsyncReset) {
    assert(p.vectorBits == 256)

    val core = kelvin.Core(p)
    val l1d = kelvin.L1DCache(p)
    val l1i = kelvin.L1ICache(p)
    val bus = Axi2Sram(p)

    // -------------------------------------------------------------------------
    // Control interface.
    finish   := core.io.halted
    host_req := false.B
    fault    := core.io.fault

    // -------------------------------------------------------------------------
    // Scalar Core logging.
    slog   := core.io.slog

    // -------------------------------------------------------------------------
    // Debug Interface.
    core.io.debug_req   := debug_req

    // -------------------------------------------------------------------------
    // L1Cache.
    l1d.io.dbus     <> core.io.dbus
    l1d.io.flush    <> core.io.dflush
    l1d.io.volt_sel := volt_sel

    l1i.io.ibus     <> core.io.ibus
    l1i.io.flush    <> core.io.iflush
    l1i.io.volt_sel := volt_sel

    // -------------------------------------------------------------------------
    // Bus Mux.
    if (p.enableVector) {
      bus.io.in0.get <> core.io.axi0.get
    }
    bus.io.in1 <> core.io.axi1
    bus.io.in2 <> l1d.io.axi
    bus.io.in3.read <> l1i.io.axi.read

    // -------------------------------------------------------------------------
    // SRAM bridge.
    mem.cvalid := bus.io.out.cvalid
    bus.io.out.cready := mem.cready
    mem.cwrite := bus.io.out.cwrite
    mem.caddr  := bus.io.out.caddr
    mem.cid    := bus.io.out.cid
    mem.wdata  := bus.io.out.wdata
    mem.wmask  := bus.io.out.wmask
    bus.io.out.rvalid := mem.rvalid
    bus.io.out.rid := mem.rid
    bus.io.out.rdata := mem.rdata

    // -------------------------------------------------------------------------
    // Command interface.
    for (i <- 0 until 12) {
      core.io.csr.in.value(i) := 0.U
    }

    core.io.csr.in.value(0) := pc_start
  }
}

object EmitKelvin extends App {
  val p = new kelvin.MatchaParameters
  val core_p = new kelvin.Parameters
  var moduleName = "Kelvin"
  var chiselArgs = List[String]()
  var targetDir: Option[String] = None
  var nextIsTargetDir = false
  for (arg <- args) {
    if (nextIsTargetDir) {
      nextIsTargetDir = false
      chiselArgs = chiselArgs :+ arg
      targetDir = Some(arg)
    }
    if (arg.startsWith("--enableFetchL0")) {
      val argval = arg.split("=")(1).toBoolean
      p.enableFetchL0 = argval
      core_p.enableFetchL0 = argval
    } else if (arg.startsWith("--moduleName")) {
      moduleName = arg.split("=")(1)
    } else if (arg.startsWith("--enableVector")) {
      val argval = arg.split("=")(1).toBoolean
      p.enableVector = argval
      core_p.enableVector = argval
    } else if (arg.startsWith("--fetchDataBits")) {
      val argval = arg.split("=")(1).toInt
      p.fetchDataBits = argval
      core_p.fetchDataBits = argval
    } else if (arg.startsWith("--lsuDataBits")) {
      val argval = arg.split("=")(1).toInt
      p.lsuDataBits = argval
      core_p.lsuDataBits = argval
    } else if (arg.startsWith("--target-dir")) {
      nextIsTargetDir = true
      chiselArgs = chiselArgs :+ arg
    } else {
      chiselArgs = chiselArgs :+ arg
    }
  }
  ChiselStage.emitSystemVerilogFile(
    new Kelvin(p, moduleName), chiselArgs.toArray)
  val header_str = kelvin.EmitParametersHeader(core_p)
  targetDir match {
    case Some(targetDir) => {
      var ret = Files.write(Paths.get(targetDir + "/V" + moduleName + "_parameters.h"), header_str.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE)
      ()
    }
    case None => ()
  }
}
