Clock: Move the clock and related functions to ClockedObject
authorAndreas Hansson <andreas.hansson@arm.com>
Tue, 21 Aug 2012 09:49:01 +0000 (05:49 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Tue, 21 Aug 2012 09:49:01 +0000 (05:49 -0400)
This patch moves the clock of the CPU, bus, and numerous devices to
the new class ClockedObject, that sits in between the SimObject and
MemObject in the class hierarchy. Although there are currently a fair
amount of MemObjects that do not make use of the clock, they
potentially should do so, e.g. the caches should at some point have
the same clock as the CPU, potentially with a 1:n ratio. This patch
does not introduce any new clock objects or object hierarchies
(clusters, clock domains etc), but is still a step in the direction of
having a more structured approach clock domains.

The most contentious part of this patch is the serialisation of clocks
that some of the modules (but not all) did previously. This
serialisation should not be needed as the clock is set through the
parameters even when restoring from the checkpoint. In other words,
the state is "stored" in the Python code that creates the modules.

The nextCycle methods are also simplified and the clock phase
parameter of the CPU is removed (this could be part of a clock object
once they are introduced).

29 files changed:
src/arch/x86/interrupts.cc
src/arch/x86/interrupts.hh
src/arch/x86/utility.cc
src/cpu/BaseCPU.py
src/cpu/base.cc
src/cpu/base.hh
src/cpu/testers/memtest/memtest.hh
src/cpu/testers/networktest/networktest.hh
src/dev/CopyEngine.py
src/dev/Ethernet.py
src/dev/arm/RealView.py
src/dev/arm/pl111.cc
src/dev/arm/pl111.hh
src/dev/arm/timer_cpulocal.cc
src/dev/i8254xGBe.cc
src/dev/i8254xGBe.hh
src/dev/ns_gige.cc
src/dev/ns_gige.hh
src/dev/sinic.cc
src/dev/sinic.hh
src/mem/Bus.py
src/mem/MemObject.py
src/mem/bus.cc
src/mem/bus.hh
src/mem/mem_object.cc
src/mem/mem_object.hh
src/sim/ClockedObject.py [new file with mode: 0644]
src/sim/SConscript
src/sim/clocked_object.hh [new file with mode: 0644]

index b418a7489bd4e8d5c9a9ad2a074d69a3cbd9de68..906903b8b9cba9271558052d885ea643188813b6 100644 (file)
@@ -619,7 +619,6 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
 
 X86ISA::Interrupts::Interrupts(Params * p) :
     BasicPioDevice(p), IntDev(this, p->int_latency), latency(p->pio_latency), 
-    clock(0),
     apicTimerEvent(this),
     pendingSmi(false), smiVector(0),
     pendingNmi(false), nmiVector(0),
@@ -630,6 +629,8 @@ X86ISA::Interrupts::Interrupts(Params * p) :
     pendingIPIs(0), cpu(NULL),
     intSlavePort(name() + ".int_slave", this, this, latency)
 {
+    // Override the default clock
+    clock = 0;
     pioSize = PageBytes;
     memset(regs, 0, sizeof(regs));
     //Set the local apic DFR to the flat model.
index 1b7f5a52c5afd482b3fed7286fc76448071fb1fc..06425fbdab6ee4623c608bcbb8957e573d1eae2c 100644 (file)
@@ -89,7 +89,6 @@ class Interrupts : public BasicPioDevice, IntDev
      * Timing related stuff.
      */
     Tick latency;
-    Tick clock;
 
     class ApicTimerEvent : public Event
     {
index 6784676728df071b1470c5f9c6e1fb845c339a71..acca97c4942860e559fee47b0a839bf043d0337d 100644 (file)
@@ -173,7 +173,9 @@ void initCPU(ThreadContext *tc, int cpuId)
     interrupts->setRegNoEffect(APIC_ID, cpuId << 24);
 
     interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14);
-    
+
+    // @todo: Control the relative frequency, in this case 16:1, of
+    // the clocks in the Python code
     interrupts->setClock(tc->getCpuPtr()->ticks(16));
 
     // TODO Set the SMRAM base address (SMBASE) to 0x00030000
index 9ed2cb78995e6be5b006a74cb854b2667b5dfccd..8c658b196e5a5e8d886f609fefd842c565182a6c 100644 (file)
@@ -145,9 +145,6 @@ class BaseCPU(MemObject):
     defer_registration = Param.Bool(False,
         "defer registration with system (for sampling)")
 
-    clock = Param.Clock('1t', "clock speed")
-    phase = Param.Latency('0ns', "clock phase")
-
     tracer = Param.InstTracer(default_tracer, "Instruction tracer")
 
     icache_port = MasterPort("Instruction Port")
index 893b0e06b845153d2b649598b594a78db48ea9eb..c1b1e6d3642b38db75fd567ee745d69adfdd37ad 100644 (file)
@@ -115,15 +115,12 @@ CPUProgressEvent::description() const
 }
 
 BaseCPU::BaseCPU(Params *p, bool is_checker)
-    : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id),
+    : MemObject(p), instCnt(0), _cpuId(p->cpu_id),
       _instMasterId(p->system->getMasterId(name() + ".inst")),
       _dataMasterId(p->system->getMasterId(name() + ".data")),
       interrupts(p->interrupts),
