Add VexRiscvSmpCluster, seem to work on simple case

This commit is contained in:
Dolu1990 2020-04-16 01:30:03 +02:00
parent b9ceabf128
commit 73c21177e5
6 changed files with 506 additions and 0 deletions

View File

@ -0,0 +1,302 @@
package vexriscv.demo.smp
import spinal.core._
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.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}
case class VexRiscvSmpClusterParameter( cpuConfigs : Seq[VexRiscvConfig])
case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
debugClockDomain : ClockDomain) extends Component{
val dBusParameter = p.cpuConfigs.head.plugins.find(_.isInstanceOf[DBusCachedPlugin]).get.asInstanceOf[DBusCachedPlugin].config.getBmbParameter()
val dBusArbiterParameter = dBusParameter.copy(sourceWidth = log2Up(p.cpuConfigs.size))
val exclusiveMonitorParameter = dBusArbiterParameter
val invalidateMonitorParameter = BmbExclusiveMonitor.outputParameter(exclusiveMonitorParameter)
val dMemParameter = BmbInvalidateMonitor.outputParameter(invalidateMonitorParameter)
val iBusParameter = p.cpuConfigs.head.plugins.find(_.isInstanceOf[IBusCachedPlugin]).get.asInstanceOf[IBusCachedPlugin].config.getBmbParameter()
val iBusArbiterParameter = iBusParameter.copy(sourceWidth = log2Up(p.cpuConfigs.size))
val iMemParameter = iBusArbiterParameter
val io = new Bundle {
val dMem = master(Bmb(dMemParameter))
val iMem = master(Bmb(iMemParameter))
val timerInterrupts = in Bits(p.cpuConfigs.size bits)
val externalInterrupts = in Bits(p.cpuConfigs.size bits)
val externalSupervisorInterrupts = in Bits(p.cpuConfigs.size bits)
val jtag = slave(Jtag())
val debugReset = out Bool()
}
val cpus = for((cpuConfig, cpuId) <- p.cpuConfigs.zipWithIndex) yield new Area{
var iBus : Bmb = null
var dBus : Bmb = null
cpuConfig.plugins.foreach {
case plugin: DebugPlugin => debugClockDomain{
plugin.debugClockDomain = debugClockDomain
}
case _ =>
}
val core = new VexRiscv(cpuConfig)
core.plugins.foreach {
case plugin: IBusCachedPlugin => iBus = plugin.iBus.toBmb()
case plugin: DBusCachedPlugin => dBus = plugin.dBus.toBmb()
case plugin: CsrPlugin => {
plugin.externalInterrupt := io.externalInterrupts(cpuId)
plugin.timerInterrupt := io.timerInterrupts(cpuId)
if (plugin.config.supervisorGen) plugin.externalInterruptS := io.externalSupervisorInterrupts(cpuId)
}
case plugin: DebugPlugin => debugClockDomain{
io.debugReset := RegNext(plugin.io.resetOut)
io.jtag <> plugin.io.bus.fromJtag()
}
case _ =>
}
}
val dBusArbiter = BmbArbiter(
p = dBusArbiterParameter,
portCount = cpus.size,
pendingRspMax = 64,
lowerFirstPriority = false,
inputsWithInv = cpus.map(_ => true),
inputsWithSync = cpus.map(_ => true),
pendingInvMax = 16
)
(dBusArbiter.io.inputs, cpus).zipped.foreach(_ << _.dBus)
val exclusiveMonitor = BmbExclusiveMonitor(
inputParameter = exclusiveMonitorParameter,
pendingWriteMax = 64
)
exclusiveMonitor.io.input << dBusArbiter.io.output
val invalidateMonitor = BmbInvalidateMonitor(
inputParameter = invalidateMonitorParameter,
pendingInvMax = 16
)
invalidateMonitor.io.input << exclusiveMonitor.io.output
io.dMem << invalidateMonitor.io.output
val iBusArbiter = BmbArbiter(
p = iBusArbiterParameter,
portCount = cpus.size,
pendingRspMax = 64,
lowerFirstPriority = false,
inputsWithInv = cpus.map(_ => true),
inputsWithSync = cpus.map(_ => true),
pendingInvMax = 16
)
(iBusArbiter.io.inputs, cpus).zipped.foreach(_ << _.iBus)
io.iMem << iBusArbiter.io.output
}
object VexRiscvSmpClusterGen {
def vexRiscvConfig(id : Int) = {
val config = VexRiscvConfig(
plugins = List(
new MmuPlugin(
ioRange = x => x(31 downto 28) === 0xF
),
//Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config
// new IBusSimplePlugin(
// resetVector = 0x80000000l,
// cmdForkOnSecondStage = false,
// cmdForkPersistence = false,
// prediction = DYNAMIC_TARGET,
// historyRamSizeLog2 = 10,
// catchAccessFault = true,
// compressedGen = true,
// busLatencyMin = 1,
// injectorStage = true,
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
// portTlbSize = 4
// )
// ),
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
new IBusCachedPlugin(
resetVector = 0x80000000l,
compressedGen = false,
prediction = STATIC,
injectorStage = false,
config = InstructionCacheConfig(
cacheSize = 4096*1,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = true,
catchAccessFault = true,
asyncTagMemory = false,
twoCycleRam = false,
twoCycleCache = true
// )
),
memoryTranslatorPortConfig = MmuPortConfig(
portTlbSize = 4
)
),
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
// new DBusSimplePlugin(
// catchAddressMisaligned = true,
// catchAccessFault = true,
// earlyInjection = false,
// withLrSc = true,
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
// portTlbSize = 4
// )
// ),
new DBusCachedPlugin(
dBusCmdMasterPipe = true,
dBusCmdSlavePipe = true,
dBusRspSlavePipe = true,
config = new DataCacheConfig(
cacheSize = 4096*1,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
withLrSc = true,
withAmo = true,
withExclusive = true,
withInvalidate = true
// )
),
memoryTranslatorPortConfig = MmuPortConfig(
portTlbSize = 4
)
),
// new MemoryTranslatorPlugin(
// tlbSize = 32,
// virtualRange = _(31 downto 28) === 0xC,
// ioRange = _(31 downto 28) === 0xF
// ),
new DecoderSimplePlugin(
catchIllegalInstruction = true
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
zeroBoot = true
),
new IntAluPlugin,
new SrcPlugin(
separatedAddSub = false
),
new FullBarrelShifterPlugin(earlyInjection = false),
// new LightShifterPlugin,
new HazardSimplePlugin(
bypassExecute = true,
bypassMemory = true,
bypassWriteBack = true,
bypassWriteBackBuffer = true,
pessimisticUseSrc = false,
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
),
// new HazardSimplePlugin(false, true, false, true),
// new HazardSimplePlugin(false, false, false, false),
new MulPlugin,
new MulDivIterativePlugin(
genMul = false,
genDiv = true,
mulUnrollFactor = 32,
divUnrollFactor = 1
),
// new DivPlugin,
new CsrPlugin(CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = false, mhartid = id)),
// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
// CsrPluginConfig(
// catchIllegalAccess = false,
// mvendorid = null,
// marchid = null,
// mimpid = null,
// mhartid = null,
// misaExtensionsInit = 0,
// misaAccess = CsrAccess.READ_ONLY,
// mtvecAccess = CsrAccess.WRITE_ONLY,
// mtvecInit = 0x80000020l,
// mepcAccess = CsrAccess.READ_WRITE,
// mscratchGen = true,
// mcauseAccess = CsrAccess.READ_ONLY,
// mbadaddrAccess = CsrAccess.READ_ONLY,
// mcycleAccess = CsrAccess.NONE,
// minstretAccess = CsrAccess.NONE,
// ecallGen = true,
// ebreakGen = true,
// wfiGenAsWait = false,
// wfiGenAsNop = true,
// ucycleAccess = CsrAccess.NONE
// )),
new BranchPlugin(
earlyBranch = false,
catchAddressMisaligned = true,
fenceiGenAsAJump = false
),
new YamlPlugin(s"cpu$id.yaml")
)
)
if(id == 0) config.plugins += new DebugPlugin(null)
config
}
def vexRiscvCluster() = VexRiscvSmpCluster(
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
p = VexRiscvSmpClusterParameter(
cpuConfigs = List.tabulate(4) {
vexRiscvConfig(_)
}
)
)
def main(args: Array[String]): Unit = {
SpinalVerilog {
vexRiscvCluster()
}
}
}
object VexRiscvSmpClusterTest extends App{
import spinal.core.sim._
val simConfig = SimConfig
simConfig.withWave
simConfig.allOptimisation
simConfig.addSimulatorFlag("--threads 1")
simConfig.compile(VexRiscvSmpClusterGen.vexRiscvCluster()).doSim(seed = 42){dut =>
dut.clockDomain.forkSimSpeedPrinter(1.0)
dut.clockDomain.forkStimulus(10)
dut.debugClockDomain.forkStimulus(10)
JtagTcp(dut.io.jtag, 100)
val ram = new BmbMemoryAgent(0x100000000l)
ram.addPort(dut.io.iMem,0,dut.clockDomain,true)
ram.addPort(dut.io.dMem,0,dut.clockDomain,true)
ram.memory.loadBin(0x80000000l, "src/test/cpp/raw/smp/build/smp.bin")
sleep(10000*10)
simSuccess()
}
}

