Skip to content

Commit

Permalink
Merge pull request #8 from bitpasta/dev_divradix2
Browse files Browse the repository at this point in the history
Dev divradix2
  • Loading branch information
Dolu1990 authored Feb 9, 2024
2 parents 07ec79c + 5a71149 commit 491522f
Show file tree
Hide file tree
Showing 7 changed files with 462 additions and 126 deletions.
30 changes: 28 additions & 2 deletions src/main/scala/vexiiriscv/Param.scala
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class ParamSimple(){
var lsuL1Ways = 1
var withLsuBypass = false
var withIterativeShift = false
var divRadix = 2
var divImpl = ""
var divArea = true

// Debug modifiers
val debugParam = sys.env.getOrElse("VEXIIRISCV_DEBUG_PARAM", "0").toInt.toBoolean
Expand Down Expand Up @@ -117,13 +120,16 @@ class ParamSimple(){
lsuL1Sets = 64
lsuL1Ways = 4
withLsuBypass = true
divImpl = ""
divRadix = 2
divArea = true
}


def getName() : String = {
def opt(that : Boolean, v : String) = that.mux(v, "")
var isa = s"rv${xlen}i"
if (withMul) isa += "m"
if (withMul) isa += s"m"
if (withRva) isa += "a"
if (withRvc) isa += "c"
if (privParam.withSupervisor) isa += "s"
Expand All @@ -146,6 +152,7 @@ class ParamSimple(){
if (relaxedSrc) r += "rsrc"
if(performanceCounters != 0) r += s"pc$performanceCounters"
if (withIterativeShift) r += "isft"
if (withDiv) r += s"d${divRadix}${divImpl}${if(divArea)"Area" else ""}"
r.mkString("_")
}

Expand Down Expand Up @@ -183,6 +190,9 @@ class ParamSimple(){
opt[Int]("lsu-l1-ways") action { (v, c) => lsuL1Ways = v }
opt[Unit]("with-lsu-bypass") action { (v, c) => withLsuBypass = true }
opt[Unit]("with-iterative-shift") action { (v, c) => withIterativeShift = true }
opt[Int]("div-radix") action { (v, c) => divRadix = v }
opt[String]("div-impl") action { (v, c) => divImpl = v }
opt[Unit]("div-ipc") action { (v, c) => divArea = false }
}

def plugins() = pluginsArea.plugins
Expand Down Expand Up @@ -420,7 +430,23 @@ class ParamSimple(){
}
if(withDiv) {
plugins += new RsUnsignedPlugin("lane0")
plugins += new DivPlugin(early0)
plugins += new DivPlugin(
layer = early0,
radix = divRadix,
impl = {
def pasta(width: Int, radix: Int, area : Boolean) = new DivRadix2(width, lowArea = area)
def vexii(width: Int, radix: Int, area: Boolean) = new DivRadix(width, radix)
def default(width: Int, radix: Int, area: Boolean) = radix match {
case 2 if area => pasta(width, radix, area)
case 4 => vexii(width, radix, area)
}
divImpl match {
case "" => default
case "bitpasta" => pasta
case "vexii" => vexii
}
}
)
}

plugins += new CsrRamPlugin()
Expand Down
9 changes: 6 additions & 3 deletions src/main/scala/vexiiriscv/execute/DivPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import spinal.core._
import spinal.lib._
import spinal.lib.misc.pipeline._
import vexiiriscv.execute.RsUnsignedPlugin._
import vexiiriscv.misc.{AdderAggregator, DivRadix4, MulSpliter}
import vexiiriscv.misc.{AdderAggregator, DivComp, DivRadix2, DivRadix, MulSpliter}
import vexiiriscv.riscv.Riscv._
import vexiiriscv.riscv._

Expand All @@ -18,8 +18,11 @@ object DivPlugin extends AreaObject {
}

class DivPlugin(val layer : LaneLayer,
var impl : (Int, Int, Boolean) => DivComp,
var divAt: Int = 0,
val writebackAt : Int = 0) extends ExecutionUnitElementSimple(layer){
var writebackAt : Int = 0,
var radix: Int = 2,
var area: Boolean = true) extends ExecutionUnitElementSimple(layer){
import DivPlugin._

val logic = during setup new Logic {
Expand Down Expand Up @@ -51,7 +54,7 @@ class DivPlugin(val layer : LaneLayer,
uopRetainer.release()

val processing = new el.Execute(divAt) {
val div = DivRadix4(width = XLEN.get)
val div = impl(Riscv.XLEN, radix, area)

DIV_REVERT_RESULT := (RS1_REVERT ^ (RS2_REVERT && !REM)) && !(RS2_FORMATED === 0 && RS2_SIGNED && !REM) //RS2_SIGNED == RS1_SIGNED anyway

Expand Down
133 changes: 133 additions & 0 deletions src/main/scala/vexiiriscv/misc/DivRadix.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// SPDX-FileCopyrightText: 2023 "Everybody"
//
// SPDX-License-Identifier: MIT

package vexiiriscv.misc

import spinal.core._
import spinal.lib._

case class DivCmd(width : Int) extends Bundle{
val a,b = UInt(width bits)
}

case class DivRsp(width : Int) extends Bundle{
val result = UInt(width bits)
val remain = UInt(width bits)
}

case class DivIo(width : Int) extends Bundle{
val flush = in Bool()
val cmd = slave Stream (DivCmd(width))
val rsp = master Stream (DivRsp(width))
}

class DivComp(val width : Int) extends Component{
val io = DivIo(width)
}

class DivRadix(width : Int, radix : Int) extends DivComp(width) {
val radixBits = radix match {
case 2 => 1
case 4 => 2
}
assert(width % radixBits == 0)

val iterations = width/radixBits
val counter = Reg(UInt(log2Up(iterations) bits))
val busy = RegInit(False) clearWhen(io.rsp.fire)
val done = RegInit(False) setWhen(busy && counter === iterations-1) clearWhen(io.rsp.fire)

val shifter = Reg(UInt(width bits))
val numerator = Reg(UInt(width bits))
val result = Reg(UInt(width bits))

val div1, div3 = Reg(UInt(width+radixBits bits))
val div2 = div1 |<< 1

val shifted = shifter @@ numerator.takeHigh(radixBits).asUInt
val sub1 = shifted -^ div1
val sub2 = (radix >= 4) generate shifted -^ div2
val sub3 = (radix >= 4) generate shifted -^ div3

io.rsp.valid := done
io.rsp.result := result.resized
io.rsp.remain := shifter.resized
io.cmd.ready := !busy

when(!done){
counter := counter + 1
val sel = CombInit(shifted)
result := result |<< radixBits
when(!sub1.msb){
sel := sub1.resized
result(radixBits-1 downto 0) := 1
}
if(radix >= 4) {
when(!sub2.msb) {
sel := sub2.resized
result(radixBits-1 downto 0) := 2
}
when(!sub3.msb) {
sel := sub3.resized
result(radixBits-1 downto 0) := 3
}
}
shifter := sel.resized
numerator := numerator |<< radixBits
}

val sliceCount = 3
val shiftWidth = width/(sliceCount+1)
val slices = io.cmd.a.subdivideIn(sliceCount+1 slices).tail
val slicesZero = slices.map(_ === 0)
val shiftSel = B((0 until sliceCount).map(i => slicesZero.drop(i).andR))
val sel = OHToUInt(OHMasking.firstV2(True ## shiftSel))
when(!busy){
busy := io.cmd.valid
div1 := io.cmd.b.resized
if(radix >= 4) div3 := io.cmd.b +^ (io.cmd.b << 1)
result := (default -> (io.cmd.b === 0))
switch(sel) {
for (i <- sliceCount downto 0) is(i) {
val shift = width - ((i + 1) * shiftWidth)
counter := shift / radixBits
shifter := U(io.cmd.a.takeHigh(shift)).resized
numerator := io.cmd.a |<< shift
}
}
}

when(io.flush){
done := False
busy := False
}
}


object DivRadix4Tester extends App{
import spinal.core.sim._

for(radix <- List(2, 4)){
SimConfig.compile(new DivRadix(16, radix)).doSim(seed = 52){ dut =>
dut.clockDomain.forkStimulus(10)
dut.io.cmd.valid #= false
dut.io.rsp.ready #= true
dut.clockDomain.waitSampling()
for (i <- 0 until 100000) {
dut.io.cmd.valid #= true
val a = dut.io.cmd.a.randomizedInt()
val b = dut.io.cmd.b.randomizedInt()
dut.io.cmd.a #= a
dut.io.cmd.b #= b
dut.clockDomain.waitSampling()
dut.io.cmd.valid #= false
dut.clockDomain.waitSamplingWhere(dut.io.rsp.valid.toBoolean)
assert(dut.io.rsp.result.toInt == a / b)
assert(dut.io.rsp.remain.toInt == a % b)
dut.clockDomain.waitSampling()
}
simSuccess()
}
}
}
Loading

0 comments on commit 491522f

Please sign in to comment.