diff options
Diffstat (limited to 'mem')
-rw-r--r-- | mem/bus.cc | 29 | ||||
-rw-r--r-- | mem/packet.hh | 123 | ||||
-rw-r--r-- | mem/physical.cc | 17 | ||||
-rw-r--r-- | mem/physical.hh | 4 | ||||
-rw-r--r-- | mem/port.cc | 2 |
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(); } |