Add openSBI test, seem to work fine

This commit is contained in:
Dolu1990 2020-04-18 00:51:47 +02:00
parent d5a52caab8
commit 8c0e534c6b
5 changed files with 144 additions and 51 deletions

View file

@ -4,6 +4,8 @@ import spinal.core._
object Riscv{
def misaToInt(values : String) = values.toLowerCase.map(e => 1 << (e-'a')).reduce(_ | _)
def funct7Range = 31 downto 25
def rdRange = 11 downto 7
def funct3Range = 14 downto 12

View file

@ -1,14 +1,17 @@
package vexriscv.demo.smp
import spinal.core
import spinal.core._
import spinal.core.sim.{onSimEnd, simSuccess}
import spinal.lib._
import spinal.lib.bus.bmb.sim.BmbMemoryAgent
import spinal.lib.bus.bmb.{Bmb, BmbArbiter, BmbDecoder, BmbExclusiveMonitor, BmbInvalidateMonitor, BmbParameter}
import spinal.lib.com.jtag.Jtag
import spinal.lib.com.jtag.sim.JtagTcp
import vexriscv.demo.smp.VexRiscvSmpClusterTest.{cpuCount, withStall}
import vexriscv.ip.{DataCacheAck, DataCacheConfig, DataCacheMemBus, InstructionCacheConfig}
import vexriscv.plugin.{BranchPlugin, CsrPlugin, CsrPluginConfig, DBusCachedPlugin, DBusSimplePlugin, DebugPlugin, DecoderSimplePlugin, FullBarrelShifterPlugin, HazardSimplePlugin, IBusCachedPlugin, IBusSimplePlugin, IntAluPlugin, MmuPlugin, MmuPortConfig, MulDivIterativePlugin, MulPlugin, RegFilePlugin, STATIC, SrcPlugin, YamlPlugin}
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
import vexriscv.{Riscv, VexRiscv, VexRiscvConfig, plugin}
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
@ -34,6 +37,7 @@ case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
val iMems = Vec(master(Bmb(iMemParameter)), p.cpuConfigs.size)
val timerInterrupts = in Bits(p.cpuConfigs.size bits)
val externalInterrupts = in Bits(p.cpuConfigs.size bits)
val softwareInterrupts = in Bits(p.cpuConfigs.size bits)
val externalSupervisorInterrupts = in Bits(p.cpuConfigs.size bits)
val jtag = slave(Jtag())
val debugReset = out Bool()
@ -53,6 +57,7 @@ case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
case plugin: IBusCachedPlugin => iBus = plugin.iBus.toBmb()
case plugin: DBusCachedPlugin => dBus = plugin.dBus.toBmb()
case plugin: CsrPlugin => {
plugin.softwareInterrupt := io.softwareInterrupts(cpuId)
plugin.externalInterrupt := io.externalInterrupts(cpuId)
plugin.timerInterrupt := io.timerInterrupts(cpuId)
if (plugin.config.supervisorGen) plugin.externalInterruptS := io.externalSupervisorInterrupts(cpuId)
@ -228,7 +233,7 @@ object VexRiscvSmpClusterGen {
divUnrollFactor = 1
),
// new DivPlugin,
new CsrPlugin(CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = false, mhartid = id)),
new CsrPlugin(CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = false, mhartid = id, misaExtensionsInit = Riscv.misaToInt("imas"))),
// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
// CsrPluginConfig(
// catchIllegalAccess = false,
@ -279,59 +284,51 @@ object VexRiscvSmpClusterGen {
}
object SmpTest{
object VexRiscvSmpClusterTestInfrastructure{
val REPORT_OFFSET = 0xF8000000
val REPORT_THREAD_ID = 0x00
val REPORT_THREAD_COUNT = 0x04
val REPORT_END = 0x08
val REPORT_BARRIER_START = 0x0C
val REPORT_BARRIER_END = 0x10
}
object VexRiscvSmpClusterTest extends App{
import spinal.core.sim._
val simConfig = SimConfig
simConfig.withWave
simConfig.allOptimisation
simConfig.addSimulatorFlag("--threads 1")
val PUTC = 0x00
val GETC = 0x04
val CLINT_ADDR = 0x10000
val CLINT_IPI_ADDR = CLINT_ADDR+0x0000
val CLINT_CMP_ADDR = CLINT_ADDR+0x4000
val CLINT_TIME_ADDR = CLINT_ADDR+0xBFF8
val cpuCount = 4
simConfig.compile(VexRiscvSmpClusterGen.vexRiscvCluster(cpuCount)).doSimUntilVoid(seed = 42){dut =>
SimTimeout(10000*10*cpuCount)
dut.clockDomain.forkSimSpeedPrinter(1.0)
dut.clockDomain.forkStimulus(10)
dut.debugClockDomain.forkStimulus(10)
JtagTcp(dut.io.jtag, 100)
val withStall = false
val cpuEnd = Array.fill(dut.p.cpuConfigs.size)(false)
val barriers = mutable.HashMap[Int, Int]()
var reportWatchdog = 0
periodicaly(10000*10){
assert(reportWatchdog != 0)
reportWatchdog = 0
}
case class Report(hart : Int, code : Int, data : Int){
override def toString: String = {
f"CPU:$hart%2d h${code}%3x -> $data%3d"
}
}
val reports = ArrayBuffer.fill(cpuCount)(ArrayBuffer[Report]())
onSimEnd{
for((list, hart) <- reports.zipWithIndex){
println(f"\n\n**** CPU $hart%2d ****")
for((report, reportId) <- list.zipWithIndex){
println(f" $reportId%3d : h${report.code}%3x -> ${report.data}%3d")
def ram(dut : VexRiscvSmpCluster) = {
import spinal.core.sim._
val cpuCount = dut.cpus.size
val ram = new BmbMemoryAgent(0x100000000l){
case class Report(hart : Int, code : Int, data : Int){
override def toString: String = {
f"CPU:$hart%2d ${code}%3x -> $data%3d"
}
}
val reports = ArrayBuffer.fill(cpuCount)(ArrayBuffer[Report]())
onSimEnd{
for((list, hart) <- reports.zipWithIndex){
println(f"\n\n**** CPU $hart%2d ****")
for((report, reportId) <- list.zipWithIndex){
println(f" $reportId%3d : ${report.code}%3x -> ${report.data}%3d")
}
}
}
}
val ram = new BmbMemoryAgent(0x100000000l){
val writeTable = mutable.HashMap[Int, Int => Unit]()
val readTable = mutable.HashMap[Int, () => Int]()
def onWrite(address : Int)(body : Int => Unit) = writeTable(address) = body
def onRead(address : Int)(body : => Int) = readTable(address) = () => body
var writeData = 0
var readData = 0
var reportWatchdog = 0
val cpuEnd = Array.fill(cpuCount)(false)
val barriers = mutable.HashMap[Int, Int]()
override def setByte(address: Long, value: Byte): Unit = {
if((address & 0xF0000000l) != 0xF0000000l) return super.setByte(address, value)
val byteId = address & 3
@ -339,7 +336,7 @@ object VexRiscvSmpClusterTest extends App{
writeData = (writeData & ~mask) | ((value.toInt << (byteId*8)) & mask)
if(byteId != 3) return
val offset = (address & ~0xF0000000l)-3
// println(s"W[0x${offset.toHexString}] = $writeData @${simTime()}")
// println(s"W[0x${offset.toHexString}] = $writeData @${simTime()}")
offset match {
case _ if offset >= 0x8000000 && offset < 0x9000000 => {
val report = Report(
@ -351,7 +348,6 @@ object VexRiscvSmpClusterTest extends App{
reports(report.hart) += report
reportWatchdog += 1
import report._
import SmpTest._
code match {
case REPORT_THREAD_ID => assert(data == hart)
case REPORT_THREAD_COUNT => assert(data == cpuCount)
@ -367,13 +363,108 @@ object VexRiscvSmpClusterTest extends App{
}
}
}
case _ => writeTable.get(offset.toInt) match {
case Some(x) => x(writeData)
case _ => simFailure(f"\n\nWrite at ${address-3}%8x with $writeData%8x")
}
}
}
}
dut.io.iMems.foreach(ram.addPort(_,0,dut.clockDomain,true, withStall)) //Moarr powaaaaa
// ram.addPort(dut.io.iMem,0,dut.clockDomain,true, withStall)
ram.addPort(dut.io.dMem,0,dut.clockDomain,true, withStall)
override def getByte(address: Long): Byte = {
if((address & 0xF0000000l) != 0xF0000000l) return super.getByte(address)
val byteId = address & 3
val offset = (address & ~0xF0000000l)
if(byteId == 0) readData = readTable.get(offset.toInt) match {
case Some(x) => x()
case _ => simFailure(f"\n\nRead at $address%8x")
}
(readData >> (byteId*8)).toByte
}
val clint = new {
val cmp = Array.fill(cpuCount)(0l)
}
onWrite(PUTC)(data => print(data.toChar))
// onWrite(GETC)(data => System.in.read().toInt)
onRead(CLINT_TIME_ADDR)(simTime().toInt)
onRead(CLINT_TIME_ADDR+4)((simTime() >> 32).toInt)
for(hartId <- 0 until cpuCount){
onWrite(CLINT_IPI_ADDR + hartId*4) {data =>
val mask = 1l << hartId
val value = (dut.io.softwareInterrupts.toLong & ~mask) | (if(data == 1) mask else 0)
dut.io.softwareInterrupts #= value
}
onRead(CLINT_CMP_ADDR + hartId*8)(clint.cmp(hartId).toInt)
onRead(CLINT_CMP_ADDR + hartId*8+4)((clint.cmp(hartId) >> 32).toInt)
onWrite(CLINT_CMP_ADDR + hartId*8)(data => clint.cmp(hartId) = (clint.cmp(hartId) & 0xFFFFFFFF00000000l) | data)
onWrite(CLINT_CMP_ADDR + hartId*8+4)(data => (clint.cmp(hartId) & 0x00000000FFFFFFFFl) | (data << 32))
}
var time = 0l
periodicaly(100){
time += 10
var timerInterrupts = 0l
for(i <- 0 until cpuCount){
if(clint.cmp(i) < time) timerInterrupts |= 1l << i
}
dut.io.timerInterrupts #= timerInterrupts
}
}
dut.io.iMems.foreach(ram.addPort(_,0,dut.clockDomain,true, withStall))
ram.addPort(dut.io.dMem,0,dut.clockDomain,true, withStall)
ram
}
def init(dut : VexRiscvSmpCluster): Unit ={
import spinal.core.sim._
dut.clockDomain.forkSimSpeedPrinter(1.0)
dut.clockDomain.forkStimulus(10)
dut.debugClockDomain.forkStimulus(10)
JtagTcp(dut.io.jtag, 100)
}
}
object VexRiscvSmpClusterTest extends App{
import spinal.core.sim._
val simConfig = SimConfig
// simConfig.withWave
simConfig.allOptimisation
simConfig.addSimulatorFlag("--threads 1")
val cpuCount = 4
val withStall = true
simConfig.compile(VexRiscvSmpClusterGen.vexRiscvCluster(cpuCount)).doSimUntilVoid(seed = 42){dut =>
SimTimeout(10000*10*cpuCount)
VexRiscvSmpClusterTestInfrastructure.init(dut)
val ram = VexRiscvSmpClusterTestInfrastructure.ram(dut)
ram.memory.loadBin(0x80000000l, "src/test/cpp/raw/smp/build/smp.bin")
periodicaly(20000*10){
assert(ram.reportWatchdog != 0)
ram.reportWatchdog = 0
}
}
}
object VexRiscvSmpClusterOpenSbi extends App{
import spinal.core.sim._
val simConfig = SimConfig
simConfig.withWave
simConfig.allOptimisation
simConfig.addSimulatorFlag("--threads 1")
val cpuCount = 4
val withStall = false
simConfig.compile(VexRiscvSmpClusterGen.vexRiscvCluster(cpuCount)).doSimUntilVoid(seed = 42){dut =>
VexRiscvSmpClusterTestInfrastructure.init(dut)
val ram = VexRiscvSmpClusterTestInfrastructure.ram(dut)
ram.memory.loadBin(0x80000000l, "../opensbi/build/platform/spinal/vexriscv/sim/smp/firmware/fw_payload.bin")
// ram.memory.loadBin(0x80000000l, "../opensbi/build/platform/spinal/vexriscv/sim/smp/firmware/fw_jump.bin")
}
}

View file

@ -21,7 +21,7 @@ Disassembly of section .crt_section:
80000028 <count_thread_wait>:
80000028: 00000417 auipc s0,0x0
8000002c: 1c442403 lw s0,452(s0) # 800001ec <thread_count>
80000030: 0c800513 li a0,200
80000030: 19000513 li a0,400
80000034: 1ac000ef jal ra,800001e0 <sleep>
80000038: 00000497 auipc s1,0x0
8000003c: 1b44a483 lw s1,436(s1) # 800001ec <thread_count>

Binary file not shown.

View file

@ -26,7 +26,7 @@ count_thread_start:
count_thread_wait:
//Wait everybody
lw s0, thread_count
li a0, 200
li a0, 400
call sleep
lw s1, thread_count
bne s1, s0, count_thread_wait