physical.cc revision 8923:820111f58fbb
110453SAndrew.Bardsley@arm.com/* 211235Sandreas.sandberg@arm.com * Copyright (c) 2010-2011 ARM Limited 310453SAndrew.Bardsley@arm.com * All rights reserved 410453SAndrew.Bardsley@arm.com * 510453SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall 610453SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual 710453SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating 810453SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software 910453SAndrew.Bardsley@arm.com * licensed hereunder. You may use the software subject to the license 1010453SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated 1110453SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software, 1210453SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form. 1310453SAndrew.Bardsley@arm.com * 1410453SAndrew.Bardsley@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 1510453SAndrew.Bardsley@arm.com * All rights reserved. 1610453SAndrew.Bardsley@arm.com * 1710453SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without 1810453SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are 1910453SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright 2010453SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer; 2110453SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright 2210453SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the 2310453SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution; 2410453SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its 2510453SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from 2610453SAndrew.Bardsley@arm.com * this software without specific prior written permission. 2710453SAndrew.Bardsley@arm.com * 2810453SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2910453SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3010453SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3110453SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3210453SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3310453SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3410453SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3510453SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3610453SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3710453SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3810453SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3910453SAndrew.Bardsley@arm.com * 4010453SAndrew.Bardsley@arm.com * Authors: Ron Dreslinski 4110453SAndrew.Bardsley@arm.com * Ali Saidi 4210453SAndrew.Bardsley@arm.com */ 4310453SAndrew.Bardsley@arm.com 4411235Sandreas.sandberg@arm.com#include <sys/mman.h> 4511235Sandreas.sandberg@arm.com#include <sys/types.h> 4611235Sandreas.sandberg@arm.com#include <sys/user.h> 4711235Sandreas.sandberg@arm.com#include <fcntl.h> 4811235Sandreas.sandberg@arm.com#include <unistd.h> 4910453SAndrew.Bardsley@arm.com#include <zlib.h> 5010453SAndrew.Bardsley@arm.com 5110453SAndrew.Bardsley@arm.com#include <cerrno> 5210453SAndrew.Bardsley@arm.com#include <cstdio> 5311235Sandreas.sandberg@arm.com#include <iostream> 5410453SAndrew.Bardsley@arm.com#include <string> 5510453SAndrew.Bardsley@arm.com 5611235Sandreas.sandberg@arm.com#include "arch/isa_traits.hh" 5710453SAndrew.Bardsley@arm.com#include "arch/registers.hh" 5810476Sandreas.hansson@arm.com#include "base/intmath.hh" 5910453SAndrew.Bardsley@arm.com#include "base/misc.hh" 6010453SAndrew.Bardsley@arm.com#include "base/random.hh" 6110453SAndrew.Bardsley@arm.com#include "base/types.hh" 6211235Sandreas.sandberg@arm.com#include "config/the_isa.hh" 6311235Sandreas.sandberg@arm.com#include "debug/LLSC.hh" 6411235Sandreas.sandberg@arm.com#include "debug/MemoryAccess.hh" 6511235Sandreas.sandberg@arm.com#include "mem/packet_access.hh" 6611235Sandreas.sandberg@arm.com#include "mem/physical.hh" 6711235Sandreas.sandberg@arm.com#include "sim/eventq.hh" 6811235Sandreas.sandberg@arm.com 6911235Sandreas.sandberg@arm.comusing namespace std; 7011235Sandreas.sandberg@arm.comusing namespace TheISA; 7111235Sandreas.sandberg@arm.com 7211235Sandreas.sandberg@arm.comPhysicalMemory::PhysicalMemory(const Params *p) 7311235Sandreas.sandberg@arm.com : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var), 7411235Sandreas.sandberg@arm.com _size(params()->range.size()), _start(params()->range.start) 7511235Sandreas.sandberg@arm.com{ 7611235Sandreas.sandberg@arm.com if (size() % TheISA::PageBytes != 0) 7711235Sandreas.sandberg@arm.com panic("Memory Size not divisible by page size\n"); 7811235Sandreas.sandberg@arm.com 7911235Sandreas.sandberg@arm.com // create the appropriate number of ports 8011235Sandreas.sandberg@arm.com for (int i = 0; i < p->port_port_connection_count; ++i) { 8111235Sandreas.sandberg@arm.com ports.push_back(new MemoryPort(csprintf("%s-port%d", name(), i), 8211235Sandreas.sandberg@arm.com this)); 8311235Sandreas.sandberg@arm.com } 8411235Sandreas.sandberg@arm.com 8511235Sandreas.sandberg@arm.com if (params()->null) 8611235Sandreas.sandberg@arm.com return; 8711235Sandreas.sandberg@arm.com 8811235Sandreas.sandberg@arm.com 8911235Sandreas.sandberg@arm.com if (params()->file == "") { 9011235Sandreas.sandberg@arm.com int map_flags = MAP_ANON | MAP_PRIVATE; 9111235Sandreas.sandberg@arm.com pmemAddr = (uint8_t *)mmap(NULL, size(), 9211235Sandreas.sandberg@arm.com PROT_READ | PROT_WRITE, map_flags, -1, 0); 9311235Sandreas.sandberg@arm.com } else { 9411235Sandreas.sandberg@arm.com int map_flags = MAP_PRIVATE; 9511235Sandreas.sandberg@arm.com int fd = open(params()->file.c_str(), O_RDONLY); 9611235Sandreas.sandberg@arm.com _size = lseek(fd, 0, SEEK_END); 9711235Sandreas.sandberg@arm.com lseek(fd, 0, SEEK_SET); 9811235Sandreas.sandberg@arm.com pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)), 9911235Sandreas.sandberg@arm.com PROT_READ | PROT_WRITE, map_flags, fd, 0); 10011235Sandreas.sandberg@arm.com } 10111235Sandreas.sandberg@arm.com 10211235Sandreas.sandberg@arm.com if (pmemAddr == (void *)MAP_FAILED) { 10311235Sandreas.sandberg@arm.com perror("mmap"); 10411235Sandreas.sandberg@arm.com if (params()->file == "") 10510453SAndrew.Bardsley@arm.com fatal("Could not mmap!\n"); 10610453SAndrew.Bardsley@arm.com else 10710453SAndrew.Bardsley@arm.com fatal("Could not find file: %s\n", params()->file); 10810453SAndrew.Bardsley@arm.com } 10910453SAndrew.Bardsley@arm.com 11010453SAndrew.Bardsley@arm.com //If requested, initialize all the memory to 0 11110476Sandreas.hansson@arm.com if (p->zero) 11210476Sandreas.hansson@arm.com memset(pmemAddr, 0, size()); 11310453SAndrew.Bardsley@arm.com} 11410453SAndrew.Bardsley@arm.com 11510453SAndrew.Bardsley@arm.comvoid 11610453SAndrew.Bardsley@arm.comPhysicalMemory::init() 11710453SAndrew.Bardsley@arm.com{ 11810453SAndrew.Bardsley@arm.com for (PortIterator p = ports.begin(); p != ports.end(); ++p) { 11910453SAndrew.Bardsley@arm.com if (!(*p)->isConnected()) { 12010453SAndrew.Bardsley@arm.com fatal("PhysicalMemory port %s is unconnected!\n", (*p)->name()); 12110476Sandreas.hansson@arm.com } else { 12210476Sandreas.hansson@arm.com (*p)->sendRangeChange(); 12310453SAndrew.Bardsley@arm.com } 12410453SAndrew.Bardsley@arm.com } 12510453SAndrew.Bardsley@arm.com} 12610453SAndrew.Bardsley@arm.com 12710453SAndrew.Bardsley@arm.comPhysicalMemory::~PhysicalMemory() 12810453SAndrew.Bardsley@arm.com{ 12910453SAndrew.Bardsley@arm.com if (pmemAddr) 13010453SAndrew.Bardsley@arm.com munmap((char*)pmemAddr, size()); 13110476Sandreas.hansson@arm.com} 13210476Sandreas.hansson@arm.com 13310453SAndrew.Bardsley@arm.comvoid 13410453SAndrew.Bardsley@arm.comPhysicalMemory::regStats() 13510453SAndrew.Bardsley@arm.com{ 13610453SAndrew.Bardsley@arm.com using namespace Stats; 13710453SAndrew.Bardsley@arm.com 13810453SAndrew.Bardsley@arm.com bytesRead 13911235Sandreas.sandberg@arm.com .name(name() + ".bytes_read") 14011235Sandreas.sandberg@arm.com .desc("Number of bytes read from this memory") 14111235Sandreas.sandberg@arm.com ; 14211235Sandreas.sandberg@arm.com bytesInstRead 14311235Sandreas.sandberg@arm.com .name(name() + ".bytes_inst_read") 14411235Sandreas.sandberg@arm.com .desc("Number of instructions bytes read from this memory") 14511235Sandreas.sandberg@arm.com ; 14611235Sandreas.sandberg@arm.com bytesWritten 14711235Sandreas.sandberg@arm.com .name(name() + ".bytes_written") 14811235Sandreas.sandberg@arm.com .desc("Number of bytes written to this memory") 14911235Sandreas.sandberg@arm.com ; 15011235Sandreas.sandberg@arm.com numReads 15111235Sandreas.sandberg@arm.com .name(name() + ".num_reads") 15211235Sandreas.sandberg@arm.com .desc("Number of read requests responded to by this memory") 15311235Sandreas.sandberg@arm.com ; 15411235Sandreas.sandberg@arm.com numWrites 15511235Sandreas.sandberg@arm.com .name(name() + ".num_writes") 15611235Sandreas.sandberg@arm.com .desc("Number of write requests responded to by this memory") 15711235Sandreas.sandberg@arm.com ; 15810453SAndrew.Bardsley@arm.com numOther 15910453SAndrew.Bardsley@arm.com .name(name() + ".num_other") 16010453SAndrew.Bardsley@arm.com .desc("Number of other requests responded to by this memory") 16110453SAndrew.Bardsley@arm.com ; 16210453SAndrew.Bardsley@arm.com bwRead 16310453SAndrew.Bardsley@arm.com .name(name() + ".bw_read") 16410453SAndrew.Bardsley@arm.com .desc("Total read bandwidth from this memory (bytes/s)") 16510453SAndrew.Bardsley@arm.com .precision(0) 16610476Sandreas.hansson@arm.com .prereq(bytesRead) 16710476Sandreas.hansson@arm.com ; 16810453SAndrew.Bardsley@arm.com bwInstRead 16910453SAndrew.Bardsley@arm.com .name(name() + ".bw_inst_read") 17010453SAndrew.Bardsley@arm.com .desc("Instruction read bandwidth from this memory (bytes/s)") 17110453SAndrew.Bardsley@arm.com .precision(0) 17210453SAndrew.Bardsley@arm.com .prereq(bytesInstRead) 17310453SAndrew.Bardsley@arm.com ; 17410453SAndrew.Bardsley@arm.com bwWrite 17510453SAndrew.Bardsley@arm.com .name(name() + ".bw_write") 17610453SAndrew.Bardsley@arm.com .desc("Write bandwidth from this memory (bytes/s)") 17710453SAndrew.Bardsley@arm.com .precision(0) 17810453SAndrew.Bardsley@arm.com .prereq(bytesWritten) 17910453SAndrew.Bardsley@arm.com ; 18010453SAndrew.Bardsley@arm.com bwTotal 18110453SAndrew.Bardsley@arm.com .name(name() + ".bw_total") 18210453SAndrew.Bardsley@arm.com .desc("Total bandwidth to/from this memory (bytes/s)") 18310453SAndrew.Bardsley@arm.com .precision(0) 18410453SAndrew.Bardsley@arm.com .prereq(bwTotal) 18510453SAndrew.Bardsley@arm.com ; 18610453SAndrew.Bardsley@arm.com bwRead = bytesRead / simSeconds; 18710453SAndrew.Bardsley@arm.com bwInstRead = bytesInstRead / simSeconds; 18810453SAndrew.Bardsley@arm.com bwWrite = bytesWritten / simSeconds; 18910453SAndrew.Bardsley@arm.com bwTotal = (bytesRead + bytesWritten) / simSeconds; 19010453SAndrew.Bardsley@arm.com} 19110453SAndrew.Bardsley@arm.com 19210453SAndrew.Bardsley@arm.comunsigned 19311235Sandreas.sandberg@arm.comPhysicalMemory::deviceBlockSize() const 19411235Sandreas.sandberg@arm.com{ 19511235Sandreas.sandberg@arm.com //Can accept anysize request 19611235Sandreas.sandberg@arm.com return 0; 19711235Sandreas.sandberg@arm.com} 19811235Sandreas.sandberg@arm.com 19911235Sandreas.sandberg@arm.comTick 20011235Sandreas.sandberg@arm.comPhysicalMemory::calculateLatency(PacketPtr pkt) 20111235Sandreas.sandberg@arm.com{ 20211235Sandreas.sandberg@arm.com Tick latency = lat; 20311235Sandreas.sandberg@arm.com if (lat_var != 0) 20411235Sandreas.sandberg@arm.com latency += random_mt.random<Tick>(0, lat_var); 20511235Sandreas.sandberg@arm.com return latency; 20610453SAndrew.Bardsley@arm.com} 20710453SAndrew.Bardsley@arm.com 20810453SAndrew.Bardsley@arm.com 20910453SAndrew.Bardsley@arm.com 21010453SAndrew.Bardsley@arm.com// Add load-locked to tracking list. Should only be called if the 21110453SAndrew.Bardsley@arm.com// operation is a load and the LLSC flag is set. 212void 213PhysicalMemory::trackLoadLocked(PacketPtr pkt) 214{ 215 Request *req = pkt->req; 216 Addr paddr = LockedAddr::mask(req->getPaddr()); 217 218 // first we check if we already have a locked addr for this 219 // xc. Since each xc only gets one, we just update the 220 // existing record with the new address. 221 list<LockedAddr>::iterator i; 222 223 for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 224 if (i->matchesContext(req)) { 225 DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 226 req->contextId(), paddr); 227 i->addr = paddr; 228 return; 229 } 230 } 231 232 // no record for this xc: need to allocate a new one 233 DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 234 req->contextId(), paddr); 235 lockedAddrList.push_front(LockedAddr(req)); 236} 237 238 239// Called on *writes* only... both regular stores and 240// store-conditional operations. Check for conventional stores which 241// conflict with locked addresses, and for success/failure of store 242// conditionals. 243bool 244PhysicalMemory::checkLockedAddrList(PacketPtr pkt) 245{ 246 Request *req = pkt->req; 247 Addr paddr = LockedAddr::mask(req->getPaddr()); 248 bool isLLSC = pkt->isLLSC(); 249 250 // Initialize return value. Non-conditional stores always 251 // succeed. Assume conditional stores will fail until proven 252 // otherwise. 253 bool success = !isLLSC; 254 255 // Iterate over list. Note that there could be multiple matching 256 // records, as more than one context could have done a load locked 257 // to this location. 258 list<LockedAddr>::iterator i = lockedAddrList.begin(); 259 260 while (i != lockedAddrList.end()) { 261 262 if (i->addr == paddr) { 263 // we have a matching address 264 265 if (isLLSC && i->matchesContext(req)) { 266 // it's a store conditional, and as far as the memory 267 // system can tell, the requesting context's lock is 268 // still valid. 269 DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 270 req->contextId(), paddr); 271 success = true; 272 } 273 274 // Get rid of our record of this lock and advance to next 275 DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 276 i->contextId, paddr); 277 i = lockedAddrList.erase(i); 278 } 279 else { 280 // no match: advance to next record 281 ++i; 282 } 283 } 284 285 if (isLLSC) { 286 req->setExtraData(success ? 1 : 0); 287 } 288 289 return success; 290} 291 292 293#if TRACING_ON 294 295#define CASE(A, T) \ 296 case sizeof(T): \ 297 DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 298 A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 299 break 300 301 302#define TRACE_PACKET(A) \ 303 do { \ 304 switch (pkt->getSize()) { \ 305 CASE(A, uint64_t); \ 306 CASE(A, uint32_t); \ 307 CASE(A, uint16_t); \ 308 CASE(A, uint8_t); \ 309 default: \ 310 DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 311 A, pkt->getSize(), pkt->getAddr()); \ 312 DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\ 313 } \ 314 } while (0) 315 316#else 317 318#define TRACE_PACKET(A) 319 320#endif 321 322Tick 323PhysicalMemory::doAtomicAccess(PacketPtr pkt) 324{ 325 assert(pkt->getAddr() >= start() && 326 pkt->getAddr() + pkt->getSize() <= start() + size()); 327 328 if (pkt->memInhibitAsserted()) { 329 DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 330 pkt->getAddr()); 331 return 0; 332 } 333 334 uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 335 336 if (pkt->cmd == MemCmd::SwapReq) { 337 IntReg overwrite_val; 338 bool overwrite_mem; 339 uint64_t condition_val64; 340 uint32_t condition_val32; 341 342 if (!pmemAddr) 343 panic("Swap only works if there is real memory (i.e. null=False)"); 344 assert(sizeof(IntReg) >= pkt->getSize()); 345 346 overwrite_mem = true; 347 // keep a copy of our possible write value, and copy what is at the 348 // memory address into the packet 349 std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 350 std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 351 352 if (pkt->req->isCondSwap()) { 353 if (pkt->getSize() == sizeof(uint64_t)) { 354 condition_val64 = pkt->req->getExtraData(); 355 overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 356 sizeof(uint64_t)); 357 } else if (pkt->getSize() == sizeof(uint32_t)) { 358 condition_val32 = (uint32_t)pkt->req->getExtraData(); 359 overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 360 sizeof(uint32_t)); 361 } else 362 panic("Invalid size for conditional read/write\n"); 363 } 364 365 if (overwrite_mem) 366 std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 367 368 assert(!pkt->req->isInstFetch()); 369 TRACE_PACKET("Read/Write"); 370 numOther++; 371 } else if (pkt->isRead()) { 372 assert(!pkt->isWrite()); 373 if (pkt->isLLSC()) { 374 trackLoadLocked(pkt); 375 } 376 if (pmemAddr) 377 memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 378 TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 379 numReads++; 380 bytesRead += pkt->getSize(); 381 if (pkt->req->isInstFetch()) 382 bytesInstRead += pkt->getSize(); 383 } else if (pkt->isWrite()) { 384 if (writeOK(pkt)) { 385 if (pmemAddr) 386 memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 387 assert(!pkt->req->isInstFetch()); 388 TRACE_PACKET("Write"); 389 numWrites++; 390 bytesWritten += pkt->getSize(); 391 } 392 } else if (pkt->isInvalidate()) { 393 //upgrade or invalidate 394 if (pkt->needsResponse()) { 395 pkt->makeAtomicResponse(); 396 } 397 } else { 398 panic("unimplemented"); 399 } 400 401 if (pkt->needsResponse()) { 402 pkt->makeAtomicResponse(); 403 } 404 return calculateLatency(pkt); 405} 406 407 408void 409PhysicalMemory::doFunctionalAccess(PacketPtr pkt) 410{ 411 assert(pkt->getAddr() >= start() && 412 pkt->getAddr() + pkt->getSize() <= start() + size()); 413 414 415 uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 416 417 if (pkt->isRead()) { 418 if (pmemAddr) 419 memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 420 TRACE_PACKET("Read"); 421 pkt->makeAtomicResponse(); 422 } else if (pkt->isWrite()) { 423 if (pmemAddr) 424 memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 425 TRACE_PACKET("Write"); 426 pkt->makeAtomicResponse(); 427 } else if (pkt->isPrint()) { 428 Packet::PrintReqState *prs = 429 dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 430 // Need to call printLabels() explicitly since we're not going 431 // through printObj(). 432 prs->printLabels(); 433 // Right now we just print the single byte at the specified address. 434 ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 435 } else { 436 panic("PhysicalMemory: unimplemented functional command %s", 437 pkt->cmdString()); 438 } 439} 440 441 442SlavePort & 443PhysicalMemory::getSlavePort(const std::string &if_name, int idx) 444{ 445 if (if_name != "port") { 446 return MemObject::getSlavePort(if_name, idx); 447 } else { 448 if (idx >= static_cast<int>(ports.size())) { 449 fatal("PhysicalMemory::getSlavePort: unknown index %d\n", idx); 450 } 451 452 return *ports[idx]; 453 } 454} 455 456PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 457 PhysicalMemory *_memory) 458 : SimpleTimingPort(_name, _memory), memory(_memory) 459{ } 460 461AddrRangeList 462PhysicalMemory::MemoryPort::getAddrRanges() 463{ 464 return memory->getAddrRanges(); 465} 466 467AddrRangeList 468PhysicalMemory::getAddrRanges() 469{ 470 AddrRangeList ranges; 471 ranges.push_back(RangeSize(start(), size())); 472 return ranges; 473} 474 475unsigned 476PhysicalMemory::MemoryPort::deviceBlockSize() const 477{ 478 return memory->deviceBlockSize(); 479} 480 481Tick 482PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 483{ 484 return memory->doAtomicAccess(pkt); 485} 486 487void 488PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 489{ 490 pkt->pushLabel(memory->name()); 491 492 if (!queue.checkFunctional(pkt)) { 493 // Default implementation of SimpleTimingPort::recvFunctional() 494 // calls recvAtomic() and throws away the latency; we can save a 495 // little here by just not calculating the latency. 496 memory->doFunctionalAccess(pkt); 497 } 498 499 pkt->popLabel(); 500} 501 502unsigned int 503PhysicalMemory::drain(Event *de) 504{ 505 int count = 0; 506 for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 507 count += (*pi)->drain(de); 508 } 509 510 if (count) 511 changeState(Draining); 512 else 513 changeState(Drained); 514 return count; 515} 516 517void 518PhysicalMemory::serialize(ostream &os) 519{ 520 if (!pmemAddr) 521 return; 522 523 gzFile compressedMem; 524 string filename = name() + ".physmem"; 525 526 SERIALIZE_SCALAR(filename); 527 SERIALIZE_SCALAR(_size); 528 529 // write memory file 530 string thefile = Checkpoint::dir() + "/" + filename.c_str(); 531 int fd = creat(thefile.c_str(), 0664); 532 if (fd < 0) { 533 perror("creat"); 534 fatal("Can't open physical memory checkpoint file '%s'\n", filename); 535 } 536 537 compressedMem = gzdopen(fd, "wb"); 538 if (compressedMem == NULL) 539 fatal("Insufficient memory to allocate compression state for %s\n", 540 filename); 541 542 if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) { 543 fatal("Write failed on physical memory checkpoint file '%s'\n", 544 filename); 545 } 546 547 if (gzclose(compressedMem)) 548 fatal("Close failed on physical memory checkpoint file '%s'\n", 549 filename); 550 551 list<LockedAddr>::iterator i = lockedAddrList.begin(); 552 553 vector<Addr> lal_addr; 554 vector<int> lal_cid; 555 while (i != lockedAddrList.end()) { 556 lal_addr.push_back(i->addr); 557 lal_cid.push_back(i->contextId); 558 i++; 559 } 560 arrayParamOut(os, "lal_addr", lal_addr); 561 arrayParamOut(os, "lal_cid", lal_cid); 562} 563 564void 565PhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 566{ 567 if (!pmemAddr) 568 return; 569 570 gzFile compressedMem; 571 long *tempPage; 572 long *pmem_current; 573 uint64_t curSize; 574 uint32_t bytesRead; 575 const uint32_t chunkSize = 16384; 576 577 string filename; 578 579 UNSERIALIZE_SCALAR(filename); 580 581 filename = cp->cptDir + "/" + filename; 582 583 // mmap memoryfile 584 int fd = open(filename.c_str(), O_RDONLY); 585 if (fd < 0) { 586 perror("open"); 587 fatal("Can't open physical memory checkpoint file '%s'", filename); 588 } 589 590 compressedMem = gzdopen(fd, "rb"); 591 if (compressedMem == NULL) 592 fatal("Insufficient memory to allocate compression state for %s\n", 593 filename); 594 595 // unmap file that was mmapped in the constructor 596 // This is done here to make sure that gzip and open don't muck with our 597 // nice large space of memory before we reallocate it 598 munmap((char*)pmemAddr, size()); 599 600 UNSERIALIZE_SCALAR(_size); 601 if (size() > params()->range.size()) 602 fatal("Memory size has changed! size %lld, param size %lld\n", 603 size(), params()->range.size()); 604 605 pmemAddr = (uint8_t *)mmap(NULL, size(), 606 PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 607 608 if (pmemAddr == (void *)MAP_FAILED) { 609 perror("mmap"); 610 fatal("Could not mmap physical memory!\n"); 611 } 612 613 curSize = 0; 614 tempPage = (long*)malloc(chunkSize); 615 if (tempPage == NULL) 616 fatal("Unable to malloc memory to read file %s\n", filename); 617 618 /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 619 while (curSize < size()) { 620 bytesRead = gzread(compressedMem, tempPage, chunkSize); 621 if (bytesRead == 0) 622 break; 623 624 assert(bytesRead % sizeof(long) == 0); 625 626 for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 627 { 628 if (*(tempPage+x) != 0) { 629 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 630 *pmem_current = *(tempPage+x); 631 } 632 } 633 curSize += bytesRead; 634 } 635 636 free(tempPage); 637 638 if (gzclose(compressedMem)) 639 fatal("Close failed on physical memory checkpoint file '%s'\n", 640 filename); 641 642 vector<Addr> lal_addr; 643 vector<int> lal_cid; 644 arrayParamIn(cp, section, "lal_addr", lal_addr); 645 arrayParamIn(cp, section, "lal_cid", lal_cid); 646 for(int i = 0; i < lal_addr.size(); i++) 647 lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 648} 649 650PhysicalMemory * 651PhysicalMemoryParams::create() 652{ 653 return new PhysicalMemory(this); 654} 655