SpinalHDL 1.9.4
This commit is contained in:
commit
07b0d7788b
36
README.md
36
README.md
|
@ -1295,6 +1295,42 @@ Write Address 0x04 ->
|
|||
|
||||
The OpenOCD port is here: <https://github.com/SpinalHDL/openocd_riscv>
|
||||
|
||||
#### EmbeddedRiscvJtag
|
||||
|
||||
VexRiscv also support the official RISC-V debug specification (Thanks Efinix for the funding !).
|
||||
|
||||
To enable it, you need to add the EmbeddedRiscvJtag to the plugin list :
|
||||
|
||||
```scala
|
||||
new EmbeddedRiscvJtag(
|
||||
p = DebugTransportModuleParameter(
|
||||
addressWidth = 7,
|
||||
version = 1,
|
||||
idle = 7
|
||||
),
|
||||
withTunneling = false,
|
||||
withTap = true
|
||||
)
|
||||
```
|
||||
|
||||
And turn on the withPrivilegedDebug option in the CsrPlugin config.
|
||||
|
||||
Here is an example of openocd tcl script to connect :
|
||||
|
||||
```tcl
|
||||
# ADD HERE YOUR JTAG ADAPTER SETTINGS
|
||||
|
||||
set _CHIPNAME riscv
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10002FFF
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
|
||||
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
|
||||
|
||||
init
|
||||
halt
|
||||
```
|
||||
|
||||
#### YamlPlugin
|
||||
|
||||
This plugin offers a service to other plugins to generate a useful Yaml file describing the CPU configuration. It contains, for instance, the sequence of instructions required
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
val spinalVersion = "1.9.3"
|
||||
val spinalVersion = "1.9.4"
|
||||
|
||||
lazy val root = (project in file(".")).
|
||||
settings(
|
||||
|
|
|
@ -14,6 +14,7 @@ import spinal.lib.com.jtag.xilinx.Bscane2BmbMasterGenerator
|
|||
import spinal.lib.generator._
|
||||
import spinal.core.fiber._
|
||||
import spinal.idslplugin.PostInitCallback
|
||||
import spinal.lib.cpu.riscv.debug.{DebugModule, DebugModuleCpuConfig, DebugModuleParameter, DebugTransportModuleParameter, DebugTransportModuleTunneled}
|
||||
import spinal.lib.misc.plic.PlicMapping
|
||||
import spinal.lib.system.debugger.SystemDebuggerConfig
|
||||
import vexriscv.ip.{DataCacheAck, DataCacheConfig, DataCacheMemBus, InstructionCache, InstructionCacheConfig}
|
||||
|
@ -30,7 +31,9 @@ case class VexRiscvSmpClusterParameter(cpuConfigs : Seq[VexRiscvConfig],
|
|||
withExclusiveAndInvalidation : Boolean,
|
||||
forcePeripheralWidth : Boolean = true,
|
||||
outOfOrderDecoder : Boolean = true,
|
||||
fpu : Boolean = false)
|
||||
fpu : Boolean = false,
|
||||
privilegedDebug : Boolean = false,
|
||||
hardwareBreakpoints : Int = 0)
|
||||
|
||||
class VexRiscvSmpClusterBase(p : VexRiscvSmpClusterParameter) extends Area with PostInitCallback{
|
||||
val cpuCount = p.cpuConfigs.size
|
||||
|
@ -52,10 +55,12 @@ class VexRiscvSmpClusterBase(p : VexRiscvSmpClusterParameter) extends Area with
|
|||
|
||||
implicit val interconnect = BmbInterconnectGenerator()
|
||||
|
||||
val customDebug = !p.privilegedDebug generate new Area {
|
||||
val debugBridge = debugCd.outputClockDomain on JtagInstructionDebuggerGenerator(p.jtagHeaderIgnoreWidth)
|
||||
debugBridge.jtagClockDomain.load(ClockDomain.external("jtag", withReset = false))
|
||||
|
||||
val debugPort = Handle(debugBridge.logic.jtagBridge.io.ctrl.toIo)
|
||||
val debugPort = Handle(debugBridge.logic.jtagBridge.io.ctrl.toIo).setName("debugPort")
|
||||
}
|
||||
|
||||
val dBusCoherent = BmbBridgeGenerator()
|
||||
val dBusNonCoherent = BmbBridgeGenerator()
|
||||
|
@ -80,12 +85,66 @@ class VexRiscvSmpClusterBase(p : VexRiscvSmpClusterParameter) extends Area with
|
|||
interconnect.addConnection(
|
||||
cpu.dBus -> List(dBusCoherent.bmb)
|
||||
)
|
||||
|
||||
cpu.hardwareBreakpointCount.load(p.hardwareBreakpoints)
|
||||
if(!p.privilegedDebug) {
|
||||
cpu.enableDebugBmb(
|
||||
debugCd = debugCd.outputClockDomain,
|
||||
resetCd = systemCd,
|
||||
mapping = SizeMapping(cpuId*0x1000, 0x1000)
|
||||
mapping = SizeMapping(cpuId * 0x1000, 0x1000)
|
||||
)
|
||||
interconnect.addConnection(debugBridge.bmb, cpu.debugBmb)
|
||||
interconnect.addConnection(customDebug.debugBridge.bmb, cpu.debugBmb)
|
||||
} else {
|
||||
cpu.enableRiscvDebug(debugCd.outputClockDomain, systemCd)
|
||||
}
|
||||
}
|
||||
|
||||
val privilegedDebug = p.privilegedDebug generate new Area{
|
||||
val jtagCd = ClockDomain.external("jtag", withReset = false)
|
||||
|
||||
val systemReset = Handle(Bool())
|
||||
systemCd.relaxedReset(systemReset, ResetSensitivity.HIGH)
|
||||
|
||||
val p = DebugTransportModuleParameter(
|
||||
addressWidth = 7,
|
||||
version = 1,
|
||||
idle = 7
|
||||
)
|
||||
|
||||
val logic = hardFork(debugCd.outputClockDomain on new Area {
|
||||
val XLEN = 32
|
||||
|
||||
val dm = DebugModule(
|
||||
DebugModuleParameter(
|
||||
version = p.version + 1,
|
||||
harts = cpuCount,
|
||||
progBufSize = 2,
|
||||
datacount = XLEN / 32 + cores.exists(_.cpu.config.get.FLEN == 64).toInt,
|
||||
hartsConfig = cores.map(c => DebugModuleCpuConfig(
|
||||
xlen = XLEN,
|
||||
flen = c.cpu.config.get.FLEN,
|
||||
withFpuRegAccess = c.cpu.config.get.FLEN == 64
|
||||
))
|
||||
)
|
||||
)
|
||||
systemReset := dm.io.ndmreset
|
||||
for ((cpu, i) <- cores.zipWithIndex) {
|
||||
val privBus = cpu.cpu.debugRiscv
|
||||
privBus <> dm.io.harts(i)
|
||||
privBus.dmToHart.removeAssignments() <-< dm.io.harts(i).dmToHart
|
||||
}
|
||||
|
||||
val clintStop = (cores.map(e => e.cpu.logic.cpu.service(classOf[CsrPlugin]).stoptime).andR)
|
||||
|
||||
val tunnel = DebugTransportModuleTunneled(
|
||||
p = p,
|
||||
jtagCd = jtagCd,
|
||||
debugCd = ClockDomain.current
|
||||
)
|
||||
dm.io.ctrl <> tunnel.io.bus
|
||||
|
||||
val debugPort = Handle(tunnel.io.instruction.toIo).setName("debugPort")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,9 +216,10 @@ class VexRiscvSmpClusterWithPeripherals(p : VexRiscvSmpClusterParameter) extends
|
|||
}
|
||||
|
||||
clint.cpuCount.load(cpuCount)
|
||||
if(p.privilegedDebug) hardFork(clint.logic.io.stop := privilegedDebug.logic.clintStop)
|
||||
}
|
||||
|
||||
|
||||
//python3 -m litex_boards.targets.digilent_nexys_video --cpu-type=vexriscv_smp --with-privileged-debug --sys-clk-freq 50000000 --cpu-count 1 --build --load
|
||||
object VexRiscvSmpClusterGen {
|
||||
def vexRiscvConfig(hartId : Int,
|
||||
ioRange : UInt => Bool = (x => x(31 downto 28) === 0xF),
|
||||
|
|
|
@ -7,6 +7,7 @@ import spinal.lib.bus.misc.{AddressMapping, DefaultMapping, SizeMapping}
|
|||
import spinal.lib.bus.wishbone.{WishboneConfig, WishboneToBmbGenerator}
|
||||
import spinal.lib.generator.GeneratorComponent
|
||||
import spinal.lib.sim.SparseMemory
|
||||
import vexriscv.demo.smp.VexRiscvLitexSmpClusterCmdGen.exposeTime
|
||||
import vexriscv.demo.smp.VexRiscvSmpClusterGen.vexRiscvConfig
|
||||
import vexriscv.ip.fpu.{FpuCore, FpuParameter}
|
||||
import vexriscv.plugin.{AesPlugin, DBusCachedPlugin, FpuPlugin}
|
||||
|
@ -17,7 +18,8 @@ case class VexRiscvLitexSmpClusterParameter( cluster : VexRiscvSmpClusterParamet
|
|||
liteDramMapping : AddressMapping,
|
||||
coherentDma : Boolean,
|
||||
wishboneMemory : Boolean,
|
||||
cpuPerFpu : Int)
|
||||
cpuPerFpu : Int,
|
||||
exposeTime : Boolean)
|
||||
|
||||
|
||||
class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter) extends VexRiscvSmpClusterWithPeripherals(p.cluster) {
|
||||
|
@ -97,10 +99,13 @@ class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter) extends VexR
|
|||
interconnect.setPipelining(iBridge.bmb)(cmdHalfRate = true)
|
||||
interconnect.setPipelining(dBridge.bmb)(cmdReady = true)
|
||||
}
|
||||
|
||||
val clint_time = p.exposeTime generate hardFork(clint.logic.io.time.toIo)
|
||||
}
|
||||
|
||||
|
||||
object VexRiscvLitexSmpClusterCmdGen extends App {
|
||||
Handle.loadHandleAsync = true
|
||||
var cpuCount = 1
|
||||
var iBusWidth = 64
|
||||
var dBusWidth = 64
|
||||
|
@ -108,6 +113,8 @@ object VexRiscvLitexSmpClusterCmdGen extends App {
|
|||
var dCacheSize = 8192
|
||||
var iCacheWays = 2
|
||||
var dCacheWays = 2
|
||||
var privilegedDebug = false
|
||||
var hardwareBreakpoints = 0
|
||||
var liteDramWidth = 128
|
||||
var coherentDma = false
|
||||
var wishboneMemory = false
|
||||
|
@ -121,9 +128,10 @@ object VexRiscvLitexSmpClusterCmdGen extends App {
|
|||
var iTlbSize = 4
|
||||
var dTlbSize = 4
|
||||
var wishboneForce32b = false
|
||||
var exposeTime = false
|
||||
assert(new scopt.OptionParser[Unit]("VexRiscvLitexSmpClusterCmdGen") {
|
||||
help("help").text("prints this usage text")
|
||||
opt[Unit]("coherent-dma") action { (v, c) => coherentDma = true }
|
||||
opt[Unit] ("coherent-dma") action { (v, c) => coherentDma = true }
|
||||
opt[String]("cpu-count") action { (v, c) => cpuCount = v.toInt }
|
||||
opt[String]("ibus-width") action { (v, c) => iBusWidth = v.toInt }
|
||||
opt[String]("dbus-width") action { (v, c) => dBusWidth = v.toInt }
|
||||
|
@ -131,6 +139,8 @@ object VexRiscvLitexSmpClusterCmdGen extends App {
|
|||
opt[String]("dcache-size") action { (v, c) => dCacheSize = v.toInt }
|
||||
opt[String]("icache-ways") action { (v, c) => iCacheWays = v.toInt }
|
||||
opt[String]("dcache-ways") action { (v, c) => dCacheWays = v.toInt }
|
||||
opt[Boolean]("privileged-debug") action { (v, c) => privilegedDebug = v }
|
||||
opt[Int] ("hardware-breakpoints") action { (v, c) => hardwareBreakpoints = v }
|
||||
opt[String]("litedram-width") action { (v, c) => liteDramWidth = v.toInt }
|
||||
opt[String]("netlist-directory") action { (v, c) => netlistDirectory = v }
|
||||
opt[String]("netlist-name") action { (v, c) => netlistName = v }
|
||||
|
@ -143,6 +153,7 @@ object VexRiscvLitexSmpClusterCmdGen extends App {
|
|||
opt[String]("rvc") action { (v, c) => rvc = v.toBoolean }
|
||||
opt[String]("itlb-size") action { (v, c) => iTlbSize = v.toInt }
|
||||
opt[String]("dtlb-size") action { (v, c) => dTlbSize = v.toInt }
|
||||
opt[String]("expose-time") action { (v, c) => exposeTime = v.toBoolean }
|
||||
}.parse(args, Unit).nonEmpty)
|
||||
|
||||
val coherency = coherentDma || cpuCount > 1
|
||||
|
@ -160,6 +171,7 @@ object VexRiscvLitexSmpClusterCmdGen extends App {
|
|||
iCacheWays = iCacheWays,
|
||||
dCacheWays = dCacheWays,
|
||||
coherency = coherency,
|
||||
privilegedDebug = privilegedDebug,
|
||||
iBusRelax = true,
|
||||
earlyBranch = true,
|
||||
withFloat = fpu,
|
||||
|
@ -178,13 +190,16 @@ object VexRiscvLitexSmpClusterCmdGen extends App {
|
|||
forcePeripheralWidth = !wishboneMemory || wishboneForce32b,
|
||||
outOfOrderDecoder = outOfOrderDecoder,
|
||||
fpu = fpu,
|
||||
jtagHeaderIgnoreWidth = 0
|
||||
jtagHeaderIgnoreWidth = 0,
|
||||
privilegedDebug = privilegedDebug,
|
||||
hardwareBreakpoints = hardwareBreakpoints
|
||||
),
|
||||
liteDram = LiteDramNativeParameter(addressWidth = 32, dataWidth = liteDramWidth),
|
||||
liteDramMapping = SizeMapping(0x40000000l, 0x40000000l),
|
||||
coherentDma = coherentDma,
|
||||
wishboneMemory = wishboneMemory,
|
||||
cpuPerFpu = cpuPerFpu
|
||||
cpuPerFpu = cpuPerFpu,
|
||||
exposeTime = exposeTime
|
||||
)
|
||||
|
||||
def dutGen = {
|
||||
|
@ -260,7 +275,8 @@ object VexRiscvLitexSmpClusterOpenSbi extends App{
|
|||
liteDramMapping = SizeMapping(0x80000000l, 0x70000000l),
|
||||
coherentDma = false,
|
||||
wishboneMemory = false,
|
||||
cpuPerFpu = 4
|
||||
cpuPerFpu = 4,
|
||||
exposeTime = false
|
||||
)
|
||||
|
||||
def dutGen = {
|
||||
|
|
|
@ -33,6 +33,7 @@ class PlicBench(inputCount : Int) extends Component{
|
|||
|
||||
val targets = Seq(
|
||||
PlicTarget(
|
||||
id = 0,
|
||||
gateways = gateways,
|
||||
priorityWidth = priorityWidth
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue