sim: Add the notion of clock domains to all ClockedObjects
authorAkash Bagdia <akash.bagdia@arm.com>
Thu, 27 Jun 2013 09:49:49 +0000 (05:49 -0400)
committerAkash Bagdia <akash.bagdia@arm.com>
Thu, 27 Jun 2013 09:49:49 +0000 (05:49 -0400)
This patch adds the notion of source- and derived-clock domains to the
ClockedObjects. As such, all clock information is moved to the clock
domain, and the ClockedObjects are grouped into domains.

The clock domains are either source domains, with a specific clock
period, or derived domains that have a parent domain and a divider
(potentially chained). For piece of logic that runs at a derived clock
(a ratio of the clock its parent is running at) the necessary derived
clock domain is created from its corresponding parent clock
domain. For now, the derived clock domain only supports a divider,
thus ensuring a lower speed compared to its parent. Multiplier
functionality implies a PLL logic that has not been modelled yet
(create a separate clock instead).

The clock domains should be used as a mechanism to provide a
controllable clock source that affects clock for every clocked object
lying beneath it. The clock of the domain can (in a future patch) be
controlled by a handler responsible for dynamic frequency scaling of
the respective clock domains.

All the config scripts have been retro-fitted with clock domains. For
the System a default SrcClockDomain is created. For CPUs that run at a
different speed than the system, there is a seperate clock domain
created. This domain incorporates the CPU and the associated
caches. As before, Ruby runs under its own clock domain.

The clock period of all domains are pre-computed, such that no virtual
functions or multiplications are needed when calling
clockPeriod. Instead, the clock period is pre-computed when any
changes occur. For this to be possible, each clock domain tracks its
children.

43 files changed:
configs/common/CacheConfig.py
configs/common/Simulation.py
configs/example/fs.py
configs/example/memtest.py
configs/example/ruby_direct_test.py
configs/example/ruby_fs.py
configs/example/ruby_mem_test.py
configs/example/ruby_network_test.py
configs/example/ruby_random_test.py
configs/example/se.py
configs/ruby/MESI_CMP_directory.py
configs/ruby/MI_example.py
configs/ruby/MOESI_CMP_directory.py
configs/ruby/MOESI_CMP_token.py
configs/ruby/MOESI_hammer.py
configs/ruby/Network_test.py
configs/ruby/Ruby.py
src/arch/alpha/AlphaSystem.py
src/arch/mips/MipsSystem.py
src/cpu/BaseCPU.py
src/cpu/dummy_checker.cc
src/cpu/o3/checker.cc
src/dev/Ethernet.py
src/mem/ruby/system/RubyMemoryControl.py
src/sim/ClockDomain.py [new file with mode: 0644]
src/sim/ClockedObject.py
src/sim/SConscript
src/sim/clock_domain.cc [new file with mode: 0644]
src/sim/clock_domain.hh [new file with mode: 0644]
src/sim/clocked_object.hh
tests/configs/base_config.py
tests/configs/memtest-ruby.py
tests/configs/memtest.py
tests/configs/o3-timing-mp-ruby.py
tests/configs/o3-timing-ruby.py
tests/configs/pc-simple-timing-ruby.py
tests/configs/rubytest-ruby.py
tests/configs/simple-atomic-mp-ruby.py
tests/configs/simple-timing-mp-ruby.py
tests/configs/simple-timing-ruby.py
tests/configs/tgen-simple-dram.py
tests/configs/tgen-simple-mem.py
tests/configs/twosys-tsunami-simple-atomic.py

index 288a633ce50d580512d6795c59e8290269bca5e4..4b4ce7553a7f086a647755dde02bd278f2353989 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 ARM Limited
+# Copyright (c) 2012-2013 ARM Limited
 # All rights reserved
 # 
 # The license below extends only to copyright in the software and shall
@@ -64,12 +64,13 @@ def config_cache(options, system):
         # are not connected using addTwoLevelCacheHierarchy. Use the
         # same clock as the CPUs, and set the L1-to-L2 bus width to 32
         # bytes (256 bits).
-        system.l2 = l2_cache_class(clock=options.cpu_clock,
+        system.l2 = l2_cache_class(clk_domain=system.cpu_clk_domain,
                                    size=options.l2_size,
                                    assoc=options.l2_assoc,
                                    block_size=options.cacheline_size)
 
-        system.tol2bus = CoherentBus(clock = options.cpu_clock, width = 32)
+        system.tol2bus = CoherentBus(clk_domain = system.cpu_clk_domain,
+                                     width = 32)
         system.l2.cpu_side = system.tol2bus.master
         system.l2.mem_side = system.membus.slave
 
index 27b1a510ab76ac8259e6b4e4c2b369edeeebdaf0..deccdad5c4bf7b311268b46f8180b4144d383cbe 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 ARM Limited
+# Copyright (c) 2012-2013 ARM Limited
 # All rights reserved
 # 
 # The license below extends only to copyright in the software and shall
@@ -308,7 +308,7 @@ def run(options, root, testsys, cpu_class):
                 testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
             switch_cpus[i].system =  testsys
             switch_cpus[i].workload = testsys.cpu[i].workload
-            switch_cpus[i].clock = testsys.cpu[i].clock
+            switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
             # simulation period
             if options.maxinsts:
                 switch_cpus[i].max_insts_any_thread = options.maxinsts
@@ -335,7 +335,7 @@ def run(options, root, testsys, cpu_class):
         for i in xrange(np):
             repeat_switch_cpus[i].system = testsys
             repeat_switch_cpus[i].workload = testsys.cpu[i].workload
-            repeat_switch_cpus[i].clock = testsys.cpu[i].clock
+            repeat_switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
 
             if options.maxinsts:
                 repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts
@@ -363,8 +363,8 @@ def run(options, root, testsys, cpu_class):
             switch_cpus_1[i].system =  testsys
             switch_cpus[i].workload = testsys.cpu[i].workload
             switch_cpus_1[i].workload = testsys.cpu[i].workload
-            switch_cpus[i].clock = testsys.cpu[i].clock
-            switch_cpus_1[i].clock = testsys.cpu[i].clock
+            switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
+            switch_cpus_1[i].clk_domain = testsys.cpu[i].clk_domain
 
             # if restoring, make atomic cpu simulate only a few instructions
             if options.checkpoint_restore != None:
index cbcacd6d4be1a443c3642bfda8557b284d407e5e..02814840486372b5b3a51c4c10c9cb1b0d31af4e 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2012 ARM Limited
+# Copyright (c) 2010-2013 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -81,9 +81,6 @@ def is_kvm_cpu(cpu_class):
 # system under test can be any CPU
 (TestCPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
 
-TestCPUClass.clock = options.cpu_clock
-DriveCPUClass.clock = options.cpu_clock
-
 # Match the memories with the CPUs, the driver system always simple,
 # and based on the options for the test system
 DriveMemClass = SimpleMemory
@@ -120,7 +117,11 @@ elif buildEnv['TARGET_ISA'] == "arm":
 else:
     fatal("Incapable of building %s full system!", buildEnv['TARGET_ISA'])
 
-test_sys.clock = options.sys_clock
+# Create a source clock for the system and set the clock period
+test_sys.clk_domain = SrcClockDomain(clock =  options.sys_clock)
+
+# Create a source clock for the CPUs and set the clock period
+test_sys.cpu_clk_domain = SrcClockDomain(clock = options.cpu_clock)
 
 if options.kernel is not None:
     test_sys.kernel = binary(options.kernel)
@@ -130,7 +131,9 @@ if options.script is not None:
 
 test_sys.init_param = options.init_param
 
-test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)]
+# For now, assign all the CPUs to the same clock domain
+test_sys.cpu = [TestCPUClass(clk_domain=test_sys.cpu_clk_domain, cpu_id=i)
+                for i in xrange(np)]
 
 if is_kvm_cpu(TestCPUClass) or is_kvm_cpu(FutureClass):
     test_sys.vm = KvmVM()