5
src/test/cpp/raw/smp/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.map
*.v
*.elf
*.o
*.hex

View File

@ -0,0 +1,108 @@
build/smp.elf: file format elf32-littleriscv
Disassembly of section .crt_section:
80000000 <_start>:
80000000: f1402a73 csrr s4,mhartid
80000004: 00000517 auipc a0,0x0
80000008: 07850513 addi a0,a0,120 # 8000007c <test1_data>
8000000c: 00000513 li a0,0
80000010: 00a52023 sw a0,0(a0)
80000014 <count_thread_start>:
80000014: 00100513 li a0,1
80000018: 00000597 auipc a1,0x0
8000001c: 05c58593 addi a1,a1,92 # 80000074 <thread_count>
80000020: 00a5a02f amoadd.w zero,a0,(a1)
80000024 <count_thread_wait>:
80000024: 00000417 auipc s0,0x0
80000028: 05042403 lw s0,80(s0) # 80000074 <thread_count>
8000002c: 0c800513 li a0,200
80000030: 038000ef jal ra,80000068 <sleep>
80000034: 00000497 auipc s1,0x0
80000038: 0404a483 lw s1,64(s1) # 80000074 <thread_count>
8000003c: fe8494e3 bne s1,s0,80000024 <count_thread_wait>
80000040: 00000513 li a0,0
80000044: 00952023 sw s1,0(a0)
80000048: 0040006f j 8000004c <success>
8000004c <success>:
8000004c: 00800513 li a0,8
80000050: 00052023 sw zero,0(a0)
80000054: 0100006f j 80000064 <end>
80000058 <failure>:
80000058: 00c00513 li a0,12
8000005c: 00052023 sw zero,0(a0)
80000060: 0040006f j 80000064 <end>
80000064 <end>:
80000064: 0000006f j 80000064 <end>
80000068 <sleep>:
80000068: fff50513 addi a0,a0,-1
8000006c: fe051ee3 bnez a0,80000068 <sleep>
80000070: 00008067 ret
80000074 <thread_count>:
80000074: 0000 unimp
...
80000078 <shared_memory_1>:
80000078: 0000 unimp
...
8000007c <test1_data>:
8000007c: 0000000b 0xb
80000080 <test2_data>:
80000080: 0016 c.slli zero,0x5
...
80000084 <test3_data>:
80000084: 0049 c.nop 18
...
80000088 <test4_data>:
80000088: 003a c.slli zero,0xe
...
8000008c <test5_data>:
8000008c: 0038 addi a4,sp,8
...
80000090 <test6_data>:
80000090: 0000004b fnmsub.s ft0,ft0,ft0,ft0,rne
80000094 <test7_data>:
80000094: 0038 addi a4,sp,8
...
80000098 <test8_data>:
80000098: 00000053 fadd.s ft0,ft0,ft0,rne
8000009c <test9_data>:
8000009c: 0021 c.nop 8
...
800000a0 <test10_data>:
800000a0: ffffffbf 0xffffffbf
800000a4 <test11_data>:
800000a4: ffa9 bnez a5,7ffffffe <_start-0x2>
800000a6: ffff 0xffff
800000a8 <test12_data>:
800000a8: ffc9 bnez a5,80000042 <count_thread_wait+0x1e>
800000aa: ffff 0xffff
800000ac <test13_data>:
800000ac: 0004 0x4
800000ae: ffff 0xffff
800000b0 <test14_data>:
800000b0: 0005 c.nop 1
800000b2: ffff 0xffff

