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 # Authors: Nathan Binkert
45 from __future__
import print_function
49 from m5
.SimObject
import *
50 from m5
.defines
import buildEnv
51 from m5
.params
import *
52 from m5
.proxy
import *
53 from m5
.util
.fdthelper
import *
55 from m5
.objects
.ClockedObject
import ClockedObject
56 from m5
.objects
.XBar
import L2XBar
57 from m5
.objects
.InstTracer
import InstTracer
58 from m5
.objects
.CPUTracers
import ExeTracer
59 from m5
.objects
.SubSystem
import SubSystem
60 from m5
.objects
.ClockDomain
import *
61 from m5
.objects
.Platform
import Platform
63 default_tracer
= ExeTracer()
65 if buildEnv
['TARGET_ISA'] == 'alpha':
66 from m5
.objects
.AlphaTLB
import AlphaDTB
as ArchDTB
, AlphaITB
as ArchITB
67 from m5
.objects
.AlphaInterrupts
import AlphaInterrupts
as ArchInterrupts
68 from m5
.objects
.AlphaISA
import AlphaISA
as ArchISA
69 ArchInterruptsParam
= VectorParam
.AlphaInterrupts
70 ArchISAsParam
= VectorParam
.AlphaISA
71 elif buildEnv
['TARGET_ISA'] == 'sparc':
72 from m5
.objects
.SparcTLB
import SparcTLB
as ArchDTB
, SparcTLB
as ArchITB
73 from m5
.objects
.SparcInterrupts
import SparcInterrupts
as ArchInterrupts
74 from m5
.objects
.SparcISA
import SparcISA
as ArchISA
75 ArchInterruptsParam
= VectorParam
.SparcInterrupts
76 ArchISAsParam
= VectorParam
.SparcISA
77 elif buildEnv
['TARGET_ISA'] == 'x86':
78 from m5
.objects
.X86TLB
import X86TLB
as ArchDTB
, X86TLB
as ArchITB
79 from m5
.objects
.X86LocalApic
import X86LocalApic
as ArchInterrupts
80 from m5
.objects
.X86ISA
import X86ISA
as ArchISA
81 ArchInterruptsParam
= VectorParam
.X86LocalApic
82 ArchISAsParam
= VectorParam
.X86ISA
83 elif buildEnv
['TARGET_ISA'] == 'mips':
84 from m5
.objects
.MipsTLB
import MipsTLB
as ArchDTB
, MipsTLB
as ArchITB
85 from m5
.objects
.MipsInterrupts
import MipsInterrupts
as ArchInterrupts
86 from m5
.objects
.MipsISA
import MipsISA
as ArchISA
87 ArchInterruptsParam
= VectorParam
.MipsInterrupts
88 ArchISAsParam
= VectorParam
.MipsISA
89 elif buildEnv
['TARGET_ISA'] == 'arm':
90 from m5
.objects
.ArmTLB
import ArmTLB
as ArchDTB
, ArmTLB
as ArchITB
91 from m5
.objects
.ArmTLB
import ArmStage2IMMU
, ArmStage2DMMU
92 from m5
.objects
.ArmInterrupts
import ArmInterrupts
as ArchInterrupts
93 from m5
.objects
.ArmISA
import ArmISA
as ArchISA
94 ArchInterruptsParam
= VectorParam
.ArmInterrupts
95 ArchISAsParam
= VectorParam
.ArmISA
96 elif buildEnv
['TARGET_ISA'] == 'power':
97 from m5
.objects
.PowerTLB
import PowerTLB
as ArchDTB
, PowerTLB
as ArchITB
98 from m5
.objects
.PowerInterrupts
import PowerInterrupts
as ArchInterrupts
99 from m5
.objects
.PowerISA
import PowerISA
as ArchISA
100 ArchInterruptsParam
= VectorParam
.PowerInterrupts
101 ArchISAsParam
= VectorParam
.PowerISA
102 elif buildEnv
['TARGET_ISA'] == 'riscv':
103 from m5
.objects
.RiscvTLB
import RiscvTLB
as ArchDTB
, RiscvTLB
as ArchITB
104 from m5
.objects
.RiscvInterrupts
import RiscvInterrupts
as ArchInterrupts
105 from m5
.objects
.RiscvISA
import RiscvISA
as ArchISA
106 ArchInterruptsParam
= VectorParam
.RiscvInterrupts
107 ArchISAsParam
= VectorParam
.RiscvISA
109 print("Don't know what object types to use for ISA %s" %
110 buildEnv
['TARGET_ISA'])
113 class BaseCPU(ClockedObject
):
116 cxx_header
= "cpu/base.hh"
119 PyBindMethod("switchOut"),
120 PyBindMethod("takeOverFrom"),
121 PyBindMethod("switchedOut"),
122 PyBindMethod("flushTLBs"),
123 PyBindMethod("totalInsts"),
124 PyBindMethod("scheduleInstStop"),
125 PyBindMethod("getCurrentInstCount"),
129 def memory_mode(cls
):
130 """Which memory mode does this CPU require?"""
134 def require_caches(cls
):
135 """Does the CPU model require caches?
137 Some CPU models might make assumptions that require them to
143 def support_take_over(cls
):
144 """Does the CPU model support CPU takeOverFrom?"""
147 def takeOverFrom(self
, old_cpu
):
148 self
._ccObject
.takeOverFrom(old_cpu
._ccObject
)
151 system
= Param
.System(Parent
.any
, "system object")
152 cpu_id
= Param
.Int(-1, "CPU identifier")
153 socket_id
= Param
.Unsigned(0, "Physical Socket identifier")
154 numThreads
= Param
.Unsigned(1, "number of HW thread contexts")
155 pwr_gating_latency
= Param
.Cycles(300,
156 "Latency to enter power gating state when all contexts are suspended")
158 power_gating_on_idle
= Param
.Bool(False, "Control whether the core goes "\
159 "to the OFF power state after all thread are disabled for "\
160 "pwr_gating_latency cycles")
162 function_trace
= Param
.Bool(False, "Enable function trace")
163 function_trace_start
= Param
.Tick(0, "Tick to start function trace")
165 checker
= Param
.BaseCPU(NULL
, "checker CPU")
167 syscallRetryLatency
= Param
.Cycles(10000, "Cycles to wait until retry")
169 do_checkpoint_insts
= Param
.Bool(True,
170 "enable checkpoint pseudo instructions")
171 do_statistics_insts
= Param
.Bool(True,
172 "enable statistics pseudo instructions")
174 profile
= Param
.Latency('0ns', "trace the kernel stack")
175 do_quiesce
= Param
.Bool(True, "enable quiesce instructions")
177 wait_for_remote_gdb
= Param
.Bool(False,
178 "Wait for a remote GDB connection");
180 workload
= VectorParam
.Process([], "processes to run")
182 dtb
= Param
.BaseTLB(ArchDTB(), "Data TLB")
183 itb
= Param
.BaseTLB(ArchITB(), "Instruction TLB")
184 if buildEnv
['TARGET_ISA'] == 'arm':
185 istage2_mmu
= Param
.ArmStage2MMU(ArmStage2IMMU(), "Stage 2 trans")
186 dstage2_mmu
= Param
.ArmStage2MMU(ArmStage2DMMU(), "Stage 2 trans")
187 elif buildEnv
['TARGET_ISA'] == 'power':
188 UnifiedTLB
= Param
.Bool(True, "Is this a Unified TLB?")
189 interrupts
= ArchInterruptsParam([], "Interrupt Controller")
190 isa
= ArchISAsParam([], "ISA instance")
192 max_insts_all_threads
= Param
.Counter(0,
193 "terminate when all threads have reached this inst count")
194 max_insts_any_thread
= Param
.Counter(0,
195 "terminate when any thread reaches this inst count")
196 simpoint_start_insts
= VectorParam
.Counter([],
197 "starting instruction counts of simpoints")
198 progress_interval
= Param
.Frequency('0Hz',
199 "frequency to print out the progress message")
201 switched_out
= Param
.Bool(False,
202 "Leave the CPU switched out after startup (used when switching " \
203 "between CPU models)")
205 tracer
= Param
.InstTracer(default_tracer
, "Instruction tracer")
207 icache_port
= MasterPort("Instruction Port")
208 dcache_port
= MasterPort("Data Port")
209 _cached_ports
= ['icache_port', 'dcache_port']
211 if buildEnv
['TARGET_ISA'] in ['x86', 'arm']:
212 _cached_ports
+= ["itb.walker.port", "dtb.walker.port"]
214 _uncached_slave_ports
= []
215 _uncached_master_ports
= []
216 if buildEnv
['TARGET_ISA'] == 'x86':
217 _uncached_slave_ports
+= ["interrupts[0].pio",
218 "interrupts[0].int_slave"]
219 _uncached_master_ports
+= ["interrupts[0].int_master"]
221 def createInterruptController(self
):
222 self
.interrupts
= [ArchInterrupts() for i
in range(self
.numThreads
)]
224 def connectCachedPorts(self
, bus
):
225 for p
in self
._cached
_ports
:
226 exec('self.%s = bus.slave' % p
)
228 def connectUncachedPorts(self
, bus
):
229 for p
in self
._uncached
_slave
_ports
:
230 exec('self.%s = bus.master' % p
)
231 for p
in self
._uncached
_master
_ports
:
232 exec('self.%s = bus.slave' % p
)
234 def connectAllPorts(self
, cached_bus
, uncached_bus
= None):
235 self
.connectCachedPorts(cached_bus
)
237 uncached_bus
= cached_bus
238 self
.connectUncachedPorts(uncached_bus
)
240 def addPrivateSplitL1Caches(self
, ic
, dc
, iwc
= None, dwc
= None):
243 self
.icache_port
= ic
.cpu_side
244 self
.dcache_port
= dc
.cpu_side
245 self
._cached
_ports
= ['icache.mem_side', 'dcache.mem_side']
246 if buildEnv
['TARGET_ISA'] in ['x86', 'arm']:
248 self
.itb_walker_cache
= iwc
249 self
.dtb_walker_cache
= dwc
250 self
.itb
.walker
.port
= iwc
.cpu_side
251 self
.dtb
.walker
.port
= dwc
.cpu_side
252 self
._cached
_ports
+= ["itb_walker_cache.mem_side", \
253 "dtb_walker_cache.mem_side"]
255 self
._cached
_ports
+= ["itb.walker.port", "dtb.walker.port"]
257 # Checker doesn't need its own tlb caches because it does
258 # functional accesses only
259 if self
.checker
!= NULL
:
260 self
._cached
_ports
+= ["checker.itb.walker.port", \
261 "checker.dtb.walker.port"]
263 def addTwoLevelCacheHierarchy(self
, ic
, dc
, l2c
, iwc
=None, dwc
=None,
265 self
.addPrivateSplitL1Caches(ic
, dc
, iwc
, dwc
)
266 self
.toL2Bus
= xbar
if xbar
else L2XBar()
267 self
.connectCachedPorts(self
.toL2Bus
)
269 self
.toL2Bus
.master
= self
.l2cache
.cpu_side
270 self
._cached
_ports
= ['l2cache.mem_side']
272 def createThreads(self
):
273 # If no ISAs have been created, assume that the user wants the
275 if len(self
.isa
) == 0:
276 self
.isa
= [ ArchISA() for i
in range(self
.numThreads
) ]
278 if len(self
.isa
) != int(self
.numThreads
):
279 raise RuntimeError("Number of ISA instances doesn't "
280 "match thread count")
281 if self
.checker
!= NULL
:
282 self
.checker
.createThreads()
284 def addCheckerCpu(self
):
287 def createPhandleKey(self
, thread
):
288 # This method creates a unique key for this cpu as a function of a
290 return 'CPU-%d-%d-%d' % (self
.socket_id
, self
.cpu_id
, thread
)
292 #Generate simple CPU Device Tree structure
293 def generateDeviceTree(self
, state
):
294 """Generate cpu nodes for each thread and the corresponding part of the
295 cpu-map node. Note that this implementation does not support clusters
296 of clusters. Note that GEM5 is not compatible with the official way of
297 numbering cores as defined in the Device Tree documentation. Where the
298 cpu_id needs to reset to 0 for each cluster by specification, GEM5
299 expects the cpu_id to be globally unique and incremental. This
300 generated node adheres the GEM5 way of doing things."""
301 if bool(self
.switched_out
):
304 cpus_node
= FdtNode('cpus')
305 cpus_node
.append(state
.CPUCellsProperty())
306 #Special size override of 0
307 cpus_node
.append(FdtPropertyWords('#size-cells', [0]))
310 for i
in range(int(self
.numThreads
)):
311 reg
= (int(self
.socket_id
)<<8) + int(self
.cpu_id
) + i
312 node
= FdtNode("cpu@%x" % reg
)
313 node
.append(FdtPropertyStrings("device_type", "cpu"))
314 node
.appendCompatible(["gem5,arm-cpu"])
315 node
.append(FdtPropertyWords("reg", state
.CPUAddrCells(reg
)))
316 platform
, found
= self
.system
.unproxy(self
).find_any(Platform
)
318 platform
.annotateCpuDeviceNode(node
, state
)
320 warn("Platform not found for device tree generation; " \
321 "system or multiple CPUs may not start")
323 freq
= int(self
.clk_domain
.unproxy(self
).clock
[0].frequency
)
324 node
.append(FdtPropertyWords("clock-frequency", freq
))
326 # Unique key for this CPU
327 phandle_key
= self
.createPhandleKey(i
)
328 node
.appendPhandle(phandle_key
)
329 cpus_node
.append(node
)