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