// 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 common

import chisel3._
import chisel3.util._
import common._
import _root_.circt.stage.ChiselStage

// An integer divide unit, to be fused with fdiv.

object IDiv {
  def apply(n: Int): IDiv = {
    return Module(new IDiv(n))
  }

  val Stages = 4
  val Rcnt = 32 / Stages
}

case class IDivOp() {
  val DIV  = 0
  val DIVU = 1
  val REM  = 2
  val REMU = 3
  val Entries = 4
}

class IDiv(n: Int) extends Module {
  val io = IO(new Bundle {
    val req = Input(UInt(new IDivOp().Entries.W))
    val ina = Flipped(Decoupled(Vec(n, UInt(32.W))))
    val inb = Flipped(Decoupled(Vec(n, UInt(32.W))))
    val out = Decoupled(Vec(n, UInt(32.W)))
  })

  val dvu = new IDivOp()

  val active = RegInit(false.B)
  val result = RegInit(false.B)
  val count = Reg(UInt(6.W))

  val state = Reg(Vec(n, new IDivState()))

  val ivalid = io.ina.valid && io.ina.ready && io.inb.valid && io.inb.ready
  val ovalid = io.out.valid && io.out.ready

  when (ivalid) {
    active := true.B
  } .elsewhen (active && count === IDiv.Rcnt.U) {
    active := false.B
  }

  when (ovalid) {
    result := false.B
  } .elsewhen (active && count === IDiv.Rcnt.U) {
    result := true.B
  }

  when (ivalid) {
    count := 0.U
  } .elsewhen (active) {
    count := count + 1.U
  }

  for (i <- 0 until n) {
    val ina = io.ina.bits(i)
    val inb = io.inb.bits(i)
    val st = state(i)

    when (ivalid) {
      val divide = io.req(dvu.DIV) || io.req(dvu.DIVU)
      val signed = io.req(dvu.DIV) || io.req(dvu.REM)
      state(i) := IDivComb1(ina, inb, signed, divide)
    } .elsewhen (active) {
      state(i) := IDivComb2(state(i), count)
    }
  }

  io.ina.ready := io.inb.valid && !active && (!result || io.out.ready)
  io.inb.ready := io.ina.valid && !active && (!result || io.out.ready)

  io.out.valid := result

  for (i <- 0 until n) {
    io.out.bits(i) := IDivComb3(state(i))
  }
}

class IDivState extends Bundle {
  val denom = UInt(32.W)  // output is placed first
  val divide = UInt(32.W)
  val remain = UInt(32.W)
  val opdiv = Bool()
  val opneg = Bool()
}

object IDivComb1 {
  def apply(ina: UInt, inb: UInt, signed: Bool, divide: Bool): IDivState = {
    val out = Wire(new IDivState())

    val divByZero = inb === 0.U
    val divsign = signed && (ina(31) =/= inb(31)) && !divByZero
    val remsign = signed && ina(31)
    val inp = Mux(signed && ina(31), ~ina + 1.U, ina)

    out.opdiv := divide
    out.opneg := Mux(divide, divsign, remsign)
    out.denom := Mux(signed && inb(31), ~inb + 1.U, inb)
    out.divide := inp
    out.remain := 0.U

    out
  }
}

object IDivComb2 {
  def apply(in: IDivState, count: UInt): IDivState = {
    val out = Wire(new IDivState())
    out := in

    when (count < IDiv.Rcnt.U) {
      val (div1, rem1) = Divide(in.divide, in.remain, in.denom)
      if (IDiv.Stages == 1) {
        out.divide := div1
        out.remain := rem1
      } else if (IDiv.Stages == 2) {
        val (div2, rem2) = Divide(div1, rem1, in.denom)
        out.divide := div2
        out.remain := rem2
      } else if (IDiv.Stages == 4) {
        val (div2, rem2) = Divide(div1, rem1, in.denom)
        val (div3, rem3) = Divide(div2, rem2, in.denom)
        val (div4, rem4) = Divide(div3, rem3, in.denom)
        out.divide := div4
        out.remain := rem4
      } else {
        assert(false)
      }
    } .otherwise {
      val div = Mux(in.opneg, ~in.divide + 1.U, in.divide)
      val rem = Mux(in.opneg, ~in.remain + 1.U, in.remain)
      out.denom := Mux(in.opdiv, div, rem)
    }

    out
  }

  def Divide(prvDivide: UInt, prvRemain: UInt, denom: UInt): (UInt, UInt) = {
    val shfRemain = Cat(prvRemain(30,0), prvDivide(31))
    val subtract = shfRemain -& denom
    assert(subtract.getWidth == 33)
    val divDivide = Wire(UInt(32.W))
    val divRemain = Wire(UInt(32.W))

    when (!subtract(32)) {
      divDivide := Cat(prvDivide(30,0), 1.U(1.W))
      divRemain := subtract(31,0)
    } .otherwise {
      divDivide := Cat(prvDivide(30,0), 0.U(1.W))
      divRemain := shfRemain
    }

    (divDivide, divRemain)
  }
}

object IDivComb3 {
  def apply(in: IDivState): UInt = {
    val result = in.denom
    assert(result.getWidth == 32)
    result
  }
}

object EmitIDiv extends App {
  ChiselStage.emitSystemVerilogFile(new IDiv(1), args)
}
