BaseCPU.py revision 12563
11689SN/A# Copyright (c) 2012-2013, 2015-2017 ARM Limited
210715SRekai.GonzalezAlberquilla@arm.com# All rights reserved.
39913Ssteve.reinhardt@amd.com#
47854SAli.Saidi@ARM.com# The license below extends only to copyright in the software and shall
57854SAli.Saidi@ARM.com# not be construed as granting a license to any other intellectual
67854SAli.Saidi@ARM.com# property including but not limited to intellectual property relating
77854SAli.Saidi@ARM.com# to a hardware implementation of the functionality of the software
87854SAli.Saidi@ARM.com# licensed hereunder.  You may use the software subject to the license
97854SAli.Saidi@ARM.com# terms below provided that you ensure that this notice is replicated
107854SAli.Saidi@ARM.com# unmodified and in its entirety in all distributions of the software,
117854SAli.Saidi@ARM.com# modified or unmodified, in source code or in binary form.
127854SAli.Saidi@ARM.com#
137854SAli.Saidi@ARM.com# Copyright (c) 2005-2008 The Regents of The University of Michigan
147854SAli.Saidi@ARM.com# Copyright (c) 2011 Regents of the University of California
152329SN/A# All rights reserved.
161689SN/A#
171689SN/A# Redistribution and use in source and binary forms, with or without
181689SN/A# modification, are permitted provided that the following conditions are
191689SN/A# met: redistributions of source code must retain the above copyright
201689SN/A# notice, this list of conditions and the following disclaimer;
211689SN/A# redistributions in binary form must reproduce the above copyright
221689SN/A# notice, this list of conditions and the following disclaimer in the
231689SN/A# documentation and/or other materials provided with the distribution;
241689SN/A# neither the name of the copyright holders nor the names of its
251689SN/A# contributors may be used to endorse or promote products derived from
261689SN/A# this software without specific prior written permission.
271689SN/A#
281689SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
291689SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
301689SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
311689SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
321689SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
331689SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
341689SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
351689SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
361689SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
371689SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
381689SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
391689SN/A#
402665Ssaidi@eecs.umich.edu# Authors: Nathan Binkert
412665Ssaidi@eecs.umich.edu#          Rick Strong
422935Sksewell@umich.edu#          Andreas Hansson
431689SN/A#          Glenn Bergmans
441689SN/A
459944Smatt.horsnell@ARM.comfrom __future__ import print_function
469944Smatt.horsnell@ARM.com
479944Smatt.horsnell@ARM.comimport sys
481060SN/A
491060SN/Afrom m5.SimObject import *
503773Sgblack@eecs.umich.edufrom m5.defines import buildEnv
516329Sgblack@eecs.umich.edufrom m5.params import *
526658Snate@binkert.orgfrom m5.proxy import *
531717SN/Afrom m5.util.fdthelper import *
549913Ssteve.reinhardt@amd.com
558232Snate@binkert.orgfrom XBar import L2XBar
568232Snate@binkert.orgfrom InstTracer import InstTracer
579527SMatt.Horsnell@arm.comfrom CPUTracers import ExeTracer
585529Snate@binkert.orgfrom MemObject import MemObject
591060SN/Afrom SubSystem import SubSystem
606221Snate@binkert.orgfrom ClockDomain import *
616221Snate@binkert.orgfrom Platform import Platform
621061SN/A
635529Snate@binkert.orgdefault_tracer = ExeTracer()
644329Sktlim@umich.edu
654329Sktlim@umich.eduif buildEnv['TARGET_ISA'] == 'alpha':
662292SN/A    from AlphaTLB import AlphaDTB as ArchDTB, AlphaITB as ArchITB
672292SN/A    from AlphaInterrupts import AlphaInterrupts
682292SN/A    from AlphaISA import AlphaISA
692292SN/A    default_isa_class = AlphaISA
705529Snate@binkert.orgelif buildEnv['TARGET_ISA'] == 'sparc':
719920Syasuko.eckert@amd.com    from SparcTLB import SparcTLB as ArchDTB, SparcTLB as ArchITB
729920Syasuko.eckert@amd.com    from SparcInterrupts import SparcInterrupts
731060SN/A    from SparcISA import SparcISA
7410172Sdam.sunwoo@arm.com    default_isa_class = SparcISA
7510172Sdam.sunwoo@arm.comelif buildEnv['TARGET_ISA'] == 'x86':
7610172Sdam.sunwoo@arm.com    from X86TLB import X86TLB as ArchDTB, X86TLB as ArchITB
7710172Sdam.sunwoo@arm.com    from X86LocalApic import X86LocalApic
7810172Sdam.sunwoo@arm.com    from X86ISA import X86ISA
792292SN/A    default_isa_class = X86ISA
8010328Smitch.hayenga@arm.comelif buildEnv['TARGET_ISA'] == 'mips':
812292SN/A    from MipsTLB import MipsTLB as ArchDTB, MipsTLB as ArchITB
822292SN/A    from MipsInterrupts import MipsInterrupts
832292SN/A    from MipsISA import MipsISA
842292SN/A    default_isa_class = MipsISA
852292SN/Aelif buildEnv['TARGET_ISA'] == 'arm':
862292SN/A    from ArmTLB import ArmTLB as ArchDTB, ArmTLB as ArchITB
872292SN/A    from ArmTLB import ArmStage2IMMU, ArmStage2DMMU
881060SN/A    from ArmInterrupts import ArmInterrupts
891060SN/A    from ArmISA import ArmISA
901061SN/A    default_isa_class = ArmISA
911060SN/Aelif buildEnv['TARGET_ISA'] == 'power':
922292SN/A    from PowerTLB import PowerTLB as ArchDTB, PowerTLB as ArchITB
931062SN/A    from PowerInterrupts import PowerInterrupts
941062SN/A    from PowerISA import PowerISA
958240Snate@binkert.org    default_isa_class = PowerISA
961062SN/Aelif buildEnv['TARGET_ISA'] == 'riscv':
971062SN/A    from RiscvTLB import RiscvTLB as ArchDTB, RiscvTLB as ArchITB
981062SN/A    from RiscvInterrupts import RiscvInterrupts
998240Snate@binkert.org    from RiscvISA import RiscvISA
1001062SN/A    default_isa_class = RiscvISA
1011062SN/A
1021062SN/Aclass BaseCPU(MemObject):
1038240Snate@binkert.org    type = 'BaseCPU'
1041062SN/A    abstract = True
1051062SN/A    cxx_header = "cpu/base.hh"
1062301SN/A
1078240Snate@binkert.org    cxx_exports = [
1082301SN/A        PyBindMethod("switchOut"),
1092301SN/A        PyBindMethod("takeOverFrom"),
1102292SN/A        PyBindMethod("switchedOut"),
1118240Snate@binkert.org        PyBindMethod("flushTLBs"),
1122292SN/A        PyBindMethod("totalInsts"),
1132292SN/A        PyBindMethod("scheduleInstStop"),
1141062SN/A        PyBindMethod("scheduleLoadStop"),
1158240Snate@binkert.org        PyBindMethod("getCurrentInstCount"),
1161062SN/A    ]
1171062SN/A
1181062SN/A    @classmethod
1198240Snate@binkert.org    def memory_mode(cls):
1201062SN/A        """Which memory mode does this CPU require?"""
1211062SN/A        return 'invalid'
1221062SN/A
1238240Snate@binkert.org    @classmethod
1241062SN/A    def require_caches(cls):
1251062SN/A        """Does the CPU model require caches?
1261062SN/A
1278240Snate@binkert.org        Some CPU models might make assumptions that require them to
1282292SN/A        have caches.
1291062SN/A        """
1301062SN/A        return False
1318240Snate@binkert.org
1322292SN/A    @classmethod
1331062SN/A    def support_take_over(cls):
13410239Sbinhpham@cs.rutgers.edu        """Does the CPU model support CPU takeOverFrom?"""
13510239Sbinhpham@cs.rutgers.edu        return False
13610239Sbinhpham@cs.rutgers.edu
13710239Sbinhpham@cs.rutgers.edu    def takeOverFrom(self, old_cpu):
13810239Sbinhpham@cs.rutgers.edu        self._ccObject.takeOverFrom(old_cpu._ccObject)
13910239Sbinhpham@cs.rutgers.edu
14010239Sbinhpham@cs.rutgers.edu
14110239Sbinhpham@cs.rutgers.edu    system = Param.System(Parent.any, "system object")
1421062SN/A    cpu_id = Param.Int(-1, "CPU identifier")
1438240Snate@binkert.org    socket_id = Param.Unsigned(0, "Physical Socket identifier")
1441062SN/A    numThreads = Param.Unsigned(1, "number of HW thread contexts")
1451062SN/A    pwr_gating_latency = Param.Cycles(300,
1461062SN/A        "Latency to enter power gating state when all contexts are suspended")
1478240Snate@binkert.org
1481062SN/A    power_gating_on_idle = Param.Bool(False, "Control whether the core goes "\
1491062SN/A        "to the OFF power state after all thread are disabled for "\
1501062SN/A        "pwr_gating_latency cycles")
1518240Snate@binkert.org
1521062SN/A    function_trace = Param.Bool(False, "Enable function trace")
1531062SN/A    function_trace_start = Param.Tick(0, "Tick to start function trace")
1541062SN/A
1558240Snate@binkert.org    checker = Param.BaseCPU(NULL, "checker CPU")
1561062SN/A
1571062SN/A    syscallRetryLatency = Param.Cycles(10000, "Cycles to wait until retry")
1581062SN/A
1598240Snate@binkert.org    do_checkpoint_insts = Param.Bool(True,
1601062SN/A        "enable checkpoint pseudo instructions")
1611062SN/A    do_statistics_insts = Param.Bool(True,
1622301SN/A        "enable statistics pseudo instructions")
1638240Snate@binkert.org
1642301SN/A    profile = Param.Latency('0ns', "trace the kernel stack")
1652301SN/A    do_quiesce = Param.Bool(True, "enable quiesce instructions")
1662301SN/A
1672301SN/A    wait_for_remote_gdb = Param.Bool(False,
1688240Snate@binkert.org        "Wait for a remote GDB connection");
1692301SN/A
1702301SN/A    workload = VectorParam.Process([], "processes to run")
1712301SN/A
1722307SN/A    dtb = Param.BaseTLB(ArchDTB(), "Data TLB")
1738240Snate@binkert.org    itb = Param.BaseTLB(ArchITB(), "Instruction TLB")
1742307SN/A    if buildEnv['TARGET_ISA'] == 'sparc':
1752307SN/A        interrupts = VectorParam.SparcInterrupts(
1762307SN/A                [], "Interrupt Controller")
1777897Shestness@cs.utexas.edu        isa = VectorParam.SparcISA([], "ISA instance")
1788240Snate@binkert.org    elif buildEnv['TARGET_ISA'] == 'alpha':
1797897Shestness@cs.utexas.edu        interrupts = VectorParam.AlphaInterrupts(
1807897Shestness@cs.utexas.edu                [], "Interrupt Controller")
1817897Shestness@cs.utexas.edu        isa = VectorParam.AlphaISA([], "ISA instance")
1828240Snate@binkert.org    elif buildEnv['TARGET_ISA'] == 'x86':
1837897Shestness@cs.utexas.edu        interrupts = VectorParam.X86LocalApic([], "Interrupt Controller")
1847897Shestness@cs.utexas.edu        isa = VectorParam.X86ISA([], "ISA instance")
1851062SN/A    elif buildEnv['TARGET_ISA'] == 'mips':
1861062SN/A        interrupts = VectorParam.MipsInterrupts(
1871062SN/A                [], "Interrupt Controller")
1881062SN/A        isa = VectorParam.MipsISA([], "ISA instance")
1892292SN/A    elif buildEnv['TARGET_ISA'] == 'arm':
1901060SN/A        istage2_mmu = Param.ArmStage2MMU(ArmStage2IMMU(), "Stage 2 trans")
1911060SN/A        dstage2_mmu = Param.ArmStage2MMU(ArmStage2DMMU(), "Stage 2 trans")
1921060SN/A        interrupts = VectorParam.ArmInterrupts(
1931060SN/A                [], "Interrupt Controller")
1941060SN/A        isa = VectorParam.ArmISA([], "ISA instance")
1951060SN/A    elif buildEnv['TARGET_ISA'] == 'power':
1961060SN/A        UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
1971060SN/A        interrupts = VectorParam.PowerInterrupts(
1981060SN/A                [], "Interrupt Controller")
1991060SN/A        isa = VectorParam.PowerISA([], "ISA instance")
2001060SN/A    elif buildEnv['TARGET_ISA'] == 'riscv':
2011060SN/A        interrupts = VectorParam.RiscvInterrupts(
2021060SN/A                [], "Interrupt Controller")
2031061SN/A        isa = VectorParam.RiscvISA([], "ISA instance")
2041060SN/A    else:
2052292SN/A        print("Don't know what TLB to use for ISA %s" %
2061060SN/A              buildEnv['TARGET_ISA'])
2071060SN/A        sys.exit(1)
2081060SN/A
2091060SN/A    max_insts_all_threads = Param.Counter(0,
2101060SN/A        "terminate when all threads have reached this inst count")
2111060SN/A    max_insts_any_thread = Param.Counter(0,
2121060SN/A        "terminate when any thread reaches this inst count")
2131061SN/A    simpoint_start_insts = VectorParam.Counter([],
2141060SN/A        "starting instruction counts of simpoints")
2152292SN/A    max_loads_all_threads = Param.Counter(0,
2161060SN/A        "terminate when all threads have reached this load count")
2171060SN/A    max_loads_any_thread = Param.Counter(0,
2181060SN/A        "terminate when any thread reaches this load count")
2191060SN/A    progress_interval = Param.Frequency('0Hz',
2201060SN/A        "frequency to print out the progress message")
2211060SN/A
2221060SN/A    switched_out = Param.Bool(False,
2231061SN/A        "Leave the CPU switched out after startup (used when switching " \
2241060SN/A        "between CPU models)")
2259427SAndreas.Sandberg@ARM.com
2261060SN/A    tracer = Param.InstTracer(default_tracer, "Instruction tracer")
2279444SAndreas.Sandberg@ARM.com
2289444SAndreas.Sandberg@ARM.com    icache_port = MasterPort("Instruction Port")
2299444SAndreas.Sandberg@ARM.com    dcache_port = MasterPort("Data Port")
2309444SAndreas.Sandberg@ARM.com    _cached_ports = ['icache_port', 'dcache_port']
2319444SAndreas.Sandberg@ARM.com
2329444SAndreas.Sandberg@ARM.com    if buildEnv['TARGET_ISA'] in ['x86', 'arm']:
2339444SAndreas.Sandberg@ARM.com        _cached_ports += ["itb.walker.port", "dtb.walker.port"]
2349444SAndreas.Sandberg@ARM.com
2359444SAndreas.Sandberg@ARM.com    _uncached_slave_ports = []
2369444SAndreas.Sandberg@ARM.com    _uncached_master_ports = []
2379444SAndreas.Sandberg@ARM.com    if buildEnv['TARGET_ISA'] == 'x86':
2389444SAndreas.Sandberg@ARM.com        _uncached_slave_ports += ["interrupts[0].pio",
2392329SN/A                                  "interrupts[0].int_slave"]
2406221Snate@binkert.org        _uncached_master_ports += ["interrupts[0].int_master"]
2419444SAndreas.Sandberg@ARM.com
2429444SAndreas.Sandberg@ARM.com    def createInterruptController(self):
2432292SN/A        if buildEnv['TARGET_ISA'] == 'sparc':
24410239Sbinhpham@cs.rutgers.edu            self.interrupts = [SparcInterrupts() for i in xrange(self.numThreads)]
24510239Sbinhpham@cs.rutgers.edu        elif buildEnv['TARGET_ISA'] == 'alpha':
2462292SN/A            self.interrupts = [AlphaInterrupts() for i in xrange(self.numThreads)]
2472292SN/A        elif buildEnv['TARGET_ISA'] == 'x86':
2489444SAndreas.Sandberg@ARM.com            self.apic_clk_domain = DerivedClockDomain(clk_domain =
2499444SAndreas.Sandberg@ARM.com                                                      Parent.clk_domain,
2509444SAndreas.Sandberg@ARM.com                                                      clk_divider = 16)
2519444SAndreas.Sandberg@ARM.com            self.interrupts = [X86LocalApic(clk_domain = self.apic_clk_domain,
2529444SAndreas.Sandberg@ARM.com                                           pio_addr=0x2000000000000000)
25310239Sbinhpham@cs.rutgers.edu                               for i in xrange(self.numThreads)]
25410239Sbinhpham@cs.rutgers.edu            _localApic = self.interrupts
2559444SAndreas.Sandberg@ARM.com        elif buildEnv['TARGET_ISA'] == 'mips':
2569444SAndreas.Sandberg@ARM.com            self.interrupts = [MipsInterrupts() for i in xrange(self.numThreads)]
2572292SN/A        elif buildEnv['TARGET_ISA'] == 'arm':
2581060SN/A            self.interrupts = [ArmInterrupts() for i in xrange(self.numThreads)]
2591060SN/A        elif buildEnv['TARGET_ISA'] == 'power':
2602292SN/A            self.interrupts = [PowerInterrupts() for i in xrange(self.numThreads)]
2612292SN/A        elif buildEnv['TARGET_ISA'] == 'riscv':
2626221Snate@binkert.org            self.interrupts = \
2632292SN/A                [RiscvInterrupts() for i in xrange(self.numThreads)]
2642292SN/A        else:
2652292SN/A            print("Don't know what Interrupt Controller to use for ISA %s" %
2662292SN/A                  buildEnv['TARGET_ISA'])
2672292SN/A            sys.exit(1)
2681061SN/A
2691060SN/A    def connectCachedPorts(self, bus):
2702292SN/A        for p in self._cached_ports:
2711060SN/A            exec('self.%s = bus.slave' % p)
2726221Snate@binkert.org
2736221Snate@binkert.org    def connectUncachedPorts(self, bus):
2741060SN/A        for p in self._uncached_slave_ports:
2751060SN/A            exec('self.%s = bus.master' % p)
2761061SN/A        for p in self._uncached_master_ports:
2771060SN/A            exec('self.%s = bus.slave' % p)
2782292SN/A
2791060SN/A    def connectAllPorts(self, cached_bus, uncached_bus = None):
2802292SN/A        self.connectCachedPorts(cached_bus)
2812292SN/A        if not uncached_bus:
2821060SN/A            uncached_bus = cached_bus
2832292SN/A        self.connectUncachedPorts(uncached_bus)
2842292SN/A
2852292SN/A    def addPrivateSplitL1Caches(self, ic, dc, iwc = None, dwc = None):
2862292SN/A        self.icache = ic
2872292SN/A        self.dcache = dc
2881060SN/A        self.icache_port = ic.cpu_side
2891060SN/A        self.dcache_port = dc.cpu_side
2901061SN/A        self._cached_ports = ['icache.mem_side', 'dcache.mem_side']
2912863Sktlim@umich.edu        if buildEnv['TARGET_ISA'] in ['x86', 'arm']:
2929444SAndreas.Sandberg@ARM.com            if iwc and dwc:
2931060SN/A                self.itb_walker_cache = iwc
2949444SAndreas.Sandberg@ARM.com                self.dtb_walker_cache = dwc
2959444SAndreas.Sandberg@ARM.com                self.itb.walker.port = iwc.cpu_side
2969444SAndreas.Sandberg@ARM.com                self.dtb.walker.port = dwc.cpu_side
2979444SAndreas.Sandberg@ARM.com                self._cached_ports += ["itb_walker_cache.mem_side", \
2989444SAndreas.Sandberg@ARM.com                                       "dtb_walker_cache.mem_side"]
2999444SAndreas.Sandberg@ARM.com            else:
3009444SAndreas.Sandberg@ARM.com                self._cached_ports += ["itb.walker.port", "dtb.walker.port"]
3012863Sktlim@umich.edu
3022316SN/A            # Checker doesn't need its own tlb caches because it does
3031060SN/A            # functional accesses only
3042316SN/A            if self.checker != NULL:
3052316SN/A                self._cached_ports += ["checker.itb.walker.port", \
3062307SN/A                                       "checker.dtb.walker.port"]
3071060SN/A
3089444SAndreas.Sandberg@ARM.com    def addTwoLevelCacheHierarchy(self, ic, dc, l2c, iwc=None, dwc=None,
3099444SAndreas.Sandberg@ARM.com                                  xbar=None):
3101060SN/A        self.addPrivateSplitL1Caches(ic, dc, iwc, dwc)
3119444SAndreas.Sandberg@ARM.com        self.toL2Bus = xbar if xbar else L2XBar()
3129444SAndreas.Sandberg@ARM.com        self.connectCachedPorts(self.toL2Bus)
3139444SAndreas.Sandberg@ARM.com        self.l2cache = l2c
3149444SAndreas.Sandberg@ARM.com        self.toL2Bus.master = self.l2cache.cpu_side
3156221Snate@binkert.org        self._cached_ports = ['l2cache.mem_side']
3169444SAndreas.Sandberg@ARM.com
3179444SAndreas.Sandberg@ARM.com    def createThreads(self):
3189444SAndreas.Sandberg@ARM.com        # If no ISAs have been created, assume that the user wants the
3199444SAndreas.Sandberg@ARM.com        # default ISA.
3202307SN/A        if len(self.isa) == 0:
3212307SN/A            self.isa = [ default_isa_class() for i in xrange(self.numThreads) ]
3222307SN/A        else:
3232307SN/A            if len(self.isa) != int(self.numThreads):
3242307SN/A                raise RuntimeError("Number of ISA instances doesn't "
3256221Snate@binkert.org                                   "match thread count")
3261858SN/A        if self.checker != NULL:
3272292SN/A            self.checker.createThreads()
3281858SN/A
3292292SN/A    def addCheckerCpu(self):
3302292SN/A        pass
3312292SN/A
3322292SN/A    def createPhandleKey(self, thread):
3333788Sgblack@eecs.umich.edu        # This method creates a unique key for this cpu as a function of a
3342292SN/A        # certain thread
3352698Sktlim@umich.edu        return 'CPU-%d-%d-%d' % (self.socket_id, self.cpu_id, thread)
3363788Sgblack@eecs.umich.edu
3372301SN/A    #Generate simple CPU Device Tree structure
3383788Sgblack@eecs.umich.edu    def generateDeviceTree(self, state):
3393788Sgblack@eecs.umich.edu        """Generate cpu nodes for each thread and the corresponding part of the
3403788Sgblack@eecs.umich.edu        cpu-map node. Note that this implementation does not support clusters
3413788Sgblack@eecs.umich.edu        of clusters. Note that GEM5 is not compatible with the official way of
3423788Sgblack@eecs.umich.edu        numbering cores as defined in the Device Tree documentation. Where the
3433788Sgblack@eecs.umich.edu        cpu_id needs to reset to 0 for each cluster by specification, GEM5
3443788Sgblack@eecs.umich.edu        expects the cpu_id to be globally unique and incremental. This
3453788Sgblack@eecs.umich.edu        generated node adheres the GEM5 way of doing things."""
3463788Sgblack@eecs.umich.edu        if bool(self.switched_out):
3473788Sgblack@eecs.umich.edu            return
3483788Sgblack@eecs.umich.edu
3492292SN/A        cpus_node = FdtNode('cpus')
3502292SN/A        cpus_node.append(state.CPUCellsProperty())
3512292SN/A        #Special size override of 0
3522292SN/A        cpus_node.append(FdtPropertyWords('#size-cells', [0]))
3532292SN/A
3542329SN/A        # Generate cpu nodes
3552292SN/A        for i in range(int(self.numThreads)):
3562935Sksewell@umich.edu            reg = (int(self.socket_id)<<8) + int(self.cpu_id) + i
3572935Sksewell@umich.edu            node = FdtNode("cpu@%x" % reg)
3582731Sktlim@umich.edu            node.append(FdtPropertyStrings("device_type", "cpu"))
3592292SN/A            node.appendCompatible(["gem5,arm-cpu"])
3602292SN/A            node.append(FdtPropertyWords("reg", state.CPUAddrCells(reg)))
3612935Sksewell@umich.edu            platform, found = self.system.unproxy(self).find_any(Platform)
3622292SN/A            if found:
3632292SN/A                platform.annotateCpuDeviceNode(node, state)
3642935Sksewell@umich.edu            else:
3654632Sgblack@eecs.umich.edu                warn("Platform not found for device tree generation; " \
3663093Sksewell@umich.edu                     "system or multiple CPUs may not start")
3672292SN/A
3682292SN/A            freq = round(self.clk_domain.unproxy(self).clock[0].frequency)
3693093Sksewell@umich.edu            node.append(FdtPropertyWords("clock-frequency", freq))
3704632Sgblack@eecs.umich.edu
3712935Sksewell@umich.edu            # Unique key for this CPU
3722292SN/A            phandle_key = self.createPhandleKey(i)
3732292SN/A            node.appendPhandle(phandle_key)
3742292SN/A            cpus_node.append(node)
3752292SN/A
3762292SN/A        yield cpus_node
3772292SN/A