-      numThreads(p->numThreads), system(p->system),
-      phase(p->phase)
+      numThreads(p->numThreads), system(p->system)
 {
-//    currentTick = curTick();
-
     // if Python did not provide a valid ID, do it here
     if (_cpuId == -1 ) {
         _cpuId = cpuList.size();
@@ -317,27 +314,6 @@ BaseCPU::getMasterPort(const string &if_name, int idx)
         return MemObject::getMasterPort(if_name, idx);
 }
 
-Tick
-BaseCPU::nextCycle()
-{
-    Tick next_tick = curTick() - phase + clock - 1;
-    next_tick -= (next_tick % clock);
-    next_tick += phase;
-    return next_tick;
-}
-
-Tick
-BaseCPU::nextCycle(Tick begin_tick)
-{
-    Tick next_tick = begin_tick;
-    if (next_tick % clock != 0)
-        next_tick = next_tick - (next_tick % clock) + clock;
-    next_tick += phase;
-
-    assert(next_tick >= curTick());
-    return next_tick;
-}
-
 void
 BaseCPU::registerThreadContexts()
 {
index b99b25d1745a64d415212db11f44563fdfa210c2..aab6ac4cafc3213520984977504841ce00afaa92 100644 (file)
@@ -88,8 +88,7 @@ class CPUProgressEvent : public Event
 class BaseCPU : public MemObject
 {
   protected:
-    // CPU's clock period in terms of the number of ticks of curTime.
-    Tick clock;
+
     // @todo remove me after debugging with legion done
     Tick instCnt;
     // every cpu has an id, put it in the base cpu
@@ -174,30 +173,11 @@ class BaseCPU : public MemObject
      */
     MasterPort &getMasterPort(const std::string &if_name, int idx = -1);
 
-//    Tick currentTick;
-    inline Tick frequency() const { return SimClock::Frequency / clock; }
-    inline Tick ticks(int numCycles) const { return clock * numCycles; }
-    inline Tick curCycle() const { return curTick() / clock; }
-    inline Tick tickToCycles(Tick val) const { return val / clock; }
     inline void workItemBegin() { numWorkItemsStarted++; }
     inline void workItemEnd() { numWorkItemsCompleted++; }
     // @todo remove me after debugging with legion done
     Tick instCount() { return instCnt; }
 
-    /** The next cycle the CPU should be scheduled, given a cache
-     * access or quiesce event returning on this cycle.  This function
-     * may return curTick() if the CPU should run on the current cycle.
-     */
-    Tick nextCycle();
-
-    /** The next cycle the CPU should be scheduled, given a cache
-     * access or quiesce event returning on the given Tick.  This
-     * function may return curTick() if the CPU should run on the
-     * current cycle.
-     * @param begin_tick The tick that the event is completing on.
-     */
-    Tick nextCycle(Tick begin_tick);
-
     TheISA::MicrocodeRom microcodeRom;
 
   protected:
@@ -328,8 +308,6 @@ class BaseCPU : public MemObject
 
     System *system;
 
-    Tick phase;
-
     /**
      * Serialize this object to the given output stream.
      * @param os The stream to serialize to.
index 52e32d72de3c4295d6eac1b5c1c3eb4635165f4c..94617c8760e6b171ceb64980f1bab549ce709c40 100644 (file)
@@ -56,8 +56,6 @@ class MemTest : public MemObject
     // register statistics
     virtual void regStats();
 
-    inline Tick ticks(int numCycles) const { return numCycles; }
-
     // main simulation loop (one cycle)
     void tick();
 
index aec74a4849e9a8558c69bc7e452ae471d83ea1f6..76119e6782f5e378fb59e8ecdae644ed5d0eb39e 100644 (file)
@@ -51,8 +51,6 @@ class NetworkTest : public MemObject
 
     virtual void init();
 
-    inline Tick ticks(int numCycles) const { return numCycles; }
-
     // main simulation loop (one cycle)
     void tick();
 
index b89486be858b700bd56367ce2144c0357a02ce54..9aa0e1fe5387f75a0dfc1f5d983a71198749a880 100644 (file)
@@ -52,8 +52,8 @@ class CopyEngine(PciDevice):
     ChanCnt = Param.UInt8(4, "Number of DMA channels that exist on device")
     XferCap = Param.MemorySize('4kB', "Number of bits of transfer size that are supported")
 
-
-    clock = Param.Clock('500MHz', "Clock speed of the device")
+    # Override the default clock
+    clock = '500MHz'
     latBeforeBegin = Param.Latency('20ns', "Latency after a DMA command is seen before it's proccessed")
     latAfterCompletion = Param.Latency('20ns', "Latency after a DMA command is complete before it's reported as such")
 
index 91d4e230e6b049609eb976fd335f8d747b0f0e5f..1afbce8eee2a813a319975e457303c30989624b5 100644 (file)
@@ -79,7 +79,8 @@ 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")
-    clock = Param.Clock('500MHz', "Clock speed of the device")
+    # Override the default clock
+    clock = '500MHz'
     VendorID = 0x8086
     SubsystemID = 0x1008
     SubsystemVendorID = 0x8086
@@ -127,7 +128,8 @@ class EtherDevBase(EtherDevice):
     hardware_address = Param.EthernetAddr(NextEthernetAddr,
         "Ethernet Hardware Address")
 
-    clock = Param.Clock('0ns', "State machine processor frequency")
+    # Override the default clock
+    clock = '0ns'
 
     dma_read_delay = Param.Latency('0us', "fixed delay for dma reads")
     dma_read_factor = Param.Latency('0us', "multiplier for dma reads")
index 967267197d7a4674dd0a37c5b1552c07d6a67397..876188c12db402f900ecac1af480f0ebef6b2e5a 100644 (file)
@@ -118,7 +118,8 @@ class CpuLocalTimer(BasicPioDevice):
     gic = Param.Gic(Parent.any, "Gic to use for interrupting")
     int_num_timer = Param.UInt32("Interrrupt number used per-cpu to GIC")
     int_num_watchdog = Param.UInt32("Interrupt number for per-cpu watchdog to GIC")
-    clock = Param.Clock('1GHz', "Clock speed at which the timer counts")
+    # Override the default clock
+    clock = '1GHz'
 
 class PL031(AmbaIntDevice):
     type = 'PL031'
@@ -134,7 +135,8 @@ class Pl050(AmbaIntDevice):
 
 class Pl111(AmbaDmaDevice):
     type = 'Pl111'
-    clock = Param.Clock('24MHz', "Clock speed of the input")
+    # Override the default clock
+    clock = '24MHz'
     vnc   = Param.VncServer(Parent.any, "Vnc server for remote frame buffer display")
     amba_id = 0x00141111
 
index 998644a8c1ad696b2034d31ff271b6bb2c7da9d8..d79a1cf3952bb20565471d5237b7fbef0b09fe51 100644 (file)
@@ -63,7 +63,7 @@ Pl111::Pl111(const Params *p)
       lcdRis(0), lcdMis(0),
       clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
       clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
-      clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
+      clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0),
       vncserver(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
       bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
       waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
@@ -512,26 +512,6 @@ Pl111::dmaDone()
         schedule(fillFifoEvent, nextCycle());
 }
 
-
-Tick
-Pl111::nextCycle()
-{
-    Tick nextTick = curTick() + clock - 1;
-    nextTick -= nextTick%clock;
-    return nextTick;
-}
-
-Tick
-Pl111::nextCycle(Tick beginTick)
-{
-    Tick nextTick = beginTick;
-    if (nextTick%clock!=0)
-        nextTick = nextTick - (nextTick%clock) + clock;
-
-    assert(nextTick >= curTick());
-    return nextTick;
-}
-
 void
 Pl111::serialize(std::ostream &os)
 {
@@ -586,7 +566,6 @@ Pl111::serialize(std::ostream &os)
     uint8_t clcdCrsrMis_serial = clcdCrsrMis;
     SERIALIZE_SCALAR(clcdCrsrMis_serial);
 
-    SERIALIZE_SCALAR(clock);
     SERIALIZE_SCALAR(height);
     SERIALIZE_SCALAR(width);
     SERIALIZE_SCALAR(bytesPerPixel);
@@ -689,7 +668,6 @@ Pl111::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
     clcdCrsrMis = clcdCrsrMis_serial;
 
-    UNSERIALIZE_SCALAR(clock);
     UNSERIALIZE_SCALAR(height);
     UNSERIALIZE_SCALAR(width);
     UNSERIALIZE_SCALAR(bytesPerPixel);
index c4fb84efa3bd9a993180d4e43e502414009104f8..599d4fa3ee641bd73be71ec90081c2ad09a95056 100644 (file)
@@ -228,9 +228,6 @@ class Pl111: public AmbaDmaDevice
     /** Cursor masked interrupt status register - const */
     InterruptReg clcdCrsrMis;
 
-    /** Clock speed */
-    Tick clock;
-
     /** VNC server */
     VncServer *vncserver;
 
@@ -291,10 +288,6 @@ class Pl111: public AmbaDmaDevice
     /** DMA done event */
     void dmaDone();
 
-    /** Next cycle event */
-    Tick nextCycle();
-    Tick nextCycle(Tick beginTick);
-
     /** DMA framebuffer read event */
     EventWrapper<Pl111, &Pl111::readFramebuffer> readEvent;
 
index 97d3c5883a94de6f8d0ae60f424817849b39aba2..097c521860696c11b100e987486d48f821f18757 100644 (file)
@@ -58,7 +58,7 @@ CpuLocalTimer::CpuLocalTimer(Params *p)
         localTimer[i].parent = this;
         localTimer[i].intNumTimer = p->int_num_timer;
         localTimer[i].intNumWatchdog = p->int_num_watchdog;
-        localTimer[i].clock = p->clock;
+        localTimer[i].clock = clock;
         localTimer[i].cpuNum = i;
     }
     pioSize = 0x38;
@@ -339,7 +339,6 @@ CpuLocalTimer::Timer::serialize(std::ostream &os)
     DPRINTF(Checkpoint, "Serializing Arm CpuLocalTimer\n");
     SERIALIZE_SCALAR(intNumTimer);
     SERIALIZE_SCALAR(intNumWatchdog);
-    SERIALIZE_SCALAR(clock);
 
     uint32_t timer_control_serial = timerControl;
     uint32_t watchdog_control_serial = watchdogControl;
@@ -379,7 +378,6 @@ CpuLocalTimer::Timer::unserialize(Checkpoint *cp, const std::string &section)
 
     UNSERIALIZE_SCALAR(intNumTimer);
     UNSERIALIZE_SCALAR(intNumWatchdog);
-    UNSERIALIZE_SCALAR(clock);
 
     uint32_t timer_control_serial;
     UNSERIALIZE_SCALAR(timer_control_serial);
index 14d767288f0d9a02f4a98c932240f4098efb3150..f7f6a11782810d749b0db8c0e231450f5c6af6f5 100644 (file)
@@ -68,7 +68,7 @@ IGbE::IGbE(const Params *p)
       tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
       rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size),
       txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size),
