timing.hh revision 10529
12SN/A/* 21762SN/A * Copyright (c) 2012-2013 ARM Limited 32SN/A * All rights reserved 42SN/A * 52SN/A * The license below extends only to copyright in the software and shall 62SN/A * not be construed as granting a license to any other intellectual 72SN/A * property including but not limited to intellectual property relating 82SN/A * to a hardware implementation of the functionality of the software 92SN/A * licensed hereunder. You may use the software subject to the license 102SN/A * terms below provided that you ensure that this notice is replicated 112SN/A * unmodified and in its entirety in all distributions of the software, 122SN/A * modified or unmodified, in source code or in binary form. 132SN/A * 142SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 152SN/A * All rights reserved. 162SN/A * 172SN/A * Redistribution and use in source and binary forms, with or without 182SN/A * modification, are permitted provided that the following conditions are 192SN/A * met: redistributions of source code must retain the above copyright 202SN/A * notice, this list of conditions and the following disclaimer; 212SN/A * redistributions in binary form must reproduce the above copyright 222SN/A * notice, this list of conditions and the following disclaimer in the 232SN/A * documentation and/or other materials provided with the distribution; 242SN/A * neither the name of the copyright holders nor the names of its 252SN/A * contributors may be used to endorse or promote products derived from 262SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282760Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292760Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392SN/A * 402SN/A * Authors: Steve Reinhardt 418229Snate@binkert.org */ 422SN/A 438229Snate@binkert.org#ifndef __CPU_SIMPLE_TIMING_HH__ 444841Ssaidi@eecs.umich.edu#define __CPU_SIMPLE_TIMING_HH__ 452SN/A 466214Snate@binkert.org#include "cpu/simple/base.hh" 472SN/A#include "cpu/translation.hh" 482738Sstever@eecs.umich.edu#include "params/TimingSimpleCPU.hh" 49395SN/A 50237SN/Aclass TimingSimpleCPU : public BaseSimpleCPU 514000Ssaidi@eecs.umich.edu{ 522SN/A public: 539048SAli.Saidi@ARM.com 549048SAli.Saidi@ARM.com TimingSimpleCPU(TimingSimpleCPUParams * params); 559056SAli.Saidi@ARM.com virtual ~TimingSimpleCPU(); 569048SAli.Saidi@ARM.com 579048SAli.Saidi@ARM.com virtual void init(); 589056SAli.Saidi@ARM.com 599048SAli.Saidi@ARM.com private: 609048SAli.Saidi@ARM.com 619048SAli.Saidi@ARM.com /* 62217SN/A * If an access needs to be broken into fragments, currently at most two, 63502SN/A * the the following two classes are used as the sender state of the 64217SN/A * packets so the CPU can keep track of everything. In the main packet 65217SN/A * sender state, there's an array with a spot for each fragment. If a 66237SN/A * fragment has already been accepted by the CPU, aka isn't waiting for 67502SN/A * a retry, it's pointer is NULL. After each fragment has successfully 68217SN/A * been processed, the "outstanding" counter is decremented. Once the 69217SN/A * count is zero, the entire larger access is complete. 706820SLisa.Hsu@amd.com */ 716820SLisa.Hsu@amd.com class SplitMainSenderState : public Packet::SenderState 726820SLisa.Hsu@amd.com { 736820SLisa.Hsu@amd.com public: 74217SN/A int outstanding; 756227Snate@binkert.org PacketPtr fragments[2]; 76217SN/A 77217SN/A int 784841Ssaidi@eecs.umich.edu getPendingFragment() 794841Ssaidi@eecs.umich.edu { 804841Ssaidi@eecs.umich.edu if (fragments[0]) { 814841Ssaidi@eecs.umich.edu return 0; 827948SAli.Saidi@ARM.com } else if (fragments[1]) { 837948SAli.Saidi@ARM.com return 1; 847948SAli.Saidi@ARM.com } else { 857948SAli.Saidi@ARM.com return -1; 86237SN/A } 876227Snate@binkert.org } 88217SN/A }; 894841Ssaidi@eecs.umich.edu 904841Ssaidi@eecs.umich.edu class SplitFragmentSenderState : public Packet::SenderState 914841Ssaidi@eecs.umich.edu { 924841Ssaidi@eecs.umich.edu public: 937948SAli.Saidi@ARM.com SplitFragmentSenderState(PacketPtr _bigPkt, int _index) : 947948SAli.Saidi@ARM.com bigPkt(_bigPkt), index(_index) 957948SAli.Saidi@ARM.com {} 967948SAli.Saidi@ARM.com PacketPtr bigPkt; 97237SN/A int index; 98237SN/A 994000Ssaidi@eecs.umich.edu void 100237SN/A clearFromParent() 1018902Sandreas.hansson@arm.com { 1028902Sandreas.hansson@arm.com SplitMainSenderState * main_send_state = 1038902Sandreas.hansson@arm.com dynamic_cast<SplitMainSenderState *>(bigPkt->senderState); 1048902Sandreas.hansson@arm.com main_send_state->fragments[index] = NULL; 1058902Sandreas.hansson@arm.com } 1068902Sandreas.hansson@arm.com }; 1078902Sandreas.hansson@arm.com 1088902Sandreas.hansson@arm.com class FetchTranslation : public BaseTLB::Translation 1098902Sandreas.hansson@arm.com { 1108902Sandreas.hansson@arm.com protected: 1118902Sandreas.hansson@arm.com TimingSimpleCPU *cpu; 112237SN/A 113217SN/A public: 114217SN/A FetchTranslation(TimingSimpleCPU *_cpu) 115217SN/A : cpu(_cpu) 116237SN/A {} 1175543Ssaidi@eecs.umich.edu 118217SN/A void 1195543Ssaidi@eecs.umich.edu markDelayed() 1206820SLisa.Hsu@amd.com { 121217SN/A assert(cpu->_status == BaseSimpleCPU::Running); 122223SN/A cpu->_status = ITBWaitResponse; 1235543Ssaidi@eecs.umich.edu } 124223SN/A 1255543Ssaidi@eecs.umich.edu void 1265543Ssaidi@eecs.umich.edu finish(const Fault &fault, RequestPtr req, ThreadContext *tc, 1275543Ssaidi@eecs.umich.edu BaseTLB::Mode mode) 1285543Ssaidi@eecs.umich.edu { 1298902Sandreas.hansson@arm.com cpu->sendFetch(fault, req, tc); 130223SN/A } 131223SN/A }; 1325543Ssaidi@eecs.umich.edu FetchTranslation fetchTranslation; 133217SN/A 134217SN/A void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read); 1355543Ssaidi@eecs.umich.edu void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req, 136237SN/A uint8_t *data, bool read); 137237SN/A 1385543Ssaidi@eecs.umich.edu void translationFault(const Fault &fault); 139237SN/A 1405543Ssaidi@eecs.umich.edu void buildPacket(PacketPtr &pkt, RequestPtr req, bool read); 1415543Ssaidi@eecs.umich.edu void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 1425543Ssaidi@eecs.umich.edu RequestPtr req1, RequestPtr req2, RequestPtr req, 1435543Ssaidi@eecs.umich.edu uint8_t *data, bool read); 1448902Sandreas.hansson@arm.com 145237SN/A bool handleReadPacket(PacketPtr pkt); 146217SN/A // This function always implicitly uses dcache_pkt. 1472SN/A bool handleWritePacket(); 1482SN/A 1492SN/A /** 150395SN/A * A TimingCPUPort overrides the default behaviour of the 1512SN/A * recvTiming and recvRetry and implements events for the 1522SN/A * scheduling of handling of incoming packets in the following 153510SN/A * cycle. 154510SN/A */ 1552SN/A class TimingCPUPort : public MasterPort 1562SN/A { 1575739Snate@binkert.org public: 1585739Snate@binkert.org 1592SN/A TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) 160265SN/A : MasterPort(_name, _cpu), cpu(_cpu), retryEvent(this) 161512SN/A { } 1622SN/A 1635739Snate@binkert.org protected: 1645739Snate@binkert.org 165237SN/A /** 1665739Snate@binkert.org * Snooping a coherence request, do nothing. 1672SN/A */ 1682287SN/A virtual void recvTimingSnoopReq(PacketPtr pkt) {} 1692287SN/A 1702287SN/A TimingSimpleCPU* cpu; 1712868Sktlim@umich.edu 172395SN/A struct TickEvent : public Event 1732SN/A { 1742SN/A PacketPtr pkt; 1752SN/A TimingSimpleCPU *cpu; 176395SN/A 177395SN/A TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {} 1782SN/A const char *description() const { return "Timing CPU tick"; } 1792SN/A void schedule(PacketPtr _pkt, Tick t); 1802SN/A }; 181395SN/A 1822SN/A EventWrapper<MasterPort, &MasterPort::sendRetry> retryEvent; 183395SN/A }; 1842SN/A 1852SN/A class IcachePort : public TimingCPUPort 186395SN/A { 1872SN/A public: 188395SN/A 1892SN/A IcachePort(TimingSimpleCPU *_cpu) 1902SN/A : TimingCPUPort(_cpu->name() + ".icache_port", _cpu), 1912SN/A tickEvent(_cpu) 192395SN/A { } 1932SN/A 194395SN/A protected: 1952SN/A 196395SN/A virtual bool recvTimingResp(PacketPtr pkt); 1972SN/A 1982SN/A virtual void recvRetry(); 199395SN/A 200395SN/A struct ITickEvent : public TickEvent 2012SN/A { 2022SN/A 2032SN/A ITickEvent(TimingSimpleCPU *_cpu) 204395SN/A : TickEvent(_cpu) {} 205395SN/A void process(); 2062SN/A const char *description() const { return "Timing CPU icache tick"; } 2072SN/A }; 2082SN/A 2092SN/A ITickEvent tickEvent; 2102SN/A 2112SN/A }; 212395SN/A 2132SN/A class DcachePort : public TimingCPUPort 2142SN/A { 2152SN/A public: 2162SN/A 2172SN/A DcachePort(TimingSimpleCPU *_cpu) 2182SN/A : TimingCPUPort(_cpu->name() + ".dcache_port", _cpu), 2192SN/A tickEvent(_cpu) 2202SN/A { 221395SN/A cacheBlockMask = ~(cpu->cacheLineSize() - 1); 222395SN/A } 2232738Sstever@eecs.umich.edu 2242SN/A Addr cacheBlockMask; 2252SN/A protected: 2262SN/A 2272SN/A /** Snoop a coherence request, we need to check if this causes 2282SN/A * a wakeup event on a cpu that is monitoring an address 229395SN/A */ 230395SN/A virtual void recvTimingSnoopReq(PacketPtr pkt); 2312SN/A virtual void recvFunctionalSnoop(PacketPtr pkt); 232395SN/A 2332SN/A virtual bool recvTimingResp(PacketPtr pkt); 234395SN/A 2352SN/A virtual void recvRetry(); 236395SN/A 2372738Sstever@eecs.umich.edu virtual bool isSnooping() const { 2382SN/A return true; 2392SN/A } 2402SN/A 2412SN/A struct DTickEvent : public TickEvent 242395SN/A { 2432SN/A DTickEvent(TimingSimpleCPU *_cpu) 2442SN/A : TickEvent(_cpu) {} 2455543Ssaidi@eecs.umich.edu void process(); 2465543Ssaidi@eecs.umich.edu const char *description() const { return "Timing CPU dcache tick"; } 247237SN/A }; 2482SN/A 249237SN/A DTickEvent tickEvent; 250237SN/A 251237SN/A }; 252237SN/A 253237SN/A void updateCycleCounts(); 254237SN/A 255237SN/A IcachePort icachePort; 2567491Ssteve.reinhardt@amd.com DcachePort dcachePort; 2579086Sandreas.hansson@arm.com 258237SN/A PacketPtr ifetch_pkt; 259937SN/A PacketPtr dcache_pkt; 260937SN/A 261237SN/A Cycles previousCycle; 262237SN/A 263237SN/A protected: 264237SN/A 2654000Ssaidi@eecs.umich.edu /** Return a reference to the data port. */ 266304SN/A virtual MasterPort &getDataPort() { return dcachePort; } 267304SN/A 268449SN/A /** Return a reference to the instruction port. */ 269449SN/A virtual MasterPort &getInstPort() { return icachePort; } 270449SN/A 2717491Ssteve.reinhardt@amd.com public: 2727491Ssteve.reinhardt@amd.com 2737491Ssteve.reinhardt@amd.com unsigned int drain(DrainManager *drain_manager); 2747491Ssteve.reinhardt@amd.com void drainResume(); 2757491Ssteve.reinhardt@amd.com 2767491Ssteve.reinhardt@amd.com void switchOut(); 2777491Ssteve.reinhardt@amd.com void takeOverFrom(BaseCPU *oldCPU); 2787491Ssteve.reinhardt@amd.com 2797491Ssteve.reinhardt@amd.com void verifyMemoryMode() const; 2807491Ssteve.reinhardt@amd.com 2817491Ssteve.reinhardt@amd.com virtual void activateContext(ThreadID thread_num); 2827823Ssteve.reinhardt@amd.com virtual void suspendContext(ThreadID thread_num); 2837491Ssteve.reinhardt@amd.com 2847491Ssteve.reinhardt@amd.com Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); 285449SN/A 286449SN/A Fault writeMem(uint8_t *data, unsigned size, 287449SN/A Addr addr, unsigned flags, uint64_t *res); 288449SN/A 289449SN/A void fetch(); 290449SN/A void sendFetch(const Fault &fault, RequestPtr req, ThreadContext *tc); 291449SN/A void completeIfetch(PacketPtr ); 292449SN/A void completeDataAccess(PacketPtr pkt); 293449SN/A void advanceInst(const Fault &fault); 294237SN/A 2952SN/A /** This function is used by the page table walker to determine if it could 2962SN/A * translate the a pending request or if the underlying request has been 297 * squashed. This always returns false for the simple timing CPU as it never 298 * executes any instructions speculatively. 299 * @ return Is the current instruction squashed? 300 */ 301 bool isSquashed() const { return false; } 302 303 /** 304 * Print state of address in memory system via PrintReq (for 305 * debugging). 306 */ 307 void printAddr(Addr a); 308 309 /** 310 * Finish a DTB translation. 311 * @param state The DTB translation state. 312 */ 313 void finishTranslation(WholeTranslationState *state); 314 315 private: 316 317 typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent; 318 FetchEvent fetchEvent; 319 320 struct IprEvent : Event { 321 Packet *pkt; 322 TimingSimpleCPU *cpu; 323 IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t); 324 virtual void process(); 325 virtual const char *description() const; 326 }; 327 328 /** 329 * Check if a system is in a drained state. 330 * 331 * We need to drain if: 332 * <ul> 333 * <li>We are in the middle of a microcode sequence as some CPUs 334 * (e.g., HW accelerated CPUs) can't be started in the middle 335 * of a gem5 microcode sequence. 336 * 337 * <li>Stay at PC is true. 338 * 339 * <li>A fetch event is scheduled. Normally this would never be the 340 * case with microPC() == 0, but right after a context is 341 * activated it can happen. 342 * </ul> 343 */ 344 bool isDrained() { 345 return microPC() == 0 && !stayAtPC && !fetchEvent.scheduled(); 346 } 347 348 /** 349 * Try to complete a drain request. 350 * 351 * @returns true if the CPU is drained, false otherwise. 352 */ 353 bool tryCompleteDrain(); 354 355 /** 356 * Drain manager to use when signaling drain completion 357 * 358 * This pointer is non-NULL when draining and NULL otherwise. 359 */ 360 DrainManager *drainManager; 361}; 362 363#endif // __CPU_SIMPLE_TIMING_HH__ 364