1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 40 unchanged lines hidden (view full) --- 49#include "cpu/exetrace.hh" 50#include "debug/Config.hh" 51#include "debug/ExecFaulting.hh" 52#include "debug/SimpleCPU.hh" 53#include "mem/packet.hh" 54#include "mem/packet_access.hh" 55#include "params/TimingSimpleCPU.hh" 56#include "sim/faults.hh" |
57#include "sim/full_system.hh" |
58#include "sim/system.hh" 59 60using namespace std; 61using namespace TheISA; 62 63Port * 64TimingSimpleCPU::getPort(const std::string &if_name, int idx) 65{ --- 4 unchanged lines hidden (view full) --- 70 else 71 panic("No Such Port\n"); 72} 73 74void 75TimingSimpleCPU::init() 76{ 77 BaseCPU::init(); |
78 if (FullSystem) { 79 for (int i = 0; i < threadContexts.size(); ++i) { |
80#if FULL_SYSTEM |
81 ThreadContext *tc = threadContexts[i]; 82 // initialize CPU, including PC 83 TheISA::initCPU(tc, _cpuId); 84#endif 85 } 86 } 87} |
88 |
89Tick 90TimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) 91{ 92 panic("TimingSimpleCPU doesn't expect recvAtomic callback!"); 93 return curTick(); 94} 95 96void 97TimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) 98{ 99 //No internal storage to update, jusst return 100 return; 101} 102 103void 104TimingSimpleCPU::CpuPort::recvStatusChange(Status status) 105{ 106 if (status == RangeChange) { 107 if (!snoopRangeSent) { 108 snoopRangeSent = true; 109 sendStatusChange(Port::RangeChange); 110 } 111 return; |
112 } 113 |
114 panic("TimingSimpleCPU doesn't expect recvStatusChange callback!"); |
115} 116 |
117 |
118void |
119TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) |
120{ 121 pkt = _pkt; 122 cpu->schedule(this, t); 123} 124 125TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) |
126 : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock), 127 dcachePort(this, p->clock), fetchEvent(this) |
128{ 129 _status = Idle; 130 |
131 icachePort.snoopRangeSent = false; 132 dcachePort.snoopRangeSent = false; 133 |
134 ifetch_pkt = dcache_pkt = NULL; 135 drainEvent = NULL; 136 previousTick = 0; 137 changeState(SimObject::Running); 138 system->totalNumInsts = 0; 139} 140 141 --- 60 unchanged lines hidden (view full) --- 202 if (fetchEvent.scheduled()) 203 deschedule(fetchEvent); 204} 205 206 207void 208TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 209{ |
210 BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); |
211 212 // if any of this CPU's ThreadContexts are active, mark the CPU as 213 // running and schedule its tick event. 214 for (int i = 0; i < threadContexts.size(); ++i) { 215 ThreadContext *tc = threadContexts[i]; 216 if (tc->status() == ThreadContext::Active && _status != Running) { 217 _status = Running; 218 break; --- 4 unchanged lines hidden (view full) --- 223 _status = Idle; 224 } 225 assert(threadContexts.size() == 1); 226 previousTick = curTick(); 227} 228 229 230void |
231TimingSimpleCPU::activateContext(int thread_num, int delay) |
232{ 233 DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay); 234 235 assert(thread_num == 0); 236 assert(thread); 237 238 assert(_status == Idle); 239 240 notIdleFraction++; 241 _status = Running; 242 243 // kick things off by initiating the fetch of the next instruction 244 schedule(fetchEvent, nextCycle(curTick() + ticks(delay))); 245} 246 247 248void |
249TimingSimpleCPU::suspendContext(int thread_num) |
250{ 251 DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num); 252 253 assert(thread_num == 0); 254 assert(thread); 255 256 if (_status == Idle) 257 return; --- 613 unchanged lines hidden (view full) --- 871void 872TimingSimpleCPU::completeDrain() 873{ 874 DPRINTF(Config, "Done draining\n"); 875 changeState(SimObject::Drained); 876 drainEvent->process(); 877} 878 |
879void 880TimingSimpleCPU::DcachePort::setPeer(Port *port) 881{ 882 Port::setPeer(port); 883 884 if (FullSystem) { 885 // Update the ThreadContext's memory ports (Functional/Virtual 886 // Ports) 887 cpu->tcBase()->connectMemPorts(cpu->tcBase()); 888 } 889} 890 |
891bool 892TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) 893{ 894 if (pkt->isResponse() && !pkt->wasNacked()) { 895 // delay processing of returned data until next CPU clock edge 896 Tick next_tick = cpu->nextCycle(curTick()); 897 898 if (next_tick == curTick()) { 899 cpu->completeDataAccess(pkt); 900 } else { 901 if (!tickEvent.scheduled()) { 902 tickEvent.schedule(pkt, next_tick); 903 } else { 904 // In the case of a split transaction and a cache that is 905 // faster than a CPU we could get two responses before 906 // next_tick expires 907 if (!retryEvent.scheduled()) |
908 schedule(retryEvent, next_tick); |
909 return false; 910 } 911 } 912 913 return true; 914 } 915 else if (pkt->wasNacked()) { 916 assert(cpu->_status == DcacheWaitResponse); --- 88 unchanged lines hidden (view full) --- 1005// 1006// TimingSimpleCPU Simulation Object 1007// 1008TimingSimpleCPU * 1009TimingSimpleCPUParams::create() 1010{ 1011 numThreads = 1; 1012#if !FULL_SYSTEM |
1013 if (!FullSystem && workload.size() != 1) |
1014 panic("only one workload allowed"); 1015#endif 1016 return new TimingSimpleCPU(this); 1017} |