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