@@ -174,9 +177,14 @@ if len(bm) == 2:
         drive_sys = makeArmSystem(drive_mem_mode, options.machine_type,
                                   DriveMemClass, bm[1])
 
-    drive_sys.clock = options.sys_clock
+    # Create a source clock for the system and set the clock period
+    drive_sys.clk_domain = SrcClockDomain(clock =  options.sys_clock)
+
+    # Create a source clock for the CPUs and set the clock period
+    drive_sys.cpu_clk_domain = SrcClockDomain(clock = options.cpu_clock)
 
-    drive_sys.cpu = DriveCPUClass(cpu_id=0)
+    drive_sys.cpu = DriveCPUClass(clk_domain=drive_sys.cpu_clk_domain,
+                                  cpu_id=0)
     drive_sys.cpu.createThreads()
     drive_sys.cpu.createInterruptController()
     drive_sys.cpu.connectAllPorts(drive_sys.membus)
index e8dc52fb522add832087cc5213fec9ca7d2329e0..a74f4b2f33c42e5ef37d5c193cf562381cb37eed 100644 (file)
@@ -144,14 +144,14 @@ for scale in treespec[:-2]:
 system = System(funcmem = SimpleMemory(in_addr_map = False),
                 funcbus = NoncoherentBus(),
                 physmem = SimpleMemory(latency = "100ns"))
-system.clock = options.sys_clock
+system.clk_domain = SrcClockDomain(clock =  options.sys_clock)
 
 def make_level(spec, prototypes, attach_obj, attach_port):
      fanout = spec[0]
      parent = attach_obj # use attach obj as config parent too
      if len(spec) > 1 and (fanout > 1 or options.force_bus):
           port = getattr(attach_obj, attach_port)
-          new_bus = CoherentBus(clock="500MHz", width=16)
+          new_bus = CoherentBus(width=16)
           if (port.role == 'MASTER'):
                new_bus.slave = port
                attach_port = "master"
index a607252305d9a7d8b43c3575a3c32a9f16dee9d5..e4d4c73f81ad8c062a19e74c8c131dccf6e765e5 100644 (file)
@@ -92,8 +92,9 @@ else:
 # actually used by the rubytester, but is included to support the
 # M5 memory size == Ruby memory size checks
 #
-system = System(physmem = SimpleMemory())
-system.clock = options.sys_clock
+system = System(physmem = SimpleMemory(),
+                clk_domain = SrcClockDomain(clock =  options.sys_clock))
+
 #
 # Create the ruby random tester
 #
@@ -103,6 +104,9 @@ system.tester = RubyDirectedTester(requests_to_complete = \
 
 Ruby.create_system(options, system)
 
+# Since Ruby runs at an independent frequency, create a seperate clock
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
 
 for ruby_port in system.ruby._cpu_ruby_ports:
index 403e55584f7a1528a40ec03098ae284559a62177..a1293a08c67ab184bfadad0c5e32ea0a85bb5084 100644 (file)
@@ -80,8 +80,6 @@ if not (options.cpu_type == "detailed" or options.cpu_type == "timing"):
     sys.exit(1)
 (CPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
 
-CPUClass.clock = options.cpu_clock
-
 TestMemClass = Simulation.setMemClass(options)
 
 if buildEnv['TARGET_ISA'] == "alpha":
@@ -93,7 +91,7 @@ elif buildEnv['TARGET_ISA'] == "x86":
 else:
     fatal("incapable of building non-alpha or non-x86 full system!")
 
-system.clock = options.sys_clock
+system.clk_domain = SrcClockDomain(clock = options.sys_clock)
 
 if options.kernel is not None:
     system.kernel = binary(options.kernel)
@@ -102,12 +100,20 @@ if options.script is not None:
     system.readfile = options.script
 
 system.cpu = [CPUClass(cpu_id=i) for i in xrange(options.num_cpus)]
+
+# Create a source clock for the CPUs and set the clock period
+system.cpu_clk_domain = SrcClockDomain(clock = options.cpu_clock)
+
 Ruby.create_system(options, system, system.piobus, system._dma_ports)
 
+# Create a seperate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 for (i, cpu) in enumerate(system.cpu):
     #
     # Tie the cpu ports to the correct ruby system ports
     #
+    cpu.clk_domain = system.cpu_clk_domain
     cpu.createThreads()
     cpu.createInterruptController()
     cpu.icache_port = system.ruby._cpu_ruby_ports[i].slave
index 14db9d40b50fd9ff35823eb4c2e8ed3ea2590408..b164447f8da509d66a67605ebd65782c81115e27 100644 (file)
@@ -107,8 +107,8 @@ cpus = [ MemTest(atomic = False,
 system = System(cpu = cpus,
                 funcmem = SimpleMemory(in_addr_map = False),
                 funcbus = NoncoherentBus(),
-                physmem = SimpleMemory())
-system.clock = options.sys_clock
+                physmem = SimpleMemory(),
+                clk_domain = SrcClockDomain(clock = options.sys_clock))
 
 if options.num_dmas > 0:
     dmas = [ MemTest(atomic = False,
@@ -129,6 +129,9 @@ for (i, dma) in enumerate(dmas):
     dma_ports.append(dma.test)
 Ruby.create_system(options, system, dma_ports = dma_ports)
 
+# Create a seperate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 #
 # The tester is most effective when randomization is turned on and
 # artifical delay is randomly inserted on messages
index 74bdd5504dd04caf1faeb85c01826e520015b420..b6fdc416fb5a2ac00739f9a1f09186726684efe8 100644 (file)
@@ -104,11 +104,14 @@ cpus = [ NetworkTest(fixed_pkts=options.fixed_pkts,
 
 # create the desired simulated system
 system = System(cpu = cpus,
-                physmem = SimpleMemory())
-system.clock = options.sys_clock
+                physmem = SimpleMemory(),
+                clk_domain = SrcClockDomain(clock = options.sys_clock))
 
 Ruby.create_system(options, system)
 
+# Create a seperate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 i = 0
 for ruby_port in system.ruby._cpu_ruby_ports:
      #
index 646863e88e0dfad9379063c4ef4bca7dd7830548..cd1b82f168924c070fce3865a9ff76cb2d4354c7 100644 (file)
@@ -97,11 +97,14 @@ tester = RubyTester(check_flush = check_flush,
 # actually used by the rubytester, but is included to support the
 # M5 memory size == Ruby memory size checks
 #
-system = System(tester = tester, physmem = SimpleMemory())
-system.clock = options.sys_clock
+system = System(tester = tester, physmem = SimpleMemory(),
+                clk_domain = SrcClockDomain(clock = options.sys_clock))
 
 Ruby.create_system(options, system)
 
+# Create a seperate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
 
 tester.num_cpus = len(system.ruby._cpu_ruby_ports)
index 3ff3f0c7de132d20b66210504e2eb4d5d2adc25f..a564901a303cd903419f48ee25e6020c796cf4bf 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 ARM Limited
+# Copyright (c) 2012-2013 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -147,7 +147,6 @@ else:
 
 
 (CPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
-CPUClass.clock = options.cpu_clock
 CPUClass.numThreads = numThreads
 
 MemClass = Simulation.setMemClass(options)
@@ -159,8 +158,16 @@ if options.smt and options.num_cpus > 1:
 np = options.num_cpus
 system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)],
                 physmem = MemClass(range=AddrRange("512MB")),
-                mem_mode = test_mem_mode)
-system.clock = options.sys_clock
+                mem_mode = test_mem_mode,
+                clk_domain = SrcClockDomain(clock = options.sys_clock))
+
+# Create a separate clock domain for the CPUs
+system.cpu_clk_domain = SrcClockDomain(clock = options.cpu_clock)
+
+# All cpus belong to a common cpu_clk_domain, therefore running at a common
+# frequency.
+for cpu in system.cpu:
+    cpu.clk_domain = system.cpu_clk_domain
 
 # Sanity check
 if options.fastmem:
index c265bd4cb7f05a283fdad57c60668add1c6cd187..4128f87ad7844cf1dd8c1f2e870bac65deea7116 100644 (file)
@@ -144,13 +144,22 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
                             system.memories.unproxy(system)))
     mem_module_size = phys_mem_size / options.num_dirs
 
+    # Run each of the ruby memory controllers at a ratio of the frequency of
+    # the ruby system
+    # clk_divider value is a fix to pass regression.
+    ruby_system.memctrl_clk_domain = DerivedClockDomain(
+                                          clk_domain=ruby_system.clk_domain,
+                                          clk_divider=3)
+
     for i in xrange(options.num_dirs):
         #
         # Create the Ruby objects associated with the directory controller
         #
 
-        mem_cntrl = RubyMemoryControl(version = i,
-                                      ruby_system = ruby_system)
+        mem_cntrl = RubyMemoryControl(
+                              clk_domain = ruby_system.memctrl_clk_domain,
+                              version = i,
+                              ruby_system = ruby_system)
 
         dir_size = MemorySize('0B')
         dir_size.value = mem_module_size
index 0514a7240821ef0e5fe78f412eae0176444b75ed..6bbd35ea7890669c458c1fd9a36d3c776c40274c 100644 (file)
@@ -109,13 +109,22 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
                             system.memories.unproxy(system)))
     mem_module_size = phys_mem_size / options.num_dirs
 
