1 # Copyright (c) 2012-2013, 2015-2017 ARM Limited
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.
13 # Copyright (c) 2005-2008 The Regents of The University of Michigan
14 # Copyright (c) 2011 Regents of the University of California
15 # All rights reserved.
17 # Redistribution and use in source and binary forms, with or without
18 # modification, are permitted provided that the following conditions are
19 # met: redistributions of source code must retain the above copyright
20 # notice, this list of conditions and the following disclaimer;
21 # redistributions in binary form must reproduce the above copyright
22 # notice, this list of conditions and the following disclaimer in the
23 # documentation and/or other materials provided with the distribution;
24 # neither the name of the copyright holders nor the names of its
25 # contributors may be used to endorse or promote products derived from
26 # this software without specific prior written permission.
28 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 from __future__
import print_function
44 from m5
.SimObject
import *
45 from m5
.defines
import buildEnv
46 from m5
.params
import *
47 from m5
.proxy
import *
48 from m5
.util
.fdthelper
import *
50 from m5
.objects
.ClockedObject
import ClockedObject
51 from m5
.objects
.XBar
import L2XBar
52 from m5
.objects
.InstTracer
import InstTracer
53 from m5
.objects
.CPUTracers
import ExeTracer
54 from m5
.objects
.SubSystem
import SubSystem
55 from m5
.objects
.ClockDomain
import *
56 from m5
.objects
.Platform
import Platform
58 default_tracer
= ExeTracer()
60 if buildEnv
['TARGET_ISA'] == 'sparc':
61 from m5
.objects
.SparcTLB
import SparcTLB
as ArchDTB
, SparcTLB
as ArchITB
62 from m5
.objects
.SparcInterrupts
import SparcInterrupts
as ArchInterrupts
63 from m5
.objects
.SparcISA
import SparcISA
as ArchISA
64 elif buildEnv
['TARGET_ISA'] == 'x86':
65 from m5
.objects
.X86TLB
import X86TLB
as ArchDTB
, X86TLB
as ArchITB
66 from m5
.objects
.X86LocalApic
import X86LocalApic
as ArchInterrupts
67 from m5
.objects
.X86ISA
import X86ISA
as ArchISA
68 elif buildEnv
['TARGET_ISA'] == 'mips':
69 from m5
.objects
.MipsTLB
import MipsTLB
as ArchDTB
, MipsTLB
as ArchITB
70 from m5
.objects
.MipsInterrupts
import MipsInterrupts
as ArchInterrupts
71 from m5
.objects
.MipsISA
import MipsISA
as ArchISA
72 elif buildEnv
['TARGET_ISA'] == 'arm':
73 from m5
.objects
.ArmTLB
import ArmDTB
as ArchDTB
, ArmITB
as ArchITB
74 from m5
.objects
.ArmInterrupts
import ArmInterrupts
as ArchInterrupts
75 from m5
.objects
.ArmISA
import ArmISA
as ArchISA
76 elif buildEnv
['TARGET_ISA'] == 'power':
77 from m5
.objects
.PowerTLB
import PowerTLB
as ArchDTB
, PowerTLB
as ArchITB
78 from m5
.objects
.PowerInterrupts
import PowerInterrupts
as ArchInterrupts
79 from m5
.objects
.PowerISA
import PowerISA
as ArchISA
80 elif buildEnv
['TARGET_ISA'] == 'riscv':
81 from m5
.objects
.RiscvTLB
import RiscvTLB
as ArchDTB
, RiscvTLB
as ArchITB
82 from m5
.objects
.RiscvInterrupts
import RiscvInterrupts
as ArchInterrupts
83 from m5
.objects
.RiscvISA
import RiscvISA
as ArchISA
85 print("Don't know what object types to use for ISA %s" %
86 buildEnv
['TARGET_ISA'])
89 class BaseCPU(ClockedObject
):
92 cxx_header
= "cpu/base.hh"
95 PyBindMethod("switchOut"),
96 PyBindMethod("takeOverFrom"),
97 PyBindMethod("switchedOut"),
98 PyBindMethod("flushTLBs"),
99 PyBindMethod("totalInsts"),
100 PyBindMethod("scheduleInstStop"),
101 PyBindMethod("getCurrentInstCount"),
105 def memory_mode(cls
):
106 """Which memory mode does this CPU require?"""
110 def require_caches(cls
):
111 """Does the CPU model require caches?
113 Some CPU models might make assumptions that require them to
119 def support_take_over(cls
):
120 """Does the CPU model support CPU takeOverFrom?"""
123 def takeOverFrom(self
, old_cpu
):
124 self
._ccObject
.takeOverFrom(old_cpu
._ccObject
)
127 system
= Param
.System(Parent
.any
, "system object")
128 cpu_id
= Param
.Int(-1, "CPU identifier")
129 socket_id
= Param
.Unsigned(0, "Physical Socket identifier")
130 numThreads
= Param
.Unsigned(1, "number of HW thread contexts")
131 pwr_gating_latency
= Param
.Cycles(300,
132 "Latency to enter power gating state when all contexts are suspended")
134 power_gating_on_idle
= Param
.Bool(False, "Control whether the core goes "\
135 "to the OFF power state after all thread are disabled for "\
136 "pwr_gating_latency cycles")
138 function_trace
= Param
.Bool(False, "Enable function trace")
139 function_trace_start
= Param
.Tick(0, "Tick to start function trace")
141 checker
= Param
.BaseCPU(NULL
, "checker CPU")
143 syscallRetryLatency
= Param
.Cycles(10000, "Cycles to wait until retry")
145 do_checkpoint_insts
= Param
.Bool(True,
146 "enable checkpoint pseudo instructions")
147 do_statistics_insts
= Param
.Bool(True,
148 "enable statistics pseudo instructions")
150 profile
= Param
.Latency('0ns', "trace the kernel stack")
151 do_quiesce
= Param
.Bool(True, "enable quiesce instructions")
153 wait_for_remote_gdb
= Param
.Bool(False,
154 "Wait for a remote GDB connection");
156 workload
= VectorParam
.Process([], "processes to run")
158 dtb
= Param
.BaseTLB(ArchDTB(), "Data TLB")
159 itb
= Param
.BaseTLB(ArchITB(), "Instruction TLB")
160 if buildEnv
['TARGET_ISA'] == 'power':
161 UnifiedTLB
= Param
.Bool(True, "Is this a Unified TLB?")
162 interrupts
= VectorParam
.BaseInterrupts([], "Interrupt Controller")
163 isa
= VectorParam
.BaseISA([], "ISA instance")
165 max_insts_all_threads
= Param
.Counter(0,
166 "terminate when all threads have reached this inst count")
167 max_insts_any_thread
= Param
.Counter(0,
168 "terminate when any thread reaches this inst count")
169 simpoint_start_insts
= VectorParam
.Counter([],
170 "starting instruction counts of simpoints")
171 progress_interval
= Param
.Frequency('0Hz',
172 "frequency to print out the progress message")
174 switched_out
= Param
.Bool(False,
175 "Leave the CPU switched out after startup (used when switching " \
176 "between CPU models)")
178 tracer
= Param
.InstTracer(default_tracer
, "Instruction tracer")
180 icache_port
= MasterPort("Instruction Port")
181 dcache_port
= MasterPort("Data Port")
182 _cached_ports
= ['icache_port', 'dcache_port']
184 if buildEnv
['TARGET_ISA'] in ['x86', 'arm']:
185 _cached_ports
+= ["itb.walker.port", "dtb.walker.port"]
187 _uncached_slave_ports
= []
188 _uncached_master_ports
= []
189 if buildEnv
['TARGET_ISA'] == 'x86':
190 _uncached_slave_ports
+= ["interrupts[0].pio",
191 "interrupts[0].int_slave"]
192 _uncached_master_ports
+= ["interrupts[0].int_master"]
194 def createInterruptController(self
):
195 self
.interrupts
= [ArchInterrupts() for i
in range(self
.numThreads
)]
197 def connectCachedPorts(self
, bus
):
198 for p
in self
._cached
_ports
:
199 exec('self.%s = bus.slave' % p
)
201 def connectUncachedPorts(self
, bus
):
202 for p
in self
._uncached
_slave
_ports
:
203 exec('self.%s = bus.master' % p
)
204 for p
in self
._uncached
_master
_ports
:
205 exec('self.%s = bus.slave' % p
)
207 def connectAllPorts(self
, cached_bus
, uncached_bus
= None):
208 self
.connectCachedPorts(cached_bus
)
210 uncached_bus
= cached_bus
211 self
.connectUncachedPorts(uncached_bus
)
213 def addPrivateSplitL1Caches(self
, ic
, dc
, iwc
= None, dwc
= None):
216 self
.icache_port
= ic
.cpu_side
217 self
.dcache_port
= dc
.cpu_side
218 self
._cached
_ports
= ['icache.mem_side', 'dcache.mem_side']
219 if buildEnv
['TARGET_ISA'] in ['x86', 'arm']:
221 self
.itb_walker_cache
= iwc
222 self
.dtb_walker_cache
= dwc
223 self
.itb
.walker
.port
= iwc
.cpu_side
224 self
.dtb
.walker
.port
= dwc
.cpu_side
225 self
._cached
_ports
+= ["itb_walker_cache.mem_side", \
226 "dtb_walker_cache.mem_side"]
228 self
._cached
_ports
+= ["itb.walker.port", "dtb.walker.port"]
230 # Checker doesn't need its own tlb caches because it does
231 # functional accesses only
232 if self
.checker
!= NULL
:
233 self
._cached
_ports
+= ["checker.itb.walker.port", \
234 "checker.dtb.walker.port"]
236 def addTwoLevelCacheHierarchy(self
, ic
, dc
, l2c
, iwc
=None, dwc
=None,
238 self
.addPrivateSplitL1Caches(ic
, dc
, iwc
, dwc
)
239 self
.toL2Bus
= xbar
if xbar
else L2XBar()
240 self
.connectCachedPorts(self
.toL2Bus
)
242 self
.toL2Bus
.master
= self
.l2cache
.cpu_side
243 self
._cached
_ports
= ['l2cache.mem_side']
245 def createThreads(self
):
246 # If no ISAs have been created, assume that the user wants the
248 if len(self
.isa
) == 0:
249 self
.isa
= [ ArchISA() for i
in range(self
.numThreads
) ]
251 if len(self
.isa
) != int(self
.numThreads
):
252 raise RuntimeError("Number of ISA instances doesn't "
253 "match thread count")
254 if self
.checker
!= NULL
:
255 self
.checker
.createThreads()
257 def addCheckerCpu(self
):
260 def createPhandleKey(self
, thread
):
261 # This method creates a unique key for this cpu as a function of a
263 return 'CPU-%d-%d-%d' % (self
.socket_id
, self
.cpu_id
, thread
)
265 #Generate simple CPU Device Tree structure
266 def generateDeviceTree(self
, state
):
267 """Generate cpu nodes for each thread and the corresponding part of the
268 cpu-map node. Note that this implementation does not support clusters
269 of clusters. Note that GEM5 is not compatible with the official way of
270 numbering cores as defined in the Device Tree documentation. Where the
271 cpu_id needs to reset to 0 for each cluster by specification, GEM5
272 expects the cpu_id to be globally unique and incremental. This
273 generated node adheres the GEM5 way of doing things."""
274 if bool(self
.switched_out
):
277 cpus_node
= FdtNode('cpus')
278 cpus_node
.append(state
.CPUCellsProperty())
279 #Special size override of 0
280 cpus_node
.append(FdtPropertyWords('#size-cells', [0]))
283 for i
in range(int(self
.numThreads
)):
284 reg
= (int(self
.socket_id
)<<8) + int(self
.cpu_id
) + i
285 node
= FdtNode("cpu@%x" % reg
)
286 node
.append(FdtPropertyStrings("device_type", "cpu"))
287 node
.appendCompatible(["gem5,arm-cpu"])
288 node
.append(FdtPropertyWords("reg", state
.CPUAddrCells(reg
)))
289 platform
, found
= self
.system
.unproxy(self
).find_any(Platform
)
291 platform
.annotateCpuDeviceNode(node
, state
)
293 warn("Platform not found for device tree generation; " \
294 "system or multiple CPUs may not start")
296 freq
= int(self
.clk_domain
.unproxy(self
).clock
[0].frequency
)
297 node
.append(FdtPropertyWords("clock-frequency", freq
))
299 # Unique key for this CPU
300 phandle_key
= self
.createPhandleKey(i
)
301 node
.appendPhandle(phandle_key
)
302 cpus_node
.append(node
)