timing.cc (8737:770ccf3af571) timing.cc (8779:2a590c51adb1)
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"
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"
57#include "sim/system.hh"
58
59using namespace std;
60using namespace TheISA;
61
62Port *
63TimingSimpleCPU::getPort(const std::string &if_name, int idx)
64{

--- 4 unchanged lines hidden (view full) ---

69 else
70 panic("No Such Port\n");
71}
72
73void
74TimingSimpleCPU::init()
75{
76 BaseCPU::init();
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) {
77#if FULL_SYSTEM
80#if FULL_SYSTEM
78 for (int i = 0; i < threadContexts.size(); ++i) {
79 ThreadContext *tc = threadContexts[i];
81 ThreadContext *tc = threadContexts[i];
82 // initialize CPU, including PC
83 TheISA::initCPU(tc, _cpuId);
84#endif
85 }
86 }
87}
80
88
81 // initialize CPU, including PC
82 TheISA::initCPU(tc, _cpuId);
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;
83 }
84
112 }
113
85 // Initialise the ThreadContext's memory proxies
86 tcBase()->initMemProxies(tcBase());
87#endif
114 panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
88}
89
115}
116
117
90void
118void
91TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
119TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
92{
93 pkt = _pkt;
94 cpu->schedule(this, t);
95}
96
97TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
120{
121 pkt = _pkt;
122 cpu->schedule(this, t);
123}
124
125TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
98 : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
99 dcachePort(this), fetchEvent(this)
126 : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock),
127 dcachePort(this, p->clock), fetchEvent(this)
100{
101 _status = Idle;
102
128{
129 _status = Idle;
130
131 icachePort.snoopRangeSent = false;
132 dcachePort.snoopRangeSent = false;
133
103 ifetch_pkt = dcache_pkt = NULL;
104 drainEvent = NULL;
105 previousTick = 0;
106 changeState(SimObject::Running);
107 system->totalNumInsts = 0;
108}
109
110

--- 60 unchanged lines hidden (view full) ---

171 if (fetchEvent.scheduled())
172 deschedule(fetchEvent);
173}
174
175
176void
177TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
178{
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{
179 BaseCPU::takeOverFrom(oldCPU);
210 BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
180
181 // if any of this CPU's ThreadContexts are active, mark the CPU as
182 // running and schedule its tick event.
183 for (int i = 0; i < threadContexts.size(); ++i) {
184 ThreadContext *tc = threadContexts[i];
185 if (tc->status() == ThreadContext::Active && _status != Running) {
186 _status = Running;
187 break;

--- 4 unchanged lines hidden (view full) ---

192 _status = Idle;
193 }
194 assert(threadContexts.size() == 1);
195 previousTick = curTick();
196}
197
198
199void
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
200TimingSimpleCPU::activateContext(ThreadID thread_num, int delay)
231TimingSimpleCPU::activateContext(int thread_num, int delay)
201{
202 DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay);
203
204 assert(thread_num == 0);
205 assert(thread);
206
207 assert(_status == Idle);
208
209 notIdleFraction++;
210 _status = Running;
211
212 // kick things off by initiating the fetch of the next instruction
213 schedule(fetchEvent, nextCycle(curTick() + ticks(delay)));
214}
215
216
217void
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
218TimingSimpleCPU::suspendContext(ThreadID thread_num)
249TimingSimpleCPU::suspendContext(int thread_num)
219{
220 DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
221
222 assert(thread_num == 0);
223 assert(thread);
224
225 if (_status == Idle)
226 return;

--- 613 unchanged lines hidden (view full) ---

840void
841TimingSimpleCPU::completeDrain()
842{
843 DPRINTF(Config, "Done draining\n");
844 changeState(SimObject::Drained);
845 drainEvent->process();
846}
847
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
848bool
849TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt)
850{
851 if (pkt->isResponse() && !pkt->wasNacked()) {
852 // delay processing of returned data until next CPU clock edge
853 Tick next_tick = cpu->nextCycle(curTick());
854
855 if (next_tick == curTick()) {
856 cpu->completeDataAccess(pkt);
857 } else {
858 if (!tickEvent.scheduled()) {
859 tickEvent.schedule(pkt, next_tick);
860 } else {
861 // In the case of a split transaction and a cache that is
862 // faster than a CPU we could get two responses before
863 // next_tick expires
864 if (!retryEvent.scheduled())
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())
865 cpu->schedule(retryEvent, next_tick);
908 schedule(retryEvent, next_tick);
866 return false;
867 }
868 }
869
870 return true;
871 }
872 else if (pkt->wasNacked()) {
873 assert(cpu->_status == DcacheWaitResponse);

--- 88 unchanged lines hidden (view full) ---

962//
963// TimingSimpleCPU Simulation Object
964//
965TimingSimpleCPU *
966TimingSimpleCPUParams::create()
967{
968 numThreads = 1;
969#if !FULL_SYSTEM
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
970 if (workload.size() != 1)
1013 if (!FullSystem && workload.size() != 1)
971 panic("only one workload allowed");
972#endif
973 return new TimingSimpleCPU(this);
974}
1014 panic("only one workload allowed");
1015#endif
1016 return new TimingSimpleCPU(this);
1017}