+    # Run each of the ruby memory controllers at a ratio of the frequency of
+    # the ruby system.
+    # clk_divider value is a fix to pass regression.
+    ruby_system.memctrl_clk_domain = DerivedClockDomain(
+                                          clk_domain=ruby_system.clk_domain,
+                                          clk_divider=3)
+
     for i in xrange(options.num_dirs):
         #
         # Create the Ruby objects associated with the directory controller
         #
 
-        mem_cntrl = RubyMemoryControl(version = i,
-                                      ruby_system = ruby_system)
+        mem_cntrl = RubyMemoryControl(
+                              clk_domain = ruby_system.memctrl_clk_domain,
+                              version = i,
+                              ruby_system = ruby_system)
 
         dir_size = MemorySize('0B')
         dir_size.value = mem_module_size
index f53758d718fca5d8de2d7a76bcba7b8152f8bf5b..81d04914c689ed8c35e2d99ca0a5265317df39da 100644 (file)
@@ -139,13 +139,22 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
                             system.memories.unproxy(system)))
     mem_module_size = phys_mem_size / options.num_dirs
 
+    # Run each of the ruby memory controllers at a ratio of the frequency of
+    # the ruby system.
+    # clk_divider value is a fix to pass regression.
+    ruby_system.memctrl_clk_domain = DerivedClockDomain(
+                                          clk_domain=ruby_system.clk_domain,
+                                          clk_divider=3)
+
     for i in xrange(options.num_dirs):
         #
         # Create the Ruby objects associated with the directory controller
         #
 
-        mem_cntrl = RubyMemoryControl(version = i,
-                                      ruby_system = ruby_system)
+        mem_cntrl = RubyMemoryControl(
+                              clk_domain = ruby_system.memctrl_clk_domain,
+                              version = i,
+                              ruby_system = ruby_system)
 
         dir_size = MemorySize('0B')
         dir_size.value = mem_module_size
index f3ad05a92b8088b0e00757ccbf23acaa6a55226f..9c2598a1dfd20a192be038d0c9f2fc2cca3377f1 100644 (file)
@@ -160,13 +160,22 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
                             system.memories.unproxy(system)))
     mem_module_size = phys_mem_size / options.num_dirs
 
+    # Run each of the ruby memory controllers at a ratio of the frequency of
+    # the ruby system
+    # clk_divider value is a fix to pass regression.
+    ruby_system.memctrl_clk_domain = DerivedClockDomain(
+                                          clk_domain=ruby_system.clk_domain,
+                                          clk_divider=3)
+
     for i in xrange(options.num_dirs):
         #
         # Create the Ruby objects associated with the directory controller
         #
 
-        mem_cntrl = RubyMemoryControl(version = i,
-                                      ruby_system = ruby_system)
+        mem_cntrl = RubyMemoryControl(
+                              clk_domain = ruby_system.memctrl_clk_domain,
+                              version = i,
+                              ruby_system = ruby_system)
 
         dir_size = MemorySize('0B')
         dir_size.value = mem_module_size
index 30fb0f0b7d36010c6a177979634702189f871c44..11ea579ea5454b99569b6a748bbc3a9d3828ce17 100644 (file)
@@ -158,13 +158,22 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
         else:
             pf_start_bit = block_size_bits
 
+    # Run each of the ruby memory controllers at a ratio of the frequency of
+    # the ruby system
+    # clk_divider value is a fix to pass regression.
+    ruby_system.memctrl_clk_domain = DerivedClockDomain(
+                                          clk_domain=ruby_system.clk_domain,
+                                          clk_divider=3)
+
     for i in xrange(options.num_dirs):
         #
         # Create the Ruby objects associated with the directory controller
         #
 
