memtest.py revision 9036:6385cf85bf12
1695SN/A# Copyright (c) 2006-2007 The Regents of The University of Michigan
21762SN/A# All rights reserved.
3695SN/A#
4695SN/A# Redistribution and use in source and binary forms, with or without
5695SN/A# modification, are permitted provided that the following conditions are
6695SN/A# met: redistributions of source code must retain the above copyright
7695SN/A# notice, this list of conditions and the following disclaimer;
8695SN/A# redistributions in binary form must reproduce the above copyright
9695SN/A# notice, this list of conditions and the following disclaimer in the
10695SN/A# documentation and/or other materials provided with the distribution;
11695SN/A# neither the name of the copyright holders nor the names of its
12695SN/A# contributors may be used to endorse or promote products derived from
13695SN/A# this software without specific prior written permission.
14695SN/A#
15695SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16695SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17695SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18695SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19695SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20695SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21695SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22695SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23695SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24695SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25695SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26695SN/A#
272665Ssaidi@eecs.umich.edu# Authors: Ron Dreslinski
282665Ssaidi@eecs.umich.edu
29695SN/Aimport optparse
30695SN/Aimport sys
31695SN/A
32695SN/Aimport m5
33695SN/Afrom m5.objects import *
34695SN/A
35695SN/Aparser = optparse.OptionParser()
36695SN/A
37695SN/Aparser.add_option("-a", "--atomic", action="store_true",
38695SN/A                  help="Use atomic (non-timing) mode")
39695SN/Aparser.add_option("-b", "--blocking", action="store_true",
40695SN/A                  help="Use blocking caches")
41695SN/Aparser.add_option("-l", "--maxloads", metavar="N", default=0,
421717SN/A                  help="Stop after N loads")
43695SN/Aparser.add_option("-m", "--maxtick", type="int", default=m5.MaxTick,
44695SN/A                  metavar="T",
45695SN/A                  help="Stop after T ticks")
46695SN/A
47729SN/A#
48729SN/A# The "tree" specification is a colon-separated list of one or more
49729SN/A# integers.  The first integer is the number of caches/testers
50729SN/A# connected directly to main memory.  The last integer in the list is
51695SN/A# the number of testers associated with the uppermost level of memory
52729SN/A# (L1 cache, if there are caches, or main memory if no caches).  Thus
53729SN/A# if there is only one integer, there are no caches, and the integer
54729SN/A# specifies the number of testers connected directly to main memory.
55729SN/A# The other integers (if any) specify the number of caches at each
56695SN/A# level of the hierarchy between.
57729SN/A#
58695SN/A# Examples:
59695SN/A#
60695SN/A#  "2:1"    Two caches connected to memory with a single tester behind each
61695SN/A#           (single-level hierarchy, two testers total)
624078Sbinkertn@umich.edu#
63695SN/A#  "2:2:1"  Two-level hierarchy, 2 L1s behind each of 2 L2s, 4 testers total
64695SN/A#
65695SN/Aparser.add_option("-t", "--treespec", type="string", default="8:1",
66695SN/A                  help="Colon-separated multilevel tree specification, "
67695SN/A                  "see script comments for details "
68695SN/A                  "[default: %default]")
69695SN/A
70695SN/Aparser.add_option("--force-bus", action="store_true",
71695SN/A                  help="Use bus between levels even with single cache")
72695SN/A
73695SN/Aparser.add_option("-f", "--functional", type="int", default=0,
74695SN/A                  metavar="PCT",
75695SN/A                  help="Target percentage of functional accesses "
76695SN/A                  "[default: %default]")
77695SN/Aparser.add_option("-u", "--uncacheable", type="int", default=0,
78695SN/A                  metavar="PCT",
791020SN/A                  help="Target percentage of uncacheable accesses "
801020SN/A                  "[default: %default]")
811020SN/A
821020SN/Aparser.add_option("--progress", type="int", default=1000,
831020SN/A                  metavar="NLOADS",
841020SN/A                  help="Progress message interval "
85695SN/A                  "[default: %default]")
86695SN/A
87695SN/A(options, args) = parser.parse_args()
884078Sbinkertn@umich.edu
89695SN/Aif args:
90695SN/A     print "Error: script doesn't take any positional arguments"
91707SN/A     sys.exit(1)
92695SN/A
93695SN/Ablock_size = 64
94695SN/A
95695SN/Atry:
96695SN/A     treespec = [int(x) for x in options.treespec.split(':')]
97695SN/A     numtesters = reduce(lambda x,y: x*y, treespec)
98695SN/Aexcept:
99695SN/A     print "Error parsing treespec option"
100695SN/A     sys.exit(1)
101695SN/A
102695SN/Aif numtesters > block_size:
103707SN/A     print "Error: Number of testers limited to %s because of false sharing" \
1041609SN/A           % (block_size)
105707SN/A     sys.exit(1)
106707SN/A
107707SN/Aif len(treespec) < 1:
108707SN/A     print "Error parsing treespec"
109695SN/A     sys.exit(1)
1101020SN/A
111695SN/A# define prototype L1 cache
112695SN/Aproto_l1 = BaseCache(size = '32kB', assoc = 4, block_size = block_size,
113695SN/A                     latency = '1ns', tgts_per_mshr = 8)
114695SN/A
115695SN/Aif options.blocking:
116695SN/A     proto_l1.mshrs = 1
117695SN/Aelse:
118695SN/A     proto_l1.mshrs = 4
119695SN/A
120695SN/A# build a list of prototypes, one for each level of treespec, starting
121695SN/A# at the end (last entry is tester objects)
122695SN/Aprototypes = [ MemTest(atomic=options.atomic, max_loads=options.maxloads,
123707SN/A                       percent_functional=options.functional,
124695SN/A                       percent_uncacheable=options.uncacheable,
125695SN/A                       progress_interval=options.progress) ]
126695SN/A
127695SN/A# next comes L1 cache, if any
128695SN/Aif len(treespec) > 1:
129695SN/A     prototypes.insert(0, proto_l1)
130707SN/A
131695SN/A# now add additional cache levels (if any) by scaling L1 params
132695SN/Afor scale in treespec[:-2]:
133695SN/A     # clone previous level and update params
134695SN/A     prev = prototypes[0]
135695SN/A     next = prev()
136695SN/A     next.size = prev.size * scale
137695SN/A     next.latency = prev.latency * 10
138695SN/A     next.assoc = prev.assoc * scale
139695SN/A     next.mshrs = prev.mshrs * scale
140695SN/A     prototypes.insert(0, next)
141695SN/A
142707SN/A# system simulated
143695SN/Asystem = System(funcmem = SimpleMemory(in_addr_map = False),
144695SN/A                physmem = SimpleMemory(latency = "100ns"))
145695SN/A
146695SN/Adef make_level(spec, prototypes, attach_obj, attach_port):
147695SN/A     fanout = spec[0]
148695SN/A     parent = attach_obj # use attach obj as config parent too
1494078Sbinkertn@umich.edu     if len(spec) > 1 and (fanout > 1 or options.force_bus):
150695SN/A          port = getattr(attach_obj, attach_port)
1514078Sbinkertn@umich.edu          new_bus = CoherentBus(clock="500MHz", width=16)
1524078Sbinkertn@umich.edu          if (port.role == 'MASTER'):
1534078Sbinkertn@umich.edu               new_bus.slave = port
154695SN/A               attach_port = "master"
155695SN/A          else:
156695SN/A               new_bus.master = port
1575606Snate@binkert.org               attach_port = "slave"
1585606Snate@binkert.org          parent.cpu_side_bus = new_bus
1594078Sbinkertn@umich.edu          attach_obj = new_bus
1604078Sbinkertn@umich.edu     objs = [prototypes[0]() for i in xrange(fanout)]
1614078Sbinkertn@umich.edu     if len(spec) > 1:
1624078Sbinkertn@umich.edu          # we just built caches, more levels to go
1634078Sbinkertn@umich.edu          parent.cache = objs
1644078Sbinkertn@umich.edu          for cache in objs:
1654078Sbinkertn@umich.edu               cache.mem_side = getattr(attach_obj, attach_port)
1664078Sbinkertn@umich.edu               make_level(spec[1:], prototypes[1:], cache, "cpu_side")
1674078Sbinkertn@umich.edu     else:
1684078Sbinkertn@umich.edu          # we just built the MemTest objects
1694078Sbinkertn@umich.edu          parent.cpu = objs
1704078Sbinkertn@umich.edu          for t in objs:
1714078Sbinkertn@umich.edu               t.test = getattr(attach_obj, attach_port)
1725606Snate@binkert.org               t.functional = system.funcmem.port
1735606Snate@binkert.org
1745606Snate@binkert.orgmake_level(treespec, prototypes, system.physmem, "port")
1755606Snate@binkert.org
1764078Sbinkertn@umich.edu# -----------------------
177695SN/A# run simulation
178695SN/A# -----------------------
1794078Sbinkertn@umich.edu
1804078Sbinkertn@umich.eduroot = Root( full_system = False, system = system )
181695SN/Aif options.atomic:
1825606Snate@binkert.org    root.system.mem_mode = 'atomic'
1835606Snate@binkert.orgelse:
184695SN/A    root.system.mem_mode = 'timing'
185695SN/A
186729SN/A# The system port is never used in the tester so merely connect it
187# to avoid problems
188root.system.system_port = root.system.physmem.port
189
190# Not much point in this being higher than the L1 latency
191m5.ticks.setGlobalFrequency('1ns')
192
193# instantiate configuration
194m5.instantiate()
195
196# simulate until program terminates
197exit_event = m5.simulate(options.maxtick)
198
199print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()
200