View File

@ -0,0 +1,5 @@
PROJ_NAME=smp
ATOMIC=yes
include ../common/asm.mk

View File

@ -0,0 +1,70 @@
#define REPORT_OFFSET 0xF0000000
#define REPORT_THREAD_ID 0
#define REPORT_THREAD_COUNT 1
#define REPORT_SUCCESS 2
#define REPORT_FAILURE 3
#define report(reg, id) \
li a0, id*4; \
sw reg, 0(a0); \
_start:
#define HART_ID x20
csrr HART_ID, mhartid
la a0, test1_data
report(a0, REPORT_THREAD_ID)
count_thread_start:
//Count up threads
li a0, 1
la a1, thread_count
amoadd.w x0, a0, (a1)
count_thread_wait:
//Wait everybody
lw s0, thread_count
li a0, 200
call sleep
lw s1, thread_count
bne s1, s0, count_thread_wait
report(s1, REPORT_THREAD_ID)
j success
success:
report(x0, REPORT_SUCCESS)
j end
failure:
report(x0, REPORT_FAILURE)
j end
end:
j end
sleep:
addi a0, a0, -1
bnez a0, sleep
ret
thread_count: .word 0
shared_memory_1: .word 0
test1_data: .word 11
test2_data: .word 22
test3_data: .word 73
test4_data: .word 58
test5_data: .word 56
test6_data: .word 75
test7_data: .word 56
test8_data: .word 83
test9_data: .word 33
test10_data: .word -65
test11_data: .word -87
test12_data: .word -55
test13_data: .word 0xFFFF0004
test14_data: .word 0xFFFF0005

View File

@ -0,0 +1,16 @@
OUTPUT_ARCH( "riscv" )
MEMORY {
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 128K
}
SECTIONS
{
.crt_section :
{
. = ALIGN(4);
*crt.o(.text)
} > onChipRam
}