timing.hh (7944:1daf51f62013) timing.hh (7945:32758425de8c)
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 */
30
31#ifndef __CPU_SIMPLE_TIMING_HH__
32#define __CPU_SIMPLE_TIMING_HH__
33
34#include "cpu/simple/base.hh"
35#include "cpu/translation.hh"
36
37#include "params/TimingSimpleCPU.hh"
38
39class TimingSimpleCPU : public BaseSimpleCPU
40{
41 public:
42
43 TimingSimpleCPU(TimingSimpleCPUParams * params);
44 virtual ~TimingSimpleCPU();
45
46 virtual void init();
47
48 public:
49 Event *drainEvent;
50
51 private:
52
53 /*
54 * If an access needs to be broken into fragments, currently at most two,
55 * the the following two classes are used as the sender state of the
56 * packets so the CPU can keep track of everything. In the main packet
57 * sender state, there's an array with a spot for each fragment. If a
58 * fragment has already been accepted by the CPU, aka isn't waiting for
59 * a retry, it's pointer is NULL. After each fragment has successfully
60 * been processed, the "outstanding" counter is decremented. Once the
61 * count is zero, the entire larger access is complete.
62 */
63 class SplitMainSenderState : public Packet::SenderState
64 {
65 public:
66 int outstanding;
67 PacketPtr fragments[2];
68
69 int
70 getPendingFragment()
71 {
72 if (fragments[0]) {
73 return 0;
74 } else if (fragments[1]) {
75 return 1;
76 } else {
77 return -1;
78 }
79 }
80 };
81
82 class SplitFragmentSenderState : public Packet::SenderState
83 {
84 public:
85 SplitFragmentSenderState(PacketPtr _bigPkt, int _index) :
86 bigPkt(_bigPkt), index(_index)
87 {}
88 PacketPtr bigPkt;
89 int index;
90
91 void
92 clearFromParent()
93 {
94 SplitMainSenderState * main_send_state =
95 dynamic_cast<SplitMainSenderState *>(bigPkt->senderState);
96 main_send_state->fragments[index] = NULL;
97 }
98 };
99
100 class FetchTranslation : public BaseTLB::Translation
101 {
102 protected:
103 TimingSimpleCPU *cpu;
104
105 public:
106 FetchTranslation(TimingSimpleCPU *_cpu)
107 : cpu(_cpu)
108 {}
109
110 void
111 markDelayed()
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 */
30
31#ifndef __CPU_SIMPLE_TIMING_HH__
32#define __CPU_SIMPLE_TIMING_HH__
33
34#include "cpu/simple/base.hh"
35#include "cpu/translation.hh"
36
37#include "params/TimingSimpleCPU.hh"
38
39class TimingSimpleCPU : public BaseSimpleCPU
40{
41 public:
42
43 TimingSimpleCPU(TimingSimpleCPUParams * params);
44 virtual ~TimingSimpleCPU();
45
46 virtual void init();
47
48 public:
49 Event *drainEvent;
50
51 private:
52
53 /*
54 * If an access needs to be broken into fragments, currently at most two,
55 * the the following two classes are used as the sender state of the
56 * packets so the CPU can keep track of everything. In the main packet
57 * sender state, there's an array with a spot for each fragment. If a
58 * fragment has already been accepted by the CPU, aka isn't waiting for
59 * a retry, it's pointer is NULL. After each fragment has successfully
60 * been processed, the "outstanding" counter is decremented. Once the
61 * count is zero, the entire larger access is complete.
62 */
63 class SplitMainSenderState : public Packet::SenderState
64 {
65 public:
66 int outstanding;
67 PacketPtr fragments[2];
68
69 int
70 getPendingFragment()
71 {
72 if (fragments[0]) {
73 return 0;
74 } else if (fragments[1]) {
75 return 1;
76 } else {
77 return -1;
78 }
79 }
80 };
81
82 class SplitFragmentSenderState : public Packet::SenderState
83 {
84 public:
85 SplitFragmentSenderState(PacketPtr _bigPkt, int _index) :
86 bigPkt(_bigPkt), index(_index)
87 {}
88 PacketPtr bigPkt;
89 int index;
90
91 void
92 clearFromParent()
93 {
94 SplitMainSenderState * main_send_state =
95 dynamic_cast<SplitMainSenderState *>(bigPkt->senderState);
96 main_send_state->fragments[index] = NULL;
97 }
98 };
99
100 class FetchTranslation : public BaseTLB::Translation
101 {
102 protected:
103 TimingSimpleCPU *cpu;
104
105 public:
106 FetchTranslation(TimingSimpleCPU *_cpu)
107 : cpu(_cpu)
108 {}
109
110 void
111 markDelayed()
112 {}
112 {
113 assert(cpu->_status == Running);
114 cpu->_status = ITBWaitResponse;
115 }
113
114 void
115 finish(Fault fault, RequestPtr req, ThreadContext *tc,
116 BaseTLB::Mode mode)
117 {
118 cpu->sendFetch(fault, req, tc);
119 }
120 };
121 FetchTranslation fetchTranslation;
122
123 void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read);
124 void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req,
125 uint8_t *data, bool read);
126
127 void translationFault(Fault fault);
128
129 void buildPacket(PacketPtr &pkt, RequestPtr req, bool read);
130 void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
131 RequestPtr req1, RequestPtr req2, RequestPtr req,
132 uint8_t *data, bool read);
133
134 bool handleReadPacket(PacketPtr pkt);
135 // This function always implicitly uses dcache_pkt.
136 bool handleWritePacket();
137
138 class CpuPort : public Port
139 {
140 protected:
141 TimingSimpleCPU *cpu;
142 Tick lat;
143
144 public:
145
146 CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat)
147 : Port(_name, _cpu), cpu(_cpu), lat(_lat), retryEvent(this)
148 { }
149
150 bool snoopRangeSent;
151
152 protected:
153
154 virtual Tick recvAtomic(PacketPtr pkt);
155
156 virtual void recvFunctional(PacketPtr pkt);
157
158 virtual void recvStatusChange(Status status);
159
160 virtual void getDeviceAddressRanges(AddrRangeList &resp,
161 bool &snoop)
162 { resp.clear(); snoop = false; }
163
164 struct TickEvent : public Event
165 {
166 PacketPtr pkt;
167 TimingSimpleCPU *cpu;
168 CpuPort *port;
169
170 TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {}
171 const char *description() const { return "Timing CPU tick"; }
172 void schedule(PacketPtr _pkt, Tick t);
173 };
174
175 EventWrapper<Port, &Port::sendRetry> retryEvent;
176 };
177
178 class IcachePort : public CpuPort
179 {
180 public:
181
182 IcachePort(TimingSimpleCPU *_cpu, Tick _lat)
183 : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu)
184 { }
185
186 protected:
187
188 virtual bool recvTiming(PacketPtr pkt);
189
190 virtual void recvRetry();
191
192 struct ITickEvent : public TickEvent
193 {
194
195 ITickEvent(TimingSimpleCPU *_cpu)
196 : TickEvent(_cpu) {}
197 void process();
198 const char *description() const { return "Timing CPU icache tick"; }
199 };
200
201 ITickEvent tickEvent;
202
203 };
204
205 class DcachePort : public CpuPort
206 {
207 public:
208
209 DcachePort(TimingSimpleCPU *_cpu, Tick _lat)
210 : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu)
211 { }
212
213 virtual void setPeer(Port *port);
214
215 protected:
216
217 virtual bool recvTiming(PacketPtr pkt);
218
219 virtual void recvRetry();
220
221 struct DTickEvent : public TickEvent
222 {
223 DTickEvent(TimingSimpleCPU *_cpu)
224 : TickEvent(_cpu) {}
225 void process();
226 const char *description() const { return "Timing CPU dcache tick"; }
227 };
228
229 DTickEvent tickEvent;
230
231 };
232
233 IcachePort icachePort;
234 DcachePort dcachePort;
235
236 PacketPtr ifetch_pkt;
237 PacketPtr dcache_pkt;
238
239 Tick previousTick;
240
241 public:
242
243 virtual Port *getPort(const std::string &if_name, int idx = -1);
244
245 virtual void serialize(std::ostream &os);
246 virtual void unserialize(Checkpoint *cp, const std::string &section);
247
248 virtual unsigned int drain(Event *drain_event);
249 virtual void resume();
250
251 void switchOut();
252 void takeOverFrom(BaseCPU *oldCPU);
253
254 virtual void activateContext(int thread_num, int delay);
255 virtual void suspendContext(int thread_num);
256
257 template <class T>
258 Fault read(Addr addr, T &data, unsigned flags);
259
260 Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
261
262 template <class T>
263 Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
264
265 Fault writeBytes(uint8_t *data, unsigned size,
266 Addr addr, unsigned flags, uint64_t *res);
267
268 void fetch();
269 void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
270 void completeIfetch(PacketPtr );
271 void completeDataAccess(PacketPtr pkt);
272 void advanceInst(Fault fault);
273
274 /**
275 * Print state of address in memory system via PrintReq (for
276 * debugging).
277 */
278 void printAddr(Addr a);
279
280 /**
281 * Finish a DTB translation.
282 * @param state The DTB translation state.
283 */
284 void finishTranslation(WholeTranslationState *state);
285
286 private:
287
288 // The backend for writeBytes and write. It's the same as writeBytes, but
289 // doesn't make a copy of data.
290 Fault writeTheseBytes(uint8_t *data, unsigned size,
291 Addr addr, unsigned flags, uint64_t *res);
292
293 typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
294 FetchEvent fetchEvent;
295
296 struct IprEvent : Event {
297 Packet *pkt;
298 TimingSimpleCPU *cpu;
299 IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t);
300 virtual void process();
301 virtual const char *description() const;
302 };
303
304 void completeDrain();
305};
306
307#endif // __CPU_SIMPLE_TIMING_HH__
116
117 void
118 finish(Fault fault, RequestPtr req, ThreadContext *tc,
119 BaseTLB::Mode mode)
120 {
121 cpu->sendFetch(fault, req, tc);
122 }
123 };
124 FetchTranslation fetchTranslation;
125
126 void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read);
127 void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req,
128 uint8_t *data, bool read);
129
130 void translationFault(Fault fault);
131
132 void buildPacket(PacketPtr &pkt, RequestPtr req, bool read);
133 void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
134 RequestPtr req1, RequestPtr req2, RequestPtr req,
135 uint8_t *data, bool read);
136
137 bool handleReadPacket(PacketPtr pkt);
138 // This function always implicitly uses dcache_pkt.
139 bool handleWritePacket();
140
141 class CpuPort : public Port
142 {
143 protected:
144 TimingSimpleCPU *cpu;
145 Tick lat;
146
147 public:
148
149 CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat)
150 : Port(_name, _cpu), cpu(_cpu), lat(_lat), retryEvent(this)
151 { }
152
153 bool snoopRangeSent;
154
155 protected:
156
157 virtual Tick recvAtomic(PacketPtr pkt);
158
159 virtual void recvFunctional(PacketPtr pkt);
160
161 virtual void recvStatusChange(Status status);
162
163 virtual void getDeviceAddressRanges(AddrRangeList &resp,
164 bool &snoop)
165 { resp.clear(); snoop = false; }
166
167 struct TickEvent : public Event
168 {
169 PacketPtr pkt;
170 TimingSimpleCPU *cpu;
171 CpuPort *port;
172
173 TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {}
174 const char *description() const { return "Timing CPU tick"; }
175 void schedule(PacketPtr _pkt, Tick t);
176 };
177
178 EventWrapper<Port, &Port::sendRetry> retryEvent;
179 };
180
181 class IcachePort : public CpuPort
182 {
183 public:
184
185 IcachePort(TimingSimpleCPU *_cpu, Tick _lat)
186 : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu)
187 { }
188
189 protected:
190
191 virtual bool recvTiming(PacketPtr pkt);
192
193 virtual void recvRetry();
194
195 struct ITickEvent : public TickEvent
196 {
197
198 ITickEvent(TimingSimpleCPU *_cpu)
199 : TickEvent(_cpu) {}
200 void process();
201 const char *description() const { return "Timing CPU icache tick"; }
202 };
203
204 ITickEvent tickEvent;
205
206 };
207
208 class DcachePort : public CpuPort
209 {
210 public:
211
212 DcachePort(TimingSimpleCPU *_cpu, Tick _lat)
213 : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu)
214 { }
215
216 virtual void setPeer(Port *port);
217
218 protected:
219
220 virtual bool recvTiming(PacketPtr pkt);
221
222 virtual void recvRetry();
223
224 struct DTickEvent : public TickEvent
225 {
226 DTickEvent(TimingSimpleCPU *_cpu)
227 : TickEvent(_cpu) {}
228 void process();
229 const char *description() const { return "Timing CPU dcache tick"; }
230 };
231
232 DTickEvent tickEvent;
233
234 };
235
236 IcachePort icachePort;
237 DcachePort dcachePort;
238
239 PacketPtr ifetch_pkt;
240 PacketPtr dcache_pkt;
241
242 Tick previousTick;
243
244 public:
245
246 virtual Port *getPort(const std::string &if_name, int idx = -1);
247
248 virtual void serialize(std::ostream &os);
249 virtual void unserialize(Checkpoint *cp, const std::string &section);
250
251 virtual unsigned int drain(Event *drain_event);
252 virtual void resume();
253
254 void switchOut();
255 void takeOverFrom(BaseCPU *oldCPU);
256
257 virtual void activateContext(int thread_num, int delay);
258 virtual void suspendContext(int thread_num);
259
260 template <class T>
261 Fault read(Addr addr, T &data, unsigned flags);
262
263 Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
264
265 template <class T>
266 Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
267
268 Fault writeBytes(uint8_t *data, unsigned size,
269 Addr addr, unsigned flags, uint64_t *res);
270
271 void fetch();
272 void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
273 void completeIfetch(PacketPtr );
274 void completeDataAccess(PacketPtr pkt);
275 void advanceInst(Fault fault);
276
277 /**
278 * Print state of address in memory system via PrintReq (for
279 * debugging).
280 */
281 void printAddr(Addr a);
282
283 /**
284 * Finish a DTB translation.
285 * @param state The DTB translation state.
286 */
287 void finishTranslation(WholeTranslationState *state);
288
289 private:
290
291 // The backend for writeBytes and write. It's the same as writeBytes, but
292 // doesn't make a copy of data.
293 Fault writeTheseBytes(uint8_t *data, unsigned size,
294 Addr addr, unsigned flags, uint64_t *res);
295
296 typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
297 FetchEvent fetchEvent;
298
299 struct IprEvent : Event {
300 Packet *pkt;
301 TimingSimpleCPU *cpu;
302 IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t);
303 virtual void process();
304 virtual const char *description() const;
305 };
306
307 void completeDrain();
308};
309
310#endif // __CPU_SIMPLE_TIMING_HH__