-      clock(p->clock), lastInterrupt(0)
+      lastInterrupt(0)
 {
     etherInt = new IGbEInt(name() + ".int", this);
 
index a6b20a2bffb6d0414c8a230662dd67074fbd348c..099cd0d1190f2d4f5565c727137b1be001c73a59 100644 (file)
@@ -523,9 +523,7 @@ class IGbE : public EtherDevice
 
     virtual EtherInt *getEthPort(const std::string &if_name, int idx);
 
-    Tick clock;
     Tick lastInterrupt;
-    inline Tick ticks(int numCycles) const { return numCycles * clock; }
 
     virtual Tick read(PacketPtr pkt);
     virtual Tick write(PacketPtr pkt);
index 4a459c6c673ce12c1d38011a1f2ca6ef9ae016d0..6a55516c569a3b435af6d47c39703969b31869f0 100644 (file)
@@ -99,7 +99,6 @@ NSGigE::NSGigE(Params *p)
       txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
       txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
       txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
-      clock(p->clock),
       txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
       txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
       rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
index 87cf56962e3e05b6d0fe0e8218fe44324541b447..8032c0623e1c7d8881ca90cb6888656a025dc555 100644 (file)
@@ -196,10 +196,6 @@ class NSGigE : public EtherDevice
     ns_desc64 txDesc64;
     ns_desc64 rxDesc64;
 
-    /* state machine cycle time */
-    Tick clock;
-    inline Tick ticks(int numCycles) const { return numCycles * clock; }
-
     /* tx State Machine */
     TxState txState;
     bool txEnable;
index 1030e1a9c21d135a9c945325a83ed35df43f8f4e..623dcf2c137383908c075b17c1eb63c9d0d7282a 100644 (file)
@@ -78,7 +78,7 @@ const char *TxStateStrings[] =
 // Sinic PCI Device
 //
 Base::Base(const Params *p)
-    : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock),
+    : PciDev(p), rxEnable(false), txEnable(false),
       intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
       cpuPendingIntr(false), intrEvent(0), interface(NULL)
 {
index 0da7ccae4bf249389c0f15db122660903b2c1284..5532650c3a0e51ff535a328535d00854b41452ca 100644 (file)
@@ -50,8 +50,6 @@ class Base : public PciDev
   protected:
     bool rxEnable;
     bool txEnable;
-    Tick clock;
-    inline Tick ticks(int numCycles) const { return numCycles * clock; }
 
   protected:
     Tick intrDelay;
index 12657e1777e53b3cbb8e057ca6a1ee89eb669d84..b398af959ecc6c34cb4d3f50d2083a40ed3ac77c 100644 (file)
@@ -47,7 +47,8 @@ class BaseBus(MemObject):
     abstract = True
     slave = VectorSlavePort("vector port for connecting masters")
     master = VectorMasterPort("vector port for connecting slaves")
-    clock = Param.Clock("1GHz", "bus clock speed")
+    # Override the default clock
+    clock = '1GHz'
     header_cycles = Param.Int(1, "cycles of overhead per transaction")
     width = Param.Int(8, "bus width (bytes)")
     block_size = Param.Int(64, "The default block size if not set by " \
index e2e8584949c8441f6feba32b542ed615916c0189..0f33cc0bfa5c4c5f7d11b4394e9bde74fae2d88b 100644 (file)
@@ -26,8 +26,8 @@
 #
 # Authors: Ron Dreslinski
 
-from m5.SimObject import SimObject
+from ClockedObject import ClockedObject
 
-class MemObject(SimObject):
+class MemObject(ClockedObject):
     type = 'MemObject'
     abstract = True
index 583e60a15c739bfb90b4ffec70bddc1abd4def10..829d694de3bfdfff1cb41c5c5b2e688f2f9d1526 100644 (file)
@@ -47,7 +47,6 @@
  * Definition of a bus object.
  */
 
-#include "base/intmath.hh"
 #include "base/misc.hh"
 #include "base/trace.hh"
 #include "debug/Bus.hh"
@@ -56,7 +55,7 @@
 #include "mem/bus.hh"
 
 BaseBus::BaseBus(const BaseBusParams *p)
-    : MemObject(p), clock(p->clock),
+    : MemObject(p),
       headerCycles(p->header_cycles), width(p->width),
       defaultPortID(InvalidPortID),
       useDefaultRange(p->use_default_range),
@@ -114,7 +113,7 @@ BaseBus::calcPacketTiming(PacketPtr pkt)
 {
     // determine the current time rounded to the closest following
     // clock edge
-    Tick now = divCeil(curTick(), clock) * clock;
+    Tick now = nextCycle();
 
     Tick headerTime = now + headerCycles * clock;
 
@@ -287,7 +286,7 @@ BaseBus::Layer<PortClass>::retryWaiting()
 
         // determine the current time rounded to the closest following
         // clock edge
-        Tick now = divCeil(curTick(), clock) * clock;
+        Tick now = bus.nextCycle();
 
         occupyLayer(now + clock);
     }
index d4c3b4724c8c9b073b7904c8793348f9805e7287..ac35581b1da6f1f5097991f5c6f9d710400ae150 100644 (file)
@@ -228,8 +228,6 @@ class BaseBus : public MemObject
 
     };
 
-    /** the clock speed for the bus */
-    Tick clock;
     /** cycles of overhead per transaction */
     int headerCycles;
     /** the width of the bus in bytes */
index ce8badbe7bea72a85c49a371ec34acde57608817..cc05b7fc219aba02d79657ea115066a32d3e1119 100644 (file)
@@ -44,7 +44,7 @@
 #include "mem/mem_object.hh"
 
 MemObject::MemObject(const Params *params)
-    : SimObject(params)
+    : ClockedObject(params)
 {
 }
 
index d8e6bdcb0de8a870a3b11f45a4c1e581e413d1e0..6cc0c4fd3f7349936aa394d4bf510a233f2a8ed4 100644 (file)
 
 #include "mem/port.hh"
 #include "params/MemObject.hh"
-#include "sim/sim_object.hh"
+#include "sim/clocked_object.hh"
 
 /**
- * The MemObject class extends the SimObject with accessor functions
+ * The MemObject class extends the ClockedObject with accessor functions
  * to get its master and slave ports.
  */
-class MemObject : public SimObject
+class MemObject : public ClockedObject
 {
   public:
     typedef MemObjectParams Params;
diff --git a/src/sim/ClockedObject.py b/src/sim/ClockedObject.py
new file mode 100644 (file)
index 0000000..9bb243d
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright (c) 2012 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: Andreas Hansson
+
+from m5.SimObject import SimObject
+from m5.params import *
+
+class ClockedObject(SimObject):
+    type = 'ClockedObject'
+    abstract = True
+
+    clock = Param.Clock('1t', "Clock speed")
index 9f76d63814a12d12f5c42b9783818cdb2bac9d0c..16eeb36d39acaa5320ef9d3d2211c5376643311e 100644 (file)
@@ -31,6 +31,7 @@
 Import('*')
 
 SimObject('BaseTLB.py')
+SimObject('ClockedObject.py')
 SimObject('Root.py')
 SimObject('InstTracer.py')
 
diff --git a/src/sim/clocked_object.hh b/src/sim/clocked_object.hh
new file mode 100644 (file)
index 0000000..8ab6377
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012 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: Andreas Hansson
+ */
+
+/**
+ * @file
+ * ClockedObject declaration and implementation.
+ */
+
+#ifndef __SIM_CLOCKED_OBJECT_HH__
+#define __SIM_CLOCKED_OBJECT_HH__
+
+#include "base/intmath.hh"
+#include "params/ClockedObject.hh"
+#include "sim/sim_object.hh"
+
+/**
+ * The ClockedObject class extends the SimObject with a clock and
+ * accessor functions to relate ticks to the cycles of the object.
+ */
+class ClockedObject : public SimObject
+{
+
+  private:
+
+    /**
+     * Prevent inadvertent use of the copy constructor and assignment
+     * operator by making them private.
+     */
+    ClockedObject(ClockedObject&);
+    ClockedObject& operator=(ClockedObject&);
+
+  protected:
+
+    // Clock period in ticks
+    Tick clock;
+
+    /**
+     * Create a clocked object and set the clock based on the
+     * parameters.
+     */
+    ClockedObject(const ClockedObjectParams* p) : SimObject(p), clock(p->clock)
+    { }
+
+    /**
+     * Virtual destructor due to inheritance.
+     */
+    virtual ~ClockedObject() { }
+
+  public:
+
+    /**
+     * Based on the clock of the object, determine the tick when the
+     * next cycle begins, in other words, round the curTick() to the
+     * next tick that is a multiple of the clock.
+     *
+     * @return The tick when the next cycle starts
+     */
+    Tick nextCycle() const
+    { return divCeil(curTick(), clock) * clock; }
+
+    /**
+     * Determine the next cycle starting from a given tick instead of
+     * curTick().
+     *
+     * @param begin_tick The tick to round to a clock edge
+     *
+     * @return The tick when the cycle after or on begin_tick starts
+     */
+    Tick nextCycle(Tick begin_tick) const
+    { return divCeil(begin_tick, clock) * clock; }
+
+    inline Tick frequency() const { return SimClock::Frequency / clock; }
+
+    inline Tick ticks(int numCycles) const { return clock * numCycles; }
+
+    inline Tick curCycle() const { return curTick() / clock; }
+
+    inline Tick tickToCycles(Tick val) const { return val / clock; }
+
+};
+
+#endif //__SIM_CLOCKED_OBJECT_HH__