From d55b25cde6d2c072885a2c468d209fb18d6628e6 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 6 Mar 2007 11:13:43 -0800 Subject: [PATCH] Move all of the parameters of the Root SimObject so they are directly configured by python. Move stuff from root.(cc|hh) to core.(cc|hh) since it really belogs there now. In the process, simplify how ticks are used in the python code. --HG-- extra : convert_revision : cf82ee1ea20f9343924f30bacc2a38d4edee8df3 --- configs/common/FSConfig.py | 1 - configs/common/Simulation.py | 2 +- configs/example/fs.py | 2 +- src/base/annotate.cc | 2 +- src/base/misc.cc | 2 +- src/base/pollevent.cc | 2 +- src/base/pollevent.hh | 2 +- src/base/trace.hh | 2 +- src/cpu/o3/cpu.cc | 2 +- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/o3/inst_queue_impl.hh | 2 +- src/cpu/ozone/inst_queue_impl.hh | 2 +- src/cpu/pc_event.cc | 2 +- src/cpu/static_inst.cc | 2 +- src/dev/etherbus.cc | 2 +- src/dev/etherdump.cc | 2 +- src/dev/etherlink.cc | 2 +- src/dev/ide_disk.cc | 2 +- src/dev/pcidev.cc | 2 +- src/kern/tru64/tru64.hh | 2 +- src/mem/cache/cache_blk.hh | 2 +- src/mem/cache/miss/mshr.cc | 2 +- src/mem/cache/tags/iic.cc | 2 +- src/mem/cache/tags/lru.cc | 2 +- src/mem/cache/tags/split_lifo.cc | 2 +- src/mem/cache/tags/split_lru.cc | 2 +- src/mem/packet.hh | 2 +- src/mem/request.hh | 2 +- src/python/m5/__init__.py | 9 +- src/python/m5/convert.py | 23 +++- src/python/m5/event.py | 42 +++++++ src/python/m5/main.py | 3 +- src/python/m5/objects/BaseCPU.py | 4 +- src/python/m5/objects/PhysicalMemory.py | 2 +- src/python/m5/objects/Root.py | 7 +- src/python/m5/params.py | 130 ++++++++++---------- src/python/m5/ticks.py | 89 ++++++++++++++ src/python/swig/core.i | 8 ++ src/python/swig/event.i | 5 - src/sim/builder.cc | 2 +- src/sim/core.cc | 64 ++++++++++ src/sim/core.hh | 49 +++++++- src/sim/eventq.cc | 2 +- src/sim/main.cc | 2 +- src/sim/root.cc | 99 +-------------- src/sim/sim_events.cc | 18 --- src/sim/sim_events.hh | 19 --- tests/configs/t1000-simple-atomic.py | 4 +- tests/configs/tsunami-simple-atomic-dual.py | 6 +- tests/configs/tsunami-simple-atomic.py | 5 +- tests/configs/tsunami-simple-timing-dual.py | 5 +- tests/configs/tsunami-simple-timing.py | 5 +- 52 files changed, 397 insertions(+), 260 deletions(-) create mode 100644 src/python/m5/event.py create mode 100644 src/python/m5/ticks.py diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index da35698f2..be3f5ff79 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -132,5 +132,4 @@ def makeDualRoot(testSystem, driveSystem, dumpfile): self.etherdump = EtherDump(file=dumpfile) self.etherlink.dump = Parent.etherdump - self.clock = '1THz' return self diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 8374d2fb5..61b14f026 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -64,7 +64,7 @@ def run(options, root, testsys, cpu_class): if options.maxtick: maxtick = options.maxtick elif options.maxtime: - simtime = int(options.maxtime * root.clock.value) + simtime = m5.ticks.seconds(simtime) print "simulating for: ", simtime maxtick = simtime else: diff --git a/configs/example/fs.py b/configs/example/fs.py index b878f2bd4..bd4637e95 100644 --- a/configs/example/fs.py +++ b/configs/example/fs.py @@ -137,7 +137,7 @@ if len(bm) == 2: drive_sys.cpu.connectMemPorts(drive_sys.membus) root = makeDualRoot(test_sys, drive_sys, options.etherdump) elif len(bm) == 1: - root = Root(clock = '1THz', system = test_sys) + root = Root(system=test_sys) else: print "Error I don't know how to create more than 2 systems." sys.exit(1) diff --git a/src/base/annotate.cc b/src/base/annotate.cc index ba2fb1788..de7eeed51 100644 --- a/src/base/annotate.cc +++ b/src/base/annotate.cc @@ -32,7 +32,7 @@ #include "base/callback.hh" #include "base/output.hh" #include "base/trace.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/sim_exit.hh" #include "sim/system.hh" diff --git a/src/base/misc.cc b/src/base/misc.cc index 29b6d2d88..afb48ca80 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -38,7 +38,7 @@ #include "base/trace.hh" #include "base/varargs.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/base/pollevent.cc b/src/base/pollevent.cc index 32724b74d..331b5eac6 100644 --- a/src/base/pollevent.cc +++ b/src/base/pollevent.cc @@ -42,7 +42,7 @@ #include "sim/host.hh" #include "base/misc.hh" #include "base/pollevent.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/serialize.hh" using namespace std; diff --git a/src/base/pollevent.hh b/src/base/pollevent.hh index 5b84650cb..ecaeb94ce 100644 --- a/src/base/pollevent.hh +++ b/src/base/pollevent.hh @@ -33,7 +33,7 @@ #include #include -#include "sim/root.hh" +#include "sim/core.hh" class Checkpoint; class PollQueue; diff --git a/src/base/trace.hh b/src/base/trace.hh index 8e380d8e1..c1b506187 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -39,7 +39,7 @@ #include "base/match.hh" #include "base/traceflags.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" namespace Trace { diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 66c75a12d..785165636 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -45,7 +45,7 @@ #include "cpu/o3/isa_specific.hh" #include "cpu/o3/cpu.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/stat_control.hh" #if USE_CHECKER diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index e6a779823..ac0149d18 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -40,7 +40,7 @@ #include "mem/request.hh" #include "sim/byteswap.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" #if FULL_SYSTEM #include "arch/tlb.hh" diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 98b8fa900..d5781d89d 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -32,7 +32,7 @@ #include #include -#include "sim/root.hh" +#include "sim/core.hh" #include "cpu/o3/fu_pool.hh" #include "cpu/o3/inst_queue.hh" diff --git a/src/cpu/ozone/inst_queue_impl.hh b/src/cpu/ozone/inst_queue_impl.hh index 84f2b2a19..ea9d03c0d 100644 --- a/src/cpu/ozone/inst_queue_impl.hh +++ b/src/cpu/ozone/inst_queue_impl.hh @@ -38,7 +38,7 @@ #include -#include "sim/root.hh" +#include "sim/core.hh" #include "cpu/ozone/inst_queue.hh" #if 0 diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc index fca357fe3..7ab8bfcb8 100644 --- a/src/cpu/pc_event.cc +++ b/src/cpu/pc_event.cc @@ -40,7 +40,7 @@ #include "cpu/thread_context.hh" #include "cpu/pc_event.hh" #include "sim/debug.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/system.hh" using namespace std; diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index cb4a7cdf7..64fcc0580 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -31,7 +31,7 @@ #include #include "cpu/static_inst.hh" -#include "sim/root.hh" +#include "sim/core.hh" StaticInstPtr StaticInst::nullStaticInstPtr; diff --git a/src/dev/etherbus.cc b/src/dev/etherbus.cc index 348bb818a..cedb3cd4d 100644 --- a/src/dev/etherbus.cc +++ b/src/dev/etherbus.cc @@ -43,7 +43,7 @@ #include "dev/etherint.hh" #include "dev/etherpkt.hh" #include "sim/builder.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/dev/etherdump.cc b/src/dev/etherdump.cc index 0c986cc21..04463f3ee 100644 --- a/src/dev/etherdump.cc +++ b/src/dev/etherdump.cc @@ -41,7 +41,7 @@ #include "base/output.hh" #include "dev/etherdump.hh" #include "sim/builder.hh" -#include "sim/root.hh" +#include "sim/core.hh" using std::string; diff --git a/src/dev/etherlink.cc b/src/dev/etherlink.cc index cd3812270..5d30e1744 100644 --- a/src/dev/etherlink.cc +++ b/src/dev/etherlink.cc @@ -47,7 +47,7 @@ #include "sim/builder.hh" #include "sim/serialize.hh" #include "sim/system.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index 5083c9c8d..9fa0cedde 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -48,7 +48,7 @@ #include "dev/alpha/tsunami_pchip.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "arch/isa_traits.hh" using namespace std; diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index 1c2465dd1..f906e69cf 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -51,7 +51,7 @@ #include "sim/builder.hh" #include "sim/byteswap.hh" #include "sim/param.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index 82db34bf6..6645aa865 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -56,7 +56,7 @@ class Tru64 {}; #include #include "cpu/base.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/syscall_emul.hh" typedef struct stat global_stat; diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index a4df1b03f..fa00a0f5a 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -37,7 +37,7 @@ #include -#include "sim/root.hh" // for Tick +#include "sim/core.hh" // for Tick #include "arch/isa_traits.hh" // for Addr #include "mem/request.hh" diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index 352d1ec6f..74dad658b 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -39,7 +39,7 @@ #include #include "mem/cache/miss/mshr.hh" -#include "sim/root.hh" // for curTick +#include "sim/core.hh" // for curTick #include "sim/host.hh" #include "base/misc.hh" #include "mem/cache/cache.hh" diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index 20e2ef0ac..9c802d0dc 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -42,7 +42,7 @@ #include "mem/cache/base_cache.hh" #include "mem/cache/tags/iic.hh" #include "base/intmath.hh" -#include "sim/root.hh" // for curTick +#include "sim/core.hh" // for curTick #include "base/trace.hh" // for DPRINTF diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 102bb3506..8e8779774 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -38,7 +38,7 @@ #include "mem/cache/base_cache.hh" #include "base/intmath.hh" #include "mem/cache/tags/lru.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/mem/cache/tags/split_lifo.cc b/src/mem/cache/tags/split_lifo.cc index 792ff8fa7..d71d1a3ef 100644 --- a/src/mem/cache/tags/split_lifo.cc +++ b/src/mem/cache/tags/split_lifo.cc @@ -38,7 +38,7 @@ #include "mem/cache/base_cache.hh" #include "base/intmath.hh" #include "mem/cache/tags/split_lifo.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "base/trace.hh" using namespace std; diff --git a/src/mem/cache/tags/split_lru.cc b/src/mem/cache/tags/split_lru.cc index c37d72cb7..7227fb5c1 100644 --- a/src/mem/cache/tags/split_lru.cc +++ b/src/mem/cache/tags/split_lru.cc @@ -38,7 +38,7 @@ #include "mem/cache/base_cache.hh" #include "base/intmath.hh" #include "mem/cache/tags/split_lru.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 16410594a..dc23e9f6d 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -46,7 +46,7 @@ #include "base/misc.hh" #include "mem/request.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" struct Packet; diff --git a/src/mem/request.hh b/src/mem/request.hh index 43d8ff1d5..d2ebc91d3 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -40,7 +40,7 @@ #define __MEM_REQUEST_HH__ #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 30ebcfe7d..6eac7b6d7 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -36,7 +36,7 @@ import internal # import a few SWIG-wrapped items (those that are likely to be used # directly by user scripts) completely into this module for # convenience -from internal.event import SimLoopExitEvent +import event # import the m5 compile options import defines @@ -80,7 +80,9 @@ env.update(os.environ) # The final hook to generate .ini files. Called from the user script # once the config is built. def instantiate(root): - params.ticks_per_sec = float(root.clock.frequency) + # we need to fix the global frequency + ticks.fixGlobalFrequency() + root.unproxy_all() # ugly temporary hack to get output to config.ini sys.stdout = file(os.path.join(options.outdir, 'config.ini'), 'w') @@ -94,6 +96,7 @@ def instantiate(root): # Initialize the global statistics internal.stats.initSimStats() + # Create the C++ sim objects and connect ports root.createCCObject() root.connectPorts() @@ -136,7 +139,7 @@ def simulate(*args, **kwargs): # Export curTick to user script. def curTick(): - return internal.event.cvar.curTick + return internal.core.cvar.curTick # Python exit handlers happen in reverse order. We want to dump stats last. atexit.register(internal.stats.dump) diff --git a/src/python/m5/convert.py b/src/python/m5/convert.py index 580a579bc..bb9e3e1f1 100644 --- a/src/python/m5/convert.py +++ b/src/python/m5/convert.py @@ -148,7 +148,7 @@ def toLatency(value): raise ValueError, "cannot convert '%s' to latency" % value -def toClockPeriod(value): +def anyToLatency(value): """result is a clock period""" if not isinstance(value, str): @@ -170,6 +170,27 @@ def toClockPeriod(value): raise ValueError, "cannot convert '%s' to clock period" % value +def anyToFrequency(value): + """result is a clock period""" + + if not isinstance(value, str): + raise TypeError, "wrong type '%s' should be str" % type(value) + + try: + val = toFrequency(value) + return val + except ValueError: + pass + + try: + val = toLatency(value) + if val != 0: + val = 1 / val + return val + except ValueError: + pass + + raise ValueError, "cannot convert '%s' to clock period" % value def toNetworkBandwidth(value): if not isinstance(value, str): diff --git a/src/python/m5/event.py b/src/python/m5/event.py new file mode 100644 index 000000000..2d6497464 --- /dev/null +++ b/src/python/m5/event.py @@ -0,0 +1,42 @@ +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from internal.event import create +from internal.event import SimLoopExitEvent as SimExit + +class ProgressEvent(object): + def __init__(self, period): + self.period = int(period) + self.schedule() + + def schedule(self): + create(self, m5.curTick() + self.period) + + def __call__(self): + print "Progress! Time now %fs" % (m5.curTick()/1e12) + self.schedule() diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 54368b91e..1695ed75f 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -188,6 +188,7 @@ def parse_args(): def main(): import defines + import event import info import internal @@ -295,7 +296,7 @@ def main(): if options.trace_start: def enable_trace(): internal.trace.cvar.enabled = True - internal.event.create(enable_trace, int(options.trace_start)) + event.create(enable_trace, int(options.trace_start)) else: internal.trace.cvar.enabled = True diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py index 67a28a61e..986220c3f 100644 --- a/src/python/m5/objects/BaseCPU.py +++ b/src/python/m5/objects/BaseCPU.py @@ -47,8 +47,8 @@ class BaseCPU(SimObject): defer_registration = Param.Bool(False, "defer registration with system (for sampling)") - clock = Param.Clock(Parent.clock, "clock speed") - phase = Param.Latency("0ns", "clock phase") + clock = Param.Clock('1t', "clock speed") + phase = Param.Latency('0ns', "clock phase") _mem_ports = [] diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py index b8df6229e..c389e4a7f 100644 --- a/src/python/m5/objects/PhysicalMemory.py +++ b/src/python/m5/objects/PhysicalMemory.py @@ -8,7 +8,7 @@ class PhysicalMemory(MemObject): functional = Port("Functional Access Port") range = Param.AddrRange(AddrRange('128MB'), "Device Address") file = Param.String('', "memory mapped file") - latency = Param.Latency(Parent.clock, "latency of an access") + latency = Param.Latency('1t', "latency of an access") zero = Param.Bool(False, "zero initialize memory") class DRAMMemory(PhysicalMemory): diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py index 8db4fa5a2..2b0e736e7 100644 --- a/src/python/m5/objects/Root.py +++ b/src/python/m5/objects/Root.py @@ -3,9 +3,4 @@ from m5.params import * class Root(SimObject): type = 'Root' - clock = Param.RootClock('1THz', "tick frequency") - max_tick = Param.Tick('0', "maximum simulation ticks (0 = infinite)") - progress_interval = Param.Tick('0', - "print a progress message every n ticks (0 = never)") - output_file = Param.String('cout', "file to dump simulator output to") - checkpoint = Param.String('', "checkpoint file to load") + dummy = Param.Int(0, "We don't support objects without params") diff --git a/src/python/m5/params.py b/src/python/m5/params.py index e71e1c3c5..7c60a8554 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -51,6 +51,7 @@ import sys import time import convert +import ticks from util import * # Dummy base class to identify types that are legitimate for SimObject @@ -632,47 +633,29 @@ class Enum(ParamValue): def __str__(self): return self.value -ticks_per_sec = None - # how big does a rounding error need to be before we warn about it? frequency_tolerance = 0.001 # 0.1% -# convert a floting-point # of ticks to integer, and warn if rounding -# discards too much precision -def tick_check(float_ticks): - if float_ticks == 0: - return 0 - int_ticks = int(round(float_ticks)) - err = (float_ticks - int_ticks) / float_ticks - if err > frequency_tolerance: - print >> sys.stderr, "Warning: rounding error > tolerance" - print >> sys.stderr, " %f rounded to %d" % (float_ticks, int_ticks) - #raise ValueError - return int_ticks - -def getLatency(value): - if isinstance(value, Latency) or isinstance(value, Clock): - return value.value - elif isinstance(value, Frequency) or isinstance(value, RootClock): - return 1 / value.value - elif isinstance(value, str): - try: - return convert.toLatency(value) - except ValueError: - try: - return 1 / convert.toFrequency(value) - except ValueError: - pass # fall through - raise ValueError, "Invalid Frequency/Latency value '%s'" % value - - -class Latency(NumericParamValue): +class TickParamValue(NumericParamValue): cxx_type = 'Tick' cxx_predecls = ['#include "sim/host.hh"'] swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + '%import "sim/host.hh"'] + +class Latency(TickParamValue): def __init__(self, value): - self.value = getLatency(value) + if isinstance(value, (Latency, Clock)): + self.ticks = value.ticks + self.value = value.value + elif isinstance(value, Frequency): + self.ticks = value.ticks + self.value = 1.0 / value.value + elif value.endswith('t'): + self.ticks = True + self.value = int(value[:-1]) + else: + self.ticks = False + self.value = convert.toLatency(value) def __getattr__(self, attr): if attr in ('latency', 'period'): @@ -683,15 +666,25 @@ class Latency(NumericParamValue): # convert latency to ticks def ini_str(self): - return str(tick_check(self.value * ticks_per_sec)) + if self.ticks or self.value == 0: + return '%d' % self.value + else: + return '%d' % (ticks.fromSeconds(self.value)) -class Frequency(NumericParamValue): - cxx_type = 'Tick' - cxx_predecls = ['#include "sim/host.hh"'] - swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + - '%import "sim/host.hh"'] +class Frequency(TickParamValue): def __init__(self, value): - self.value = 1 / getLatency(value) + if isinstance(value, (Latency, Clock)): + if value.value == 0: + self.value = 0 + else: + self.value = 1.0 / value.value + self.ticks = value.ticks + elif isinstance(value, Frequency): + self.value = value.value + self.ticks = value.ticks + else: + self.ticks = False + self.value = convert.toFrequency(value) def __getattr__(self, attr): if attr == 'frequency': @@ -700,30 +693,12 @@ class Frequency(NumericParamValue): return Latency(self) raise AttributeError, "Frequency object has no attribute '%s'" % attr - # convert frequency to ticks per period - def ini_str(self): - return self.period.ini_str() - -# Just like Frequency, except ini_str() is absolute # of ticks per sec (Hz). -# We can't inherit from Frequency because we don't want it to be directly -# assignable to a regular Frequency parameter. -class RootClock(ParamValue): - cxx_type = 'Tick' - cxx_predecls = ['#include "sim/host.hh"'] - swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + - '%import "sim/host.hh"'] - def __init__(self, value): - self.value = 1 / getLatency(value) - - def __getattr__(self, attr): - if attr == 'frequency': - return Frequency(self) - if attr in ('latency', 'period'): - return Latency(self) - raise AttributeError, "Frequency object has no attribute '%s'" % attr - + # convert latency to ticks def ini_str(self): - return str(tick_check(self.value)) + if self.ticks or self.value == 0: + return '%d' % self.value + else: + return '%d' % (ticks.fromSeconds(1.0 / self.value)) # A generic frequency and/or Latency value. Value is stored as a latency, # but to avoid ambiguity this object does not support numeric ops (* or /). @@ -734,7 +709,18 @@ class Clock(ParamValue): swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + '%import "sim/host.hh"'] def __init__(self, value): - self.value = getLatency(value) + if isinstance(value, (Latency, Clock)): + self.ticks = value.ticks + self.value = value.value + elif isinstance(value, Frequency): + self.ticks = value.ticks + self.value = 1.0 / value.value + elif value.endswith('t'): + self.ticks = True + self.value = int(value[:-1]) + else: + self.ticks = False + self.value = convert.anyToLatency(value) def __getattr__(self, attr): if attr == 'frequency': @@ -749,18 +735,23 @@ class Clock(ParamValue): class NetworkBandwidth(float,ParamValue): cxx_type = 'float' def __new__(cls, value): - val = convert.toNetworkBandwidth(value) / 8.0 + # convert to bits per second + val = convert.toNetworkBandwidth(value) return super(cls, NetworkBandwidth).__new__(cls, val) def __str__(self): return str(self.val) def ini_str(self): - return '%f' % (ticks_per_sec / float(self)) + # convert to seconds per byte + value = 8.0 / float(self) + # convert to ticks per byte + return '%f' % (ticks.fromSeconds(value)) class MemoryBandwidth(float,ParamValue): cxx_type = 'float' def __new__(self, value): + # we want the number of ticks per byte of data val = convert.toMemoryBandwidth(value) return super(cls, MemoryBandwidth).__new__(cls, val) @@ -768,7 +759,10 @@ class MemoryBandwidth(float,ParamValue): return str(self.val) def ini_str(self): - return '%f' % (ticks_per_sec / float(self)) + # convert to seconds per byte + value = 1.0 / float(self) + # convert to ticks per byte + return '%f' % (ticks.fromSeconds(value)) # # "Constants"... handy aliases for various values. @@ -1023,7 +1017,7 @@ __all__ = ['Param', 'VectorParam', 'Counter', 'Addr', 'Tick', 'Percent', 'TcpPort', 'UdpPort', 'EthernetAddr', 'MemorySize', 'MemorySize32', - 'Latency', 'Frequency', 'RootClock', 'Clock', + 'Latency', 'Frequency', 'Clock', 'NetworkBandwidth', 'MemoryBandwidth', 'Range', 'AddrRange', 'TickRange', 'MaxAddr', 'MaxTick', 'AllMemory', diff --git a/src/python/m5/ticks.py b/src/python/m5/ticks.py new file mode 100644 index 000000000..e91b470ff --- /dev/null +++ b/src/python/m5/ticks.py @@ -0,0 +1,89 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import sys + +import convert +import internal + +tps = 1.0e12 # default to 1 THz (1 Tick == 1 ps) +tps_fixed = False # once set to true, can't be changed + +# fix the global frequency and tell C++ about it +def fixGlobalFrequency(): + global tps, tps_fixed + if not tps_fixed: + tps_fixed = True + internal.core.setClockFrequency(int(tps)) + print "Global frequency set at %d ticks per second" % int(tps) + +def setGlobalFrequency(ticksPerSecond): + global tps, tps_fixed + + if tps_fixed: + raise AttributeError, \ + "Global frequency already fixed at %f ticks/s." % tps + + if isinstance(ticksPerSecond, (int, long)): + tps = ticksPerSecond + elif isinstance(ticksPerSecond, float): + tps = ticksPerSecond + elif isinstance(ticksPerSecond, str): + tps = round(convert.anyToFrequency(ticksPerSecond)) + else: + raise TypeError, \ + "wrong type '%s' for ticksPerSecond" % type(ticksPerSecond) + +# how big does a rounding error need to be before we warn about it? +frequency_tolerance = 0.001 # 0.1% + +def fromSeconds(value): + if not isinstance(value, float): + raise TypeError, "can't convert '%s' to type tick" % type(value) + + # once someone needs to convert to seconds, the global frequency + # had better be fixed + if not tps_fixed: + raise AttributeError, \ + "In order to do conversions, the global frequency must be fixed" + + if value == 0: + return 0 + + # convert the value from time to ticks + value *= tps + + int_value = int(round(value)) + err = (value - int_value) / value + if err > frequency_tolerance: + print >>sys.stderr, "Warning: rounding error > tolerance" + print >>sys.stderr, " %f rounded to %d" % (value, int_value) + return int_value + +__all__ = [ 'setGlobalFrequency', 'fixGlobalFrequency', 'fromSeconds', + 'frequency_tolerance' ] diff --git a/src/python/swig/core.i b/src/python/swig/core.i index 116890763..3edfa4c7e 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -41,15 +41,23 @@ extern const char *compileDate; %} +%include "stdint.i" %include "std_string.i" +%include "sim/host.hh" void setOutputDir(const std::string &dir); +void setOutputFile(const std::string &file); void loadIniFile(PyObject *); void SimStartup(); void doExitCleanup(); char *compileDate; +void setClockFrequency(Tick ticksPerSecond); + +%immutable curTick; +Tick curTick; + %wrapper %{ // fix up module name to reflect the fact that it's inside the m5 package #undef SWIG_name diff --git a/src/python/swig/event.i b/src/python/swig/event.i index 51d7d89f0..9a2093c99 100644 --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -53,9 +53,6 @@ class CountedDrainEvent : public Event { CountedDrainEvent *createCountedDrain(); void cleanupCountedDrain(Event *drain_event); -%immutable curTick; -Tick curTick; - // minimal definition of SimExitEvent interface to wrap class SimLoopExitEvent { public: @@ -74,8 +71,6 @@ class SimLoopExitEvent { SimLoopExitEvent *simulate(Tick num_cycles = MaxTick); void exitSimLoop(const std::string &message, int exit_code); -Tick curTick; - %wrapper %{ // fix up module name to reflect the fact that it's inside the m5 package #undef SWIG_name diff --git a/src/sim/builder.cc b/src/sim/builder.cc index 8ef54ce52..532df36b1 100644 --- a/src/sim/builder.cc +++ b/src/sim/builder.cc @@ -35,7 +35,7 @@ #include "sim/builder.hh" #include "sim/host.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/sim/core.cc b/src/sim/core.cc index 24cc33da2..c961e9eb8 100644 --- a/src/sim/core.cc +++ b/src/sim/core.cc @@ -34,15 +34,78 @@ #include "base/callback.hh" #include "base/output.hh" +#include "sim/core.hh" using namespace std; +Tick curTick = 0; + +namespace Clock { +/// The simulated frequency of curTick. (In ticks per second) +Tick Frequency; + +namespace Float { +double s; +double ms; +double us; +double ns; +double ps; + +double Hz; +double kHz; +double MHz; +double GHZ; +/* namespace Float */ } + +namespace Int { +Tick s; +Tick ms; +Tick us; +Tick ns; +Tick ps; +/* namespace Float */ } + +/* namespace Clock */ } + +void +setClockFrequency(Tick ticksPerSecond) +{ + using namespace Clock; + Frequency = ticksPerSecond; + Float::s = static_cast(Frequency); + Float::ms = Float::s / 1.0e3; + Float::us = Float::s / 1.0e6; + Float::ns = Float::s / 1.0e9; + Float::ps = Float::s / 1.0e12; + + Float::Hz = 1.0 / Float::s; + Float::kHz = 1.0 / Float::ms; + Float::MHz = 1.0 / Float::us; + Float::GHZ = 1.0 / Float::ns; + + Int::s = Frequency; + Int::ms = Int::s / 1000; + Int::us = Int::ms / 1000; + Int::ns = Int::us / 1000; + Int::ps = Int::ns / 1000; + +} + void setOutputDir(const string &dir) { simout.setDirectory(dir); } +ostream *outputStream; +ostream *configStream; + +void +setOutputFile(const string &file) +{ + outputStream = simout.find(file); +} + /** * Queue of C++ callbacks to invoke on simulator exit. */ @@ -74,3 +137,4 @@ doExitCleanup() cout.flush(); } + diff --git a/src/sim/core.hh b/src/sim/core.hh index 2ef21c4b6..7360032c2 100644 --- a/src/sim/core.hh +++ b/src/sim/core.hh @@ -29,12 +29,57 @@ * Steve Reinhardt */ -#include +#ifndef __SIM_CORE_HH__ +#define __SIM_CORE_HH__ + #include -#include "base/callback.hh" +#include "sim/host.hh" + +/// The universal simulation clock. +extern Tick curTick; +const Tick retryTime = 1000; + +namespace Clock { +/// The simulated frequency of curTick. +extern Tick Frequency; + +namespace Float { +extern double s; +extern double ms; +extern double us; +extern double ns; +extern double ps; + +extern double Hz; +extern double kHz; +extern double MHz; +extern double GHZ; +/* namespace Float */ } +namespace Int { +extern Tick s; +extern Tick ms; +extern Tick us; +extern Tick ns; +extern Tick ps; +/* namespace Int */ } +/* namespace Clock */ } + +void setClockFrequency(Tick ticksPerSecond); + +/// Output stream for simulator messages (e.g., cprintf()). Also used +/// as default stream for tracing and DPRINTF() messages (unless +/// overridden with trace:file option). +extern std::ostream *outputStream; +void setOutputFile(const std::string &file); void setOutputDir(const std::string &dir); +/// Output stream for configuration dump. +extern std::ostream *configStream; + +struct Callback; void registerExitCallback(Callback *callback); void doExitCleanup(); + +#endif /* __SIM_CORE_HH__ */ diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 356472d9a..bcd0d3df3 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -41,7 +41,7 @@ #include "sim/eventq.hh" #include "base/trace.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/sim/main.cc b/src/sim/main.cc index 0341b7d5f..5bf4add4b 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -40,7 +40,7 @@ #include "python/swig/init.hh" #include "sim/async.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/sim/root.cc b/src/sim/root.cc index 565b57269..f4743af0a 100644 --- a/src/sim/root.cc +++ b/src/sim/root.cc @@ -36,91 +36,24 @@ #include #include "base/misc.hh" -#include "base/output.hh" #include "sim/builder.hh" -#include "sim/host.hh" -#include "sim/sim_events.hh" -#include "sim/sim_exit.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" - -using namespace std; - -Tick curTick = 0; -ostream *outputStream; -ostream *configStream; - -/// The simulated frequency of curTick. (This is only here for a short time) -Tick ticksPerSecond; - -namespace Clock { -/// The simulated frequency of curTick. (In ticks per second) -Tick Frequency; - -namespace Float { -double s; -double ms; -double us; -double ns; -double ps; - -double Hz; -double kHz; -double MHz; -double GHZ; -/* namespace Float */ } - -namespace Int { -Tick s; -Tick ms; -Tick us; -Tick ns; -Tick ps; -/* namespace Float */ } - -/* namespace Clock */ } - // Dummy Object -class Root : public SimObject +struct Root : public SimObject { - private: - Tick max_tick; - Tick progress_interval; - - public: - Root(const std::string &name, Tick maxtick, Tick pi) - : SimObject(name), max_tick(maxtick), progress_interval(pi) - {} - - virtual void startup(); + Root(const std::string &name) : SimObject(name) {} }; -void -Root::startup() -{ - if (max_tick != 0) - schedExitSimLoop("reached maximum cycle count", curTick + max_tick); - - if (progress_interval != 0) - new ProgressEvent(&mainEventQueue, progress_interval); -} - BEGIN_DECLARE_SIM_OBJECT_PARAMS(Root) - Param clock; - Param max_tick; - Param progress_interval; - Param output_file; + Param dummy; // needed below END_DECLARE_SIM_OBJECT_PARAMS(Root) BEGIN_INIT_SIM_OBJECT_PARAMS(Root) - INIT_PARAM(clock, "tick frequency"), - INIT_PARAM(max_tick, "maximum simulation time"), - INIT_PARAM(progress_interval, "print a progress message"), - INIT_PARAM(output_file, "file to dump simulator output to") + INIT_PARAM(dummy, "") // All SimObjects must have params END_INIT_SIM_OBJECT_PARAMS(Root) @@ -132,29 +65,7 @@ CREATE_SIM_OBJECT(Root) created = true; - outputStream = simout.find(output_file); - Root *root = new Root(getInstanceName(), max_tick, progress_interval); - - using namespace Clock; - Frequency = clock; - Float::s = static_cast(Frequency); - Float::ms = Float::s / 1.0e3; - Float::us = Float::s / 1.0e6; - Float::ns = Float::s / 1.0e9; - Float::ps = Float::s / 1.0e12; - - Float::Hz = 1.0 / Float::s; - Float::kHz = 1.0 / Float::ms; - Float::MHz = 1.0 / Float::us; - Float::GHZ = 1.0 / Float::ns; - - Int::s = Frequency; - Int::ms = Int::s / 1000; - Int::us = Int::ms / 1000; - Int::ns = Int::us / 1000; - Int::ps = Int::ns / 1000; - - return root; + return new Root(getInstanceName()); } REGISTER_SIM_OBJECT("Root", Root) diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 2ccc9dad2..a4457a11c 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -158,21 +158,3 @@ CheckSwapEvent::description() { return "check swap"; } - -// -// handle progress event: print message and reschedule -// -void -ProgressEvent::process() -{ - DPRINTFN("ProgressEvent\n"); - // reschedule for next interval - schedule(curTick + interval); -} - - -const char * -ProgressEvent::description() -{ - return "progress message"; -} diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index e1576b38c..94e2540b1 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -125,23 +125,4 @@ class CheckSwapEvent : public Event virtual const char *description(); }; -// -// Progress event: print out cycle every so often so we know we're -// making forward progress. -// -class ProgressEvent : public Event -{ - protected: - Tick interval; - - public: - ProgressEvent(EventQueue *q, Tick ival) - : Event(q), interval(ival) - { schedule(curTick + interval); } - - void process(); // process event - - virtual const char *description(); -}; - #endif // __SIM_SIM_EVENTS_HH__ diff --git a/tests/configs/t1000-simple-atomic.py b/tests/configs/t1000-simple-atomic.py index 51745892a..6a078e715 100644 --- a/tests/configs/t1000-simple-atomic.py +++ b/tests/configs/t1000-simple-atomic.py @@ -36,4 +36,6 @@ system = FSConfig.makeSparcSystem('atomic') system.cpu = cpu cpu.connectMemPorts(system.membus) -root = Root(clock = '2GHz', system = system) +root = Root(system=system) + +m5.ticks.setGlobalFrequency('2GHz') diff --git a/tests/configs/tsunami-simple-atomic-dual.py b/tests/configs/tsunami-simple-atomic-dual.py index 4adb32868..7ed854f44 100644 --- a/tests/configs/tsunami-simple-atomic-dual.py +++ b/tests/configs/tsunami-simple-atomic-dual.py @@ -1,4 +1,4 @@ -# Copyright (c) 2006 The Regents of The University of Michigan +# Copyright (c) 2006-2007 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,4 +37,6 @@ system.cpu = cpus for c in cpus: c.connectMemPorts(system.membus) -root = Root(clock = '2GHz', system = system) +root = Root(system=system) + +m5.ticks.setGlobalFrequency('2GHz') diff --git a/tests/configs/tsunami-simple-atomic.py b/tests/configs/tsunami-simple-atomic.py index 653df9bb0..4859f30cf 100644 --- a/tests/configs/tsunami-simple-atomic.py +++ b/tests/configs/tsunami-simple-atomic.py @@ -1,4 +1,4 @@ -# Copyright (c) 2006 The Regents of The University of Michigan +# Copyright (c) 2006-2007 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,4 +36,5 @@ system = FSConfig.makeLinuxAlphaSystem('atomic') system.cpu = cpu cpu.connectMemPorts(system.membus) -root = Root(clock = '2GHz', system = system) +root = Root(system=system) +m5.ticks.setGlobalFrequency('2GHz') diff --git a/tests/configs/tsunami-simple-timing-dual.py b/tests/configs/tsunami-simple-timing-dual.py index bfd478969..0c8c3d523 100644 --- a/tests/configs/tsunami-simple-timing-dual.py +++ b/tests/configs/tsunami-simple-timing-dual.py @@ -1,4 +1,4 @@ -# Copyright (c) 2006 The Regents of The University of Michigan +# Copyright (c) 2006-2007 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,4 +37,5 @@ system.cpu = cpus for c in cpus: c.connectMemPorts(system.membus) -root = Root(clock = '2GHz', system = system) +root = Root(system=system) +m5.ticks.setGlobalFrequency('2GHz') diff --git a/tests/configs/tsunami-simple-timing.py b/tests/configs/tsunami-simple-timing.py index 59401c040..9f532e3ae 100644 --- a/tests/configs/tsunami-simple-timing.py +++ b/tests/configs/tsunami-simple-timing.py @@ -1,4 +1,4 @@ -# Copyright (c) 2006 The Regents of The University of Michigan +# Copyright (c) 2006-2007 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,4 +36,5 @@ system = FSConfig.makeLinuxAlphaSystem('timing') system.cpu = cpu cpu.connectMemPorts(system.membus) -root = Root(clock = '2GHz', system = system) +root = Root(system=system) +m5.ticks.setGlobalFrequency('2GHz') -- 2.30.2