memtest.py revision 9267
12SN/A# Copyright (c) 2006-2007 The Regents of The University of Michigan
21762SN/A# All rights reserved.
38332Snate@binkert.org#
42SN/A# Redistribution and use in source and binary forms, with or without
52SN/A# modification, are permitted provided that the following conditions are
62SN/A# met: redistributions of source code must retain the above copyright
72SN/A# notice, this list of conditions and the following disclaimer;
82SN/A# redistributions in binary form must reproduce the above copyright
92SN/A# notice, this list of conditions and the following disclaimer in the
102SN/A# documentation and/or other materials provided with the distribution;
112SN/A# neither the name of the copyright holders nor the names of its
122SN/A# contributors may be used to endorse or promote products derived from
132SN/A# this software without specific prior written permission.
142SN/A#
152SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262SN/A#
272SN/A# Authors: Ron Dreslinski
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.eduimport optparse
302665Ssaidi@eecs.umich.eduimport sys
317861Sgblack@eecs.umich.edu
322SN/Aimport m5
332SN/Afrom m5.objects import *
34488SN/A
359356Snilay@cs.wisc.eduparser = optparse.OptionParser()
369048SAli.Saidi@ARM.com
378232Snate@binkert.orgparser.add_option("-a", "--atomic", action="store_true",
388801Sgblack@eecs.umich.edu                  help="Use atomic (non-timing) mode")
397861Sgblack@eecs.umich.eduparser.add_option("-b", "--blocking", action="store_true",
401609SN/A                  help="Use blocking caches")
417861Sgblack@eecs.umich.eduparser.add_option("-l", "--maxloads", metavar="N", default=0,
427861Sgblack@eecs.umich.edu                  help="Stop after N loads")
437861Sgblack@eecs.umich.eduparser.add_option("-m", "--maxtick", type="int", default=m5.MaxTick,
447861Sgblack@eecs.umich.edu                  metavar="T",
457861Sgblack@eecs.umich.edu                  help="Stop after T ticks")
467861Sgblack@eecs.umich.edu
477861Sgblack@eecs.umich.edu#
487861Sgblack@eecs.umich.edu# The "tree" specification is a colon-separated list of one or more
497861Sgblack@eecs.umich.edu# integers.  The first integer is the number of caches/testers
507861Sgblack@eecs.umich.edu# connected directly to main memory.  The last integer in the list is
512SN/A# the number of testers associated with the uppermost level of memory
527861Sgblack@eecs.umich.edu# (L1 cache, if there are caches, or main memory if no caches).  Thus
537861Sgblack@eecs.umich.edu# if there is only one integer, there are no caches, and the integer
547861Sgblack@eecs.umich.edu# specifies the number of testers connected directly to main memory.
557861Sgblack@eecs.umich.edu# The other integers (if any) specify the number of caches at each
567861Sgblack@eecs.umich.edu# level of the hierarchy between.
577861Sgblack@eecs.umich.edu#
587861Sgblack@eecs.umich.edu# Examples:
597861Sgblack@eecs.umich.edu#
607861Sgblack@eecs.umich.edu#  "2:1"    Two caches connected to memory with a single tester behind each
617861Sgblack@eecs.umich.edu#           (single-level hierarchy, two testers total)
627861Sgblack@eecs.umich.edu#
637861Sgblack@eecs.umich.edu#  "2:2:1"  Two-level hierarchy, 2 L1s behind each of 2 L2s, 4 testers total
647861Sgblack@eecs.umich.edu#
657861Sgblack@eecs.umich.eduparser.add_option("-t", "--treespec", type="string", default="8:1",
667861Sgblack@eecs.umich.edu                  help="Colon-separated multilevel tree specification, "
677861Sgblack@eecs.umich.edu                  "see script comments for details "
687861Sgblack@eecs.umich.edu                  "[default: %default]")
697861Sgblack@eecs.umich.edu
707861Sgblack@eecs.umich.eduparser.add_option("--force-bus", action="store_true",
717861Sgblack@eecs.umich.edu                  help="Use bus between levels even with single cache")
727861Sgblack@eecs.umich.edu
737861Sgblack@eecs.umich.eduparser.add_option("-f", "--functional", type="int", default=0,
747861Sgblack@eecs.umich.edu                  metavar="PCT",
757861Sgblack@eecs.umich.edu                  help="Target percentage of functional accesses "
767861Sgblack@eecs.umich.edu                  "[default: %default]")
777861Sgblack@eecs.umich.eduparser.add_option("-u", "--uncacheable", type="int", default=0,
787861Sgblack@eecs.umich.edu                  metavar="PCT",
797861Sgblack@eecs.umich.edu                  help="Target percentage of uncacheable accesses "
807861Sgblack@eecs.umich.edu                  "[default: %default]")
817861Sgblack@eecs.umich.edu
827861Sgblack@eecs.umich.eduparser.add_option("--progress", type="int", default=1000,
837861Sgblack@eecs.umich.edu                  metavar="NLOADS",
847861Sgblack@eecs.umich.edu                  help="Progress message interval "
857861Sgblack@eecs.umich.edu                  "[default: %default]")
867861Sgblack@eecs.umich.edu
877861Sgblack@eecs.umich.edu(options, args) = parser.parse_args()
887861Sgblack@eecs.umich.edu
897861Sgblack@eecs.umich.eduif args:
907861Sgblack@eecs.umich.edu     print "Error: script doesn't take any positional arguments"
917861Sgblack@eecs.umich.edu     sys.exit(1)
927861Sgblack@eecs.umich.edu
937863Sgblack@eecs.umich.edublock_size = 64
947861Sgblack@eecs.umich.edu
957861Sgblack@eecs.umich.edutry:
967861Sgblack@eecs.umich.edu     treespec = [int(x) for x in options.treespec.split(':')]
977861Sgblack@eecs.umich.edu     numtesters = reduce(lambda x,y: x*y, treespec)
987861Sgblack@eecs.umich.eduexcept:
997861Sgblack@eecs.umich.edu     print "Error parsing treespec option"
1007861Sgblack@eecs.umich.edu     sys.exit(1)
1017861Sgblack@eecs.umich.edu
1027861Sgblack@eecs.umich.eduif numtesters > block_size:
1037861Sgblack@eecs.umich.edu     print "Error: Number of testers limited to %s because of false sharing" \
1047861Sgblack@eecs.umich.edu           % (block_size)
1057861Sgblack@eecs.umich.edu     sys.exit(1)
1067861Sgblack@eecs.umich.edu
1077861Sgblack@eecs.umich.eduif len(treespec) < 1:
1087861Sgblack@eecs.umich.edu     print "Error parsing treespec"
1097863Sgblack@eecs.umich.edu     sys.exit(1)
1107863Sgblack@eecs.umich.edu
1117861Sgblack@eecs.umich.edu# define prototype L1 cache
1127861Sgblack@eecs.umich.eduproto_l1 = BaseCache(size = '32kB', assoc = 4, block_size = block_size,
1137861Sgblack@eecs.umich.edu                     hit_latency = '1ns', response_latency = '1ns',
1147861Sgblack@eecs.umich.edu                     tgts_per_mshr = 8)
1159983Sstever@gmail.com
1169983Sstever@gmail.comif options.blocking:
1177942SAli.Saidi@ARM.com     proto_l1.mshrs = 1
1187942SAli.Saidi@ARM.comelse:
1197942SAli.Saidi@ARM.com     proto_l1.mshrs = 4
1207942SAli.Saidi@ARM.com
1217942SAli.Saidi@ARM.com# build a list of prototypes, one for each level of treespec, starting
1227942SAli.Saidi@ARM.com# at the end (last entry is tester objects)
1237942SAli.Saidi@ARM.comprototypes = [ MemTest(atomic=options.atomic, max_loads=options.maxloads,
1247942SAli.Saidi@ARM.com                       percent_functional=options.functional,
1257942SAli.Saidi@ARM.com                       percent_uncacheable=options.uncacheable,
12610905Sandreas.sandberg@arm.com                       progress_interval=options.progress) ]
1277942SAli.Saidi@ARM.com
1289048SAli.Saidi@ARM.com# next comes L1 cache, if any
1297942SAli.Saidi@ARM.comif len(treespec) > 1:
1307861Sgblack@eecs.umich.edu     prototypes.insert(0, proto_l1)
1311104SN/A
1329048SAli.Saidi@ARM.com# now add additional cache levels (if any) by scaling L1 params
13310905Sandreas.sandberg@arm.comfor scale in treespec[:-2]:
1349048SAli.Saidi@ARM.com     # clone previous level and update params
1359048SAli.Saidi@ARM.com     prev = prototypes[0]
1369048SAli.Saidi@ARM.com     next = prev()
1379048SAli.Saidi@ARM.com     next.size = prev.size * scale
1389048SAli.Saidi@ARM.com     next.latency = prev.latency * 10
1399048SAli.Saidi@ARM.com     next.assoc = prev.assoc * scale
1409048SAli.Saidi@ARM.com     next.mshrs = prev.mshrs * scale
14110905Sandreas.sandberg@arm.com     prototypes.insert(0, next)
14211077SCurtis.Dunham@arm.com
1439048SAli.Saidi@ARM.com# system simulated
1449048SAli.Saidi@ARM.comsystem = System(funcmem = SimpleMemory(in_addr_map = False),
1458801Sgblack@eecs.umich.edu                funcbus = NoncoherentBus(),
1468901Sandreas.hansson@arm.com                physmem = SimpleMemory(latency = "100ns"))
1478801Sgblack@eecs.umich.edu
1484762Snate@binkert.orgdef make_level(spec, prototypes, attach_obj, attach_port):
1494762Snate@binkert.org     fanout = spec[0]
1501310SN/A     parent = attach_obj # use attach obj as config parent too
1511388SN/A     if len(spec) > 1 and (fanout > 1 or options.force_bus):
1521388SN/A          port = getattr(attach_obj, attach_port)
1531388SN/A          new_bus = CoherentBus(clock="500MHz", width=16)
1541388SN/A          if (port.role == 'MASTER'):
1551388SN/A               new_bus.slave = port
1561310SN/A               attach_port = "master"
1578801Sgblack@eecs.umich.edu          else:
1588901Sandreas.hansson@arm.com               new_bus.master = port
1598801Sgblack@eecs.umich.edu               attach_port = "slave"
1604762Snate@binkert.org          parent.cpu_side_bus = new_bus
1611310SN/A          attach_obj = new_bus
162     objs = [prototypes[0]() for i in xrange(fanout)]
163     if len(spec) > 1:
164          # we just built caches, more levels to go
165          parent.cache = objs
166          for cache in objs:
167               cache.mem_side = getattr(attach_obj, attach_port)
168               make_level(spec[1:], prototypes[1:], cache, "cpu_side")
169     else:
170          # we just built the MemTest objects
171          parent.cpu = objs
172          for t in objs:
173               t.test = getattr(attach_obj, attach_port)
174               t.functional = system.funcbus.slave
175
176make_level(treespec, prototypes, system.physmem, "port")
177
178# connect reference memory to funcbus
179system.funcbus.master = system.funcmem.port
180
181# -----------------------
182# run simulation
183# -----------------------
184
185root = Root( full_system = False, system = system )
186if options.atomic:
187    root.system.mem_mode = 'atomic'
188else:
189    root.system.mem_mode = 'timing'
190
191# The system port is never used in the tester so merely connect it
192# to avoid problems
193root.system.system_port = root.system.funcbus.slave
194
195# Not much point in this being higher than the L1 latency
196m5.ticks.setGlobalFrequency('1ns')
197
198# instantiate configuration
199m5.instantiate()
200
201# simulate until program terminates
202exit_event = m5.simulate(options.maxtick)
203
204print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()
205