timing.hh revision 10713
12623SN/A/* 22623SN/A * Copyright (c) 2012-2013 ARM Limited 32623SN/A * All rights reserved 42623SN/A * 52623SN/A * The license below extends only to copyright in the software and shall 62623SN/A * not be construed as granting a license to any other intellectual 72623SN/A * property including but not limited to intellectual property relating 82623SN/A * to a hardware implementation of the functionality of the software 92623SN/A * licensed hereunder. You may use the software subject to the license 102623SN/A * terms below provided that you ensure that this notice is replicated 112623SN/A * unmodified and in its entirety in all distributions of the software, 122623SN/A * modified or unmodified, in source code or in binary form. 132623SN/A * 142623SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 152623SN/A * All rights reserved. 162623SN/A * 172623SN/A * Redistribution and use in source and binary forms, with or without 182623SN/A * modification, are permitted provided that the following conditions are 192623SN/A * met: redistributions of source code must retain the above copyright 202623SN/A * notice, this list of conditions and the following disclaimer; 212623SN/A * redistributions in binary form must reproduce the above copyright 222623SN/A * notice, this list of conditions and the following disclaimer in the 232623SN/A * documentation and/or other materials provided with the distribution; 242623SN/A * neither the name of the copyright holders nor the names of its 252623SN/A * contributors may be used to endorse or promote products derived from 262623SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392623SN/A * 402623SN/A * Authors: Steve Reinhardt 412623SN/A */ 422623SN/A 432623SN/A#ifndef __CPU_SIMPLE_TIMING_HH__ 442623SN/A#define __CPU_SIMPLE_TIMING_HH__ 452623SN/A 462623SN/A#include "cpu/simple/base.hh" 472623SN/A#include "cpu/translation.hh" 482623SN/A#include "params/TimingSimpleCPU.hh" 492623SN/A 502623SN/Aclass TimingSimpleCPU : public BaseSimpleCPU 512623SN/A{ 522623SN/A public: 532623SN/A 542623SN/A TimingSimpleCPU(TimingSimpleCPUParams * params); 552623SN/A virtual ~TimingSimpleCPU(); 562623SN/A 572623SN/A virtual void init(); 582623SN/A 592623SN/A private: 602623SN/A 612623SN/A /* 622623SN/A * If an access needs to be broken into fragments, currently at most two, 632623SN/A * the the following two classes are used as the sender state of the 642623SN/A * packets so the CPU can keep track of everything. In the main packet 652623SN/A * sender state, there's an array with a spot for each fragment. If a 662623SN/A * fragment has already been accepted by the CPU, aka isn't waiting for 672839Sktlim@umich.edu * a retry, it's pointer is NULL. After each fragment has successfully 682798Sktlim@umich.edu * been processed, the "outstanding" counter is decremented. Once the 692623SN/A * count is zero, the entire larger access is complete. 702623SN/A */ 712623SN/A class SplitMainSenderState : public Packet::SenderState 722623SN/A { 732623SN/A public: 742623SN/A int outstanding; 752948Ssaidi@eecs.umich.edu PacketPtr fragments[2]; 762623SN/A 772623SN/A int 782623SN/A getPendingFragment() 792948Ssaidi@eecs.umich.edu { 803401Sktlim@umich.edu if (fragments[0]) { 812623SN/A return 0; 822623SN/A } else if (fragments[1]) { 833647Srdreslin@umich.edu return 1; 843647Srdreslin@umich.edu } else { 852623SN/A return -1; 862623SN/A } 873349Sbinkertn@umich.edu } 882623SN/A }; 893349Sbinkertn@umich.edu 902623SN/A class SplitFragmentSenderState : public Packet::SenderState 912623SN/A { 922623SN/A public: 932623SN/A SplitFragmentSenderState(PacketPtr _bigPkt, int _index) : 944475Sstever@eecs.umich.edu bigPkt(_bigPkt), index(_index) 954475Sstever@eecs.umich.edu {} 962948Ssaidi@eecs.umich.edu PacketPtr bigPkt; 972948Ssaidi@eecs.umich.edu int index; 982948Ssaidi@eecs.umich.edu 993349Sbinkertn@umich.edu void 1002948Ssaidi@eecs.umich.edu clearFromParent() 1012948Ssaidi@eecs.umich.edu { 1022948Ssaidi@eecs.umich.edu SplitMainSenderState * main_send_state = 1032948Ssaidi@eecs.umich.edu dynamic_cast<SplitMainSenderState *>(bigPkt->senderState); 1044873Sstever@eecs.umich.edu main_send_state->fragments[index] = NULL; 1053349Sbinkertn@umich.edu } 1062948Ssaidi@eecs.umich.edu }; 1072948Ssaidi@eecs.umich.edu 1082623SN/A class FetchTranslation : public BaseTLB::Translation 1092623SN/A { 1102623SN/A protected: 1112623SN/A TimingSimpleCPU *cpu; 1122623SN/A 1132623SN/A public: 1142948Ssaidi@eecs.umich.edu FetchTranslation(TimingSimpleCPU *_cpu) 1152948Ssaidi@eecs.umich.edu : cpu(_cpu) 1162623SN/A {} 1172623SN/A 1182623SN/A void 1192623SN/A markDelayed() 1203349Sbinkertn@umich.edu { 1212623SN/A assert(cpu->_status == BaseSimpleCPU::Running); 1222657Ssaidi@eecs.umich.edu cpu->_status = ITBWaitResponse; 1232948Ssaidi@eecs.umich.edu } 1242948Ssaidi@eecs.umich.edu 1252948Ssaidi@eecs.umich.edu void 1262948Ssaidi@eecs.umich.edu finish(const Fault &fault, RequestPtr req, ThreadContext *tc, 1272948Ssaidi@eecs.umich.edu BaseTLB::Mode mode) 1282948Ssaidi@eecs.umich.edu { 1292948Ssaidi@eecs.umich.edu cpu->sendFetch(fault, req, tc); 1304873Sstever@eecs.umich.edu } 1312948Ssaidi@eecs.umich.edu }; 1322948Ssaidi@eecs.umich.edu FetchTranslation fetchTranslation; 1332948Ssaidi@eecs.umich.edu 1342948Ssaidi@eecs.umich.edu void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read); 1352623SN/A void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req, 1362623SN/A uint8_t *data, bool read); 1372623SN/A 1382623SN/A void translationFault(const Fault &fault); 1392623SN/A 1402623SN/A PacketPtr buildPacket(RequestPtr req, bool read); 1412948Ssaidi@eecs.umich.edu void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 1422948Ssaidi@eecs.umich.edu RequestPtr req1, RequestPtr req2, RequestPtr req, 1432623SN/A uint8_t *data, bool read); 1442623SN/A 1454192Sktlim@umich.edu bool handleReadPacket(PacketPtr pkt); 1464192Sktlim@umich.edu // This function always implicitly uses dcache_pkt. 1472623SN/A bool handleWritePacket(); 1482623SN/A 1493349Sbinkertn@umich.edu /** 1502623SN/A * A TimingCPUPort overrides the default behaviour of the 1512657Ssaidi@eecs.umich.edu * recvTiming and recvRetry and implements events for the 1522948Ssaidi@eecs.umich.edu * scheduling of handling of incoming packets in the following 1532948Ssaidi@eecs.umich.edu * cycle. 1542948Ssaidi@eecs.umich.edu */ 1552948Ssaidi@eecs.umich.edu class TimingCPUPort : public MasterPort 1562948Ssaidi@eecs.umich.edu { 1572948Ssaidi@eecs.umich.edu public: 1584873Sstever@eecs.umich.edu 1592948Ssaidi@eecs.umich.edu TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) 1602948Ssaidi@eecs.umich.edu : MasterPort(_name, _cpu), cpu(_cpu), retryRespEvent(this) 1612948Ssaidi@eecs.umich.edu { } 1622948Ssaidi@eecs.umich.edu 1632623SN/A protected: 1642623SN/A 1652623SN/A /** 1662623SN/A * Snooping a coherence request, do nothing. 1672623SN/A */ 1683349Sbinkertn@umich.edu virtual void recvTimingSnoopReq(PacketPtr pkt) {} 1693349Sbinkertn@umich.edu 1702623SN/A TimingSimpleCPU* cpu; 1713222Sktlim@umich.edu 1723170Sstever@eecs.umich.edu struct TickEvent : public Event 1732623SN/A { 1742623SN/A PacketPtr pkt; 1752856Srdreslin@umich.edu TimingSimpleCPU *cpu; 1762856Srdreslin@umich.edu 1772623SN/A TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {} 1782623SN/A const char *description() const { return "Timing CPU tick"; } 1792623SN/A void schedule(PacketPtr _pkt, Tick t); 1802901Ssaidi@eecs.umich.edu }; 1812798Sktlim@umich.edu 1822798Sktlim@umich.edu EventWrapper<MasterPort, &MasterPort::sendRetryResp> retryRespEvent; 1832798Sktlim@umich.edu }; 1842623SN/A 1852623SN/A class IcachePort : public TimingCPUPort 1862623SN/A { 1872623SN/A public: 1882623SN/A 1892623SN/A IcachePort(TimingSimpleCPU *_cpu) 1902623SN/A : TimingCPUPort(_cpu->name() + ".icache_port", _cpu), 1912623SN/A tickEvent(_cpu) 1925177Sgblack@eecs.umich.edu { } 1935177Sgblack@eecs.umich.edu 1945177Sgblack@eecs.umich.edu protected: 1952623SN/A 1962623SN/A virtual bool recvTimingResp(PacketPtr pkt); 1972623SN/A 1985177Sgblack@eecs.umich.edu virtual void recvReqRetry(); 1995177Sgblack@eecs.umich.edu 2005177Sgblack@eecs.umich.edu struct ITickEvent : public TickEvent 2012623SN/A { 2023349Sbinkertn@umich.edu 2033349Sbinkertn@umich.edu ITickEvent(TimingSimpleCPU *_cpu) 2042644Sstever@eecs.umich.edu : TickEvent(_cpu) {} 2054471Sstever@eecs.umich.edu void process(); 2065315Sstever@gmail.com const char *description() const { return "Timing CPU icache tick"; } 2075315Sstever@gmail.com }; 2085315Sstever@gmail.com 2095315Sstever@gmail.com ITickEvent tickEvent; 2105315Sstever@gmail.com 2115315Sstever@gmail.com }; 2122798Sktlim@umich.edu 2134471Sstever@eecs.umich.edu class DcachePort : public TimingCPUPort 2144471Sstever@eecs.umich.edu { 2154471Sstever@eecs.umich.edu public: 2164471Sstever@eecs.umich.edu 2175103Ssaidi@eecs.umich.edu DcachePort(TimingSimpleCPU *_cpu) 2185103Ssaidi@eecs.umich.edu : TimingCPUPort(_cpu->name() + ".dcache_port", _cpu), 2195103Ssaidi@eecs.umich.edu tickEvent(_cpu) 2205103Ssaidi@eecs.umich.edu { 2215103Ssaidi@eecs.umich.edu cacheBlockMask = ~(cpu->cacheLineSize() - 1); 2225103Ssaidi@eecs.umich.edu } 2235103Ssaidi@eecs.umich.edu 2245103Ssaidi@eecs.umich.edu Addr cacheBlockMask; 2252839Sktlim@umich.edu protected: 2262623SN/A 2272623SN/A /** Snoop a coherence request, we need to check if this causes 2282623SN/A * a wakeup event on a cpu that is monitoring an address 229 */ 230 virtual void recvTimingSnoopReq(PacketPtr pkt); 231 virtual void recvFunctionalSnoop(PacketPtr pkt); 232 233 virtual bool recvTimingResp(PacketPtr pkt); 234 235 virtual void recvReqRetry(); 236 237 virtual bool isSnooping() const { 238 return true; 239 } 240 241 struct DTickEvent : public TickEvent 242 { 243 DTickEvent(TimingSimpleCPU *_cpu) 244 : TickEvent(_cpu) {} 245 void process(); 246 const char *description() const { return "Timing CPU dcache tick"; } 247 }; 248 249 DTickEvent tickEvent; 250 251 }; 252 253 void updateCycleCounts(); 254 255 IcachePort icachePort; 256 DcachePort dcachePort; 257 258 PacketPtr ifetch_pkt; 259 PacketPtr dcache_pkt; 260 261 Cycles previousCycle; 262 263 protected: 264 265 /** Return a reference to the data port. */ 266 virtual MasterPort &getDataPort() { return dcachePort; } 267 268 /** Return a reference to the instruction port. */ 269 virtual MasterPort &getInstPort() { return icachePort; } 270 271 public: 272 273 unsigned int drain(DrainManager *drain_manager); 274 void drainResume(); 275 276 void switchOut(); 277 void takeOverFrom(BaseCPU *oldCPU); 278 279 void verifyMemoryMode() const; 280 281 virtual void activateContext(ThreadID thread_num); 282 virtual void suspendContext(ThreadID thread_num); 283 284 Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); 285 286 Fault writeMem(uint8_t *data, unsigned size, 287 Addr addr, unsigned flags, uint64_t *res); 288 289 void fetch(); 290 void sendFetch(const Fault &fault, RequestPtr req, ThreadContext *tc); 291 void completeIfetch(PacketPtr ); 292 void completeDataAccess(PacketPtr pkt); 293 void advanceInst(const Fault &fault); 294 295 /** This function is used by the page table walker to determine if it could 296 * 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