timing.hh revision 9523:b8c8437f71d9
113759Sgiacomo.gabrielli@arm.com/* 27760SGiacomo.Gabrielli@arm.com * Copyright (c) 2012 ARM Limited 37760SGiacomo.Gabrielli@arm.com * All rights reserved 47760SGiacomo.Gabrielli@arm.com * 57760SGiacomo.Gabrielli@arm.com * The license below extends only to copyright in the software and shall 67760SGiacomo.Gabrielli@arm.com * not be construed as granting a license to any other intellectual 77760SGiacomo.Gabrielli@arm.com * property including but not limited to intellectual property relating 87760SGiacomo.Gabrielli@arm.com * to a hardware implementation of the functionality of the software 97760SGiacomo.Gabrielli@arm.com * licensed hereunder. You may use the software subject to the license 107760SGiacomo.Gabrielli@arm.com * terms below provided that you ensure that this notice is replicated 117760SGiacomo.Gabrielli@arm.com * unmodified and in its entirety in all distributions of the software, 127760SGiacomo.Gabrielli@arm.com * modified or unmodified, in source code or in binary form. 134486Sbinkertn@umich.edu * 144486Sbinkertn@umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 154486Sbinkertn@umich.edu * All rights reserved. 164486Sbinkertn@umich.edu * 174486Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 184486Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 194486Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 204486Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 214486Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 224486Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 234486Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 244486Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 254486Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 264486Sbinkertn@umich.edu * this software without specific prior written permission. 274486Sbinkertn@umich.edu * 284486Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 294486Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 304486Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 314486Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 324486Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 334486Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 344486Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 354486Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 364486Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 374486Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 384486Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394486Sbinkertn@umich.edu * 404486Sbinkertn@umich.edu * Authors: Steve Reinhardt 413102SN/A */ 423102SN/A 432736SN/A#ifndef __CPU_SIMPLE_TIMING_HH__ 444556Sbinkertn@umich.edu#define __CPU_SIMPLE_TIMING_HH__ 454556Sbinkertn@umich.edu 4611683Sfernando.endo2@gmail.com#include "cpu/simple/base.hh" 4711683Sfernando.endo2@gmail.com#include "cpu/translation.hh" 487760SGiacomo.Gabrielli@arm.com#include "params/TimingSimpleCPU.hh" 497760SGiacomo.Gabrielli@arm.com 5013759Sgiacomo.gabrielli@arm.comclass TimingSimpleCPU : public BaseSimpleCPU 5113759Sgiacomo.gabrielli@arm.com{ 5213759Sgiacomo.gabrielli@arm.com public: 5313759Sgiacomo.gabrielli@arm.com 5413759Sgiacomo.gabrielli@arm.com TimingSimpleCPU(TimingSimpleCPUParams * params); 5513169Smatt.horsnell@arm.com virtual ~TimingSimpleCPU(); 5613169Smatt.horsnell@arm.com 5713759Sgiacomo.gabrielli@arm.com virtual void init(); 5813759Sgiacomo.gabrielli@arm.com 5913759Sgiacomo.gabrielli@arm.com private: 6011683Sfernando.endo2@gmail.com 612736SN/A /* 622736SN/A * If an access needs to be broken into fragments, currently at most two, 632736SN/A * the the following two classes are used as the sender state of the 649338SAndreas.Sandberg@arm.com * packets so the CPU can keep track of everything. In the main packet 654556Sbinkertn@umich.edu * sender state, there's an array with a spot for each fragment. If a 669184Sandreas.hansson@arm.com * fragment has already been accepted by the CPU, aka isn't waiting for 6710807Snilay@cs.wisc.edu * a retry, it's pointer is NULL. After each fragment has successfully 6810807Snilay@cs.wisc.edu * been processed, the "outstanding" counter is decremented. Once the 692736SN/A * count is zero, the entire larger access is complete. 702736SN/A */ 712736SN/A class SplitMainSenderState : public Packet::SenderState 729338SAndreas.Sandberg@arm.com { 732736SN/A public: 742736SN/A int outstanding; 75 PacketPtr fragments[2]; 76 77 int 78 getPendingFragment() 79 { 80 if (fragments[0]) { 81 return 0; 82 } else if (fragments[1]) { 83 return 1; 84 } else { 85 return -1; 86 } 87 } 88 }; 89 90 class SplitFragmentSenderState : public Packet::SenderState 91 { 92 public: 93 SplitFragmentSenderState(PacketPtr _bigPkt, int _index) : 94 bigPkt(_bigPkt), index(_index) 95 {} 96 PacketPtr bigPkt; 97 int index; 98 99 void 100 clearFromParent() 101 { 102 SplitMainSenderState * main_send_state = 103 dynamic_cast<SplitMainSenderState *>(bigPkt->senderState); 104 main_send_state->fragments[index] = NULL; 105 } 106 }; 107 108 class FetchTranslation : public BaseTLB::Translation 109 { 110 protected: 111 TimingSimpleCPU *cpu; 112 113 public: 114 FetchTranslation(TimingSimpleCPU *_cpu) 115 : cpu(_cpu) 116 {} 117 118 void 119 markDelayed() 120 { 121 assert(cpu->_status == BaseSimpleCPU::Running); 122 cpu->_status = ITBWaitResponse; 123 } 124 125 void 126 finish(Fault fault, RequestPtr req, ThreadContext *tc, 127 BaseTLB::Mode mode) 128 { 129 cpu->sendFetch(fault, req, tc); 130 } 131 }; 132 FetchTranslation fetchTranslation; 133 134 void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read); 135 void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req, 136 uint8_t *data, bool read); 137 138 void translationFault(Fault fault); 139 140 void buildPacket(PacketPtr &pkt, RequestPtr req, bool read); 141 void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 142 RequestPtr req1, RequestPtr req2, RequestPtr req, 143 uint8_t *data, bool read); 144 145 bool handleReadPacket(PacketPtr pkt); 146 // This function always implicitly uses dcache_pkt. 147 bool handleWritePacket(); 148 149 /** 150 * A TimingCPUPort overrides the default behaviour of the 151 * recvTiming and recvRetry and implements events for the 152 * scheduling of handling of incoming packets in the following 153 * cycle. 154 */ 155 class TimingCPUPort : public CpuPort 156 { 157 public: 158 159 TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) 160 : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this) 161 { } 162 163 protected: 164 165 /** 166 * Snooping a coherence request, do nothing. 167 */ 168 virtual void recvTimingSnoopReq(PacketPtr pkt) { } 169 170 TimingSimpleCPU* cpu; 171 172 struct TickEvent : public Event 173 { 174 PacketPtr pkt; 175 TimingSimpleCPU *cpu; 176 177 TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {} 178 const char *description() const { return "Timing CPU tick"; } 179 void schedule(PacketPtr _pkt, Tick t); 180 }; 181 182 EventWrapper<MasterPort, &MasterPort::sendRetry> retryEvent; 183 }; 184 185 class IcachePort : public TimingCPUPort 186 { 187 public: 188 189 IcachePort(TimingSimpleCPU *_cpu) 190 : TimingCPUPort(_cpu->name() + ".icache_port", _cpu), 191 tickEvent(_cpu) 192 { } 193 194 protected: 195 196 virtual bool recvTimingResp(PacketPtr pkt); 197 198 virtual void recvRetry(); 199 200 struct ITickEvent : public TickEvent 201 { 202 203 ITickEvent(TimingSimpleCPU *_cpu) 204 : TickEvent(_cpu) {} 205 void process(); 206 const char *description() const { return "Timing CPU icache tick"; } 207 }; 208 209 ITickEvent tickEvent; 210 211 }; 212 213 class DcachePort : public TimingCPUPort 214 { 215 public: 216 217 DcachePort(TimingSimpleCPU *_cpu) 218 : TimingCPUPort(_cpu->name() + ".dcache_port", _cpu), 219 tickEvent(_cpu) 220 { } 221 222 protected: 223 224 virtual bool recvTimingResp(PacketPtr pkt); 225 226 virtual void recvRetry(); 227 228 struct DTickEvent : public TickEvent 229 { 230 DTickEvent(TimingSimpleCPU *_cpu) 231 : TickEvent(_cpu) {} 232 void process(); 233 const char *description() const { return "Timing CPU dcache tick"; } 234 }; 235 236 DTickEvent tickEvent; 237 238 }; 239 240 IcachePort icachePort; 241 DcachePort dcachePort; 242 243 PacketPtr ifetch_pkt; 244 PacketPtr dcache_pkt; 245 246 Tick previousCycle; 247 248 protected: 249 250 /** Return a reference to the data port. */ 251 virtual CpuPort &getDataPort() { return dcachePort; } 252 253 /** Return a reference to the instruction port. */ 254 virtual CpuPort &getInstPort() { return icachePort; } 255 256 public: 257 258 unsigned int drain(DrainManager *drain_manager); 259 void drainResume(); 260 261 void switchOut(); 262 void takeOverFrom(BaseCPU *oldCPU); 263 264 void verifyMemoryMode() const; 265 266 virtual void activateContext(ThreadID thread_num, Cycles delay); 267 virtual void suspendContext(ThreadID thread_num); 268 269 Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); 270 271 Fault writeMem(uint8_t *data, unsigned size, 272 Addr addr, unsigned flags, uint64_t *res); 273 274 void fetch(); 275 void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc); 276 void completeIfetch(PacketPtr ); 277 void completeDataAccess(PacketPtr pkt); 278 void advanceInst(Fault fault); 279 280 /** This function is used by the page table walker to determine if it could 281 * translate the a pending request or if the underlying request has been 282 * squashed. This always returns false for the simple timing CPU as it never 283 * executes any instructions speculatively. 284 * @ return Is the current instruction squashed? 285 */ 286 bool isSquashed() const { return false; } 287 288 /** 289 * Print state of address in memory system via PrintReq (for 290 * debugging). 291 */ 292 void printAddr(Addr a); 293 294 /** 295 * Finish a DTB translation. 296 * @param state The DTB translation state. 297 */ 298 void finishTranslation(WholeTranslationState *state); 299 300 private: 301 302 typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent; 303 FetchEvent fetchEvent; 304 305 struct IprEvent : Event { 306 Packet *pkt; 307 TimingSimpleCPU *cpu; 308 IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t); 309 virtual void process(); 310 virtual const char *description() const; 311 }; 312 313 /** 314 * Check if a system is in a drained state. 315 * 316 * We need to drain if: 317 * <ul> 318 * <li>We are in the middle of a microcode sequence as some CPUs 319 * (e.g., HW accelerated CPUs) can't be started in the middle 320 * of a gem5 microcode sequence. 321 * 322 * <li>Stay at PC is true. 323 * </ul> 324 */ 325 bool isDrained() { 326 return microPC() == 0 && 327 !stayAtPC; 328 } 329 330 /** 331 * Try to complete a drain request. 332 * 333 * @returns true if the CPU is drained, false otherwise. 334 */ 335 bool tryCompleteDrain(); 336 337 /** 338 * Drain manager to use when signaling drain completion 339 * 340 * This pointer is non-NULL when draining and NULL otherwise. 341 */ 342 DrainManager *drainManager; 343}; 344 345#endif // __CPU_SIMPLE_TIMING_HH__ 346