timing.hh revision 13954
17259Sgblack@eecs.umich.edu/* 212669Schuan.zhu@arm.com * Copyright (c) 2012-2013,2015,2018 ARM Limited 37259Sgblack@eecs.umich.edu * All rights reserved 47259Sgblack@eecs.umich.edu * 57259Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67259Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77259Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87259Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97259Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107259Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117259Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127259Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137259Sgblack@eecs.umich.edu * 147259Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 157259Sgblack@eecs.umich.edu * All rights reserved. 167259Sgblack@eecs.umich.edu * 177259Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 187259Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 197259Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 207259Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 217259Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 227259Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 237259Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 247259Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 257259Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 267259Sgblack@eecs.umich.edu * this software without specific prior written permission. 277259Sgblack@eecs.umich.edu * 287259Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 297259Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 307259Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 317259Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327259Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 337259Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 347259Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 357259Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 367259Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 377259Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 387405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3910037SARM gem5 Developers * 407259Sgblack@eecs.umich.edu * Authors: Steve Reinhardt 417259Sgblack@eecs.umich.edu */ 4211793Sbrandon.potter@amd.com 4311793Sbrandon.potter@amd.com#ifndef __CPU_SIMPLE_TIMING_HH__ 4411939Snikos.nikoleris@arm.com#define __CPU_SIMPLE_TIMING_HH__ 4511939Snikos.nikoleris@arm.com 467405SAli.Saidi@ARM.com#include "cpu/simple/base.hh" 4712334Sgabeblack@google.com#include "cpu/simple/exec_context.hh" 4810037SARM gem5 Developers#include "cpu/translation.hh" 4910828SGiacomo.Gabrielli@arm.com#include "params/TimingSimpleCPU.hh" 507259Sgblack@eecs.umich.edu 517259Sgblack@eecs.umich.educlass TimingSimpleCPU : public BaseSimpleCPU 527259Sgblack@eecs.umich.edu{ 537259Sgblack@eecs.umich.edu public: 547259Sgblack@eecs.umich.edu 558868SMatt.Horsnell@arm.com TimingSimpleCPU(TimingSimpleCPUParams * params); 568868SMatt.Horsnell@arm.com virtual ~TimingSimpleCPU(); 578868SMatt.Horsnell@arm.com 588868SMatt.Horsnell@arm.com void init() override; 5910037SARM gem5 Developers 608868SMatt.Horsnell@arm.com private: 6110037SARM gem5 Developers 628868SMatt.Horsnell@arm.com /* 6310037SARM gem5 Developers * If an access needs to be broken into fragments, currently at most two, 6410037SARM gem5 Developers * the the following two classes are used as the sender state of the 6510037SARM gem5 Developers * packets so the CPU can keep track of everything. In the main packet 6610037SARM gem5 Developers * sender state, there's an array with a spot for each fragment. If a 6710037SARM gem5 Developers * fragment has already been accepted by the CPU, aka isn't waiting for 6810037SARM gem5 Developers * a retry, it's pointer is NULL. After each fragment has successfully 6910037SARM gem5 Developers * been processed, the "outstanding" counter is decremented. Once the 708868SMatt.Horsnell@arm.com * count is zero, the entire larger access is complete. 7110037SARM gem5 Developers */ 7210037SARM gem5 Developers class SplitMainSenderState : public Packet::SenderState 7310037SARM gem5 Developers { 7410037SARM gem5 Developers public: 7510037SARM gem5 Developers int outstanding; 7610037SARM gem5 Developers PacketPtr fragments[2]; 7710037SARM gem5 Developers 7810037SARM gem5 Developers int 7910037SARM gem5 Developers getPendingFragment() 8010037SARM gem5 Developers { 8110037SARM gem5 Developers if (fragments[0]) { 829959Schander.sudanthi@arm.com return 0; 8310037SARM gem5 Developers } else if (fragments[1]) { 849959Schander.sudanthi@arm.com return 1; 859959Schander.sudanthi@arm.com } else { 869959Schander.sudanthi@arm.com return -1; 879959Schander.sudanthi@arm.com } 889959Schander.sudanthi@arm.com } 899959Schander.sudanthi@arm.com }; 909959Schander.sudanthi@arm.com 919959Schander.sudanthi@arm.com class SplitFragmentSenderState : public Packet::SenderState 929959Schander.sudanthi@arm.com { 9310037SARM gem5 Developers public: 949959Schander.sudanthi@arm.com SplitFragmentSenderState(PacketPtr _bigPkt, int _index) : 9510037SARM gem5 Developers bigPkt(_bigPkt), index(_index) 9610037SARM gem5 Developers {} 9710037SARM gem5 Developers PacketPtr bigPkt; 9810037SARM gem5 Developers int index; 9910037SARM gem5 Developers 10010037SARM gem5 Developers void 10110037SARM gem5 Developers clearFromParent() 10210037SARM gem5 Developers { 10310037SARM gem5 Developers SplitMainSenderState * main_send_state = 10410037SARM gem5 Developers dynamic_cast<SplitMainSenderState *>(bigPkt->senderState); 10510037SARM gem5 Developers main_send_state->fragments[index] = NULL; 1068868SMatt.Horsnell@arm.com } 10710037SARM gem5 Developers }; 10810037SARM gem5 Developers 10910037SARM gem5 Developers class FetchTranslation : public BaseTLB::Translation 11010037SARM gem5 Developers { 11110037SARM gem5 Developers protected: 11210037SARM gem5 Developers TimingSimpleCPU *cpu; 11310037SARM gem5 Developers 11410037SARM gem5 Developers public: 11510037SARM gem5 Developers FetchTranslation(TimingSimpleCPU *_cpu) 11610037SARM gem5 Developers : cpu(_cpu) 11710037SARM gem5 Developers {} 11810037SARM gem5 Developers 11910037SARM gem5 Developers void 12010037SARM gem5 Developers markDelayed() 12110037SARM gem5 Developers { 1228868SMatt.Horsnell@arm.com assert(cpu->_status == BaseSimpleCPU::Running); 12310037SARM gem5 Developers cpu->_status = ITBWaitResponse; 12410037SARM gem5 Developers } 12510037SARM gem5 Developers 12610037SARM gem5 Developers void 12710037SARM gem5 Developers finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, 1288868SMatt.Horsnell@arm.com BaseTLB::Mode mode) 12910037SARM gem5 Developers { 13010037SARM gem5 Developers cpu->sendFetch(fault, req, tc); 1318868SMatt.Horsnell@arm.com } 1327259Sgblack@eecs.umich.edu }; 1337259Sgblack@eecs.umich.edu FetchTranslation fetchTranslation; 1347259Sgblack@eecs.umich.edu 1357259Sgblack@eecs.umich.edu void threadSnoop(PacketPtr pkt, ThreadID sender); 1367259Sgblack@eecs.umich.edu void sendData(const RequestPtr &req, 1377259Sgblack@eecs.umich.edu uint8_t *data, uint64_t *res, bool read); 1387259Sgblack@eecs.umich.edu void sendSplitData(const RequestPtr &req1, const RequestPtr &req2, 1397259Sgblack@eecs.umich.edu const RequestPtr &req, 1407259Sgblack@eecs.umich.edu uint8_t *data, bool read); 1417259Sgblack@eecs.umich.edu 1427259Sgblack@eecs.umich.edu void translationFault(const Fault &fault); 1437259Sgblack@eecs.umich.edu 1447259Sgblack@eecs.umich.edu PacketPtr buildPacket(const RequestPtr &req, bool read); 1457351Sgblack@eecs.umich.edu void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 1467351Sgblack@eecs.umich.edu const RequestPtr &req1, const RequestPtr &req2, 1477259Sgblack@eecs.umich.edu const RequestPtr &req, 1487259Sgblack@eecs.umich.edu uint8_t *data, bool read); 14910037SARM gem5 Developers 15010037SARM gem5 Developers bool handleReadPacket(PacketPtr pkt); 1517259Sgblack@eecs.umich.edu // This function always implicitly uses dcache_pkt. 1527259Sgblack@eecs.umich.edu bool handleWritePacket(); 1537259Sgblack@eecs.umich.edu 1547259Sgblack@eecs.umich.edu /** 1557259Sgblack@eecs.umich.edu * A TimingCPUPort overrides the default behaviour of the 1567259Sgblack@eecs.umich.edu * recvTiming and recvRetry and implements events for the 1577259Sgblack@eecs.umich.edu * scheduling of handling of incoming packets in the following 1587259Sgblack@eecs.umich.edu * cycle. 1597259Sgblack@eecs.umich.edu */ 1607259Sgblack@eecs.umich.edu class TimingCPUPort : public MasterPort 1617259Sgblack@eecs.umich.edu { 1627259Sgblack@eecs.umich.edu public: 1637259Sgblack@eecs.umich.edu 1647259Sgblack@eecs.umich.edu TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) 1657259Sgblack@eecs.umich.edu : MasterPort(_name, _cpu), cpu(_cpu), 1667259Sgblack@eecs.umich.edu retryRespEvent([this]{ sendRetryResp(); }, name()) 1677259Sgblack@eecs.umich.edu { } 1687259Sgblack@eecs.umich.edu 1697259Sgblack@eecs.umich.edu protected: 1707259Sgblack@eecs.umich.edu 1717259Sgblack@eecs.umich.edu TimingSimpleCPU* cpu; 1727259Sgblack@eecs.umich.edu 1737259Sgblack@eecs.umich.edu struct TickEvent : public Event 1747259Sgblack@eecs.umich.edu { 1757259Sgblack@eecs.umich.edu PacketPtr pkt; 1767259Sgblack@eecs.umich.edu TimingSimpleCPU *cpu; 1777259Sgblack@eecs.umich.edu 1787259Sgblack@eecs.umich.edu TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {} 1797259Sgblack@eecs.umich.edu const char *description() const { return "Timing CPU tick"; } 1807259Sgblack@eecs.umich.edu void schedule(PacketPtr _pkt, Tick t); 1817259Sgblack@eecs.umich.edu }; 1827259Sgblack@eecs.umich.edu 1837259Sgblack@eecs.umich.edu EventFunctionWrapper retryRespEvent; 1847259Sgblack@eecs.umich.edu }; 1857259Sgblack@eecs.umich.edu 1867259Sgblack@eecs.umich.edu class IcachePort : public TimingCPUPort 1877259Sgblack@eecs.umich.edu { 1887259Sgblack@eecs.umich.edu public: 1897259Sgblack@eecs.umich.edu 1907259Sgblack@eecs.umich.edu IcachePort(TimingSimpleCPU *_cpu) 1917259Sgblack@eecs.umich.edu : TimingCPUPort(_cpu->name() + ".icache_port", _cpu), 1927259Sgblack@eecs.umich.edu tickEvent(_cpu) 1937259Sgblack@eecs.umich.edu { } 1947259Sgblack@eecs.umich.edu 1957259Sgblack@eecs.umich.edu protected: 1967259Sgblack@eecs.umich.edu 1977259Sgblack@eecs.umich.edu virtual bool recvTimingResp(PacketPtr pkt); 1987259Sgblack@eecs.umich.edu 1997259Sgblack@eecs.umich.edu virtual void recvReqRetry(); 2007259Sgblack@eecs.umich.edu 2017259Sgblack@eecs.umich.edu struct ITickEvent : public TickEvent 2027259Sgblack@eecs.umich.edu { 2037259Sgblack@eecs.umich.edu 2047259Sgblack@eecs.umich.edu ITickEvent(TimingSimpleCPU *_cpu) 2057259Sgblack@eecs.umich.edu : TickEvent(_cpu) {} 2067259Sgblack@eecs.umich.edu void process(); 2077259Sgblack@eecs.umich.edu const char *description() const { return "Timing CPU icache tick"; } 2087259Sgblack@eecs.umich.edu }; 2097259Sgblack@eecs.umich.edu 2107259Sgblack@eecs.umich.edu ITickEvent tickEvent; 2117259Sgblack@eecs.umich.edu 2127259Sgblack@eecs.umich.edu }; 2137259Sgblack@eecs.umich.edu 2147259Sgblack@eecs.umich.edu class DcachePort : public TimingCPUPort 21510037SARM gem5 Developers { 21610037SARM gem5 Developers public: 21710037SARM gem5 Developers 21810037SARM gem5 Developers DcachePort(TimingSimpleCPU *_cpu) 21910037SARM gem5 Developers : TimingCPUPort(_cpu->name() + ".dcache_port", _cpu), 22010037SARM gem5 Developers tickEvent(_cpu) 22110037SARM gem5 Developers { 22210037SARM gem5 Developers cacheBlockMask = ~(cpu->cacheLineSize() - 1); 2237259Sgblack@eecs.umich.edu } 2247259Sgblack@eecs.umich.edu 2257259Sgblack@eecs.umich.edu Addr cacheBlockMask; 2267351Sgblack@eecs.umich.edu protected: 2277351Sgblack@eecs.umich.edu 2287351Sgblack@eecs.umich.edu /** Snoop a coherence request, we need to check if this causes 2297351Sgblack@eecs.umich.edu * a wakeup event on a cpu that is monitoring an address 2307351Sgblack@eecs.umich.edu */ 2317351Sgblack@eecs.umich.edu virtual void recvTimingSnoopReq(PacketPtr pkt); 2327351Sgblack@eecs.umich.edu virtual void recvFunctionalSnoop(PacketPtr pkt); 2337351Sgblack@eecs.umich.edu 2347351Sgblack@eecs.umich.edu virtual bool recvTimingResp(PacketPtr pkt); 2357351Sgblack@eecs.umich.edu 2367351Sgblack@eecs.umich.edu virtual void recvReqRetry(); 2377351Sgblack@eecs.umich.edu 2387351Sgblack@eecs.umich.edu virtual bool isSnooping() const { 2397351Sgblack@eecs.umich.edu return true; 2407351Sgblack@eecs.umich.edu } 2417351Sgblack@eecs.umich.edu 2427351Sgblack@eecs.umich.edu struct DTickEvent : public TickEvent 2437351Sgblack@eecs.umich.edu { 2447351Sgblack@eecs.umich.edu DTickEvent(TimingSimpleCPU *_cpu) 2457351Sgblack@eecs.umich.edu : TickEvent(_cpu) {} 24610037SARM gem5 Developers void process(); 24710037SARM gem5 Developers const char *description() const { return "Timing CPU dcache tick"; } 24810037SARM gem5 Developers }; 24910037SARM gem5 Developers 25010037SARM gem5 Developers DTickEvent tickEvent; 25110037SARM gem5 Developers 25210037SARM gem5 Developers }; 25310037SARM gem5 Developers 25410037SARM gem5 Developers void updateCycleCounts(); 25510037SARM gem5 Developers 25610037SARM gem5 Developers IcachePort icachePort; 25710037SARM gem5 Developers DcachePort dcachePort; 25810037SARM gem5 Developers 25910037SARM gem5 Developers PacketPtr ifetch_pkt; 26010037SARM gem5 Developers PacketPtr dcache_pkt; 26110037SARM gem5 Developers 26210037SARM gem5 Developers Cycles previousCycle; 26310037SARM gem5 Developers 26410037SARM gem5 Developers protected: 26510037SARM gem5 Developers 2667351Sgblack@eecs.umich.edu /** Return a reference to the data port. */ 2677351Sgblack@eecs.umich.edu MasterPort &getDataPort() override { return dcachePort; } 2687351Sgblack@eecs.umich.edu 2697406SAli.Saidi@ARM.com /** Return a reference to the instruction port. */ 2707259Sgblack@eecs.umich.edu MasterPort &getInstPort() override { return icachePort; } 2717259Sgblack@eecs.umich.edu 2727351Sgblack@eecs.umich.edu public: 2737259Sgblack@eecs.umich.edu 2747351Sgblack@eecs.umich.edu DrainState drain() override; 2757351Sgblack@eecs.umich.edu void drainResume() override; 2767351Sgblack@eecs.umich.edu 2777259Sgblack@eecs.umich.edu void switchOut() override; 27810037SARM gem5 Developers void takeOverFrom(BaseCPU *oldCPU) override; 27910037SARM gem5 Developers 28010037SARM gem5 Developers void verifyMemoryMode() const override; 28110037SARM gem5 Developers 28210037SARM gem5 Developers void activateContext(ThreadID thread_num) override; 2837259Sgblack@eecs.umich.edu void suspendContext(ThreadID thread_num) override; 2847259Sgblack@eecs.umich.edu 2857351Sgblack@eecs.umich.edu Fault initiateMemRead(Addr addr, unsigned size, 2867351Sgblack@eecs.umich.edu Request::Flags flags, 2877351Sgblack@eecs.umich.edu const std::vector<bool>& byteEnable =std::vector<bool>()) 2887351Sgblack@eecs.umich.edu override; 2897351Sgblack@eecs.umich.edu 2907259Sgblack@eecs.umich.edu Fault writeMem(uint8_t *data, unsigned size, 2917259Sgblack@eecs.umich.edu Addr addr, Request::Flags flags, uint64_t *res, 2927259Sgblack@eecs.umich.edu const std::vector<bool>& byteEnable = std::vector<bool>()) 2937259Sgblack@eecs.umich.edu override; 2947259Sgblack@eecs.umich.edu 2957259Sgblack@eecs.umich.edu Fault initiateMemAMO(Addr addr, unsigned size, Request::Flags flags, 2967259Sgblack@eecs.umich.edu AtomicOpFunctor *amo_op) override; 2977259Sgblack@eecs.umich.edu 2987259Sgblack@eecs.umich.edu void fetch(); 2997259Sgblack@eecs.umich.edu void sendFetch(const Fault &fault, 3007259Sgblack@eecs.umich.edu const RequestPtr &req, ThreadContext *tc); 3017259Sgblack@eecs.umich.edu void completeIfetch(PacketPtr ); 3027259Sgblack@eecs.umich.edu void completeDataAccess(PacketPtr pkt); 3037259Sgblack@eecs.umich.edu void advanceInst(const Fault &fault); 3047259Sgblack@eecs.umich.edu 30510037SARM gem5 Developers /** This function is used by the page table walker to determine if it could 30610037SARM gem5 Developers * translate the a pending request or if the underlying request has been 30710037SARM gem5 Developers * squashed. This always returns false for the simple timing CPU as it never 30810037SARM gem5 Developers * executes any instructions speculatively. 30910037SARM gem5 Developers * @ return Is the current instruction squashed? 31010037SARM gem5 Developers */ 31110037SARM gem5 Developers bool isSquashed() const { return false; } 31210037SARM gem5 Developers 31310037SARM gem5 Developers /** 3147259Sgblack@eecs.umich.edu * Print state of address in memory system via PrintReq (for 3157259Sgblack@eecs.umich.edu * debugging). 3167259Sgblack@eecs.umich.edu */ 3177351Sgblack@eecs.umich.edu void printAddr(Addr a); 3187351Sgblack@eecs.umich.edu 3197259Sgblack@eecs.umich.edu /** 3207351Sgblack@eecs.umich.edu * Finish a DTB translation. 3217259Sgblack@eecs.umich.edu * @param state The DTB translation state. 3227351Sgblack@eecs.umich.edu */ 3237259Sgblack@eecs.umich.edu void finishTranslation(WholeTranslationState *state); 32410037SARM gem5 Developers 32510037SARM gem5 Developers private: 32610037SARM gem5 Developers 32710037SARM gem5 Developers EventFunctionWrapper fetchEvent; 32810037SARM gem5 Developers 32910037SARM gem5 Developers struct IprEvent : Event { 33010037SARM gem5 Developers Packet *pkt; 33110037SARM gem5 Developers TimingSimpleCPU *cpu; 33210037SARM gem5 Developers IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t); 3337259Sgblack@eecs.umich.edu virtual void process(); 3347259Sgblack@eecs.umich.edu virtual const char *description() const; 3357259Sgblack@eecs.umich.edu }; 3367259Sgblack@eecs.umich.edu 3377259Sgblack@eecs.umich.edu /** 3387259Sgblack@eecs.umich.edu * Check if a system is in a drained state. 3397259Sgblack@eecs.umich.edu * 3407259Sgblack@eecs.umich.edu * We need to drain if: 3417259Sgblack@eecs.umich.edu * <ul> 3427259Sgblack@eecs.umich.edu * <li>We are in the middle of a microcode sequence as some CPUs 3437259Sgblack@eecs.umich.edu * (e.g., HW accelerated CPUs) can't be started in the middle 3447259Sgblack@eecs.umich.edu * of a gem5 microcode sequence. 3457259Sgblack@eecs.umich.edu * 3467259Sgblack@eecs.umich.edu * <li>Stay at PC is true. 3477259Sgblack@eecs.umich.edu * 3487259Sgblack@eecs.umich.edu * <li>A fetch event is scheduled. Normally this would never be the 3497259Sgblack@eecs.umich.edu * case with microPC() == 0, but right after a context is 3507259Sgblack@eecs.umich.edu * activated it can happen. 3517351Sgblack@eecs.umich.edu * </ul> 3527351Sgblack@eecs.umich.edu */ 3537351Sgblack@eecs.umich.edu bool isDrained() { 3547351Sgblack@eecs.umich.edu SimpleExecContext& t_info = *threadInfo[curThread]; 3557351Sgblack@eecs.umich.edu SimpleThread* thread = t_info.thread; 3567259Sgblack@eecs.umich.edu 3577259Sgblack@eecs.umich.edu return thread->microPC() == 0 && !t_info.stayAtPC && 3587259Sgblack@eecs.umich.edu !fetchEvent.scheduled(); 3597259Sgblack@eecs.umich.edu } 3607259Sgblack@eecs.umich.edu 3617259Sgblack@eecs.umich.edu /** 3627259Sgblack@eecs.umich.edu * Try to complete a drain request. 3637259Sgblack@eecs.umich.edu * 3647259Sgblack@eecs.umich.edu * @returns true if the CPU is drained, false otherwise. 3657259Sgblack@eecs.umich.edu */ 3667259Sgblack@eecs.umich.edu bool tryCompleteDrain(); 3677259Sgblack@eecs.umich.edu}; 3687259Sgblack@eecs.umich.edu 3697259Sgblack@eecs.umich.edu#endif // __CPU_SIMPLE_TIMING_HH__ 3707259Sgblack@eecs.umich.edu