-        mem_cntrl = RubyMemoryControl(version = i,
-                                      ruby_system = ruby_system)
+        mem_cntrl = RubyMemoryControl(
+                              clk_domain = ruby_system.memctrl_clk_domain,
+                              version = i,
+                              ruby_system = ruby_system)
 
         dir_size = MemorySize('0B')
         dir_size.value = mem_module_size
index c1a1f9509f9d80fe6d3415163c1cad416c606061..c4df4dddbd6986e506403a31895614df623d73af 100644 (file)
@@ -107,13 +107,22 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
                             system.memories.unproxy(system)))
     mem_module_size = phys_mem_size / options.num_dirs
 
+    # Run each of the ruby memory controllers at a ratio of the frequency of
+    # the ruby system.
+    # clk_divider value is a fix to pass regression.
+    ruby_system.memctrl_clk_domain = DerivedClockDomain(
+                                          clk_domain=ruby_system.clk_domain,
+                                          clk_divider=3)
+
     for i in xrange(options.num_dirs):
         #
         # Create the Ruby objects associated with the directory controller
         #
 
-        mem_cntrl = RubyMemoryControl(version = i,
-                                      ruby_system = ruby_system)
+        mem_cntrl = RubyMemoryControl(
+                              clk_domain = ruby_system.memctrl_clk_domain,
+                              version = i,
+                              ruby_system = ruby_system)
 
         dir_size = MemorySize('0B')
         dir_size.value = mem_module_size
index 5c5e84197184f8a9b2f0d11e743b4209859306e6..a35ef4f095fb9f7259dec76e03f99bc3049959e2 100644 (file)
@@ -95,8 +95,7 @@ def create_topology(controllers, options):
 
 def create_system(options, system, piobus = None, dma_ports = []):
 
