// 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._

// 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 {
  (new chisel3.stage.ChiselStage).emitVerilog(new IDiv(1), args)
}
