MulPlugin.outputBuffer feature added
This commit is contained in:
parent
3b99090879
commit
fe690528f7
|
@ -5,7 +5,8 @@ import spinal.core._
|
||||||
import spinal.lib.KeepAttribute
|
import spinal.lib.KeepAttribute
|
||||||
|
|
||||||
//Input buffer generaly avoid the FPGA synthesis to duplicate reg inside the DSP cell, which could stress timings quite much.
|
//Input buffer generaly avoid the FPGA synthesis to duplicate reg inside the DSP cell, which could stress timings quite much.
|
||||||
class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv]{
|
class MulPlugin(var inputBuffer : Boolean = false,
|
||||||
|
var outputBuffer : Boolean = false) extends Plugin[VexRiscv]{
|
||||||
object MUL_LL extends Stageable(UInt(32 bits))
|
object MUL_LL extends Stageable(UInt(32 bits))
|
||||||
object MUL_LH extends Stageable(SInt(34 bits))
|
object MUL_LH extends Stageable(SInt(34 bits))
|
||||||
object MUL_HL extends Stageable(SInt(34 bits))
|
object MUL_HL extends Stageable(SInt(34 bits))
|
||||||
|
@ -53,16 +54,26 @@ class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv]{
|
||||||
// a := input(SRC1)
|
// a := input(SRC1)
|
||||||
// b := input(SRC2)
|
// b := input(SRC2)
|
||||||
|
|
||||||
|
val delay = (if(inputBuffer) 1 else 0) + (if(outputBuffer) 1 else 0)
|
||||||
|
|
||||||
|
val delayLogic = (delay != 0) generate new Area{
|
||||||
|
val counter = Reg(UInt(log2Up(delay+1) bits))
|
||||||
|
when(arbitration.isValid && input(IS_MUL) && counter =/= delay){
|
||||||
|
arbitration.haltItself := True
|
||||||
|
}
|
||||||
|
when(!arbitration.isStuckByOthers){
|
||||||
|
counter := counter + 1
|
||||||
|
}
|
||||||
|
when(!arbitration.isStuck){
|
||||||
|
counter := 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val withInputBuffer = inputBuffer generate new Area{
|
val withInputBuffer = inputBuffer generate new Area{
|
||||||
val rs1 = RegNext(input(RS1))
|
val rs1 = RegNext(input(RS1))
|
||||||
val rs2 = RegNext(input(RS2))
|
val rs2 = RegNext(input(RS2))
|
||||||
a := rs1
|
a := rs1
|
||||||
b := rs2
|
b := rs2
|
||||||
|
|
||||||
val delay = RegNext(arbitration.isStuck)
|
|
||||||
when(arbitration.isValid && input(IS_MUL) && !delay){
|
|
||||||
arbitration.haltItself := True
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val noInputBuffer = (!inputBuffer) generate new Area{
|
val noInputBuffer = (!inputBuffer) generate new Area{
|
||||||
|
@ -91,10 +102,25 @@ class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv]{
|
||||||
val bSLow = (False ## b(15 downto 0)).asSInt
|
val bSLow = (False ## b(15 downto 0)).asSInt
|
||||||
val aHigh = (((aSigned && a.msb) ## a(31 downto 16))).asSInt
|
val aHigh = (((aSigned && a.msb) ## a(31 downto 16))).asSInt
|
||||||
val bHigh = (((bSigned && b.msb) ## b(31 downto 16))).asSInt
|
val bHigh = (((bSigned && b.msb) ## b(31 downto 16))).asSInt
|
||||||
insert(MUL_LL) := aULow * bULow
|
|
||||||
insert(MUL_LH) := aSLow * bHigh
|
val withOuputBuffer = outputBuffer generate new Area{
|
||||||
insert(MUL_HL) := aHigh * bSLow
|
val mul_ll = RegNext(aULow * bULow)
|
||||||
insert(MUL_HH) := aHigh * bHigh
|
val mul_lh = RegNext(aSLow * bHigh)
|
||||||
|
val mul_hl = RegNext(aHigh * bSLow)
|
||||||
|
val mul_hh = RegNext(aHigh * bHigh)
|
||||||
|
|
||||||
|
insert(MUL_LL) := mul_ll
|
||||||
|
insert(MUL_LH) := mul_lh
|
||||||
|
insert(MUL_HL) := mul_hl
|
||||||
|
insert(MUL_HH) := mul_hh
|
||||||
|
}
|
||||||
|
|
||||||
|
val noOutputBuffer = (!outputBuffer) generate new Area{
|
||||||
|
insert(MUL_LL) := aULow * bULow
|
||||||
|
insert(MUL_LH) := aSLow * bHigh
|
||||||
|
insert(MUL_HL) := aHigh * bSLow
|
||||||
|
insert(MUL_HH) := aHigh * bHigh
|
||||||
|
}
|
||||||
|
|
||||||
Component.current.afterElaboration{
|
Component.current.afterElaboration{
|
||||||
//Avoid synthesis tools to retime RS1 RS2 from execute stage to decode stage leading to bad timings (ex : Vivado, even if retiming is disabled)
|
//Avoid synthesis tools to retime RS1 RS2 from execute stage to decode stage leading to bad timings (ex : Vivado, even if retiming is disabled)
|
||||||
|
|
|
@ -173,19 +173,26 @@ class MulDivDimension extends VexRiscvDimension("MulDiv") {
|
||||||
} :: l
|
} :: l
|
||||||
|
|
||||||
|
|
||||||
if(!noMemory && !noWriteBack) l =
|
if(!noMemory && !noWriteBack) {
|
||||||
new VexRiscvPosition("MulDivFpga") {
|
val inputBuffer = r.nextBoolean()
|
||||||
override def testParam = "MUL=yes DIV=yes"
|
val outputBuffer = r.nextBoolean()
|
||||||
override def applyOn(config: VexRiscvConfig): Unit = {
|
l = new VexRiscvPosition(s"MulDivFpga$inputBuffer$outputBuffer") {
|
||||||
config.plugins += new MulPlugin
|
override def testParam = "MUL=yes DIV=yes"
|
||||||
config.plugins += new MulDivIterativePlugin(
|
|
||||||
genMul = false,
|
override def applyOn(config: VexRiscvConfig): Unit = {
|
||||||
genDiv = true,
|
config.plugins += new MulPlugin(
|
||||||
mulUnrollFactor = 32,
|
inputBuffer = inputBuffer,
|
||||||
divUnrollFactor = 1
|
outputBuffer = outputBuffer
|
||||||
)
|
)
|
||||||
}
|
config.plugins += new MulDivIterativePlugin(
|
||||||
} :: l
|
genMul = false,
|
||||||
|
genDiv = true,
|
||||||
|
mulUnrollFactor = 32,
|
||||||
|
divUnrollFactor = 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} :: l
|
||||||
|
}
|
||||||
|
|
||||||
random(r, l)
|
random(r, l)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue