physical.cc revision 3749
12391SN/A/* 22391SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 32391SN/A * All rights reserved. 42391SN/A * 52391SN/A * Redistribution and use in source and binary forms, with or without 62391SN/A * modification, are permitted provided that the following conditions are 72391SN/A * met: redistributions of source code must retain the above copyright 82391SN/A * notice, this list of conditions and the following disclaimer; 92391SN/A * redistributions in binary form must reproduce the above copyright 102391SN/A * notice, this list of conditions and the following disclaimer in the 112391SN/A * documentation and/or other materials provided with the distribution; 122391SN/A * neither the name of the copyright holders nor the names of its 132391SN/A * contributors may be used to endorse or promote products derived from 142391SN/A * this software without specific prior written permission. 152391SN/A * 162391SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172391SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182391SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192391SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202391SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212391SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222391SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232391SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242391SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252391SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262391SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292914Ssaidi@eecs.umich.edu * Ali Saidi 302391SN/A */ 312391SN/A 322391SN/A#include <sys/types.h> 332391SN/A#include <sys/mman.h> 342391SN/A#include <errno.h> 352391SN/A#include <fcntl.h> 362391SN/A#include <unistd.h> 372391SN/A#include <zlib.h> 382391SN/A 392391SN/A#include <iostream> 402391SN/A#include <string> 412391SN/A 423348Sbinkertn@umich.edu#include "arch/isa_traits.hh" 432391SN/A#include "base/misc.hh" 442391SN/A#include "config/full_system.hh" 452394SN/A#include "mem/physical.hh" 462391SN/A#include "sim/builder.hh" 472415SN/A#include "sim/eventq.hh" 483348Sbinkertn@umich.edu#include "sim/host.hh" 492394SN/A 502391SN/Ausing namespace std; 512423SN/Ausing namespace TheISA; 522391SN/A 533012Ssaidi@eecs.umich.eduPhysicalMemory::PhysicalMemory(Params *p) 543012Ssaidi@eecs.umich.edu : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p) 552391SN/A{ 563012Ssaidi@eecs.umich.edu if (params()->addrRange.size() % TheISA::PageBytes != 0) 572391SN/A panic("Memory Size not divisible by page size\n"); 582391SN/A 592391SN/A int map_flags = MAP_ANON | MAP_PRIVATE; 603012Ssaidi@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 612391SN/A map_flags, -1, 0); 622391SN/A 633012Ssaidi@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 642391SN/A perror("mmap"); 652391SN/A fatal("Could not mmap!\n"); 662391SN/A } 672391SN/A 683012Ssaidi@eecs.umich.edu pagePtr = 0; 692391SN/A} 702391SN/A 712541SN/Avoid 722541SN/APhysicalMemory::init() 732541SN/A{ 742541SN/A if (!port) 752541SN/A panic("PhysicalMemory not connected to anything!"); 762541SN/A port->sendStatusChange(Port::RangeChange); 772541SN/A} 782541SN/A 792391SN/APhysicalMemory::~PhysicalMemory() 802391SN/A{ 813012Ssaidi@eecs.umich.edu if (pmemAddr) 823012Ssaidi@eecs.umich.edu munmap(pmemAddr, params()->addrRange.size()); 832416SN/A //Remove memPorts? 842391SN/A} 852391SN/A 862391SN/AAddr 872391SN/APhysicalMemory::new_page() 882391SN/A{ 893012Ssaidi@eecs.umich.edu Addr return_addr = pagePtr << LogVMPageSize; 903012Ssaidi@eecs.umich.edu return_addr += params()->addrRange.start; 912391SN/A 923012Ssaidi@eecs.umich.edu ++pagePtr; 932391SN/A return return_addr; 942391SN/A} 952391SN/A 962408SN/Aint 972408SN/APhysicalMemory::deviceBlockSize() 982408SN/A{ 992409SN/A //Can accept anysize request 1002409SN/A return 0; 1012408SN/A} 1022408SN/A 1033012Ssaidi@eecs.umich.eduTick 1043349Sbinkertn@umich.eduPhysicalMemory::calculateLatency(PacketPtr pkt) 1053012Ssaidi@eecs.umich.edu{ 1063012Ssaidi@eecs.umich.edu return lat; 1073012Ssaidi@eecs.umich.edu} 1082413SN/A 1093170Sstever@eecs.umich.edu 1103170Sstever@eecs.umich.edu 1113170Sstever@eecs.umich.edu// Add load-locked to tracking list. Should only be called if the 1123170Sstever@eecs.umich.edu// operation is a load and the LOCKED flag is set. 1133170Sstever@eecs.umich.eduvoid 1143170Sstever@eecs.umich.eduPhysicalMemory::trackLoadLocked(Request *req) 1153170Sstever@eecs.umich.edu{ 1163170Sstever@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1173170Sstever@eecs.umich.edu 1183170Sstever@eecs.umich.edu // first we check if we already have a locked addr for this 1193170Sstever@eecs.umich.edu // xc. Since each xc only gets one, we just update the 1203170Sstever@eecs.umich.edu // existing record with the new address. 1213170Sstever@eecs.umich.edu list<LockedAddr>::iterator i; 1223170Sstever@eecs.umich.edu 1233170Sstever@eecs.umich.edu for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1243170Sstever@eecs.umich.edu if (i->matchesContext(req)) { 1253170Sstever@eecs.umich.edu DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n", 1263170Sstever@eecs.umich.edu req->getCpuNum(), req->getThreadNum(), paddr); 1273170Sstever@eecs.umich.edu i->addr = paddr; 1283170Sstever@eecs.umich.edu return; 1293170Sstever@eecs.umich.edu } 1303170Sstever@eecs.umich.edu } 1313170Sstever@eecs.umich.edu 1323170Sstever@eecs.umich.edu // no record for this xc: need to allocate a new one 1333170Sstever@eecs.umich.edu DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n", 1343170Sstever@eecs.umich.edu req->getCpuNum(), req->getThreadNum(), paddr); 1353170Sstever@eecs.umich.edu lockedAddrList.push_front(LockedAddr(req)); 1363170Sstever@eecs.umich.edu} 1373170Sstever@eecs.umich.edu 1383170Sstever@eecs.umich.edu 1393170Sstever@eecs.umich.edu// Called on *writes* only... both regular stores and 1403170Sstever@eecs.umich.edu// store-conditional operations. Check for conventional stores which 1413170Sstever@eecs.umich.edu// conflict with locked addresses, and for success/failure of store 1423170Sstever@eecs.umich.edu// conditionals. 1433170Sstever@eecs.umich.edubool 1443170Sstever@eecs.umich.eduPhysicalMemory::checkLockedAddrList(Request *req) 1453170Sstever@eecs.umich.edu{ 1463170Sstever@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1473170Sstever@eecs.umich.edu bool isLocked = req->isLocked(); 1483170Sstever@eecs.umich.edu 1493170Sstever@eecs.umich.edu // Initialize return value. Non-conditional stores always 1503170Sstever@eecs.umich.edu // succeed. Assume conditional stores will fail until proven 1513170Sstever@eecs.umich.edu // otherwise. 1523170Sstever@eecs.umich.edu bool success = !isLocked; 1533170Sstever@eecs.umich.edu 1543170Sstever@eecs.umich.edu // Iterate over list. Note that there could be multiple matching 1553170Sstever@eecs.umich.edu // records, as more than one context could have done a load locked 1563170Sstever@eecs.umich.edu // to this location. 1573170Sstever@eecs.umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 1583170Sstever@eecs.umich.edu 1593170Sstever@eecs.umich.edu while (i != lockedAddrList.end()) { 1603170Sstever@eecs.umich.edu 1613170Sstever@eecs.umich.edu if (i->addr == paddr) { 1623170Sstever@eecs.umich.edu // we have a matching address 1633170Sstever@eecs.umich.edu 1643170Sstever@eecs.umich.edu if (isLocked && i->matchesContext(req)) { 1653170Sstever@eecs.umich.edu // it's a store conditional, and as far as the memory 1663170Sstever@eecs.umich.edu // system can tell, the requesting context's lock is 1673170Sstever@eecs.umich.edu // still valid. 1683170Sstever@eecs.umich.edu DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n", 1693170Sstever@eecs.umich.edu req->getCpuNum(), req->getThreadNum(), paddr); 1703170Sstever@eecs.umich.edu success = true; 1713170Sstever@eecs.umich.edu } 1723170Sstever@eecs.umich.edu 1733170Sstever@eecs.umich.edu // Get rid of our record of this lock and advance to next 1743170Sstever@eecs.umich.edu DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n", 1753170Sstever@eecs.umich.edu i->cpuNum, i->threadNum, paddr); 1763170Sstever@eecs.umich.edu i = lockedAddrList.erase(i); 1773170Sstever@eecs.umich.edu } 1783170Sstever@eecs.umich.edu else { 1793170Sstever@eecs.umich.edu // no match: advance to next record 1803170Sstever@eecs.umich.edu ++i; 1813170Sstever@eecs.umich.edu } 1823170Sstever@eecs.umich.edu } 1833170Sstever@eecs.umich.edu 1843170Sstever@eecs.umich.edu if (isLocked) { 1853170Sstever@eecs.umich.edu req->setScResult(success ? 1 : 0); 1863170Sstever@eecs.umich.edu } 1873170Sstever@eecs.umich.edu 1883170Sstever@eecs.umich.edu return success; 1893170Sstever@eecs.umich.edu} 1903170Sstever@eecs.umich.edu 1913029Ssaidi@eecs.umich.eduvoid 1923349Sbinkertn@umich.eduPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 1932413SN/A{ 1943749Sgblack@eecs.umich.edu assert(pkt->getAddr() >= params()->addrRange.start && 1953584Ssaidi@eecs.umich.edu pkt->getAddr() + pkt->getSize() <= params()->addrRange.start + 1963584Ssaidi@eecs.umich.edu params()->addrRange.size()); 1972414SN/A 1983175Srdreslin@umich.edu if (pkt->isRead()) { 1993170Sstever@eecs.umich.edu if (pkt->req->isLocked()) { 2003170Sstever@eecs.umich.edu trackLoadLocked(pkt->req); 2013170Sstever@eecs.umich.edu } 2023281Srdreslin@umich.edu DPRINTF(MemoryAccess, "Performing Read of size %i on address 0x%x\n", 2033281Srdreslin@umich.edu pkt->getSize(), pkt->getAddr()); 2042641Sstever@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), 2053012Ssaidi@eecs.umich.edu pmemAddr + pkt->getAddr() - params()->addrRange.start, 2062641Sstever@eecs.umich.edu pkt->getSize()); 2073175Srdreslin@umich.edu } 2083175Srdreslin@umich.edu else if (pkt->isWrite()) { 2093170Sstever@eecs.umich.edu if (writeOK(pkt->req)) { 2103281Srdreslin@umich.edu DPRINTF(MemoryAccess, "Performing Write of size %i on address 0x%x\n", 2113281Srdreslin@umich.edu pkt->getSize(), pkt->getAddr()); 2123170Sstever@eecs.umich.edu memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, 2133170Sstever@eecs.umich.edu pkt->getPtr<uint8_t>(), pkt->getSize()); 2142631SN/A } 2153175Srdreslin@umich.edu } 2163175Srdreslin@umich.edu else if (pkt->isInvalidate()) { 2173175Srdreslin@umich.edu //upgrade or invalidate 2183175Srdreslin@umich.edu pkt->flags |= SATISFIED; 2193175Srdreslin@umich.edu } 2203175Srdreslin@umich.edu else { 2212413SN/A panic("unimplemented"); 2222413SN/A } 2232420SN/A 2242641Sstever@eecs.umich.edu pkt->result = Packet::Success; 2252413SN/A} 2262413SN/A 2272413SN/APort * 2282738Sstever@eecs.umich.eduPhysicalMemory::getPort(const std::string &if_name, int idx) 2292413SN/A{ 2302738Sstever@eecs.umich.edu if (if_name == "port" && idx == -1) { 2312499SN/A if (port != NULL) 2322499SN/A panic("PhysicalMemory::getPort: additional port requested to memory!"); 2332640Sstever@eecs.umich.edu port = new MemoryPort(name() + "-port", this); 2342499SN/A return port; 2352519SN/A } else if (if_name == "functional") { 2363196Srdreslin@umich.edu /* special port for functional writes at startup. And for memtester */ 2372640Sstever@eecs.umich.edu return new MemoryPort(name() + "-funcport", this); 2382462SN/A } else { 2392462SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 2402462SN/A } 2412413SN/A} 2422413SN/A 2432413SN/Avoid 2442413SN/APhysicalMemory::recvStatusChange(Port::Status status) 2452413SN/A{ 2462413SN/A} 2472413SN/A 2482640Sstever@eecs.umich.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 2492640Sstever@eecs.umich.edu PhysicalMemory *_memory) 2502914Ssaidi@eecs.umich.edu : SimpleTimingPort(_name), memory(_memory) 2512413SN/A{ } 2522413SN/A 2532413SN/Avoid 2542413SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 2552413SN/A{ 2562413SN/A memory->recvStatusChange(status); 2572413SN/A} 2582413SN/A 2592413SN/Avoid 2602522SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 2612522SN/A AddrRangeList &snoop) 2622413SN/A{ 2632522SN/A memory->getAddressRanges(resp, snoop); 2642497SN/A} 2652497SN/A 2662497SN/Avoid 2672522SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 2682497SN/A{ 2692522SN/A snoop.clear(); 2702522SN/A resp.clear(); 2713091Sstever@eecs.umich.edu resp.push_back(RangeSize(params()->addrRange.start, 2723091Sstever@eecs.umich.edu params()->addrRange.size())); 2732413SN/A} 2742413SN/A 2752415SN/Aint 2762415SN/APhysicalMemory::MemoryPort::deviceBlockSize() 2772415SN/A{ 2782415SN/A return memory->deviceBlockSize(); 2792415SN/A} 2802413SN/A 2812413SN/ATick 2823349Sbinkertn@umich.eduPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 2832413SN/A{ 2843029Ssaidi@eecs.umich.edu memory->doFunctionalAccess(pkt); 2853029Ssaidi@eecs.umich.edu return memory->calculateLatency(pkt); 2862413SN/A} 2872413SN/A 2882413SN/Avoid 2893349Sbinkertn@umich.eduPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 2902413SN/A{ 2913612Srdreslin@umich.edu //Since we are overriding the function, make sure to have the impl of the 2923612Srdreslin@umich.edu //check or functional accesses here. 2933612Srdreslin@umich.edu std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin(); 2943612Srdreslin@umich.edu std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end(); 2953612Srdreslin@umich.edu bool notDone = true; 2963612Srdreslin@umich.edu 2973612Srdreslin@umich.edu while (i != end && notDone) { 2983612Srdreslin@umich.edu PacketPtr target = i->second; 2993612Srdreslin@umich.edu // If the target contains data, and it overlaps the 3003612Srdreslin@umich.edu // probed request, need to update data 3013612Srdreslin@umich.edu if (target->intersect(pkt)) 3023612Srdreslin@umich.edu notDone = fixPacket(pkt, target); 3033612Srdreslin@umich.edu i++; 3043612Srdreslin@umich.edu } 3053612Srdreslin@umich.edu 3063091Sstever@eecs.umich.edu // Default implementation of SimpleTimingPort::recvFunctional() 3073091Sstever@eecs.umich.edu // calls recvAtomic() and throws away the latency; we can save a 3083091Sstever@eecs.umich.edu // little here by just not calculating the latency. 3092413SN/A memory->doFunctionalAccess(pkt); 3102413SN/A} 3112413SN/A 3122914Ssaidi@eecs.umich.eduunsigned int 3132914Ssaidi@eecs.umich.eduPhysicalMemory::drain(Event *de) 3142914Ssaidi@eecs.umich.edu{ 3152914Ssaidi@eecs.umich.edu int count = port->drain(de); 3162914Ssaidi@eecs.umich.edu if (count) 3172914Ssaidi@eecs.umich.edu changeState(Draining); 3182914Ssaidi@eecs.umich.edu else 3192914Ssaidi@eecs.umich.edu changeState(Drained); 3202914Ssaidi@eecs.umich.edu return count; 3212914Ssaidi@eecs.umich.edu} 3222413SN/A 3232391SN/Avoid 3242391SN/APhysicalMemory::serialize(ostream &os) 3252391SN/A{ 3262391SN/A gzFile compressedMem; 3272391SN/A string filename = name() + ".physmem"; 3282391SN/A 3292391SN/A SERIALIZE_SCALAR(filename); 3302391SN/A 3312391SN/A // write memory file 3322391SN/A string thefile = Checkpoint::dir() + "/" + filename.c_str(); 3332391SN/A int fd = creat(thefile.c_str(), 0664); 3342391SN/A if (fd < 0) { 3352391SN/A perror("creat"); 3362391SN/A fatal("Can't open physical memory checkpoint file '%s'\n", filename); 3372391SN/A } 3382391SN/A 3392391SN/A compressedMem = gzdopen(fd, "wb"); 3402391SN/A if (compressedMem == NULL) 3412391SN/A fatal("Insufficient memory to allocate compression state for %s\n", 3422391SN/A filename); 3432391SN/A 3443012Ssaidi@eecs.umich.edu if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) { 3452391SN/A fatal("Write failed on physical memory checkpoint file '%s'\n", 3462391SN/A filename); 3472391SN/A } 3482391SN/A 3492391SN/A if (gzclose(compressedMem)) 3502391SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 3512391SN/A filename); 3522391SN/A} 3532391SN/A 3542391SN/Avoid 3552391SN/APhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 3562391SN/A{ 3572391SN/A gzFile compressedMem; 3582391SN/A long *tempPage; 3592391SN/A long *pmem_current; 3602391SN/A uint64_t curSize; 3612391SN/A uint32_t bytesRead; 3622391SN/A const int chunkSize = 16384; 3632391SN/A 3642391SN/A 3652391SN/A string filename; 3662391SN/A 3672391SN/A UNSERIALIZE_SCALAR(filename); 3682391SN/A 3692391SN/A filename = cp->cptDir + "/" + filename; 3702391SN/A 3712391SN/A // mmap memoryfile 3722391SN/A int fd = open(filename.c_str(), O_RDONLY); 3732391SN/A if (fd < 0) { 3742391SN/A perror("open"); 3752391SN/A fatal("Can't open physical memory checkpoint file '%s'", filename); 3762391SN/A } 3772391SN/A 3782391SN/A compressedMem = gzdopen(fd, "rb"); 3792391SN/A if (compressedMem == NULL) 3802391SN/A fatal("Insufficient memory to allocate compression state for %s\n", 3812391SN/A filename); 3822391SN/A 3833012Ssaidi@eecs.umich.edu // unmap file that was mmaped in the constructor 3843012Ssaidi@eecs.umich.edu // This is done here to make sure that gzip and open don't muck with our 3853012Ssaidi@eecs.umich.edu // nice large space of memory before we reallocate it 3863012Ssaidi@eecs.umich.edu munmap(pmemAddr, params()->addrRange.size()); 3872391SN/A 3883012Ssaidi@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 3892391SN/A MAP_ANON | MAP_PRIVATE, -1, 0); 3902391SN/A 3913012Ssaidi@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 3922391SN/A perror("mmap"); 3932391SN/A fatal("Could not mmap physical memory!\n"); 3942391SN/A } 3952391SN/A 3962391SN/A curSize = 0; 3972391SN/A tempPage = (long*)malloc(chunkSize); 3982391SN/A if (tempPage == NULL) 3992391SN/A fatal("Unable to malloc memory to read file %s\n", filename); 4002391SN/A 4012391SN/A /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 4023012Ssaidi@eecs.umich.edu while (curSize < params()->addrRange.size()) { 4032391SN/A bytesRead = gzread(compressedMem, tempPage, chunkSize); 4043012Ssaidi@eecs.umich.edu if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize) 4052391SN/A fatal("Read failed on physical memory checkpoint file '%s'" 4062391SN/A " got %d bytes, expected %d or %d bytes\n", 4073012Ssaidi@eecs.umich.edu filename, bytesRead, chunkSize, params()->addrRange.size()-curSize); 4082391SN/A 4092391SN/A assert(bytesRead % sizeof(long) == 0); 4102391SN/A 4112391SN/A for (int x = 0; x < bytesRead/sizeof(long); x++) 4122391SN/A { 4132391SN/A if (*(tempPage+x) != 0) { 4143012Ssaidi@eecs.umich.edu pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 4152391SN/A *pmem_current = *(tempPage+x); 4162391SN/A } 4172391SN/A } 4182391SN/A curSize += bytesRead; 4192391SN/A } 4202391SN/A 4212391SN/A free(tempPage); 4222391SN/A 4232391SN/A if (gzclose(compressedMem)) 4242391SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 4252391SN/A filename); 4262391SN/A 4272391SN/A} 4282391SN/A 4292413SN/A 4302391SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 4312391SN/A 4322391SN/A Param<string> file; 4332391SN/A Param<Range<Addr> > range; 4342565SN/A Param<Tick> latency; 4352391SN/A 4362391SN/AEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 4372391SN/A 4382391SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 4392391SN/A 4402391SN/A INIT_PARAM_DFLT(file, "memory mapped file", ""), 4412565SN/A INIT_PARAM(range, "Device Address Range"), 4422565SN/A INIT_PARAM(latency, "Memory access latency") 4432391SN/A 4442391SN/AEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 4452391SN/A 4462391SN/ACREATE_SIM_OBJECT(PhysicalMemory) 4472391SN/A{ 4483012Ssaidi@eecs.umich.edu PhysicalMemory::Params *p = new PhysicalMemory::Params; 4493012Ssaidi@eecs.umich.edu p->name = getInstanceName(); 4503012Ssaidi@eecs.umich.edu p->addrRange = range; 4513012Ssaidi@eecs.umich.edu p->latency = latency; 4523012Ssaidi@eecs.umich.edu return new PhysicalMemory(p); 4532391SN/A} 4542391SN/A 4552391SN/AREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 456