diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/bridge.cc | 263 | ||||
-rw-r--r-- | src/mem/bridge.hh | 214 | ||||
-rw-r--r-- | src/mem/bus.cc | 188 | ||||
-rw-r--r-- | src/mem/bus.hh | 164 | ||||
-rw-r--r-- | src/mem/cache/prefetch/tagged_prefetcher_impl.hh | 73 | ||||
-rw-r--r-- | src/mem/config/prefetch.hh | 39 | ||||
-rw-r--r-- | src/mem/mem_object.cc | 37 | ||||
-rw-r--r-- | src/mem/mem_object.hh | 54 | ||||
-rw-r--r-- | src/mem/packet.cc | 94 | ||||
-rw-r--r-- | src/mem/packet.hh | 194 | ||||
-rw-r--r-- | src/mem/page_table.cc | 134 | ||||
-rw-r--r-- | src/mem/page_table.hh | 90 | ||||
-rw-r--r-- | src/mem/physical.cc | 373 | ||||
-rw-r--r-- | src/mem/physical.hh | 127 | ||||
-rw-r--r-- | src/mem/port.cc | 78 | ||||
-rw-r--r-- | src/mem/port.hh | 247 | ||||
-rw-r--r-- | src/mem/request.hh | 200 | ||||
-rw-r--r-- | src/mem/translating_port.cc | 186 | ||||
-rw-r--r-- | src/mem/translating_port.hh | 64 | ||||
-rw-r--r-- | src/mem/vport.cc | 69 | ||||
-rw-r--r-- | src/mem/vport.hh | 76 |
21 files changed, 2964 insertions, 0 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc new file mode 100644 index 000000000..c4b137869 --- /dev/null +++ b/src/mem/bridge.cc @@ -0,0 +1,263 @@ + +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Definition of a simple bus bridge without buffering. + */ + + +#include "base/trace.hh" +#include "mem/bridge.hh" +#include "sim/builder.hh" + +void +Bridge::init() +{ + // Make sure that both sides are connected to. + if (sideA == NULL || sideB == NULL) + panic("Both ports of bus bridge are not connected to a bus.\n"); +} + + +/** Function called by the port when the bus is recieving a Timing + * transaction.*/ +bool +Bridge::recvTiming(Packet *pkt, Side id) +{ + if (blockedA && id == SideA) + return false; + if (blockedB && id == SideB) + return false; + + if (delay) { + if (!sendEvent.scheduled()) + sendEvent.schedule(curTick + delay); + if (id == SideA) { + inboundA.push_back(std::make_pair<Packet*, Tick>(pkt, curTick)); + blockCheck(SideA); + } else { + inboundB.push_back(std::make_pair<Packet*, Tick>(pkt, curTick)); + blockCheck(SideB); + } + } else { + if (id == SideB) { + sideA->sendPkt(pkt); + blockCheck(SideB); + } else { + sideB->sendPkt(pkt); + blockCheck(SideA); + } + } + return true; + +} + +void +Bridge::blockCheck(Side id) +{ + /* Check that we still have buffer space available. */ + if (id == SideB) { + if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) { + sideB->sendStatusChange(Port::Blocked); + blockedB = true; + } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) { + sideB->sendStatusChange(Port::Unblocked); + blockedB = false; + } + } else { + if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) { + sideA->sendStatusChange(Port::Blocked); + blockedA = true; + } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) { + sideA->sendStatusChange(Port::Unblocked); + blockedA = false; + } + } +} + +void Bridge::timerEvent() +{ + Tick t = 0; + + assert(inboundA.size() || inboundB.size()); + if (inboundA.size()) { + while (inboundA.front().second <= curTick + delay){ + sideB->sendPkt(inboundA.front()); + inboundA.pop_front(); + } + if (inboundA.size()) + t = inboundA.front().second + delay; + } + if (inboundB.size()) { + while (inboundB.front().second <= curTick + delay){ + sideB->sendPkt(inboundA.front()); + inboundB.pop_front(); + } + if (inboundB.size()) + if (t == 0) + t = inboundB.front().second + delay; + else + t = std::min(t,inboundB.front().second + delay); + } else { + panic("timerEvent() called but nothing to do?"); + } + + if (t != 0) + sendEvent.schedule(t); +} + + +void +Bridge::BridgePort::sendPkt(Packet *pkt) +{ + if (!sendTiming(pkt)) + outbound.push_back(std::make_pair<Packet*,Tick>(pkt, curTick)); +} + +void +Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p) +{ + if (!sendTiming(p.first)) + outbound.push_back(p); +} + + +Packet * +Bridge::BridgePort::recvRetry() +{ + Packet *pkt; + assert(outbound.size() > 0); + assert(outbound.front().second >= curTick + bridge->delay); + pkt = outbound.front().first; + outbound.pop_front(); + bridge->blockCheck(side); + return pkt; +} + +/** Function called by the port when the bus is recieving a Atomic + * transaction.*/ +Tick +Bridge::recvAtomic(Packet *pkt, Side id) +{ + pkt->time += delay; + + if (id == SideA) + return sideB->sendAtomic(pkt); + else + return sideA->sendAtomic(pkt); +} + +/** Function called by the port when the bus is recieving a Functional + * transaction.*/ +void +Bridge::recvFunctional(Packet *pkt, Side id) +{ + pkt->time += delay; + std::list<std::pair<Packet*, Tick> >::iterator i; + bool pktContinue = true; + + for(i = inboundA.begin(); i != inboundA.end(); ++i) { + if (pkt->intersect(i->first)) { + pktContinue &= fixPacket(pkt, i->first); + } + } + + for(i = inboundB.begin(); i != inboundB.end(); ++i) { + if (pkt->intersect(i->first)) { + pktContinue &= fixPacket(pkt, i->first); + } + } + + for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) { + if (pkt->intersect(i->first)) { + pktContinue &= fixPacket(pkt, i->first); + } + } + + for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) { + if (pkt->intersect(i->first)) { + pktContinue &= fixPacket(pkt, i->first); + } + } + + if (pktContinue) { + if (id == SideA) + sideB->sendFunctional(pkt); + else + sideA->sendFunctional(pkt); + } +} + +/** Function called by the port when the bus is recieving a status change.*/ +void +Bridge::recvStatusChange(Port::Status status, Side id) +{ + if (status == Port::Blocked || status == Port::Unblocked) + return ; + + if (id == SideA) + sideB->sendStatusChange(status); + else + sideA->sendStatusChange(status); +} + +void +Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id) +{ + if (id == SideA) + sideB->getPeerAddressRanges(resp, snoop); + else + sideA->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..5f19ded40 --- /dev/null +++ b/src/mem/bridge.hh @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file 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 +{ + public: + enum Side + { + SideA, + SideB + }; + + protected: + /** Function called by the port when the bus is recieving a Timing + transaction.*/ + bool recvTiming(Packet *pkt, Side id); + + /** Function called by the port when the bus is recieving a Atomic + transaction.*/ + Tick recvAtomic(Packet *pkt, Side id); + + /** Function called by the port when the bus is recieving a Functional + transaction.*/ + void recvFunctional(Packet *pkt, Side id); + + /** Function called by the port when the bus is recieving a status change.*/ + void recvStatusChange(Port::Status status, Side 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, Side id); + + + /** Event that the SendEvent calls when it fires. This code must reschedule + * the send event as required. */ + void timerEvent(); + + /** 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 bus to which this port belongs. */ + Bridge *bridge; + + /** A id to keep track of the intercafe ID this port is connected to. */ + Bridge::Side side; + + public: + + /** Constructor for the BusPort.*/ + BridgePort(Bridge *_bridge, Side _side) + : bridge(_bridge), side(_side) + { } + + int numQueued() { return outbound.size(); } + + protected: + /** Data this is waiting to be transmitted. */ + std::list<std::pair<Packet*, Tick> > outbound; + + void sendPkt(Packet *pkt); + void sendPkt(std::pair<Packet*, Tick> p); + + /** When reciving a timing request from the peer port, + pass it to the bridge. */ + virtual bool recvTiming(Packet *pkt) + { return bridge->recvTiming(pkt, side); } + + /** When reciving a retry request from the peer port, + pass it to the bridge. */ + virtual Packet* recvRetry(); + + /** When reciving a Atomic requestfrom the peer port, + pass it to the bridge. */ + virtual Tick recvAtomic(Packet *pkt) + { return bridge->recvAtomic(pkt, side); } + + /** When reciving a Functional request from the peer port, + pass it to the bridge. */ + virtual void recvFunctional(Packet *pkt) + { bridge->recvFunctional(pkt, side); } + + /** When reciving a status changefrom the peer port, + pass it to the bridge. */ + virtual void recvStatusChange(Status status) + { bridge->recvStatusChange(status, side); } + + /** When reciving a address range request the peer port, + pass it to the bridge. */ + virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) + { bridge->addressRanges(resp, snoop, side); } + + friend class Bridge; + }; + + class SendEvent : public Event + { + Bridge *bridge; + + SendEvent(Bridge *b) + : Event(&mainEventQueue), bridge(b) {} + + virtual void process() { bridge->timerEvent(); } + + virtual const char *description() { return "bridge delay event"; } + friend class Bridge; + }; + + SendEvent sendEvent; + + /** Sides of the bus bridges. */ + BridgePort* sideA; + BridgePort* sideB; + + /** inbound queues on both sides. */ + std::list<std::pair<Packet*, Tick> > inboundA; + std::list<std::pair<Packet*, Tick> > inboundB; + + /** The size of the queue for data coming into side a */ + int queueSizeA; + int queueSizeB; + + /* if the side is blocked or not. */ + bool blockedA; + bool blockedB; + + /** Miminum delay though this bridge. */ + Tick delay; + + /** 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) + { + if (if_name == "side_a") { + if (sideA != NULL) + panic("bridge side a already connected to."); + sideA = new BridgePort(this, SideA); + return sideA; + } else if (if_name == "side_b") { + if (sideB != NULL) + panic("bridge side b already connected to."); + sideB = new BridgePort(this, SideB); + return sideB; + } else + return NULL; + } + + virtual void init(); + + Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack) + : MemObject(n), sendEvent(this), sideA(NULL), sideB(NULL), + queueSizeA(qsa), queueSizeB(qsb), blockedA(false), blockedB(false), + delay(_delay), ackWrites(write_ack) + {} + + /** Check if the port should block/unblock after recieving/sending a packet. + * */ + void blockCheck(Side id); + + friend class Bridge::SendEvent; + +}; + +#endif //__MEM_BUS_HH__ diff --git a/src/mem/bus.cc b/src/mem/bus.cc new file mode 100644 index 000000000..f7c2b874a --- /dev/null +++ b/src/mem/bus.cc @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Definition of a bus object. + */ + + +#include "base/trace.hh" +#include "mem/bus.hh" +#include "sim/builder.hh" + +/** 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 recieving a Timing + * transaction.*/ +bool +Bus::recvTiming(Packet *pkt) +{ + Port *port; + if (pkt->dest == Packet::Broadcast) { + port = findPort(pkt->addr, pkt->src); + } else { + assert(pkt->dest > 0 && pkt->dest < interfaces.size()); + port = interfaces[pkt->dest]; + } + return port->sendTiming(pkt); +} + +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: %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 recieving a Atomic + * transaction.*/ +Tick +Bus::recvAtomic(Packet *pkt) +{ + assert(pkt->dest == Packet::Broadcast); + return findPort(pkt->addr, pkt->src)->sendAtomic(pkt); +} + +/** Function called by the port when the bus is recieving a Functional + * transaction.*/ +void +Bus::recvFunctional(Packet *pkt) +{ + assert(pkt->dest == Packet::Broadcast); + findPort(pkt->addr, pkt->src)->sendFunctional(pkt); +} + +/** Function called by the port when the bus is recieving a status change.*/ +void +Bus::recvStatusChange(Port::Status status, int id) +{ + DPRINTF(Bus, "Bus %d recieved status change from device id %d\n", + busId, id); + assert(status == Port::RangeChange && + "The other statuses need to be implemented."); + + 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(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, + dm.range.end, id); + portList.push_back(dm); + } + DPRINTF(MMU, "port list has %d entries\n", portList.size()); + + // 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(Bus, "Bus id %d recieved address range request returning\n", + busId); + for (portIter = portList.begin(); portIter != portList.end(); portIter++) { + if (portIter->portId != id) { + resp.push_back(portIter->range); + DPRINTF(Bus, "-- %#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..38573e514 --- /dev/null +++ b/src/mem/bus.hh @@ -0,0 +1,164 @@ +/* + * 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. + */ + +/** + * @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); + + /** 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(Bus *_bus, int _id) + : 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->src = 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->src = 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->src = 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); } + + // 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; + + public: + + /** A function used to return the port associated with this bus object. */ + virtual Port *getPort(const std::string &if_name) + { + // if_name ignored? forced to be empty? + int id = interfaces.size(); + interfaces.push_back(new BusPort(this, id)); + return interfaces.back(); + } + + 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..6c27256a9 --- /dev/null +++ b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh @@ -0,0 +1,73 @@ +/* + * 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. + */ + +/** + * @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..03eb570f0 --- /dev/null +++ b/src/mem/config/prefetch.hh @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/** + * @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..f579a0727 --- /dev/null +++ b/src/mem/mem_object.cc @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#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..58930eccc --- /dev/null +++ b/src/mem/mem_object.hh @@ -0,0 +1,54 @@ +/* + * 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. + */ + +/** + * @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..a9be7ac51 --- /dev/null +++ b/src/mem/packet.cc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Definition of 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" + + +/** 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[size]; +} + +/** Do the packet modify the same addresses. */ +bool +Packet::intersect(Packet *p) { + Addr s1 = addr; + Addr e1 = addr + size; + Addr s2 = p->addr; + Addr e2 = p->addr + p->size; + + if (s1 >= s2 && s1 < e2) + return true; + if (e1 >= s2 && e1 < e2) + return true; + return false; +} + +/** Minimally reset a packet so something like simple cpu can reuse it. */ +void +Packet::reset() { + result = Unknown; + if (dynamicData) { + deleteData(); + dynamicData = false; + arrayData = false; + time = curTick; + } +} + + + + +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..e8a7b0c73 --- /dev/null +++ b/src/mem/packet.hh @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of the Packet Class, a packet is a transaction occuring + * between a single level of the memory heirarchy (ie L1->L2). + */ + +#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; + +/** List of all commands associated with a packet. */ +enum Command +{ + Read, + Write +}; + +/** The result of a particular pakets request. */ +enum PacketResult +{ + Success, + BadAddress, + Unknown +}; + +class SenderState{}; +class Coherence{}; + +/** + * A Packet is the structure to handle requests between two levels + * of the memory system. The Request is a global object that trancends + * all of the memory heirarchy, but at each levels interface a packet + * is created to transfer data/requests. For example, a request would + * be used to initiate a request to go to memory/IOdevices, as the request + * passes through the memory system several packets will be created. One + * will be created to go between the L1 and L2 caches and another to go to + * the next level and so forth. + * + * Packets are assumed to be returned in the case of a single response. If + * the transaction has no response, then the consumer will delete the packet. + */ +struct Packet +{ + private: + /** A pointer to the data being transfered. It can be differnt sizes + at each level of the heirarchy so it belongs in the packet, + not request. This may or may not be populated when a responder recieves + the packet. If not populated it memory should be allocated. + */ + PacketDataPtr data; + + /** Is the data pointer set to a value that shouldn't be freed when the + * packet is destroyed? */ + bool staticData; + /** The data pointer points to a value that should be freed when the packet + * is destroyed. */ + bool dynamicData; + /** the data pointer points to an array (thus delete [] ) needs to be called + * on it rather than simply delete.*/ + bool arrayData; + + + public: + /** The address of the request, could be virtual or physical (depending on + cache configurations). */ + Addr addr; + + /** Flag structure to hold flags for this particular packet */ + uint64_t flags; + + /** A pointer to the overall request. */ + RequestPtr req; + + /** A virtual base opaque structure used to hold + coherence status messages. */ + Coherence *coherence; // virtual base opaque, + // assert(dynamic_cast<Foo>) etc. + + /** A virtual base opaque structure used to hold the senders state. */ + void *senderState; // virtual base opaque, + // assert(dynamic_cast<Foo>) etc. + + /** Indicates the size of the request. */ + int size; + + /** A index of the source of the transaction. */ + short src; + + static const short Broadcast = -1; + + /** A index to the destination of the transaction. */ + short dest; + + /** The command of the transaction. */ + Command cmd; + + /** The time this request was responded to. Used to calculate latencies. */ + Tick time; + + /** The result of the packet transaction. */ + PacketResult result; + + /** Accessor function that returns the source index of the packet. */ + short getSrc() const { return src; } + + /** Accessor function that returns the destination index of + the packet. */ + short getDest() const { return dest; } + + Packet() + : data(NULL), staticData(false), dynamicData(false), arrayData(false), + time(curTick), result(Unknown) + {} + + ~Packet() + { deleteData(); } + + + /** Minimally reset a packet so something like simple cpu can reuse it. */ + void reset(); + + /** 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..c4e1ea193 --- /dev/null +++ b/src/mem/page_table.cc @@ -0,0 +1,134 @@ +/* + * 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. + */ + +/** + * @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..26248261a --- /dev/null +++ b/src/mem/page_table.hh @@ -0,0 +1,90 @@ +/* + * 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. + */ + +/** + * @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..bc2500678 --- /dev/null +++ b/src/mem/physical.cc @@ -0,0 +1,373 @@ +/* + * 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. + */ + +#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); + + pkt->dest = pkt->src; + MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort); + response->schedule(curTick + lat); + + return true; +} + +Tick +PhysicalMemory::doAtomicAccess(Packet *pkt) +{ + doFunctionalAccess(pkt); + pkt->time = curTick + lat; + return curTick + lat; +} + +void +PhysicalMemory::doFunctionalAccess(Packet *pkt) +{ + assert(pkt->addr + pkt->size < pmem_size); + + switch (pkt->cmd) { + case Read: + memcpy(pkt->getPtr<uint8_t>(), pmem_addr + pkt->addr - base_addr, + pkt->size); + break; + case Write: + memcpy(pmem_addr + pkt->addr - base_addr, pkt->getPtr<uint8_t>(), + pkt->size); + // 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 = 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(this); + return port; + } else if (if_name == "functional") { + /* special port for functional writes at startup. */ + return new MemoryPort(this); + } else { + panic("PhysicalMemory::getPort: unknown port %s requested", if_name); + } +} + +void +PhysicalMemory::recvStatusChange(Port::Status status) +{ +} + +PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory) + : 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 §ion) +{ + 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..1cf5444ab --- /dev/null +++ b/src/mem/physical.hh @@ -0,0 +1,127 @@ +/* + * 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. + */ + +/* @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(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 §ion); + +}; + +#endif //__PHYSICAL_MEMORY_HH__ diff --git a/src/mem/port.cc b/src/mem/port.cc new file mode 100644 index 000000000..fb3103ed1 --- /dev/null +++ b/src/mem/port.cc @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/** + * @file Port object definitions. + */ + +#include "base/chunk_generator.hh" +#include "mem/packet_impl.hh" +#include "mem/port.hh" + +void +Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd) +{ + Request req(false); + Packet pkt; + pkt.req = &req; + pkt.cmd = cmd; + pkt.dest = Packet::Broadcast; + + for (ChunkGenerator gen(addr, size, peerBlockSize()); + !gen.done(); gen.next()) { + req.setPaddr(pkt.addr = gen.addr()); + req.setSize(pkt.size = gen.size()); + pkt.dataStatic(p); + sendFunctional(&pkt); + p += gen.size(); + } +} + +void +Port::writeBlob(Addr addr, uint8_t *p, int size) +{ + blobHelper(addr, p, size, Write); +} + +void +Port::readBlob(Addr addr, uint8_t *p, int size) +{ + blobHelper(addr, p, size, Read); +} + +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, Write); + + delete [] buf; +} diff --git a/src/mem/port.hh b/src/mem/port.hh new file mode 100644 index 000000000..1b1920c03 --- /dev/null +++ b/src/mem/port.hh @@ -0,0 +1,247 @@ +/* + * 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. + */ + +/** + * @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 +{ + public: + + virtual ~Port() {}; + // mey be better to use subclasses & RTTI? + /** Holds the ports status. Keeps track if it is blocked, or has + calculated a range change. */ + enum Status { + Blocked, + Unblocked, + RangeChange + }; + + private: + + /** 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: + + /** Function to set the pointer for the peer port. + @todo should be called by the configuration stuff (python). + */ + void setPeer(Port *port) { peer = 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 Packet *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 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. + */ + 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. + */ + Packet *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, Command cmd); +}; + +/** A simple functional port that is only meant for one way communication to + * physical memory. It is only meant to be used to load data into memory before + * the simulation begins. + */ + +class FunctionalPort : public Port +{ + public: + virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); } + virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); } + virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); } + virtual void recvStatusChange(Status status) {} + + 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/request.hh b/src/mem/request.hh new file mode 100644 index 000000000..2db7b7779 --- /dev/null +++ b/src/mem/request.hh @@ -0,0 +1,200 @@ +/* + * 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. + */ + +/** + * @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 +{ + //@todo Make Accesor functions, make these private. + public: + /** Constructor, needs a bool to signify if it is/isn't Cpu Request. */ + Request(bool isCpu); + + /** reset the request to it's initial state so it can be reused.*/ + void resetAll(bool isCpu); + + /** reset the request's addrs times, etc, so but not everything to same + * time. */ + void resetMin(); + +//First non-cpu request fields + private: + /** The physical address of the request. */ + Addr paddr; + /** Wether or not paddr is valid (has been written yet). */ + bool validPaddr; + + /** The size of the request. */ + int size; + /** Wether or not size is valid (has been written yet). */ + bool validSize; + + /** The time this request was started. Used to calculate latencies. */ + Tick time; + /** Wether or not time is valid (has been written yet). */ + bool validTime; + + /** Destination address if this is a block copy. */ + Addr copyDest; + /** Wether or not copyDest is valid (has been written yet). */ + bool validCopyDest; + + /** Flag structure for the request. */ + uint32_t flags; + +//Accsesors for non-cpu request fields + public: + /** Accesor for paddr. */ + Addr getPaddr(); + /** Accesor for paddr. */ + void setPaddr(Addr _paddr); + + /** Accesor for size. */ + int getSize(); + /** Accesor for size. */ + void setSize(int _size); + + /** Accesor for time. */ + Tick getTime(); + /** Accesor for time. */ + void setTime(Tick _time); + + /** Accesor for copy dest. */ + Addr getCopyDest(); + /** Accesor for copy dest. */ + void setCopyDest(Addr _copyDest); + + /** Accesor for flags. */ + uint32_t getFlags(); + /** Accesor for paddr. */ + void setFlags(uint32_t _flags); + +//Now cpu-request fields + private: + /** Bool to signify if this is a cpuRequest. */ + bool cpuReq; + + /** The virtual address of the request. */ + Addr vaddr; + /** Wether or not the vaddr is valid. */ + bool validVaddr; + + /** The address space ID. */ + int asid; + /** Wether or not the asid is valid. */ + bool validAsid; + + /** The return value of store conditional. */ + uint64_t scResult; + /** Wether or not the sc result is valid. */ + bool validScResult; + + /** The cpu number for statistics. */ + int cpuNum; + /** Wether or not the cpu number is valid. */ + bool validCpuNum; + + /** The requesting thread id. */ + int threadNum; + /** Wether or not the thread id is valid. */ + bool validThreadNum; + + /** program counter of initiating access; for tracing/debugging */ + Addr pc; + /** Wether or not the pc is valid. */ + bool validPC; + +//Accessor Functions for cpu request fields + public: + /** Accesor function to determine if this is a cpu request or not.*/ + bool isCpuRequest(); + + /** Accesor function for vaddr.*/ + Addr getVaddr(); + /** Accesor function for vaddr.*/ + void setVaddr(Addr _vaddr); + + /** Accesor function for asid.*/ + int getAsid(); + /** Accesor function for asid.*/ + void setAsid(int _asid); + + /** Accesor function for store conditional return value.*/ + uint64_t getScResult(); + /** Accesor function for store conditional return value.*/ + void setScResult(uint64_t _scResult); + + /** Accesor function for cpu number.*/ + int getCpuNum(); + /** Accesor function for cpu number.*/ + void setCpuNum(int _cpuNum); + + /** Accesor function for thread number.*/ + int getThreadNum(); + /** Accesor function for thread number.*/ + void setThreadNum(int _threadNum); + + /** Accesor function for pc.*/ + Addr getPC(); + /** Accesor function for pc.*/ + void setPC(Addr _pc); + +}; + +#endif // __MEM_REQUEST_HH__ diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc new file mode 100644 index 000000000..5dfeaff31 --- /dev/null +++ b/src/mem/translating_port.cc @@ -0,0 +1,186 @@ +/* + * 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. + */ + +#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(PageTable *p_table, bool alloc) + : 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..7611ac3c7 --- /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. + */ + +#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; + + TranslatingPort(const TranslatingPort &specmem); + const TranslatingPort &operator=(const TranslatingPort &specmem); + + public: + TranslatingPort(PageTable *p_table, bool alloc = false); + virtual ~TranslatingPort(); + + public: + bool tryReadBlob(Addr addr, uint8_t *p, int size); + bool tryWriteBlob(Addr addr, uint8_t *p, int size); + bool 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..cc569acf3 --- /dev/null +++ b/src/mem/vport.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Port object definitions. + */ + +#include "base/chunk_generator.hh" +#include "mem/vport.hh" + +void +VirtualPort::readBlob(Addr addr, uint8_t *p, int size) +{ + Addr paddr; + for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done(); + gen.next()) + { + if (xc) + paddr = TheISA::vtophys(xc,gen.addr()); + else + paddr = TheISA::vtophys(gen.addr()); + + FunctionalPort::readBlob(paddr, p, gen.size()); + p += gen.size(); + } +} + +void +VirtualPort::writeBlob(Addr addr, uint8_t *p, int size) +{ + Addr paddr; + for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done(); + gen.next()) + { + if (xc) + paddr = TheISA::vtophys(xc,gen.addr()); + else + paddr = TheISA::vtophys(gen.addr()); + + FunctionalPort::writeBlob(paddr, p, gen.size()); + p += gen.size(); + } +} + diff --git a/src/mem/vport.hh b/src/mem/vport.hh new file mode 100644 index 000000000..fbc230ba3 --- /dev/null +++ b/src/mem/vport.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Virtual Port Object Decleration. These ports incorporate some translation + * into their access methods. Thus you can use one to read and write data + * to/from virtual addresses. + */ + +#ifndef __MEM_VPORT_HH__ +#define __MEM_VPORT_HH__ + +#include "mem/port.hh" +#include "config/full_system.hh" +#include "arch/vtophys.hh" + + +/** A class that translates a virtual address to a physical address and then + * calls the above read/write functions. If an execution context is provided the + * address can alway be translated, If not it can only be translated if it is a + * simple address masking operation (such as alpha super page accesses). + */ + +class VirtualPort : public FunctionalPort +{ + private: + ExecContext *xc; + + public: + VirtualPort(ExecContext *_xc = NULL) + : xc(_xc) + {} + + /** Return true if we have an exec context. This is used to prevent someone + * from accidently deleting the cpus statically allocated vport. + * @return true if an execution context isn't valid + */ + bool nullExecContext() { return xc != NULL; } + + /** 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__ + |