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 &section)
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