BaseCPU.py revision 14147:638fe1150005
14486Sbinkertn@umich.edu# Copyright (c) 2012-2013, 2015-2017 ARM Limited
24486Sbinkertn@umich.edu# All rights reserved.
34486Sbinkertn@umich.edu#
44486Sbinkertn@umich.edu# The license below extends only to copyright in the software and shall
54486Sbinkertn@umich.edu# not be construed as granting a license to any other intellectual
64486Sbinkertn@umich.edu# property including but not limited to intellectual property relating
74486Sbinkertn@umich.edu# to a hardware implementation of the functionality of the software
84486Sbinkertn@umich.edu# licensed hereunder.  You may use the software subject to the license
94486Sbinkertn@umich.edu# terms below provided that you ensure that this notice is replicated
104486Sbinkertn@umich.edu# unmodified and in its entirety in all distributions of the software,
114486Sbinkertn@umich.edu# modified or unmodified, in source code or in binary form.
124486Sbinkertn@umich.edu#
134486Sbinkertn@umich.edu# Copyright (c) 2005-2008 The Regents of The University of Michigan
144486Sbinkertn@umich.edu# Copyright (c) 2011 Regents of the University of California
154486Sbinkertn@umich.edu# All rights reserved.
164486Sbinkertn@umich.edu#
174486Sbinkertn@umich.edu# Redistribution and use in source and binary forms, with or without
184486Sbinkertn@umich.edu# modification, are permitted provided that the following conditions are
194486Sbinkertn@umich.edu# met: redistributions of source code must retain the above copyright
204486Sbinkertn@umich.edu# notice, this list of conditions and the following disclaimer;
214486Sbinkertn@umich.edu# redistributions in binary form must reproduce the above copyright
224486Sbinkertn@umich.edu# notice, this list of conditions and the following disclaimer in the
234486Sbinkertn@umich.edu# documentation and/or other materials provided with the distribution;
244486Sbinkertn@umich.edu# neither the name of the copyright holders nor the names of its
254486Sbinkertn@umich.edu# contributors may be used to endorse or promote products derived from
264486Sbinkertn@umich.edu# this software without specific prior written permission.
274486Sbinkertn@umich.edu#
284486Sbinkertn@umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
296654Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
303102SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
313102SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
321681SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
333223SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
348887Sgeoffrey.blake@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
354486Sbinkertn@umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362817SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372817SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
389341SAndreas.Sandberg@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
399341SAndreas.Sandberg@arm.com#
402932SN/A# Authors: Nathan Binkert
411681SN/A#          Rick Strong
424597Sbinkertn@umich.edu#          Andreas Hansson
431681SN/A#          Glenn Bergmans
449184Sandreas.hansson@arm.com
459184Sandreas.hansson@arm.comfrom __future__ import print_function
469184Sandreas.hansson@arm.com
479184Sandreas.hansson@arm.comimport sys
489184Sandreas.hansson@arm.com
492932SN/Afrom m5.SimObject import *
502932SN/Afrom m5.defines import buildEnv
519184Sandreas.hansson@arm.comfrom m5.params import *
529184Sandreas.hansson@arm.comfrom m5.proxy import *
539184Sandreas.hansson@arm.comfrom m5.util.fdthelper import *
549184Sandreas.hansson@arm.com
559184Sandreas.hansson@arm.comfrom m5.objects.ClockedObject import ClockedObject
562932SN/Afrom m5.objects.XBar import L2XBar
571681SN/Afrom m5.objects.InstTracer import InstTracer
589184Sandreas.hansson@arm.comfrom m5.objects.CPUTracers import ExeTracer
599184Sandreas.hansson@arm.comfrom m5.objects.SubSystem import SubSystem
609184Sandreas.hansson@arm.comfrom m5.objects.ClockDomain import *
619184Sandreas.hansson@arm.comfrom m5.objects.Platform import Platform
622932SN/A
631681SN/Adefault_tracer = ExeTracer()
649184Sandreas.hansson@arm.com
652932SN/Aif buildEnv['TARGET_ISA'] == 'alpha':
669184Sandreas.hansson@arm.com    from m5.objects.AlphaTLB import AlphaDTB as ArchDTB, AlphaITB as ArchITB
672932SN/A    from m5.objects.AlphaInterrupts import AlphaInterrupts as ArchInterrupts
689184Sandreas.hansson@arm.com    from m5.objects.AlphaISA import AlphaISA as ArchISA
692932SN/A    ArchInterruptsParam = VectorParam.AlphaInterrupts
702932SN/A    ArchISAsParam = VectorParam.AlphaISA
712932SN/Aelif buildEnv['TARGET_ISA'] == 'sparc':
722932SN/A    from m5.objects.SparcTLB import SparcTLB as ArchDTB, SparcTLB as ArchITB
732932SN/A    from m5.objects.SparcInterrupts import SparcInterrupts as ArchInterrupts
743223SN/A    from m5.objects.SparcISA import SparcISA as ArchISA
752932SN/A    ArchInterruptsParam = VectorParam.SparcInterrupts
769184Sandreas.hansson@arm.com    ArchISAsParam = VectorParam.SparcISA
771681SN/Aelif buildEnv['TARGET_ISA'] == 'x86':
789184Sandreas.hansson@arm.com    from m5.objects.X86TLB import X86TLB as ArchDTB, X86TLB as ArchITB
792932SN/A    from m5.objects.X86LocalApic import X86LocalApic as ArchInterrupts
802932SN/A    from m5.objects.X86ISA import X86ISA as ArchISA
819184Sandreas.hansson@arm.com    ArchInterruptsParam = VectorParam.X86LocalApic
829184Sandreas.hansson@arm.com    ArchISAsParam = VectorParam.X86ISA
831681SN/Aelif buildEnv['TARGET_ISA'] == 'mips':
842932SN/A    from m5.objects.MipsTLB import MipsTLB as ArchDTB, MipsTLB as ArchITB
852932SN/A    from m5.objects.MipsInterrupts import MipsInterrupts as ArchInterrupts
861681SN/A    from m5.objects.MipsISA import MipsISA as ArchISA
872932SN/A    ArchInterruptsParam = VectorParam.MipsInterrupts
882932SN/A    ArchISAsParam = VectorParam.MipsISA
892932SN/Aelif buildEnv['TARGET_ISA'] == 'arm':
902932SN/A    from m5.objects.ArmTLB import ArmTLB as ArchDTB, ArmTLB as ArchITB
912932SN/A    from m5.objects.ArmTLB import ArmStage2IMMU, ArmStage2DMMU
922932SN/A    from m5.objects.ArmInterrupts import ArmInterrupts as ArchInterrupts
932932SN/A    from m5.objects.ArmISA import ArmISA as ArchISA
943223SN/A    ArchInterruptsParam = VectorParam.ArmInterrupts
952932SN/A    ArchISAsParam = VectorParam.ArmISA
962932SN/Aelif buildEnv['TARGET_ISA'] == 'power':
971681SN/A    from m5.objects.PowerTLB import PowerTLB as ArchDTB, PowerTLB as ArchITB
982932SN/A    from m5.objects.PowerInterrupts import PowerInterrupts as ArchInterrupts
992932SN/A    from m5.objects.PowerISA import PowerISA as ArchISA
1002873SN/A    ArchInterruptsParam = VectorParam.PowerInterrupts
1012932SN/A    ArchISAsParam = VectorParam.PowerISA
1021681SN/Aelif buildEnv['TARGET_ISA'] == 'riscv':
1032932SN/A    from m5.objects.RiscvTLB import RiscvTLB as ArchDTB, RiscvTLB as ArchITB
1042932SN/A    from m5.objects.RiscvInterrupts import RiscvInterrupts as ArchInterrupts
1058199SAli.Saidi@ARM.com    from m5.objects.RiscvISA import RiscvISA as ArchISA
1068199SAli.Saidi@ARM.com    ArchInterruptsParam = VectorParam.RiscvInterrupts
1078199SAli.Saidi@ARM.com    ArchISAsParam = VectorParam.RiscvISA
1088519SAli.Saidi@ARM.comelse:
1098519SAli.Saidi@ARM.com    print("Don't know what object types to use for ISA %s" %
1102932SN/A            buildEnv['TARGET_ISA'])
1112932SN/A    sys.exit(1)
1121681SN/A
1132932SN/Aclass BaseCPU(ClockedObject):
1141681SN/A    type = 'BaseCPU'
1152932SN/A    abstract = True
1162932SN/A    cxx_header = "cpu/base.hh"
1172932SN/A
1182932SN/A    cxx_exports = [
1192932SN/A        PyBindMethod("switchOut"),
1201681SN/A        PyBindMethod("takeOverFrom"),
1212932SN/A        PyBindMethod("switchedOut"),
1221681SN/A        PyBindMethod("flushTLBs"),
1234597Sbinkertn@umich.edu        PyBindMethod("totalInsts"),
1244597Sbinkertn@umich.edu        PyBindMethod("scheduleInstStop"),
1254597Sbinkertn@umich.edu        PyBindMethod("scheduleLoadStop"),
1264597Sbinkertn@umich.edu        PyBindMethod("getCurrentInstCount"),
1274597Sbinkertn@umich.edu    ]
1284597Sbinkertn@umich.edu
1294597Sbinkertn@umich.edu    @classmethod
1304597Sbinkertn@umich.edu    def memory_mode(cls):
1314597Sbinkertn@umich.edu        """Which memory mode does this CPU require?"""
1324303SN/A        return 'invalid'
1338727Snilay@cs.wisc.edu
1348727Snilay@cs.wisc.edu    @classmethod
1358887Sgeoffrey.blake@arm.com    def require_caches(cls):
1368887Sgeoffrey.blake@arm.com        """Does the CPU model require caches?
1378887Sgeoffrey.blake@arm.com
1388887Sgeoffrey.blake@arm.com        Some CPU models might make assumptions that require them to
1398887Sgeoffrey.blake@arm.com        have caches.
1408887Sgeoffrey.blake@arm.com        """
1418887Sgeoffrey.blake@arm.com        return False
1428887Sgeoffrey.blake@arm.com
1438887Sgeoffrey.blake@arm.com    @classmethod
1448887Sgeoffrey.blake@arm.com    def support_take_over(cls):
1458887Sgeoffrey.blake@arm.com        """Does the CPU model support CPU takeOverFrom?"""
1469132Satgutier@umich.edu        return False
1478887Sgeoffrey.blake@arm.com
1488887Sgeoffrey.blake@arm.com    def takeOverFrom(self, old_cpu):
1498887Sgeoffrey.blake@arm.com        self._ccObject.takeOverFrom(old_cpu._ccObject)
1508887Sgeoffrey.blake@arm.com
151
152    system = Param.System(Parent.any, "system object")
153    cpu_id = Param.Int(-1, "CPU identifier")
154    socket_id = Param.Unsigned(0, "Physical Socket identifier")
155    numThreads = Param.Unsigned(1, "number of HW thread contexts")
156    pwr_gating_latency = Param.Cycles(300,
157        "Latency to enter power gating state when all contexts are suspended")
158
159    power_gating_on_idle = Param.Bool(False, "Control whether the core goes "\
160        "to the OFF power state after all thread are disabled for "\
161        "pwr_gating_latency cycles")
162
163    function_trace = Param.Bool(False, "Enable function trace")
164    function_trace_start = Param.Tick(0, "Tick to start function trace")
165
166    checker = Param.BaseCPU(NULL, "checker CPU")
167
168    syscallRetryLatency = Param.Cycles(10000, "Cycles to wait until retry")
169
170    do_checkpoint_insts = Param.Bool(True,
171        "enable checkpoint pseudo instructions")
172    do_statistics_insts = Param.Bool(True,
173        "enable statistics pseudo instructions")
174
175    profile = Param.Latency('0ns', "trace the kernel stack")
176    do_quiesce = Param.Bool(True, "enable quiesce instructions")
177
178    wait_for_remote_gdb = Param.Bool(False,
179        "Wait for a remote GDB connection");
180
181    workload = VectorParam.Process([], "processes to run")
182
183    dtb = Param.BaseTLB(ArchDTB(), "Data TLB")
184    itb = Param.BaseTLB(ArchITB(), "Instruction TLB")
185    if buildEnv['TARGET_ISA'] == 'arm':
186        istage2_mmu = Param.ArmStage2MMU(ArmStage2IMMU(), "Stage 2 trans")
187        dstage2_mmu = Param.ArmStage2MMU(ArmStage2DMMU(), "Stage 2 trans")
188    elif buildEnv['TARGET_ISA'] == 'power':
189        UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
190    interrupts = ArchInterruptsParam([], "Interrupt Controller")
191    isa = ArchISAsParam([], "ISA instance")
192
193    max_insts_all_threads = Param.Counter(0,
194        "terminate when all threads have reached this inst count")
195    max_insts_any_thread = Param.Counter(0,
196        "terminate when any thread reaches this inst count")
197    simpoint_start_insts = VectorParam.Counter([],
198        "starting instruction counts of simpoints")
199    max_loads_all_threads = Param.Counter(0,
200        "terminate when all threads have reached this load count")
201    max_loads_any_thread = Param.Counter(0,
202        "terminate when any thread reaches this load count")
203    progress_interval = Param.Frequency('0Hz',
204        "frequency to print out the progress message")
205
206    switched_out = Param.Bool(False,
207        "Leave the CPU switched out after startup (used when switching " \
208        "between CPU models)")
209
210    tracer = Param.InstTracer(default_tracer, "Instruction tracer")
211
212    icache_port = MasterPort("Instruction Port")
213    dcache_port = MasterPort("Data Port")
214    _cached_ports = ['icache_port', 'dcache_port']
215
216    if buildEnv['TARGET_ISA'] in ['x86', 'arm']:
217        _cached_ports += ["itb.walker.port", "dtb.walker.port"]
218
219    _uncached_slave_ports = []
220    _uncached_master_ports = []
221    if buildEnv['TARGET_ISA'] == 'x86':
222        _uncached_slave_ports += ["interrupts[0].pio",
223                                  "interrupts[0].int_slave"]
224        _uncached_master_ports += ["interrupts[0].int_master"]
225
226    def createInterruptController(self):
227        self.interrupts = [ArchInterrupts() for i in range(self.numThreads)]
228
229    def connectCachedPorts(self, bus):
230        for p in self._cached_ports:
231            exec('self.%s = bus.slave' % p)
232
233    def connectUncachedPorts(self, bus):
234        for p in self._uncached_slave_ports:
235            exec('self.%s = bus.master' % p)
236        for p in self._uncached_master_ports:
237            exec('self.%s = bus.slave' % p)
238
239    def connectAllPorts(self, cached_bus, uncached_bus = None):
240        self.connectCachedPorts(cached_bus)
241        if not uncached_bus:
242            uncached_bus = cached_bus
243        self.connectUncachedPorts(uncached_bus)
244
245    def addPrivateSplitL1Caches(self, ic, dc, iwc = None, dwc = None):
246        self.icache = ic
247        self.dcache = dc
248        self.icache_port = ic.cpu_side
249        self.dcache_port = dc.cpu_side
250        self._cached_ports = ['icache.mem_side', 'dcache.mem_side']
251        if buildEnv['TARGET_ISA'] in ['x86', 'arm']:
252            if iwc and dwc:
253                self.itb_walker_cache = iwc
254                self.dtb_walker_cache = dwc
255                self.itb.walker.port = iwc.cpu_side
256                self.dtb.walker.port = dwc.cpu_side
257                self._cached_ports += ["itb_walker_cache.mem_side", \
258                                       "dtb_walker_cache.mem_side"]
259            else:
260                self._cached_ports += ["itb.walker.port", "dtb.walker.port"]
261
262            # Checker doesn't need its own tlb caches because it does
263            # functional accesses only
264            if self.checker != NULL:
265                self._cached_ports += ["checker.itb.walker.port", \
266                                       "checker.dtb.walker.port"]
267
268    def addTwoLevelCacheHierarchy(self, ic, dc, l2c, iwc=None, dwc=None,
269                                  xbar=None):
270        self.addPrivateSplitL1Caches(ic, dc, iwc, dwc)
271        self.toL2Bus = xbar if xbar else L2XBar()
272        self.connectCachedPorts(self.toL2Bus)
273        self.l2cache = l2c
274        self.toL2Bus.master = self.l2cache.cpu_side
275        self._cached_ports = ['l2cache.mem_side']
276
277    def createThreads(self):
278        # If no ISAs have been created, assume that the user wants the
279        # default ISA.
280        if len(self.isa) == 0:
281            self.isa = [ ArchISA() for i in range(self.numThreads) ]
282        else:
283            if len(self.isa) != int(self.numThreads):
284                raise RuntimeError("Number of ISA instances doesn't "
285                                   "match thread count")
286        if self.checker != NULL:
287            self.checker.createThreads()
288
289    def addCheckerCpu(self):
290        pass
291
292    def createPhandleKey(self, thread):
293        # This method creates a unique key for this cpu as a function of a
294        # certain thread
295        return 'CPU-%d-%d-%d' % (self.socket_id, self.cpu_id, thread)
296
297    #Generate simple CPU Device Tree structure
298    def generateDeviceTree(self, state):
299        """Generate cpu nodes for each thread and the corresponding part of the
300        cpu-map node. Note that this implementation does not support clusters
301        of clusters. Note that GEM5 is not compatible with the official way of
302        numbering cores as defined in the Device Tree documentation. Where the
303        cpu_id needs to reset to 0 for each cluster by specification, GEM5
304        expects the cpu_id to be globally unique and incremental. This
305        generated node adheres the GEM5 way of doing things."""
306        if bool(self.switched_out):
307            return
308
309        cpus_node = FdtNode('cpus')
310        cpus_node.append(state.CPUCellsProperty())
311        #Special size override of 0
312        cpus_node.append(FdtPropertyWords('#size-cells', [0]))
313
314        # Generate cpu nodes
315        for i in range(int(self.numThreads)):
316            reg = (int(self.socket_id)<<8) + int(self.cpu_id) + i
317            node = FdtNode("cpu@%x" % reg)
318            node.append(FdtPropertyStrings("device_type", "cpu"))
319            node.appendCompatible(["gem5,arm-cpu"])
320            node.append(FdtPropertyWords("reg", state.CPUAddrCells(reg)))
321            platform, found = self.system.unproxy(self).find_any(Platform)
322            if found:
323                platform.annotateCpuDeviceNode(node, state)
324            else:
325                warn("Platform not found for device tree generation; " \
326                     "system or multiple CPUs may not start")
327
328            freq = int(self.clk_domain.unproxy(self).clock[0].frequency)
329            node.append(FdtPropertyWords("clock-frequency", freq))
330
331            # Unique key for this CPU
332            phandle_key = self.createPhandleKey(i)
333            node.appendPhandle(phandle_key)
334            cpus_node.append(node)
335
336        yield cpus_node
337