RealView.py revision 12760:145d5c512cfc
1# Copyright (c) 2009-2018 ARM Limited
2# All rights reserved.
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder.  You may use the software subject to the license
9# terms below provided that you ensure that this notice is replicated
10# unmodified and in its entirety in all distributions of the software,
11# modified or unmodified, in source code or in binary form.
12#
13# Copyright (c) 2006-2007 The Regents of The University of Michigan
14# All rights reserved.
15#
16# Redistribution and use in source and binary forms, with or without
17# modification, are permitted provided that the following conditions are
18# met: redistributions of source code must retain the above copyright
19# notice, this list of conditions and the following disclaimer;
20# redistributions in binary form must reproduce the above copyright
21# notice, this list of conditions and the following disclaimer in the
22# documentation and/or other materials provided with the distribution;
23# neither the name of the copyright holders nor the names of its
24# contributors may be used to endorse or promote products derived from
25# this software without specific prior written permission.
26#
27# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38#
39# Authors: Ali Saidi
40#          Gabe Black
41#          William Wang
42#          Glenn Bergmans
43
44from m5.defines import buildEnv
45from m5.params import *
46from m5.proxy import *
47from m5.util.fdthelper import *
48from ClockDomain import ClockDomain
49from VoltageDomain import VoltageDomain
50from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr, DmaDevice
51from PciHost import *
52from Ethernet import NSGigE, IGbE_igb, IGbE_e1000
53from Ide import *
54from Platform import Platform
55from Terminal import Terminal
56from Uart import Uart
57from SimpleMemory import SimpleMemory
58from Gic import *
59from EnergyCtrl import EnergyCtrl
60from ClockedObject import ClockedObject
61from ClockDomain import SrcClockDomain
62from SubSystem import SubSystem
63from Graphics import ImageFormat
64from ClockedObject import ClockedObject
65from PS2 import *
66from VirtIOMMIO import MmioVirtIO
67
68# Platforms with KVM support should generally use in-kernel GIC
69# emulation. Use a GIC model that automatically switches between
70# gem5's GIC model and KVM's GIC model if KVM is available.
71try:
72    from KvmGic import MuxingKvmGic
73    kvm_gicv2_class = MuxingKvmGic
74except ImportError:
75    # KVM support wasn't compiled into gem5. Fallback to a
76    # software-only GIC.
77    kvm_gicv2_class = Pl390
78    pass
79
80class AmbaPioDevice(BasicPioDevice):
81    type = 'AmbaPioDevice'
82    abstract = True
83    cxx_header = "dev/arm/amba_device.hh"
84    amba_id = Param.UInt32("ID of AMBA device for kernel detection")
85
86class AmbaIntDevice(AmbaPioDevice):
87    type = 'AmbaIntDevice'
88    abstract = True
89    cxx_header = "dev/arm/amba_device.hh"
90    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
91    int_num = Param.UInt32("Interrupt number that connects to GIC")
92    int_delay = Param.Latency("100ns",
93            "Time between action and interrupt generation by device")
94
95class AmbaDmaDevice(DmaDevice):
96    type = 'AmbaDmaDevice'
97    abstract = True
98    cxx_header = "dev/arm/amba_device.hh"
99    pio_addr = Param.Addr("Address for AMBA slave interface")
100    pio_latency = Param.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
101    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
102    int_num = Param.UInt32("Interrupt number that connects to GIC")
103    amba_id = Param.UInt32("ID of AMBA device for kernel detection")
104
105class A9SCU(BasicPioDevice):
106    type = 'A9SCU'
107    cxx_header = "dev/arm/a9scu.hh"
108
109class ArmPciIntRouting(Enum): vals = [
110    'ARM_PCI_INT_STATIC',
111    'ARM_PCI_INT_DEV',
112    'ARM_PCI_INT_PIN',
113    ]
114
115class GenericArmPciHost(GenericPciHost):
116    type = 'GenericArmPciHost'
117    cxx_header = "dev/arm/pci_host.hh"
118
119    int_policy = Param.ArmPciIntRouting("PCI interrupt routing policy")
120    int_base = Param.Unsigned("PCI interrupt base")
121    int_count = Param.Unsigned("Maximum number of interrupts used by this host")
122
123    def generateDeviceTree(self, state):
124        local_state = FdtState(addr_cells=3, size_cells=2, cpu_cells=1)
125        intterrupt_cells = 1
126
127        node = FdtNode("pci")
128
129        if int(self.conf_device_bits) == 8:
130            node.appendCompatible("pci-host-cam-generic")
131        elif int(self.conf_device_bits) == 12:
132            node.appendCompatible("pci-host-ecam-generic")
133        else:
134            m5.fatal("No compatibility string for the set conf_device_width")
135
136        node.append(FdtPropertyStrings("device_type", ["pci"]))
137
138        # Cell sizes of child nodes/peripherals
139        node.append(local_state.addrCellsProperty())
140        node.append(local_state.sizeCellsProperty())
141        node.append(FdtPropertyWords("#interrupt-cells", intterrupt_cells))
142        # PCI address for CPU
143        node.append(FdtPropertyWords("reg",
144            state.addrCells(self.conf_base) +
145            state.sizeCells(self.conf_size) ))
146
147        # Ranges mapping
148        # For now some of this is hard coded, because the PCI module does not
149        # have a proper full understanding of the memory map, but adapting the
150        # PCI module is beyond the scope of what I'm trying to do here.
151        # Values are taken from the VExpress_GEM5_V1 platform.
152        ranges = []
153        # Pio address range
154        ranges += self.pciFdtAddr(space=1, addr=0)
155        ranges += state.addrCells(self.pci_pio_base)
156        ranges += local_state.sizeCells(0x10000)  # Fixed size
157
158        # AXI memory address range
159        ranges += self.pciFdtAddr(space=2, addr=0)
160        ranges += state.addrCells(0x40000000) # Fixed offset
161        ranges += local_state.sizeCells(0x40000000) # Fixed size
162        node.append(FdtPropertyWords("ranges", ranges))
163
164        if str(self.int_policy) == 'ARM_PCI_INT_DEV':
165            int_phandle = state.phandle(self._parent.unproxy(self).gic)
166            # Interrupt mapping
167            interrupts = []
168            for i in range(int(self.int_count)):
169                interrupts += self.pciFdtAddr(device=i, addr=0) + \
170                    [0x0, int_phandle, 0, int(self.int_base) - 32 + i, 1]
171
172            node.append(FdtPropertyWords("interrupt-map", interrupts))
173
174            int_count = int(self.int_count)
175            if int_count & (int_count - 1):
176                fatal("PCI interrupt count should be power of 2")
177
178            intmask = self.pciFdtAddr(device=int_count - 1, addr=0) + [0x0]
179            node.append(FdtPropertyWords("interrupt-map-mask", intmask))
180        else:
181            m5.fatal("Unsupported PCI interrupt policy " +
182                     "for Device Tree generation")
183
184        node.append(FdtProperty("dma-coherent"))
185
186        yield node
187
188class RealViewCtrl(BasicPioDevice):
189    type = 'RealViewCtrl'
190    cxx_header = "dev/arm/rv_ctrl.hh"
191    proc_id0 = Param.UInt32(0x0C000000, "Processor ID, SYS_PROCID")
192    proc_id1 = Param.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
193    idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
194
195    def generateDeviceTree(self, state):
196        node = FdtNode("sysreg@%x" % long(self.pio_addr))
197        node.appendCompatible("arm,vexpress-sysreg")
198        node.append(FdtPropertyWords("reg",
199            state.addrCells(self.pio_addr) +
200            state.sizeCells(0x1000) ))
201        node.append(FdtProperty("gpio-controller"))
202        node.append(FdtPropertyWords("#gpio-cells", [2]))
203        node.appendPhandle(self)
204
205        yield node
206
207class RealViewOsc(ClockDomain):
208    type = 'RealViewOsc'
209    cxx_header = "dev/arm/rv_ctrl.hh"
210
211    parent = Param.RealViewCtrl(Parent.any, "RealView controller")
212
213    # TODO: We currently don't have the notion of a clock source,
214    # which means we have to associate oscillators with a voltage
215    # source.
216    voltage_domain = Param.VoltageDomain(Parent.voltage_domain,
217                                         "Voltage domain")
218
219    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
220    # the individual core/logic tile reference manuals for details
221    # about the site/position/dcc/device allocation.
222    site = Param.UInt8("Board Site")
223    position = Param.UInt8("Position in device stack")
224    dcc = Param.UInt8("Daughterboard Configuration Controller")
225    device = Param.UInt8("Device ID")
226
227    freq = Param.Clock("Default frequency")
228
229    def generateDeviceTree(self, state):
230        phandle = state.phandle(self)
231        node = FdtNode("osc@" + format(long(phandle), 'x'))
232        node.appendCompatible("arm,vexpress-osc")
233        node.append(FdtPropertyWords("arm,vexpress-sysreg,func",
234                                     [0x1, int(self.device)]))
235        node.append(FdtPropertyWords("#clock-cells", [0]))
236        freq = int(1.0/self.freq.value) # Values are stored as a clock period
237        node.append(FdtPropertyWords("freq-range", [freq, freq]))
238        node.append(FdtPropertyStrings("clock-output-names",
239                                       ["oscclk" + str(phandle)]))
240        node.appendPhandle(self)
241        yield node
242
243class RealViewTemperatureSensor(SimObject):
244    type = 'RealViewTemperatureSensor'
245    cxx_header = "dev/arm/rv_ctrl.hh"
246
247    parent = Param.RealViewCtrl(Parent.any, "RealView controller")
248
249    system = Param.System(Parent.any, "system")
250
251    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
252    # the individual core/logic tile reference manuals for details
253    # about the site/position/dcc/device allocation.
254    site = Param.UInt8("Board Site")
255    position = Param.UInt8("Position in device stack")
256    dcc = Param.UInt8("Daughterboard Configuration Controller")
257    device = Param.UInt8("Device ID")
258
259class VExpressMCC(SubSystem):
260    """ARM V2M-P1 Motherboard Configuration Controller
261
262This subsystem describes a subset of the devices that sit behind the
263motherboard configuration controller on the the ARM Motherboard
264Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
265    """
266
267    class Osc(RealViewOsc):
268        site, position, dcc = (0, 0, 0)
269
270    class Temperature(RealViewTemperatureSensor):
271        site, position, dcc = (0, 0, 0)
272
273    osc_mcc = Osc(device=0, freq="50MHz")
274    osc_clcd = Osc(device=1, freq="23.75MHz")
275    osc_peripheral = Osc(device=2, freq="24MHz")
276    osc_system_bus = Osc(device=4, freq="24MHz")
277
278    # See Table 4.19 in ARM DUI 0447J (Motherboard Express uATX TRM).
279    temp_crtl = Temperature(device=0)
280
281    def generateDeviceTree(self, state):
282        node = FdtNode("mcc")
283        node.appendCompatible("arm,vexpress,config-bus")
284        node.append(FdtPropertyWords("arm,vexpress,site", [0]))
285
286        for obj in self._children.values():
287            if issubclass(type(obj), SimObject):
288                node.append(obj.generateDeviceTree(state))
289
290        io_phandle = state.phandle(self.osc_mcc.parent.unproxy(self))
291        node.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle))
292
293        yield node
294
295class CoreTile2A15DCC(SubSystem):
296    """ARM CoreTile Express A15x2 Daughterboard Configuration Controller
297
298This subsystem describes a subset of the devices that sit behind the
299daughterboard configuration controller on a CoreTile Express A15x2. See
300ARM DUI 0604E for details.
301    """
302
303    class Osc(RealViewOsc):
304        site, position, dcc = (1, 0, 0)
305
306    # See Table 2.8 in ARM DUI 0604E (CoreTile Express A15x2 TRM)
307    osc_cpu = Osc(device=0, freq="60MHz")
308    osc_hsbm = Osc(device=4, freq="40MHz")
309    osc_pxl = Osc(device=5, freq="23.75MHz")
310    osc_smb = Osc(device=6, freq="50MHz")
311    osc_sys = Osc(device=7, freq="60MHz")
312    osc_ddr = Osc(device=8, freq="40MHz")
313
314    def generateDeviceTree(self, state):
315        node = FdtNode("dcc")
316        node.appendCompatible("arm,vexpress,config-bus")
317
318        for obj in self._children.values():
319            if isinstance(obj, SimObject):
320                node.append(obj.generateDeviceTree(state))
321
322        io_phandle = state.phandle(self.osc_cpu.parent.unproxy(self))
323        node.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle))
324
325        yield node
326
327class VGic(PioDevice):
328    type = 'VGic'
329    cxx_header = "dev/arm/vgic.hh"
330    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
331    platform = Param.Platform(Parent.any, "Platform this device is part of.")
332    vcpu_addr = Param.Addr(0, "Address for vcpu interfaces")
333    hv_addr = Param.Addr(0, "Address for hv control")
334    pio_delay = Param.Latency('10ns', "Delay for PIO r/w")
335   # The number of list registers is not currently configurable at runtime.
336    ppint = Param.UInt32("HV maintenance interrupt number")
337
338    def generateDeviceTree(self, state):
339        gic = self.gic.unproxy(self)
340
341        node = FdtNode("interrupt-controller")
342        node.appendCompatible(["gem5,gic", "arm,cortex-a15-gic",
343                               "arm,cortex-a9-gic"])
344        node.append(FdtPropertyWords("#interrupt-cells", [3]))
345        node.append(FdtPropertyWords("#address-cells", [0]))
346        node.append(FdtProperty("interrupt-controller"))
347
348        regs = (
349            state.addrCells(gic.dist_addr) +
350            state.sizeCells(0x1000) +
351            state.addrCells(gic.cpu_addr) +
352            state.sizeCells(0x1000) +
353            state.addrCells(self.hv_addr) +
354            state.sizeCells(0x2000) +
355            state.addrCells(self.vcpu_addr) +
356            state.sizeCells(0x2000) )
357
358        node.append(FdtPropertyWords("reg", regs))
359        node.append(FdtPropertyWords("interrupts",
360                                     [1, int(self.ppint)-16, 0xf04]))
361
362        node.appendPhandle(gic)
363
364        yield node
365
366class AmbaFake(AmbaPioDevice):
367    type = 'AmbaFake'
368    cxx_header = "dev/arm/amba_fake.hh"
369    ignore_access = Param.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)")
370    amba_id = 0;
371
372class Pl011(Uart):
373    type = 'Pl011'
374    cxx_header = "dev/arm/pl011.hh"
375    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
376    int_num = Param.UInt32("Interrupt number that connects to GIC")
377    end_on_eot = Param.Bool(False, "End the simulation when a EOT is received on the UART")
378    int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
379
380    def generateDeviceTree(self, state):
381        node = self.generateBasicPioDeviceNode(state, 'uart', self.pio_addr,
382                                               0x1000, [int(self.int_num)])
383        node.appendCompatible(["arm,pl011", "arm,primecell"])
384
385        # Hardcoded reference to the realview platform clocks, because the
386        # clk_domain can only store one clock (i.e. it is not a VectorParam)
387        realview = self._parent.unproxy(self)
388        node.append(FdtPropertyWords("clocks",
389            [state.phandle(realview.mcc.osc_peripheral),
390            state.phandle(realview.dcc.osc_smb)]))
391        node.append(FdtPropertyStrings("clock-names", ["uartclk", "apb_pclk"]))
392        yield node
393
394class Sp804(AmbaPioDevice):
395    type = 'Sp804'
396    cxx_header = "dev/arm/timer_sp804.hh"
397    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
398    int_num0 = Param.UInt32("Interrupt number that connects to GIC")
399    clock0 = Param.Clock('1MHz', "Clock speed of the input")
400    int_num1 = Param.UInt32("Interrupt number that connects to GIC")
401    clock1 = Param.Clock('1MHz', "Clock speed of the input")
402    amba_id = 0x00141804
403
404class A9GlobalTimer(BasicPioDevice):
405    type = 'A9GlobalTimer'
406    cxx_header = "dev/arm/timer_a9global.hh"
407    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
408    int_num = Param.UInt32("Interrrupt number that connects to GIC")
409
410class CpuLocalTimer(BasicPioDevice):
411    type = 'CpuLocalTimer'
412    cxx_header = "dev/arm/timer_cpulocal.hh"
413    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
414    int_num_timer = Param.UInt32("Interrrupt number used per-cpu to GIC")
415    int_num_watchdog = Param.UInt32("Interrupt number for per-cpu watchdog to GIC")
416
417class GenericTimer(ClockedObject):
418    type = 'GenericTimer'
419    cxx_header = "dev/arm/generic_timer.hh"
420    system = Param.ArmSystem(Parent.any, "system")
421    gic = Param.BaseGic(Parent.any, "GIC to use for interrupting")
422    int_phys_s = Param.UInt32("Physical (S) timer interrupt number")
423    int_phys_ns = Param.UInt32("Physical (NS) timer interrupt number")
424    int_virt = Param.UInt32("Virtual timer interrupt number")
425    int_hyp = Param.UInt32("Hypervisor timer interrupt number")
426
427    def generateDeviceTree(self, state):
428        node = FdtNode("timer")
429
430        node.appendCompatible(["arm,cortex-a15-timer",
431                               "arm,armv7-timer",
432                               "arm,armv8-timer"])
433        node.append(FdtPropertyWords("interrupts", [
434            1, int(self.int_phys_s) - 16, 0xf08,
435            1, int(self.int_phys_ns) - 16, 0xf08,
436            1, int(self.int_virt) - 16, 0xf08,
437            1, int(self.int_hyp) - 16, 0xf08,
438        ]))
439        clock = state.phandle(self.clk_domain.unproxy(self))
440        node.append(FdtPropertyWords("clocks", clock))
441
442        yield node
443
444class GenericTimerMem(PioDevice):
445    type = 'GenericTimerMem'
446    cxx_header = "dev/arm/generic_timer.hh"
447    gic = Param.BaseGic(Parent.any, "GIC to use for interrupting")
448
449    base = Param.Addr(0, "Base address")
450
451    int_phys = Param.UInt32("Interrupt number")
452    int_virt = Param.UInt32("Interrupt number")
453
454class PL031(AmbaIntDevice):
455    type = 'PL031'
456    cxx_header = "dev/arm/rtc_pl031.hh"
457    time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)")
458    amba_id = 0x00341031
459
460    def generateDeviceTree(self, state):
461        node = self.generateBasicPioDeviceNode(state, 'rtc', self.pio_addr,
462                                               0x1000, [int(self.int_num)])
463
464        node.appendCompatible(["arm,pl031", "arm,primecell"])
465        clock = state.phandle(self.clk_domain.unproxy(self))
466        node.append(FdtPropertyWords("clocks", clock))
467
468        yield node
469
470class Pl050(AmbaIntDevice):
471    type = 'Pl050'
472    cxx_header = "dev/arm/kmi.hh"
473    amba_id = 0x00141050
474
475    ps2 = Param.PS2Device("PS/2 device")
476
477    def generateDeviceTree(self, state):
478        node = self.generateBasicPioDeviceNode(state, 'kmi', self.pio_addr,
479                                               0x1000, [int(self.int_num)])
480
481        node.appendCompatible(["arm,pl050", "arm,primecell"])
482        clock = state.phandle(self.clk_domain.unproxy(self))
483        node.append(FdtPropertyWords("clocks", clock))
484
485        yield node
486
487class Pl111(AmbaDmaDevice):
488    type = 'Pl111'
489    cxx_header = "dev/arm/pl111.hh"
490    pixel_clock = Param.Clock('24MHz', "Pixel clock")
491    vnc   = Param.VncInput(Parent.any, "Vnc server for remote frame buffer display")
492    amba_id = 0x00141111
493    enable_capture = Param.Bool(True, "capture frame to system.framebuffer.bmp")
494
495class HDLcd(AmbaDmaDevice):
496    type = 'HDLcd'
497    cxx_header = "dev/arm/hdlcd.hh"
498    vnc = Param.VncInput(Parent.any, "Vnc server for remote frame buffer "
499                                     "display")
500    amba_id = 0x00141000
501    workaround_swap_rb = Param.Bool(False, "Workaround incorrect color "
502                                    "selector order in some kernels")
503    workaround_dma_line_count = Param.Bool(True, "Workaround incorrect "
504                                           "DMA line count (off by 1)")
505    enable_capture = Param.Bool(True, "capture frame to "
506                                      "system.framebuffer.{extension}")
507    frame_format = Param.ImageFormat("Auto",
508                                     "image format of the captured frame")
509
510    pixel_buffer_size = Param.MemorySize32("2kB", "Size of address range")
511
512    pxl_clk = Param.ClockDomain("Pixel clock source")
513    pixel_chunk = Param.Unsigned(32, "Number of pixels to handle in one batch")
514    virt_refresh_rate = Param.Frequency("20Hz", "Frame refresh rate "
515                                        "in KVM mode")
516
517    def generateDeviceTree(self, state):
518        # Interrupt number is hardcoded; it is not a property of this class
519        node = self.generateBasicPioDeviceNode(state, 'hdlcd',
520                                               self.pio_addr, 0x1000, [63])
521
522        node.appendCompatible(["arm,hdlcd"])
523        node.append(FdtPropertyWords("clocks", state.phandle(self.pxl_clk)))
524        node.append(FdtPropertyStrings("clock-names", ["pxlclk"]))
525
526        # This driver is disabled by default since the required DT nodes
527        # haven't been standardized yet. To use it,  override this status to
528        # "ok" and add the display configuration nodes required by the driver.
529        # See the driver for more information.
530        node.append(FdtPropertyStrings("status", ["disabled"]))
531
532        yield node
533
534class RealView(Platform):
535    type = 'RealView'
536    cxx_header = "dev/arm/realview.hh"
537    system = Param.System(Parent.any, "system")
538    _mem_regions = [(Addr(0), Addr('256MB'))]
539
540    def _on_chip_devices(self):
541        return []
542
543    def _off_chip_devices(self):
544        return []
545
546    _off_chip_ranges = []
547
548    def _attach_device(self, device, bus, dma_ports=None):
549        if hasattr(device, "pio"):
550            device.pio = bus.master
551        if hasattr(device, "dma"):
552            if dma_ports is None:
553                device.dma = bus.slave
554            else:
555                dma_ports.append(device.dma)
556
557    def _attach_io(self, devices, *args, **kwargs):
558        for d in devices:
559            self._attach_device(d, *args, **kwargs)
560
561    def _attach_clk(self, devices, clkdomain):
562        for d in devices:
563            if hasattr(d, "clk_domain"):
564                d.clk_domain = clkdomain
565
566    def attachPciDevices(self):
567        pass
568
569    def enableMSIX(self):
570        pass
571
572    def onChipIOClkDomain(self, clkdomain):
573        self._attach_clk(self._on_chip_devices(), clkdomain)
574
575    def offChipIOClkDomain(self, clkdomain):
576        self._attach_clk(self._off_chip_devices(), clkdomain)
577
578    def attachOnChipIO(self, bus, bridge=None, *args, **kwargs):
579        self._attach_io(self._on_chip_devices(), bus, *args, **kwargs)
580        if bridge:
581            bridge.ranges = self._off_chip_ranges
582
583    def attachIO(self, *args, **kwargs):
584        self._attach_io(self._off_chip_devices(), *args, **kwargs)
585
586    def setupBootLoader(self, mem_bus, cur_sys, loc):
587        cur_sys.bootmem = SimpleMemory(
588            range = AddrRange('2GB', size = '64MB'),
589            conf_table_reported = False)
590        if mem_bus is not None:
591            cur_sys.bootmem.port = mem_bus.master
592        cur_sys.boot_loader = loc('boot.arm')
593        cur_sys.atags_addr = 0x100
594        cur_sys.load_offset = 0
595
596    def generateDeviceTree(self, state):
597        node = FdtNode("/") # Things in this module need to end up in the root
598        node.append(FdtPropertyWords("interrupt-parent",
599                                     state.phandle(self.gic)))
600
601        for device in [getattr(self, c) for c in self._children]:
602            if issubclass(type(device), SimObject):
603                subnode = device.generateDeviceTree(state)
604                node.append(subnode)
605
606        yield node
607
608    def annotateCpuDeviceNode(self, cpu, state):
609        cpu.append(FdtPropertyStrings("enable-method", "spin-table"))
610        cpu.append(FdtPropertyWords("cpu-release-addr", \
611                                    state.addrCells(0x8000fff8)))
612
613# Reference for memory map and interrupt number
614# RealView Platform Baseboard Explore for Cortex-A9 User Guide(ARM DUI 0440A)
615# Chapter 4: Programmer's Reference
616class RealViewPBX(RealView):
617    uart = Pl011(pio_addr=0x10009000, int_num=44)
618    realview_io = RealViewCtrl(pio_addr=0x10000000)
619    mcc = VExpressMCC()
620    dcc = CoreTile2A15DCC()
621    gic = Pl390()
622    pci_host = GenericPciHost(
623        conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
624        pci_pio_base=0)
625    timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
626    timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
627    global_timer = A9GlobalTimer(int_num=27, pio_addr=0x1f000200)
628    local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30,
629                                    pio_addr=0x1f000600)
630    clcd = Pl111(pio_addr=0x10020000, int_num=55)
631    kmi0   = Pl050(pio_addr=0x10006000, int_num=52, ps2=PS2Keyboard())
632    kmi1   = Pl050(pio_addr=0x10007000, int_num=53, ps2=PS2TouchKit())
633    a9scu  = A9SCU(pio_addr=0x1f000000)
634    cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=7, pci_bus=2,
635                            io_shift = 1, ctrl_offset = 2, Command = 0x1,
636                            BAR0 = 0x18000000, BAR0Size = '16B',
637                            BAR1 = 0x18000100, BAR1Size = '1B',
638                            BAR0LegacyIO = True, BAR1LegacyIO = True)
639
640
641    l2x0_fake     = IsaFake(pio_addr=0x1f002000, pio_size=0xfff)
642    flash_fake    = IsaFake(pio_addr=0x40000000, pio_size=0x20000000,
643                            fake_mem=True)
644    dmac_fake     = AmbaFake(pio_addr=0x10030000)
645    uart1_fake    = AmbaFake(pio_addr=0x1000a000)
646    uart2_fake    = AmbaFake(pio_addr=0x1000b000)
647    uart3_fake    = AmbaFake(pio_addr=0x1000c000)
648    smc_fake      = AmbaFake(pio_addr=0x100e1000)
649    sp810_fake    = AmbaFake(pio_addr=0x10001000, ignore_access=True)
650    watchdog_fake = AmbaFake(pio_addr=0x10010000)
651    gpio0_fake    = AmbaFake(pio_addr=0x10013000)
652    gpio1_fake    = AmbaFake(pio_addr=0x10014000)
653    gpio2_fake    = AmbaFake(pio_addr=0x10015000)
654    ssp_fake      = AmbaFake(pio_addr=0x1000d000)
655    sci_fake      = AmbaFake(pio_addr=0x1000e000)
656    aaci_fake     = AmbaFake(pio_addr=0x10004000)
657    mmc_fake      = AmbaFake(pio_addr=0x10005000)
658    rtc           = PL031(pio_addr=0x10017000, int_num=42)
659    energy_ctrl   = EnergyCtrl(pio_addr=0x1000f000)
660
661
662    # Attach I/O devices that are on chip and also set the appropriate
663    # ranges for the bridge
664    def attachOnChipIO(self, bus, bridge):
665       self.gic.pio = bus.master
666       self.l2x0_fake.pio = bus.master
667       self.a9scu.pio = bus.master
668       self.global_timer.pio = bus.master
669       self.local_cpu_timer.pio = bus.master
670       # Bridge ranges based on excluding what is part of on-chip I/O
671       # (gic, l2x0, a9scu, local_cpu_timer)
672       bridge.ranges = [AddrRange(self.realview_io.pio_addr,
673                                  self.a9scu.pio_addr - 1),
674                        AddrRange(self.flash_fake.pio_addr,
675                                  self.flash_fake.pio_addr + \
676                                  self.flash_fake.pio_size - 1)]
677
678    # Set the clock domain for IO objects that are considered
679    # to be "close" to the cores.
680    def onChipIOClkDomain(self, clkdomain):
681        self.gic.clk_domain             = clkdomain
682        self.l2x0_fake.clk_domain       = clkdomain
683        self.a9scu.clkdomain            = clkdomain
684        self.local_cpu_timer.clk_domain = clkdomain
685
686    # Attach I/O devices to specified bus object.  Can't do this
687    # earlier, since the bus object itself is typically defined at the
688    # System level.
689    def attachIO(self, bus):
690       self.uart.pio          = bus.master
691       self.realview_io.pio   = bus.master
692       self.pci_host.pio      = bus.master
693       self.timer0.pio        = bus.master
694       self.timer1.pio        = bus.master
695       self.clcd.pio          = bus.master
696       self.clcd.dma          = bus.slave
697       self.kmi0.pio          = bus.master
698       self.kmi1.pio          = bus.master
699       self.cf_ctrl.pio       = bus.master
700       self.cf_ctrl.dma       = bus.slave
701       self.dmac_fake.pio     = bus.master
702       self.uart1_fake.pio    = bus.master
703       self.uart2_fake.pio    = bus.master
704       self.uart3_fake.pio    = bus.master
705       self.smc_fake.pio      = bus.master
706       self.sp810_fake.pio    = bus.master
707       self.watchdog_fake.pio = bus.master
708       self.gpio0_fake.pio    = bus.master
709       self.gpio1_fake.pio    = bus.master
710       self.gpio2_fake.pio    = bus.master
711       self.ssp_fake.pio      = bus.master
712       self.sci_fake.pio      = bus.master
713       self.aaci_fake.pio     = bus.master
714       self.mmc_fake.pio      = bus.master
715       self.rtc.pio           = bus.master
716       self.flash_fake.pio    = bus.master
717       self.energy_ctrl.pio   = bus.master
718
719    # Set the clock domain for IO objects that are considered
720    # to be "far" away from the cores.
721    def offChipIOClkDomain(self, clkdomain):
722        self.uart.clk_domain          = clkdomain
723        self.realview_io.clk_domain   = clkdomain
724        self.timer0.clk_domain        = clkdomain
725        self.timer1.clk_domain        = clkdomain
726        self.clcd.clk_domain          = clkdomain
727        self.kmi0.clk_domain          = clkdomain
728        self.kmi1.clk_domain          = clkdomain
729        self.cf_ctrl.clk_domain       = clkdomain
730        self.dmac_fake.clk_domain     = clkdomain
731        self.uart1_fake.clk_domain    = clkdomain
732        self.uart2_fake.clk_domain    = clkdomain
733        self.uart3_fake.clk_domain    = clkdomain
734        self.smc_fake.clk_domain      = clkdomain
735        self.sp810_fake.clk_domain    = clkdomain
736        self.watchdog_fake.clk_domain = clkdomain
737        self.gpio0_fake.clk_domain    = clkdomain
738        self.gpio1_fake.clk_domain    = clkdomain
739        self.gpio2_fake.clk_domain    = clkdomain
740        self.ssp_fake.clk_domain      = clkdomain
741        self.sci_fake.clk_domain      = clkdomain
742        self.aaci_fake.clk_domain     = clkdomain
743        self.mmc_fake.clk_domain      = clkdomain
744        self.rtc.clk_domain           = clkdomain
745        self.flash_fake.clk_domain    = clkdomain
746        self.energy_ctrl.clk_domain   = clkdomain
747
748# Reference for memory map and interrupt number
749# RealView Emulation Baseboard User Guide (ARM DUI 0143B)
750# Chapter 4: Programmer's Reference
751class RealViewEB(RealView):
752    uart = Pl011(pio_addr=0x10009000, int_num=44)
753    realview_io = RealViewCtrl(pio_addr=0x10000000, idreg=0x01400500)
754    mcc = VExpressMCC()
755    dcc = CoreTile2A15DCC()
756    gic = Pl390(dist_addr=0x10041000, cpu_addr=0x10040000)
757    timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
758    timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
759    clcd   = Pl111(pio_addr=0x10020000, int_num=23)
760    kmi0   = Pl050(pio_addr=0x10006000, int_num=20, ps2=PS2Keyboard())
761    kmi1   = Pl050(pio_addr=0x10007000, int_num=21, ps2=PS2TouchKit())
762
763    l2x0_fake     = IsaFake(pio_addr=0x1f002000, pio_size=0xfff, warn_access="1")
764    flash_fake    = IsaFake(pio_addr=0x40000000, pio_size=0x20000000-1,
765                            fake_mem=True)
766    dmac_fake     = AmbaFake(pio_addr=0x10030000)
767    uart1_fake    = AmbaFake(pio_addr=0x1000a000)
768    uart2_fake    = AmbaFake(pio_addr=0x1000b000)
769    uart3_fake    = AmbaFake(pio_addr=0x1000c000)
770    smcreg_fake   = IsaFake(pio_addr=0x10080000, pio_size=0x10000-1)
771    smc_fake      = AmbaFake(pio_addr=0x100e1000)
772    sp810_fake    = AmbaFake(pio_addr=0x10001000, ignore_access=True)
773    watchdog_fake = AmbaFake(pio_addr=0x10010000)
774    gpio0_fake    = AmbaFake(pio_addr=0x10013000)
775    gpio1_fake    = AmbaFake(pio_addr=0x10014000)
776    gpio2_fake    = AmbaFake(pio_addr=0x10015000)
777    ssp_fake      = AmbaFake(pio_addr=0x1000d000)
778    sci_fake      = AmbaFake(pio_addr=0x1000e000)
779    aaci_fake     = AmbaFake(pio_addr=0x10004000)
780    mmc_fake      = AmbaFake(pio_addr=0x10005000)
781    rtc_fake      = AmbaFake(pio_addr=0x10017000, amba_id=0x41031)
782    energy_ctrl   = EnergyCtrl(pio_addr=0x1000f000)
783
784    # Attach I/O devices that are on chip and also set the appropriate
785    # ranges for the bridge
786    def attachOnChipIO(self, bus, bridge):
787       self.gic.pio = bus.master
788       self.l2x0_fake.pio = bus.master
789       # Bridge ranges based on excluding what is part of on-chip I/O
790       # (gic, l2x0)
791       bridge.ranges = [AddrRange(self.realview_io.pio_addr,
792                                  self.gic.cpu_addr - 1),
793                        AddrRange(self.flash_fake.pio_addr, Addr.max)]
794
795    # Set the clock domain for IO objects that are considered
796    # to be "close" to the cores.
797    def onChipIOClkDomain(self, clkdomain):
798        self.gic.clk_domain             = clkdomain
799        self.l2x0_fake.clk_domain       = clkdomain
800
801    # Attach I/O devices to specified bus object.  Can't do this
802    # earlier, since the bus object itself is typically defined at the
803    # System level.
804    def attachIO(self, bus):
805       self.uart.pio          = bus.master
806       self.realview_io.pio   = bus.master
807       self.pci_host.pio      = bus.master
808       self.timer0.pio        = bus.master
809       self.timer1.pio        = bus.master
810       self.clcd.pio          = bus.master
811       self.clcd.dma          = bus.slave
812       self.kmi0.pio          = bus.master
813       self.kmi1.pio          = bus.master
814       self.dmac_fake.pio     = bus.master
815       self.uart1_fake.pio    = bus.master
816       self.uart2_fake.pio    = bus.master
817       self.uart3_fake.pio    = bus.master
818       self.smc_fake.pio      = bus.master
819       self.sp810_fake.pio    = bus.master
820       self.watchdog_fake.pio = bus.master
821       self.gpio0_fake.pio    = bus.master
822       self.gpio1_fake.pio    = bus.master
823       self.gpio2_fake.pio    = bus.master
824       self.ssp_fake.pio      = bus.master
825       self.sci_fake.pio      = bus.master
826       self.aaci_fake.pio     = bus.master
827       self.mmc_fake.pio      = bus.master
828       self.rtc_fake.pio      = bus.master
829       self.flash_fake.pio    = bus.master
830       self.smcreg_fake.pio   = bus.master
831       self.energy_ctrl.pio   = bus.master
832
833    # Set the clock domain for IO objects that are considered
834    # to be "far" away from the cores.
835    def offChipIOClkDomain(self, clkdomain):
836        self.uart.clk_domain          = clkdomain
837        self.realview_io.clk_domain   = clkdomain
838        self.timer0.clk_domain        = clkdomain
839        self.timer1.clk_domain        = clkdomain
840        self.clcd.clk_domain          = clkdomain
841        self.kmi0.clk_domain          = clkdomain
842        self.kmi1.clk_domain          = clkdomain
843        self.dmac_fake.clk_domain     = clkdomain
844        self.uart1_fake.clk_domain    = clkdomain
845        self.uart2_fake.clk_domain    = clkdomain
846        self.uart3_fake.clk_domain    = clkdomain
847        self.smc_fake.clk_domain      = clkdomain
848        self.sp810_fake.clk_domain    = clkdomain
849        self.watchdog_fake.clk_domain = clkdomain
850        self.gpio0_fake.clk_domain    = clkdomain
851        self.gpio1_fake.clk_domain    = clkdomain
852        self.gpio2_fake.clk_domain    = clkdomain
853        self.ssp_fake.clk_domain      = clkdomain
854        self.sci_fake.clk_domain      = clkdomain
855        self.aaci_fake.clk_domain     = clkdomain
856        self.mmc_fake.clk_domain      = clkdomain
857        self.rtc.clk_domain           = clkdomain
858        self.flash_fake.clk_domain    = clkdomain
859        self.smcreg_fake.clk_domain   = clkdomain
860        self.energy_ctrl.clk_domain   = clkdomain
861
862class VExpress_EMM(RealView):
863    _mem_regions = [(Addr('2GB'), Addr('2GB'))]
864
865    # Ranges based on excluding what is part of on-chip I/O (gic,
866    # a9scu)
867    _off_chip_ranges = [AddrRange(0x2F000000, size='16MB'),
868                        AddrRange(0x30000000, size='256MB'),
869                        AddrRange(0x40000000, size='512MB'),
870                        AddrRange(0x18000000, size='64MB'),
871                        AddrRange(0x1C000000, size='64MB')]
872
873    # Platform control device (off-chip)
874    realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
875                               idreg=0x02250000, pio_addr=0x1C010000)
876
877    mcc = VExpressMCC()
878    dcc = CoreTile2A15DCC()
879
880    ### On-chip devices ###
881    gic = Pl390(dist_addr=0x2C001000, cpu_addr=0x2C002000)
882    vgic   = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, ppint=25)
883
884    local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30,
885                                    pio_addr=0x2C080000)
886
887    hdlcd  = HDLcd(pxl_clk=dcc.osc_pxl,
888                   pio_addr=0x2b000000, int_num=117,
889                   workaround_swap_rb=True)
890
891    def _on_chip_devices(self):
892        devices = [
893            self.gic, self.vgic,
894            self.local_cpu_timer
895        ]
896        if hasattr(self, "gicv2m"):
897            devices.append(self.gicv2m)
898        devices.append(self.hdlcd)
899        return devices
900
901    ### Off-chip devices ###
902    uart = Pl011(pio_addr=0x1c090000, int_num=37)
903    pci_host = GenericPciHost(
904        conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
905        pci_pio_base=0)
906
907    generic_timer = GenericTimer(int_phys_s=29, int_phys_ns=30,
908                                 int_virt=27, int_hyp=26)
909    timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
910    timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
911    clcd   = Pl111(pio_addr=0x1c1f0000, int_num=46)
912    kmi0   = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
913    kmi1   = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
914    cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=0, pci_bus=2,
915                            io_shift = 2, ctrl_offset = 2, Command = 0x1,
916                            BAR0 = 0x1C1A0000, BAR0Size = '256B',
917                            BAR1 = 0x1C1A0100, BAR1Size = '4096B',
918                            BAR0LegacyIO = True, BAR1LegacyIO = True)
919
920    vram           = SimpleMemory(range = AddrRange(0x18000000, size='32MB'),
921                                  conf_table_reported = False)
922    rtc            = PL031(pio_addr=0x1C170000, int_num=36)
923
924    l2x0_fake      = IsaFake(pio_addr=0x2C100000, pio_size=0xfff)
925    uart1_fake     = AmbaFake(pio_addr=0x1C0A0000)
926    uart2_fake     = AmbaFake(pio_addr=0x1C0B0000)
927    uart3_fake     = AmbaFake(pio_addr=0x1C0C0000)
928    sp810_fake     = AmbaFake(pio_addr=0x1C020000, ignore_access=True)
929    watchdog_fake  = AmbaFake(pio_addr=0x1C0F0000)
930    aaci_fake      = AmbaFake(pio_addr=0x1C040000)
931    lan_fake       = IsaFake(pio_addr=0x1A000000, pio_size=0xffff)
932    usb_fake       = IsaFake(pio_addr=0x1B000000, pio_size=0x1ffff)
933    mmc_fake       = AmbaFake(pio_addr=0x1c050000)
934    energy_ctrl    = EnergyCtrl(pio_addr=0x1c080000)
935
936    def _off_chip_devices(self):
937        devices = [
938            self.uart,
939            self.realview_io,
940            self.pci_host,
941            self.timer0,
942            self.timer1,
943            self.clcd,
944            self.kmi0,
945            self.kmi1,
946            self.cf_ctrl,
947            self.rtc,
948            self.vram,
949            self.l2x0_fake,
950            self.uart1_fake,
951            self.uart2_fake,
952            self.uart3_fake,
953            self.sp810_fake,
954            self.watchdog_fake,
955            self.aaci_fake,
956            self.lan_fake,
957            self.usb_fake,
958            self.mmc_fake,
959            self.energy_ctrl,
960        ]
961        # Try to attach the I/O if it exists
962        if hasattr(self, "ide"):
963            devices.append(self.ide)
964        if hasattr(self, "ethernet"):
965            devices.append(self.ethernet)
966        return devices
967
968    # Attach any PCI devices that are supported
969    def attachPciDevices(self):
970        self.ethernet = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0,
971                                   InterruptLine=1, InterruptPin=1)
972        self.ide = IdeController(disks = [], pci_bus=0, pci_dev=1, pci_func=0,
973                                 InterruptLine=2, InterruptPin=2)
974
975    def enableMSIX(self):
976        self.gic = Pl390(dist_addr=0x2C001000, cpu_addr=0x2C002000, it_lines=512)
977        self.gicv2m = Gicv2m()
978        self.gicv2m.frames = [Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2C1C0000)]
979
980    def setupBootLoader(self, mem_bus, cur_sys, loc):
981        cur_sys.bootmem = SimpleMemory(range = AddrRange('64MB'),
982                                       conf_table_reported = False)
983        if mem_bus is not None:
984            cur_sys.bootmem.port = mem_bus.master
985        if not cur_sys.boot_loader:
986            cur_sys.boot_loader = loc('boot_emm.arm')
987        cur_sys.atags_addr = 0x8000000
988        cur_sys.load_offset = 0x80000000
989
990class VExpress_EMM64(VExpress_EMM):
991    # Three memory regions are specified totalling 512GB
992    _mem_regions = [(Addr('2GB'), Addr('2GB')), (Addr('34GB'), Addr('30GB')),
993                    (Addr('512GB'), Addr('480GB'))]
994    pci_host = GenericPciHost(
995        conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
996        pci_pio_base=0x2f000000)
997
998    def setupBootLoader(self, mem_bus, cur_sys, loc):
999        cur_sys.bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
1000                                       conf_table_reported=False)
1001        if mem_bus is not None:
1002            cur_sys.bootmem.port = mem_bus.master
1003        if not cur_sys.boot_loader:
1004            cur_sys.boot_loader = loc('boot_emm.arm64')
1005        cur_sys.atags_addr = 0x8000000
1006        cur_sys.load_offset = 0x80000000
1007
1008class VExpress_GEM5_V1_Base(RealView):
1009    """
1010The VExpress gem5 memory map is loosely based on a modified
1011Versatile Express RS1 memory map.
1012
1013The gem5 platform has been designed to implement a subset of the
1014original Versatile Express RS1 memory map. Off-chip peripherals should,
1015when possible, adhere to the Versatile Express memory map. Non-PCI
1016off-chip devices that are gem5-specific should live in the CS5 memory
1017space to avoid conflicts with existing devices that we might want to
1018model in the future. Such devices should normally have interrupts in
1019the gem5-specific SPI range.
1020
1021On-chip peripherals are loosely modeled after the ARM CoreTile Express
1022A15x2 A7x3 memory and interrupt map. In particular, the GIC and
1023Generic Timer have the same interrupt lines and base addresses. Other
1024on-chip devices are gem5 specific.
1025
1026Unlike the original Versatile Express RS2 extended platform, gem5 implements a
1027large contigious DRAM space, without aliases or holes, starting at the
10282GiB boundary. This means that PCI memory is limited to 1GiB.
1029
1030Memory map:
1031   0x00000000-0x03ffffff: Boot memory (CS0)
1032   0x04000000-0x07ffffff: Reserved
1033   0x08000000-0x0bffffff: Reserved (CS0 alias)
1034   0x0c000000-0x0fffffff: Reserved (Off-chip, CS4)
1035   0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
1036       0x10000000-0x1000ffff: gem5 energy controller
1037       0x10010000-0x1001ffff: gem5 pseudo-ops
1038
1039   0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
1040   0x18000000-0x1bffffff: Reserved (Off-chip, Peripherals, CS2)
1041   0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3):
1042       0x1c010000-0x1c01ffff: realview_io (VE system control regs.)
1043       0x1c060000-0x1c06ffff: KMI0 (keyboard)
1044       0x1c070000-0x1c07ffff: KMI1 (mouse)
1045       0x1c090000-0x1c09ffff: UART0
1046       0x1c0a0000-0x1c0affff: UART1 (reserved)
1047       0x1c0b0000-0x1c0bffff: UART2 (reserved)
1048       0x1c0c0000-0x1c0cffff: UART3 (reserved)
1049       0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
1050       0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
1051       0x1c170000-0x1c17ffff: RTC
1052
1053   0x20000000-0x3fffffff: On-chip peripherals:
1054       0x2b000000-0x2b00ffff: HDLCD
1055
1056       0x2c001000-0x2c001fff: GIC (distributor)
1057       0x2c002000-0x2c0020ff: GIC (CPU interface)
1058       0x2c004000-0x2c005fff: vGIC (HV)
1059       0x2c006000-0x2c007fff: vGIC (VCPU)
1060       0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
1061
1062       0x2d000000-0x2d00ffff: GPU (reserved)
1063
1064       0x2f000000-0x2fffffff: PCI IO space
1065       0x30000000-0x3fffffff: PCI config space
1066
1067   0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
1068
1069   0x80000000-X: DRAM
1070
1071Interrupts:
1072      0- 15: Software generated interrupts (SGIs)
1073     16- 31: On-chip private peripherals (PPIs)
1074        25   : vgic
1075        26   : generic_timer (hyp)
1076        27   : generic_timer (virt)
1077        28   : Reserved (Legacy FIQ)
1078        29   : generic_timer (phys, sec)
1079        30   : generic_timer (phys, non-sec)
1080        31   : Reserved (Legacy IRQ)
1081    32- 95: Mother board peripherals (SPIs)
1082        32   : Reserved (SP805)
1083        33   : Reserved (IOFPGA SW int)
1084        34-35: Reserved (SP804)
1085        36   : RTC
1086        37-40: uart0-uart3
1087        41-42: Reserved (PL180)
1088        43   : Reserved (AACI)
1089        44-45: kmi0-kmi1
1090        46   : Reserved (CLCD)
1091        47   : Reserved (Ethernet)
1092        48   : Reserved (USB)
1093    95-255: On-chip interrupt sources (we use these for
1094            gem5-specific devices, SPIs)
1095         74    : VirtIO (gem5/FM extension)
1096         75    : VirtIO (gem5/FM extension)
1097         95    : HDLCD
1098         96- 98: GPU (reserved)
1099        100-103: PCI
1100   256-319: MSI frame 0 (gem5-specific, SPIs)
1101   320-511: Unused
1102
1103    """
1104
1105    # Everything above 2GiB is memory
1106    _mem_regions = [(Addr('2GB'), Addr('510GB'))]
1107
1108    _off_chip_ranges = [
1109        # CS1-CS5
1110        AddrRange(0x0c000000, 0x1fffffff),
1111        # External AXI interface (PCI)
1112        AddrRange(0x2f000000, 0x7fffffff),
1113    ]
1114
1115    # Platform control device (off-chip)
1116    realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
1117                               idreg=0x02250000, pio_addr=0x1c010000)
1118    mcc = VExpressMCC()
1119    dcc = CoreTile2A15DCC()
1120
1121    ### On-chip devices ###
1122    gic = kvm_gicv2_class(dist_addr=0x2c001000, cpu_addr=0x2c002000,
1123                          it_lines=512)
1124    vgic = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, ppint=25)
1125    gicv2m = Gicv2m()
1126    gicv2m.frames = [
1127        Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2c1c0000),
1128    ]
1129
1130    generic_timer = GenericTimer(int_phys_s=29, int_phys_ns=30,
1131                                 int_virt=27, int_hyp=26)
1132
1133    def _on_chip_devices(self):
1134        return [
1135            self.gic, self.vgic, self.gicv2m,
1136            self.generic_timer,
1137        ]
1138
1139    ### Off-chip devices ###
1140    clock24MHz = SrcClockDomain(clock="24MHz",
1141        voltage_domain=VoltageDomain(voltage="3.3V"))
1142
1143    uart0 = Pl011(pio_addr=0x1c090000, int_num=37)
1144
1145    kmi0 = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
1146    kmi1 = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
1147
1148    rtc = PL031(pio_addr=0x1c170000, int_num=36)
1149
1150    ### gem5-specific off-chip devices ###
1151    pci_host = GenericArmPciHost(
1152        conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
1153        pci_pio_base=0x2f000000,
1154        int_policy="ARM_PCI_INT_DEV", int_base=100, int_count=4)
1155
1156    energy_ctrl = EnergyCtrl(pio_addr=0x10000000)
1157
1158    vio = [
1159        MmioVirtIO(pio_addr=0x1c130000, pio_size=0x1000,
1160                   interrupt=ArmSPI(num=74)),
1161        MmioVirtIO(pio_addr=0x1c140000, pio_size=0x1000,
1162                   interrupt=ArmSPI(num=75)),
1163    ]
1164
1165    def _off_chip_devices(self):
1166        return [
1167            self.realview_io,
1168            self.uart0,
1169            self.kmi0,
1170            self.kmi1,
1171            self.rtc,
1172            self.pci_host,
1173            self.energy_ctrl,
1174            self.clock24MHz,
1175            self.vio[0],
1176            self.vio[1],
1177        ]
1178
1179    def attachPciDevice(self, device, *args, **kwargs):
1180        device.host = self.pci_host
1181        self._attach_device(device, *args, **kwargs)
1182
1183    def setupBootLoader(self, mem_bus, cur_sys, loc):
1184        cur_sys.bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
1185                                       conf_table_reported=False)
1186        if mem_bus is not None:
1187            cur_sys.bootmem.port = mem_bus.master
1188        if not cur_sys.boot_loader:
1189            cur_sys.boot_loader = [ loc('boot_emm.arm64'), loc('boot_emm.arm') ]
1190        cur_sys.atags_addr = 0x8000000
1191        cur_sys.load_offset = 0x80000000
1192
1193        #  Setup m5ops. It's technically not a part of the boot
1194        #  loader, but this is the only place we can configure the
1195        #  system.
1196        cur_sys.m5ops_base = 0x10010000
1197
1198    def generateDeviceTree(self, state):
1199        # Generate using standard RealView function
1200        dt = list(super(VExpress_GEM5_V1_Base, self).generateDeviceTree(state))
1201        if len(dt) > 1:
1202            raise Exception("System returned too many DT nodes")
1203        node = dt[0]
1204
1205        node.appendCompatible(["arm,vexpress"])
1206        node.append(FdtPropertyStrings("model", ["V2P-CA15"]))
1207        node.append(FdtPropertyWords("arm,hbi", [0x0]))
1208        node.append(FdtPropertyWords("arm,vexpress,site", [0xf]))
1209
1210        yield node
1211
1212
1213class VExpress_GEM5_V1(VExpress_GEM5_V1_Base):
1214    hdlcd  = HDLcd(pxl_clk=VExpress_GEM5_V1_Base.dcc.osc_pxl,
1215                   pio_addr=0x2b000000, int_num=95)
1216
1217    def _on_chip_devices(self):
1218        return super(VExpress_GEM5_V1,self)._on_chip_devices() + [
1219                self.hdlcd,
1220            ]
1221