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