abstract_mem.cc revision 3170
12623SN/A/* 22623SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 32623SN/A * All rights reserved. 42623SN/A * 52623SN/A * Redistribution and use in source and binary forms, with or without 62623SN/A * modification, are permitted provided that the following conditions are 72623SN/A * met: redistributions of source code must retain the above copyright 82623SN/A * notice, this list of conditions and the following disclaimer; 92623SN/A * redistributions in binary form must reproduce the above copyright 102623SN/A * notice, this list of conditions and the following disclaimer in the 112623SN/A * documentation and/or other materials provided with the distribution; 122623SN/A * neither the name of the copyright holders nor the names of its 132623SN/A * contributors may be used to endorse or promote products derived from 142623SN/A * this software without specific prior written permission. 152623SN/A * 162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292623SN/A * Ali Saidi 302623SN/A */ 313170Sstever@eecs.umich.edu 323806Ssaidi@eecs.umich.edu#include <sys/types.h> 332623SN/A#include <sys/mman.h> 344040Ssaidi@eecs.umich.edu#include <errno.h> 352623SN/A#include <fcntl.h> 362623SN/A#include <unistd.h> 373348Sbinkertn@umich.edu#include <zlib.h> 383348Sbinkertn@umich.edu 394762Snate@binkert.org#include <iostream> 402901Ssaidi@eecs.umich.edu#include <string> 412623SN/A 422623SN/A 432623SN/A#include "base/misc.hh" 442623SN/A#include "config/full_system.hh" 452623SN/A#include "mem/packet_impl.hh" 465606Snate@binkert.org#include "mem/physical.hh" 472623SN/A#include "sim/host.hh" 482623SN/A#include "sim/builder.hh" 492623SN/A#include "sim/eventq.hh" 502623SN/A#include "arch/isa_traits.hh" 512623SN/A 522623SN/A 532623SN/Ausing namespace std; 542623SN/Ausing namespace TheISA; 552623SN/A 562623SN/A 572623SN/APhysicalMemory::PhysicalMemory(Params *p) 585336Shines@cs.fsu.edu : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p) 592623SN/A{ 604873Sstever@eecs.umich.edu if (params()->addrRange.size() % TheISA::PageBytes != 0) 612623SN/A panic("Memory Size not divisible by page size\n"); 622623SN/A 632856Srdreslin@umich.edu int map_flags = MAP_ANON | MAP_PRIVATE; 642856Srdreslin@umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 652856Srdreslin@umich.edu map_flags, -1, 0); 662856Srdreslin@umich.edu 672856Srdreslin@umich.edu if (pmemAddr == (void *)MAP_FAILED) { 682856Srdreslin@umich.edu perror("mmap"); 692856Srdreslin@umich.edu fatal("Could not mmap!\n"); 704968Sacolyte@umich.edu } 714968Sacolyte@umich.edu 724968Sacolyte@umich.edu pagePtr = 0; 734968Sacolyte@umich.edu} 742856Srdreslin@umich.edu 752856Srdreslin@umich.eduvoid 762856Srdreslin@umich.eduPhysicalMemory::init() 772623SN/A{ 782623SN/A if (!port) 792623SN/A panic("PhysicalMemory not connected to anything!"); 802623SN/A port->sendStatusChange(Port::RangeChange); 812623SN/A} 822623SN/A 832680Sktlim@umich.eduPhysicalMemory::~PhysicalMemory() 842680Sktlim@umich.edu{ 852623SN/A if (pmemAddr) 862623SN/A munmap(pmemAddr, params()->addrRange.size()); 875712Shsul@eecs.umich.edu //Remove memPorts? 882623SN/A} 892623SN/A 904968Sacolyte@umich.eduAddr 914968Sacolyte@umich.eduPhysicalMemory::new_page() 924968Sacolyte@umich.edu{ 934968Sacolyte@umich.edu Addr return_addr = pagePtr << LogVMPageSize; 944968Sacolyte@umich.edu return_addr += params()->addrRange.start; 954968Sacolyte@umich.edu 965712Shsul@eecs.umich.edu ++pagePtr; 975712Shsul@eecs.umich.edu return return_addr; 985712Shsul@eecs.umich.edu} 992623SN/A 1002623SN/Aint 1012623SN/APhysicalMemory::deviceBlockSize() 1023349Sbinkertn@umich.edu{ 1032623SN/A //Can accept anysize request 1043184Srdreslin@umich.edu return 0; 1052623SN/A} 1062623SN/A 1072623SN/ATick 1082623SN/APhysicalMemory::calculateLatency(Packet *pkt) 1093349Sbinkertn@umich.edu{ 1102623SN/A return lat; 1113310Srdreslin@umich.edu} 1123649Srdreslin@umich.edu 1132623SN/A 1142623SN/A 1152623SN/A// Add load-locked to tracking list. Should only be called if the 1163349Sbinkertn@umich.edu// operation is a load and the LOCKED flag is set. 1172623SN/Avoid 1183184Srdreslin@umich.eduPhysicalMemory::trackLoadLocked(Request *req) 1193184Srdreslin@umich.edu{ 1202623SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1212623SN/A 1222623SN/A // first we check if we already have a locked addr for this 1232623SN/A // xc. Since each xc only gets one, we just update the 1242623SN/A // existing record with the new address. 1253647Srdreslin@umich.edu list<LockedAddr>::iterator i; 1263647Srdreslin@umich.edu 1273647Srdreslin@umich.edu for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1283647Srdreslin@umich.edu if (i->matchesContext(req)) { 1293647Srdreslin@umich.edu DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n", 1302626SN/A req->getCpuNum(), req->getThreadNum(), paddr); 1313647Srdreslin@umich.edu i->addr = paddr; 1322626SN/A return; 1332623SN/A } 1342623SN/A } 1352623SN/A 1362657Ssaidi@eecs.umich.edu // no record for this xc: need to allocate a new one 1372623SN/A DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n", 1382623SN/A req->getCpuNum(), req->getThreadNum(), paddr); 1392623SN/A lockedAddrList.push_front(LockedAddr(req)); 1402623SN/A} 1412623SN/A 1424192Sktlim@umich.edu 1434192Sktlim@umich.edu// Called on *writes* only... both regular stores and 1444192Sktlim@umich.edu// store-conditional operations. Check for conventional stores which 1454192Sktlim@umich.edu// conflict with locked addresses, and for success/failure of store 1464192Sktlim@umich.edu// conditionals. 1474192Sktlim@umich.edubool 1484192Sktlim@umich.eduPhysicalMemory::checkLockedAddrList(Request *req) 1494192Sktlim@umich.edu{ 1505497Ssaidi@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1514192Sktlim@umich.edu bool isLocked = req->isLocked(); 1524192Sktlim@umich.edu 1532623SN/A // Initialize return value. Non-conditional stores always 1545529Snate@binkert.org // succeed. Assume conditional stores will fail until proven 1555487Snate@binkert.org // otherwise. 1565487Snate@binkert.org bool success = !isLocked; 1575487Snate@binkert.org 1584968Sacolyte@umich.edu // Iterate over list. Note that there could be multiple matching 1594968Sacolyte@umich.edu // records, as more than one context could have done a load locked 1602623SN/A // to this location. 1612623SN/A list<LockedAddr>::iterator i = lockedAddrList.begin(); 1622623SN/A 1633647Srdreslin@umich.edu while (i != lockedAddrList.end()) { 1643647Srdreslin@umich.edu 1653647Srdreslin@umich.edu if (i->addr == paddr) { 1662623SN/A // we have a matching address 1672623SN/A 1682623SN/A if (isLocked && i->matchesContext(req)) { 1692623SN/A // it's a store conditional, and as far as the memory 1702623SN/A // system can tell, the requesting context's lock is 1712623SN/A // still valid. 1722623SN/A DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n", 1732623SN/A req->getCpuNum(), req->getThreadNum(), paddr); 1742623SN/A success = true; 1752623SN/A } 1762915Sktlim@umich.edu 1772915Sktlim@umich.edu // Get rid of our record of this lock and advance to next 1783145Shsul@eecs.umich.edu DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n", 1792623SN/A i->cpuNum, i->threadNum, paddr); 1802623SN/A i = lockedAddrList.erase(i); 1812623SN/A } 1822623SN/A else { 1832623SN/A // no match: advance to next record 1842623SN/A ++i; 1852623SN/A } 1862915Sktlim@umich.edu } 1872915Sktlim@umich.edu 1883145Shsul@eecs.umich.edu if (isLocked) { 1892915Sktlim@umich.edu req->setScResult(success ? 1 : 0); 1902915Sktlim@umich.edu } 1912915Sktlim@umich.edu 1922915Sktlim@umich.edu return success; 1932915Sktlim@umich.edu} 1942915Sktlim@umich.edu 1955220Ssaidi@eecs.umich.eduvoid 1965220Ssaidi@eecs.umich.eduPhysicalMemory::doFunctionalAccess(Packet *pkt) 1975220Ssaidi@eecs.umich.edu{ 1984940Snate@binkert.org assert(pkt->getAddr() + pkt->getSize() < params()->addrRange.size()); 1995220Ssaidi@eecs.umich.edu 2003324Shsul@eecs.umich.edu switch (pkt->cmd) { 2015220Ssaidi@eecs.umich.edu case Packet::ReadReq: 2025220Ssaidi@eecs.umich.edu if (pkt->req->isLocked()) { 2035606Snate@binkert.org trackLoadLocked(pkt->req); 2045606Snate@binkert.org } 2052915Sktlim@umich.edu memcpy(pkt->getPtr<uint8_t>(), 2062623SN/A pmemAddr + pkt->getAddr() - params()->addrRange.start, 2072623SN/A pkt->getSize()); 2082623SN/A break; 2092798Sktlim@umich.edu case Packet::WriteReq: 2102623SN/A if (writeOK(pkt->req)) { 2115496Ssaidi@eecs.umich.edu memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, 2122798Sktlim@umich.edu pkt->getPtr<uint8_t>(), pkt->getSize()); 2132623SN/A } 2142798Sktlim@umich.edu break; 2152623SN/A default: 2162623SN/A panic("unimplemented"); 2172623SN/A } 2182623SN/A 2192623SN/A pkt->result = Packet::Success; 2202623SN/A} 2214192Sktlim@umich.edu 2222623SN/APort * 2232623SN/APhysicalMemory::getPort(const std::string &if_name, int idx) 2242623SN/A{ 2252680Sktlim@umich.edu if (if_name == "port" && idx == -1) { 2262623SN/A if (port != NULL) 2272680Sktlim@umich.edu panic("PhysicalMemory::getPort: additional port requested to memory!"); 2282680Sktlim@umich.edu port = new MemoryPort(name() + "-port", this); 2292680Sktlim@umich.edu return port; 2302623SN/A } else if (if_name == "functional") { 2315606Snate@binkert.org /* special port for functional writes at startup. */ 2322623SN/A return new MemoryPort(name() + "-funcport", this); 2332623SN/A } else { 2342623SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 2353512Sktlim@umich.edu } 2363512Sktlim@umich.edu} 2373512Sktlim@umich.edu 2385169Ssaidi@eecs.umich.eduvoid 2395712Shsul@eecs.umich.eduPhysicalMemory::recvStatusChange(Port::Status status) 2405712Shsul@eecs.umich.edu{ 2415712Shsul@eecs.umich.edu} 2422623SN/A 2432623SN/APhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 2442623SN/A PhysicalMemory *_memory) 2452623SN/A : SimpleTimingPort(_name), memory(_memory) 2462623SN/A{ } 2472623SN/A 2484940Snate@binkert.orgvoid 2494940Snate@binkert.orgPhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 2502623SN/A{ 2512683Sktlim@umich.edu memory->recvStatusChange(status); 2522623SN/A} 2532623SN/A 2542623SN/Avoid 2552623SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 2562623SN/A AddrRangeList &snoop) 2575101Ssaidi@eecs.umich.edu{ 2583686Sktlim@umich.edu memory->getAddressRanges(resp, snoop); 2593430Sgblack@eecs.umich.edu} 2605606Snate@binkert.org 2612623SN/Avoid 2622623SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 2632623SN/A{ 2642623SN/A snoop.clear(); 2652623SN/A resp.clear(); 2662623SN/A resp.push_back(RangeSize(params()->addrRange.start, 2672623SN/A params()->addrRange.size())); 2684940Snate@binkert.org} 2694940Snate@binkert.org 2702623SN/Aint 2712683Sktlim@umich.eduPhysicalMemory::MemoryPort::deviceBlockSize() 2722623SN/A{ 2732623SN/A return memory->deviceBlockSize(); 2742626SN/A} 2752626SN/A 2762626SN/ATick 2772626SN/APhysicalMemory::MemoryPort::recvAtomic(Packet *pkt) 2785606Snate@binkert.org{ 2792623SN/A memory->doFunctionalAccess(pkt); 2802623SN/A return memory->calculateLatency(pkt); 2812623SN/A} 2822623SN/A 2832623SN/Avoid 2842623SN/APhysicalMemory::MemoryPort::recvFunctional(Packet *pkt) 2852623SN/A{ 2862623SN/A // Default implementation of SimpleTimingPort::recvFunctional() 2872623SN/A // calls recvAtomic() and throws away the latency; we can save a 2882623SN/A // little here by just not calculating the latency. 2893169Sstever@eecs.umich.edu memory->doFunctionalAccess(pkt); 2904870Sstever@eecs.umich.edu} 2912623SN/A 2922623SN/Aunsigned int 2932623SN/APhysicalMemory::drain(Event *de) 2942623SN/A{ 2952623SN/A int count = port->drain(de); 2964999Sgblack@eecs.umich.edu if (count) 2974999Sgblack@eecs.umich.edu changeState(Draining); 2984999Sgblack@eecs.umich.edu else 2994999Sgblack@eecs.umich.edu changeState(Drained); 3002623SN/A return count; 3014999Sgblack@eecs.umich.edu} 3022623SN/A 3034999Sgblack@eecs.umich.eduvoid 3044999Sgblack@eecs.umich.eduPhysicalMemory::serialize(ostream &os) 3054999Sgblack@eecs.umich.edu{ 3064999Sgblack@eecs.umich.edu gzFile compressedMem; 3074999Sgblack@eecs.umich.edu string filename = name() + ".physmem"; 3084999Sgblack@eecs.umich.edu 3094999Sgblack@eecs.umich.edu SERIALIZE_SCALAR(filename); 3104999Sgblack@eecs.umich.edu 3114999Sgblack@eecs.umich.edu // write memory file 3124999Sgblack@eecs.umich.edu string thefile = Checkpoint::dir() + "/" + filename.c_str(); 3134999Sgblack@eecs.umich.edu int fd = creat(thefile.c_str(), 0664); 3144999Sgblack@eecs.umich.edu if (fd < 0) { 3154999Sgblack@eecs.umich.edu perror("creat"); 3164999Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'\n", filename); 3174999Sgblack@eecs.umich.edu } 3184999Sgblack@eecs.umich.edu 3194999Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "wb"); 3204999Sgblack@eecs.umich.edu if (compressedMem == NULL) 3214999Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 3224999Sgblack@eecs.umich.edu filename); 3234999Sgblack@eecs.umich.edu 3244999Sgblack@eecs.umich.edu if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) { 3254999Sgblack@eecs.umich.edu fatal("Write failed on physical memory checkpoint file '%s'\n", 3264999Sgblack@eecs.umich.edu filename); 3274999Sgblack@eecs.umich.edu } 3284999Sgblack@eecs.umich.edu 3294999Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 3304999Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 3314999Sgblack@eecs.umich.edu filename); 3324999Sgblack@eecs.umich.edu} 3334999Sgblack@eecs.umich.edu 3345012Sgblack@eecs.umich.eduvoid 3354999Sgblack@eecs.umich.eduPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 3364999Sgblack@eecs.umich.edu{ 3374999Sgblack@eecs.umich.edu gzFile compressedMem; 3384999Sgblack@eecs.umich.edu long *tempPage; 3394999Sgblack@eecs.umich.edu long *pmem_current; 3404968Sacolyte@umich.edu uint64_t curSize; 3414986Ssaidi@eecs.umich.edu uint32_t bytesRead; 3424999Sgblack@eecs.umich.edu const int chunkSize = 16384; 3434999Sgblack@eecs.umich.edu 3444999Sgblack@eecs.umich.edu 3454762Snate@binkert.org string filename; 3464999Sgblack@eecs.umich.edu 3474999Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(filename); 3484999Sgblack@eecs.umich.edu 3494999Sgblack@eecs.umich.edu filename = cp->cptDir + "/" + filename; 3504999Sgblack@eecs.umich.edu 3514999Sgblack@eecs.umich.edu // mmap memoryfile 3524999Sgblack@eecs.umich.edu int fd = open(filename.c_str(), O_RDONLY); 3535408Sgblack@eecs.umich.edu if (fd < 0) { 3545408Sgblack@eecs.umich.edu perror("open"); 3555408Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'", filename); 3564999Sgblack@eecs.umich.edu } 3574968Sacolyte@umich.edu 3583170Sstever@eecs.umich.edu compressedMem = gzdopen(fd, "rb"); 3594999Sgblack@eecs.umich.edu if (compressedMem == NULL) 3604999Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 3614999Sgblack@eecs.umich.edu filename); 3624999Sgblack@eecs.umich.edu 3634999Sgblack@eecs.umich.edu // unmap file that was mmaped in the constructor 3644999Sgblack@eecs.umich.edu // This is done here to make sure that gzip and open don't muck with our 3654999Sgblack@eecs.umich.edu // nice large space of memory before we reallocate it 3664999Sgblack@eecs.umich.edu munmap(pmemAddr, params()->addrRange.size()); 3674999Sgblack@eecs.umich.edu 3684999Sgblack@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 3692623SN/A MAP_ANON | MAP_PRIVATE, -1, 0); 3702623SN/A 3712623SN/A if (pmemAddr == (void *)MAP_FAILED) { 3725177Sgblack@eecs.umich.edu perror("mmap"); 3735177Sgblack@eecs.umich.edu fatal("Could not mmap physical memory!\n"); 3745177Sgblack@eecs.umich.edu } 3755177Sgblack@eecs.umich.edu 3765177Sgblack@eecs.umich.edu curSize = 0; 3775177Sgblack@eecs.umich.edu tempPage = (long*)malloc(chunkSize); 3785177Sgblack@eecs.umich.edu if (tempPage == NULL) 3795177Sgblack@eecs.umich.edu fatal("Unable to malloc memory to read file %s\n", filename); 3805177Sgblack@eecs.umich.edu 3815177Sgblack@eecs.umich.edu /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 3825177Sgblack@eecs.umich.edu while (curSize < params()->addrRange.size()) { 3835177Sgblack@eecs.umich.edu bytesRead = gzread(compressedMem, tempPage, chunkSize); 3845177Sgblack@eecs.umich.edu if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize) 3855177Sgblack@eecs.umich.edu fatal("Read failed on physical memory checkpoint file '%s'" 3865177Sgblack@eecs.umich.edu " got %d bytes, expected %d or %d bytes\n", 3875177Sgblack@eecs.umich.edu filename, bytesRead, chunkSize, params()->addrRange.size()-curSize); 3885177Sgblack@eecs.umich.edu 3895177Sgblack@eecs.umich.edu assert(bytesRead % sizeof(long) == 0); 3905177Sgblack@eecs.umich.edu 3915177Sgblack@eecs.umich.edu for (int x = 0; x < bytesRead/sizeof(long); x++) 3925177Sgblack@eecs.umich.edu { 3935177Sgblack@eecs.umich.edu if (*(tempPage+x) != 0) { 3945177Sgblack@eecs.umich.edu pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 3955177Sgblack@eecs.umich.edu *pmem_current = *(tempPage+x); 3965177Sgblack@eecs.umich.edu } 3975177Sgblack@eecs.umich.edu } 3985177Sgblack@eecs.umich.edu curSize += bytesRead; 3995177Sgblack@eecs.umich.edu } 4005177Sgblack@eecs.umich.edu 4015177Sgblack@eecs.umich.edu free(tempPage); 4025177Sgblack@eecs.umich.edu 4035177Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 4045177Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 4055177Sgblack@eecs.umich.edu filename); 4065177Sgblack@eecs.umich.edu 4075177Sgblack@eecs.umich.edu} 4085177Sgblack@eecs.umich.edu 4095177Sgblack@eecs.umich.edu 4105177Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 4115177Sgblack@eecs.umich.edu 4125177Sgblack@eecs.umich.edu Param<string> file; 4135177Sgblack@eecs.umich.edu Param<Range<Addr> > range; 4145177Sgblack@eecs.umich.edu Param<Tick> latency; 4155177Sgblack@eecs.umich.edu 4165177Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 4175177Sgblack@eecs.umich.edu 4185177Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 4195177Sgblack@eecs.umich.edu 4205177Sgblack@eecs.umich.edu INIT_PARAM_DFLT(file, "memory mapped file", ""), 4215177Sgblack@eecs.umich.edu INIT_PARAM(range, "Device Address Range"), 4225177Sgblack@eecs.umich.edu INIT_PARAM(latency, "Memory access latency") 4235177Sgblack@eecs.umich.edu 4245177Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 4255177Sgblack@eecs.umich.edu 4265177Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(PhysicalMemory) 4272623SN/A{ 4282623SN/A PhysicalMemory::Params *p = new PhysicalMemory::Params; 4292623SN/A p->name = getInstanceName(); 4302623SN/A p->addrRange = range; 4314115Ssaidi@eecs.umich.edu p->latency = latency; 4324115Ssaidi@eecs.umich.edu return new PhysicalMemory(p); 4334115Ssaidi@eecs.umich.edu} 4344115Ssaidi@eecs.umich.edu 4354040Ssaidi@eecs.umich.eduREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 4364040Ssaidi@eecs.umich.edu