mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
Add openSBI test, seem to work fine
This commit is contained in:
parent
d5a52caab8
commit
8c0e534c6b
5 changed files with 144 additions and 51 deletions
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
|
@ -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.
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue