Clock: Move the clock and related functions to ClockedObject
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).
This commit is contained in:
parent
4ebefc145a
commit
452217817f
29 changed files with 197 additions and 122 deletions
|
@ -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.
|
||||
|
|
|
@ -89,7 +89,6 @@ class Interrupts : public BasicPioDevice, IntDev
|
|||
* Timing related stuff.
|
||||
*/
|
||||
Tick latency;
|
||||
Tick clock;
|
||||
|
||||
class ApicTimerEvent : public Event
|
||||
{
|
||||
|
|
|
@ -174,6 +174,8 @@ void initCPU(ThreadContext *tc, int cpuId)
|
|||
|
||||
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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 §ion)
|
|||
UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
|
||||
clcdCrsrMis = clcdCrsrMis_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(clock);
|
||||
UNSERIALIZE_SCALAR(height);
|
||||
UNSERIALIZE_SCALAR(width);
|
||||
UNSERIALIZE_SCALAR(bytesPerPixel);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 §ion)
|
|||
|
||||
UNSERIALIZE_SCALAR(intNumTimer);
|
||||
UNSERIALIZE_SCALAR(intNumWatchdog);
|
||||
UNSERIALIZE_SCALAR(clock);
|
||||
|
||||
uint32_t timer_control_serial;
|
||||
UNSERIALIZE_SCALAR(timer_control_serial);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 " \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#include "mem/mem_object.hh"
|
||||
|
||||
MemObject::MemObject(const Params *params)
|
||||
: SimObject(params)
|
||||
: ClockedObject(params)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -51,13 +51,13 @@
|
|||
|
||||
#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;
|
||||
|
|
45
src/sim/ClockedObject.py
Normal file
45
src/sim/ClockedObject.py
Normal file
|
@ -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")
|
|
@ -31,6 +31,7 @@
|
|||
Import('*')
|
||||
|
||||
SimObject('BaseTLB.py')
|
||||
SimObject('ClockedObject.py')
|
||||
SimObject('Root.py')
|
||||
SimObject('InstTracer.py')
|
||||
|
||||
|
|
118
src/sim/clocked_object.hh
Normal file
118
src/sim/clocked_object.hh
Normal file
|
@ -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__
|
Loading…
Reference in a new issue