summaryrefslogtreecommitdiff
path: root/mem
diff options
context:
space:
mode:
Diffstat (limited to 'mem')
-rw-r--r--mem/bus.cc29
-rw-r--r--mem/packet.hh123
-rw-r--r--mem/physical.cc17
-rw-r--r--mem/physical.hh4
-rw-r--r--mem/port.cc2
5 files changed, 143 insertions, 32 deletions
diff --git a/mem/bus.cc b/mem/bus.cc
index 5e84beb83..86e834894 100644
--- a/mem/bus.cc
+++ b/mem/bus.cc
@@ -97,21 +97,30 @@ Bus::recvStatusChange(Port::Status status, int id)
Port *port = interfaces[id];
AddrRangeList ranges;
AddrRangeList snoops;
+ AddrRangeIter iter;
+ std::vector<DevMap>::iterator portIter;
+
+ // Clean out any previously existent ids
+ for (portIter = portList.begin(); portIter != portList.end(); ) {
+ if (portIter->portId == id)
+ portIter = portList.erase(portIter);
+ else
+ portIter++;
+ }
port->getPeerAddressRanges(ranges, snoops);
// not dealing with snooping yet either
assert(snoops.size() == 0);
- // or multiple ranges
- assert(ranges.size() == 1);
-
- DevMap dm;
- dm.portId = id;
- dm.range = ranges.front();
-
- DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
- dm.range.end, id);
- portList.push_back(dm);
+ for(iter = ranges.begin(); iter != ranges.end(); iter++) {
+ DevMap dm;
+ dm.portId = id;
+ dm.range = *iter;
+
+ DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
+ dm.range.end, id);
+ portList.push_back(dm);
+ }
DPRINTF(MMU, "port list has %d entries\n", portList.size());
}
diff --git a/mem/packet.hh b/mem/packet.hh
index 843d34ac0..4329094d5 100644
--- a/mem/packet.hh
+++ b/mem/packet.hh
@@ -76,6 +76,26 @@ class Coherence{};
*/
struct Packet
{
+ private:
+ /** A pointer to the data being transfered. It can be differnt sizes
+ at each level of the heirarchy so it belongs in the packet,
+ not request. This may or may not be populated when a responder recieves
+ the packet. If not populated it memory should be allocated.
+ */
+ PacketDataPtr data;
+
+ /** Is the data pointer set to a value that shouldn't be freed when the
+ * packet is destroyed? */
+ bool staticData;
+ /** The data pointer points to a value that should be freed when the packet
+ * is destroyed. */
+ bool dynamicData;
+ /** the data pointer points to an array (thus delete [] ) needs to be called
+ * on it rather than simply delete.*/
+ bool arrayData;
+
+
+ public:
/** The address of the request, could be virtual or physical (depending on
cache configurations). */
Addr addr;
@@ -92,19 +112,10 @@ struct Packet
// assert(dynamic_cast<Foo>) etc.
/** A virtual base opaque structure used to hold the senders state. */
- SenderState *senderState; // virtual base opaque,
+ void *senderState; // virtual base opaque,
// assert(dynamic_cast<Foo>) etc.
- /** A pointer to the data being transfered. It can be differnt sizes
- at each level of the heirarchy so it belongs in the packet,
- not request.
- This pointer may be NULL! If it isn't null when received by the producer
- of data it refers to memory that has not been dynamically allocated.
- Otherwise the producer should simply allocate dynamic memory to use.
- */
- PacketDataPtr data;
-
- /** Indicates the size of the request. */
+ /** Indicates the size of the request. */
int size;
/** A index of the source of the transaction. */
@@ -130,10 +141,96 @@ struct Packet
short getDest() const { return dest; }
Packet()
- : result(Unknown)
+ : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ result(Unknown)
{}
- void reset() { result = Unknown; }
+ ~Packet()
+ { deleteData(); }
+
+
+ /** Minimally reset a packet so something like simple cpu can reuse it. */
+ void reset() {
+ result = Unknown;
+ if (dynamicData) {
+ deleteData();
+ dynamicData = false;
+ arrayData = false;
+ }
+ }
+
+ /** Set the data pointer to the following value that should not be freed. */
+ template <typename T>
+ void dataStatic(T *p) {
+ assert(!dynamicData);
+ data = (PacketDataPtr)p;
+ staticData = true;
+ }
+
+ /** Set the data pointer to a value that should have delete [] called on it.
+ */
+ template <typename T>
+ void dataDynamicArray(T *p) {
+ assert(!staticData && !dynamicData);
+ data = (PacketDataPtr)p;
+ dynamicData = true;
+ arrayData = true;
+ }
+
+ /** set the data pointer to a value that should have delete called on it. */
+ template <typename T>
+ void dataDynamic(T *p) {
+ assert(!staticData && !dynamicData);
+ data = (PacketDataPtr)p;
+ dynamicData = true;
+ arrayData = false;
+ }
+
+ /** return the value of what is pointed to in the packet. */
+ template <typename T>
+ T get() {
+ assert(staticData || dynamicData);
+ assert(sizeof(T) <= size);
+ return *(T*)data;
+ }
+
+ /** get a pointer to the data ptr. */
+ template <typename T>
+ T* getPtr() {
+ assert(staticData || dynamicData);
+ return (T*)data;
+ }
+
+
+ /** set the value in the data pointer to v. */
+ template <typename T>
+ void set(T v) {
+ assert(sizeof(T) <= size);
+ *(T*)data = v;
+ }
+
+ /** delete the data pointed to in the data pointer. Ok to call to matter how
+ * data was allocted. */
+ void deleteData() {
+ assert(staticData || dynamicData);
+ if (staticData)
+ return;
+
+ if (arrayData)
+ delete [] data;
+ else
+ delete data;
+ }
+
+ /** If there isn't data in the packet, allocate some. */
+ void allocate() {
+ if (data)
+ return;
+ assert(!staticData);
+ dynamicData = true;
+ arrayData = true;
+ data = new uint8_t[size];
+ }
};
#endif //__MEM_PACKET_HH
diff --git a/mem/physical.cc b/mem/physical.cc
index b00935990..02a48b22b 100644
--- a/mem/physical.cc
+++ b/mem/physical.cc
@@ -69,8 +69,8 @@ PhysicalMemory::MemResponseEvent::description()
return "Physical Memory Timing Access respnse event";
}
-PhysicalMemory::PhysicalMemory(const string &n)
- : MemObject(n), base_addr(0), pmem_addr(NULL), port(NULL)
+PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
+ : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
{
// Hardcoded to 128 MB for now.
pmem_size = 1 << 27;
@@ -137,6 +137,7 @@ Tick
PhysicalMemory::doAtomicAccess(Packet &pkt)
{
doFunctionalAccess(pkt);
+ pkt.time = curTick + lat;
return curTick + lat;
}
@@ -147,10 +148,12 @@ PhysicalMemory::doFunctionalAccess(Packet &pkt)
switch (pkt.cmd) {
case Read:
- memcpy(pkt.data, pmem_addr + pkt.addr - base_addr, pkt.size);
+ memcpy(pkt.getPtr<uint8_t>(), pmem_addr + pkt.addr - base_addr,
+ pkt.size);
break;
case Write:
- memcpy(pmem_addr + pkt.addr - base_addr, pkt.data, pkt.size);
+ memcpy(pmem_addr + pkt.addr - base_addr, pkt.getPtr<uint8_t>(),
+ pkt.size);
break;
default:
panic("unimplemented");
@@ -344,20 +347,22 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
Param<string> file;
Param<Range<Addr> > range;
+ Param<Tick> latency;
END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
INIT_PARAM_DFLT(file, "memory mapped file", ""),
- INIT_PARAM(range, "Device Address Range")
+ INIT_PARAM(range, "Device Address Range"),
+ INIT_PARAM(latency, "Memory access latency")
END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
CREATE_SIM_OBJECT(PhysicalMemory)
{
- return new PhysicalMemory(getInstanceName());
+ return new PhysicalMemory(getInstanceName(), latency);
}
REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
diff --git a/mem/physical.hh b/mem/physical.hh
index ce0a2099c..f87683c45 100644
--- a/mem/physical.hh
+++ b/mem/physical.hh
@@ -71,7 +71,6 @@ class PhysicalMemory : public MemObject
int numPorts;
- int lat;
struct MemResponseEvent : public Event
{
@@ -94,13 +93,14 @@ class PhysicalMemory : public MemObject
uint8_t *pmem_addr;
MemoryPort *port;
int page_ptr;
+ Tick lat;
public:
Addr new_page();
uint64_t size() { return pmem_size; }
public:
- PhysicalMemory(const std::string &n);
+ PhysicalMemory(const std::string &n, Tick latency);
virtual ~PhysicalMemory();
public:
diff --git a/mem/port.cc b/mem/port.cc
index d312f3e3c..32031d96c 100644
--- a/mem/port.cc
+++ b/mem/port.cc
@@ -45,7 +45,7 @@ Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
!gen.done(); gen.next()) {
req.setPaddr(pkt.addr = gen.addr());
req.setSize(pkt.size = gen.size());
- pkt.data = p;
+ pkt.dataStatic(p);
sendFunctional(pkt);
p += gen.size();
}