1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
package vexriscv
import spinal.core._
import spinal.lib.bus.bmb.{Bmb, BmbAccessCapabilities, BmbAccessParameter, BmbImplicitDebugDecoder, BmbInterconnectGenerator, BmbInvalidationParameter, BmbParameter}
import spinal.lib.bus.misc.AddressMapping
import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl}
import spinal.lib.generator._
import spinal.lib.{sexport, slave}
import vexriscv.plugin._
import spinal.core.fiber._
object VexRiscvBmbGenerator{
val DEBUG_NONE = 0
val DEBUG_JTAG = 1
val DEBUG_JTAG_CTRL = 2
val DEBUG_BUS = 3
val DEBUG_BMB = 4
}
case class VexRiscvBmbGenerator()(implicit interconnectSmp: BmbInterconnectGenerator = null) extends Area {
import VexRiscvBmbGenerator._
val config = Handle[VexRiscvConfig]
val withDebug = Handle[Int]
val debugClockDomain = Handle[ClockDomain]
val debugReset = Handle[Bool]
val debugAskReset = Handle[() => Unit]
val hardwareBreakpointCount = Handle.sync(0)
val iBus, dBus = Handle[Bmb]
val externalInterrupt = Handle[Bool]
val externalSupervisorInterrupt = Handle[Bool]
val timerInterrupt = Handle[Bool]
val softwareInterrupt = Handle[Bool]
def setTimerInterrupt(that: Handle[Bool]) = Dependable(that, timerInterrupt){timerInterrupt := that}
def setSoftwareInterrupt(that: Handle[Bool]) = Dependable(that, softwareInterrupt){softwareInterrupt := that}
def disableDebug() = {
withDebug.load(DEBUG_NONE)
}
def enableJtag(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd.rework{
this.debugClockDomain.load(debugCd.outputClockDomain)
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
debugAskReset.loadNothing()
withDebug.load(DEBUG_JTAG)
}
def enableJtagInstructionCtrl(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd.rework{
this.debugClockDomain.load(debugCd.outputClockDomain)
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
debugAskReset.loadNothing()
withDebug.load(DEBUG_JTAG_CTRL)
}
def enableDebugBus(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd.rework{
this.debugClockDomain.load(debugCd.outputClockDomain)
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
debugAskReset.loadNothing()
withDebug.load(DEBUG_BUS)
}
val debugBmbAccessSource = Handle[BmbAccessCapabilities]
val debugBmbAccessRequirements = Handle[BmbAccessParameter]
def enableDebugBmb(debugCd : Handle[ClockDomain], resetCd : ClockDomainResetGenerator, mapping : AddressMapping)(implicit debugMaster : BmbImplicitDebugDecoder = null) : Unit = debugCd.on{
this.debugClockDomain.load(debugCd)
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
debugAskReset.loadNothing()
withDebug.load(DEBUG_BMB)
val slaveModel = debugCd on interconnectSmp.addSlave(
accessSource = debugBmbAccessSource,
accessCapabilities = debugBmbAccessSource.derivate(DebugExtensionBus.getBmbAccessParameter(_)),
accessRequirements = debugBmbAccessRequirements,
bus = debugBmb,
mapping = mapping
)
debugBmb.derivatedFrom(debugBmbAccessRequirements)(Bmb(_))
if(debugMaster != null) interconnectSmp.addConnection(debugMaster.bus, debugBmb)
}
val jtag = Handle(withDebug.get == DEBUG_JTAG generate slave(Jtag()))
val jtagInstructionCtrl = withDebug.produce(withDebug.get == DEBUG_JTAG_CTRL generate JtagTapInstructionCtrl())
val debugBus = withDebug.produce(withDebug.get == DEBUG_BUS generate DebugExtensionBus())
val debugBmb = Handle[Bmb]
val jtagClockDomain = Handle[ClockDomain]
val logic = Handle(new Area {
withDebug.get != DEBUG_NONE generate new Area {
config.add(new DebugPlugin(debugClockDomain, hardwareBreakpointCount))
}
val cpu = new VexRiscv(config)
def doExport(value : => Any, postfix : String) = {
sexport(Handle(value).setCompositeName(VexRiscvBmbGenerator.this, postfix))
}
doExport(cpu.plugins.exists(_.isInstanceOf[CfuPlugin]), "cfu")
doExport(cpu.plugins.exists(_.isInstanceOf[FpuPlugin]), "fpu")
for (plugin <- cpu.plugins) plugin match {
case plugin: IBusSimplePlugin => iBus.load(plugin.iBus.toBmb())
case plugin: DBusSimplePlugin => dBus.load(plugin.dBus.toBmb())
case plugin: IBusCachedPlugin => {
iBus.load(plugin.iBus.toBmb())
doExport(plugin.config.wayCount, "icacheWays")
doExport(plugin.config.cacheSize, "icacheSize")
doExport(plugin.config.bytePerLine, "bytesPerLine")
}
case plugin: DBusCachedPlugin => {
dBus.load(plugin.dBus.toBmb())
doExport(plugin.config.wayCount, "dcacheWays")
doExport(plugin.config.cacheSize, "dcacheSize")
doExport(plugin.config.bytePerLine, "bytesPerLine")
}
case plugin: MmuPlugin => {
doExport(true, "mmu")
}
case plugin: StaticMemoryTranslatorPlugin => {
doExport(false, "mmu")
}
case plugin: CsrPlugin => {
doExport(plugin.config.supervisorGen, "supervisor")
externalInterrupt load plugin.externalInterrupt
timerInterrupt load plugin.timerInterrupt
softwareInterrupt load plugin.softwareInterrupt
if (plugin.config.supervisorGen) externalSupervisorInterrupt load plugin.externalInterruptS
}
case plugin: DebugPlugin => plugin.debugClockDomain {
if(debugAskReset.get != null) when(RegNext(plugin.io.resetOut)) {
debugAskReset.get()
} else {
debugReset.load(RegNext(plugin.io.resetOut))
}
withDebug.get match {
case DEBUG_JTAG => jtag <> plugin.io.bus.fromJtag()
case DEBUG_JTAG_CTRL => jtagInstructionCtrl <> plugin.io.bus.fromJtagInstructionCtrl(jtagClockDomain, 0)
case DEBUG_BUS => debugBus <> plugin.io.bus
case DEBUG_BMB => debugBmb >> plugin.io.bus.fromBmb()
}
}
case _ =>
}
})
logic.soon(debugReset)
val parameterGenerator = new Generator {
val iBusParameter, dBusParameter = product[BmbParameter]
dependencies += config
add task {
for (plugin <- config.plugins) plugin match {
case plugin: IBusSimplePlugin => iBusParameter.load(IBusSimpleBus.getBmbParameter())
case plugin: DBusSimplePlugin => dBusParameter.load(DBusSimpleBus.getBmbParameter())
case plugin: IBusCachedPlugin => iBusParameter.load(plugin.config.getBmbParameter())
case plugin: DBusCachedPlugin => dBusParameter.load(plugin.config.getBmbParameter())
case _ =>
}
}
}
val invalidationSource = Handle[BmbInvalidationParameter]
val invalidationRequirements = Handle[BmbInvalidationParameter]
if(interconnectSmp != null){
interconnectSmp.addMaster(accessRequirements = parameterGenerator.iBusParameter.derivate(_.access), bus = iBus)
interconnectSmp.addMaster(
accessRequirements = parameterGenerator.dBusParameter.derivate(_.access),
invalidationSource = invalidationSource,
invalidationCapabilities = invalidationSource,
invalidationRequirements = invalidationRequirements,
bus = dBus
)
}
}
|