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