cpu.hh (13910:d5deee7b4279) cpu.hh (13953:43ae8a30ec1f)
1/*
1/*
2 * Copyright (c) 2011, 2016-2017 ARM Limited
2 * Copyright (c) 2011, 2016-2018 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 */
43
44#ifndef __CPU_CHECKER_CPU_HH__
45#define __CPU_CHECKER_CPU_HH__
46
47#include <list>
48#include <map>
49#include <queue>
50
51#include "arch/types.hh"
52#include "base/statistics.hh"
53#include "cpu/base.hh"
54#include "cpu/base_dyn_inst.hh"
55#include "cpu/exec_context.hh"
56#include "cpu/inst_res.hh"
57#include "cpu/pc_event.hh"
58#include "cpu/simple_thread.hh"
59#include "cpu/static_inst.hh"
60#include "debug/Checker.hh"
61#include "mem/request.hh"
62#include "params/CheckerCPU.hh"
63#include "sim/eventq.hh"
64
65class BaseTLB;
66template <class>
67class BaseDynInst;
68class ThreadContext;
69class Request;
70
71/**
72 * CheckerCPU class. Dynamically verifies instructions as they are
73 * completed by making sure that the instruction and its results match
74 * the independent execution of the benchmark inside the checker. The
75 * checker verifies instructions in order, regardless of the order in
76 * which instructions complete. There are certain results that can
77 * not be verified, specifically the result of a store conditional or
78 * the values of uncached accesses. In these cases, and with
79 * instructions marked as "IsUnverifiable", the checker assumes that
80 * the value from the main CPU's execution is correct and simply
81 * copies that value. It provides a CheckerThreadContext (see
82 * checker/thread_context.hh) that provides hooks for updating the
83 * Checker's state through any ThreadContext accesses. This allows the
84 * checker to be able to correctly verify instructions, even with
85 * external accesses to the ThreadContext that change state.
86 */
87class CheckerCPU : public BaseCPU, public ExecContext
88{
89 protected:
90 typedef TheISA::MachInst MachInst;
91 using VecRegContainer = TheISA::VecRegContainer;
92
93 /** id attached to all issued requests */
94 MasterID masterId;
95 public:
96 void init() override;
97
98 typedef CheckerCPUParams Params;
99 CheckerCPU(Params *p);
100 virtual ~CheckerCPU();
101
102 void setSystem(System *system);
103
104 void setIcachePort(MasterPort *icache_port);
105
106 void setDcachePort(MasterPort *dcache_port);
107
108 MasterPort &getDataPort() override
109 {
110 // the checker does not have ports on its own so return the
111 // data port of the actual CPU core
112 assert(dcachePort);
113 return *dcachePort;
114 }
115
116 MasterPort &getInstPort() override
117 {
118 // the checker does not have ports on its own so return the
119 // data port of the actual CPU core
120 assert(icachePort);
121 return *icachePort;
122 }
123
124 protected:
125
126 std::vector<Process*> workload;
127
128 System *systemPtr;
129
130 MasterPort *icachePort;
131 MasterPort *dcachePort;
132
133 ThreadContext *tc;
134
135 BaseTLB *itb;
136 BaseTLB *dtb;
137
138 Addr dbg_vtophys(Addr addr);
139
140 // ISAs like ARM can have multiple destination registers to check,
141 // keep them all in a std::queue
142 std::queue<InstResult> result;
143
144 StaticInstPtr curStaticInst;
145 StaticInstPtr curMacroStaticInst;
146
147 // number of simulated instructions
148 Counter numInst;
149 Counter startNumInst;
150
151 std::queue<int> miscRegIdxs;
152
153 public:
154
155 // Primary thread being run.
156 SimpleThread *thread;
157
158 BaseTLB* getITBPtr() { return itb; }
159 BaseTLB* getDTBPtr() { return dtb; }
160
161 virtual Counter totalInsts() const override
162 {
163 return 0;
164 }
165
166 virtual Counter totalOps() const override
167 {
168 return 0;
169 }
170
171 // number of simulated loads
172 Counter numLoad;
173 Counter startNumLoad;
174
175 void serialize(CheckpointOut &cp) const override;
176 void unserialize(CheckpointIn &cp) override;
177
178 // The register accessor methods provide the index of the
179 // instruction's operand (e.g., 0 or 1), not the architectural
180 // register index, to simplify the implementation of register
181 // renaming. We find the architectural register index by indexing
182 // into the instruction's own operand index table. Note that a
183 // raw pointer to the StaticInst is provided instead of a
184 // ref-counted StaticInstPtr to redice overhead. This is fine as
185 // long as these methods don't copy the pointer into any long-term
186 // storage (which is pretty hard to imagine they would have reason
187 // to do).
188
189 RegVal
190 readIntRegOperand(const StaticInst *si, int idx) override
191 {
192 const RegId& reg = si->srcRegIdx(idx);
193 assert(reg.isIntReg());
194 return thread->readIntReg(reg.index());
195 }
196
197 RegVal
198 readFloatRegOperandBits(const StaticInst *si, int idx) override
199 {
200 const RegId& reg = si->srcRegIdx(idx);
201 assert(reg.isFloatReg());
202 return thread->readFloatReg(reg.index());
203 }
204
205 /**
206 * Read source vector register operand.
207 */
208 const VecRegContainer &
209 readVecRegOperand(const StaticInst *si, int idx) const override
210 {
211 const RegId& reg = si->srcRegIdx(idx);
212 assert(reg.isVecReg());
213 return thread->readVecReg(reg);
214 }
215
216 /**
217 * Read destination vector register operand for modification.
218 */
219 VecRegContainer &
220 getWritableVecRegOperand(const StaticInst *si, int idx) override
221 {
222 const RegId& reg = si->destRegIdx(idx);
223 assert(reg.isVecReg());
224 return thread->getWritableVecReg(reg);
225 }
226
227 /** Vector Register Lane Interfaces. */
228 /** @{ */
229 /** Reads source vector 8bit operand. */
230 virtual ConstVecLane8
231 readVec8BitLaneOperand(const StaticInst *si, int idx) const override
232 {
233 const RegId& reg = si->destRegIdx(idx);
234 assert(reg.isVecReg());
235 return thread->readVec8BitLaneReg(reg);
236 }
237
238 /** Reads source vector 16bit operand. */
239 virtual ConstVecLane16
240 readVec16BitLaneOperand(const StaticInst *si, int idx) const override
241 {
242 const RegId& reg = si->destRegIdx(idx);
243 assert(reg.isVecReg());
244 return thread->readVec16BitLaneReg(reg);
245 }
246
247 /** Reads source vector 32bit operand. */
248 virtual ConstVecLane32
249 readVec32BitLaneOperand(const StaticInst *si, int idx) const override
250 {
251 const RegId& reg = si->destRegIdx(idx);
252 assert(reg.isVecReg());
253 return thread->readVec32BitLaneReg(reg);
254 }
255
256 /** Reads source vector 64bit operand. */
257 virtual ConstVecLane64
258 readVec64BitLaneOperand(const StaticInst *si, int idx) const override
259 {
260 const RegId& reg = si->destRegIdx(idx);
261 assert(reg.isVecReg());
262 return thread->readVec64BitLaneReg(reg);
263 }
264
265 /** Write a lane of the destination vector operand. */
266 template <typename LD>
267 void
268 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
269 {
270 const RegId& reg = si->destRegIdx(idx);
271 assert(reg.isVecReg());
272 return thread->setVecLane(reg, val);
273 }
274 virtual void
275 setVecLaneOperand(const StaticInst *si, int idx,
276 const LaneData<LaneSize::Byte>& val) override
277 {
278 setVecLaneOperandT(si, idx, val);
279 }
280 virtual void
281 setVecLaneOperand(const StaticInst *si, int idx,
282 const LaneData<LaneSize::TwoByte>& val) override
283 {
284 setVecLaneOperandT(si, idx, val);
285 }
286 virtual void
287 setVecLaneOperand(const StaticInst *si, int idx,
288 const LaneData<LaneSize::FourByte>& val) override
289 {
290 setVecLaneOperandT(si, idx, val);
291 }
292 virtual void
293 setVecLaneOperand(const StaticInst *si, int idx,
294 const LaneData<LaneSize::EightByte>& val) override
295 {
296 setVecLaneOperandT(si, idx, val);
297 }
298 /** @} */
299
300 VecElem
301 readVecElemOperand(const StaticInst *si, int idx) const override
302 {
303 const RegId& reg = si->srcRegIdx(idx);
304 return thread->readVecElem(reg);
305 }
306
307 const VecPredRegContainer&
308 readVecPredRegOperand(const StaticInst *si, int idx) const override
309 {
310 const RegId& reg = si->srcRegIdx(idx);
311 assert(reg.isVecPredReg());
312 return thread->readVecPredReg(reg);
313 }
314
315 VecPredRegContainer&
316 getWritableVecPredRegOperand(const StaticInst *si, int idx) override
317 {
318 const RegId& reg = si->destRegIdx(idx);
319 assert(reg.isVecPredReg());
320 return thread->getWritableVecPredReg(reg);
321 }
322
323 RegVal
324 readCCRegOperand(const StaticInst *si, int idx) override
325 {
326 const RegId& reg = si->srcRegIdx(idx);
327 assert(reg.isCCReg());
328 return thread->readCCReg(reg.index());
329 }
330
331 template<typename T>
332 void
333 setScalarResult(T&& t)
334 {
335 result.push(InstResult(std::forward<T>(t),
336 InstResult::ResultType::Scalar));
337 }
338
339 template<typename T>
340 void
341 setVecResult(T&& t)
342 {
343 result.push(InstResult(std::forward<T>(t),
344 InstResult::ResultType::VecReg));
345 }
346
347 template<typename T>
348 void
349 setVecElemResult(T&& t)
350 {
351 result.push(InstResult(std::forward<T>(t),
352 InstResult::ResultType::VecElem));
353 }
354
355 template<typename T>
356 void
357 setVecPredResult(T&& t)
358 {
359 result.push(InstResult(std::forward<T>(t),
360 InstResult::ResultType::VecPredReg));
361 }
362
363 void
364 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
365 {
366 const RegId& reg = si->destRegIdx(idx);
367 assert(reg.isIntReg());
368 thread->setIntReg(reg.index(), val);
369 setScalarResult(val);
370 }
371
372 void
373 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
374 {
375 const RegId& reg = si->destRegIdx(idx);
376 assert(reg.isFloatReg());
377 thread->setFloatReg(reg.index(), val);
378 setScalarResult(val);
379 }
380
381 void
382 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
383 {
384 const RegId& reg = si->destRegIdx(idx);
385 assert(reg.isCCReg());
386 thread->setCCReg(reg.index(), val);
387 setScalarResult((uint64_t)val);
388 }
389
390 void
391 setVecRegOperand(const StaticInst *si, int idx,
392 const VecRegContainer& val) override
393 {
394 const RegId& reg = si->destRegIdx(idx);
395 assert(reg.isVecReg());
396 thread->setVecReg(reg, val);
397 setVecResult(val);
398 }
399
400 void
401 setVecElemOperand(const StaticInst *si, int idx,
402 const VecElem val) override
403 {
404 const RegId& reg = si->destRegIdx(idx);
405 assert(reg.isVecElem());
406 thread->setVecElem(reg, val);
407 setVecElemResult(val);
408 }
409
410 void setVecPredRegOperand(const StaticInst *si, int idx,
411 const VecPredRegContainer& val) override
412 {
413 const RegId& reg = si->destRegIdx(idx);
414 assert(reg.isVecPredReg());
415 thread->setVecPredReg(reg, val);
416 setVecPredResult(val);
417 }
418
419 bool readPredicate() const override { return thread->readPredicate(); }
420
421 void
422 setPredicate(bool val) override
423 {
424 thread->setPredicate(val);
425 }
426
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 */
43
44#ifndef __CPU_CHECKER_CPU_HH__
45#define __CPU_CHECKER_CPU_HH__
46
47#include <list>
48#include <map>
49#include <queue>
50
51#include "arch/types.hh"
52#include "base/statistics.hh"
53#include "cpu/base.hh"
54#include "cpu/base_dyn_inst.hh"
55#include "cpu/exec_context.hh"
56#include "cpu/inst_res.hh"
57#include "cpu/pc_event.hh"
58#include "cpu/simple_thread.hh"
59#include "cpu/static_inst.hh"
60#include "debug/Checker.hh"
61#include "mem/request.hh"
62#include "params/CheckerCPU.hh"
63#include "sim/eventq.hh"
64
65class BaseTLB;
66template <class>
67class BaseDynInst;
68class ThreadContext;
69class Request;
70
71/**
72 * CheckerCPU class. Dynamically verifies instructions as they are
73 * completed by making sure that the instruction and its results match
74 * the independent execution of the benchmark inside the checker. The
75 * checker verifies instructions in order, regardless of the order in
76 * which instructions complete. There are certain results that can
77 * not be verified, specifically the result of a store conditional or
78 * the values of uncached accesses. In these cases, and with
79 * instructions marked as "IsUnverifiable", the checker assumes that
80 * the value from the main CPU's execution is correct and simply
81 * copies that value. It provides a CheckerThreadContext (see
82 * checker/thread_context.hh) that provides hooks for updating the
83 * Checker's state through any ThreadContext accesses. This allows the
84 * checker to be able to correctly verify instructions, even with
85 * external accesses to the ThreadContext that change state.
86 */
87class CheckerCPU : public BaseCPU, public ExecContext
88{
89 protected:
90 typedef TheISA::MachInst MachInst;
91 using VecRegContainer = TheISA::VecRegContainer;
92
93 /** id attached to all issued requests */
94 MasterID masterId;
95 public:
96 void init() override;
97
98 typedef CheckerCPUParams Params;
99 CheckerCPU(Params *p);
100 virtual ~CheckerCPU();
101
102 void setSystem(System *system);
103
104 void setIcachePort(MasterPort *icache_port);
105
106 void setDcachePort(MasterPort *dcache_port);
107
108 MasterPort &getDataPort() override
109 {
110 // the checker does not have ports on its own so return the
111 // data port of the actual CPU core
112 assert(dcachePort);
113 return *dcachePort;
114 }
115
116 MasterPort &getInstPort() override
117 {
118 // the checker does not have ports on its own so return the
119 // data port of the actual CPU core
120 assert(icachePort);
121 return *icachePort;
122 }
123
124 protected:
125
126 std::vector<Process*> workload;
127
128 System *systemPtr;
129
130 MasterPort *icachePort;
131 MasterPort *dcachePort;
132
133 ThreadContext *tc;
134
135 BaseTLB *itb;
136 BaseTLB *dtb;
137
138 Addr dbg_vtophys(Addr addr);
139
140 // ISAs like ARM can have multiple destination registers to check,
141 // keep them all in a std::queue
142 std::queue<InstResult> result;
143
144 StaticInstPtr curStaticInst;
145 StaticInstPtr curMacroStaticInst;
146
147 // number of simulated instructions
148 Counter numInst;
149 Counter startNumInst;
150
151 std::queue<int> miscRegIdxs;
152
153 public:
154
155 // Primary thread being run.
156 SimpleThread *thread;
157
158 BaseTLB* getITBPtr() { return itb; }
159 BaseTLB* getDTBPtr() { return dtb; }
160
161 virtual Counter totalInsts() const override
162 {
163 return 0;
164 }
165
166 virtual Counter totalOps() const override
167 {
168 return 0;
169 }
170
171 // number of simulated loads
172 Counter numLoad;
173 Counter startNumLoad;
174
175 void serialize(CheckpointOut &cp) const override;
176 void unserialize(CheckpointIn &cp) override;
177
178 // The register accessor methods provide the index of the
179 // instruction's operand (e.g., 0 or 1), not the architectural
180 // register index, to simplify the implementation of register
181 // renaming. We find the architectural register index by indexing
182 // into the instruction's own operand index table. Note that a
183 // raw pointer to the StaticInst is provided instead of a
184 // ref-counted StaticInstPtr to redice overhead. This is fine as
185 // long as these methods don't copy the pointer into any long-term
186 // storage (which is pretty hard to imagine they would have reason
187 // to do).
188
189 RegVal
190 readIntRegOperand(const StaticInst *si, int idx) override
191 {
192 const RegId& reg = si->srcRegIdx(idx);
193 assert(reg.isIntReg());
194 return thread->readIntReg(reg.index());
195 }
196
197 RegVal
198 readFloatRegOperandBits(const StaticInst *si, int idx) override
199 {
200 const RegId& reg = si->srcRegIdx(idx);
201 assert(reg.isFloatReg());
202 return thread->readFloatReg(reg.index());
203 }
204
205 /**
206 * Read source vector register operand.
207 */
208 const VecRegContainer &
209 readVecRegOperand(const StaticInst *si, int idx) const override
210 {
211 const RegId& reg = si->srcRegIdx(idx);
212 assert(reg.isVecReg());
213 return thread->readVecReg(reg);
214 }
215
216 /**
217 * Read destination vector register operand for modification.
218 */
219 VecRegContainer &
220 getWritableVecRegOperand(const StaticInst *si, int idx) override
221 {
222 const RegId& reg = si->destRegIdx(idx);
223 assert(reg.isVecReg());
224 return thread->getWritableVecReg(reg);
225 }
226
227 /** Vector Register Lane Interfaces. */
228 /** @{ */
229 /** Reads source vector 8bit operand. */
230 virtual ConstVecLane8
231 readVec8BitLaneOperand(const StaticInst *si, int idx) const override
232 {
233 const RegId& reg = si->destRegIdx(idx);
234 assert(reg.isVecReg());
235 return thread->readVec8BitLaneReg(reg);
236 }
237
238 /** Reads source vector 16bit operand. */
239 virtual ConstVecLane16
240 readVec16BitLaneOperand(const StaticInst *si, int idx) const override
241 {
242 const RegId& reg = si->destRegIdx(idx);
243 assert(reg.isVecReg());
244 return thread->readVec16BitLaneReg(reg);
245 }
246
247 /** Reads source vector 32bit operand. */
248 virtual ConstVecLane32
249 readVec32BitLaneOperand(const StaticInst *si, int idx) const override
250 {
251 const RegId& reg = si->destRegIdx(idx);
252 assert(reg.isVecReg());
253 return thread->readVec32BitLaneReg(reg);
254 }
255
256 /** Reads source vector 64bit operand. */
257 virtual ConstVecLane64
258 readVec64BitLaneOperand(const StaticInst *si, int idx) const override
259 {
260 const RegId& reg = si->destRegIdx(idx);
261 assert(reg.isVecReg());
262 return thread->readVec64BitLaneReg(reg);
263 }
264
265 /** Write a lane of the destination vector operand. */
266 template <typename LD>
267 void
268 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
269 {
270 const RegId& reg = si->destRegIdx(idx);
271 assert(reg.isVecReg());
272 return thread->setVecLane(reg, val);
273 }
274 virtual void
275 setVecLaneOperand(const StaticInst *si, int idx,
276 const LaneData<LaneSize::Byte>& val) override
277 {
278 setVecLaneOperandT(si, idx, val);
279 }
280 virtual void
281 setVecLaneOperand(const StaticInst *si, int idx,
282 const LaneData<LaneSize::TwoByte>& val) override
283 {
284 setVecLaneOperandT(si, idx, val);
285 }
286 virtual void
287 setVecLaneOperand(const StaticInst *si, int idx,
288 const LaneData<LaneSize::FourByte>& val) override
289 {
290 setVecLaneOperandT(si, idx, val);
291 }
292 virtual void
293 setVecLaneOperand(const StaticInst *si, int idx,
294 const LaneData<LaneSize::EightByte>& val) override
295 {
296 setVecLaneOperandT(si, idx, val);
297 }
298 /** @} */
299
300 VecElem
301 readVecElemOperand(const StaticInst *si, int idx) const override
302 {
303 const RegId& reg = si->srcRegIdx(idx);
304 return thread->readVecElem(reg);
305 }
306
307 const VecPredRegContainer&
308 readVecPredRegOperand(const StaticInst *si, int idx) const override
309 {
310 const RegId& reg = si->srcRegIdx(idx);
311 assert(reg.isVecPredReg());
312 return thread->readVecPredReg(reg);
313 }
314
315 VecPredRegContainer&
316 getWritableVecPredRegOperand(const StaticInst *si, int idx) override
317 {
318 const RegId& reg = si->destRegIdx(idx);
319 assert(reg.isVecPredReg());
320 return thread->getWritableVecPredReg(reg);
321 }
322
323 RegVal
324 readCCRegOperand(const StaticInst *si, int idx) override
325 {
326 const RegId& reg = si->srcRegIdx(idx);
327 assert(reg.isCCReg());
328 return thread->readCCReg(reg.index());
329 }
330
331 template<typename T>
332 void
333 setScalarResult(T&& t)
334 {
335 result.push(InstResult(std::forward<T>(t),
336 InstResult::ResultType::Scalar));
337 }
338
339 template<typename T>
340 void
341 setVecResult(T&& t)
342 {
343 result.push(InstResult(std::forward<T>(t),
344 InstResult::ResultType::VecReg));
345 }
346
347 template<typename T>
348 void
349 setVecElemResult(T&& t)
350 {
351 result.push(InstResult(std::forward<T>(t),
352 InstResult::ResultType::VecElem));
353 }
354
355 template<typename T>
356 void
357 setVecPredResult(T&& t)
358 {
359 result.push(InstResult(std::forward<T>(t),
360 InstResult::ResultType::VecPredReg));
361 }
362
363 void
364 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
365 {
366 const RegId& reg = si->destRegIdx(idx);
367 assert(reg.isIntReg());
368 thread->setIntReg(reg.index(), val);
369 setScalarResult(val);
370 }
371
372 void
373 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
374 {
375 const RegId& reg = si->destRegIdx(idx);
376 assert(reg.isFloatReg());
377 thread->setFloatReg(reg.index(), val);
378 setScalarResult(val);
379 }
380
381 void
382 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
383 {
384 const RegId& reg = si->destRegIdx(idx);
385 assert(reg.isCCReg());
386 thread->setCCReg(reg.index(), val);
387 setScalarResult((uint64_t)val);
388 }
389
390 void
391 setVecRegOperand(const StaticInst *si, int idx,
392 const VecRegContainer& val) override
393 {
394 const RegId& reg = si->destRegIdx(idx);
395 assert(reg.isVecReg());
396 thread->setVecReg(reg, val);
397 setVecResult(val);
398 }
399
400 void
401 setVecElemOperand(const StaticInst *si, int idx,
402 const VecElem val) override
403 {
404 const RegId& reg = si->destRegIdx(idx);
405 assert(reg.isVecElem());
406 thread->setVecElem(reg, val);
407 setVecElemResult(val);
408 }
409
410 void setVecPredRegOperand(const StaticInst *si, int idx,
411 const VecPredRegContainer& val) override
412 {
413 const RegId& reg = si->destRegIdx(idx);
414 assert(reg.isVecPredReg());
415 thread->setVecPredReg(reg, val);
416 setVecPredResult(val);
417 }
418
419 bool readPredicate() const override { return thread->readPredicate(); }
420
421 void
422 setPredicate(bool val) override
423 {
424 thread->setPredicate(val);
425 }
426
427 bool
428 readMemAccPredicate() const override
429 {
430 return thread->readMemAccPredicate();
431 }
432
433 void
434 setMemAccPredicate(bool val) override
435 {
436 thread->setMemAccPredicate(val);
437 }
438
427 TheISA::PCState pcState() const override { return thread->pcState(); }
428 void
429 pcState(const TheISA::PCState &val) override
430 {
431 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
432 val, thread->pcState());
433 thread->pcState(val);
434 }
435 Addr instAddr() { return thread->instAddr(); }
436 Addr nextInstAddr() { return thread->nextInstAddr(); }
437 MicroPC microPC() { return thread->microPC(); }
438 //////////////////////////////////////////
439
440 RegVal
441 readMiscRegNoEffect(int misc_reg) const
442 {
443 return thread->readMiscRegNoEffect(misc_reg);
444 }
445
446 RegVal
447 readMiscReg(int misc_reg) override
448 {
449 return thread->readMiscReg(misc_reg);
450 }
451
452 void
453 setMiscRegNoEffect(int misc_reg, RegVal val)
454 {
455 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n",
456 misc_reg);
457 miscRegIdxs.push(misc_reg);
458 return thread->setMiscRegNoEffect(misc_reg, val);
459 }
460
461 void
462 setMiscReg(int misc_reg, RegVal val) override
463 {
464 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n",
465 misc_reg);
466 miscRegIdxs.push(misc_reg);
467 return thread->setMiscReg(misc_reg, val);
468 }
469
470 RegVal
471 readMiscRegOperand(const StaticInst *si, int idx) override
472 {
473 const RegId& reg = si->srcRegIdx(idx);
474 assert(reg.isMiscReg());
475 return thread->readMiscReg(reg.index());
476 }
477
478 void
479 setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
480 {
481 const RegId& reg = si->destRegIdx(idx);
482 assert(reg.isMiscReg());
483 return this->setMiscReg(reg.index(), val);
484 }
485
486 /////////////////////////////////////////
487
488 void
489 recordPCChange(const TheISA::PCState &val)
490 {
491 changedPC = true;
492 newPCState = val;
493 }
494
495 void
496 demapPage(Addr vaddr, uint64_t asn) override
497 {
498 this->itb->demapPage(vaddr, asn);
499 this->dtb->demapPage(vaddr, asn);
500 }
501
502 // monitor/mwait funtions
503 void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); }
504 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
505 void mwaitAtomic(ThreadContext *tc) override
506 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
507 AddressMonitor *getAddrMonitor() override
508 { return BaseCPU::getCpuAddrMonitor(0); }
509
510 void
511 demapInstPage(Addr vaddr, uint64_t asn)
512 {
513 this->itb->demapPage(vaddr, asn);
514 }
515
516 void
517 demapDataPage(Addr vaddr, uint64_t asn)
518 {
519 this->dtb->demapPage(vaddr, asn);
520 }
521
522 Fault readMem(Addr addr, uint8_t *data, unsigned size,
523 Request::Flags flags) override;
524
525 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
526 Request::Flags flags, uint64_t *res) override;
527
528 Fault amoMem(Addr addr, uint8_t* data, unsigned size,
529 Request::Flags flags, AtomicOpFunctor *amo_op) override
530 {
531 panic("AMO is not supported yet in CPU checker\n");
532 }
533
534 unsigned int
535 readStCondFailures() const override {
536 return thread->readStCondFailures();
537 }
538
539 void setStCondFailures(unsigned int sc_failures) override {}
540 /////////////////////////////////////////////////////
541
542 void wakeup(ThreadID tid) override { }
543 // Assume that the normal CPU's call to syscall was successful.
544 // The checker's state would have already been updated by the syscall.
545 void syscall(int64_t callnum, Fault *fault) override { }
546
547 void
548 handleError()
549 {
550 if (exitOnError)
551 dumpAndExit();
552 }
553
554 bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
555 Addr pAddr, int flags);
556
557 void dumpAndExit();
558
559 ThreadContext *tcBase() override { return tc; }
560 SimpleThread *threadBase() { return thread; }
561
562 InstResult unverifiedResult;
563 RequestPtr unverifiedReq;
564 uint8_t *unverifiedMemData;
565
566 bool changedPC;
567 bool willChangePC;
568 TheISA::PCState newPCState;
569 bool exitOnError;
570 bool updateOnError;
571 bool warnOnlyOnLoadError;
572
573 InstSeqNum youngestSN;
574};
575
576/**
577 * Templated Checker class. This Checker class is templated on the
578 * DynInstPtr of the instruction type that will be verified. Proper
579 * template instantiations of the Checker must be placed at the bottom
580 * of checker/cpu.cc.
581 */
582template <class Impl>
583class Checker : public CheckerCPU
584{
585 private:
586 typedef typename Impl::DynInstPtr DynInstPtr;
587
588 public:
589 Checker(Params *p)
590 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
591 { }
592
593 void switchOut();
594 void takeOverFrom(BaseCPU *oldCPU);
595
596 void advancePC(const Fault &fault);
597
598 void verify(const DynInstPtr &inst);
599
600 void validateInst(const DynInstPtr &inst);
601 void validateExecution(const DynInstPtr &inst);
602 void validateState();
603
604 void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
605 int start_idx);
606 void handlePendingInt();
607
608 private:
609 void handleError(const DynInstPtr &inst)
610 {
611 if (exitOnError) {
612 dumpAndExit(inst);
613 } else if (updateOnError) {
614 updateThisCycle = true;
615 }
616 }
617
618 void dumpAndExit(const DynInstPtr &inst);
619
620 bool updateThisCycle;
621
622 DynInstPtr unverifiedInst;
623
624 std::list<DynInstPtr> instList;
625 typedef typename std::list<DynInstPtr>::iterator InstListIt;
626 void dumpInsts();
627};
628
629#endif // __CPU_CHECKER_CPU_HH__
439 TheISA::PCState pcState() const override { return thread->pcState(); }
440 void
441 pcState(const TheISA::PCState &val) override
442 {
443 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
444 val, thread->pcState());
445 thread->pcState(val);
446 }
447 Addr instAddr() { return thread->instAddr(); }
448 Addr nextInstAddr() { return thread->nextInstAddr(); }
449 MicroPC microPC() { return thread->microPC(); }
450 //////////////////////////////////////////
451
452 RegVal
453 readMiscRegNoEffect(int misc_reg) const
454 {
455 return thread->readMiscRegNoEffect(misc_reg);
456 }
457
458 RegVal
459 readMiscReg(int misc_reg) override
460 {
461 return thread->readMiscReg(misc_reg);
462 }
463
464 void
465 setMiscRegNoEffect(int misc_reg, RegVal val)
466 {
467 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n",
468 misc_reg);
469 miscRegIdxs.push(misc_reg);
470 return thread->setMiscRegNoEffect(misc_reg, val);
471 }
472
473 void
474 setMiscReg(int misc_reg, RegVal val) override
475 {
476 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n",
477 misc_reg);
478 miscRegIdxs.push(misc_reg);
479 return thread->setMiscReg(misc_reg, val);
480 }
481
482 RegVal
483 readMiscRegOperand(const StaticInst *si, int idx) override
484 {
485 const RegId& reg = si->srcRegIdx(idx);
486 assert(reg.isMiscReg());
487 return thread->readMiscReg(reg.index());
488 }
489
490 void
491 setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
492 {
493 const RegId& reg = si->destRegIdx(idx);
494 assert(reg.isMiscReg());
495 return this->setMiscReg(reg.index(), val);
496 }
497
498 /////////////////////////////////////////
499
500 void
501 recordPCChange(const TheISA::PCState &val)
502 {
503 changedPC = true;
504 newPCState = val;
505 }
506
507 void
508 demapPage(Addr vaddr, uint64_t asn) override
509 {
510 this->itb->demapPage(vaddr, asn);
511 this->dtb->demapPage(vaddr, asn);
512 }
513
514 // monitor/mwait funtions
515 void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); }
516 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
517 void mwaitAtomic(ThreadContext *tc) override
518 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
519 AddressMonitor *getAddrMonitor() override
520 { return BaseCPU::getCpuAddrMonitor(0); }
521
522 void
523 demapInstPage(Addr vaddr, uint64_t asn)
524 {
525 this->itb->demapPage(vaddr, asn);
526 }
527
528 void
529 demapDataPage(Addr vaddr, uint64_t asn)
530 {
531 this->dtb->demapPage(vaddr, asn);
532 }
533
534 Fault readMem(Addr addr, uint8_t *data, unsigned size,
535 Request::Flags flags) override;
536
537 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
538 Request::Flags flags, uint64_t *res) override;
539
540 Fault amoMem(Addr addr, uint8_t* data, unsigned size,
541 Request::Flags flags, AtomicOpFunctor *amo_op) override
542 {
543 panic("AMO is not supported yet in CPU checker\n");
544 }
545
546 unsigned int
547 readStCondFailures() const override {
548 return thread->readStCondFailures();
549 }
550
551 void setStCondFailures(unsigned int sc_failures) override {}
552 /////////////////////////////////////////////////////
553
554 void wakeup(ThreadID tid) override { }
555 // Assume that the normal CPU's call to syscall was successful.
556 // The checker's state would have already been updated by the syscall.
557 void syscall(int64_t callnum, Fault *fault) override { }
558
559 void
560 handleError()
561 {
562 if (exitOnError)
563 dumpAndExit();
564 }
565
566 bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
567 Addr pAddr, int flags);
568
569 void dumpAndExit();
570
571 ThreadContext *tcBase() override { return tc; }
572 SimpleThread *threadBase() { return thread; }
573
574 InstResult unverifiedResult;
575 RequestPtr unverifiedReq;
576 uint8_t *unverifiedMemData;
577
578 bool changedPC;
579 bool willChangePC;
580 TheISA::PCState newPCState;
581 bool exitOnError;
582 bool updateOnError;
583 bool warnOnlyOnLoadError;
584
585 InstSeqNum youngestSN;
586};
587
588/**
589 * Templated Checker class. This Checker class is templated on the
590 * DynInstPtr of the instruction type that will be verified. Proper
591 * template instantiations of the Checker must be placed at the bottom
592 * of checker/cpu.cc.
593 */
594template <class Impl>
595class Checker : public CheckerCPU
596{
597 private:
598 typedef typename Impl::DynInstPtr DynInstPtr;
599
600 public:
601 Checker(Params *p)
602 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
603 { }
604
605 void switchOut();
606 void takeOverFrom(BaseCPU *oldCPU);
607
608 void advancePC(const Fault &fault);
609
610 void verify(const DynInstPtr &inst);
611
612 void validateInst(const DynInstPtr &inst);
613 void validateExecution(const DynInstPtr &inst);
614 void validateState();
615
616 void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
617 int start_idx);
618 void handlePendingInt();
619
620 private:
621 void handleError(const DynInstPtr &inst)
622 {
623 if (exitOnError) {
624 dumpAndExit(inst);
625 } else if (updateOnError) {
626 updateThisCycle = true;
627 }
628 }
629
630 void dumpAndExit(const DynInstPtr &inst);
631
632 bool updateThisCycle;
633
634 DynInstPtr unverifiedInst;
635
636 std::list<DynInstPtr> instList;
637 typedef typename std::list<DynInstPtr>::iterator InstListIt;
638 void dumpInsts();
639};
640
641#endif // __CPU_CHECKER_CPU_HH__