Fix Physical Memory to allow memory sizes bigger than 128MB.

Kinda port DRAM to new memory system. The code is *really* ugly (not my fault) and right now something about the stats it uses
causes a simulator segfault.

src/SConscript:
    Add dram.cc to sconscript
src/mem/physical.cc:
src/mem/physical.hh:
    Add params struct to physical memory, use params, make latency function be virtual
src/python/m5/objects/PhysicalMemory.py:
    Add DRAMMemory python class

--HG--
extra : convert_revision : 5bd9f2e071c62da89e8efa46fa016f342c01535d
This commit is contained in:
Ali Saidi 2006-08-16 19:01:11 -04:00
parent bb6af8eb8a
commit 2f145ac54a
6 changed files with 2991 additions and 41 deletions

View file

@ -94,6 +94,7 @@ base_sources = Split('''
mem/bridge.cc mem/bridge.cc
mem/bus.cc mem/bus.cc
mem/dram.cc
mem/mem_object.cc mem/mem_object.cc
mem/packet.cc mem/packet.cc
mem/physical.cc mem/physical.cc

2746
src/mem/dram.cc Normal file

File diff suppressed because it is too large Load diff

172
src/mem/dram.hh Normal file
View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2003-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ron Dreslinski
* Ali Saidi
*/
/**
* @file
* Derrive a class from PhysicalMemory that support DRAM like timing access.
*/
#ifndef __MEM_DRAM_HH__
#define __MEM_DRAM_HH__
#include "base/statistics.hh"
#include "mem/physical.hh"
class DRAMMemory : public PhysicalMemory
{
protected:
/* added for dram support */
const int cpu_ratio; // ratio between CPU speed and memory bus speed
const int bus_width; // memory access bus width (in bytes)
/* memory access latency (<first_chunk> <inter_chunk>) */
const std::string mem_type;
const std::string mem_actpolicy;
const std::string memctrladdr_type;
const int act_lat;
const int cas_lat;
const int war_lat;
const int pre_lat;
const int dpl_lat;
const int trc_lat;
const int num_banks;
const int num_cpus;
int bank_size;
int num_rows;
int *active_row;
int last_bank;
int last_row;
Tick *busy_until;
int last_dev;
bool lastCmdIsRead;
int precharge;
/* memory access statistics */
int same_row_read_access;
int srr_after_read;
int srr_after_write;
int same_row_write_access;
int srw_after_read;
int srw_after_write;
int same_bank_read_access;
int sbr_after_read;
int sbr_after_write;
int same_bank_write_access;
int sbw_after_read;
int sbw_after_write;
int other_bank_read_access_hit;
int obr_after_read_hit;
int obr_after_write_hit;
int other_bank_write_access_hit;
int obw_after_read_hit;
int obw_after_write_hit;
// DR
// int other_bank_read_access_miss;
int obr_after_read_miss;
int obr_after_write_miss;
// DR
// int other_bank_write_access_miss;
int obw_after_read_miss;
int obw_after_write_miss;
int total_access;
int adjacent_access;
int adjacent_read;
int adjacent_write;
int command_overlapping;
int best_case;
int in_between_case;
int worst_case;
int full_overlapping;
int partial_overlapping;
int mem_access_details;
int memctrlpipe_enable;
Tick time_last_access;
Stats::Vector<> accesses;
Stats::Vector<> bytesRequested;
Stats::Vector<> bytesSent;
Stats::Vector<> compressedAccesses;
Stats::Vector<> cycles_nCKE;
Stats::Vector<> cycles_all_precharge_CKE;
Stats::Vector<> cycles_all_precharge_nCKE;
Stats::Vector<> cycles_bank_active_nCKE;
Stats::Vector<> cycles_avg_ACT;
Stats::Vector<> cycles_read_out;
Stats::Vector<> cycles_write_in;
Stats::Vector<> cycles_between_misses;
Stats::Vector<> other_bank_read_access_miss;
Stats::Vector<> other_bank_write_access_miss;
Stats::Scalar<> total_latency;
Stats::Scalar<> total_icache_req;
Stats::Scalar<> total_arb_latency;
Stats::Formula avg_latency;
Stats::Formula avg_arb_latency;
Stats::Vector2d<> bank_access_profile;
protected:
Tick calculateLatency(Packet *pkt);
int prechargeBanksAround(int bank);
public:
struct Params : public PhysicalMemory::Params
{
/* additional params for dram protocol*/
int cpu_ratio;
int bus_width;
std::string mem_type; /* DRDRAM, SDRAM */
std::string mem_actpolicy; /* closed, open */
std::string memctrladdr_type; /* interleaved, anythingelse */
int act_lat;
int cas_lat;
int war_lat;
int pre_lat;
int dpl_lat;
int trc_lat;
int num_banks;
int num_cpus;
};
virtual void regStats();
DRAMMemory(Params *p);
};
#endif// __MEM_DRAM_HH__

View file

@ -54,25 +54,22 @@ using namespace std;
using namespace TheISA; using namespace TheISA;
PhysicalMemory::PhysicalMemory(const string &n, Tick latency) PhysicalMemory::PhysicalMemory(Params *p)
: MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency) : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p)
{ {
// Hardcoded to 128 MB for now. if (params()->addrRange.size() % TheISA::PageBytes != 0)
pmem_size = 1 << 27;
if (pmem_size % TheISA::PageBytes != 0)
panic("Memory Size not divisible by page size\n"); panic("Memory Size not divisible by page size\n");
int map_flags = MAP_ANON | MAP_PRIVATE; int map_flags = MAP_ANON | MAP_PRIVATE;
pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
map_flags, -1, 0); map_flags, -1, 0);
if (pmem_addr == (void *)MAP_FAILED) { if (pmemAddr == (void *)MAP_FAILED) {
perror("mmap"); perror("mmap");
fatal("Could not mmap!\n"); fatal("Could not mmap!\n");
} }
page_ptr = 0; pagePtr = 0;
} }
void void
@ -85,18 +82,18 @@ PhysicalMemory::init()
PhysicalMemory::~PhysicalMemory() PhysicalMemory::~PhysicalMemory()
{ {
if (pmem_addr) if (pmemAddr)
munmap(pmem_addr, pmem_size); munmap(pmemAddr, params()->addrRange.size());
//Remove memPorts? //Remove memPorts?
} }
Addr Addr
PhysicalMemory::new_page() PhysicalMemory::new_page()
{ {
Addr return_addr = page_ptr << LogVMPageSize; Addr return_addr = pagePtr << LogVMPageSize;
return_addr += base_addr; return_addr += params()->addrRange.start;
++page_ptr; ++pagePtr;
return return_addr; return return_addr;
} }
@ -107,20 +104,25 @@ PhysicalMemory::deviceBlockSize()
return 0; return 0;
} }
Tick
PhysicalMemory::calculateLatency(Packet *pkt)
{
return lat;
}
Tick Tick
PhysicalMemory::doFunctionalAccess(Packet *pkt) PhysicalMemory::doFunctionalAccess(Packet *pkt)
{ {
assert(pkt->getAddr() + pkt->getSize() < pmem_size); assert(pkt->getAddr() + pkt->getSize() < params()->addrRange.size());
switch (pkt->cmd) { switch (pkt->cmd) {
case Packet::ReadReq: case Packet::ReadReq:
memcpy(pkt->getPtr<uint8_t>(), memcpy(pkt->getPtr<uint8_t>(),
pmem_addr + pkt->getAddr() - base_addr, pmemAddr + pkt->getAddr() - params()->addrRange.start,
pkt->getSize()); pkt->getSize());
break; break;
case Packet::WriteReq: case Packet::WriteReq:
memcpy(pmem_addr + pkt->getAddr() - base_addr, memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(),
pkt->getSize()); pkt->getSize());
// temporary hack: will need to add real LL/SC implementation // temporary hack: will need to add real LL/SC implementation
@ -134,7 +136,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
} }
pkt->result = Packet::Success; pkt->result = Packet::Success;
return lat; return calculateLatency(pkt);
} }
Port * Port *
@ -181,7 +183,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
{ {
snoop.clear(); snoop.clear();
resp.clear(); resp.clear();
resp.push_back(RangeSize(base_addr, pmem_size)); resp.push_back(RangeSize(params()->addrRange.start, params()->addrRange.size()));
} }
int int
@ -232,7 +234,6 @@ PhysicalMemory::serialize(ostream &os)
gzFile compressedMem; gzFile compressedMem;
string filename = name() + ".physmem"; string filename = name() + ".physmem";
SERIALIZE_SCALAR(pmem_size);
SERIALIZE_SCALAR(filename); SERIALIZE_SCALAR(filename);
// write memory file // write memory file
@ -248,7 +249,7 @@ PhysicalMemory::serialize(ostream &os)
fatal("Insufficient memory to allocate compression state for %s\n", fatal("Insufficient memory to allocate compression state for %s\n",
filename); filename);
if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) { if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) {
fatal("Write failed on physical memory checkpoint file '%s'\n", fatal("Write failed on physical memory checkpoint file '%s'\n",
filename); filename);
} }
@ -269,12 +270,8 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
const int chunkSize = 16384; const int chunkSize = 16384;
// unmap file that was mmaped in the constructor
munmap(pmem_addr, pmem_size);
string filename; string filename;
UNSERIALIZE_SCALAR(pmem_size);
UNSERIALIZE_SCALAR(filename); UNSERIALIZE_SCALAR(filename);
filename = cp->cptDir + "/" + filename; filename = cp->cptDir + "/" + filename;
@ -291,11 +288,15 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
fatal("Insufficient memory to allocate compression state for %s\n", fatal("Insufficient memory to allocate compression state for %s\n",
filename); filename);
// unmap file that was mmaped in the constructor
// This is done here to make sure that gzip and open don't muck with our
// nice large space of memory before we reallocate it
munmap(pmemAddr, params()->addrRange.size());
pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0); MAP_ANON | MAP_PRIVATE, -1, 0);
if (pmem_addr == (void *)MAP_FAILED) { if (pmemAddr == (void *)MAP_FAILED) {
perror("mmap"); perror("mmap");
fatal("Could not mmap physical memory!\n"); fatal("Could not mmap physical memory!\n");
} }
@ -306,19 +307,19 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
fatal("Unable to malloc memory to read file %s\n", filename); fatal("Unable to malloc memory to read file %s\n", filename);
/* Only copy bytes that are non-zero, so we don't give the VM system hell */ /* Only copy bytes that are non-zero, so we don't give the VM system hell */
while (curSize < pmem_size) { while (curSize < params()->addrRange.size()) {
bytesRead = gzread(compressedMem, tempPage, chunkSize); bytesRead = gzread(compressedMem, tempPage, chunkSize);
if (bytesRead != chunkSize && bytesRead != pmem_size - curSize) if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize)
fatal("Read failed on physical memory checkpoint file '%s'" fatal("Read failed on physical memory checkpoint file '%s'"
" got %d bytes, expected %d or %d bytes\n", " got %d bytes, expected %d or %d bytes\n",
filename, bytesRead, chunkSize, pmem_size-curSize); filename, bytesRead, chunkSize, params()->addrRange.size()-curSize);
assert(bytesRead % sizeof(long) == 0); assert(bytesRead % sizeof(long) == 0);
for (int x = 0; x < bytesRead/sizeof(long); x++) for (int x = 0; x < bytesRead/sizeof(long); x++)
{ {
if (*(tempPage+x) != 0) { if (*(tempPage+x) != 0) {
pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long)); pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
*pmem_current = *(tempPage+x); *pmem_current = *(tempPage+x);
} }
} }
@ -352,8 +353,11 @@ END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
CREATE_SIM_OBJECT(PhysicalMemory) CREATE_SIM_OBJECT(PhysicalMemory)
{ {
PhysicalMemory::Params *p = new PhysicalMemory::Params;
return new PhysicalMemory(getInstanceName(), latency); p->name = getInstanceName();
p->addrRange = range;
p->latency = latency;
return new PhysicalMemory(p);
} }
REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)

View file

@ -80,19 +80,28 @@ class PhysicalMemory : public MemObject
const PhysicalMemory &operator=(const PhysicalMemory &specmem); const PhysicalMemory &operator=(const PhysicalMemory &specmem);
protected: protected:
Addr base_addr; uint8_t *pmemAddr;
Addr pmem_size;
uint8_t *pmem_addr;
MemoryPort *port; MemoryPort *port;
int page_ptr; int pagePtr;
Tick lat; Tick lat;
public: public:
Addr new_page(); Addr new_page();
uint64_t size() { return pmem_size; } uint64_t size() { return params()->addrRange.size(); }
struct Params
{
std::string name;
Range<Addr> addrRange;
Tick latency;
};
protected:
Params *_params;
public: public:
PhysicalMemory(const std::string &n, Tick latency); const Params *params() const { return _params; }
PhysicalMemory(Params *p);
virtual ~PhysicalMemory(); virtual ~PhysicalMemory();
public: public:
@ -102,9 +111,9 @@ class PhysicalMemory : public MemObject
void virtual init(); void virtual init();
unsigned int drain(Event *de); unsigned int drain(Event *de);
private: protected:
Tick doFunctionalAccess(Packet *pkt); Tick doFunctionalAccess(Packet *pkt);
virtual Tick calculateLatency(Packet *pkt);
void recvStatusChange(Port::Status status); void recvStatusChange(Port::Status status);
public: public:

View file

@ -7,3 +7,21 @@ class PhysicalMemory(MemObject):
range = Param.AddrRange("Device Address") range = Param.AddrRange("Device Address")
file = Param.String('', "memory mapped file") file = Param.String('', "memory mapped file")
latency = Param.Latency(Parent.clock, "latency of an access") latency = Param.Latency(Parent.clock, "latency of an access")
class DRAMMemory(PhysicalMemory):
type = 'DRAMMemory'
# Many of these should be observed from the configuration
cpu_ratio = Param.Int(5,"ratio between CPU speed and memory bus speed")
mem_type = Param.String("SDRAM", "Type of DRAM (DRDRAM, SDRAM)")
mem_actpolicy = Param.String("open", "Open/Close policy")
memctrladdr_type = Param.String("interleaved", "Mapping interleaved or direct")
bus_width = Param.Int(16, "")
act_lat = Param.Int(2, "RAS to CAS delay")
cas_lat = Param.Int(1, "CAS delay")
war_lat = Param.Int(2, "write after read delay")
pre_lat = Param.Int(2, "precharge delay")
dpl_lat = Param.Int(2, "data in to precharge delay")
trc_lat = Param.Int(6, "row cycle delay")
num_banks = Param.Int(4, "Number of Banks")
num_cpus = Param.Int(4, "Number of CPUs connected to DRAM")