-    system.ruby = RubySystem(clock = options.ruby_clock,
-                             stats_filename = options.ruby_stats,
+    system.ruby = RubySystem(stats_filename = options.ruby_stats,
                              no_mem_vec = options.use_map)
     ruby = system.ruby
 
index 2486ec059136ac525c0e0c9232778b2a5e2c4e61..cc8e453b17c3aea2013a7c2ec7786d1fa4e0eb11 100644 (file)
@@ -45,7 +45,7 @@ class LinuxAlphaSystem(AlphaSystem):
     system_type = 34
     system_rev = 1 << 10
 
-    boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
+    boot_cpu_frequency = Param.Frequency(Self.cpu[0].clk_domain.clock.frequency,
                                          "boot processor frequency")
 
 class FreebsdAlphaSystem(AlphaSystem):
index c6ceb71db32838ffb0ce57340ad7112f3c170c9c..4605b21a725cf2d4e8c897b9c993dab5fb801fff 100644 (file)
@@ -50,7 +50,7 @@ class LinuxMipsSystem(MipsSystem):
     system_type = 34
     system_rev = 1 << 10
 
-    boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
+    boot_cpu_frequency = Param.Frequency(Self.cpu[0].clk_domain.clock.frequency,
                                          "boot processor frequency")
 
 class BareIronMipsSystem(MipsSystem):
index e7613c5bb7493bb938e477cf0c6ed0ff369c9792..7ec79ad0ae7e61c6d50f8aa17a9b0da1f9b772cb 100644 (file)
@@ -52,6 +52,7 @@ from InstTracer import InstTracer
 from ExeTracer import ExeTracer
 from MemObject import MemObject
 from BranchPredictor import BranchPredictor
+from ClockDomain import *
 
 default_tracer = ExeTracer()
 
@@ -226,7 +227,10 @@ class BaseCPU(MemObject):
         elif buildEnv['TARGET_ISA'] == 'alpha':
             self.interrupts = AlphaInterrupts()
         elif buildEnv['TARGET_ISA'] == 'x86':
-            self.interrupts = X86LocalApic(clock = Parent.clock * 16,
+            self.apic_clk_domain = DerivedClockDomain(clk_domain =
+                                                      Parent.clk_domain,
+                                                      clk_divider = 16)
+            self.interrupts = X86LocalApic(clk_domain = self.apic_clk_domain,
                                            pio_addr=0x2000000000000000)
             _localApic = self.interrupts
         elif buildEnv['TARGET_ISA'] == 'mips':
index 7a5b46e43f20f81b5752b617a5380508b6bb2ed1..bbd905492b2a94a5b816cd5324e80f4145bdeb58 100644 (file)
@@ -54,7 +54,7 @@ DummyCheckerParams::create()
     params->max_insts_all_threads = 0;
     params->max_loads_any_thread = 0;
     params->max_loads_all_threads = 0;
-    params->clock = clock;
+    params->clk_domain = clk_domain;
     // Hack to touch all parameters.  Consider not deriving Checker
     // from BaseCPU..it's not really a CPU in the end.
     Counter temp;
index 3ff3d86bc327306ff81b98243a45084b84f4825b..ce7a99f0f01f9d6b857da768a99789b3c5e647f6 100644 (file)
@@ -66,7 +66,7 @@ O3CheckerParams::create()
     params->exitOnError = exitOnError;
     params->updateOnError = updateOnError;
     params->warnOnlyOnLoadError = warnOnlyOnLoadError;
-    params->clock = clock;
+    params->clk_domain = clk_domain;
     params->tracer = tracer;
     // Hack to touch all parameters.  Consider not deriving Checker
     // from BaseCPU..it's not really a CPU in the end.
index 0072b90faaa273071cb904e3712758f176e644ee..147ad156c0846b4eb370fc7d438a78ff29300c1c 100644 (file)
@@ -84,8 +84,6 @@ class IGbE(EtherDevice):
         "Number of enteries in the rx descriptor cache")
     tx_desc_cache_size = Param.Int(64,
         "Number of enteries in the rx descriptor cache")
-    # Override the default clock
-    clock = '500MHz'
     VendorID = 0x8086
     SubsystemID = 0x1008
     SubsystemVendorID = 0x8086
@@ -135,9 +133,6 @@ class EtherDevBase(EtherDevice):
     hardware_address = Param.EthernetAddr(NextEthernetAddr,
         "Ethernet Hardware Address")
 
-    # Override the default clock
-    clock = '500MHz'
-
     dma_read_delay = Param.Latency('0us', "fixed delay for dma reads")
     dma_read_factor = Param.Latency('0us', "multiplier for dma reads")
     dma_write_delay = Param.Latency('0us', "fixed delay for dma writes")
index e46b3f223bb7d81da52062fb14a804f92265fa06..118e4f20efc2a69413c07e01f7bbe6823aa4bef9 100644 (file)
@@ -37,8 +37,6 @@ class RubyMemoryControl(MemoryControl):
     cxx_header = "mem/ruby/system/RubyMemoryControl.hh"
     version = Param.Int("");
 
-    # Override the default clock
-    clock = '400MHz'
     banks_per_rank = Param.Int(8, "");
     ranks_per_dimm = Param.Int(2, "");
     dimms_per_channel = Param.Int(2, "");
diff --git a/src/sim/ClockDomain.py b/src/sim/ClockDomain.py
new file mode 100644 (file)
index 0000000..37958dc
--- /dev/null
@@ -0,0 +1,60 @@
+# Copyright (c) 2013 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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: Vasileios Spiliopoulos
+#          Akash Bagdia
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+# Abstract clock domain
+class ClockDomain(SimObject):
+    type = 'ClockDomain'
+    cxx_header = "sim/clock_domain.hh"
+    abstract = True
+
+# Source clock domain with an actual clock
+class SrcClockDomain(ClockDomain):
+    type = 'SrcClockDomain'
+    cxx_header = "sim/clock_domain.hh"
+    clock = Param.Clock("Clock period")
+
+# Derived clock domain with a parent clock domain and a frequency
+# divider
+class DerivedClockDomain(ClockDomain):
+    type = 'DerivedClockDomain'
+    cxx_header = "sim/clock_domain.hh"
+    clk_domain = Param.ClockDomain("Parent clock domain")
+    clk_divider = Param.Unsigned(1, "Frequency divider")
index 8bc4031a4c392b78e5973038d4f88bea57ee1081..2562f1f01ff9f53e00731e21c72534d247caf331 100644 (file)
@@ -44,7 +44,6 @@ class ClockedObject(SimObject):
     abstract = True
     cxx_header = "sim/clocked_object.hh"
 
-    # Clock period of this object, with the default value being the
-    # clock period of the parent object, unproxied at instantiation
-    # time
-    clock = Param.Clock(Parent.clock, "Clock speed")
+    # The clock domain this clocked object belongs to, inheriting the
+    # parent's clock domain by default
+    clk_domain = Param.ClockDomain(Parent.clk_domain, "Clock domain")
index 093130f24b69bc3aedb3c21d7d46a93c5a36f796..7aa4702cd1151e9512a112ebcb00d83e5fc51c33 100644 (file)
@@ -34,6 +34,7 @@ SimObject('BaseTLB.py')
 SimObject('ClockedObject.py')
 SimObject('Root.py')
 SimObject('InstTracer.py')
+SimObject('ClockDomain.py')
 
 Source('arguments.cc')
 Source('async.cc')
@@ -50,6 +51,7 @@ Source('sim_object.cc')
 Source('simulate.cc')
 Source('stat_control.cc')
 Source('syscall_emul.cc')
+Source('clock_domain.cc')
 
 if env['TARGET_ISA'] != 'no':
     SimObject('Process.py')
@@ -81,3 +83,4 @@ DebugFlag('Thread')
 DebugFlag('Timer')
 DebugFlag('VtoPhys')
 DebugFlag('WorkItems')
+DebugFlag('ClockDomain')
diff --git a/src/sim/clock_domain.cc b/src/sim/clock_domain.cc
new file mode 100644 (file)
index 0000000..262ae90
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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: Vasileios Spiliopoulos
+ *          Akash Bagdia
+ *          Andreas Hansson
+ */
+
+#include "debug/ClockDomain.hh"
+#include "params/ClockDomain.hh"
+#include "params/DerivedClockDomain.hh"
+#include "params/SrcClockDomain.hh"
+#include "sim/clock_domain.hh"
+
+SrcClockDomain::SrcClockDomain(const Params *p) : ClockDomain(p)
+{
+    clockPeriod(p->clock);
+}
+
+void
+SrcClockDomain::clockPeriod(Tick clock_period)
+{
+    if (clock_period == 0) {
+        fatal("%s has a clock period of zero\n", name());
+    }
+
+    _clockPeriod = clock_period;
+
+    DPRINTF(ClockDomain,
+            "Setting clock period to %d ticks for source clock %s\n",
+            _clockPeriod, name());
+
+    // inform any derived clocks they need to updated their period
+    for (auto c = children.begin(); c != children.end(); ++c) {
+        (*c)->updateClockPeriod();
+    }
+}
+
+SrcClockDomain *
+SrcClockDomainParams::create()
+{
+    return new SrcClockDomain(this);
+}
+
+DerivedClockDomain::DerivedClockDomain(const Params *p) :
+    ClockDomain(p),
+    parent(*p->clk_domain),
+    clockDivider(p->clk_divider)
+{
+    // Ensure that clock divider setting works as frequency divider and never
+    // work as frequency multiplier
+    if (clockDivider < 1) {
+       fatal("Clock divider param cannot be less than 1");
+    }
+
+    // let the parent keep track of this derived domain so that it can
+    // propagate changes
+    parent.addDerivedDomain(this);
+
+    // update our clock period based on the parents clock
+    updateClockPeriod();
+}
+
+void
+DerivedClockDomain::updateClockPeriod()
+{
+    // recalculate the clock period, relying on the fact that changes
+    // propagate downwards in the tree
+    _clockPeriod = parent.clockPeriod() * clockDivider;
+
+    DPRINTF(ClockDomain,
+            "Setting clock period to %d ticks for derived clock %s\n",
+            _clockPeriod, name());
+
+    // inform any derived clocks
+    for (auto c = children.begin(); c != children.end(); ++c) {
+        (*c)->updateClockPeriod();
+    }
+}
+
+DerivedClockDomain *
+DerivedClockDomainParams::create()
+{
+    return new DerivedClockDomain(this);
+}
diff --git a/src/sim/clock_domain.hh b/src/sim/clock_domain.hh
new file mode 100644 (file)
index 0000000..c3f53e6
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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: Vasileios Spiliopoulos
+ *          Akash Bagdia
+ */
+
+/**
+ * @file
+ * ClockDomain declarations.
+ */
+
+#ifndef __SIM_CLOCK_DOMAIN_HH__
+#define __SIM_CLOCK_DOMAIN_HH__
+
+#include "base/statistics.hh"
+#include "params/ClockDomain.hh"
+#include "params/DerivedClockDomain.hh"
+#include "params/SrcClockDomain.hh"
+#include "sim/sim_object.hh"
+
+/**
+ * Forward declaration
+ */
+class DerivedClockDomain;
+
+/**
+ * The ClockDomain provides clock to group of clocked objects bundled
+ * under the same clock domain. The clock domains provide support for
+ * a hierarchial structure with source and derived domains.
+ */
+class ClockDomain : public SimObject
+{
+
+  protected:
+
+    /**
+     * Pre-computed clock period in ticks. This is populated by the
+     * inheriting classes based on how their period is determined.
+     */
+    Tick _clockPeriod;
+
+    /**
+     * Pointers to potential derived clock domains so we can propagate
+     * changes.
+     */
+    std::vector<DerivedClockDomain*> children;
+
+  public:
+
+    typedef ClockDomainParams Params;
+    ClockDomain(const Params *p) : SimObject(p), _clockPeriod(0) {}
+
+    /**
+     * Get the clock period.
+     *
+     * @return Clock period in ticks
+     */
+    inline Tick clockPeriod() const { return _clockPeriod; }
+
+    /**
+     * Add a derived domain.
+     *
+     * @param Derived domain to add as a child
+     */
+    void addDerivedDomain(DerivedClockDomain *clock_domain)
+    { children.push_back(clock_domain); }
+
+};
+
+/**
+ * The source clock domains provides the notion of a clock domain that is
+ * connected to a tunable clock source. It maintains the clock period and
+ * provides methods for setting/getting the clock.
+ */
+class SrcClockDomain : public ClockDomain
+{
+
+  public:
+
+    typedef SrcClockDomainParams Params;
+    SrcClockDomain(const Params *p);
+
+    /**
+     * Set new clock value
+     * @param clock The new clock period in ticks
+     */
+    void clockPeriod(Tick clock_period);
+
+};
+
+/**
+ * The derived clock domains provides the notion of a clock domain
+ * that is connected to a parent clock domain that can either be a
+ * source clock domain or a derived clock domain. It maintains the
+ * clock divider and provides methods for getting the clock.
+ */
+class DerivedClockDomain: public ClockDomain
+{
+
+  public:
+
+    typedef DerivedClockDomainParams Params;
+    DerivedClockDomain(const Params *p);
+
+    /**
+     * Called by the parent clock domain to propagate changes. This
+     * also involves propagating the change further to any children of
+     * the derived domain itself.
+     */
+    void updateClockPeriod();
+
+  private:
+
+    /**
+     * Reference to the parent clock domain this clock domain derives
+     * its clock period from
+     */
+    ClockDomain &parent;
+
+    /**
+     * Local clock divider of the domain
+     */
+    const uint64_t clockDivider;
+};
+
+#endif
index d836c48cc1276358b994bf4b440a39452e25a90e..c959c5c04a39c9c175108b79ec04d7d3114cde5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -49,6 +49,7 @@
 #include "base/misc.hh"
 #include "params/ClockedObject.hh"
 #include "sim/core.hh"
+#include "sim/clock_domain.hh"
 #include "sim/sim_object.hh"
 
 /**
@@ -88,7 +89,7 @@ class ClockedObject : public SimObject
 
         // optimise for the common case and see if the tick should be
         // advanced by a single clock period
-        tick += clock;
+        tick += clockPeriod();
         ++cycle;
 
         // see if we are done at this point
@@ -98,26 +99,25 @@ class ClockedObject : public SimObject
         // if not, we have to recalculate the cycle and tick, we
         // perform the calculations in terms of relative cycles to
         // allow changes to the clock period in the future
-        Cycles elapsedCycles(divCeil(curTick() - tick, clock));
+        Cycles elapsedCycles(divCeil(curTick() - tick, clockPeriod()));
         cycle += elapsedCycles;
-        tick += elapsedCycles * clock;
+        tick += elapsedCycles * clockPeriod();
     }
 
-    // Clock period in ticks
-    Tick clock;
+    /**
+     * The clock domain this clocked object belongs to
+     */
+    ClockDomain &clockDomain;
 
   protected:
 
     /**
-     * Create a clocked object and set the clock based on the
+     * Create a clocked object and set the clock domain based on the
      * parameters.
      */
     ClockedObject(const ClockedObjectParams* p) :
-        SimObject(p), tick(0), cycle(0), clock(p->clock)
+        SimObject(p), tick(0), cycle(0), clockDomain(*p->clk_domain)
     {
-        if (clock == 0) {
-            fatal("%s has a clock period of zero\n", name());
-        }
     }
 
     /**
@@ -132,9 +132,9 @@ class ClockedObject : public SimObject
      */
     void resetClock() const
     {
-        Cycles elapsedCycles(divCeil(curTick(), clock));
+        Cycles elapsedCycles(divCeil(curTick(), clockPeriod()));
         cycle = elapsedCycles;
-        tick = elapsedCycles * clock;
+        tick = elapsedCycles * clockPeriod();
     }
 
   public:
@@ -154,7 +154,7 @@ class ClockedObject : public SimObject
         update();
 
         // figure out when this future cycle is
-        return tick + clock * cycles;
+        return tick + clockPeriod() * cycles;
     }
 
     /**
@@ -181,12 +181,18 @@ class ClockedObject : public SimObject
     Tick nextCycle() const
     { return clockEdge(Cycles(1)); }
 
-    inline uint64_t frequency() const { return SimClock::Frequency / clock; }
+    inline uint64_t frequency() const
+    {
+        return SimClock::Frequency / clockPeriod();
+    }
 
-    inline Tick clockPeriod() const { return clock; }
+    inline Tick clockPeriod() const
+    {
+        return clockDomain.clockPeriod();
+    }
 
     inline Cycles ticksToCycles(Tick t) const
-    { return Cycles(t / clock); }
+    { return Cycles(t / clockPeriod()); }
 
 };
 
index 0cafacddaba2ecec0f3e17932b3572e6ffef42d5..16620c4ddab2018cf96887c9088f9ed024d5adea 100644 (file)
@@ -74,9 +74,10 @@ class BaseSystem(object):
         self.num_cpus = num_cpus
         self.checker = checker
 
-    def create_cpus(self):
+    def create_cpus(self, cpu_clk_domain):
         """Return a list of CPU objects to add to a system."""
-        cpus = [ self.cpu_class(cpu_id=i, clock='2GHz')
+        cpus = [ self.cpu_class(clk_domain = cpu_clk_domain,
+                                cpu_id=i)
                  for i in range(self.num_cpus) ]
         if self.checker:
             for c in cpus:
@@ -101,8 +102,9 @@ class BaseSystem(object):
         Returns:
           A bus that CPUs should use to connect to the shared cache.
         """
-        system.toL2Bus = CoherentBus(clock='2GHz')
-        system.l2c = L2Cache(clock='2GHz', size='4MB', assoc=8)
+        system.toL2Bus = CoherentBus(clk_domain=system.cpu_clk_domain)
+        system.l2c = L2Cache(clk_domain=system.cpu_clk_domain,
+                             size='4MB', assoc=8)
         system.l2c.cpu_side = system.toL2Bus.master
         system.l2c.mem_side = system.membus.slave
         return system.toL2Bus
@@ -134,8 +136,8 @@ class BaseSystem(object):
         Arguments:
           system -- System to initialize.
         """
-        system.clock = '1GHz'
-        system.cpu = self.create_cpus()
+        self.create_clk_src(system)
+        system.cpu = self.create_cpus(system.cpu_clk_domain)
 
         if _have_kvm_support and \
                 any([isinstance(c, BaseKvmCPU) for c in system.cpu]):
@@ -145,6 +147,16 @@ class BaseSystem(object):
         for cpu in system.cpu:
             self.init_cpu(system, cpu, sha_bus)
 
+    def create_clk_src(self,system):
+        # Create system clock domain. This provides clock value to every
+        # clocked object that lies beneath it unless explicitly overwritten
+        # by a different clock domain.
+        system.clk_domain = SrcClockDomain(clock = '1GHz')
+
+        # Create a seperate clock domain for components that should
+        # run at CPUs frequency
+        system.cpu_clk_domain = SrcClockDomain(clock = '2GHz')
+
     @abstractmethod
     def create_system(self):
         """Create an return an initialized system."""
@@ -244,8 +256,10 @@ class BaseFSSwitcheroo(BaseFSSystem):
         BaseFSSystem.__init__(self, **kwargs)
         self.cpu_classes = tuple(cpu_classes)
 
-    def create_cpus(self):
-        cpus = [ cclass(cpu_id=0, clock='2GHz', switched_out=True)
+    def create_cpus(self, cpu_clk_domain):
+        cpus = [ cclass(clk_domain = cpu_clk_domain,
+                        cpu_id=0,
+                        switched_out=True)
                  for cclass in self.cpu_classes ]
         cpus[0].switched_out = False
         return cpus
index dbd1082d10ca9278f3692b84b6b5a20f38bf56e8..3261ba3ffca4d0a101e93537320f063164f121bb 100644 (file)
@@ -69,7 +69,7 @@ options.l3_assoc=2
 nb_cores = 8
 
 # ruby does not support atomic, functional, or uncacheable accesses
-cpus = [ MemTest(clock = '2GHz', atomic=False, percent_functional=50,
+cpus = [ MemTest(atomic=False, percent_functional=50,
                  percent_uncacheable=0, suppress_func_warnings=True) \
          for i in xrange(nb_cores) ]
 
@@ -80,11 +80,22 @@ options.num_cpus = nb_cores
 system = System(cpu = cpus,
                 funcmem = SimpleMemory(in_addr_map = False),
                 physmem = SimpleMemory(null = True),
-                funcbus = NoncoherentBus())
-system.clock = options.sys_clock
+                funcbus = NoncoherentBus(),
+                clk_domain = SrcClockDomain(clock = options.sys_clock))
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+system.cpu_clk_domain = SrcClockDomain(clock = '2GHz')
+
+# All cpus are associated with cpu_clk_domain
+for cpu in cpus:
+    cpu.clk_domain = system.cpu_clk_domain
 
 Ruby.create_system(options, system)
 
+# Create a separate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 assert(len(cpus) == len(system.ruby._cpu_ruby_ports))
 
 for (i, ruby_port) in enumerate(system.ruby._cpu_ruby_ports):
index efaae61330b1f64cd52a6585e83762d85d35742b..35efe646da92a2a8a1f872b66cb45c8417e280dd 100644 (file)
@@ -33,18 +33,21 @@ from Caches import *
 
 #MAX CORES IS 8 with the fals sharing method
 nb_cores = 8
-cpus = [ MemTest(clock = '2GHz') for i in xrange(nb_cores) ]
+cpus = [ MemTest() for i in xrange(nb_cores) ]
 
 # system simulated
 system = System(cpu = cpus, funcmem = SimpleMemory(in_addr_map = False),
                 funcbus = NoncoherentBus(),
                 physmem = SimpleMemory(),
-                membus = CoherentBus(width=16))
-system.clock = '1GHz'
+                membus = CoherentBus(width=16),
+                clk_domain = SrcClockDomain(clock = '1GHz'))
 
-# l2cache & bus
-system.toL2Bus = CoherentBus(clock="2GHz", width=16)
-system.l2c = L2Cache(clock = '2GHz', size='64kB', assoc=8)
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+system.cpu_clk_domain = SrcClockDomain(clock = '2GHz')
+
+system.toL2Bus = CoherentBus(clk_domain = system.cpu_clk_domain, width=16)
+system.l2c = L2Cache(clk_domain = system.cpu_clk_domain, size='64kB', assoc=8)
 system.l2c.cpu_side = system.toL2Bus.master
 
 # connect l2c to membus
@@ -52,6 +55,8 @@ system.l2c.mem_side = system.membus.slave
 
 # add L1 caches
 for cpu in cpus:
+    # All cpus are associated with cpu_clk_domain
+    cpu.clk_domain = system.cpu_clk_domain
     cpu.l1c = L1Cache(size = '32kB', assoc = 4)
     cpu.l1c.cpu_side = cpu.test
     cpu.l1c.mem_side = system.toL2Bus.slave
index 0060689b8d124dae201bf71151e909fd2ac84fef..292c7a42dd7f55784a2baef8967cc4f8f52d608f 100644 (file)
@@ -39,14 +39,19 @@ ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", nb_cores)
 
 # system simulated
 system = System(cpu = cpus, physmem = ruby_memory, membus = CoherentBus(),
-                mem_mode = "timing")
-system.clock = '1GHz'
+                mem_mode = "timing",
+                clk_domain = SrcClockDomain(clock = '1GHz'))
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+system.cpu_clk_domain = SrcClockDomain(clock = '2GHz')
 
 for cpu in cpus:
     # create the interrupt controller
     cpu.createInterruptController()
     cpu.connectAllPorts(system.membus)
-    cpu.clock = '2GHz'
+    # All cpus are associated with cpu_clk_domain
+    cpu.clk_domain = system.cpu_clk_domain
 
 # connect memory to membus
 system.physmem.port = system.membus.master
index 22e1047a397a65ec152cd5f14384d1d69a1c6a83..d1b471bacf778faaea8699fba467caf1f26529cf 100644 (file)
@@ -36,13 +36,17 @@ import ruby_config
 ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", 1)
 
 cpu = DerivO3CPU(cpu_id=0)
-cpu.clock = '2GHz'
 
 system = System(cpu = cpu,
                 physmem = ruby_memory,
                 membus = CoherentBus(),
-                mem_mode = "timing")
-system.clock = '1GHz'
+                mem_mode = "timing",
+                clk_domain = SrcClockDomain(clock = '1GHz'))
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+system.cpu.clk_domain = SrcClockDomain(clock = '2GHz')
+
 system.physmem.port = system.membus.master
 # create the interrupt controller
 cpu.createInterruptController()
index f17083fe43b0bb3695411338d69f3e448812227b..5799c0c7aeead682ce7ccc8f817dd417942f82a9 100644 (file)
@@ -56,11 +56,16 @@ options.num_cpus = 2
 #the system
 mdesc = SysConfig(disk = 'linux-x86.img')
 system = FSConfig.makeLinuxX86System('timing', DDR3_1600_x64, options.num_cpus,
-                                     mdesc=mdesc, Ruby=True)
+                                     mdesc=mdesc, Ruby=True,
+
 system.kernel = FSConfig.binary('x86_64-vmlinux-2.6.22.9.smp')
 system.cpu = [TimingSimpleCPU(cpu_id=i) for i in xrange(options.num_cpus)]
+
 Ruby.create_system(options, system, system.piobus, system._dma_ports)
 
+# Create a seperate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 for (i, cpu) in enumerate(system.cpu):
     # create the interrupt controller
     cpu.createInterruptController()
@@ -72,7 +77,6 @@ for (i, cpu) in enumerate(system.cpu):
     cpu.interrupts.pio = system.piobus.master
     cpu.interrupts.int_master = system.piobus.slave
     cpu.interrupts.int_slave = system.piobus.master
-    cpu.clock = '2GHz'
 
     # Set access_phys_mem to True for ruby port
     system.ruby._cpu_ruby_ports[i].access_phys_mem = True
index 328337190a44e7e131c70ea8aa31ad243bba8ab4..1553e29f4d4b94431e43fa3e20198e8ce373641b 100644 (file)
@@ -77,11 +77,14 @@ if buildEnv['PROTOCOL'] == 'MOESI_hammer':
 tester = RubyTester(check_flush = check_flush, checks_to_complete = 100,
                     wakeup_frequency = 10, num_cpus = options.num_cpus)
 
-system = System(tester = tester, physmem = SimpleMemory(null = True))
-system.clock = options.sys_clock
+system = System(tester = tester, physmem = SimpleMemory(null = True),
+                clk_domain = SrcClockDomain(clock = options.sys_clock))
 
 Ruby.create_system(options, system)
 
+# Create a separate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = '1GHz')
+
 assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
 
 #
index 12c26d97b0c10c8586988cd040f528b1663f9068..9feccb12c142d20bebf27fe8d006a1f23f146c63 100644 (file)
@@ -38,13 +38,18 @@ import ruby_config
 ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", nb_cores)
 
 # system simulated
-system = System(cpu = cpus, physmem = ruby_memory, membus = CoherentBus())
-system.clock = '1GHz'
+system = System(cpu = cpus, physmem = ruby_memory, membus = CoherentBus(),
+                clk_domain = SrcClockDomain(clock = '1GHz'))
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+system.cpu.clk_domain = SrcClockDomain(clock = '2GHz')
 
 # add L1 caches
 for cpu in cpus:
     cpu.connectAllPorts(system.membus)
-    cpu.clock = '2GHz'
+    # All cpus are associated with cpu_clk_domain
+    cpu.clk_domain = system.cpu_clk_domain
 
 # connect memory to membus
 system.physmem.port = system.membus.master
index 2fa314d09b23c9bbe8db4567aa2dbea06bc74383..835428c3be6d7f9e9c7ee8bfa01d0126070e85a8 100644 (file)
@@ -71,11 +71,18 @@ cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ]
 options.num_cpus = nb_cores
 
 # system simulated
-system = System(cpu = cpus, physmem = SimpleMemory())
-system.clock = options.sys_clock
+system = System(cpu = cpus, physmem = SimpleMemory(),
+                clk_domain = SrcClockDomain(clock = '1GHz'))
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+system.cpu.clk_domain = SrcClockDomain(clock = '2GHz')
 
 Ruby.create_system(options, system)
 
+# Create a separate clock domain for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
 
 for (i, cpu) in enumerate(system.cpu):
index 9057475a5e905ad7aa2c724b6f662e0b6c1b46e6..27d56a31da756a7339ef6890a3d0b09755aeb432 100644 (file)
@@ -67,11 +67,18 @@ options.l3_assoc=2
 options.num_cpus = 1
 
 cpu = TimingSimpleCPU(cpu_id=0)
-system = System(cpu = cpu, physmem = SimpleMemory(null = True))
-system.clock = options.sys_clock
+system = System(cpu = cpu, physmem = SimpleMemory(null = True),
+                clk_domain = SrcClockDomain(clock = '1GHz'))
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+system.cpu.clk_domain = SrcClockDomain(clock = '2GHz')
 
 Ruby.create_system(options, system)
 
+# Create a separate clock for Ruby
+system.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock)
+
 assert(len(system.ruby._cpu_ruby_ports) == 1)
 
 # create the interrupt controller
index a79b65d43862f4ef7671149c9371ad1b8bb0c95b..394aac4cb4ab9d45b730e5ea6c843d29ca8feaf8 100644 (file)
@@ -49,8 +49,8 @@ cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-dram.cfg")
 
 # system simulated
 system = System(cpu = cpu, physmem = DDR3_1600_x64(),
-                membus = NoncoherentBus(width = 16))
-system.clock = '1GHz'
+                membus = NoncoherentBus(width = 16),
+                clk_domain = SrcClockDomain(clock = '1GHz'))
 
 # add a communication monitor
 system.monitor = CommMonitor()
index b93165f509dc8dc09cbc06453511e59468df7e52..2d39a2ab09a95e9baad1b733328326fa6687d2b2 100644 (file)
@@ -49,8 +49,8 @@ cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-mem.cfg")
 
 # system simulated
 system = System(cpu = cpu, physmem = SimpleMemory(),
-                membus = NoncoherentBus(width = 16))
-system.clock = '1GHz'
+                membus = NoncoherentBus(width = 16),
+                clk_domain = SrcClockDomain(clock = '1GHz'))
 
 # add a communication monitor, and also trace all the packets
 system.monitor = CommMonitor(trace_file = "monitor.ptrc.gz")
index 8025b4e7b0bbe881edbaa5bd74bf9e8ad2d28458..22c6686ae2b985f86b70a32eea94ecda5e5c89d9 100644 (file)
@@ -34,12 +34,22 @@ from Benchmarks import *
 
 test_sys = makeLinuxAlphaSystem('atomic', SimpleMemory,
                                  SysConfig('netperf-stream-client.rcS'))
-test_sys.clock = '1GHz'
+
+# Create the system clock domain
+test_sys.clk_domain = SrcClockDomain(clock = '1GHz')
+
 test_sys.cpu = AtomicSimpleCPU(cpu_id=0)
 # create the interrupt controller
 test_sys.cpu.createInterruptController()
 test_sys.cpu.connectAllPorts(test_sys.membus)
-test_sys.cpu.clock = '2GHz'
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+test_sys.cpu.clk_domain = SrcClockDomain(clock = '2GHz')
+
+# Create a separate clock domain for Ethernet
+test_sys.tsunami.ethernet.clk_domain = SrcClockDomain(clock = '500MHz')
+
 # In contrast to the other (one-system) Tsunami configurations we do
 # not have an IO cache but instead rely on an IO bridge for accesses
 # from masters on the IO bus to the memory bus
@@ -49,12 +59,20 @@ test_sys.iobridge.master = test_sys.membus.slave
 
 drive_sys = makeLinuxAlphaSystem('atomic', SimpleMemory,
                                  SysConfig('netperf-server.rcS'))
-drive_sys.clock = '1GHz'
+# Create the system clock domain
+drive_sys.clk_domain = SrcClockDomain(clock = '1GHz')
 drive_sys.cpu = AtomicSimpleCPU(cpu_id=0)
 # create the interrupt controller
 drive_sys.cpu.createInterruptController()
 drive_sys.cpu.connectAllPorts(drive_sys.membus)
-drive_sys.cpu.clock = '4GHz'
+
+# Create a seperate clock domain for components that should run at
+# CPUs frequency
+drive_sys.cpu.clk_domain = SrcClockDomain(clock = '4GHz')
+
+# Create a separate clock domain for Ethernet
+drive_sys.tsunami.ethernet.clk_domain = SrcClockDomain(clock = '500MHz')
+
 drive_sys.iobridge = Bridge(delay='50ns', ranges = drive_sys.mem_ranges)
 drive_sys.iobridge.slave = drive_sys.iobus.master
 drive_sys.iobridge.master = drive_sys.membus.slave