cpu_impl.hh (2765:2962455d1c0a) cpu_impl.hh (2789:f99d51ed08d6)
1/*
2 * Copyright (c) 2006 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;

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

27 *
28 * Authors: Kevin Lim
29 */
30
31#include <list>
32#include <string>
33
34#include "base/refcnt.hh"
1/*
2 * Copyright (c) 2006 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;

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

27 *
28 * Authors: Kevin Lim
29 */
30
31#include <list>
32#include <string>
33
34#include "base/refcnt.hh"
35#include "cpu/base.hh"
36#include "cpu/base_dyn_inst.hh"
37#include "cpu/checker/cpu.hh"
38#include "cpu/simple_thread.hh"
39#include "cpu/thread_context.hh"
40#include "cpu/static_inst.hh"
41#include "mem/packet_impl.hh"
42#include "sim/byteswap.hh"
43#include "sim/sim_object.hh"
44#include "sim/stats.hh"
45
46#if FULL_SYSTEM
35#include "cpu/base_dyn_inst.hh"
36#include "cpu/checker/cpu.hh"
37#include "cpu/simple_thread.hh"
38#include "cpu/thread_context.hh"
39#include "cpu/static_inst.hh"
40#include "mem/packet_impl.hh"
41#include "sim/byteswap.hh"
42#include "sim/sim_object.hh"
43#include "sim/stats.hh"
44
45#if FULL_SYSTEM
47#include "sim/system.hh"
48#include "arch/vtophys.hh"
46#include "arch/vtophys.hh"
49#include "kern/kernel_stats.hh"
50#endif // FULL_SYSTEM
51
52using namespace std;
53//The CheckerCPU does alpha only
54using namespace AlphaISA;
55
47#endif // FULL_SYSTEM
48
49using namespace std;
50//The CheckerCPU does alpha only
51using namespace AlphaISA;
52
56void
57CheckerCPU::init()
58{
59}
60
61CheckerCPU::CheckerCPU(Params *p)
62 : BaseCPU(p), thread(NULL), tc(NULL)
63{
64 memReq = NULL;
65
66 numInst = 0;
67 startNumInst = 0;
68 numLoad = 0;
69 startNumLoad = 0;
70 youngestSN = 0;
71
72 changedPC = willChangePC = changedNextPC = false;
73
74 exitOnError = p->exitOnError;
75 warnOnlyOnLoadError = p->warnOnlyOnLoadError;
76#if FULL_SYSTEM
77 itb = p->itb;
78 dtb = p->dtb;
79 systemPtr = NULL;
80#else
81 process = p->process;
82#endif
83
84 result.integer = 0;
85}
86
87CheckerCPU::~CheckerCPU()
88{
89}
90
91void
92CheckerCPU::setMemory(MemObject *mem)
93{
94#if !FULL_SYSTEM
95 memPtr = mem;
96 thread = new SimpleThread(this, /* thread_num */ 0, process,
97 /* asid */ 0, mem);
98
99 thread->setStatus(ThreadContext::Suspended);
100 tc = thread->getTC();
101 threadContexts.push_back(tc);
102#endif
103}
104
105void
106CheckerCPU::setSystem(System *system)
107{
108#if FULL_SYSTEM
109 systemPtr = system;
110
111 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
112
113 thread->setStatus(ThreadContext::Suspended);
114 tc = thread->getTC();
115 threadContexts.push_back(tc);
116 delete thread->kernelStats;
117 thread->kernelStats = NULL;
118#endif
119}
120
121void
122CheckerCPU::setIcachePort(Port *icache_port)
123{
124 icachePort = icache_port;
125}
126
127void
128CheckerCPU::setDcachePort(Port *dcache_port)
129{
130 dcachePort = dcache_port;
131}
132
133void
134CheckerCPU::serialize(ostream &os)
135{
136/*
137 BaseCPU::serialize(os);
138 SERIALIZE_SCALAR(inst);
139 nameOut(os, csprintf("%s.xc", name()));
140 thread->serialize(os);
141 cacheCompletionEvent.serialize(os);
142*/
143}
144
145void
146CheckerCPU::unserialize(Checkpoint *cp, const string &section)
147{
148/*
149 BaseCPU::unserialize(cp, section);
150 UNSERIALIZE_SCALAR(inst);
151 thread->unserialize(cp, csprintf("%s.xc", section));
152*/
153}
154
155Fault
156CheckerCPU::copySrcTranslate(Addr src)
157{
158 panic("Unimplemented!");
159}
160
161Fault
162CheckerCPU::copy(Addr dest)
163{
164 panic("Unimplemented!");
165}
166
167template <class T>
168Fault
169CheckerCPU::read(Addr addr, T &data, unsigned flags)
170{
171 // need to fill in CPU & thread IDs here
172 memReq = new Request();
173
174 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
175
176 // translate to physical address
177 translateDataReadReq(memReq);
178
179 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
180
181 pkt->dataStatic(&data);
182
183 if (!(memReq->getFlags() & UNCACHEABLE)) {
184 // Access memory to see if we have the same data
185 dcachePort->sendFunctional(pkt);
186 } else {
187 // Assume the data is correct if it's an uncached access
188 memcpy(&data, &unverifiedResult.integer, sizeof(T));
189 }
190
191 delete pkt;
192
193 return NoFault;
194}
195
196#ifndef DOXYGEN_SHOULD_SKIP_THIS
197
198template
199Fault
200CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
201
202template
203Fault
204CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
205
206template
207Fault
208CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
209
210template
211Fault
212CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
213
214#endif //DOXYGEN_SHOULD_SKIP_THIS
215
216template<>
217Fault
218CheckerCPU::read(Addr addr, double &data, unsigned flags)
219{
220 return read(addr, *(uint64_t*)&data, flags);
221}
222
223template<>
224Fault
225CheckerCPU::read(Addr addr, float &data, unsigned flags)
226{
227 return read(addr, *(uint32_t*)&data, flags);
228}
229
230template<>
231Fault
232CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
233{
234 return read(addr, (uint32_t&)data, flags);
235}
236
237template <class T>
238Fault
239CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
240{
241 // need to fill in CPU & thread IDs here
242 memReq = new Request();
243
244 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
245
246 // translate to physical address
247 thread->translateDataWriteReq(memReq);
248
249 // Can compare the write data and result only if it's cacheable,
250 // not a store conditional, or is a store conditional that
251 // succeeded.
252 // @todo: Verify that actual memory matches up with these values.
253 // Right now it only verifies that the instruction data is the
254 // same as what was in the request that got sent to memory; there
255 // is no verification that it is the same as what is in memory.
256 // This is because the LSQ would have to be snooped in the CPU to
257 // verify this data.
258 if (unverifiedReq &&
259 !(unverifiedReq->getFlags() & UNCACHEABLE) &&
260 (!(unverifiedReq->getFlags() & LOCKED) ||
261 ((unverifiedReq->getFlags() & LOCKED) &&
262 unverifiedReq->getScResult() == 1))) {
263 T inst_data;
264/*
265 // This code would work if the LSQ allowed for snooping.
266 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
267 pkt.dataStatic(&inst_data);
268
269 dcachePort->sendFunctional(pkt);
270
271 delete pkt;
272*/
273 memcpy(&inst_data, unverifiedMemData, sizeof(T));
274
275 if (data != inst_data) {
276 warn("%lli: Store value does not match value in memory! "
277 "Instruction: %#x, memory: %#x",
278 curTick, inst_data, data);
279 handleError();
280 }
281 }
282
283 // Assume the result was the same as the one passed in. This checker
284 // doesn't check if the SC should succeed or fail, it just checks the
285 // value.
286 if (res && unverifiedReq->scResultValid())
287 *res = unverifiedReq->getScResult();
288
289 return NoFault;
290}
291
292
293#ifndef DOXYGEN_SHOULD_SKIP_THIS
294template
295Fault
296CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
297
298template
299Fault
300CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
301
302template
303Fault
304CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
305
306template
307Fault
308CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
309
310#endif //DOXYGEN_SHOULD_SKIP_THIS
311
312template<>
313Fault
314CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
315{
316 return write(*(uint64_t*)&data, addr, flags, res);
317}
318
319template<>
320Fault
321CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
322{
323 return write(*(uint32_t*)&data, addr, flags, res);
324}
325
326template<>
327Fault
328CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
329{
330 return write((uint32_t)data, addr, flags, res);
331}
332
333
334#if FULL_SYSTEM
335Addr
336CheckerCPU::dbg_vtophys(Addr addr)
337{
338 return vtophys(tc, addr);
339}
340#endif // FULL_SYSTEM
341
342bool
343CheckerCPU::translateInstReq(Request *req)
344{
345#if FULL_SYSTEM
346 return (thread->translateInstReq(req) == NoFault);
347#else
348 thread->translateInstReq(req);
349 return true;
350#endif
351}
352
353void
354CheckerCPU::translateDataReadReq(Request *req)
355{
356 thread->translateDataReadReq(req);
357
358 if (req->getVaddr() != unverifiedReq->getVaddr()) {
359 warn("%lli: Request virtual addresses do not match! Inst: %#x, "
360 "checker: %#x",
361 curTick, unverifiedReq->getVaddr(), req->getVaddr());
362 handleError();
363 }
364 req->setPaddr(unverifiedReq->getPaddr());
365
366 if (checkFlags(req)) {
367 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
368 curTick, unverifiedReq->getFlags(), req->getFlags());
369 handleError();
370 }
371}
372
373void
374CheckerCPU::translateDataWriteReq(Request *req)
375{
376 thread->translateDataWriteReq(req);
377
378 if (req->getVaddr() != unverifiedReq->getVaddr()) {
379 warn("%lli: Request virtual addresses do not match! Inst: %#x, "
380 "checker: %#x",
381 curTick, unverifiedReq->getVaddr(), req->getVaddr());
382 handleError();
383 }
384 req->setPaddr(unverifiedReq->getPaddr());
385
386 if (checkFlags(req)) {
387 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
388 curTick, unverifiedReq->getFlags(), req->getFlags());
389 handleError();
390 }
391}
392
393bool
394CheckerCPU::checkFlags(Request *req)
395{
396 // Remove any dynamic flags that don't have to do with the request itself.
397 unsigned flags = unverifiedReq->getFlags();
398 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
399 flags = flags & (mask);
400 if (flags == req->getFlags()) {
401 return false;
402 } else {
403 return true;
404 }
405}
406
407void
408CheckerCPU::dumpAndExit()
409{
410 warn("%lli: Checker PC:%#x, next PC:%#x",
411 curTick, thread->readPC(), thread->readNextPC());
412 panic("Checker found an error!");
413}
414
415template <class DynInstPtr>
416void
417Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
418{
419 DynInstPtr inst;
420
421 // Either check this instruction, or add it to a list of
422 // instructions waiting to be checked. Instructions must be

--- 400 unchanged lines hidden ---
53template <class DynInstPtr>
54void
55Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
56{
57 DynInstPtr inst;
58
59 // Either check this instruction, or add it to a list of
60 // instructions waiting to be checked. Instructions must be

--- 400 unchanged lines hidden ---