panic("Security Extensions not implemented!");
}
warn("Translating via MISCREG in atomic mode! Fix Me!\n");
- req->setVirt(0, val, 1, flags, tc->pcState().pc());
+ req->setVirt(0, val, 1, flags, tc->pcState().pc(),
+ Request::funcMasterId);
fault = tc->getDTBPtr()->translateAtomic(req, tc, mode);
if (fault == NoFault) {
miscRegs[MISCREG_PAR] =
TableWalker::TableWalker(const Params *p)
: MemObject(p), port(NULL), tlb(NULL), currState(NULL), pending(false),
+ masterId(p->sys->getMasterId(name())),
doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this)
{
sctlr = 0;
;
}
-
unsigned int
TableWalker::drain(Event *de)
{
doL1Descriptor();
f = currState->fault;
} else {
- RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag);
+ RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId);
PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
port->sendFunctional(pkt);
currState->tc->getCpuPtr()->ticks(1));
doL2Descriptor();
} else {
- RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0);
+ RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0, masterId);
PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
pkt->dataStatic((uint8_t*)&currState->l2Desc.data);
port->sendFunctional(pkt);
/** If a timing translation is currently in progress */
bool pending;
+ /** Request id for requests generated by this walker */
+ MasterID masterId;
+
public:
typedef ArmTableWalkerParams Params;
TableWalker(const Params *p);
prepIntRequest(const uint8_t id, Addr offset, Addr size)
{
RequestPtr req = new Request(x86InterruptAddress(id, offset),
- size, Request::UNCACHEABLE);
+ size, Request::UNCACHEABLE,
+ Request::intMasterId);
PacketPtr pkt = new Packet(req, MemCmd::MessageReq, Packet::Broadcast);
pkt->allocate();
return pkt;
Request::Flags flags = oldRead->req->getFlags();
flags.set(Request::UNCACHEABLE, uncacheable);
RequestPtr request =
- new Request(nextRead, oldRead->getSize(), flags);
+ new Request(nextRead, oldRead->getSize(), flags, walker->masterId);
read = new Packet(request, MemCmd::ReadReq, Packet::Broadcast);
read->allocate();
// If we need to write, adjust the read packet to write the modified
Request::Flags flags = Request::PHYSICAL;
if (cr3.pcd)
flags.set(Request::UNCACHEABLE);
- RequestPtr request = new Request(topAddr, dataSize, flags);
+ RequestPtr request = new Request(topAddr, dataSize, flags, walker->masterId);
read = new Packet(request, MemCmd::ReadReq, Packet::Broadcast);
read->allocate();
}
#include "mem/packet.hh"
#include "params/X86PagetableWalker.hh"
#include "sim/faults.hh"
+#include "sim/system.hh"
class ThreadContext;
{}
protected:
- Walker * walker;
+ Walker *walker;
bool recvTiming(PacketPtr pkt);
Tick recvAtomic(PacketPtr pkt);
};
protected:
- Walker * walker;
+ Walker *walker;
ThreadContext *tc;
RequestPtr req;
State state;
bool timing;
bool retrying;
bool started;
-
public:
WalkerState(Walker * _walker, BaseTLB::Translation *_translation,
RequestPtr _req, bool _isFunctional = false) :
// The TLB we're supposed to load.
TLB * tlb;
System * sys;
+ MasterID masterId;
// Functions for dealing with packets.
bool recvTiming(PacketPtr pkt);
typedef X86PagetableWalkerParams Params;
+ const Params *
+ params() const
+ {
+ return static_cast<const Params *>(_params);
+ }
+
Walker(const Params *params) :
MemObject(params), port(name() + ".port", this),
- funcState(this, NULL, NULL, true), tlb(NULL), sys(params->system)
+ funcState(this, NULL, NULL, true), tlb(NULL), sys(params->system),
+ masterId(sys->getMasterId(name()))
{
}
};
BaseCPU::BaseCPU(Params *p)
: MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id),
+ _instMasterId(p->system->getMasterId(name() + ".inst")),
+ _dataMasterId(p->system->getMasterId(name() + ".data")),
interrupts(p->interrupts),
numThreads(p->numThreads), system(p->system),
phase(p->phase)
// therefore no setCpuId() method is provided
int _cpuId;
+ /** instruction side request id that must be placed in all requests */
+ MasterID _instMasterId;
+
+ /** data side request id that must be placed in all requests */
+ MasterID _dataMasterId;
+
/**
* Define a base class for the CPU ports (instruction and data)
* that is refined in the subclasses. This class handles the
/** Reads this CPU's ID. */
int cpuId() { return _cpuId; }
+ /** Reads this CPU's unique data requestor ID */
+ MasterID dataMasterId() { return _dataMasterId; }
+ /** Reads this CPU's unique instruction requestor ID */
+ MasterID instMasterId() { return _instMasterId; }
+
// Tick currentTick;
inline Tick frequency() const { return SimClock::Frequency / clock; }
inline Tick ticks(int numCycles) const { return clock * numCycles; }
/** Read this CPU's ID. */
int cpuId() { return cpu->cpuId(); }
+ /** Read this CPU's data requestor ID */
+ MasterID masterId() { return cpu->dataMasterId(); }
+
/** Read this context's system-wide ID **/
int contextId() { return thread->contextId(); }
sreqLow = savedSreqLow;
sreqHigh = savedSreqHigh;
} else {
- req = new Request(asid, addr, size, flags, this->pc.instAddr(),
+ req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(),
thread->contextId(), threadNumber);
// Only split the request if the ISA supports unaligned accesses.
sreqLow = savedSreqLow;
sreqHigh = savedSreqHigh;
} else {
- req = new Request(asid, addr, size, flags, this->pc.instAddr(),
+ req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(),
thread->contextId(), threadNumber);
// Only split the request if the ISA supports unaligned accesses.
void
CheckerCPU::init()
{
+ masterId = systemPtr->getMasterId(name());
}
CheckerCPU::CheckerCPU(Params *p)
// Need to account for a multiple access like Atomic and Timing CPUs
while (1) {
memReq = new Request();
- memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr());
+ memReq->setVirt(0, addr, size, flags, masterId, thread->pcState().instAddr());
// translate to physical address
fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write);
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
+
+ /** id attached to all issued requests */
+ MasterID masterId;
public:
virtual void init();
fetch_PC, thread->contextId(),
unverifiedInst->threadNumber);
memReq->setVirt(0, fetch_PC, sizeof(MachInst),
- Request::INST_FETCH, thread->instAddr());
+ Request::INST_FETCH, masterId, thread->instAddr());
fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute);
if (cache_req->memReq == NULL) {
cache_req->memReq =
new Request(cpu->asid[tid], aligned_addr, acc_size, flags,
+ cpu->dataMasterId(),
inst->instAddr(),
cpu->readCpuId(), //@todo: use context id
tid);
inst->split2ndAddr,
acc_size,
flags,
+ cpu->dataMasterId(),
inst->instAddr(),
cpu->readCpuId(),
tid);
inst->getMemAddr(),
inst->totalSize,
0,
+ cpu->dataMasterId(),
0);
split_pkt = new Packet(cache_req->memReq, cache_req->pktCmd,
if (cache_req->memReq == NULL) {
cache_req->memReq =
new Request(tid, aligned_addr, acc_size, flags,
- inst->instAddr(), cpu->readCpuId(), tid);
+ cpu->instMasterId(), inst->instAddr(), cpu->readCpuId(),
+ tid);
DPRINTF(InOrderCachePort, "[sn:%i] Created memReq @%x, ->%x\n",
inst->seqNum, &cache_req->memReq, cache_req->memReq);
}
req_size = sizeof(TheISA::MachInst);
flags = 0;
inst->fetchMemReq = new Request(inst->readTid(), aligned_addr,
- req_size, flags, inst->instAddr(),
+ req_size, flags,
+ res->cpu->instMasterId(),
+ inst->instAddr(),
res->cpu->readCpuId(),
inst->readTid());
memReq = inst->fetchMemReq;
}
inst->dataMemReq = new Request(inst->readTid(), aligned_addr,
- req_size, flags, inst->instAddr(),
+ req_size, flags,
+ res->cpu->dataMasterId(),
+ inst->instAddr(),
res->cpu->readCpuId(),
inst->readTid());
memReq = inst->dataMemReq;
// Build request here.
RequestPtr mem_req =
new Request(tid, block_PC, cacheBlkSize, Request::INST_FETCH,
- pc, cpu->thread[tid]->contextId(), tid);
+ cpu->instMasterId(), pc, cpu->thread[tid]->contextId(), tid);
memReq[tid] = mem_req;
dcache_latency = 0;
while (1) {
- req->setVirt(0, addr, size, flags, thread->pcState().instAddr());
+ req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr());
// translate to physical address
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
dcache_latency = 0;
while(1) {
- req->setVirt(0, addr, size, flags, thread->pcState().instAddr());
+ req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr());
// translate to physical address
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
DPRINTF(Fetch, "Fetch: PC:%08p\n", instAddr);
Addr fetchPC = (instAddr & PCMask) + fetchOffset;
- req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instAddr);
+ req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instMasterId(),
+ instAddr);
}
buildPacket(pkt1, req1, read);
buildPacket(pkt2, req2, read);
- req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags());
+ req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags(), dataMasterId());
PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(),
Packet::Broadcast);
}
RequestPtr req = new Request(asid, addr, size,
- flags, pc, _cpuId, tid);
+ flags, dataMasterId(), pc, _cpuId, tid);
Addr split_addr = roundDown(addr + size - 1, block_size);
assert(split_addr <= addr || split_addr - addr < block_size);
}
RequestPtr req = new Request(asid, addr, size,
- flags, pc, _cpuId, tid);
+ flags, dataMasterId(), pc, _cpuId, tid);
Addr split_addr = roundDown(addr + size - 1, block_size);
assert(split_addr <= addr || split_addr - addr < block_size);
*/
#include "cpu/testers/directedtest/DirectedGenerator.hh"
+#include "sim/system.hh"
DirectedGenerator::DirectedGenerator(const Params *p)
- : SimObject(p)
+ : SimObject(p),
+ masterId(p->system->getMasterId(name()))
{
m_num_cpus = p->num_cpus;
m_directed_tester = NULL;
protected:
int m_num_cpus;
+ MasterID masterId;
RubyDirectedTester* m_directed_tester;
};
Packet::Command cmd;
// For simplicity, requests are assumed to be 1 byte-sized
- Request *req = new Request(m_address, 1, flags);
+ Request *req = new Request(m_address, 1, flags, masterId);
//
// Based on the current state, issue a load or a store
type = 'DirectedGenerator'
abstract = True
num_cpus = Param.Int("num of cpus")
+ system = Param.System(Parent.any, "System we belong to")
class SeriesRequestGenerator(DirectedGenerator):
type = 'SeriesRequestGenerator'
Request::Flags flags;
// For simplicity, requests are assumed to be 1 byte-sized
- Request *req = new Request(m_address, 1, flags);
+ Request *req = new Request(m_address, 1, flags, masterId);
Packet::Command cmd;
if (m_issue_writes) {
functional = Port("Port to the functional memory used for verification")
suppress_func_warnings = Param.Bool(False,
"suppress warnings when functional accesses fail.\n")
+ sys = Param.System(Parent.any, "System Parameter")
+
#include "mem/request.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
+#include "sim/system.hh"
using namespace std;
percentFunctional(p->percent_functional),
percentUncacheable(p->percent_uncacheable),
issueDmas(p->issue_dmas),
+ masterId(p->sys->getMasterId(name())),
progressInterval(p->progress_interval),
nextProgressMessage(p->progress_interval),
percentSourceUnaligned(p->percent_source_unaligned),
if (issueDmas) {
paddr &= ~((1 << dma_access_size) - 1);
- req->setPhys(paddr, 1 << dma_access_size, flags);
+ req->setPhys(paddr, 1 << dma_access_size, flags, masterId);
req->setThreadContext(id,0);
} else {
paddr &= ~((1 << access_size) - 1);
- req->setPhys(paddr, 1 << access_size, flags);
+ req->setPhys(paddr, 1 << access_size, flags, masterId);
req->setThreadContext(id,0);
}
assert(req->getSize() == 1);
bool issueDmas;
+ /** Request id for all generated traffic */
+ MasterID masterId;
+
int id;
std::set<unsigned> outstandingAddrs;
from MemObject import MemObject
from m5.params import *
+from m5.proxy import *
class NetworkTest(MemObject):
type = 'NetworkTest'
inj_rate = Param.Float(0.1, "Packet injection rate")
precision = Param.Int(3, "Number of digits of precision after decimal point")
test = Port("Port to the memory system to test")
+ system = Param.System(Parent.any, "System we belong to")
#include "mem/request.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
+#include "sim/system.hh"
using namespace std;
maxPackets(p->max_packets),
trafficType(p->traffic_type),
injRate(p->inj_rate),
- precision(p->precision)
+ precision(p->precision),
+ masterId(p->system->getMasterId(name()))
{
// set up counters
noResponseCycles = 0;
if (randomReqType == 0) {
// generate packet for virtual network 0
requestType = MemCmd::ReadReq;
- req->setPhys(paddr, access_size, flags);
+ req->setPhys(paddr, access_size, flags, masterId);
} else if (randomReqType == 1) {
// generate packet for virtual network 1
requestType = MemCmd::ReadReq;
flags.set(Request::INST_FETCH);
- req->setVirt(0, 0x0, access_size, flags, 0x0);
+ req->setVirt(0, 0x0, access_size, flags, 0x0, masterId);
req->setPaddr(paddr);
} else { // if (randomReqType == 2)
// generate packet for virtual network 2
requestType = MemCmd::WriteReq;
- req->setPhys(paddr, access_size, flags);
+ req->setPhys(paddr, access_size, flags, masterId);
}
req->setThreadContext(id,0);
double injRate;
int precision;
+ MasterID masterId;
+
void completeRequest(PacketPtr pkt);
void generatePkt();
}
// Prefetches are assumed to be 0 sized
- Request *req = new Request(m_address.getAddress(), 0, flags, curTick(),
- m_pc.getAddress());
+ Request *req = new Request(m_address.getAddress(), 0, flags,
+ m_tester_ptr->masterId(), curTick(), m_pc.getAddress());
req->setThreadContext(index, 0);
PacketPtr pkt = new Packet(req, cmd, port->idx);
Request::Flags flags;
- Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags, curTick(),
- m_pc.getAddress());
+ Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags,
+ m_tester_ptr->masterId(), curTick(), m_pc.getAddress());
Packet::Command cmd;
Address writeAddr(m_address.getAddress() + m_store_count);
// Stores are assumed to be 1 byte-sized
- Request *req = new Request(writeAddr.getAddress(), 1, flags, curTick(),
+ Request *req = new Request(writeAddr.getAddress(), 1, flags,
+ m_tester_ptr->masterId(), curTick(),
m_pc.getAddress());
req->setThreadContext(index, 0);
// Checks are sized depending on the number of bytes written
Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags,
- curTick(), m_pc.getAddress());
+ m_tester_ptr->masterId(), curTick(), m_pc.getAddress());
req->setThreadContext(index, 0);
PacketPtr pkt = new Packet(req, MemCmd::ReadReq, port->idx);
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/system/System.hh"
#include "sim/sim_exit.hh"
+#include "sim/system.hh"
RubyTester::RubyTester(const Params *p)
: MemObject(p), checkStartEvent(this),
+ _masterId(p->system->getMasterId(name())),
m_checks_to_complete(p->checks_to_complete),
m_deadlock_threshold(p->deadlock_threshold),
m_wakeup_frequency(p->wakeup_frequency),
void print(std::ostream& out) const;
bool getCheckFlush() { return m_check_flush; }
+ MasterID masterId() { return _masterId; }
protected:
class CheckStartEvent : public Event
{
CheckStartEvent checkStartEvent;
+ MasterID _masterId;
+
private:
void hitCallback(NodeID proc, SubBlock* data);
deadlock_threshold = Param.Int(50000, "how often to check for deadlock")
wakeup_frequency = Param.Int(10, "number of cycles between wakeups")
check_flush = Param.Bool(False, "check cache flushing")
+ system = Param.System(Parent.any, "System we belong to")
DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff,
bool recv_snoops)
: Port(dev->name() + "-dmaport", dev), device(dev), sys(s),
+ masterId(s->getMasterId(dev->name())),
pendingCount(0), actionInProgress(0), drainEvent(NULL),
backoffTime(0), minBackoffDelay(min_backoff),
maxBackoffDelay(max_backoff), inRetry(false), recvSnoops(recv_snoops),
: PioDevice(p), dmaPort(NULL)
{ }
-
unsigned int
DmaDevice::drain(Event *de)
{
event ? event->scheduled() : -1 );
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
- Request *req = new Request(gen.addr(), gen.size(), flag);
+ Request *req = new Request(gen.addr(), gen.size(), flag, masterId);
PacketPtr pkt = new Packet(req, cmd, Packet::Broadcast);
// Increment the data pointer on a write
* we are currently operating in. */
System *sys;
+ /** Id for all requests */
+ MasterID masterId;
+
/** Number of outstanding packets the dma port has. */
int pendingCount;
writebacks[0/*pkt->req->threadId()*/]++;
Request *writebackReq =
- new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0);
+ new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0,
+ Request::wbMasterId);
PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback, -1);
if (blk->isWritable()) {
writeback->setSupplyExclusive();
from m5.SimObject import SimObject
from m5.params import *
+from m5.proxy import *
+
class BasePrefetcher(SimObject):
type = 'BasePrefetcher'
abstract = True
"Degree of the prefetch depth")
latency = Param.Latency('10t',
"Latency of the prefetcher")
- use_cpu_id = Param.Bool(True,
- "Use the CPU ID to separate calculations of prefetches")
+ use_master_id = Param.Bool(True,
+ "Use the master id to separate calculations of prefetches")
data_accesses_only = Param.Bool(False,
"Only prefetch on data not on instruction accesses")
+ sys = Param.System(Parent.any, "System this device belongs to")
class GHBPrefetcher(BasePrefetcher):
type = 'GHBPrefetcher'
#include "mem/cache/prefetch/base.hh"
#include "mem/cache/base.hh"
#include "mem/request.hh"
+#include "sim/system.hh"
BasePrefetcher::BasePrefetcher(const Params *p)
: SimObject(p), size(p->size), latency(p->latency), degree(p->degree),
- useContextId(p->use_cpu_id), pageStop(!p->cross_pages),
- serialSquash(p->serial_squash), onlyData(p->data_accesses_only)
+ useMasterId(p->use_master_id), pageStop(!p->cross_pages),
+ serialSquash(p->serial_squash), onlyData(p->data_accesses_only),
+ system(p->sys), masterId(system->getMasterId(name()))
{
}
}
// create a prefetch memreq
- Request *prefetchReq = new Request(*addrIter, blkSize, 0);
+ Request *prefetchReq = new Request(*addrIter, blkSize, 0, masterId);
PacketPtr prefetch =
new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast);
prefetch->allocate();
unsigned degree;
/** If patterns should be found per context id */
- bool useContextId;
+ bool useMasterId;
/** Do we prefetch across page boundaries. */
bool pageStop;
/** Do we prefetch on only data reads, or on inst reads as well. */
bool onlyData;
+ /** System we belong to */
+ System* system;
+
+ /** Request id for prefetches */
+ MasterID masterId;
+
public:
Stats::Scalar pfIdentified;
GHBPrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
std::list<Tick> &delays)
{
- if (useContextId && !pkt->req->hasContextId()) {
- DPRINTF(HWPrefetch, "ignoring request with no context ID");
- return;
- }
-
Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
- int ctx_id = useContextId ? pkt->req->contextId() : 0;
- assert(ctx_id < Max_Contexts);
+ int master_id = useMasterId ? pkt->req->masterId() : 0;
+ assert(master_id < Max_Masters);
- int new_stride = blk_addr - lastMissAddr[ctx_id];
- int old_stride = lastMissAddr[ctx_id] - secondLastMissAddr[ctx_id];
+ int new_stride = blk_addr - lastMissAddr[master_id];
+ int old_stride = lastMissAddr[master_id] - secondLastMissAddr[master_id];
- secondLastMissAddr[ctx_id] = lastMissAddr[ctx_id];
- lastMissAddr[ctx_id] = blk_addr;
+ secondLastMissAddr[master_id] = lastMissAddr[master_id];
+ lastMissAddr[master_id] = blk_addr;
if (new_stride == old_stride) {
for (int d = 1; d <= degree; d++) {
{
protected:
- static const int Max_Contexts = 64;
+ static const int Max_Masters = 64;
- Addr secondLastMissAddr[Max_Contexts];
- Addr lastMissAddr[Max_Contexts];
+ Addr secondLastMissAddr[Max_Masters];
+ Addr lastMissAddr[Max_Masters];
public:
GHBPrefetcher(const Params *p)
return;
}
- if (useContextId && !pkt->req->hasContextId()) {
- DPRINTF(HWPrefetch, "ignoring request with no context ID");
- return;
- }
-
Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
- int ctx_id = useContextId ? pkt->req->contextId() : 0;
+ MasterID master_id = useMasterId ? pkt->req->masterId() : 0;
Addr pc = pkt->req->getPC();
- assert(ctx_id < Max_Contexts);
- std::list<StrideEntry*> &tab = table[ctx_id];
+ assert(master_id < Max_Contexts);
+ std::list<StrideEntry*> &tab = table[master_id];
/* Scan Table for instAddr Match */
std::list<StrideEntry*>::iterator iter;
tag_ptr->size);
*/
Request *writebackReq = new Request(regenerateBlkAddr(tag_ptr->tag, 0),
- blkSize, 0);
+ blkSize, 0, Request::wbMasterId);
PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback,
-1);
writeback->allocate();
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
- req.setPhys(gen.addr(), gen.size(), 0);
+ req.setPhys(gen.addr(), gen.size(), 0, Request::funcMasterId);
Packet pkt(&req, cmd, Packet::Broadcast);
pkt.dataStatic(p);
sendFunctional(&pkt);
void
Port::printAddr(Addr a)
{
- Request req(a, 1, 0);
+ Request req(a, 1, 0, Request::funcMasterId);
Packet pkt(&req, MemCmd::PrintReq, Packet::Broadcast);
Packet::PrintReqState prs(std::cerr);
pkt.senderState = &prs;
class Request;
typedef Request* RequestPtr;
+typedef uint16_t MasterID;
class Request : public FastAlloc
{
(assigned a new address). */
static const FlagsType STICKY_FLAGS = INST_FETCH;
+ /** Request Ids that are statically allocated
+ * @{*/
+ /** This request id is used for writeback requests by the caches */
+ static const MasterID wbMasterId = 0;
+ /** This request id is used for functional requests that don't come from a
+ * particular device
+ */
+ static const MasterID funcMasterId = 1;
+ /** This request id is used for message signaled interrupts */
+ static const MasterID intMasterId = 2;
+ /** @} */
+
private:
typedef uint8_t PrivateFlagsType;
typedef ::Flags<PrivateFlagsType> PrivateFlags;
*/
int _size;
+ /** The requestor ID which is unique in the system for all ports
+ * that are capable of issuing a transaction
+ */
+ MasterID _masterId;
+
/** Flag structure for the request. */
Flags _flags;
* just physical address, size, flags, and timestamp (to curTick()).
* These fields are adequate to perform a request.
*/
- Request(Addr paddr, int size, Flags flags)
+ Request(Addr paddr, int size, Flags flags, MasterID mid)
{
- setPhys(paddr, size, flags);
+ setPhys(paddr, size, flags, mid);
}
- Request(Addr paddr, int size, Flags flags, Tick time)
+ Request(Addr paddr, int size, Flags flags, MasterID mid, Tick time)
{
- setPhys(paddr, size, flags, time);
+ setPhys(paddr, size, flags, mid, time);
}
- Request(Addr paddr, int size, Flags flags, Tick time, Addr pc)
+ Request(Addr paddr, int size, Flags flags, MasterID mid, Tick time, Addr pc)
{
- setPhys(paddr, size, flags, time);
+ setPhys(paddr, size, flags, mid, time);
privateFlags.set(VALID_PC);
_pc = pc;
}
- Request(int asid, Addr vaddr, int size, Flags flags, Addr pc,
+ Request(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc,
int cid, ThreadID tid)
{
- setVirt(asid, vaddr, size, flags, pc);
+ setVirt(asid, vaddr, size, flags, mid, pc);
setThreadContext(cid, tid);
}
* allocated Request object.
*/
void
- setPhys(Addr paddr, int size, Flags flags, Tick time)
+ setPhys(Addr paddr, int size, Flags flags, MasterID mid, Tick time)
{
assert(size >= 0);
_paddr = paddr;
_size = size;
_time = time;
-
+ _masterId = mid;
_flags.clear(~STICKY_FLAGS);
_flags.set(flags);
privateFlags.clear(~STICKY_PRIVATE_FLAGS);
}
void
- setPhys(Addr paddr, int size, Flags flags)
+ setPhys(Addr paddr, int size, Flags flags, MasterID mid)
{
- setPhys(paddr, size, flags, curTick());
+ setPhys(paddr, size, flags, mid, curTick());
}
/**
* allocated Request object.
*/
void
- setVirt(int asid, Addr vaddr, int size, Flags flags, Addr pc)
+ setVirt(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc)
{
assert(size >= 0);
_asid = asid;
_vaddr = vaddr;
_size = size;
+ _masterId = mid;
_pc = pc;
_time = curTick();
return _vaddr;
}
+ /** Accesssor for the requestor id. */
+ MasterID
+ masterId()
+ {
+ return _masterId;
+ }
+
/** Accessor function for asid.*/
int
getAsid()
TraceRecord* rec = m_records[m_records_flushed];
m_records_flushed++;
Request* req = new Request(rec->m_data_address,
- RubySystem::getBlockSizeBytes(),0);
+ RubySystem::getBlockSizeBytes(),0,
+ Request::funcMasterId);
MemCmd::Command requestType = MemCmd::FlushReq;
Packet *pkt = new Packet(req, requestType, -1);
if (traceRecord->m_type == RubyRequestType_LD) {
requestType = MemCmd::ReadReq;
req->setPhys(traceRecord->m_data_address,
- RubySystem::getBlockSizeBytes(),0);
+ RubySystem::getBlockSizeBytes(),0, Request::funcMasterId);
} else if (traceRecord->m_type == RubyRequestType_IFETCH) {
requestType = MemCmd::ReadReq;
req->setPhys(traceRecord->m_data_address,
RubySystem::getBlockSizeBytes(),
- Request::INST_FETCH);
+ Request::INST_FETCH, Request::funcMasterId);
} else {
requestType = MemCmd::WriteReq;
req->setPhys(traceRecord->m_data_address,
- RubySystem::getBlockSizeBytes(),0);
+ RubySystem::getBlockSizeBytes(),0, Request::funcMasterId);
}
Packet *pkt = new Packet(req, requestType, -1);
RubyPort::ruby_eviction_callback(const Address& address)
{
DPRINTF(RubyPort, "Sending invalidations.\n");
- Request req(address.getAddress(), 0, 0);
+ Request req(address.getAddress(), 0, 0, Request::funcMasterId);
for (CpuPortIter it = cpu_ports.begin(); it != cpu_ports.end(); it++) {
Packet *pkt = new Packet(&req, MemCmd::InvalidationReq, -1);
(*it)->sendTiming(pkt);
physProxy = new PortProxy(*getSystemPort());
virtProxy = new FSTranslatingPortProxy(*getSystemPort());
}
+
+ // Get the generic system master IDs
+ MasterID tmp_id M5_VAR_USED;
+ tmp_id = getMasterId("writebacks");
+ assert(tmp_id == Request::wbMasterId);
+ tmp_id = getMasterId("functional");
+ assert(tmp_id == Request::funcMasterId);
+ tmp_id = getMasterId("interrupt");
+ assert(tmp_id == Request::intMasterId);
+
}
System::~System()
System::printSystems();
}
+MasterID
+System::getMasterId(std::string master_name)
+{
+ // strip off system name if the string starts with it
+ if (master_name.size() > name().size() &&
+ master_name.compare(0, name().size(), name()) == 0)
+ master_name = master_name.erase(0, name().size() + 1);
+
+ // CPUs in switch_cpus ask for ids again after switching
+ for (int i = 0; i < masterIds.size(); i++) {
+ if (masterIds[i] == master_name) {
+ return i;
+ }
+ }
+
+ // todo: Check if stats are enabled yet
+ // I just don't know a good way to do it
+
+ if (false)
+ fatal("Can't request a masterId after regStats(). \
+ You must do so in init().\n");
+
+ masterIds.push_back(master_name);
+
+ return masterIds.size() - 1;
+}
+
+std::string
+System::getMasterName(MasterID master_id)
+{
+ if (master_id >= masterIds.size())
+ fatal("Invalid master_id passed to getMasterName()\n");
+
+ return masterIds[master_id];
+}
+
const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
"timing"};
uint32_t numWorkIds;
std::vector<bool> activeCpus;
+ /** This array is a per-sytem list of all devices capable of issuing a
+ * memory system request and an associated string for each master id.
+ * It's used to uniquely id any master in the system by name for things
+ * like cache statistics.
+ */
+ std::vector<std::string> masterIds;
+
public:
+
+ /** Request an id used to create a request object in the system. All objects
+ * that intend to issues requests into the memory system must request an id
+ * in the init() phase of startup. All master ids must be fixed by the
+ * regStats() phase that immediately preceeds it. This allows objects in the
+ * memory system to understand how many masters may exist and
+ * appropriately name the bins of their per-master stats before the stats
+ * are finalized
+ */
+ MasterID getMasterId(std::string req_name);
+
+ /** Get the name of an object for a given request id.
+ */
+ std::string getMasterName(MasterID master_id);
+
+ /** Get the number of masters registered in the system */
+ MasterID maxMasters()
+ {
+ return masterIds.size();
+ }
+
virtual void regStats();
/**
* Called by pseudo_inst to track the number of work items started by this