summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/bridge.cc261
-rw-r--r--src/mem/bridge.hh187
-rw-r--r--src/mem/bus.cc234
-rw-r--r--src/mem/bus.hh173
-rw-r--r--src/mem/cache/prefetch/tagged_prefetcher_impl.hh75
-rw-r--r--src/mem/config/prefetch.hh41
-rw-r--r--src/mem/mem_object.cc39
-rw-r--r--src/mem/mem_object.hh56
-rw-r--r--src/mem/packet.cc107
-rw-r--r--src/mem/packet.hh300
-rw-r--r--src/mem/page_table.cc137
-rw-r--r--src/mem/page_table.hh92
-rw-r--r--src/mem/physical.cc378
-rw-r--r--src/mem/physical.hh129
-rw-r--r--src/mem/port.cc85
-rw-r--r--src/mem/port.hh275
-rw-r--r--src/mem/port_impl.hh53
-rw-r--r--src/mem/request.hh230
-rw-r--r--src/mem/translating_port.cc190
-rw-r--r--src/mem/translating_port.hh64
-rw-r--r--src/mem/vport.cc71
-rw-r--r--src/mem/vport.hh79
22 files changed, 3256 insertions, 0 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
new file mode 100644
index 000000000..3718cbaaf
--- /dev/null
+++ b/src/mem/bridge.cc
@@ -0,0 +1,261 @@
+
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ * Steve Reinhardt
+ */
+
+/**
+ * @file Definition of a simple bus bridge without buffering.
+ */
+
+#include <algorithm>
+
+#include "base/trace.hh"
+#include "mem/bridge.hh"
+#include "sim/builder.hh"
+
+Bridge::BridgePort::BridgePort(const std::string &_name,
+ Bridge *_bridge, BridgePort *_otherPort,
+ int _delay, int _queueLimit)
+ : Port(_name), bridge(_bridge), otherPort(_otherPort),
+ delay(_delay), outstandingResponses(0),
+ queueLimit(_queueLimit), sendEvent(this)
+{
+}
+
+Bridge::Bridge(const std::string &n, int qsa, int qsb,
+ Tick _delay, int write_ack)
+ : MemObject(n),
+ portA(n + "-portA", this, &portB, _delay, qsa),
+ portB(n + "-portB", this, &portA, _delay, qsa),
+ ackWrites(write_ack)
+{
+}
+
+Port *
+Bridge::getPort(const std::string &if_name)
+{
+ BridgePort *port;
+
+ if (if_name == "side_a")
+ port = &portA;
+ else if (if_name == "side_b")
+ port = &portB;
+ else
+ return NULL;
+
+ if (port->getPeer() != NULL)
+ panic("bridge side %s already connected to.", if_name);
+ return port;
+}
+
+
+void
+Bridge::init()
+{
+ // Make sure that both sides are connected to.
+ if (portA.getPeer() == NULL || portB.getPeer() == NULL)
+ panic("Both ports of bus bridge are not connected to a bus.\n");
+}
+
+
+/** Function called by the port when the bus is receiving a Timing
+ * transaction.*/
+bool
+Bridge::BridgePort::recvTiming(Packet *pkt)
+{
+ DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr());
+
+ return otherPort->queueForSendTiming(pkt);
+}
+
+
+bool
+Bridge::BridgePort::queueForSendTiming(Packet *pkt)
+{
+ if (queueFull())
+ return false;
+
+ if (pkt->isResponse()) {
+ // This is a response for a request we forwarded earlier. The
+ // corresponding PacketBuffer should be stored in the packet's
+ // senderState field.
+ PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
+ assert(buf != NULL);
+ // set up new packet dest & senderState based on values saved
+ // from original request
+ buf->fixResponse(pkt);
+ DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n",
+ pkt->senderState, buf);
+ DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
+ delete buf;
+ }
+
+ Tick readyTime = curTick + delay;
+ PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
+ DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n",
+ buf->origSenderState, buf);
+
+ // If we're about to put this packet at the head of the queue, we
+ // need to schedule an event to do the transmit. Otherwise there
+ // should already be an event scheduled for sending the head
+ // packet.
+ if (sendQueue.empty()) {
+ sendEvent.schedule(readyTime);
+ }
+
+ sendQueue.push_back(buf);
+
+ return true;
+}
+
+void
+Bridge::BridgePort::trySend()
+{
+ assert(!sendQueue.empty());
+
+ bool was_full = queueFull();
+
+ PacketBuffer *buf = sendQueue.front();
+
+ assert(buf->ready <= curTick);
+
+ Packet *pkt = buf->pkt;
+
+ DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
+ buf->origSrc, pkt->getDest(), pkt->getAddr());
+
+ if (sendTiming(pkt)) {
+ // send successful
+ sendQueue.pop_front();
+ buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
+
+ if (buf->expectResponse) {
+ // Must wait for response. We just need to count outstanding
+ // responses (in case we want to cap them); PacketBuffer
+ // pointer will be recovered on response.
+ ++outstandingResponses;
+ DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
+ outstandingResponses);
+ } else {
+ // no response expected... deallocate packet buffer now.
+ DPRINTF(BusBridge, " successful: no response expected\n");
+ delete buf;
+ }
+
+ // If there are more packets to send, schedule event to try again.
+ if (!sendQueue.empty()) {
+ buf = sendQueue.front();
+ sendEvent.schedule(std::max(buf->ready, curTick + 1));
+ }
+ // Let things start sending again
+ if (was_full) {
+ DPRINTF(BusBridge, "Queue was full, sending retry\n");
+ otherPort->sendRetry();
+ }
+
+ } else {
+ DPRINTF(BusBridge, " unsuccessful\n");
+ }
+}
+
+
+void
+Bridge::BridgePort::recvRetry()
+{
+ trySend();
+}
+
+/** Function called by the port when the bus is receiving a Atomic
+ * transaction.*/
+Tick
+Bridge::BridgePort::recvAtomic(Packet *pkt)
+{
+ return otherPort->sendAtomic(pkt) + delay;
+}
+
+/** Function called by the port when the bus is receiving a Functional
+ * transaction.*/
+void
+Bridge::BridgePort::recvFunctional(Packet *pkt)
+{
+ std::list<PacketBuffer*>::iterator i;
+ bool pktContinue = true;
+
+ for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
+ if (pkt->intersect((*i)->pkt)) {
+ pktContinue &= fixPacket(pkt, (*i)->pkt);
+ }
+ }
+
+ if (pktContinue) {
+ otherPort->sendFunctional(pkt);
+ }
+}
+
+/** Function called by the port when the bus is receiving a status change.*/
+void
+Bridge::BridgePort::recvStatusChange(Port::Status status)
+{
+ otherPort->sendStatusChange(status);
+}
+
+void
+Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+{
+ otherPort->getPeerAddressRanges(resp, snoop);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
+
+ Param<int> queue_size_a;
+ Param<int> queue_size_b;
+ Param<Tick> delay;
+ Param<bool> write_ack;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Bridge)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge)
+
+ INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"),
+ INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"),
+ INIT_PARAM(delay, "The miminum delay to cross this bridge"),
+ INIT_PARAM(write_ack, "Acknowledge any writes that are received.")
+
+END_INIT_SIM_OBJECT_PARAMS(Bridge)
+
+CREATE_SIM_OBJECT(Bridge)
+{
+ return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay,
+ write_ack);
+}
+
+REGISTER_SIM_OBJECT("Bridge", Bridge)
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh
new file mode 100644
index 000000000..37fb92662
--- /dev/null
+++ b/src/mem/bridge.hh
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ * Steve Reinhardt
+ */
+
+/**
+ * @file Decleration of a simple bus bridge object with no buffering
+ */
+
+#ifndef __MEM_BRIDGE_HH__
+#define __MEM_BRIDGE_HH__
+
+#include <string>
+#include <list>
+#include <inttypes.h>
+#include <queue>
+
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+
+class Bridge : public MemObject
+{
+ protected:
+ /** Decleration of the buses port type, one will be instantiated for each
+ of the interfaces connecting to the bus. */
+ class BridgePort : public Port
+ {
+ /** A pointer to the bridge to which this port belongs. */
+ Bridge *bridge;
+
+ /**
+ * Pointer to the port on the other side of the bridge
+ * (connected to the other bus).
+ */
+ BridgePort *otherPort;
+
+ /** Minimum delay though this bridge. */
+ Tick delay;
+
+ class PacketBuffer : public Packet::SenderState {
+
+ public:
+ Tick ready;
+ Packet *pkt;
+ Packet::SenderState *origSenderState;
+ short origSrc;
+ bool expectResponse;
+
+ PacketBuffer(Packet *_pkt, Tick t)
+ : ready(t), pkt(_pkt),
+ origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
+ expectResponse(_pkt->needsResponse())
+ {
+ if (!pkt->isResponse())
+ pkt->senderState = this;
+ }
+
+ void fixResponse(Packet *pkt)
+ {
+ assert(pkt->senderState == this);
+ pkt->setDest(origSrc);
+ pkt->senderState = origSenderState;
+ }
+ };
+
+ /**
+ * Outbound packet queue. Packets are held in this queue for a
+ * specified delay to model the processing delay of the
+ * bridge.
+ */
+ std::list<PacketBuffer*> sendQueue;
+
+ int outstandingResponses;
+
+ /** Max queue size for outbound packets */
+ int queueLimit;
+
+ /**
+ * Is this side blocked from accepting outbound packets?
+ */
+ bool queueFull() { return (sendQueue.size() == queueLimit); }
+
+ bool queueForSendTiming(Packet *pkt);
+
+ void finishSend(PacketBuffer *buf);
+
+ /**
+ * Handle send event, scheduled when the packet at the head of
+ * the outbound queue is ready to transmit (for timing
+ * accesses only).
+ */
+ void trySend();
+
+ class SendEvent : public Event
+ {
+ BridgePort *port;
+
+ public:
+ SendEvent(BridgePort *p)
+ : Event(&mainEventQueue), port(p) {}
+
+ virtual void process() { port->trySend(); }
+
+ virtual const char *description() { return "bridge send event"; }
+ };
+
+ SendEvent sendEvent;
+
+ public:
+
+ /** Constructor for the BusPort.*/
+ BridgePort(const std::string &_name,
+ Bridge *_bridge, BridgePort *_otherPort,
+ int _delay, int _queueLimit);
+
+ protected:
+
+ /** When receiving a timing request from the peer port,
+ pass it to the bridge. */
+ virtual bool recvTiming(Packet *pkt);
+
+ /** When receiving a retry request from the peer port,
+ pass it to the bridge. */
+ virtual void recvRetry();
+
+ /** When receiving a Atomic requestfrom the peer port,
+ pass it to the bridge. */
+ virtual Tick recvAtomic(Packet *pkt);
+
+ /** When receiving a Functional request from the peer port,
+ pass it to the bridge. */
+ virtual void recvFunctional(Packet *pkt);
+
+ /** When receiving a status changefrom the peer port,
+ pass it to the bridge. */
+ virtual void recvStatusChange(Status status);
+
+ /** When receiving a address range request the peer port,
+ pass it to the bridge. */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop);
+ };
+
+ BridgePort portA, portB;
+
+ /** If this bridge should acknowledge writes. */
+ bool ackWrites;
+
+ public:
+
+ /** A function used to return the port associated with this bus object. */
+ virtual Port *getPort(const std::string &if_name);
+
+ virtual void init();
+
+ Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack);
+};
+
+#endif //__MEM_BUS_HH__
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
new file mode 100644
index 000000000..919acd23c
--- /dev/null
+++ b/src/mem/bus.cc
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ */
+
+/**
+ * @file Definition of a bus object.
+ */
+
+
+#include "base/trace.hh"
+#include "mem/bus.hh"
+#include "sim/builder.hh"
+
+Port *
+Bus::getPort(const std::string &if_name)
+{
+ // if_name ignored? forced to be empty?
+ int id = interfaces.size();
+ BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
+ interfaces.push_back(bp);
+ return bp;
+}
+
+/** Get the ranges of anyone that we are connected to. */
+void
+Bus::init()
+{
+ std::vector<Port*>::iterator intIter;
+ for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
+ (*intIter)->sendStatusChange(Port::RangeChange);
+}
+
+
+/** Function called by the port when the bus is receiving a Timing
+ * transaction.*/
+bool
+Bus::recvTiming(Packet *pkt)
+{
+ Port *port;
+ DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+
+ short dest = pkt->getDest();
+ if (dest == Packet::Broadcast) {
+ port = findPort(pkt->getAddr(), pkt->getSrc());
+ } else {
+ assert(dest >= 0 && dest < interfaces.size());
+ assert(dest != pkt->getSrc()); // catch infinite loops
+ port = interfaces[dest];
+ }
+ if (port->sendTiming(pkt)) {
+ // packet was successfully sent, just return true.
+ return true;
+ }
+
+ // packet not successfully sent
+ retryList.push_back(interfaces[pkt->getSrc()]);
+ return false;
+}
+
+void
+Bus::recvRetry(int id)
+{
+ // Go through all the elements on the list calling sendRetry on each
+ // This is not very efficient at all but it works. Ultimately we should end
+ // up with something that is more intelligent.
+ int initialSize = retryList.size();
+ int i;
+ Port *p;
+
+ for (i = 0; i < initialSize; i++) {
+ assert(retryList.size() > 0);
+ p = retryList.front();
+ retryList.pop_front();
+ p->sendRetry();
+ }
+}
+
+
+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;
+ DPRINTF(Bus, " found addr 0x%llx on device %d\n", addr, dest_id);
+ }
+ i++;
+ }
+ if (dest_id == -1)
+ panic("Unable to find destination for addr: %llx", addr);
+
+ // 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 receiving a Atomic
+ * transaction.*/
+Tick
+Bus::recvAtomic(Packet *pkt)
+{
+ DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+ assert(pkt->getDest() == Packet::Broadcast);
+ return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
+}
+
+/** Function called by the port when the bus is receiving a Functional
+ * transaction.*/
+void
+Bus::recvFunctional(Packet *pkt)
+{
+ DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+ assert(pkt->getDest() == Packet::Broadcast);
+ findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt);
+}
+
+/** Function called by the port when the bus is receiving a status change.*/
+void
+Bus::recvStatusChange(Port::Status status, int id)
+{
+ assert(status == Port::RangeChange &&
+ "The other statuses need to be implemented.");
+
+ DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
+
+ assert(id < interfaces.size() && id >= 0);
+ int x;
+ 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);
+ for(iter = ranges.begin(); iter != ranges.end(); iter++) {
+ DevMap dm;
+ dm.portId = id;
+ dm.range = *iter;
+
+ DPRINTF(BusAddrRanges, "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());
+
+ // tell all our peers that our address range has changed.
+ // Don't tell the device that caused this change, it already knows
+ for (x = 0; x < interfaces.size(); x++)
+ if (x != id)
+ interfaces[x]->sendStatusChange(Port::RangeChange);
+}
+
+void
+Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
+{
+ std::vector<DevMap>::iterator portIter;
+
+ resp.clear();
+ snoop.clear();
+
+ DPRINTF(BusAddrRanges, "received address range request, returning:\n");
+ for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
+ if (portIter->portId != id) {
+ resp.push_back(portIter->range);
+ DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",
+ portIter->range.start, portIter->range.end);
+ }
+ }
+}
+
+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, "a globally unique bus id")
+END_INIT_SIM_OBJECT_PARAMS(Bus)
+
+CREATE_SIM_OBJECT(Bus)
+{
+ return new Bus(getInstanceName(), bus_id);
+}
+
+REGISTER_SIM_OBJECT("Bus", Bus)
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
new file mode 100644
index 000000000..50bfba6e4
--- /dev/null
+++ b/src/mem/bus.hh
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2002-2005 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
+ */
+
+/**
+ * @file Decleration of a bus object.
+ */
+
+#ifndef __MEM_BUS_HH__
+#define __MEM_BUS_HH__
+
+#include <string>
+#include <list>
+#include <inttypes.h>
+
+#include "base/range.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "mem/request.hh"
+
+class Bus : public MemObject
+{
+ /** a globally unique id for this bus. */
+ int busId;
+
+ 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);
+
+ /** Function called by the port when the bus is recieving a Atomic
+ transaction.*/
+ Tick recvAtomic(Packet *pkt);
+
+ /** Function called by the port when the bus is recieving a Functional
+ transaction.*/
+ void recvFunctional(Packet *pkt);
+
+ /** Timing function called by port when it is once again able to process
+ * requests. */
+ void recvRetry(int id);
+
+ /** 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 *findPort(Addr addr, int id);
+
+ /** Process address range request.
+ * @param resp addresses that we can respond to
+ * @param snoop addresses that we would like to snoop
+ * @param id ide of the busport that made the request.
+ */
+ void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, 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
+ {
+ /** A pointer to the bus to which this port belongs. */
+ Bus *bus;
+
+ /** A id to keep track of the intercafe ID this port is connected to. */
+ int id;
+
+ public:
+
+ /** Constructor for the BusPort.*/
+ BusPort(const std::string &_name, Bus *_bus, int _id)
+ : Port(_name), bus(_bus), id(_id)
+ { }
+
+ protected:
+
+ /** When reciving a timing request from the peer port (at id),
+ pass it to the bus. */
+ virtual bool recvTiming(Packet *pkt)
+ { pkt->setSrc(id); return bus->recvTiming(pkt); }
+
+ /** When reciving a Atomic requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual Tick recvAtomic(Packet *pkt)
+ { pkt->setSrc(id); return bus->recvAtomic(pkt); }
+
+ /** When reciving a Functional requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual void recvFunctional(Packet *pkt)
+ { pkt->setSrc(id); bus->recvFunctional(pkt); }
+
+ /** When reciving a status changefrom the peer port (at id),
+ pass it to the bus. */
+ virtual void recvStatusChange(Status status)
+ { bus->recvStatusChange(status, id); }
+
+ /** When reciving a retry from the peer port (at id),
+ pass it to the bus. */
+ virtual void recvRetry()
+ { bus->recvRetry(id); }
+
+ // This should return all the 'owned' addresses that are
+ // 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 getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+ { bus->addressRanges(resp, snoop, id); }
+
+ // Hack to make translating port work without changes
+ virtual int deviceBlockSize() { return 32; }
+
+ };
+
+ /** An array of pointers to the peer port interfaces
+ connected to this bus.*/
+ std::vector<Port*> interfaces;
+
+ /** An array of pointers to ports that retry should be called on because the
+ * original send failed for whatever reason.*/
+ std::list<Port*> retryList;
+
+ public:
+
+ /** A function used to return the port associated with this bus object. */
+ virtual Port *getPort(const std::string &if_name);
+
+ virtual void init();
+
+ Bus(const std::string &n, int bus_id)
+ : MemObject(n), busId(bus_id) {}
+
+};
+
+#endif //__MEM_BUS_HH__
diff --git a/src/mem/cache/prefetch/tagged_prefetcher_impl.hh b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh
new file mode 100644
index 000000000..7bdabbe14
--- /dev/null
+++ b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2005 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
+ */
+
+/**
+ * @file
+ * Describes a tagged prefetcher based on template policies.
+ */
+
+#include "mem/cache/prefetch/tagged_prefetcher.hh"
+
+template <class TagStore, class Buffering>
+TaggedPrefetcher<TagStore, Buffering>::
+TaggedPrefetcher(int size, bool pageStop, bool serialSquash,
+ bool cacheCheckPush, bool onlyData,
+ Tick latency, int degree)
+ :Prefetcher<TagStore, Buffering>(size, pageStop, serialSquash,
+ cacheCheckPush, onlyData),
+ latency(latency), degree(degree)
+{
+}
+
+template <class TagStore, class Buffering>
+void
+TaggedPrefetcher<TagStore, Buffering>::
+calculatePrefetch(MemReqPtr &req, std::list<Addr> &addresses,
+ std::list<Tick> &delays)
+{
+ Addr blkAddr = req->paddr & ~(Addr)(this->blkSize-1);
+
+ for (int d=1; d <= degree; d++) {
+ Addr newAddr = blkAddr + d*(this->blkSize);
+ if (this->pageStop &&
+ (blkAddr & ~(TheISA::VMPageSize - 1)) !=
+ (newAddr & ~(TheISA::VMPageSize - 1)))
+ {
+ //Spanned the page, so now stop
+ this->pfSpanPage += degree - d + 1;
+ return;
+ }
+ else
+ {
+ addresses.push_back(newAddr);
+ delays.push_back(latency);
+ }
+ }
+}
+
+
diff --git a/src/mem/config/prefetch.hh b/src/mem/config/prefetch.hh
new file mode 100644
index 000000000..d24db79da
--- /dev/null
+++ b/src/mem/config/prefetch.hh
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004-2005 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
+ */
+
+/**
+ * @file
+ * Central location to configure which prefetch types we want to build
+ * into the simulator. In the future, this should probably be
+ * autogenerated by some sort of configuration script.
+ */
+#define USE_TAGGED 1 //Be sure not to turn this off, it is also used for no
+ //prefetching case unless you always want to use a
+ //different prefetcher
+//#define USE_STRIDED 1
+//#define USE_GHB 1
diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc
new file mode 100644
index 000000000..d4d3fd283
--- /dev/null
+++ b/src/mem/mem_object.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002-2005 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: Steve Reinhardt
+ */
+
+#include "mem/mem_object.hh"
+#include "sim/param.hh"
+
+MemObject::MemObject(const std::string &name)
+ : SimObject(name)
+{
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("MemObject", MemObject)
diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh
new file mode 100644
index 000000000..ac547619d
--- /dev/null
+++ b/src/mem/mem_object.hh
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2002-2005 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
+ */
+
+/**
+ * @file
+ * Base Memory Object decleration.
+ */
+
+#ifndef __MEM_MEM_OBJECT_HH__
+#define __MEM_MEM_OBJECT_HH__
+
+#include "sim/sim_object.hh"
+#include "mem/port.hh"
+
+/**
+ * The base MemoryObject class, allows for an accesor function to a
+ * simobj that returns the Port.
+ */
+class MemObject : public SimObject
+{
+ public:
+ MemObject(const std::string &name);
+
+ public:
+ /** Additional function to return the Port of a memory object. */
+ virtual Port *getPort(const std::string &if_name) = 0;
+};
+
+#endif //__MEM_MEM_OBJECT_HH__
diff --git a/src/mem/packet.cc b/src/mem/packet.cc
new file mode 100644
index 000000000..56dd2bdfa
--- /dev/null
+++ b/src/mem/packet.cc
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ * Steve Reinhardt
+ */
+
+/**
+ * @file
+ * Definition of the Packet Class, a packet is a transaction occuring
+ * between a single level of the memory heirarchy (ie L1->L2).
+ */
+#include "base/misc.hh"
+#include "mem/packet.hh"
+
+static const std::string ReadReqString("ReadReq");
+static const std::string WriteReqString("WriteReq");
+static const std::string WriteReqNoAckString("WriteReqNoAck");
+static const std::string ReadRespString("ReadResp");
+static const std::string WriteRespString("WriteResp");
+static const std::string OtherCmdString("<other>");
+
+const std::string &
+Packet::cmdString() const
+{
+ switch (cmd) {
+ case ReadReq: return ReadReqString;
+ case WriteReq: return WriteReqString;
+ case WriteReqNoAck: return WriteReqNoAckString;
+ case ReadResp: return ReadRespString;
+ case WriteResp: return WriteRespString;
+ default: return OtherCmdString;
+ }
+}
+
+/** delete the data pointed to in the data pointer. Ok to call to matter how
+ * data was allocted. */
+void
+Packet::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
+Packet::allocate()
+{
+ if (data)
+ return;
+ assert(!staticData);
+ dynamicData = true;
+ arrayData = true;
+ data = new uint8_t[getSize()];
+}
+
+/** Do the packet modify the same addresses. */
+bool
+Packet::intersect(Packet *p)
+{
+ Addr s1 = getAddr();
+ Addr e1 = getAddr() + getSize();
+ Addr s2 = p->getAddr();
+ Addr e2 = p->getAddr() + p->getSize();
+
+ if (s1 >= s2 && s1 < e2)
+ return true;
+ if (e1 >= s2 && e1 < e2)
+ return true;
+ return false;
+}
+
+bool
+fixPacket(Packet *func, Packet *timing)
+{
+ panic("Need to implement!");
+}
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
new file mode 100644
index 000000000..403039d96
--- /dev/null
+++ b/src/mem/packet.hh
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ *
+ * Authors: Ron Dreslinski
+ * Steve Reinhardt
+ * Ali Saidi
+ */
+
+/**
+ * @file
+ * Declaration of the Packet class.
+ */
+
+#ifndef __MEM_PACKET_HH__
+#define __MEM_PACKET_HH__
+
+#include "mem/request.hh"
+#include "arch/isa_traits.hh"
+#include "sim/root.hh"
+
+struct Packet;
+typedef Packet* PacketPtr;
+typedef uint8_t* PacketDataPtr;
+
+/**
+ * A Packet is used to encapsulate a transfer between two objects in
+ * the memory system (e.g., the L1 and L2 cache). (In contrast, a
+ * single Request travels all the way from the requester to the
+ * ultimate destination and back, possibly being conveyed by several
+ * different Packets along the way.)
+ */
+class 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;
+
+
+ /** The address of the request. This address could be virtual or
+ * physical, depending on the system configuration. */
+ Addr addr;
+
+ /** The size of the request or transfer. */
+ int size;
+
+ /** Device address (e.g., bus ID) of the source of the
+ * transaction. The source is not responsible for setting this
+ * field; it is set implicitly by the interconnect when the
+ * packet * is first sent. */
+ short src;
+
+ /** Device address (e.g., bus ID) of the destination of the
+ * transaction. The special value Broadcast indicates that the
+ * packet should be routed based on its address. This field is
+ * initialized in the constructor and is thus always valid
+ * (unlike * addr, size, and src). */
+ short dest;
+
+ /** Are the 'addr' and 'size' fields valid? */
+ bool addrSizeValid;
+ /** Is the 'src' field valid? */
+ bool srcValid;
+
+ public:
+
+ /** The special destination address indicating that the packet
+ * should be routed based on its address. */
+ static const short Broadcast = -1;
+
+ /** A pointer to the original request. */
+ RequestPtr req;
+
+ /** A virtual base opaque structure used to hold coherence-related
+ * state. A specific subclass would be derived from this to
+ * carry state specific to a particular coherence protocol. */
+ class CoherenceState {
+ public:
+ virtual ~CoherenceState() {}
+ };
+
+ /** This packet's coherence state. Caches should use
+ * dynamic_cast<> to cast to the state appropriate for the
+ * system's coherence protocol. */
+ CoherenceState *coherence;
+
+ /** A virtual base opaque structure used to hold state associated
+ * with the packet but specific to the sending device (e.g., an
+ * MSHR). A pointer to this state is returned in the packet's
+ * response so that the sender can quickly look up the state
+ * needed to process it. A specific subclass would be derived
+ * from this to carry state specific to a particular sending
+ * device. */
+ class SenderState {
+ public:
+ virtual ~SenderState() {}
+ };
+
+ /** This packet's sender state. Devices should use dynamic_cast<>
+ * to cast to the state appropriate to the sender. */
+ SenderState *senderState;
+
+ private:
+ /** List of command attributes. */
+ enum CommandAttribute
+ {
+ IsRead = 1 << 0,
+ IsWrite = 1 << 1,
+ IsPrefetch = 1 << 2,
+ IsInvalidate = 1 << 3,
+ IsRequest = 1 << 4,
+ IsResponse = 1 << 5,
+ NeedsResponse = 1 << 6,
+ };
+
+ public:
+ /** List of all commands associated with a packet. */
+ enum Command
+ {
+ ReadReq = IsRead | IsRequest | NeedsResponse,
+ WriteReq = IsWrite | IsRequest | NeedsResponse,
+ WriteReqNoAck = IsWrite | IsRequest,
+ ReadResp = IsRead | IsResponse,
+ WriteResp = IsWrite | IsResponse
+ };
+
+ /** Return the string name of the cmd field (for debugging and
+ * tracing). */
+ const std::string &cmdString() const;
+
+ /** The command field of the packet. */
+ Command cmd;
+
+ bool isRead() { return (cmd & IsRead) != 0; }
+ bool isRequest() { return (cmd & IsRequest) != 0; }
+ bool isResponse() { return (cmd & IsResponse) != 0; }
+ bool needsResponse() { return (cmd & NeedsResponse) != 0; }
+
+ /** Possible results of a packet's request. */
+ enum Result
+ {
+ Success,
+ BadAddress,
+ Nacked,
+ Unknown
+ };
+
+ /** The result of this packet's request. */
+ Result result;
+
+ /** Accessor function that returns the source index of the packet. */
+ short getSrc() const { assert(srcValid); return src; }
+ void setSrc(short _src) { src = _src; srcValid = true; }
+
+ /** Accessor function that returns the destination index of
+ the packet. */
+ short getDest() const { return dest; }
+ void setDest(short _dest) { dest = _dest; }
+
+ Addr getAddr() const { assert(addrSizeValid); return addr; }
+ int getSize() const { assert(addrSizeValid); return size; }
+
+ /** Constructor. Note that a Request object must be constructed
+ * first, but the Requests's physical address and size fields
+ * need not be valid. The command and destination addresses
+ * must be supplied. */
+ Packet(Request *_req, Command _cmd, short _dest)
+ : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ addr(_req->paddr), size(_req->size), dest(_dest),
+ addrSizeValid(_req->validPaddr),
+ srcValid(false),
+ req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
+ result(Unknown)
+ {
+ }
+
+ /** Destructor. */
+ ~Packet()
+ { deleteData(); }
+
+ /** Reinitialize packet address and size from the associated
+ * Request object, and reset other fields that may have been
+ * modified by a previous transaction. Typically called when a
+ * statically allocated Request/Packet pair is reused for
+ * multiple transactions. */
+ void reinitFromRequest() {
+ assert(req->validPaddr);
+ addr = req->paddr;
+ size = req->size;
+ addrSizeValid = true;
+ result = Unknown;
+ if (dynamicData) {
+ deleteData();
+ dynamicData = false;
+ arrayData = false;
+ }
+ }
+
+ /** Take a request packet and modify it in place to be suitable
+ * for returning as a response to that request. Used for timing
+ * accesses only. For atomic and functional accesses, the
+ * request packet is always implicitly passed back *without*
+ * modifying the command or destination fields, so this function
+ * should not be called. */
+ void makeTimingResponse() {
+ assert(needsResponse());
+ int icmd = (int)cmd;
+ icmd &= ~(IsRequest | NeedsResponse);
+ icmd |= IsResponse;
+ cmd = (Command)icmd;
+ dest = src;
+ srcValid = false;
+ }
+
+ /** Take a request packet that has been returned as NACKED and modify it so
+ * that it can be sent out again. Only packets that need a response can be
+ * NACKED, so verify that that is true. */
+ void reinitNacked() {
+ assert(needsResponse() && result == Nacked);
+ dest = Broadcast;
+ result = Unknown;
+ }
+
+
+ /** Set the data pointer to the following value that should not be freed. */
+ template <typename T>
+ void dataStatic(T *p);
+
+ /** Set the data pointer to a value that should have delete [] called on it.
+ */
+ template <typename T>
+ void dataDynamicArray(T *p);
+
+ /** set the data pointer to a value that should have delete called on it. */
+ template <typename T>
+ void dataDynamic(T *p);
+
+ /** return the value of what is pointed to in the packet. */
+ template <typename T>
+ T get();
+
+ /** get a pointer to the data ptr. */
+ template <typename T>
+ T* getPtr();
+
+ /** set the value in the data pointer to v. */
+ template <typename T>
+ void set(T v);
+
+ /** delete the data pointed to in the data pointer. Ok to call to matter how
+ * data was allocted. */
+ void deleteData();
+
+ /** If there isn't data in the packet, allocate some. */
+ void allocate();
+
+ /** Do the packet modify the same addresses. */
+ bool intersect(Packet *p);
+};
+
+bool fixPacket(Packet *func, Packet *timing);
+#endif //__MEM_PACKET_HH
diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc
new file mode 100644
index 000000000..b5cecc7da
--- /dev/null
+++ b/src/mem/page_table.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2003 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: Steve Reinhardt
+ * Ron Dreslinski
+ */
+
+/**
+ * @file
+ * Definitions of page table.
+ */
+#include <string>
+#include <map>
+#include <fstream>
+
+#include "arch/faults.hh"
+#include "base/bitfield.hh"
+#include "base/intmath.hh"
+#include "base/trace.hh"
+#include "mem/page_table.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace TheISA;
+
+PageTable::PageTable(System *_system, Addr _pageSize)
+ : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))),
+ system(_system)
+{
+ assert(isPowerOf2(pageSize));
+}
+
+PageTable::~PageTable()
+{
+}
+
+Fault
+PageTable::page_check(Addr addr, int size) const
+{
+ if (size < sizeof(uint64_t)) {
+ if (!isPowerOf2(size)) {
+ panic("Invalid request size!\n");
+ return genMachineCheckFault();
+ }
+
+ if ((size - 1) & addr)
+ return genAlignmentFault();
+ }
+ else {
+ if ((addr & (VMPageSize - 1)) + size > VMPageSize) {
+ panic("Invalid request size!\n");
+ return genMachineCheckFault();
+ }
+
+ if ((sizeof(uint64_t) - 1) & addr)
+ return genAlignmentFault();
+ }
+
+ return NoFault;
+}
+
+
+
+
+void
+PageTable::allocate(Addr vaddr, int size)
+{
+ // starting address must be page aligned
+ assert(pageOffset(vaddr) == 0);
+
+ for (; size > 0; size -= pageSize, vaddr += pageSize) {
+ std::map<Addr,Addr>::iterator iter = pTable.find(vaddr);
+
+ if (iter != pTable.end()) {
+ // already mapped
+ fatal("PageTable::allocate: address 0x%x already mapped", vaddr);
+ }
+
+ pTable[vaddr] = system->new_page();
+ }
+}
+
+
+
+bool
+PageTable::translate(Addr vaddr, Addr &paddr)
+{
+ Addr page_addr = pageAlign(vaddr);
+ std::map<Addr,Addr>::iterator iter = pTable.find(page_addr);
+
+ if (iter == pTable.end()) {
+ return false;
+ }
+
+ paddr = iter->second + pageOffset(vaddr);
+ return true;
+}
+
+
+Fault
+PageTable::translate(RequestPtr &req)
+{
+ Addr paddr;
+ assert(pageAlign(req->getVaddr() + req->getSize() - 1)
+ == pageAlign(req->getVaddr()));
+ if (!translate(req->getVaddr(), paddr)) {
+ return genMachineCheckFault();
+ }
+ req->setPaddr(paddr);
+ return page_check(req->getPaddr(), req->getSize());
+}
diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh
new file mode 100644
index 000000000..f7212d423
--- /dev/null
+++ b/src/mem/page_table.hh
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2003 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: Steve Reinhardt
+ */
+
+/**
+ * @file
+ * Declaration of a non-full system Page Table.
+ */
+
+#ifndef __PAGE_TABLE__
+#define __PAGE_TABLE__
+
+#include <string>
+#include <map>
+
+#include "arch/isa_traits.hh"
+#include "base/trace.hh"
+#include "mem/request.hh"
+#include "mem/packet.hh"
+#include "sim/sim_object.hh"
+
+class System;
+
+/**
+ * Page Table Decleration.
+ */
+class PageTable
+{
+ protected:
+ std::map<Addr,Addr> pTable;
+
+ const Addr pageSize;
+ const Addr offsetMask;
+
+ System *system;
+
+ public:
+
+ PageTable(System *_system, Addr _pageSize = TheISA::VMPageSize);
+
+ ~PageTable();
+
+ Addr pageAlign(Addr a) { return (a & ~offsetMask); }
+ Addr pageOffset(Addr a) { return (a & offsetMask); }
+
+ Fault page_check(Addr addr, int size) const;
+
+ void allocate(Addr vaddr, int size);
+
+ /**
+ * Translate function
+ * @param vaddr The virtual address.
+ * @return Physical address from translation.
+ */
+ bool translate(Addr vaddr, Addr &paddr);
+
+ /**
+ * Perform a translation on the memory request, fills in paddr
+ * field of mem_req.
+ * @param req The memory request.
+ */
+ Fault translate(RequestPtr &req);
+
+};
+
+#endif
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
new file mode 100644
index 000000000..fb31fb4a3
--- /dev/null
+++ b/src/mem/physical.cc
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2001-2005 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
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include <iostream>
+#include <string>
+
+
+#include "base/misc.hh"
+#include "config/full_system.hh"
+#include "mem/packet_impl.hh"
+#include "mem/physical.hh"
+#include "sim/host.hh"
+#include "sim/builder.hh"
+#include "sim/eventq.hh"
+#include "arch/isa_traits.hh"
+
+
+using namespace std;
+using namespace TheISA;
+
+PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m)
+ : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
+{
+
+ this->setFlags(AutoDelete);
+}
+
+void
+PhysicalMemory::MemResponseEvent::process()
+{
+ memoryPort->sendTiming(pkt);
+}
+
+const char *
+PhysicalMemory::MemResponseEvent::description()
+{
+ return "Physical Memory Timing Access respnse event";
+}
+
+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;
+
+ if (pmem_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,
+ map_flags, -1, 0);
+
+ if (pmem_addr == (void *)MAP_FAILED) {
+ perror("mmap");
+ fatal("Could not mmap!\n");
+ }
+
+ page_ptr = 0;
+}
+
+void
+PhysicalMemory::init()
+{
+ if (!port)
+ panic("PhysicalMemory not connected to anything!");
+ port->sendStatusChange(Port::RangeChange);
+}
+
+PhysicalMemory::~PhysicalMemory()
+{
+ if (pmem_addr)
+ munmap(pmem_addr, pmem_size);
+ //Remove memPorts?
+}
+
+Addr
+PhysicalMemory::new_page()
+{
+ Addr return_addr = page_ptr << LogVMPageSize;
+ return_addr += base_addr;
+
+ ++page_ptr;
+ return return_addr;
+}
+
+int
+PhysicalMemory::deviceBlockSize()
+{
+ //Can accept anysize request
+ return 0;
+}
+
+bool
+PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
+{
+ doFunctionalAccess(pkt);
+
+ // turn packet around to go back to requester
+ pkt->makeTimingResponse();
+ MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
+ response->schedule(curTick + lat);
+
+ return true;
+}
+
+Tick
+PhysicalMemory::doAtomicAccess(Packet *pkt)
+{
+ doFunctionalAccess(pkt);
+ return lat;
+}
+
+void
+PhysicalMemory::doFunctionalAccess(Packet *pkt)
+{
+ assert(pkt->getAddr() + pkt->getSize() < pmem_size);
+
+ switch (pkt->cmd) {
+ case Packet::ReadReq:
+ memcpy(pkt->getPtr<uint8_t>(),
+ pmem_addr + pkt->getAddr() - base_addr,
+ pkt->getSize());
+ break;
+ case Packet::WriteReq:
+ memcpy(pmem_addr + pkt->getAddr() - base_addr,
+ pkt->getPtr<uint8_t>(),
+ pkt->getSize());
+ // temporary hack: will need to add real LL/SC implementation
+ // for cacheless systems later.
+ if (pkt->req->getFlags() & LOCKED) {
+ pkt->req->setScResult(1);
+ }
+ break;
+ default:
+ panic("unimplemented");
+ }
+
+ pkt->result = Packet::Success;
+}
+
+Port *
+PhysicalMemory::getPort(const std::string &if_name)
+{
+ if (if_name == "") {
+ if (port != NULL)
+ panic("PhysicalMemory::getPort: additional port requested to memory!");
+ port = new MemoryPort(name() + "-port", this);
+ return port;
+ } else if (if_name == "functional") {
+ /* special port for functional writes at startup. */
+ return new MemoryPort(name() + "-funcport", this);
+ } else {
+ panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
+ }
+}
+
+void
+PhysicalMemory::recvStatusChange(Port::Status status)
+{
+}
+
+PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
+ PhysicalMemory *_memory)
+ : Port(_name), memory(_memory)
+{ }
+
+void
+PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
+{
+ memory->recvStatusChange(status);
+}
+
+void
+PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+{
+ memory->getAddressRanges(resp, snoop);
+}
+
+void
+PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+{
+ snoop.clear();
+ resp.clear();
+ resp.push_back(RangeSize(base_addr, pmem_size));
+}
+
+int
+PhysicalMemory::MemoryPort::deviceBlockSize()
+{
+ return memory->deviceBlockSize();
+}
+
+bool
+PhysicalMemory::MemoryPort::recvTiming(Packet *pkt)
+{
+ return memory->doTimingAccess(pkt, this);
+}
+
+Tick
+PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt)
+{
+ return memory->doAtomicAccess(pkt);
+}
+
+void
+PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt)
+{
+ memory->doFunctionalAccess(pkt);
+}
+
+
+
+void
+PhysicalMemory::serialize(ostream &os)
+{
+ gzFile compressedMem;
+ string filename = name() + ".physmem";
+
+ SERIALIZE_SCALAR(pmem_size);
+ SERIALIZE_SCALAR(filename);
+
+ // write memory file
+ string thefile = Checkpoint::dir() + "/" + filename.c_str();
+ int fd = creat(thefile.c_str(), 0664);
+ if (fd < 0) {
+ perror("creat");
+ fatal("Can't open physical memory checkpoint file '%s'\n", filename);
+ }
+
+ compressedMem = gzdopen(fd, "wb");
+ if (compressedMem == NULL)
+ fatal("Insufficient memory to allocate compression state for %s\n",
+ filename);
+
+ if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) {
+ fatal("Write failed on physical memory checkpoint file '%s'\n",
+ filename);
+ }
+
+ if (gzclose(compressedMem))
+ fatal("Close failed on physical memory checkpoint file '%s'\n",
+ filename);
+}
+
+void
+PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
+{
+ gzFile compressedMem;
+ long *tempPage;
+ long *pmem_current;
+ uint64_t curSize;
+ uint32_t bytesRead;
+ 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;
+
+ // mmap memoryfile
+ int fd = open(filename.c_str(), O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ fatal("Can't open physical memory checkpoint file '%s'", filename);
+ }
+
+ compressedMem = gzdopen(fd, "rb");
+ if (compressedMem == NULL)
+ fatal("Insufficient memory to allocate compression state for %s\n",
+ filename);
+
+
+ pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+
+ if (pmem_addr == (void *)MAP_FAILED) {
+ perror("mmap");
+ fatal("Could not mmap physical memory!\n");
+ }
+
+ curSize = 0;
+ tempPage = (long*)malloc(chunkSize);
+ if (tempPage == NULL)
+ 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) {
+ bytesRead = gzread(compressedMem, tempPage, chunkSize);
+ if (bytesRead != chunkSize && bytesRead != pmem_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);
+
+ 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 = *(tempPage+x);
+ }
+ }
+ curSize += bytesRead;
+ }
+
+ free(tempPage);
+
+ if (gzclose(compressedMem))
+ fatal("Close failed on physical memory checkpoint file '%s'\n",
+ filename);
+
+}
+
+
+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(latency, "Memory access latency")
+
+END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+CREATE_SIM_OBJECT(PhysicalMemory)
+{
+
+ return new PhysicalMemory(getInstanceName(), latency);
+}
+
+REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
new file mode 100644
index 000000000..88ea543da
--- /dev/null
+++ b/src/mem/physical.hh
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2001-2005 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
+ */
+
+/* @file
+ */
+
+#ifndef __PHYSICAL_MEMORY_HH__
+#define __PHYSICAL_MEMORY_HH__
+
+#include "base/range.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+#include <map>
+#include <string>
+
+//
+// Functional model for a contiguous block of physical memory. (i.e. RAM)
+//
+class PhysicalMemory : public MemObject
+{
+ class MemoryPort : public Port
+ {
+ PhysicalMemory *memory;
+
+ public:
+
+ MemoryPort(const std::string &_name, PhysicalMemory *_memory);
+
+ protected:
+
+ virtual bool recvTiming(Packet *pkt);
+
+ virtual Tick recvAtomic(Packet *pkt);
+
+ virtual void recvFunctional(Packet *pkt);
+
+ virtual void recvStatusChange(Status status);
+
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop);
+
+ virtual int deviceBlockSize();
+ };
+
+ int numPorts;
+
+
+ struct MemResponseEvent : public Event
+ {
+ Packet *pkt;
+ MemoryPort *memoryPort;
+
+ MemResponseEvent(Packet *pkt, MemoryPort *memoryPort);
+ void process();
+ const char *description();
+ };
+
+ private:
+ // prevent copying of a MainMemory object
+ PhysicalMemory(const PhysicalMemory &specmem);
+ const PhysicalMemory &operator=(const PhysicalMemory &specmem);
+
+ protected:
+ Addr base_addr;
+ Addr pmem_size;
+ 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, Tick latency);
+ virtual ~PhysicalMemory();
+
+ public:
+ int deviceBlockSize();
+ void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+ virtual Port *getPort(const std::string &if_name);
+ void virtual init();
+
+ // fast back-door memory access for vtophys(), remote gdb, etc.
+ // uint64_t phys_read_qword(Addr addr) const;
+ private:
+ bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort);
+ Tick doAtomicAccess(Packet *pkt);
+ void doFunctionalAccess(Packet *pkt);
+
+ void recvStatusChange(Port::Status status);
+
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif //__PHYSICAL_MEMORY_HH__
diff --git a/src/mem/port.cc b/src/mem/port.cc
new file mode 100644
index 000000000..bec9d2274
--- /dev/null
+++ b/src/mem/port.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2005 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: Steve Reinhardt
+ */
+
+/**
+ * @file Port object definitions.
+ */
+
+#include "base/chunk_generator.hh"
+#include "base/trace.hh"
+#include "mem/packet_impl.hh"
+#include "mem/port.hh"
+
+void
+Port::setPeer(Port *port)
+{
+ DPRINTF(Config, "setting peer to %s\n", port->name());
+ peer = port;
+}
+
+void
+Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd)
+{
+ Request req;
+ Packet pkt(&req, cmd, Packet::Broadcast);
+
+ for (ChunkGenerator gen(addr, size, peerBlockSize());
+ !gen.done(); gen.next()) {
+ req.setPhys(gen.addr(), gen.size(), 0);
+ pkt.reinitFromRequest();
+ pkt.dataStatic(p);
+ sendFunctional(&pkt);
+ p += gen.size();
+ }
+}
+
+void
+Port::writeBlob(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Packet::WriteReq);
+}
+
+void
+Port::readBlob(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Packet::ReadReq);
+}
+
+void
+Port::memsetBlob(Addr addr, uint8_t val, int size)
+{
+ // quick and dirty...
+ uint8_t *buf = new uint8_t[size];
+
+ memset(buf, val, size);
+ blobHelper(addr, buf, size, Packet::WriteReq);
+
+ delete [] buf;
+}
diff --git a/src/mem/port.hh b/src/mem/port.hh
new file mode 100644
index 000000000..2edad095e
--- /dev/null
+++ b/src/mem/port.hh
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2002-2005 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
+ */
+
+/**
+ * @file
+ * Port Object Decleration. Ports are used to interface memory objects to
+ * each other. They will always come in pairs, and we refer to the other
+ * port object as the peer. These are used to make the design more
+ * modular so that a specific interface between every type of objcet doesn't
+ * have to be created.
+ */
+
+#ifndef __MEM_PORT_HH__
+#define __MEM_PORT_HH__
+
+#include <list>
+#include <inttypes.h>
+
+#include "base/misc.hh"
+#include "base/range.hh"
+#include "mem/packet.hh"
+#include "mem/request.hh"
+
+/** This typedef is used to clean up the parameter list of
+ * getDeviceAddressRanges() and getPeerAddressRanges(). It's declared
+ * outside the Port object since it's also used by some mem objects.
+ * Eventually we should move this typedef to wherever Addr is
+ * defined.
+ */
+
+typedef std::list<Range<Addr> > AddrRangeList;
+typedef std::list<Range<Addr> >::iterator AddrRangeIter;
+
+/**
+ * Ports are used to interface memory objects to
+ * each other. They will always come in pairs, and we refer to the other
+ * port object as the peer. These are used to make the design more
+ * modular so that a specific interface between every type of objcet doesn't
+ * have to be created.
+ *
+ * Recv accesor functions are being called from the peer interface.
+ * Send accessor functions are being called from the device the port is
+ * associated with, and it will call the peer recv. accessor function.
+ */
+class Port
+{
+ private:
+
+ /** Descriptive name (for DPRINTF output) */
+ const std::string portName;
+
+ /** A pointer to the peer port. Ports always come in pairs, that way they
+ can use a standardized interface to communicate between different
+ memory objects. */
+ Port *peer;
+
+ public:
+
+ /**
+ * Constructor.
+ *
+ * @param _name Port name for DPRINTF output. Should include name
+ * of memory system object to which the port belongs.
+ */
+ Port(const std::string &_name)
+ : portName(_name), peer(NULL)
+ { }
+
+ /** Return port name (for DPRINTF). */
+ const std::string &name() const { return portName; }
+
+ virtual ~Port() {};
+
+ // mey be better to use subclasses & RTTI?
+ /** Holds the ports status. Currently just that a range recomputation needs
+ * to be done. */
+ enum Status {
+ RangeChange
+ };
+
+ /** Function to set the pointer for the peer port.
+ @todo should be called by the configuration stuff (python).
+ */
+ void setPeer(Port *port);
+
+ /** Function to set the pointer for the peer port.
+ @todo should be called by the configuration stuff (python).
+ */
+ Port *getPeer() { return peer; }
+
+ protected:
+
+ /** These functions are protected because they should only be
+ * called by a peer port, never directly by any outside object. */
+
+ /** Called to recive a timing call from the peer port. */
+ virtual bool recvTiming(Packet *pkt) = 0;
+
+ /** Called to recive a atomic call from the peer port. */
+ virtual Tick recvAtomic(Packet *pkt) = 0;
+
+ /** Called to recive a functional call from the peer port. */
+ virtual void recvFunctional(Packet *pkt) = 0;
+
+ /** Called to recieve a status change from the peer port. */
+ virtual void recvStatusChange(Status status) = 0;
+
+ /** Called by a peer port if the send was unsuccesful, and had to
+ wait. This shouldn't be valid for response paths (IO Devices).
+ so it is set to panic if it isn't already defined.
+ */
+ virtual void recvRetry() { panic("??"); }
+
+ /** Called by a peer port in order to determine the block size of the
+ device connected to this port. It sometimes doesn't make sense for
+ this function to be called, a DMA interface doesn't really have a
+ block size, so it is defaulted to a panic.
+ */
+ virtual int deviceBlockSize() { panic("??"); }
+
+ /** The peer port is requesting us to reply with a list of the ranges we
+ are responsible for.
+ @param resp is a list of ranges responded to
+ @param snoop is a list of ranges snooped
+ */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+ { panic("??"); }
+
+ public:
+
+ /** Function called by associated memory device (cache, memory, iodevice)
+ in order to send a timing request to the port. Simply calls the peer
+ port receive function.
+ @return This function returns if the send was succesful in it's
+ recieve. If it was a failure, then the port will wait for a recvRetry
+ at which point it can possibly issue a successful sendTiming. This is used in
+ case a cache has a higher priority request come in while waiting for
+ the bus to arbitrate.
+ */
+ bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); }
+
+ /** Function called by the associated device to send an atomic
+ * access, an access in which the data is moved and the state is
+ * updated in one cycle, without interleaving with other memory
+ * accesses. Returns estimated latency of access.
+ */
+ Tick sendAtomic(Packet *pkt)
+ { return peer->recvAtomic(pkt); }
+
+ /** 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.
+ */
+ void sendFunctional(Packet *pkt)
+ { return peer->recvFunctional(pkt); }
+
+ /** Called by the associated device to send a status change to the device
+ connected to the peer interface.
+ */
+ void sendStatusChange(Status status) {peer->recvStatusChange(status); }
+
+ /** When a timing access doesn't return a success, some time later the
+ Retry will be sent.
+ */
+ void sendRetry() { return peer->recvRetry(); }
+
+ /** Called by the associated device if it wishes to find out the blocksize
+ of the device on attached to the peer port.
+ */
+ int peerBlockSize() { return peer->deviceBlockSize(); }
+
+ /** Called by the associated device if it wishes to find out the address
+ ranges connected to the peer ports devices.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ virtual void memsetBlob(Addr addr, uint8_t val, int size);
+
+ private:
+
+ /** Internal helper function for read/writeBlob().
+ */
+ void blobHelper(Addr addr, uint8_t *p, int size, Packet::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:
+ FunctionalPort(const std::string &_name)
+ : Port(_name)
+ {}
+
+ 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) {}
+
+ /** a write function that also does an endian conversion. */
+ template <typename T>
+ inline void writeHtoG(Addr addr, T d);
+
+ /** a read function that also does an endian conversion. */
+ template <typename T>
+ inline T readGtoH(Addr addr);
+
+ 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/src/mem/port_impl.hh b/src/mem/port_impl.hh
new file mode 100644
index 000000000..e9a159293
--- /dev/null
+++ b/src/mem/port_impl.hh
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include "arch/isa_specific.hh"
+#include "arch/isa_traits.hh"
+#include "mem/port.hh"
+#include "sim/byteswap.hh"
+
+template <typename T>
+void
+FunctionalPort::writeHtoG(Addr addr, T d)
+{
+ d = TheISA::htog(d);
+ writeBlob(addr, (uint8_t*)&d, sizeof(T));
+}
+
+
+template <typename T>
+T
+FunctionalPort::readGtoH(Addr addr)
+{
+ T d;
+ readBlob(addr, (uint8_t*)&d, sizeof(T));
+ return TheISA::gtoh(d);
+}
+
diff --git a/src/mem/request.hh b/src/mem/request.hh
new file mode 100644
index 000000000..af1d6d8a8
--- /dev/null
+++ b/src/mem/request.hh
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2002-2005 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
+ * Steve Reinhardt
+ * Ali Saidi
+ */
+
+/**
+ * @file Decleration of a request, the overall memory request consisting of
+ the parts of the request that are persistent throughout the transaction.
+ */
+
+#ifndef __MEM_REQUEST_HH__
+#define __MEM_REQUEST_HH__
+
+#include "arch/isa_traits.hh"
+
+class Request;
+
+typedef Request* RequestPtr;
+
+/** The request is a Load locked/store conditional. */
+const unsigned LOCKED = 0x001;
+/** The virtual address is also the physical address. */
+const unsigned PHYSICAL = 0x002;
+/** The request is an ALPHA VPTE pal access (hw_ld). */
+const unsigned VPTE = 0x004;
+/** Use the alternate mode bits in ALPHA. */
+const unsigned ALTMODE = 0x008;
+/** The request is to an uncacheable address. */
+const unsigned UNCACHEABLE = 0x010;
+/** The request should not cause a page fault. */
+const unsigned NO_FAULT = 0x020;
+/** The request should be prefetched into the exclusive state. */
+const unsigned PF_EXCLUSIVE = 0x100;
+/** The request should be marked as LRU. */
+const unsigned EVICT_NEXT = 0x200;
+/** The request should ignore unaligned access faults */
+const unsigned NO_ALIGN_FAULT = 0x400;
+
+class Request
+{
+ private:
+ /**
+ * The physical address of the request. Valid only if validPaddr
+ * is set. */
+ Addr paddr;
+
+ /**
+ * The size of the request. This field must be set when vaddr or
+ * paddr is written via setVirt() or setPhys(), so it is always
+ * valid as long as one of the address fields is valid. */
+ int size;
+
+ /** Flag structure for the request. */
+ uint32_t flags;
+
+ /**
+ * The time this request was started. Used to calculate
+ * latencies. This field is set to curTick any time paddr or vaddr
+ * is written. */
+ Tick time;
+
+ /** The address space ID. */
+ int asid;
+ /** The virtual address of the request. */
+ Addr vaddr;
+
+ /** The return value of store conditional. */
+ uint64_t scResult;
+
+ /** The cpu number (for statistics, typically). */
+ int cpuNum;
+ /** The requesting thread id (for statistics, typically). */
+ int threadNum;
+
+ /** program counter of initiating access; for tracing/debugging */
+ Addr pc;
+
+ /** Whether or not paddr is valid (has been written yet). */
+ bool validPaddr;
+ /** Whether or not the asid & vaddr are valid. */
+ bool validAsidVaddr;
+ /** Whether or not the sc result is valid. */
+ bool validScResult;
+ /** Whether or not the cpu number & thread ID are valid. */
+ bool validCpuAndThreadNums;
+ /** Whether or not the pc is valid. */
+ bool validPC;
+
+ public:
+ /** Minimal constructor. No fields are initialized. */
+ Request()
+ : validPaddr(false), validAsidVaddr(false),
+ validScResult(false), validCpuAndThreadNums(false), validPC(false)
+ {}
+
+ /**
+ * Constructor for physical (e.g. device) requests. Initializes
+ * just physical address, size, flags, and timestamp (to curTick).
+ * These fields are adequate to perform a request. */
+ Request(Addr _paddr, int _size, int _flags)
+ : validCpuAndThreadNums(false)
+ { setPhys(_paddr, _size, _flags); }
+
+ Request(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc,
+ int _cpuNum, int _threadNum)
+ {
+ setThreadContext(_cpuNum, _threadNum);
+ setVirt(_asid, _vaddr, _size, _flags, _pc);
+ }
+
+ /**
+ * Set up CPU and thread numbers. */
+ void setThreadContext(int _cpuNum, int _threadNum)
+ {
+ cpuNum = _cpuNum;
+ threadNum = _threadNum;
+ validCpuAndThreadNums = true;
+ }
+
+ /**
+ * Set up a physical (e.g. device) request in a previously
+ * allocated Request object. */
+ void setPhys(Addr _paddr, int _size, int _flags)
+ {
+ paddr = _paddr;
+ size = _size;
+ flags = _flags;
+ time = curTick;
+ validPaddr = true;
+ validAsidVaddr = false;
+ validPC = false;
+ validScResult = false;
+ }
+
+ /**
+ * Set up a virtual (e.g., CPU) request in a previously
+ * allocated Request object. */
+ void setVirt(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc)
+ {
+ asid = _asid;
+ vaddr = _vaddr;
+ size = _size;
+ flags = _flags;
+ pc = _pc;
+ time = curTick;
+ validPaddr = false;
+ validAsidVaddr = true;
+ validPC = true;
+ validScResult = false;
+ }
+
+ /** Set just the physical address. This should only be used to
+ * record the result of a translation, and thus the vaddr must be
+ * valid before this method is called. Otherwise, use setPhys()
+ * to guarantee that the size and flags are also set.
+ */
+ void setPaddr(Addr _paddr)
+ {
+ assert(validAsidVaddr);
+ paddr = _paddr;
+ validPaddr = true;
+ }
+
+ /** Accessor for paddr. */
+ Addr getPaddr() { assert(validPaddr); return paddr; }
+
+ /** Accessor for size. */
+ int getSize() { assert(validPaddr || validAsidVaddr); return size; }
+ /** Accessor for time. */
+ Tick getTime() { assert(validPaddr || validAsidVaddr); return time; }
+
+ /** Accessor for flags. */
+ uint32_t getFlags() { assert(validPaddr || validAsidVaddr); return flags; }
+ /** Accessor for paddr. */
+ void setFlags(uint32_t _flags)
+ { assert(validPaddr || validAsidVaddr); flags = _flags; }
+
+ /** Accessor function for vaddr.*/
+ Addr getVaddr() { assert(validAsidVaddr); return vaddr; }
+
+ /** Accessor function for asid.*/
+ int getAsid() { assert(validAsidVaddr); return asid; }
+
+ /** Accessor function to check if sc result is valid. */
+ bool scResultValid() { return validScResult; }
+ /** Accessor function for store conditional return value.*/
+ uint64_t getScResult() { assert(validScResult); return scResult; }
+ /** Accessor function for store conditional return value.*/
+ void setScResult(uint64_t _scResult)
+ { scResult = _scResult; validScResult = true; }
+
+ /** Accessor function for cpu number.*/
+ int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; }
+ /** Accessor function for thread number.*/
+ int getThreadNum() { assert(validCpuAndThreadNums); return threadNum; }
+
+ /** Accessor function for pc.*/
+ Addr getPC() { assert(validPC); return pc; }
+
+ friend class Packet;
+};
+
+#endif // __MEM_REQUEST_HH__
diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc
new file mode 100644
index 000000000..d2c854086
--- /dev/null
+++ b/src/mem/translating_port.cc
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2001-2005 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
+ * Steve Reinhardt
+ */
+
+#include <string>
+#include "base/chunk_generator.hh"
+#include "mem/port.hh"
+#include "mem/translating_port.hh"
+#include "mem/page_table.hh"
+
+using namespace TheISA;
+
+TranslatingPort::TranslatingPort(const std::string &_name,
+ PageTable *p_table, bool alloc)
+ : FunctionalPort(_name), pTable(p_table), allocating(alloc)
+{ }
+
+TranslatingPort::~TranslatingPort()
+{ }
+
+bool
+TranslatingPort::tryReadBlob(Addr addr, uint8_t *p, int size)
+{
+ Addr paddr;
+ int prevSize = 0;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(),paddr))
+ return false;
+
+ Port::readBlob(paddr, p + prevSize, gen.size());
+ prevSize += gen.size();
+ }
+
+ return true;
+}
+
+void
+TranslatingPort::readBlob(Addr addr, uint8_t *p, int size)
+{
+ if (!tryReadBlob(addr, p, size))
+ fatal("readBlob(0x%x, ...) failed", addr);
+}
+
+
+bool
+TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size)
+{
+
+ Addr paddr;
+ int prevSize = 0;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(), paddr)) {
+ if (allocating) {
+ pTable->allocate(roundDown(gen.addr(), VMPageSize),
+ VMPageSize);
+ pTable->translate(gen.addr(), paddr);
+ } else {
+ return false;
+ }
+ }
+
+ Port::writeBlob(paddr, p + prevSize, gen.size());
+ prevSize += gen.size();
+ }
+
+ return true;
+}
+
+
+void
+TranslatingPort::writeBlob(Addr addr, uint8_t *p, int size)
+{
+ if (!tryWriteBlob(addr, p, size))
+ fatal("writeBlob(0x%x, ...) failed", addr);
+}
+
+bool
+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 (allocating) {
+ pTable->allocate(roundDown(gen.addr(), VMPageSize),
+ VMPageSize);
+ pTable->translate(gen.addr(), paddr);
+ } else {
+ return false;
+ }
+ }
+
+ Port::memsetBlob(paddr, val, gen.size());
+ }
+
+ return true;
+}
+
+void
+TranslatingPort::memsetBlob(Addr addr, uint8_t val, int size)
+{
+ if (!tryMemsetBlob(addr, val, size))
+ fatal("memsetBlob(0x%x, ...) failed", addr);
+}
+
+
+bool
+TranslatingPort::tryWriteString(Addr addr, const char *str)
+{
+ Addr paddr,vaddr;
+ uint8_t c;
+
+ vaddr = addr;
+
+ do {
+ c = *str++;
+ if (!pTable->translate(vaddr++,paddr))
+ return false;
+
+ Port::writeBlob(paddr, &c, 1);
+ } while (c);
+
+ return true;
+}
+
+void
+TranslatingPort::writeString(Addr addr, const char *str)
+{
+ if (!tryWriteString(addr, str))
+ fatal("writeString(0x%x, ...) failed", addr);
+}
+
+bool
+TranslatingPort::tryReadString(std::string &str, Addr addr)
+{
+ Addr paddr,vaddr;
+ uint8_t c;
+
+ vaddr = addr;
+
+ do {
+ if (!pTable->translate(vaddr++,paddr))
+ return false;
+
+ Port::readBlob(paddr, &c, 1);
+ str += c;
+ } while (c);
+
+ return true;
+}
+
+void
+TranslatingPort::readString(std::string &str, Addr addr)
+{
+ if (!tryReadString(str, addr))
+ fatal("readString(0x%x, ...) failed", addr);
+}
+
diff --git a/src/mem/translating_port.hh b/src/mem/translating_port.hh
new file mode 100644
index 000000000..7354278ba
--- /dev/null
+++ b/src/mem/translating_port.hh
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001-2005 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
+ */
+
+#ifndef __MEM_TRANSLATING_PROT_HH__
+#define __MEM_TRANSLATING_PROT_HH__
+
+#include "mem/port.hh"
+
+class PageTable;
+
+class TranslatingPort : public FunctionalPort
+{
+ private:
+ PageTable *pTable;
+ bool allocating;
+
+ public:
+ TranslatingPort(const std::string &_name,
+ PageTable *p_table, bool alloc = false);
+ virtual ~TranslatingPort();
+
+ bool tryReadBlob(Addr addr, uint8_t *p, int size);
+ 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);
+
+ 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/src/mem/vport.cc b/src/mem/vport.cc
new file mode 100644
index 000000000..cd297bb8e
--- /dev/null
+++ b/src/mem/vport.cc
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ */
+
+/**
+ * @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 (tc)
+ paddr = TheISA::vtophys(tc,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 (tc)
+ paddr = TheISA::vtophys(tc,gen.addr());
+ else
+ paddr = TheISA::vtophys(gen.addr());
+
+ FunctionalPort::writeBlob(paddr, p, gen.size());
+ p += gen.size();
+ }
+}
+
diff --git a/src/mem/vport.hh b/src/mem/vport.hh
new file mode 100644
index 000000000..697c8e5f3
--- /dev/null
+++ b/src/mem/vport.hh
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ */
+
+/**
+ * @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_impl.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 a thread 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:
+ ThreadContext *tc;
+
+ public:
+ VirtualPort(const std::string &_name, ThreadContext *_tc = NULL)
+ : FunctionalPort(_name), tc(_tc)
+ {}
+
+ /** Return true if we have an thread context. This is used to
+ * prevent someone from accidently deleting the cpus statically
+ * allocated vport.
+ * @return true if a thread context isn't valid
+ */
+ bool nullThreadContext() { return tc != NULL; }
+
+ /** 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__
+