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:
parent
bb6af8eb8a
commit
2f145ac54a
|
@ -94,6 +94,7 @@ base_sources = Split('''
|
|||
|
||||
mem/bridge.cc
|
||||
mem/bus.cc
|
||||
mem/dram.cc
|
||||
mem/mem_object.cc
|
||||
mem/packet.cc
|
||||
mem/physical.cc
|
||||
|
|
2746
src/mem/dram.cc
Normal file
2746
src/mem/dram.cc
Normal file
File diff suppressed because it is too large
Load diff
172
src/mem/dram.hh
Normal file
172
src/mem/dram.hh
Normal 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__
|
||||
|
|
@ -54,25 +54,22 @@ using namespace std;
|
|||
using namespace TheISA;
|
||||
|
||||
|
||||
PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
|
||||
: MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
|
||||
PhysicalMemory::PhysicalMemory(Params *p)
|
||||
: MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p)
|
||||
{
|
||||
// Hardcoded to 128 MB for now.
|
||||
pmem_size = 1 << 27;
|
||||
|
||||
if (pmem_size % TheISA::PageBytes != 0)
|
||||
if (params()->addrRange.size() % TheISA::PageBytes != 0)
|
||||
panic("Memory Size not divisible by page size\n");
|
||||
|
||||
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);
|
||||
|
||||
if (pmem_addr == (void *)MAP_FAILED) {
|
||||
if (pmemAddr == (void *)MAP_FAILED) {
|
||||
perror("mmap");
|
||||
fatal("Could not mmap!\n");
|
||||
}
|
||||
|
||||
page_ptr = 0;
|
||||
pagePtr = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -85,18 +82,18 @@ PhysicalMemory::init()
|
|||
|
||||
PhysicalMemory::~PhysicalMemory()
|
||||
{
|
||||
if (pmem_addr)
|
||||
munmap(pmem_addr, pmem_size);
|
||||
if (pmemAddr)
|
||||
munmap(pmemAddr, params()->addrRange.size());
|
||||
//Remove memPorts?
|
||||
}
|
||||
|
||||
Addr
|
||||
PhysicalMemory::new_page()
|
||||
{
|
||||
Addr return_addr = page_ptr << LogVMPageSize;
|
||||
return_addr += base_addr;
|
||||
Addr return_addr = pagePtr << LogVMPageSize;
|
||||
return_addr += params()->addrRange.start;
|
||||
|
||||
++page_ptr;
|
||||
++pagePtr;
|
||||
return return_addr;
|
||||
}
|
||||
|
||||
|
@ -107,20 +104,25 @@ PhysicalMemory::deviceBlockSize()
|
|||
return 0;
|
||||
}
|
||||
|
||||
Tick
|
||||
PhysicalMemory::calculateLatency(Packet *pkt)
|
||||
{
|
||||
return lat;
|
||||
}
|
||||
|
||||
Tick
|
||||
PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
||||
{
|
||||
assert(pkt->getAddr() + pkt->getSize() < pmem_size);
|
||||
assert(pkt->getAddr() + pkt->getSize() < params()->addrRange.size());
|
||||
|
||||
switch (pkt->cmd) {
|
||||
case Packet::ReadReq:
|
||||
memcpy(pkt->getPtr<uint8_t>(),
|
||||
pmem_addr + pkt->getAddr() - base_addr,
|
||||
pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
||||
pkt->getSize());
|
||||
break;
|
||||
case Packet::WriteReq:
|
||||
memcpy(pmem_addr + pkt->getAddr() - base_addr,
|
||||
memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
||||
pkt->getPtr<uint8_t>(),
|
||||
pkt->getSize());
|
||||
// temporary hack: will need to add real LL/SC implementation
|
||||
|
@ -134,7 +136,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
|||
}
|
||||
|
||||
pkt->result = Packet::Success;
|
||||
return lat;
|
||||
return calculateLatency(pkt);
|
||||
}
|
||||
|
||||
Port *
|
||||
|
@ -181,7 +183,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
|||
{
|
||||
snoop.clear();
|
||||
resp.clear();
|
||||
resp.push_back(RangeSize(base_addr, pmem_size));
|
||||
resp.push_back(RangeSize(params()->addrRange.start, params()->addrRange.size()));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -232,7 +234,6 @@ PhysicalMemory::serialize(ostream &os)
|
|||
gzFile compressedMem;
|
||||
string filename = name() + ".physmem";
|
||||
|
||||
SERIALIZE_SCALAR(pmem_size);
|
||||
SERIALIZE_SCALAR(filename);
|
||||
|
||||
// write memory file
|
||||
|
@ -248,7 +249,7 @@ PhysicalMemory::serialize(ostream &os)
|
|||
fatal("Insufficient memory to allocate compression state for %s\n",
|
||||
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",
|
||||
filename);
|
||||
}
|
||||
|
@ -269,12 +270,8 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string §ion)
|
|||
const int chunkSize = 16384;
|
||||
|
||||
|
||||
// unmap file that was mmaped in the constructor
|
||||
munmap(pmem_addr, pmem_size);
|
||||
|
||||
string filename;
|
||||
|
||||
UNSERIALIZE_SCALAR(pmem_size);
|
||||
UNSERIALIZE_SCALAR(filename);
|
||||
|
||||
filename = cp->cptDir + "/" + filename;
|
||||
|
@ -291,11 +288,15 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string §ion)
|
|||
fatal("Insufficient memory to allocate compression state for %s\n",
|
||||
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);
|
||||
|
||||
if (pmem_addr == (void *)MAP_FAILED) {
|
||||
if (pmemAddr == (void *)MAP_FAILED) {
|
||||
perror("mmap");
|
||||
fatal("Could not mmap physical memory!\n");
|
||||
}
|
||||
|
@ -306,19 +307,19 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string §ion)
|
|||
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 */
|
||||
while (curSize < pmem_size) {
|
||||
while (curSize < params()->addrRange.size()) {
|
||||
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'"
|
||||
" 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);
|
||||
|
||||
for (int x = 0; x < bytesRead/sizeof(long); x++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -352,8 +353,11 @@ END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
|
|||
|
||||
CREATE_SIM_OBJECT(PhysicalMemory)
|
||||
{
|
||||
|
||||
return new PhysicalMemory(getInstanceName(), latency);
|
||||
PhysicalMemory::Params *p = new PhysicalMemory::Params;
|
||||
p->name = getInstanceName();
|
||||
p->addrRange = range;
|
||||
p->latency = latency;
|
||||
return new PhysicalMemory(p);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
|
||||
|
|
|
@ -80,19 +80,28 @@ class PhysicalMemory : public MemObject
|
|||
const PhysicalMemory &operator=(const PhysicalMemory &specmem);
|
||||
|
||||
protected:
|
||||
Addr base_addr;
|
||||
Addr pmem_size;
|
||||
uint8_t *pmem_addr;
|
||||
uint8_t *pmemAddr;
|
||||
MemoryPort *port;
|
||||
int page_ptr;
|
||||
int pagePtr;
|
||||
Tick lat;
|
||||
|
||||
public:
|
||||
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:
|
||||
PhysicalMemory(const std::string &n, Tick latency);
|
||||
const Params *params() const { return _params; }
|
||||
PhysicalMemory(Params *p);
|
||||
virtual ~PhysicalMemory();
|
||||
|
||||
public:
|
||||
|
@ -102,9 +111,9 @@ class PhysicalMemory : public MemObject
|
|||
void virtual init();
|
||||
unsigned int drain(Event *de);
|
||||
|
||||
private:
|
||||
protected:
|
||||
Tick doFunctionalAccess(Packet *pkt);
|
||||
|
||||
virtual Tick calculateLatency(Packet *pkt);
|
||||
void recvStatusChange(Port::Status status);
|
||||
|
||||
public:
|
||||
|
|
|
@ -7,3 +7,21 @@ class PhysicalMemory(MemObject):
|
|||
range = Param.AddrRange("Device Address")
|
||||
file = Param.String('', "memory mapped file")
|
||||
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")
|
||||
|
||||
|
|
Loading…
Reference in a new issue