cpu.cc (13905:5cf30883255c) | cpu.cc (13954:2f400a5f2627) |
---|---|
1/* | 1/* |
2 * Copyright (c) 2011,2013,2017 ARM Limited | 2 * Copyright (c) 2011,2013,2017-2018 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 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated --- 36 unchanged lines hidden (view full) --- 47#include <string> 48 49#include "arch/generic/tlb.hh" 50#include "arch/vtophys.hh" 51#include "cpu/base.hh" 52#include "cpu/simple_thread.hh" 53#include "cpu/static_inst.hh" 54#include "cpu/thread_context.hh" | 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 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated --- 36 unchanged lines hidden (view full) --- 47#include <string> 48 49#include "arch/generic/tlb.hh" 50#include "arch/vtophys.hh" 51#include "cpu/base.hh" 52#include "cpu/simple_thread.hh" 53#include "cpu/static_inst.hh" 54#include "cpu/thread_context.hh" |
55#include "cpu/utils.hh" |
|
55#include "params/CheckerCPU.hh" 56#include "sim/full_system.hh" 57 58using namespace std; 59using namespace TheISA; 60 61void 62CheckerCPU::init() --- 71 unchanged lines hidden (view full) --- 134{ 135} 136 137void 138CheckerCPU::unserialize(CheckpointIn &cp) 139{ 140} 141 | 56#include "params/CheckerCPU.hh" 57#include "sim/full_system.hh" 58 59using namespace std; 60using namespace TheISA; 61 62void 63CheckerCPU::init() --- 71 unchanged lines hidden (view full) --- 135{ 136} 137 138void 139CheckerCPU::unserialize(CheckpointIn &cp) 140{ 141} 142 |
143RequestPtr 144CheckerCPU::genMemFragmentRequest(Addr frag_addr, int size, 145 Request::Flags flags, 146 const std::vector<bool>& byte_enable, 147 int& frag_size, int& size_left) const 148{ 149 frag_size = std::min( 150 cacheLineSize() - addrBlockOffset(frag_addr, cacheLineSize()), 151 (Addr) size_left); 152 size_left -= frag_size; 153 154 RequestPtr mem_req; 155 156 if (!byte_enable.empty()) { 157 // Set up byte-enable mask for the current fragment 158 auto it_start = byte_enable.cbegin() + (size - (frag_size + 159 size_left)); 160 auto it_end = byte_enable.cbegin() + (size - size_left); 161 if (isAnyActiveElement(it_start, it_end)) { 162 mem_req = std::make_shared<Request>(0, frag_addr, frag_size, 163 flags, masterId, thread->pcState().instAddr(), 164 tc->contextId()); 165 mem_req->setByteEnable(std::vector<bool>(it_start, it_end)); 166 } 167 } else { 168 mem_req = std::make_shared<Request>(0, frag_addr, frag_size, 169 flags, masterId, thread->pcState().instAddr(), 170 tc->contextId()); 171 } 172 173 return mem_req; 174} 175 |
|
142Fault 143CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, | 176Fault 177CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, |
144 Request::Flags flags) | 178 Request::Flags flags, 179 const std::vector<bool>& byteEnable) |
145{ 146 Fault fault = NoFault; | 180{ 181 Fault fault = NoFault; |
147 int fullSize = size; 148 Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); | |
149 bool checked_flags = false; 150 bool flags_match = true; 151 Addr pAddr = 0x0; 152 | 182 bool checked_flags = false; 183 bool flags_match = true; 184 Addr pAddr = 0x0; 185 |
186 Addr frag_addr = addr; 187 int frag_size = 0; 188 int size_left = size; 189 bool predicate; |
|
153 | 190 |
154 if (secondAddr > addr) 155 size = secondAddr - addr; 156 | |
157 // Need to account for multiple accesses like the Atomic and TimingSimple 158 while (1) { | 191 // Need to account for multiple accesses like the Atomic and TimingSimple 192 while (1) { |
159 auto mem_req = std::make_shared<Request>( 160 0, addr, size, flags, masterId, 161 thread->pcState().instAddr(), tc->contextId()); | 193 RequestPtr mem_req = genMemFragmentRequest(frag_addr, size, flags, 194 byteEnable, frag_size, 195 size_left); |
162 | 196 |
197 predicate = (mem_req != nullptr); 198 |
|
163 // translate to physical address | 199 // translate to physical address |
164 fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Read); | 200 if (predicate) { 201 fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Read); 202 } |
165 | 203 |
166 if (!checked_flags && fault == NoFault && unverifiedReq) { | 204 if (predicate && !checked_flags && fault == NoFault && unverifiedReq) { |
167 flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(), 168 mem_req->getPaddr(), mem_req->getFlags()); 169 pAddr = mem_req->getPaddr(); 170 checked_flags = true; 171 } 172 173 // Now do the access | 205 flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(), 206 mem_req->getPaddr(), mem_req->getFlags()); 207 pAddr = mem_req->getPaddr(); 208 checked_flags = true; 209 } 210 211 // Now do the access |
174 if (fault == NoFault && | 212 if (predicate && fault == NoFault && |
175 !mem_req->getFlags().isSet(Request::NO_ACCESS)) { 176 PacketPtr pkt = Packet::createRead(mem_req); 177 178 pkt->dataStatic(data); 179 180 if (!(mem_req->isUncacheable() || mem_req->isMmappedIpr())) { 181 // Access memory to see if we have the same data 182 dcachePort->sendFunctional(pkt); 183 } else { 184 // Assume the data is correct if it's an uncached access | 213 !mem_req->getFlags().isSet(Request::NO_ACCESS)) { 214 PacketPtr pkt = Packet::createRead(mem_req); 215 216 pkt->dataStatic(data); 217 218 if (!(mem_req->isUncacheable() || mem_req->isMmappedIpr())) { 219 // Access memory to see if we have the same data 220 dcachePort->sendFunctional(pkt); 221 } else { 222 // Assume the data is correct if it's an uncached access |
185 memcpy(data, unverifiedMemData, size); | 223 memcpy(data, unverifiedMemData, frag_size); |
186 } 187 188 delete pkt; 189 } 190 191 if (fault != NoFault) { 192 if (mem_req->isPrefetch()) { 193 fault = NoFault; 194 } 195 break; 196 } 197 198 //If we don't need to access a second cache line, stop now. | 224 } 225 226 delete pkt; 227 } 228 229 if (fault != NoFault) { 230 if (mem_req->isPrefetch()) { 231 fault = NoFault; 232 } 233 break; 234 } 235 236 //If we don't need to access a second cache line, stop now. |
199 if (secondAddr <= addr) | 237 if (size_left == 0) |
200 { 201 break; 202 } 203 204 // Setup for accessing next cache line | 238 { 239 break; 240 } 241 242 // Setup for accessing next cache line |
205 data += size; 206 unverifiedMemData += size; 207 size = addr + fullSize - secondAddr; 208 addr = secondAddr; | 243 frag_addr += frag_size; 244 data += frag_size; 245 unverifiedMemData += frag_size; |
209 } 210 211 if (!flags_match) { 212 warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n", 213 curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), | 246 } 247 248 if (!flags_match) { 249 warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n", 250 curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), |
214 unverifiedReq->getFlags(), addr, pAddr, flags); | 251 unverifiedReq->getFlags(), frag_addr, pAddr, flags); |
215 handleError(); 216 } 217 218 return fault; 219} 220 221Fault 222CheckerCPU::writeMem(uint8_t *data, unsigned size, | 252 handleError(); 253 } 254 255 return fault; 256} 257 258Fault 259CheckerCPU::writeMem(uint8_t *data, unsigned size, |
223 Addr addr, Request::Flags flags, uint64_t *res) | 260 Addr addr, Request::Flags flags, uint64_t *res, 261 const std::vector<bool>& byteEnable) |
224{ | 262{ |
263 assert(byteEnable.empty() || byteEnable.size() == size); 264 |
|
225 Fault fault = NoFault; 226 bool checked_flags = false; 227 bool flags_match = true; 228 Addr pAddr = 0x0; 229 static uint8_t zero_data[64] = {}; 230 | 265 Fault fault = NoFault; 266 bool checked_flags = false; 267 bool flags_match = true; 268 Addr pAddr = 0x0; 269 static uint8_t zero_data[64] = {}; 270 |
231 int fullSize = size; | 271 Addr frag_addr = addr; 272 int frag_size = 0; 273 int size_left = size; 274 bool predicate; |
232 | 275 |
233 Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); 234 235 if (secondAddr > addr) 236 size = secondAddr - addr; 237 | |
238 // Need to account for a multiple access like Atomic and Timing CPUs 239 while (1) { | 276 // Need to account for a multiple access like Atomic and Timing CPUs 277 while (1) { |
240 auto mem_req = std::make_shared<Request>( 241 0, addr, size, flags, masterId, 242 thread->pcState().instAddr(), tc->contextId()); | 278 RequestPtr mem_req = genMemFragmentRequest(frag_addr, size, flags, 279 byteEnable, frag_size, 280 size_left); |
243 | 281 |
244 // translate to physical address 245 fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Write); | 282 predicate = (mem_req != nullptr); |
246 | 283 |
247 if (!checked_flags && fault == NoFault && unverifiedReq) { | 284 if (predicate) { 285 fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Write); 286 } 287 288 if (predicate && !checked_flags && fault == NoFault && unverifiedReq) { |
248 flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(), 249 mem_req->getPaddr(), mem_req->getFlags()); 250 pAddr = mem_req->getPaddr(); 251 checked_flags = true; 252 } 253 254 /* 255 * We don't actually check memory for the store because there 256 * is no guarantee it has left the lsq yet, and therefore we 257 * can't verify the memory on stores without lsq snooping 258 * enabled. This is left as future work for the Checker: LSQ snooping 259 * and memory validation after stores have committed. 260 */ 261 bool was_prefetch = mem_req->isPrefetch(); 262 263 //If we don't need to access a second cache line, stop now. | 289 flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(), 290 mem_req->getPaddr(), mem_req->getFlags()); 291 pAddr = mem_req->getPaddr(); 292 checked_flags = true; 293 } 294 295 /* 296 * We don't actually check memory for the store because there 297 * is no guarantee it has left the lsq yet, and therefore we 298 * can't verify the memory on stores without lsq snooping 299 * enabled. This is left as future work for the Checker: LSQ snooping 300 * and memory validation after stores have committed. 301 */ 302 bool was_prefetch = mem_req->isPrefetch(); 303 304 //If we don't need to access a second cache line, stop now. |
264 if (fault != NoFault || secondAddr <= addr) | 305 if (fault != NoFault || size_left == 0) |
265 { 266 if (fault != NoFault && was_prefetch) { 267 fault = NoFault; 268 } 269 break; 270 } 271 | 306 { 307 if (fault != NoFault && was_prefetch) { 308 fault = NoFault; 309 } 310 break; 311 } 312 |
272 //Update size and access address 273 size = addr + fullSize - secondAddr; 274 //And access the right address. 275 addr = secondAddr; | 313 frag_addr += frag_size; |
276 } 277 278 if (!flags_match) { 279 warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n", 280 curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), | 314 } 315 316 if (!flags_match) { 317 warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n", 318 curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), |
281 unverifiedReq->getFlags(), addr, pAddr, flags); | 319 unverifiedReq->getFlags(), frag_addr, pAddr, flags); |
282 handleError(); 283 } 284 285 // Assume the result was the same as the one passed in. This checker 286 // doesn't check if the SC should succeed or fail, it just checks the 287 // value. 288 if (unverifiedReq && res && unverifiedReq->extraDataValid()) 289 *res = unverifiedReq->getExtraData(); --- 9 unchanged lines hidden (view full) --- 299 unverifiedReq->getExtraData() : true; 300 } 301 302 // If the request is to ZERO a cache block, there is no data to check 303 // against, but it's all zero. We need something to compare to, so use a 304 // const set of zeros. 305 if (flags & Request::STORE_NO_DATA) { 306 assert(!data); | 320 handleError(); 321 } 322 323 // Assume the result was the same as the one passed in. This checker 324 // doesn't check if the SC should succeed or fail, it just checks the 325 // value. 326 if (unverifiedReq && res && unverifiedReq->extraDataValid()) 327 *res = unverifiedReq->getExtraData(); --- 9 unchanged lines hidden (view full) --- 337 unverifiedReq->getExtraData() : true; 338 } 339 340 // If the request is to ZERO a cache block, there is no data to check 341 // against, but it's all zero. We need something to compare to, so use a 342 // const set of zeros. 343 if (flags & Request::STORE_NO_DATA) { 344 assert(!data); |
307 assert(sizeof(zero_data) <= fullSize); | 345 assert(sizeof(zero_data) <= size); |
308 data = zero_data; 309 } 310 311 if (unverifiedReq && unverifiedMemData && | 346 data = zero_data; 347 } 348 349 if (unverifiedReq && unverifiedMemData && |
312 memcmp(data, unverifiedMemData, fullSize) && extraData) { | 350 memcmp(data, unverifiedMemData, size) && extraData) { |
313 warn("%lli: Store value does not match value sent to memory! " 314 "data: %#x inst_data: %#x", curTick(), data, 315 unverifiedMemData); 316 handleError(); 317 } 318 319 return fault; 320} --- 34 unchanged lines hidden --- | 351 warn("%lli: Store value does not match value sent to memory! " 352 "data: %#x inst_data: %#x", curTick(), data, 353 unverifiedMemData); 354 handleError(); 355 } 356 357 return fault; 358} --- 34 unchanged lines hidden --- |