abstract_mem.cc revision 2665
12207SN/A/* 22207SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 32207SN/A * All rights reserved. 42207SN/A * 52207SN/A * Redistribution and use in source and binary forms, with or without 62207SN/A * modification, are permitted provided that the following conditions are 72207SN/A * met: redistributions of source code must retain the above copyright 82207SN/A * notice, this list of conditions and the following disclaimer; 92207SN/A * redistributions in binary form must reproduce the above copyright 102207SN/A * notice, this list of conditions and the following disclaimer in the 112207SN/A * documentation and/or other materials provided with the distribution; 122207SN/A * neither the name of the copyright holders nor the names of its 132207SN/A * contributors may be used to endorse or promote products derived from 142207SN/A * this software without specific prior written permission. 152207SN/A * 162207SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172207SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182207SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192207SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202207SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212207SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222207SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232207SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242207SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252207SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262207SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292665Ssaidi@eecs.umich.edu */ 302207SN/A 312207SN/A#include <sys/types.h> 323589Sgblack@eecs.umich.edu#include <sys/mman.h> 334111Sgblack@eecs.umich.edu#include <errno.h> 342474SN/A#include <fcntl.h> 352207SN/A#include <unistd.h> 363760Sgblack@eecs.umich.edu#include <zlib.h> 372454SN/A 382976Sgblack@eecs.umich.edu#include <iostream> 392454SN/A#include <string> 402680Sktlim@umich.edu 412561SN/A 424434Ssaidi@eecs.umich.edu#include "base/misc.hh" 432561SN/A#include "config/full_system.hh" 442474SN/A#include "mem/packet_impl.hh" 452207SN/A#include "mem/physical.hh" 462458SN/A#include "sim/host.hh" 472474SN/A#include "sim/builder.hh" 482458SN/A#include "sim/eventq.hh" 492207SN/A#include "arch/isa_traits.hh" 505154Sgblack@eecs.umich.edu 515285Sgblack@eecs.umich.edu 525285Sgblack@eecs.umich.eduusing namespace std; 532474SN/Ausing namespace TheISA; 542474SN/A 552474SN/APhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m) 562474SN/A : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m) 572474SN/A{ 582474SN/A 592474SN/A this->setFlags(AutoDelete); 602474SN/A} 613415Sgblack@eecs.umich.edu 623415Sgblack@eecs.umich.eduvoid 633415Sgblack@eecs.umich.eduPhysicalMemory::MemResponseEvent::process() 643415Sgblack@eecs.umich.edu{ 652474SN/A memoryPort->sendTiming(pkt); 662474SN/A} 674111Sgblack@eecs.umich.edu 684111Sgblack@eecs.umich.educonst char * 694111Sgblack@eecs.umich.eduPhysicalMemory::MemResponseEvent::description() 704111Sgblack@eecs.umich.edu{ 715128Sgblack@eecs.umich.edu return "Physical Memory Timing Access respnse event"; 725128Sgblack@eecs.umich.edu} 735128Sgblack@eecs.umich.edu 745128Sgblack@eecs.umich.eduPhysicalMemory::PhysicalMemory(const string &n, Tick latency) 755128Sgblack@eecs.umich.edu : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency) 765128Sgblack@eecs.umich.edu{ 775128Sgblack@eecs.umich.edu // Hardcoded to 128 MB for now. 784111Sgblack@eecs.umich.edu pmem_size = 1 << 27; 795128Sgblack@eecs.umich.edu 805128Sgblack@eecs.umich.edu if (pmem_size % TheISA::PageBytes != 0) 815128Sgblack@eecs.umich.edu panic("Memory Size not divisible by page size\n"); 825128Sgblack@eecs.umich.edu 835128Sgblack@eecs.umich.edu int map_flags = MAP_ANON | MAP_PRIVATE; 845128Sgblack@eecs.umich.edu pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, 855128Sgblack@eecs.umich.edu map_flags, -1, 0); 865128Sgblack@eecs.umich.edu 875128Sgblack@eecs.umich.edu if (pmem_addr == (void *)MAP_FAILED) { 885128Sgblack@eecs.umich.edu perror("mmap"); 895128Sgblack@eecs.umich.edu fatal("Could not mmap!\n"); 905128Sgblack@eecs.umich.edu } 915128Sgblack@eecs.umich.edu 925128Sgblack@eecs.umich.edu page_ptr = 0; 935128Sgblack@eecs.umich.edu} 945128Sgblack@eecs.umich.edu 955128Sgblack@eecs.umich.eduvoid 965128Sgblack@eecs.umich.eduPhysicalMemory::init() 975128Sgblack@eecs.umich.edu{ 985128Sgblack@eecs.umich.edu if (!port) 995128Sgblack@eecs.umich.edu panic("PhysicalMemory not connected to anything!"); 1005128Sgblack@eecs.umich.edu port->sendStatusChange(Port::RangeChange); 1015128Sgblack@eecs.umich.edu} 1025128Sgblack@eecs.umich.edu 1035128Sgblack@eecs.umich.eduPhysicalMemory::~PhysicalMemory() 1044111Sgblack@eecs.umich.edu{ 1054111Sgblack@eecs.umich.edu if (pmem_addr) 1064111Sgblack@eecs.umich.edu munmap(pmem_addr, pmem_size); 1074111Sgblack@eecs.umich.edu //Remove memPorts? 1084111Sgblack@eecs.umich.edu} 1094111Sgblack@eecs.umich.edu 1102474SN/AAddr 1115285Sgblack@eecs.umich.eduPhysicalMemory::new_page() 1124111Sgblack@eecs.umich.edu{ 1135285Sgblack@eecs.umich.edu Addr return_addr = page_ptr << LogVMPageSize; 1144111Sgblack@eecs.umich.edu return_addr += base_addr; 1154111Sgblack@eecs.umich.edu 1164111Sgblack@eecs.umich.edu ++page_ptr; 1172646Ssaidi@eecs.umich.edu return return_addr; 1184172Ssaidi@eecs.umich.edu} 1192646Ssaidi@eecs.umich.edu 1204172Ssaidi@eecs.umich.eduint 1214997Sgblack@eecs.umich.eduPhysicalMemory::deviceBlockSize() 1222561SN/A{ 1232561SN/A //Can accept anysize request 1242561SN/A return 0; 1252561SN/A} 1262561SN/A 1274172Ssaidi@eecs.umich.edubool 1283761Sgblack@eecs.umich.eduPhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort) 1292561SN/A{ 1304172Ssaidi@eecs.umich.edu doFunctionalAccess(pkt); 1313761Sgblack@eecs.umich.edu 1322561SN/A // turn packet around to go back to requester 1334172Ssaidi@eecs.umich.edu pkt->makeTimingResponse(); 1343761Sgblack@eecs.umich.edu MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort); 1352561SN/A response->schedule(curTick + lat); 1364172Ssaidi@eecs.umich.edu 1373761Sgblack@eecs.umich.edu return true; 1382561SN/A} 1394172Ssaidi@eecs.umich.edu 1403415Sgblack@eecs.umich.eduTick 1414172Ssaidi@eecs.umich.eduPhysicalMemory::doAtomicAccess(Packet *pkt) 1423761Sgblack@eecs.umich.edu{ 1433415Sgblack@eecs.umich.edu doFunctionalAccess(pkt); 1444172Ssaidi@eecs.umich.edu return lat; 1453589Sgblack@eecs.umich.edu} 1464172Ssaidi@eecs.umich.edu 1474997Sgblack@eecs.umich.eduvoid 1484997Sgblack@eecs.umich.eduPhysicalMemory::doFunctionalAccess(Packet *pkt) 1494997Sgblack@eecs.umich.edu{ 1504997Sgblack@eecs.umich.edu assert(pkt->getAddr() + pkt->getSize() < pmem_size); 1514997Sgblack@eecs.umich.edu 1524997Sgblack@eecs.umich.edu switch (pkt->cmd) { 1532474SN/A case Packet::ReadReq: 1542474SN/A memcpy(pkt->getPtr<uint8_t>(), 1555285Sgblack@eecs.umich.edu pmem_addr + pkt->getAddr() - base_addr, 1565285Sgblack@eecs.umich.edu pkt->getSize()); 1572585SN/A break; 1585285Sgblack@eecs.umich.edu case Packet::WriteReq: 1595285Sgblack@eecs.umich.edu memcpy(pmem_addr + pkt->getAddr() - base_addr, 1602585SN/A pkt->getPtr<uint8_t>(), 1615285Sgblack@eecs.umich.edu pkt->getSize()); 1625285Sgblack@eecs.umich.edu // temporary hack: will need to add real LL/SC implementation 1635285Sgblack@eecs.umich.edu // for cacheless systems later. 1645285Sgblack@eecs.umich.edu if (pkt->req->getFlags() & LOCKED) { 1655285Sgblack@eecs.umich.edu pkt->req->setScResult(1); 1665285Sgblack@eecs.umich.edu } 1674111Sgblack@eecs.umich.edu break; 1683415Sgblack@eecs.umich.edu default: 1692561SN/A panic("unimplemented"); 1705285Sgblack@eecs.umich.edu } 1712561SN/A 1725285Sgblack@eecs.umich.edu pkt->result = Packet::Success; 1735285Sgblack@eecs.umich.edu} 1745285Sgblack@eecs.umich.edu 1755285Sgblack@eecs.umich.eduPort * 1765285Sgblack@eecs.umich.eduPhysicalMemory::getPort(const std::string &if_name) 1775285Sgblack@eecs.umich.edu{ 1785285Sgblack@eecs.umich.edu if (if_name == "") { 1795285Sgblack@eecs.umich.edu if (port != NULL) 1805285Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: additional port requested to memory!"); 1815285Sgblack@eecs.umich.edu port = new MemoryPort(name() + "-port", this); 1825285Sgblack@eecs.umich.edu return port; 1835285Sgblack@eecs.umich.edu } else if (if_name == "functional") { 1845285Sgblack@eecs.umich.edu /* special port for functional writes at startup. */ 1855285Sgblack@eecs.umich.edu return new MemoryPort(name() + "-funcport", this); 1865285Sgblack@eecs.umich.edu } else { 1875285Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 1885285Sgblack@eecs.umich.edu } 1895285Sgblack@eecs.umich.edu} 1905285Sgblack@eecs.umich.edu 1915285Sgblack@eecs.umich.eduvoid 1922474SN/APhysicalMemory::recvStatusChange(Port::Status status) 1933044Sgblack@eecs.umich.edu{ 1943044Sgblack@eecs.umich.edu} 1953044Sgblack@eecs.umich.edu 1963044Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 1973044Sgblack@eecs.umich.edu PhysicalMemory *_memory) 1983044Sgblack@eecs.umich.edu : Port(_name), memory(_memory) 1995285Sgblack@eecs.umich.edu{ } 2005285Sgblack@eecs.umich.edu 2015285Sgblack@eecs.umich.eduvoid 2022561SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 2032561SN/A{ 2042561SN/A memory->recvStatusChange(status); 2052561SN/A} 2062585SN/A 2072585SN/Avoid 2082585SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 2092585SN/A AddrRangeList &snoop) 2102585SN/A{ 2112585SN/A memory->getAddressRanges(resp, snoop); 2122585SN/A} 2132585SN/A 2142585SN/Avoid 2152585SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 2162585SN/A{ 2172585SN/A snoop.clear(); 2182585SN/A resp.clear(); 2192585SN/A resp.push_back(RangeSize(base_addr, pmem_size)); 2202585SN/A} 2212585SN/A 2222585SN/Aint 2232585SN/APhysicalMemory::MemoryPort::deviceBlockSize() 2242585SN/A{ 2252585SN/A return memory->deviceBlockSize(); 2262585SN/A} 2272976Sgblack@eecs.umich.edu 2282976Sgblack@eecs.umich.edubool 2292976Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvTiming(Packet *pkt) 2302976Sgblack@eecs.umich.edu{ 2312976Sgblack@eecs.umich.edu return memory->doTimingAccess(pkt, this); 2322976Sgblack@eecs.umich.edu} 2334793Sgblack@eecs.umich.edu 2342976Sgblack@eecs.umich.eduTick 2354793Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvAtomic(Packet *pkt) 2362976Sgblack@eecs.umich.edu{ 2372976Sgblack@eecs.umich.edu return memory->doAtomicAccess(pkt); 2384793Sgblack@eecs.umich.edu} 2392976Sgblack@eecs.umich.edu 2402976Sgblack@eecs.umich.eduvoid 2414793Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvFunctional(Packet *pkt) 2422976Sgblack@eecs.umich.edu{ 2434793Sgblack@eecs.umich.edu memory->doFunctionalAccess(pkt); 2442976Sgblack@eecs.umich.edu} 2454793Sgblack@eecs.umich.edu 2462976Sgblack@eecs.umich.edu 2472976Sgblack@eecs.umich.edu 2482976Sgblack@eecs.umich.eduvoid 2494793Sgblack@eecs.umich.eduPhysicalMemory::serialize(ostream &os) 2502976Sgblack@eecs.umich.edu{ 2514793Sgblack@eecs.umich.edu gzFile compressedMem; 2522976Sgblack@eecs.umich.edu string filename = name() + ".physmem"; 2534793Sgblack@eecs.umich.edu 2542976Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pmem_size); 2554793Sgblack@eecs.umich.edu SERIALIZE_SCALAR(filename); 2564793Sgblack@eecs.umich.edu 2574793Sgblack@eecs.umich.edu // write memory file 2584793Sgblack@eecs.umich.edu string thefile = Checkpoint::dir() + "/" + filename.c_str(); 2592976Sgblack@eecs.umich.edu int fd = creat(thefile.c_str(), 0664); 2604793Sgblack@eecs.umich.edu if (fd < 0) { 2612976Sgblack@eecs.umich.edu perror("creat"); 2622585SN/A fatal("Can't open physical memory checkpoint file '%s'\n", filename); 2632561SN/A } 2642561SN/A 2654164Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "wb"); 2664164Sgblack@eecs.umich.edu if (compressedMem == NULL) 2674111Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 2684111Sgblack@eecs.umich.edu filename); 2694111Sgblack@eecs.umich.edu 2704111Sgblack@eecs.umich.edu if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) { 2714111Sgblack@eecs.umich.edu fatal("Write failed on physical memory checkpoint file '%s'\n", 2724111Sgblack@eecs.umich.edu filename); 2734111Sgblack@eecs.umich.edu } 2744111Sgblack@eecs.umich.edu 2754111Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 2764111Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 2774111Sgblack@eecs.umich.edu filename); 2784111Sgblack@eecs.umich.edu} 2794111Sgblack@eecs.umich.edu 2804111Sgblack@eecs.umich.eduvoid 2814164Sgblack@eecs.umich.eduPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 2824111Sgblack@eecs.umich.edu{ 2834164Sgblack@eecs.umich.edu gzFile compressedMem; 2844164Sgblack@eecs.umich.edu long *tempPage; 2854111Sgblack@eecs.umich.edu long *pmem_current; 2864164Sgblack@eecs.umich.edu uint64_t curSize; 2874111Sgblack@eecs.umich.edu uint32_t bytesRead; 2885285Sgblack@eecs.umich.edu const int chunkSize = 16384; 2894111Sgblack@eecs.umich.edu 2904111Sgblack@eecs.umich.edu 2914111Sgblack@eecs.umich.edu // unmap file that was mmaped in the constructor 2924111Sgblack@eecs.umich.edu munmap(pmem_addr, pmem_size); 2934111Sgblack@eecs.umich.edu 2944111Sgblack@eecs.umich.edu string filename; 2954111Sgblack@eecs.umich.edu 2964111Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(pmem_size); 2974111Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(filename); 2984164Sgblack@eecs.umich.edu 2994111Sgblack@eecs.umich.edu filename = cp->cptDir + "/" + filename; 3004111Sgblack@eecs.umich.edu 3014111Sgblack@eecs.umich.edu // mmap memoryfile 3024111Sgblack@eecs.umich.edu int fd = open(filename.c_str(), O_RDONLY); 3034111Sgblack@eecs.umich.edu if (fd < 0) { 3044111Sgblack@eecs.umich.edu perror("open"); 3054111Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'", filename); 3064111Sgblack@eecs.umich.edu } 3074111Sgblack@eecs.umich.edu 3084111Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "rb"); 3095285Sgblack@eecs.umich.edu if (compressedMem == NULL) 3104111Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 3114111Sgblack@eecs.umich.edu filename); 3124111Sgblack@eecs.umich.edu 3134111Sgblack@eecs.umich.edu 3145285Sgblack@eecs.umich.edu pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, 3155285Sgblack@eecs.umich.edu MAP_ANON | MAP_PRIVATE, -1, 0); 3165285Sgblack@eecs.umich.edu 3175285Sgblack@eecs.umich.edu if (pmem_addr == (void *)MAP_FAILED) { 3185285Sgblack@eecs.umich.edu perror("mmap"); 3194117Sgblack@eecs.umich.edu fatal("Could not mmap physical memory!\n"); 3204117Sgblack@eecs.umich.edu } 3215285Sgblack@eecs.umich.edu 3225285Sgblack@eecs.umich.edu curSize = 0; 3235285Sgblack@eecs.umich.edu tempPage = (long*)malloc(chunkSize); 3245285Sgblack@eecs.umich.edu if (tempPage == NULL) 3254111Sgblack@eecs.umich.edu fatal("Unable to malloc memory to read file %s\n", filename); 3264111Sgblack@eecs.umich.edu 3275285Sgblack@eecs.umich.edu /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 3285285Sgblack@eecs.umich.edu while (curSize < pmem_size) { 3295285Sgblack@eecs.umich.edu bytesRead = gzread(compressedMem, tempPage, chunkSize); 3305285Sgblack@eecs.umich.edu if (bytesRead != chunkSize && bytesRead != pmem_size - curSize) 3315285Sgblack@eecs.umich.edu fatal("Read failed on physical memory checkpoint file '%s'" 3325285Sgblack@eecs.umich.edu " got %d bytes, expected %d or %d bytes\n", 3335285Sgblack@eecs.umich.edu filename, bytesRead, chunkSize, pmem_size-curSize); 3345285Sgblack@eecs.umich.edu 3355285Sgblack@eecs.umich.edu assert(bytesRead % sizeof(long) == 0); 3364111Sgblack@eecs.umich.edu 3374111Sgblack@eecs.umich.edu for (int x = 0; x < bytesRead/sizeof(long); x++) 3384111Sgblack@eecs.umich.edu { 3394111Sgblack@eecs.umich.edu if (*(tempPage+x) != 0) { 3405285Sgblack@eecs.umich.edu pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long)); 3415285Sgblack@eecs.umich.edu *pmem_current = *(tempPage+x); 3424111Sgblack@eecs.umich.edu } 3434111Sgblack@eecs.umich.edu } 3444111Sgblack@eecs.umich.edu curSize += bytesRead; 3454111Sgblack@eecs.umich.edu } 3464111Sgblack@eecs.umich.edu 3474111Sgblack@eecs.umich.edu free(tempPage); 3484111Sgblack@eecs.umich.edu 3494111Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 3504111Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 3514111Sgblack@eecs.umich.edu filename); 3524111Sgblack@eecs.umich.edu 3534111Sgblack@eecs.umich.edu} 3544111Sgblack@eecs.umich.edu 3554111Sgblack@eecs.umich.edu 3564111Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 3574111Sgblack@eecs.umich.edu 3584111Sgblack@eecs.umich.edu Param<string> file; 3595285Sgblack@eecs.umich.edu Param<Range<Addr> > range; 3604111Sgblack@eecs.umich.edu Param<Tick> latency; 3615285Sgblack@eecs.umich.edu 3624111Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 3634111Sgblack@eecs.umich.edu 3644111Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 3654117Sgblack@eecs.umich.edu 3664117Sgblack@eecs.umich.edu INIT_PARAM_DFLT(file, "memory mapped file", ""), 3674111Sgblack@eecs.umich.edu INIT_PARAM(range, "Device Address Range"), 3684111Sgblack@eecs.umich.edu INIT_PARAM(latency, "Memory access latency") 3694111Sgblack@eecs.umich.edu 3705285Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 3715285Sgblack@eecs.umich.edu 3725285Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(PhysicalMemory) 3734111Sgblack@eecs.umich.edu{ 3745285Sgblack@eecs.umich.edu 3754111Sgblack@eecs.umich.edu return new PhysicalMemory(getInstanceName(), latency); 3764111Sgblack@eecs.umich.edu} 3774772Sgblack@eecs.umich.edu 3784772Sgblack@eecs.umich.eduREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 3794772Sgblack@eecs.umich.edu