timing.hh revision 10407:a9023811bf9e
12348SN/A/* 22348SN/A * Copyright (c) 2012-2013 ARM Limited 32348SN/A * All rights reserved 42348SN/A * 52348SN/A * The license below extends only to copyright in the software and shall 62348SN/A * not be construed as granting a license to any other intellectual 72348SN/A * property including but not limited to intellectual property relating 82348SN/A * to a hardware implementation of the functionality of the software 92348SN/A * licensed hereunder. You may use the software subject to the license 102348SN/A * terms below provided that you ensure that this notice is replicated 112348SN/A * unmodified and in its entirety in all distributions of the software, 122348SN/A * modified or unmodified, in source code or in binary form. 132348SN/A * 142348SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 152348SN/A * All rights reserved. 162348SN/A * 172348SN/A * Redistribution and use in source and binary forms, with or without 182348SN/A * modification, are permitted provided that the following conditions are 192348SN/A * met: redistributions of source code must retain the above copyright 202348SN/A * notice, this list of conditions and the following disclaimer; 212348SN/A * redistributions in binary form must reproduce the above copyright 222348SN/A * notice, this list of conditions and the following disclaimer in the 232348SN/A * documentation and/or other materials provided with the distribution; 242348SN/A * neither the name of the copyright holders nor the names of its 252348SN/A * contributors may be used to endorse or promote products derived from 262348SN/A * this software without specific prior written permission. 272689Sktlim@umich.edu * 282689Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292348SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302325SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 315804Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323918Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332325SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342325SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352325SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 365804Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 375804Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 385804Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 395804Snate@binkert.org * 405804Snate@binkert.org * Authors: Steve Reinhardt 415804Snate@binkert.org */ 425804Snate@binkert.org 432325SN/A#ifndef __CPU_SIMPLE_TIMING_HH__ 442325SN/A#define __CPU_SIMPLE_TIMING_HH__ 453918Ssaidi@eecs.umich.edu 462325SN/A#include "cpu/simple/base.hh" 472325SN/A#include "cpu/translation.hh" 482325SN/A#include "params/TimingSimpleCPU.hh" 492325SN/A 502325SN/Aclass TimingSimpleCPU : public BaseSimpleCPU 512348SN/A{ 522348SN/A public: 532325SN/A 542325SN/A TimingSimpleCPU(TimingSimpleCPUParams * params); 552325SN/A virtual ~TimingSimpleCPU(); 562325SN/A 572325SN/A virtual void init(); 582325SN/A 592325SN/A private: 602325SN/A 612325SN/A /* 622325SN/A * If an access needs to be broken into fragments, currently at most two, 632325SN/A * the the following two classes are used as the sender state of the 642325SN/A * packets so the CPU can keep track of everything. In the main packet 652325SN/A * sender state, there's an array with a spot for each fragment. If a 662325SN/A * fragment has already been accepted by the CPU, aka isn't waiting for 672348SN/A * a retry, it's pointer is NULL. After each fragment has successfully 682348SN/A * been processed, the "outstanding" counter is decremented. Once the 692325SN/A * count is zero, the entire larger access is complete. 702325SN/A */ 712325SN/A class SplitMainSenderState : public Packet::SenderState 722325SN/A { 732325SN/A public: 742325SN/A int outstanding; 752325SN/A PacketPtr fragments[2]; 762325SN/A 772325SN/A int 782325SN/A getPendingFragment() 792325SN/A { 802325SN/A if (fragments[0]) { 812325SN/A return 0; 822325SN/A } else if (fragments[1]) { 832325SN/A return 1; 842325SN/A } else { 852325SN/A return -1; 862325SN/A } 872348SN/A } 882325SN/A }; 892325SN/A 902325SN/A class SplitFragmentSenderState : public Packet::SenderState 912325SN/A { 922325SN/A public: 932325SN/A SplitFragmentSenderState(PacketPtr _bigPkt, int _index) : 942325SN/A bigPkt(_bigPkt), index(_index) 952325SN/A {} 962325SN/A PacketPtr bigPkt; 972325SN/A int index; 982325SN/A 992325SN/A void 1002325SN/A clearFromParent() 1012325SN/A { 1022325SN/A SplitMainSenderState * main_send_state = 1032325SN/A dynamic_cast<SplitMainSenderState *>(bigPkt->senderState); 1042348SN/A main_send_state->fragments[index] = NULL; 1052325SN/A } 1062325SN/A }; 1072325SN/A 1082325SN/A class FetchTranslation : public BaseTLB::Translation 1092325SN/A { 1102325SN/A protected: 1112325SN/A TimingSimpleCPU *cpu; 1122325SN/A 1132325SN/A public: 1142325SN/A FetchTranslation(TimingSimpleCPU *_cpu) 1152325SN/A : cpu(_cpu) 1162325SN/A {} 1172325SN/A 1182325SN/A void 1192325SN/A markDelayed() 1202325SN/A { 1212325SN/A assert(cpu->_status == BaseSimpleCPU::Running); 1223918Ssaidi@eecs.umich.edu cpu->_status = ITBWaitResponse; 1232325SN/A } 1242325SN/A 1252325SN/A void 1262325SN/A finish(const Fault &fault, RequestPtr req, ThreadContext *tc, 1272325SN/A BaseTLB::Mode mode) 1282325SN/A { 1292325SN/A cpu->sendFetch(fault, req, tc); 1302325SN/A } 1312325SN/A }; 1322325SN/A FetchTranslation fetchTranslation; 1332325SN/A 1342325SN/A void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read); 1352325SN/A void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req, 1362325SN/A uint8_t *data, bool read); 1372325SN/A 1382325SN/A void translationFault(const Fault &fault); 1392325SN/A 1402325SN/A void buildPacket(PacketPtr &pkt, RequestPtr req, bool read); 1412325SN/A void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, 1422325SN/A RequestPtr req1, RequestPtr req2, RequestPtr req, 1432325SN/A uint8_t *data, bool read); 1442325SN/A 1452325SN/A bool handleReadPacket(PacketPtr pkt); 1462325SN/A // This function always implicitly uses dcache_pkt. 1472325SN/A bool handleWritePacket(); 1482325SN/A 1492325SN/A /** 1502325SN/A * A TimingCPUPort overrides the default behaviour of the 1512325SN/A * recvTiming and recvRetry and implements events for the 1522325SN/A * scheduling of handling of incoming packets in the following 1532325SN/A * cycle. 1542325SN/A */ 1552325SN/A class TimingCPUPort : public MasterPort 1562325SN/A { 1572325SN/A public: 1582325SN/A 1592325SN/A TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) 1602325SN/A : MasterPort(_name, _cpu), cpu(_cpu), retryEvent(this) 1612325SN/A { } 1622325SN/A 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 cacheBlockMask = ~(cpu->cacheLineSize() - 1); 222 } 223 224 Addr cacheBlockMask; 225 protected: 226 227 /** Snoop a coherence request, we need to check if this causes 228 * a wakeup event on a cpu that is monitoring an address 229 */ 230 virtual void recvTimingSnoopReq(PacketPtr pkt); 231 232 virtual bool recvTimingResp(PacketPtr pkt); 233 234 virtual void recvRetry(); 235 236 struct DTickEvent : public TickEvent 237 { 238 DTickEvent(TimingSimpleCPU *_cpu) 239 : TickEvent(_cpu) {} 240 void process(); 241 const char *description() const { return "Timing CPU dcache tick"; } 242 }; 243 244 DTickEvent tickEvent; 245 246 }; 247 248 IcachePort icachePort; 249 DcachePort dcachePort; 250 251 PacketPtr ifetch_pkt; 252 PacketPtr dcache_pkt; 253 254 Tick previousCycle; 255 256 protected: 257 258 /** Return a reference to the data port. */ 259 virtual MasterPort &getDataPort() { return dcachePort; } 260 261 /** Return a reference to the instruction port. */ 262 virtual MasterPort &getInstPort() { return icachePort; } 263 264 public: 265 266 unsigned int drain(DrainManager *drain_manager); 267 void drainResume(); 268 269 void switchOut(); 270 void takeOverFrom(BaseCPU *oldCPU); 271 272 void verifyMemoryMode() const; 273 274 virtual void activateContext(ThreadID thread_num); 275 virtual void suspendContext(ThreadID thread_num); 276 277 Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); 278 279 Fault writeMem(uint8_t *data, unsigned size, 280 Addr addr, unsigned flags, uint64_t *res); 281 282 void fetch(); 283 void sendFetch(const Fault &fault, RequestPtr req, ThreadContext *tc); 284 void completeIfetch(PacketPtr ); 285 void completeDataAccess(PacketPtr pkt); 286 void advanceInst(const Fault &fault); 287 288 /** This function is used by the page table walker to determine if it could 289 * translate the a pending request or if the underlying request has been 290 * squashed. This always returns false for the simple timing CPU as it never 291 * executes any instructions speculatively. 292 * @ return Is the current instruction squashed? 293 */ 294 bool isSquashed() const { return false; } 295 296 /** 297 * Print state of address in memory system via PrintReq (for 298 * debugging). 299 */ 300 void printAddr(Addr a); 301 302 /** 303 * Finish a DTB translation. 304 * @param state The DTB translation state. 305 */ 306 void finishTranslation(WholeTranslationState *state); 307 308 private: 309 310 typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent; 311 FetchEvent fetchEvent; 312 313 struct IprEvent : Event { 314 Packet *pkt; 315 TimingSimpleCPU *cpu; 316 IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t); 317 virtual void process(); 318 virtual const char *description() const; 319 }; 320 321 /** 322 * Check if a system is in a drained state. 323 * 324 * We need to drain if: 325 * <ul> 326 * <li>We are in the middle of a microcode sequence as some CPUs 327 * (e.g., HW accelerated CPUs) can't be started in the middle 328 * of a gem5 microcode sequence. 329 * 330 * <li>Stay at PC is true. 331 * 332 * <li>A fetch event is scheduled. Normally this would never be the 333 * case with microPC() == 0, but right after a context is 334 * activated it can happen. 335 * </ul> 336 */ 337 bool isDrained() { 338 return microPC() == 0 && !stayAtPC && !fetchEvent.scheduled(); 339 } 340 341 /** 342 * Try to complete a drain request. 343 * 344 * @returns true if the CPU is drained, false otherwise. 345 */ 346 bool tryCompleteDrain(); 347 348 /** 349 * Drain manager to use when signaling drain completion 350 * 351 * This pointer is non-NULL when draining and NULL otherwise. 352 */ 353 DrainManager *drainManager; 354}; 355 356#endif // __CPU_SIMPLE_TIMING_HH__ 357