summaryrefslogtreecommitdiff
path: root/mem
diff options
context:
space:
mode:
Diffstat (limited to 'mem')
-rw-r--r--mem/bus.cc130
-rw-r--r--mem/bus.hh39
-rw-r--r--mem/mem_object.hh2
-rw-r--r--mem/packet.hh12
-rw-r--r--mem/page_table.cc17
-rw-r--r--mem/page_table.hh2
-rw-r--r--mem/physical.cc37
-rw-r--r--mem/physical.hh21
-rw-r--r--mem/port.cc6
-rw-r--r--mem/port.hh56
-rw-r--r--mem/request.hh104
-rw-r--r--mem/translating_port.cc30
-rw-r--r--mem/translating_port.hh20
-rw-r--r--mem/vport.cc69
-rw-r--r--mem/vport.hh109
15 files changed, 551 insertions, 103 deletions
diff --git a/mem/bus.cc b/mem/bus.cc
new file mode 100644
index 000000000..8e8bc2203
--- /dev/null
+++ b/mem/bus.cc
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/**
+ * @file Definition of a bus object.
+ */
+
+
+#include "bus.hh"
+#include "sim/builder.hh"
+
+/** Function called by the port when the bus is recieving a Timing
+ * transaction.*/
+bool
+Bus::recvTiming(Packet &pkt, int id)
+{
+
+ panic("I need to be implemented, but not right now.");
+}
+
+Port *
+Bus::findPort(Addr addr, int id)
+{
+ /* An interval tree would be a better way to do this. --ali. */
+ int dest_id = -1;
+ int i = 0;
+ bool found = false;
+
+ while (i < portList.size() && !found)
+ {
+ if (portList[i].range == addr) {
+ dest_id = portList[i].portId;
+ found = true;
+ }
+ }
+ assert(dest_id != -1 && "Unable to find destination");
+ // we shouldn't be sending this back to where it came from
+ assert(dest_id != id);
+
+ return interfaces[dest_id];
+}
+
+/** Function called by the port when the bus is recieving a Atomic
+ * transaction.*/
+Tick
+Bus::recvAtomic(Packet &pkt, int id)
+{
+ return findPort(pkt.addr, id)->sendAtomic(pkt);
+}
+
+/** Function called by the port when the bus is recieving a Functional
+ * transaction.*/
+void
+Bus::recvFunctional(Packet &pkt, int id)
+{
+ findPort(pkt.addr, id)->sendFunctional(pkt);
+}
+
+/** Function called by the port when the bus is recieving a status change.*/
+void
+Bus::recvStatusChange(Port::Status status, int id)
+{
+ assert(status == Port::RangeChange &&
+ "The other statuses need to be implemented.");
+
+ assert(id < interfaces.size() && id >= 0);
+ Port *port = interfaces[id];
+ AddrRangeList ranges;
+ AddrRangeList snoops;
+
+ 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();
+
+ portList.push_back(dm);
+}
+
+void
+Bus::BusPort::addressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+{
+ panic("I'm not implemented.\n");
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
+
+ Param<int> bus_id;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Bus)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Bus)
+ INIT_PARAM(bus_id, "junk bus id")
+END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+CREATE_SIM_OBJECT(Bus)
+{
+ return new Bus(getInstanceName());
+}
+
+REGISTER_SIM_OBJECT("Bus", Bus)
diff --git a/mem/bus.hh b/mem/bus.hh
index e26065295..fad44aba5 100644
--- a/mem/bus.hh
+++ b/mem/bus.hh
@@ -45,6 +45,13 @@
class Bus : public MemObject
{
+ struct DevMap {
+ int portId;
+ Range<Addr> range;
+ };
+ std::vector<DevMap> portList;
+
+
/** Function called by the port when the bus is recieving a Timing
transaction.*/
bool recvTiming(Packet &pkt, int id);
@@ -60,6 +67,16 @@ class Bus : public MemObject
/** Function called by the port when the bus is recieving a status change.*/
void recvStatusChange(Port::Status status, int id);
+ /** Find which port connected to this bus (if any) should be given a packet
+ * with this address.
+ * @param addr Address to find port for.
+ * @param id Id of the port this packet was received from (to prevent
+ * loops)
+ * @return pointer to port that the packet should be sent out of.
+ */
+ Port *
+ Bus::findPort(Addr addr, int id);
+
/** Decleration of the buses port type, one will be instantiated for each
of the interfaces connecting to the bus. */
class BusPort : public Port
@@ -103,26 +120,30 @@ class Bus : public MemObject
// downstream from this bus, yes? That is, the union of all
// the 'owned' address ranges of all the other interfaces on
// this bus...
- virtual void addressRanges(AddrRangeList &range_list, bool &owner);
- };
+ virtual void addressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+
+ // Hack to make translating port work without changes
+ virtual int deviceBlockSize() { return 32; }
- /** A count of the number of interfaces connected to this bus. */
- int num_interfaces;
+ };
/** An array of pointers to the peer port interfaces
connected to this bus.*/
- Port *interfaces[];
+ std::vector<Port*> interfaces;
public:
/** A function used to return the port associated with this bus object. */
- virtual Port *getPort(const char *if_name)
+ virtual Port *getPort(const std::string &if_name)
{
// if_name ignored? forced to be empty?
- int id = num_interfaces++;
- interfaces[id] = new BusPort(this, id);
- return interfaces[id];
+ int id = interfaces.size();
+ interfaces.push_back(new BusPort(this, id));
+ return interfaces.back();
}
+ Bus(const std::string &n)
+ : MemObject(n) {}
+
};
#endif //__MEM_BUS_HH__
diff --git a/mem/mem_object.hh b/mem/mem_object.hh
index 7b3d942a4..58930eccc 100644
--- a/mem/mem_object.hh
+++ b/mem/mem_object.hh
@@ -48,7 +48,7 @@ class MemObject : public SimObject
public:
/** Additional function to return the Port of a memory object. */
- virtual Port *getPort(const char *if_name = NULL) = 0;
+ virtual Port *getPort(const std::string &if_name) = 0;
};
#endif //__MEM_MEM_OBJECT_HH__
diff --git a/mem/packet.hh b/mem/packet.hh
index 260fc60f7..91e56385d 100644
--- a/mem/packet.hh
+++ b/mem/packet.hh
@@ -54,7 +54,8 @@ enum Command
enum PacketResult
{
Success,
- BadAddress
+ BadAddress,
+ Unknown
};
class SenderState{};
@@ -96,7 +97,11 @@ struct Packet
/** 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*/
+ 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. */
@@ -111,6 +116,9 @@ struct Packet
/** The command of the transaction. */
Command cmd;
+ /** The time this request was responded to. Used to calculate latencies. */
+ Tick time;
+
/** The result of the packet transaction. */
PacketResult result;
diff --git a/mem/page_table.cc b/mem/page_table.cc
index eb2c7cdbb..c4e1ea193 100644
--- a/mem/page_table.cc
+++ b/mem/page_table.cc
@@ -58,7 +58,7 @@ PageTable::~PageTable()
}
Fault
-PageTable::page_check(Addr addr, int size, uint32_t flags) const
+PageTable::page_check(Addr addr, int size) const
{
if (size < sizeof(uint64_t)) {
if (!isPowerOf2(size)) {
@@ -66,7 +66,7 @@ PageTable::page_check(Addr addr, int size, uint32_t flags) const
return genMachineCheckFault();
}
- if (((size - 1) & addr) && (flags & NO_ALIGN_FAULT == 0))
+ if ((size - 1) & addr)
return genAlignmentFault();
}
else {
@@ -75,7 +75,7 @@ PageTable::page_check(Addr addr, int size, uint32_t flags) const
return genMachineCheckFault();
}
- if (((sizeof(uint64_t) - 1) & addr) && (flags & NO_ALIGN_FAULT == 0))
+ if ((sizeof(uint64_t) - 1) & addr)
return genAlignmentFault();
}
@@ -121,11 +121,14 @@ PageTable::translate(Addr vaddr, Addr &paddr)
Fault
-PageTable::translate(CpuRequestPtr &req)
+PageTable::translate(RequestPtr &req)
{
- assert(pageAlign(req->vaddr + req->size - 1) == pageAlign(req->vaddr));
- if (!translate(req->vaddr, req->paddr)) {
+ Addr paddr;
+ assert(pageAlign(req->getVaddr() + req->getSize() - 1)
+ == pageAlign(req->getVaddr()));
+ if (!translate(req->getVaddr(), paddr)) {
return genMachineCheckFault();
}
- return page_check(req->paddr, req->size, req->flags);
+ req->setPaddr(paddr);
+ return page_check(req->getPaddr(), req->getSize());
}
diff --git a/mem/page_table.hh b/mem/page_table.hh
index 66cce7cd6..c799f8acd 100644
--- a/mem/page_table.hh
+++ b/mem/page_table.hh
@@ -83,7 +83,7 @@ class PageTable
* field of mem_req.
* @param req The memory request.
*/
- Fault translate(CpuRequestPtr &req);
+ Fault translate(RequestPtr &req);
};
diff --git a/mem/physical.cc b/mem/physical.cc
index c1e83fb9e..603f8f63e 100644
--- a/mem/physical.cc
+++ b/mem/physical.cc
@@ -70,7 +70,7 @@ PhysicalMemory::MemResponseEvent::description()
}
PhysicalMemory::PhysicalMemory(const string &n)
- : MemObject(n), base_addr(0), pmem_addr(NULL)
+ : MemObject(n), base_addr(0), pmem_addr(NULL), port(NULL)
{
// Hardcoded to 128 MB for now.
pmem_size = 1 << 27;
@@ -152,9 +152,15 @@ PhysicalMemory::doFunctionalAccess(Packet &pkt)
}
Port *
-PhysicalMemory::getPort(const char *if_name)
+PhysicalMemory::getPort(const std::string &if_name)
{
- if (if_name == NULL) {
+ if (if_name == "") {
+ if (port != NULL)
+ panic("PhysicalMemory::getPort: additional port requested to memory!");
+ port = new MemoryPort(this);
+ return port;
+ } else if (if_name == "functional") {
+ /* special port for functional writes at startup. */
return new MemoryPort(this);
} else {
panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
@@ -178,10 +184,18 @@ PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
}
void
-PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &range_list,
- bool &owner)
+PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
{
- panic("??");
+ memory->getAddressRanges(resp, snoop);
+}
+
+void
+PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+{
+ snoop.clear();
+ resp.clear();
+ resp.push_back(RangeSize(base_addr, pmem_size));
}
int
@@ -321,9 +335,6 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
Param<string> file;
-#if FULL_SYSTEM
- SimObjectParam<MemoryController *> mmu;
-#endif
Param<Range<Addr> > range;
END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
@@ -331,20 +342,12 @@ END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
INIT_PARAM_DFLT(file, "memory mapped file", ""),
-#if FULL_SYSTEM
- INIT_PARAM(mmu, "Memory Controller"),
-#endif
INIT_PARAM(range, "Device Address Range")
END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
CREATE_SIM_OBJECT(PhysicalMemory)
{
-#if FULL_SYSTEM
- if (mmu) {
- return new PhysicalMemory(getInstanceName(), range, mmu, file);
- }
-#endif
return new PhysicalMemory(getInstanceName());
}
diff --git a/mem/physical.hh b/mem/physical.hh
index b066d3dfc..53e86f85f 100644
--- a/mem/physical.hh
+++ b/mem/physical.hh
@@ -63,14 +63,12 @@ class PhysicalMemory : public MemObject
virtual void recvStatusChange(Status status);
- virtual void getDeviceAddressRanges(AddrRangeList &range_list,
- bool &owner);
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop);
virtual int deviceBlockSize();
};
- virtual Port * getPort(const char *if_name);
-
int numPorts;
int lat;
@@ -94,6 +92,7 @@ class PhysicalMemory : public MemObject
Addr base_addr;
Addr pmem_size;
uint8_t *pmem_addr;
+ MemoryPort *port;
int page_ptr;
public:
@@ -106,6 +105,9 @@ class PhysicalMemory : public MemObject
public:
int deviceBlockSize();
+ void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+ virtual Port *getPort(const std::string &if_name);
+ void virtual init() { port->sendStatusChange(Port::RangeChange); }
// fast back-door memory access for vtophys(), remote gdb, etc.
// uint64_t phys_read_qword(Addr addr) const;
@@ -119,16 +121,7 @@ class PhysicalMemory : public MemObject
public:
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-/*uint64_t
-PhysicalMemory::phys_read_qword(Addr addr) const
-{
- if (addr + sizeof(uint64_t) > pmem_size)
- return 0;
-
- return *(uint64_t *)(pmem_addr + addr);
-}*/
+};
#endif //__PHYSICAL_MEMORY_HH__
diff --git a/mem/port.cc b/mem/port.cc
index fb4f3b4e0..d19d8146c 100644
--- a/mem/port.cc
+++ b/mem/port.cc
@@ -36,15 +36,15 @@
void
Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
{
- Request req;
+ Request req(false);
Packet pkt;
pkt.req = &req;
pkt.cmd = cmd;
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
- pkt.addr = req.paddr = gen.addr();
- pkt.size = req.size = gen.size();
+ req.setPaddr(pkt.addr = gen.addr());
+ req.setSize(pkt.size = gen.size());
pkt.data = p;
sendFunctional(pkt);
p += gen.size();
diff --git a/mem/port.hh b/mem/port.hh
index 947e7896a..9557f654c 100644
--- a/mem/port.hh
+++ b/mem/port.hh
@@ -38,7 +38,6 @@
#ifndef __MEM_PORT_HH__
#define __MEM_PORT_HH__
-#include <string>
#include <list>
#include <inttypes.h>
@@ -55,6 +54,7 @@
*/
typedef std::list<Range<Addr> > AddrRangeList;
+typedef std::list<Range<Addr> >::iterator AddrRangeIter;
/**
* Ports are used to interface memory objects to
@@ -132,15 +132,11 @@ class Port
/** The peer port is requesting us to reply with a list of the ranges we
are responsible for.
- @param owner is an output param that, if set, indicates that the
- port is the owner of the specified ranges (i.e., slave, default
- responder, etc.). If 'owner' is false, the interface is
- interested in the specified ranges for snooping purposes. If
- an object wants to own some ranges and snoop on others, it will
- need to use two different ports.
+ @param resp is a list of ranges responded to
+ @param snoop is a list of ranges snooped
*/
- virtual void getDeviceAddressRanges(AddrRangeList &range_list,
- bool &owner)
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
{ panic("??"); }
public:
@@ -165,8 +161,8 @@ class Port
/** Function called by the associated device to send a functional access,
an access in which the data is instantly updated everywhere in the
- memory system, without affecting the current state of any block
- or moving the block.
+ memory system, without affecting the current state of any block or
+ moving the block.
*/
void sendFunctional(Packet &pkt)
{ return peer->recvFunctional(pkt); }
@@ -189,29 +185,29 @@ class Port
/** Called by the associated device if it wishes to find out the address
ranges connected to the peer ports devices.
*/
- void getPeerAddressRanges(AddrRangeList &range_list, bool &owner)
- { peer->getDeviceAddressRanges(range_list, owner); }
+ void getPeerAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+ { peer->getDeviceAddressRanges(resp, snoop); }
/** This function is a wrapper around sendFunctional()
that breaks a larger, arbitrarily aligned access into
appropriate chunks. The default implementation can use
getBlockSize() to determine the block size and go from there.
*/
- void readBlob(Addr addr, uint8_t *p, int size);
+ virtual void readBlob(Addr addr, uint8_t *p, int size);
/** This function is a wrapper around sendFunctional()
that breaks a larger, arbitrarily aligned access into
appropriate chunks. The default implementation can use
getBlockSize() to determine the block size and go from there.
*/
- void writeBlob(Addr addr, uint8_t *p, int size);
+ virtual void writeBlob(Addr addr, uint8_t *p, int size);
/** Fill size bytes starting at addr with byte value val. This
should not need to be virtual, since it can be implemented in
terms of writeBlob(). However, it shouldn't be
performance-critical either, so it could be if we wanted to.
*/
- void memsetBlob(Addr addr, uint8_t val, int size);
+ virtual void memsetBlob(Addr addr, uint8_t val, int size);
private:
@@ -220,4 +216,32 @@ class Port
void blobHelper(Addr addr, uint8_t *p, int size, Command cmd);
};
+/** A simple functional port that is only meant for one way communication to
+ * physical memory. It is only meant to be used to load data into memory before
+ * the simulation begins.
+ */
+
+class FunctionalPort : public Port
+{
+ public:
+ virtual bool recvTiming(Packet &pkt) { panic("FuncPort is UniDir"); }
+ virtual Tick recvAtomic(Packet &pkt) { panic("FuncPort is UniDir"); }
+ virtual void recvFunctional(Packet &pkt) { panic("FuncPort is UniDir"); }
+ virtual void recvStatusChange(Status status) {panic("FuncPort is UniDir");}
+
+ template <typename T>
+ inline void write(Addr addr, T d)
+ {
+ writeBlob(addr, (uint8_t*)&d, sizeof(T));
+ }
+
+ template <typename T>
+ inline T read(Addr addr)
+ {
+ T d;
+ readBlob(addr, (uint8_t*)&d, sizeof(T));
+ return d;
+ }
+};
+
#endif //__MEM_PORT_HH__
diff --git a/mem/request.hh b/mem/request.hh
index 4b4703a0b..90c46646e 100644
--- a/mem/request.hh
+++ b/mem/request.hh
@@ -37,10 +37,8 @@
#include "arch/isa_traits.hh"
class Request;
-class CpuRequest;
typedef Request* RequestPtr;
-typedef CpuRequest* CpuRequestPtr;
/** The request is a Load locked/store conditional. */
const unsigned LOCKED = 0x001;
@@ -65,45 +63,133 @@ class Request
{
//@todo Make Accesor functions, make these private.
public:
+ /** Cunstructor, needs a bool to signify if it is/isn't Cpu Request. */
+ Request(bool isCpu);
+
+//First non-cpu request fields
+ private:
/** The physical address of the request. */
Addr paddr;
-
- /** whether this req came from the CPU or not **DO we need this??***/
- bool nicReq;
+ /** Wether or not paddr is valid (has been written yet). */
+ bool validPaddr;
/** The size of the request. */
int size;
+ /** Wether or not size is valid (has been written yet). */
+ bool validSize;
/** The time this request was started. Used to calculate latencies. */
Tick time;
+ /** Wether or not time is valid (has been written yet). */
+ bool validTime;
/** Destination address if this is a block copy. */
Addr copyDest;
+ /** Wether or not copyDest is valid (has been written yet). */
+ bool validCopyDest;
+ /** Flag structure for the request. */
uint32_t flags;
-};
+ /** Wether or not flags is valid (has been written yet). */
+ bool validFlags;
-class CpuRequest : public Request
-{
- //@todo Make Accesor functions, make these private.
+//Accsesors for non-cpu request fields
public:
+ /** Accesor for paddr. */
+ Addr getPaddr();
+ /** Accesor for paddr. */
+ void setPaddr(Addr _paddr);
+
+ /** Accesor for size. */
+ int getSize();
+ /** Accesor for size. */
+ void setSize(int _size);
+
+ /** Accesor for time. */
+ Tick getTime();
+ /** Accesor for time. */
+ void setTime(Tick _time);
+
+ /** Accesor for copy dest. */
+ Addr getCopyDest();
+ /** Accesor for copy dest. */
+ void setCopyDest(Addr _copyDest);
+
+ /** Accesor for flags. */
+ uint32_t getFlags();
+ /** Accesor for paddr. */
+ void setFlags(uint32_t _flags);
+
+//Now cpu-request fields
+ private:
+ /** Bool to signify if this is a cpuRequest. */
+ bool cpuReq;
+
/** The virtual address of the request. */
Addr vaddr;
+ /** Wether or not the vaddr is valid. */
+ bool validVaddr;
/** The address space ID. */
int asid;
+ /** Wether or not the asid is valid. */
+ bool validAsid;
/** The return value of store conditional. */
uint64_t scResult;
+ /** Wether or not the sc result is valid. */
+ bool validScResult;
/** The cpu number for statistics. */
int cpuNum;
+ /** Wether or not the cpu number is valid. */
+ bool validCpuNum;
/** The requesting thread id. */
int threadNum;
+ /** Wether or not the thread id is valid. */
+ bool validThreadNum;
/** program counter of initiating access; for tracing/debugging */
Addr pc;
+ /** Wether or not the pc is valid. */
+ bool validPC;
+
+//Accessor Functions for cpu request fields
+ public:
+ /** Accesor function to determine if this is a cpu request or not.*/
+ bool isCpuRequest();
+
+ /** Accesor function for vaddr.*/
+ Addr getVaddr();
+ /** Accesor function for vaddr.*/
+ void setVaddr(Addr _vaddr);
+
+ /** Accesor function for asid.*/
+ int getAsid();
+ /** Accesor function for asid.*/
+ void setAsid(int _asid);
+
+ /** Accesor function for store conditional return value.*/
+ uint64_t getScResult();
+ /** Accesor function for store conditional return value.*/
+ void setScResult(uint64_t _scResult);
+
+ /** Accesor function for cpu number.*/
+ int getCpuNum();
+ /** Accesor function for cpu number.*/
+ void setCpuNum(int _cpuNum);
+
+ /** Accesor function for thread number.*/
+ int getThreadNum();
+ /** Accesor function for thread number.*/
+ void setThreadNum(int _threadNum);
+
+ /** Accesor function for pc.*/
+ Addr getPC();
+ /** Accesor function for pc.*/
+ void setPC(Addr _pc);
+
};
#endif // __MEM_REQUEST_HH__
diff --git a/mem/translating_port.cc b/mem/translating_port.cc
index f0059fc08..5dfeaff31 100644
--- a/mem/translating_port.cc
+++ b/mem/translating_port.cc
@@ -34,8 +34,8 @@
using namespace TheISA;
-TranslatingPort::TranslatingPort(Port *_port, PageTable *p_table)
- : port(_port), pTable(p_table)
+TranslatingPort::TranslatingPort(PageTable *p_table, bool alloc)
+ : pTable(p_table), allocating(alloc)
{ }
TranslatingPort::~TranslatingPort()
@@ -52,7 +52,7 @@ TranslatingPort::tryReadBlob(Addr addr, uint8_t *p, int size)
if (!pTable->translate(gen.addr(),paddr))
return false;
- port->readBlob(paddr, p + prevSize, gen.size());
+ Port::readBlob(paddr, p + prevSize, gen.size());
prevSize += gen.size();
}
@@ -68,7 +68,7 @@ TranslatingPort::readBlob(Addr addr, uint8_t *p, int size)
bool
-TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size, bool alloc)
+TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size)
{
Addr paddr;
@@ -77,7 +77,7 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size, bool alloc)
for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
if (!pTable->translate(gen.addr(), paddr)) {
- if (alloc) {
+ if (allocating) {
pTable->allocate(roundDown(gen.addr(), VMPageSize),
VMPageSize);
pTable->translate(gen.addr(), paddr);
@@ -86,7 +86,7 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size, bool alloc)
}
}
- port->writeBlob(paddr, p + prevSize, gen.size());
+ Port::writeBlob(paddr, p + prevSize, gen.size());
prevSize += gen.size();
}
@@ -95,21 +95,21 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size, bool alloc)
void
-TranslatingPort::writeBlob(Addr addr, uint8_t *p, int size, bool alloc)
+TranslatingPort::writeBlob(Addr addr, uint8_t *p, int size)
{
- if (!tryWriteBlob(addr, p, size, alloc))
+ if (!tryWriteBlob(addr, p, size))
fatal("writeBlob(0x%x, ...) failed", addr);
}
bool
-TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size, bool alloc)
+TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size)
{
Addr paddr;
for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
if (!pTable->translate(gen.addr(), paddr)) {
- if (alloc) {
+ if (allocating) {
pTable->allocate(roundDown(gen.addr(), VMPageSize),
VMPageSize);
pTable->translate(gen.addr(), paddr);
@@ -118,16 +118,16 @@ TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size, bool alloc)
}
}
- port->memsetBlob(paddr, val, gen.size());
+ Port::memsetBlob(paddr, val, gen.size());
}
return true;
}
void
-TranslatingPort::memsetBlob(Addr addr, uint8_t val, int size, bool alloc)
+TranslatingPort::memsetBlob(Addr addr, uint8_t val, int size)
{
- if (!tryMemsetBlob(addr, val, size, alloc))
+ if (!tryMemsetBlob(addr, val, size))
fatal("memsetBlob(0x%x, ...) failed", addr);
}
@@ -145,7 +145,7 @@ TranslatingPort::tryWriteString(Addr addr, const char *str)
if (!pTable->translate(vaddr++,paddr))
return false;
- port->writeBlob(paddr, &c, 1);
+ Port::writeBlob(paddr, &c, 1);
} while (c);
return true;
@@ -170,7 +170,7 @@ TranslatingPort::tryReadString(std::string &str, Addr addr)
if (!pTable->translate(vaddr++,paddr))
return false;
- port->readBlob(paddr, &c, 1);
+ Port::readBlob(paddr, &c, 1);
str += c;
} while (c);
diff --git a/mem/translating_port.hh b/mem/translating_port.hh
index 2ba3d68e2..7611ac3c7 100644
--- a/mem/translating_port.hh
+++ b/mem/translating_port.hh
@@ -29,34 +29,36 @@
#ifndef __MEM_TRANSLATING_PROT_HH__
#define __MEM_TRANSLATING_PROT_HH__
-class Port;
+#include "mem/port.hh"
+
class PageTable;
-class TranslatingPort
+class TranslatingPort : public FunctionalPort
{
private:
- Port *port;
PageTable *pTable;
+ bool allocating;
TranslatingPort(const TranslatingPort &specmem);
const TranslatingPort &operator=(const TranslatingPort &specmem);
public:
- TranslatingPort(Port *_port, PageTable *p_table);
+ TranslatingPort(PageTable *p_table, bool alloc = false);
virtual ~TranslatingPort();
public:
bool tryReadBlob(Addr addr, uint8_t *p, int size);
- bool tryWriteBlob(Addr addr, uint8_t *p, int size, bool alloc = false);
- bool tryMemsetBlob(Addr addr, uint8_t val, int size, bool alloc = false);
+ bool tryWriteBlob(Addr addr, uint8_t *p, int size);
+ bool tryMemsetBlob(Addr addr, uint8_t val, int size);
bool tryWriteString(Addr addr, const char *str);
bool tryReadString(std::string &str, Addr addr);
- void readBlob(Addr addr, uint8_t *p, int size);
- void writeBlob(Addr addr, uint8_t *p, int size, bool alloc = false);
- void memsetBlob(Addr addr, uint8_t val, int size, bool alloc = false);
+ virtual void readBlob(Addr addr, uint8_t *p, int size);
+ virtual void writeBlob(Addr addr, uint8_t *p, int size);
+ virtual void memsetBlob(Addr addr, uint8_t val, int size);
void writeString(Addr addr, const char *str);
void readString(std::string &str, Addr addr);
+
};
#endif
diff --git a/mem/vport.cc b/mem/vport.cc
new file mode 100644
index 000000000..cc569acf3
--- /dev/null
+++ b/mem/vport.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/**
+ * @file Port object definitions.
+ */
+
+#include "base/chunk_generator.hh"
+#include "mem/vport.hh"
+
+void
+VirtualPort::readBlob(Addr addr, uint8_t *p, int size)
+{
+ Addr paddr;
+ for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done();
+ gen.next())
+ {
+ if (xc)
+ paddr = TheISA::vtophys(xc,gen.addr());
+ else
+ paddr = TheISA::vtophys(gen.addr());
+
+ FunctionalPort::readBlob(paddr, p, gen.size());
+ p += gen.size();
+ }
+}
+
+void
+VirtualPort::writeBlob(Addr addr, uint8_t *p, int size)
+{
+ Addr paddr;
+ for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done();
+ gen.next())
+ {
+ if (xc)
+ paddr = TheISA::vtophys(xc,gen.addr());
+ else
+ paddr = TheISA::vtophys(gen.addr());
+
+ FunctionalPort::writeBlob(paddr, p, gen.size());
+ p += gen.size();
+ }
+}
+
diff --git a/mem/vport.hh b/mem/vport.hh
new file mode 100644
index 000000000..da036b981
--- /dev/null
+++ b/mem/vport.hh
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/**
+ * @file
+ * Virtual Port Object Decleration. These ports incorporate some translation
+ * into their access methods. Thus you can use one to read and write data
+ * to/from virtual addresses.
+ */
+
+#ifndef __MEM_VPORT_HH__
+#define __MEM_VPORT_HH__
+
+#include "mem/port.hh"
+#include "config/full_system.hh"
+#include "arch/vtophys.hh"
+
+
+/** A class that translates a virtual address to a physical address and then
+ * calls the above read/write functions. If an execution context is provided the
+ * address can alway be translated, If not it can only be translated if it is a
+ * simple address masking operation (such as alpha super page accesses).
+ */
+
+class VirtualPort : public FunctionalPort
+{
+ private:
+ ExecContext *xc;
+
+ public:
+ VirtualPort(ExecContext *_xc = NULL)
+ : xc(_xc)
+ {}
+
+ /** Return true if we have an exec context. This is used to prevent someone
+ * from accidently deleting the cpus statically allocated vport.
+ * @return true if an execution context isn't valid
+ */
+ bool nullExecContext() { return xc != NULL; }
+
+ /** Write a piece of data into a virtual address.
+ * @param vaddr virtual address to write to
+ * @param data data to write
+ */
+ template <typename T>
+ inline void write(Addr vaddr, T data)
+ {
+ Addr paddr;
+ if (xc)
+ paddr = TheISA::vtophys(xc,vaddr);
+ else
+ paddr = TheISA::vtophys(vaddr);
+
+ FunctionalPort::write(paddr, data);
+ }
+
+ /** Read data from a virtual address and return it.
+ * @param vaddr address to read
+ * @return data read
+ */
+
+ template <typename T>
+ inline T read(Addr vaddr)
+ {
+ Addr paddr;
+ if (xc)
+ paddr = TheISA::vtophys(xc,vaddr);
+ else
+ paddr = TheISA::vtophys(vaddr);
+
+ return FunctionalPort::read<T>(paddr);
+ }
+
+ /** Version of readblob that translates virt->phys and deals
+ * with page boundries. */
+ virtual void readBlob(Addr addr, uint8_t *p, int size);
+
+ /** Version of writeBlob that translates virt->phys and deals
+ * with page boundries. */
+ virtual void writeBlob(Addr addr, uint8_t *p, int size);
+};
+
+#endif //__MEM_VPORT_HH__
+