fpu integration wip, got mandelbrot to work in linux with no inline (crash when inlined)

This commit is contained in:
Dolu1990 2021-02-19 11:26:28 +01:00
parent 8537d18b16
commit e504afbf18
7 changed files with 75 additions and 31 deletions

View File

@ -33,7 +33,7 @@ import vexriscv.ip.fpu.FpuParameter
object TestsWorkspace {
def main(args: Array[String]) {
SpinalConfig().generateVerilog {
// make clean all REDO=10 CSR=no MMU=no COREMARK=no RVF=no REDO=1 DBUS_LOAD_DATA_WIDTH=64 DBUS_STORE_DATA_WIDTH=64 DEBUG=ye TRACE=ye
// make clean all REDO=10 CSR=no MMU=no COREMARK=no RVF=yes RVD=yes REDO=1 DBUS_LOAD_DATA_WIDTH=64 DBUS_STORE_DATA_WIDTH=64 DEBUG=ye TRACE=ye
val config = VexRiscvConfig(
plugins = List(
new IBusCachedPlugin(

View File

@ -15,12 +15,13 @@ import spinal.lib.generator.Handle
import spinal.lib.misc.plic.PlicMapping
import spinal.lib.system.debugger.SystemDebuggerConfig
import vexriscv.ip.{DataCacheAck, DataCacheConfig, DataCacheMemBus, InstructionCache, InstructionCacheConfig}
import vexriscv.plugin.{BranchPlugin, CsrAccess, CsrPlugin, CsrPluginConfig, DBusCachedPlugin, DBusSimplePlugin, DYNAMIC_TARGET, DebugPlugin, DecoderSimplePlugin, FullBarrelShifterPlugin, HazardSimplePlugin, IBusCachedPlugin, IBusSimplePlugin, IntAluPlugin, MmuPlugin, MmuPortConfig, MulDivIterativePlugin, MulPlugin, RegFilePlugin, STATIC, SrcPlugin, StaticMemoryTranslatorPlugin, YamlPlugin}
import vexriscv.plugin.{BranchPlugin, CsrAccess, CsrPlugin, CsrPluginConfig, DBusCachedPlugin, DBusSimplePlugin, DYNAMIC_TARGET, DebugPlugin, DecoderSimplePlugin, FpuPlugin, FullBarrelShifterPlugin, HazardSimplePlugin, IBusCachedPlugin, IBusSimplePlugin, IntAluPlugin, MmuPlugin, MmuPortConfig, MulDivIterativePlugin, MulPlugin, RegFilePlugin, STATIC, SrcPlugin, StaticMemoryTranslatorPlugin, YamlPlugin}
import vexriscv.{Riscv, VexRiscv, VexRiscvBmbGenerator, VexRiscvConfig, plugin}
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import spinal.lib.generator._
import vexriscv.ip.fpu.FpuParameter
case class VexRiscvSmpClusterParameter(cpuConfigs : Seq[VexRiscvConfig], withExclusiveAndInvalidation : Boolean, forcePeripheralWidth : Boolean = true, outOfOrderDecoder : Boolean = true)
@ -163,10 +164,15 @@ object VexRiscvSmpClusterGen {
earlyBranch : Boolean = false,
dBusCmdMasterPipe : Boolean = false,
withMmu : Boolean = true,
withSupervisor : Boolean = true
withSupervisor : Boolean = true,
withFloat : Boolean = false,
withDouble : Boolean = false,
externalFpu : Boolean = true
) = {
assert(iCacheSize/iCacheWays <= 4096, "Instruction cache ways can't be bigger than 4096 bytes")
assert(dCacheSize/dCacheWays <= 4096, "Data cache ways can't be bigger than 4096 bytes")
assert(!(withDouble && !withFloat))
val config = VexRiscvConfig(
plugins = List(
if(withMmu)new MmuPlugin(
@ -262,7 +268,7 @@ object VexRiscvSmpClusterGen {
mulUnrollFactor = 32,
divUnrollFactor = 1
),
new CsrPlugin(CsrPluginConfig.openSbi(mhartid = hartId, misa = Riscv.misaToInt("imas")).copy(utimeAccess = CsrAccess.READ_ONLY)),
new CsrPlugin(CsrPluginConfig.openSbi(mhartid = hartId, misa = Riscv.misaToInt(s"ima${if(withFloat) "f" else ""}${if(withDouble) "d" else ""}s")).copy(utimeAccess = CsrAccess.READ_ONLY)),
new BranchPlugin(
earlyBranch = earlyBranch,
catchAddressMisaligned = true,
@ -271,6 +277,11 @@ object VexRiscvSmpClusterGen {
new YamlPlugin(s"cpu$hartId.yaml")
)
)
if(withFloat) config.plugins += new FpuPlugin(
externalFpu = true,
p = FpuParameter(withDouble = withDouble)
)
config
}

View File

@ -675,7 +675,7 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam
val rspSync = True
val rspLast = True
val memCmdSent = RegInit(False) setWhen (io.mem.cmd.ready) clearWhen (!io.cpu.writeBack.isStuck)
val memCmdSent = RegInit(False) setWhen (io.mem.cmd.fire) clearWhen (!io.cpu.writeBack.isStuck)
val pending = withExclusive generate new Area{
val counter = Reg(UInt(log2Up(pendingMax) + 1 bits)) init(0)
val counterNext = counter + U(io.mem.cmd.fire && io.mem.cmd.last) - ((io.mem.rsp.valid && io.mem.rsp.last) ? (io.mem.rsp.aggregated +^ 1) | 0)

View File

@ -207,7 +207,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
arbiterOutput.source := arbiter.io.chosen
arbiterOutput.payload.assignSomeByName(arbiter.io.output.payload)
val s0 = arbiterOutput.pipelined(m2s = true, s2m = true)
val s0 = arbiterOutput.pipelined(m2s = true, s2m = true) //TODO may need to remove m2s for store latency
val useRs1, useRs2, useRs3, useRd = False
switch(s0.opcode){
is(p.Opcode.LOAD) { useRd := True }
@ -287,28 +287,28 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
}
val decode = new Area{
val input = read.output.combStage()
val input = read.output/*.s2mPipe()*/.combStage()
input.ready := False
val loadHit = List(FpuOpcode.LOAD, FpuOpcode.FMV_W_X, FpuOpcode.I2F).map(input.opcode === _).orR
val load = Stream(LoadInput())
load.valid := input.valid && loadHit
input.ready setWhen(loadHit && load.ready)
load.payload.assignSomeByName(read.output.payload)
load.payload.assignSomeByName(input.payload)
load.i2f := input.opcode === FpuOpcode.I2F
val shortPipHit = List(FpuOpcode.STORE, FpuOpcode.F2I, FpuOpcode.CMP, FpuOpcode.MIN_MAX, FpuOpcode.SGNJ, FpuOpcode.FMV_X_W, FpuOpcode.FCLASS, FpuOpcode.FCVT_X_X).map(input.opcode === _).orR
val shortPip = Stream(ShortPipInput())
input.ready setWhen(shortPipHit && shortPip.ready)
shortPip.valid := input.valid && shortPipHit
shortPip.payload.assignSomeByName(read.output.payload)
shortPip.payload.assignSomeByName(input.payload)
val divSqrtHit = input.opcode === p.Opcode.DIV || input.opcode === p.Opcode.SQRT
val divSqrt = Stream(DivSqrtInput())
if(p.withDivSqrt) {
input.ready setWhen (divSqrtHit && divSqrt.ready)
divSqrt.valid := input.valid && divSqrtHit
divSqrt.payload.assignSomeByName(read.output.payload)
divSqrt.payload.assignSomeByName(input.payload)
divSqrt.div := input.opcode === p.Opcode.DIV
}
@ -324,15 +324,15 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
divSqrtToMul.ready := mul.ready
mul.payload := divSqrtToMul.payload
when(!divSqrtToMul.valid) {
mul.payload.assignSomeByName(read.output.payload)
mul.payload.assignSomeByName(input.payload)
mul.add := fmaHit
mul.divSqrt := False
mul.msb1 := True
mul.msb2 := True
mul.rs2.sign.allowOverride();
mul.rs2.sign := read.output.rs2.sign ^ input.arg(0)
mul.rs2.sign := input.rs2.sign ^ input.arg(0)
mul.rs3.sign.allowOverride();
mul.rs3.sign := read.output.rs3.sign ^ input.arg(1)
mul.rs3.sign := input.rs3.sign ^ input.arg(1)
}
}
@ -348,9 +348,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
mulToAdd.ready := add.ready
add.payload := mulToAdd.payload
when(!mulToAdd.valid) {
add.payload.assignSomeByName(read.output.payload)
add.payload.assignSomeByName(input.payload)
add.rs2.sign.allowOverride;
add.rs2.sign := read.output.rs2.sign ^ input.arg(0)
add.rs2.sign := input.rs2.sign ^ input.arg(0)
}
}
}
@ -578,7 +578,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val input = UInt(p.internalMantissaSize+1 max 33 bits).assignDontCare()
var logic = input
val scrap = Reg(Bool)
for(i <- by.range){
for(i <- by.range.reverse){
scrap setWhen(by(i) && logic(0, 1 << i bits) =/= 0)
logic \= by(i) ? (logic |>> (BigInt(1) << i)) | logic
}
@ -809,11 +809,13 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
List(FpuOpcode.CMP, FpuOpcode.MIN_MAX).map(input.opcode === _).orR && rs2NanNv
flag.NV setWhen(input.valid && nv)
input.ready := !halt && (toFpuRf ? rfOutput.ready | io.port.map(_.rsp.ready).read(input.source))
val rspStreams = Vec(Stream(FpuRsp(p)), portCount)
input.ready := !halt && (toFpuRf ? rfOutput.ready | rspStreams.map(_.ready).read(input.source))
for(i <- 0 until portCount){
def rsp = io.port(i).rsp
def rsp = rspStreams(i)
rsp.valid := input.valid && input.source === i && !toFpuRf && !halt
rsp.value := result
io.port(i).rsp << rsp.stage()
completion(i).increments += (RegNext(rsp.fire) init(False))
}
}
@ -940,7 +942,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
}
val divSqrt = p.withDivSqrt generate new Area {
val input = decode.divSqrt.stage()
val input = decode.divSqrt.halfPipe()
val aproxWidth = 8
val aproxDepth = 64
@ -1142,7 +1144,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val rs1ExponentEqual = input.rs1.exponent === input.rs2.exponent
val rs1MantissaBigger = input.rs1.mantissa > input.rs2.mantissa
val absRs1Bigger = ((rs1ExponentBigger || rs1ExponentEqual && rs1MantissaBigger) && !input.rs1.isZero || input.rs1.isInfinity) && !input.rs2.isInfinity
val shiftBy = rs1ExponentBigger ? (0-exp21) | exp21
val shiftBy = exp21.asSInt.abs//rs1ExponentBigger ? (0-exp21) | exp21
val shiftOverflow = (shiftBy >= p.internalMantissaSize+3)
val passThrough = shiftOverflow || (input.rs1.isZero) || (input.rs2.isZero)
@ -1153,8 +1155,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val xMantissa = U"1" @@ (rs1ExponentBigger ? input.rs1.mantissa | input.rs2.mantissa) @@ U"00"
val yMantissaUnshifted = U"1" @@ (rs1ExponentBigger ? input.rs2.mantissa | input.rs1.mantissa) @@ U"00"
var yMantissa = CombInit(yMantissaUnshifted)
val roundingScrap = CombInit(shiftOverflow)
for(i <- 0 until log2Up(p.internalMantissaSize)){
val roundingScrap = False
for(i <- log2Up(p.internalMantissaSize) - 1 downto 0){
roundingScrap setWhen(shiftBy(i) && yMantissa(0, 1 << i bits) =/= 0)
yMantissa \= shiftBy(i) ? (yMantissa |>> (BigInt(1) << i)) | yMantissa
}
@ -1181,6 +1183,25 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val xSigned = xMantissa.twoComplement(xSign) //TODO Is that necessary ?
val ySigned = ((ySign ## Mux(ySign, ~yMantissa, yMantissa)).asUInt + (ySign && !roundingScrap).asUInt).asSInt //rounding here
output.xyMantissa := U(xSigned +^ ySigned).trim(1 bits)
}
class OhOutput extends MathOutput{
// val shiftOh = Vec(Bool, p.internalMantissaSize+4)
val shift = UInt(log2Up(p.internalMantissaSize+4) bits)
}
val oh = new Area {
val input = math.output.stage()
val output = input.swapPayload(new OhOutput)
output.payload.assignSomeByName(input.payload)
import input.payload._
val shiftOh = OHMasking.first(output.xyMantissa.asBools.reverse) //The OhMasking.first can be processed in parallel to the xyMantissa carry chaine
// output.shiftOh := shiftOh
val shift = OHToUInt(shiftOh)
output.shift := shift
}
@ -1193,13 +1214,11 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
}
val norm = new Area{
val input = math.output.stage()
val input = oh.output.stage()
val output = input.swapPayload(new NormOutput)
output.payload.assignSomeByName(input.payload)
import input.payload._
val shiftOh = OHMasking.first(xyMantissa.asBools.reverse)
val shift = OHToUInt(shiftOh)
output.mantissa := (xyMantissa |<< shift)
output.exponent := xyExponent -^ shift + 1
output.forceInfinity := (input.rs1.isInfinity || input.rs2.isInfinity)
@ -1210,7 +1229,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
}
val result = new Area {
val input = norm.output.stage()
val input = norm.output.pipelined()
val output = input.swapPayload(new MergeInput())
import input.payload._
@ -1251,7 +1270,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
inputs += load.s1.output.stage()
if(p.withAdd) (inputs += add.result.output)
if(p.withMul) (inputs += mul.result.output)
if(p.withShortPipMisc) (inputs += shortPip.rfOutput)
if(p.withShortPipMisc) (inputs += shortPip.rfOutput.pipelined(m2s = true))
val arbitrated = StreamArbiterFactory.lowerFirst.noLock.on(inputs)
val isCommited = rf.lock.map(_.commited).read(arbitrated.lockId)
val commited = arbitrated.haltWhen(!isCommited).toFlow
@ -1301,7 +1320,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val mantissaRange = p.internalMantissaSize downto 1
val adderMantissa = input.value.mantissa(mantissaRange) & (mantissaIncrement ? ~(exactMask.trim(1) >> 1) | input.value.mantissa(mantissaRange).maxValue)
val adderRightOp = (mantissaIncrement ? (exactMask >> 1)| U(0)).resize(p.internalMantissaSize bits)
val adder = (input.value.exponent @@ adderMantissa) + adderRightOp + U(mantissaIncrement)
val adder = KeepAttribute(KeepAttribute(input.value.exponent @@ adderMantissa) + KeepAttribute(adderRightOp) + KeepAttribute(U(mantissaIncrement)))
math.special := input.value.special
math.sign := input.value.sign
math.exponent := adder(p.internalMantissaSize, p.internalExponentSize bits)

View File

@ -138,6 +138,12 @@ case class FpuFlags() extends Bundle{
case class FpuCompletion() extends Bundle{
val flag = FpuFlags()
val count = UInt(2 bits)
def stage() = {
val ret = FpuCompletion().setCompositeName(this, "stage", true)
ret := this
ret
}
}
case class FpuCmd(p : FpuParameter) extends Bundle{

View File

@ -72,6 +72,9 @@ class DBusCachedPlugin(val config : DataCacheConfig,
MEMORY_WR -> False
) ++ (if(catchSomething) List(HAS_SIDE_EFFECT -> True) else Nil)
)
if(withLrSc) decoderService.add(key, Seq(MEMORY_LRSC -> False))
if(withAmo) decoderService.add(key, Seq(MEMORY_AMO -> False))
}
override def addStoreWordEncoding(key : MaskedLiteral): Unit = {
val decoderService = pipeline.service(classOf[DecoderService])
@ -91,6 +94,9 @@ class DBusCachedPlugin(val config : DataCacheConfig,
MEMORY_WR -> True
) ++ (if(catchSomething) List(HAS_SIDE_EFFECT -> True) else Nil)
)
if(withLrSc) decoderService.add(key, Seq(MEMORY_LRSC -> False))
if(withAmo) decoderService.add(key, Seq(MEMORY_AMO -> False))
}
val bypassStoreList = ArrayBuffer[(Bool, Bits)]()
@ -501,6 +507,7 @@ class DBusCachedPlugin(val config : DataCacheConfig,
dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError
dBusAccess.rsp.redo := cache.io.cpu.redo
component.addPrePopTask{() =>
managementStage.input(IS_DBUS_SHARING).getDrivingReg clearWhen(dBusAccess.rsp.fire)
when(forceDatapath){
execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits
}

View File

@ -157,13 +157,13 @@ class FpuPlugin(externalFpu : Boolean = false,
import pipeline.config._
import Riscv._
val internal = !externalFpu generate pipeline plug new Area{
val internal = (!externalFpu).generate (pipeline plug new Area{
val fpu = FpuCore(1, p)
fpu.io.port(0).cmd << port.cmd
fpu.io.port(0).commit << port.commit
fpu.io.port(0).rsp >> port.rsp
fpu.io.port(0).completion <> port.completion
}
})
val csr = pipeline plug new Area{
@ -195,6 +195,7 @@ class FpuPlugin(externalFpu : Boolean = false,
fs := 3 //DIRTY
}
service.rw(CSR.SSTATUS, 13, fs)
service.rw(CSR.MSTATUS, 13, fs)
}
decode plug new Area{
@ -259,7 +260,7 @@ class FpuPlugin(externalFpu : Boolean = false,
commit.write := arbitration.isValid && !arbitration.removeIt
commit.sync := input(FPU_COMMIT_SYNC)
when(arbitration.isValid && !commit.ready){
when(isCommit && !commit.ready){
arbitration.haltByOther := True
}