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