mem: Rename Bus to XBar to better reflect its behaviour

This patch changes the name of the Bus classes to XBar to better
reflect the actual timing behaviour. The actual instances in the
config scripts are not renamed, and remain as e.g. iobus or membus.

As part of this renaming, the code has also been clean up slightly,
making use of range-based for loops and tidying up some comments. The
only changes outside the bus/crossbar code is due to the delay
variables in the packet.

--HG--
rename : src/mem/Bus.py => src/mem/XBar.py
rename : src/mem/coherent_bus.cc => src/mem/coherent_xbar.cc
rename : src/mem/coherent_bus.hh => src/mem/coherent_xbar.hh
rename : src/mem/noncoherent_bus.cc => src/mem/noncoherent_xbar.cc
rename : src/mem/noncoherent_bus.hh => src/mem/noncoherent_xbar.hh
rename : src/mem/bus.cc => src/mem/xbar.cc
rename : src/mem/bus.hh => src/mem/xbar.hh
This commit is contained in:
Andreas Hansson 2014-09-20 17:18:32 -04:00
parent 1884bcc03b
commit 1f6d5f8f84
40 changed files with 645 additions and 692 deletions

View file

@ -71,7 +71,7 @@ def config_cache(options, system):
size=options.l2_size,
assoc=options.l2_assoc)
system.tol2bus = CoherentBus(clk_domain = system.cpu_clk_domain,
system.tol2bus = CoherentXBar(clk_domain = system.cpu_clk_domain,
width = 32)
system.l2.cpu_side = system.tol2bus.master
system.l2.mem_side = system.membus.slave

View file

@ -50,7 +50,7 @@ class CowIdeDisk(IdeDisk):
def childImage(self, ci):
self.image.child.image_file = ci
class MemBus(CoherentBus):
class MemBus(CoherentXBar):
badaddr_responder = BadAddr()
default = Self.badaddr_responder.pio
@ -71,7 +71,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None, ruby = False):
self.tsunami = BaseTsunami()
# Create the io bus to connect all device ports
self.iobus = NoncoherentBus()
self.iobus = NoncoherentXBar()
self.tsunami.attachIO(self.iobus)
self.tsunami.ide.pio = self.iobus.master
@ -134,7 +134,7 @@ def makeSparcSystem(mem_mode, mdesc = None):
# generic system
mdesc = SysConfig()
self.readfile = mdesc.script()
self.iobus = NoncoherentBus()
self.iobus = NoncoherentXBar()
self.membus = MemBus()
self.bridge = Bridge(delay='50ns')
self.t1000 = T1000()
@ -196,7 +196,7 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None,
mdesc = SysConfig()
self.readfile = mdesc.script()
self.iobus = NoncoherentBus()
self.iobus = NoncoherentXBar()
self.membus = MemBus()
self.membus.badaddr_responder.warn_access = "warn"
self.bridge = Bridge(delay='50ns')
@ -299,7 +299,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None):
# generic system
mdesc = SysConfig()
self.readfile = mdesc.script()
self.iobus = NoncoherentBus()
self.iobus = NoncoherentXBar()
self.membus = MemBus()
self.bridge = Bridge(delay='50ns')
self.mem_ranges = [AddrRange('1GB')]
@ -344,7 +344,7 @@ def connectX86ClassicSystem(x86_sys, numCPUs):
x86_sys.membus = MemBus()
# North Bridge
x86_sys.iobus = NoncoherentBus()
x86_sys.iobus = NoncoherentXBar()
x86_sys.bridge = Bridge(delay='50ns')
x86_sys.bridge.master = x86_sys.iobus.slave
x86_sys.bridge.slave = x86_sys.membus.master
@ -379,7 +379,7 @@ def connectX86ClassicSystem(x86_sys, numCPUs):
def connectX86RubySystem(x86_sys):
# North Bridge
x86_sys.iobus = NoncoherentBus()
x86_sys.iobus = NoncoherentXBar()
# add the ide to the list of dma devices that later need to attach to
# dma controllers

View file

@ -82,9 +82,9 @@ if args:
# and address mapping
# start with the system itself, using a multi-layer 1.5 GHz
# bus/crossbar, delivering 64 bytes / 5 cycles (one header cycle)
# crossbar, delivering 64 bytes / 5 cycles (one header cycle)
# which amounts to 19.2 GByte/s per layer and thus per port
system = System(membus = NoncoherentBus(width = 16))
system = System(membus = NoncoherentXBar(width = 16))
system.clk_domain = SrcClockDomain(clock = '1.5GHz',
voltage_domain =
VoltageDomain(voltage = '1V'))

View file

@ -147,7 +147,7 @@ for scale in treespec[:-2]:
# system simulated
system = System(funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
funcbus = NoncoherentXBar(),
physmem = SimpleMemory(latency = "100ns"),
cache_line_size = block_size)
@ -162,7 +162,7 @@ def make_level(spec, prototypes, attach_obj, attach_port):
parent = attach_obj # use attach obj as config parent too
if len(spec) > 1 and (fanout > 1 or options.force_bus):
port = getattr(attach_obj, attach_port)
new_bus = CoherentBus(width=16)
new_bus = CoherentXBar(width=16)
if (port.role == 'MASTER'):
new_bus.slave = port
attach_port = "master"

View file

@ -106,7 +106,7 @@ cpus = [ MemTest(atomic = False,
system = System(cpu = cpus,
funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
funcbus = NoncoherentXBar(),
physmem = SimpleMemory(),
clk_domain = SrcClockDomain(clock = options.sys_clock),
mem_ranges = [AddrRange(options.mem_size)])

View file

@ -255,7 +255,7 @@ if options.ruby:
system.cpu[i].dtb.walker.port = ruby_port.slave
else:
MemClass = Simulation.setMemClass(options)
system.membus = CoherentBus()
system.membus = CoherentXBar()
system.system_port = system.membus.slave
CacheConfig.config_cache(options, system)
MemConfig.config_mem(options, system)

View file

@ -171,7 +171,7 @@ if options.timing:
for j in xrange(options.numclusters):
clusters[j].id = j
for cluster in clusters:
cluster.clusterbus = CoherentBus(clock=busFrequency)
cluster.clusterbus = CoherentXBar(clock=busFrequency)
all_l1buses += [cluster.clusterbus]
cluster.cpus = [TimingSimpleCPU(cpu_id = i + cluster.id,
clock=options.frequency)
@ -184,7 +184,7 @@ elif options.detailed:
for j in xrange(options.numclusters):
clusters[j].id = j
for cluster in clusters:
cluster.clusterbus = CoherentBus(clock=busFrequency)
cluster.clusterbus = CoherentXBar(clock=busFrequency)
all_l1buses += [cluster.clusterbus]
cluster.cpus = [DerivO3CPU(cpu_id = i + cluster.id,
clock=options.frequency)
@ -197,7 +197,7 @@ else:
for j in xrange(options.numclusters):
clusters[j].id = j
for cluster in clusters:
cluster.clusterbus = CoherentBus(clock=busFrequency)
cluster.clusterbus = CoherentXBar(clock=busFrequency)
all_l1buses += [cluster.clusterbus]
cluster.cpus = [AtomicSimpleCPU(cpu_id = i + cluster.id,
clock=options.frequency)
@ -211,10 +211,10 @@ else:
# ----------------------
system = System(cpu = all_cpus, l1_ = all_l1s, l1bus_ = all_l1buses,
physmem = SimpleMemory(),
membus = CoherentBus(clock = busFrequency))
membus = CoherentXBar(clock = busFrequency))
system.clock = '1GHz'
system.toL2bus = CoherentBus(clock = busFrequency)
system.toL2bus = CoherentXBar(clock = busFrequency)
system.l2 = L2(size = options.l2size, assoc = 8)
# ----------------------

View file

@ -196,10 +196,10 @@ else:
# Create a system, and add system wide objects
# ----------------------
system = System(cpu = cpus, physmem = SimpleMemory(),
membus = CoherentBus(clock = busFrequency))
membus = CoherentXBar(clock = busFrequency))
system.clock = '1GHz'
system.toL2bus = CoherentBus(clock = busFrequency)
system.toL2bus = CoherentXBar(clock = busFrequency)
system.l2 = L2(size = options.l2size, assoc = 8)
# ----------------------

View file

@ -597,7 +597,7 @@ Walker::WalkerState::recvPacket(PacketPtr pkt)
assert(!read);
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
state = nextState;
nextState = Ready;

View file

@ -47,7 +47,7 @@ from m5.defines import buildEnv
from m5.params import *
from m5.proxy import *
from Bus import CoherentBus
from XBar import CoherentXBar
from InstTracer import InstTracer
from ExeTracer import ExeTracer
from MemObject import MemObject
@ -274,8 +274,8 @@ class BaseCPU(MemObject):
self.itb_walker_cache = iwc
self.dtb_walker_cache = dwc
if buildEnv['TARGET_ISA'] in ['arm']:
self.itb_walker_cache_bus = CoherentBus()
self.dtb_walker_cache_bus = CoherentBus()
self.itb_walker_cache_bus = CoherentXBar()
self.dtb_walker_cache_bus = CoherentXBar()
self.itb_walker_cache_bus.master = iwc.cpu_side
self.dtb_walker_cache_bus.master = dwc.cpu_side
self.itb.walker.port = self.itb_walker_cache_bus.slave
@ -308,7 +308,7 @@ class BaseCPU(MemObject):
# Set a width of 32 bytes (256-bits), which is four times that
# of the default bus. The clock of the CPU is inherited by
# default.
self.toL2Bus = CoherentBus(width = 32)
self.toL2Bus = CoherentXBar(width = 32)
self.connectCachedPorts(self.toL2Bus)
self.l2cache = l2c
self.toL2Bus.master = self.l2cache.cpu_side

View file

@ -42,7 +42,7 @@
*/
#include "base/trace.hh"
#include "debug/BusAddrRanges.hh"
#include "debug/AddrRanges.hh"
#include "dev/io_device.hh"
#include "sim/system.hh"
@ -55,7 +55,7 @@ Tick
PioPort::recvAtomic(PacketPtr pkt)
{
// @todo: We need to pay for this and not just zero it out
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
return pkt->isRead() ? device->read(pkt) : device->write(pkt);
}
@ -113,7 +113,7 @@ BasicPioDevice::getAddrRanges() const
{
assert(pioSize != 0);
AddrRangeList ranges;
DPRINTF(BusAddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
DPRINTF(AddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
ranges.push_back(RangeSize(pioAddr, pioSize));
return ranges;
}

View file

@ -80,7 +80,7 @@ PciDevice::PciConfigPort::recvAtomic(PacketPtr pkt)
assert(pkt->getAddr() >= configAddr &&
pkt->getAddr() < configAddr + PCI_CONFIG_SIZE);
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
return pkt->isRead() ? device->readConfig(pkt) : device->writeConfig(pkt);
}

View file

@ -82,7 +82,7 @@ class IntDevice
Tick recvMessage(PacketPtr pkt)
{
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
return device->recvMessage(pkt);
}
};

View file

@ -39,28 +39,28 @@ if env['HAVE_PROTOBUF']:
SimObject('AbstractMemory.py')
SimObject('AddrMapper.py')
SimObject('Bridge.py')
SimObject('Bus.py')
SimObject('DRAMCtrl.py')
SimObject('MemObject.py')
SimObject('SimpleMemory.py')
SimObject('XBar.py')
Source('abstract_mem.cc')
Source('addr_mapper.cc')
Source('bridge.cc')
Source('bus.cc')
Source('coherent_bus.cc')
Source('coherent_xbar.cc')
Source('dram_ctrl.cc')
Source('mem_object.cc')
Source('mport.cc')
Source('noncoherent_bus.cc')
Source('noncoherent_xbar.cc')
Source('packet.cc')
Source('port.cc')
Source('packet_queue.cc')
Source('tport.cc')
Source('port_proxy.cc')
Source('simple_mem.cc')
Source('physical.cc')
Source('simple_mem.cc')
Source('snoop_filter.cc')
Source('tport.cc')
Source('xbar.cc')
if env['TARGET_ISA'] != 'null':
Source('fs_translating_port_proxy.cc')
@ -74,13 +74,13 @@ if env['HAVE_DRAMSIM']:
Source('dramsim2_wrapper.cc')
Source('dramsim2.cc')
DebugFlag('BaseBus')
DebugFlag('BusAddrRanges')
DebugFlag('CoherentBus')
DebugFlag('NoncoherentBus')
DebugFlag('AddrRanges')
DebugFlag('BaseXBar')
DebugFlag('CoherentXBar')
DebugFlag('NoncoherentXBar')
DebugFlag('SnoopFilter')
CompoundFlag('Bus', ['BaseBus', 'BusAddrRanges', 'CoherentBus',
'NoncoherentBus', 'SnoopFilter'])
CompoundFlag('XBar', ['BaseXBar', 'CoherentXBar', 'NoncoherentXBar',
'SnoopFilter'])
DebugFlag('Bridge')
DebugFlag('CommMonitor')

View file

@ -45,14 +45,14 @@ from m5.params import *
from m5.proxy import *
from m5.SimObject import SimObject
class BaseBus(MemObject):
type = 'BaseBus'
class BaseXBar(MemObject):
type = 'BaseXBar'
abstract = True
cxx_header = "mem/bus.hh"
cxx_header = "mem/xbar.hh"
slave = VectorSlavePort("vector port for connecting masters")
master = VectorMasterPort("vector port for connecting slaves")
header_cycles = Param.Cycles(1, "cycles of overhead per transaction")
width = Param.Unsigned(8, "bus width (bytes)")
width = Param.Unsigned(8, "xbar width (bytes)")
# The default port can be left unconnected, or be used to connect
# a default slave port
@ -62,24 +62,24 @@ class BaseBus(MemObject):
# address range, in which case it may overlap with other
# ports. The default range is always checked first, thus creating
# a two-level hierarchical lookup. This is useful e.g. for the PCI
# bus configuration.
# xbar configuration.
use_default_range = Param.Bool(False, "Perform address mapping for " \
"the default port")
class NoncoherentBus(BaseBus):
type = 'NoncoherentBus'
cxx_header = "mem/noncoherent_bus.hh"
class NoncoherentXBar(BaseXBar):
type = 'NoncoherentXBar'
cxx_header = "mem/noncoherent_xbar.hh"
class CoherentBus(BaseBus):
type = 'CoherentBus'
cxx_header = "mem/coherent_bus.hh"
class CoherentXBar(BaseXBar):
type = 'CoherentXBar'
cxx_header = "mem/coherent_xbar.hh"
system = Param.System(Parent.any, "System that the bus belongs to.")
snoop_filter = Param.SnoopFilter(NULL, "Selected snoop filter for the bus.")
system = Param.System(Parent.any, "System that the crossbar belongs to.")
snoop_filter = Param.SnoopFilter(NULL, "Selected snoop filter.")
class SnoopFilter(SimObject):
type = 'SnoopFilter'
cxx_header = "mem/snoop_filter.hh"
lookup_latency = Param.Cycles(3, "lookup latency (cycles)")
system = Param.System(Parent.any, "System that the bus belongs to.")
system = Param.System(Parent.any, "System that the crossbar belongs to.")

View file

@ -44,7 +44,7 @@
/**
* @file
* Implementation of a memory-mapped bus bridge that connects a master
* Implementation of a memory-mapped bridge that connects a master
* and a slave through a request and response queue.
*/
@ -108,7 +108,7 @@ Bridge::init()
{
// make sure both sides are connected and have the same block size
if (!slavePort.isConnected() || !masterPort.isConnected())
fatal("Both ports of bus bridge are not connected to a bus.\n");
fatal("Both ports of a bridge must be connected.\n");
// notify the master side of our address ranges
slavePort.sendRangeChange();
@ -137,7 +137,7 @@ Bridge::BridgeMasterPort::recvTimingResp(PacketPtr pkt)
DPRINTF(Bridge, "Request queue size: %d\n", transmitList.size());
// @todo: We need to pay for this and not just zero it out
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
slavePort.schedTimingResp(pkt, bridge.clockEdge(delay));
@ -181,7 +181,7 @@ Bridge::BridgeSlavePort::recvTimingReq(PacketPtr pkt)
if (!retryReq) {
// @todo: We need to pay for this and not just zero it out
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
masterPort.schedTimingReq(pkt, bridge.clockEdge(delay));
}
@ -209,7 +209,7 @@ Bridge::BridgeMasterPort::schedTimingReq(PacketPtr pkt, Tick when)
{
// If we expect to see a response, we need to restore the source
// and destination field that is potentially changed by a second
// bus
// crossbar
if (!pkt->memInhibitAsserted() && pkt->needsResponse()) {
// Update the sender state so we can deal with the response
// appropriately
@ -242,7 +242,7 @@ Bridge::BridgeSlavePort::schedTimingResp(PacketPtr pkt, Tick when)
pkt->setDest(req_state->origSrc);
delete req_state;
// the bridge assumes that at least one bus has set the
// the bridge assumes that at least one crossbar has set the
// destination field of the packet
assert(pkt->isDestValid());
DPRINTF(Bridge, "response, new dest %d\n", pkt->getDest());

View file

@ -44,7 +44,7 @@
/**
* @file
* Declaration of a memory-mapped bus bridge that connects a master
* Declaration of a memory-mapped bridge that connects a master
* and a slave through a request and response queue.
*/
@ -58,7 +58,7 @@
#include "params/Bridge.hh"
/**
* A bridge is used to interface two different busses (or in general a
* A bridge is used to interface two different crossbars (or in general a
* memory-mapped master and slave), with buffering for requests and
* responses. The bridge has a fixed delay for packets passing through
* it and responds to a fixed set of address ranges.
@ -125,8 +125,7 @@ class Bridge : public MemObject
Bridge& bridge;
/**
* Master port on the other side of the bridge (connected to
* the other bus).
* Master port on the other side of the bridge.
*/
BridgeMasterPort& masterPort;
@ -241,8 +240,7 @@ class Bridge : public MemObject
Bridge& bridge;
/**
* The slave port on the other side of the bridge (connected
* to the other bus).
* The slave port on the other side of the bridge.
*/
BridgeSlavePort& slavePort;
@ -343,4 +341,4 @@ class Bridge : public MemObject
Bridge(Params *p);
};
#endif //__MEM_BUS_HH__
#endif //__MEM_BRIDGE_HH__

View file

@ -423,7 +423,7 @@ Cache<TagStore>::recvTimingSnoopResp(PacketPtr pkt)
pkt->setDest(rec->prevSrc);
delete rec;
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
memSidePort->schedTimingSnoopResp(pkt, time);
}
@ -482,7 +482,7 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
Packet *snoopPkt = new Packet(pkt, true); // clear flags
// also reset the bus time that the original packet has
// not yet paid for
snoopPkt->busFirstWordDelay = snoopPkt->busLastWordDelay = 0;
snoopPkt->firstWordDelay = snoopPkt->lastWordDelay = 0;
snoopPkt->setExpressSnoop();
snoopPkt->assertMemInhibit();
bool M5_VAR_USED success = memSidePort->sendTimingReq(snoopPkt);
@ -505,7 +505,7 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
uncacheableFlush(pkt);
// @todo: someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
// writes go in write buffer, reads use MSHR,
// prefetches are acknowledged (responded to) and dropped
@ -562,7 +562,7 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
if (needsResponse) {
pkt->makeTimingResponse();
// @todo: Make someone pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
cpuSidePort->schedTimingResp(pkt, clockEdge(lat));
} else {
/// @todo nominally we should just delete the packet here,
@ -574,7 +574,7 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
// miss
// @todo: Make someone pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
if (blk && blk->isValid() && (blk->status & BlkCanGoExclusive) &&
pkt->isWrite() && (pkt->cmd != MemCmd::WriteInvalidateReq)) {
@ -1115,8 +1115,8 @@ Cache<TagStore>::recvTimingResp(PacketPtr pkt)
// from lower level caches/memory to an upper level cache or
// the core.
completion_time = clockEdge(responseLatency) +
(transfer_offset ? pkt->busLastWordDelay :
pkt->busFirstWordDelay);
(transfer_offset ? pkt->lastWordDelay :
pkt->firstWordDelay);
assert(!target->pkt->req->isUncacheable());
@ -1132,7 +1132,7 @@ Cache<TagStore>::recvTimingResp(PacketPtr pkt)
// from lower level caches/memory to an upper level cache or
// the core.
completion_time = clockEdge(responseLatency) +
pkt->busLastWordDelay;
pkt->lastWordDelay;
target->pkt->req->setExtraData(0);
} else if (pkt->cmd == MemCmd::WriteInvalidateResp) {
if (blk) {
@ -1165,13 +1165,13 @@ Cache<TagStore>::recvTimingResp(PacketPtr pkt)
// will occur for its impatience (since it will think it
// has dirty data), but it really can't be helped.
completion_time = clockEdge(responseLatency) +
pkt->busLastWordDelay;
pkt->lastWordDelay;
} else {
// not a cache fill, just forwarding response
// responseLatency is the latency of the return path
// from lower level cahces/memory to the core.
completion_time = clockEdge(responseLatency) +
pkt->busLastWordDelay;
pkt->lastWordDelay;
if (pkt->isRead() && !is_error) {
target->pkt->setData(pkt->getPtr<uint8_t>());
}
@ -1191,7 +1191,7 @@ Cache<TagStore>::recvTimingResp(PacketPtr pkt)
target->pkt->getAddr());
}
// reset the bus additional time as it is now accounted for
target->pkt->busFirstWordDelay = target->pkt->busLastWordDelay = 0;
target->pkt->firstWordDelay = target->pkt->lastWordDelay = 0;
cpuSidePort->schedTimingResp(target->pkt, completion_time);
break;
@ -1239,7 +1239,7 @@ Cache<TagStore>::recvTimingResp(PacketPtr pkt)
mq = mshr->queue;
mq->markPending(mshr);
requestMemSideBus((RequestCause)mq->index, clockEdge() +
pkt->busLastWordDelay);
pkt->lastWordDelay);
} else {
mq->deallocate(mshr);
if (wasFull && !mq->isFull()) {
@ -1495,7 +1495,7 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
}
blk->whenReady = clockEdge() + responseLatency * clockPeriod() +
pkt->busLastWordDelay;
pkt->lastWordDelay;
return blk;
}
@ -1522,7 +1522,7 @@ doTimingSupplyResponse(PacketPtr req_pkt, uint8_t *blk_data,
pkt->allocate();
pkt->makeTimingResponse();
// @todo Make someone pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
if (pkt->isRead()) {
pkt->setDataFromBlock(blk_data, blkSize);
}
@ -1572,7 +1572,7 @@ Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk,
snoopPkt.pushSenderState(new ForwardResponseRecord(pkt->getSrc()));
// the snoop packet does not need to wait any additional
// time
snoopPkt.busFirstWordDelay = snoopPkt.busLastWordDelay = 0;
snoopPkt.firstWordDelay = snoopPkt.lastWordDelay = 0;
cpuSidePort->sendTimingSnoopReq(&snoopPkt);
if (snoopPkt.memInhibitAsserted()) {
// cache-to-cache response from some upper cache

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2013 ARM Limited
* Copyright (c) 2011-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -44,25 +44,25 @@
/**
* @file
* Definition of a bus object.
* Definition of a crossbar object.
*/
#include "base/misc.hh"
#include "base/trace.hh"
#include "debug/BusAddrRanges.hh"
#include "debug/CoherentBus.hh"
#include "mem/coherent_bus.hh"
#include "debug/AddrRanges.hh"
#include "debug/CoherentXBar.hh"
#include "mem/coherent_xbar.hh"
#include "sim/system.hh"
CoherentBus::CoherentBus(const CoherentBusParams *p)
: BaseBus(p), system(p->system), snoopFilter(p->snoop_filter)
CoherentXBar::CoherentXBar(const CoherentXBarParams *p)
: BaseXBar(p), system(p->system), snoopFilter(p->snoop_filter)
{
// create the ports based on the size of the master and slave
// vector ports, and the presence of the default port, the ports
// are enumerated starting from zero
for (int i = 0; i < p->port_master_connection_count; ++i) {
std::string portName = csprintf("%s.master[%d]", name(), i);
MasterPort* bp = new CoherentBusMasterPort(portName, *this, i);
MasterPort* bp = new CoherentXBarMasterPort(portName, *this, i);
masterPorts.push_back(bp);
reqLayers.push_back(new ReqLayer(*bp, *this,
csprintf(".reqLayer%d", i)));
@ -75,7 +75,7 @@ CoherentBus::CoherentBus(const CoherentBusParams *p)
if (p->port_default_connection_count) {
defaultPortID = masterPorts.size();
std::string portName = name() + ".default";
MasterPort* bp = new CoherentBusMasterPort(portName, *this,
MasterPort* bp = new CoherentXBarMasterPort(portName, *this,
defaultPortID);
masterPorts.push_back(bp);
reqLayers.push_back(new ReqLayer(*bp, *this, csprintf(".reqLayer%d",
@ -88,7 +88,7 @@ CoherentBus::CoherentBus(const CoherentBusParams *p)
// create the slave ports, once again starting at zero
for (int i = 0; i < p->port_slave_connection_count; ++i) {
std::string portName = csprintf("%s.slave[%d]", name(), i);
SlavePort* bp = new CoherentBusSlavePort(portName, *this, i);
SlavePort* bp = new CoherentXBarSlavePort(portName, *this, i);
slavePorts.push_back(bp);
respLayers.push_back(new RespLayer(*bp, *this,
csprintf(".respLayer%d", i)));
@ -101,42 +101,41 @@ CoherentBus::CoherentBus(const CoherentBusParams *p)
clearPortCache();
}
CoherentBus::~CoherentBus()
CoherentXBar::~CoherentXBar()
{
for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
delete *l;
for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
delete *l;
for (auto l = snoopLayers.begin(); l != snoopLayers.end(); ++l)
delete *l;
for (auto p = snoopRespPorts.begin(); p != snoopRespPorts.end(); ++p)
delete *p;
for (auto l: reqLayers)
delete l;
for (auto l: respLayers)
delete l;
for (auto l: snoopLayers)
delete l;
for (auto p: snoopRespPorts)
delete p;
}
void
CoherentBus::init()
CoherentXBar::init()
{
// the base class is responsible for determining the block size
BaseBus::init();
BaseXBar::init();
// iterate over our slave ports and determine which of our
// neighbouring master ports are snooping and add them as snoopers
for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end();
++p) {
for (const auto& p: slavePorts) {
// check if the connected master port is snooping
if ((*p)->isSnooping()) {
DPRINTF(BusAddrRanges, "Adding snooping master %s\n",
(*p)->getMasterPort().name());
snoopPorts.push_back(*p);
if (p->isSnooping()) {
DPRINTF(AddrRanges, "Adding snooping master %s\n",
p->getMasterPort().name());
snoopPorts.push_back(p);
}
}
if (snoopPorts.empty())
warn("CoherentBus %s has no snooping ports attached!\n", name());
warn("CoherentXBar %s has no snooping ports attached!\n", name());
}
bool
CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
CoherentXBar::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
{
// determine the source port based on the id
SlavePort *src_port = slavePorts[slave_port_id];
@ -147,15 +146,15 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
// determine the destination based on the address
PortID master_port_id = findPort(pkt->getAddr());
// test if the bus should be considered occupied for the current
// test if the crossbar should be considered occupied for the current
// port, and exclude express snoops from the check
if (!is_express_snoop && !reqLayers[master_port_id]->tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x BUS BUSY\n",
DPRINTF(CoherentXBar, "recvTimingReq: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
}
DPRINTF(CoherentBus, "recvTimingReq: src %s %s expr %d 0x%x\n",
DPRINTF(CoherentXBar, "recvTimingReq: src %s %s expr %d 0x%x\n",
src_port->name(), pkt->cmdString(), is_express_snoop,
pkt->getAddr());
@ -168,7 +167,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
pkt->setSrc(slave_port_id);
calcPacketTiming(pkt);
Tick packetFinishTime = pkt->busLastWordDelay + curTick();
Tick packetFinishTime = pkt->lastWordDelay + curTick();
// uncacheable requests need never be snooped
if (!pkt->req->isUncacheable() && !system->bypassCaches()) {
@ -178,7 +177,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
// check with the snoop filter where to forward this packet
auto sf_res = snoopFilter->lookupRequest(pkt, *src_port);
packetFinishTime += sf_res.second * clockPeriod();
DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x"\
DPRINTF(CoherentXBar, "recvTimingReq: src %s %s 0x%x"\
" SF size: %i lat: %i\n", src_port->name(),
pkt->cmdString(), pkt->getAddr(), sf_res.first.size(),
sf_res.second);
@ -228,8 +227,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
// if this is an express snoop, we are done at this point
if (is_express_snoop) {
assert(success);
snoopDataThroughBus += pkt_size;
snoopsThroughBus++;
snoops++;
} else {
// for normal requests, check if successful
if (!success) {
@ -242,25 +240,24 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
outstandingReq.erase(pkt->req);
// undo the calculation so we can check for 0 again
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n",
DPRINTF(CoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
// update the bus state and schedule an idle event
// update the layer state and schedule an idle event
reqLayers[master_port_id]->failedTiming(src_port,
clockEdge(headerCycles));
} else {
// update the bus state and schedule an idle event
// update the layer state and schedule an idle event
reqLayers[master_port_id]->succeededTiming(packetFinishTime);
dataThroughBus += pkt_size;
}
}
// stats updates only consider packets that were successfully sent
if (success) {
pktCount[slave_port_id][master_port_id]++;
totPktSize[slave_port_id][master_port_id] += pkt_size;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
}
@ -268,7 +265,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
}
bool
CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
CoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id)
{
// determine the source port based on the id
MasterPort *src_port = masterPorts[master_port_id];
@ -276,15 +273,15 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
// determine the destination based on what is stored in the packet
PortID slave_port_id = pkt->getDest();
// test if the bus should be considered occupied for the current
// port
// test if the crossbar should be considered occupied for the
// current port
if (!respLayers[slave_port_id]->tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n",
DPRINTF(CoherentXBar, "recvTimingResp: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
}
DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x\n",
DPRINTF(CoherentXBar, "recvTimingResp: src %s %s 0x%x\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
// store size and command as they might be modified when
@ -293,10 +290,10 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
unsigned int pkt_cmd = pkt->cmdToIndex();
calcPacketTiming(pkt);
Tick packetFinishTime = pkt->busLastWordDelay + curTick();
Tick packetFinishTime = pkt->lastWordDelay + curTick();
// the packet is a normal response to a request that we should
// have seen passing through the bus
// have seen passing through the crossbar
assert(outstandingReq.find(pkt->req) != outstandingReq.end());
if (snoopFilter && !pkt->req->isUncacheable() && !system->bypassCaches()) {
@ -317,25 +314,23 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
respLayers[slave_port_id]->succeededTiming(packetFinishTime);
// stats updates
dataThroughBus += pkt_size;
pktCount[slave_port_id][master_port_id]++;
totPktSize[slave_port_id][master_port_id] += pkt_size;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
return true;
}
void
CoherentBus::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
CoherentXBar::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
{
DPRINTF(CoherentBus, "recvTimingSnoopReq: src %s %s 0x%x\n",
DPRINTF(CoherentXBar, "recvTimingSnoopReq: src %s %s 0x%x\n",
masterPorts[master_port_id]->name(), pkt->cmdString(),
pkt->getAddr());
// update stats here as we know the forwarding will succeed
transDist[pkt->cmdToIndex()]++;
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
snoopsThroughBus++;
snoops++;
// we should only see express snoops from caches
assert(pkt->isExpressSnoop());
@ -347,7 +342,7 @@ CoherentBus::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
// let the Snoop Filter work its magic and guide probing
auto sf_res = snoopFilter->lookupSnoop(pkt);
// No timing here: packetFinishTime += sf_res.second * clockPeriod();
DPRINTF(CoherentBus, "recvTimingSnoopReq: src %s %s 0x%x"\
DPRINTF(CoherentXBar, "recvTimingSnoopReq: src %s %s 0x%x"\
" SF size: %i lat: %i\n", masterPorts[master_port_id]->name(),
pkt->cmdString(), pkt->getAddr(), sf_res.first.size(),
sf_res.second);
@ -367,7 +362,7 @@ CoherentBus::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
}
bool
CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
CoherentXBar::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
{
// determine the source port based on the id
SlavePort* src_port = slavePorts[slave_port_id];
@ -382,13 +377,13 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
bool forwardAsSnoop = outstandingReq.find(pkt->req) ==
outstandingReq.end();
// test if the bus should be considered occupied for the current
// port, note that the check is bypassed if the response is being
// passed on as a normal response since this is occupying the
// response layer rather than the snoop response layer
// test if the crossbar should be considered occupied for the
// current port, note that the check is bypassed if the response
// is being passed on as a normal response since this is occupying
// the response layer rather than the snoop response layer
if (forwardAsSnoop) {
if (!snoopLayers[dest_port_id]->tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
DPRINTF(CoherentXBar, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
}
@ -396,13 +391,13 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
// get the master port that mirrors this slave port internally
MasterPort* snoop_port = snoopRespPorts[slave_port_id];
if (!respLayers[dest_port_id]->tryTiming(snoop_port)) {
DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
DPRINTF(CoherentXBar, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
snoop_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
}
}
DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x\n",
DPRINTF(CoherentXBar, "recvTimingSnoopResp: src %s %s 0x%x\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
// store size and command as they might be modified when
@ -414,7 +409,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
assert(!pkt->isExpressSnoop());
calcPacketTiming(pkt);
Tick packetFinishTime = pkt->busLastWordDelay + curTick();
Tick packetFinishTime = pkt->lastWordDelay + curTick();
// forward it either as a snoop response or a normal response
if (forwardAsSnoop) {
@ -431,22 +426,22 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
bool success M5_VAR_USED =
masterPorts[dest_port_id]->sendTimingSnoopResp(pkt);
pktCount[slave_port_id][dest_port_id]++;
totPktSize[slave_port_id][dest_port_id] += pkt_size;
pktSize[slave_port_id][dest_port_id] += pkt_size;
assert(success);
snoopLayers[dest_port_id]->succeededTiming(packetFinishTime);
} else {
// we got a snoop response on one of our slave ports,
// i.e. from a coherent master connected to the bus, and
// since we created the snoop request as part of
// recvTiming, this should now be a normal response again
// i.e. from a coherent master connected to the crossbar, and
// since we created the snoop request as part of recvTiming,
// this should now be a normal response again
outstandingReq.erase(pkt->req);
// this is a snoop response from a coherent master, with a
// destination field set on its way through the bus as
// request, hence it should never go back to where the
// snoop response came from, but instead to where the
// original request came from
// destination field set on its way through the crossbar as
// request, hence it should never go back to where the snoop
// response came from, but instead to where the original
// request came from
assert(slave_port_id != dest_port_id);
if (snoopFilter) {
@ -455,7 +450,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
*slavePorts[dest_port_id]);
}
DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x"\
DPRINTF(CoherentXBar, "recvTimingSnoopResp: src %s %s 0x%x"\
" FWD RESP\n", src_port->name(), pkt->cmdString(),
pkt->getAddr());
@ -478,18 +473,17 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
// stats updates
transDist[pkt_cmd]++;
snoopDataThroughBus += pkt_size;
snoopsThroughBus++;
snoops++;
return true;
}
void
CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
CoherentXBar::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
const std::vector<SlavePort*>& dests)
{
DPRINTF(CoherentBus, "%s for %s address %x size %d\n", __func__,
DPRINTF(CoherentXBar, "%s for %s address %x size %d\n", __func__,
pkt->cmdString(), pkt->getAddr(), pkt->getSize());
// snoops should only happen if the system isn't bypassing caches
@ -497,8 +491,7 @@ CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
unsigned fanout = 0;
for (SlavePortConstIter s = dests.begin(); s != dests.end(); ++s) {
SlavePort *p = *s;
for (const auto& p: dests) {
// we could have gotten this request from a snooping master
// (corresponding to our own slave port that is also in
// snoopPorts) and should not send it back to where it came
@ -516,7 +509,7 @@ CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
}
void
CoherentBus::recvRetry(PortID master_port_id)
CoherentXBar::recvRetry(PortID master_port_id)
{
// responses and snoop responses never block on forwarding them,
// so the retry will always be coming from a port to which we
@ -525,14 +518,14 @@ CoherentBus::recvRetry(PortID master_port_id)
}
Tick
CoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id)
CoherentXBar::recvAtomic(PacketPtr pkt, PortID slave_port_id)
{
DPRINTF(CoherentBus, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
DPRINTF(CoherentXBar, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
slavePorts[slave_port_id]->name(), pkt->getAddr(),
pkt->cmdString());
// add the request data
dataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
unsigned int pkt_cmd = pkt->cmdToIndex();
MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
Tick snoop_response_latency = 0;
@ -546,7 +539,7 @@ CoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id)
auto sf_res =
snoopFilter->lookupRequest(pkt, *slavePorts[slave_port_id]);
snoop_response_latency += sf_res.second * clockPeriod();
DPRINTF(CoherentBus, "%s: src %s %s 0x%x"\
DPRINTF(CoherentXBar, "%s: src %s %s 0x%x"\
" SF size: %i lat: %i\n", __func__,
slavePorts[slave_port_id]->name(), pkt->cmdString(),
pkt->getAddr(), sf_res.first.size(), sf_res.second);
@ -561,10 +554,15 @@ CoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id)
// even if we had a snoop response, we must continue and also
// perform the actual request at the destination
PortID dest_id = findPort(pkt->getAddr());
PortID master_port_id = findPort(pkt->getAddr());
// stats updates for the request
pktCount[slave_port_id][master_port_id]++;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
// forward the request to the appropriate destination
Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt);
Tick response_latency = masterPorts[master_port_id]->sendAtomic(pkt);
// Lower levels have replied, tell the snoop filter
if (snoopFilter && !pkt->req->isUncacheable() && !system->bypassCaches() &&
@ -581,24 +579,30 @@ CoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id)
}
// add the response data
if (pkt->isResponse())
dataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
if (pkt->isResponse()) {
pkt_size = pkt->hasData() ? pkt->getSize() : 0;
pkt_cmd = pkt->cmdToIndex();
// stats updates
pktCount[slave_port_id][master_port_id]++;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
}
// @todo: Not setting first-word time
pkt->busLastWordDelay = response_latency;
pkt->lastWordDelay = response_latency;
return response_latency;
}
Tick
CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
CoherentXBar::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
{
DPRINTF(CoherentBus, "recvAtomicSnoop: packet src %s addr 0x%x cmd %s\n",
DPRINTF(CoherentXBar, "recvAtomicSnoop: packet src %s addr 0x%x cmd %s\n",
masterPorts[master_port_id]->name(), pkt->getAddr(),
pkt->cmdString());
// add the request snoop data
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
snoopsThroughBus++;
snoops++;
// forward to all snoopers
std::pair<MemCmd, Tick> snoop_result;
@ -606,7 +610,7 @@ CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
if (snoopFilter) {
auto sf_res = snoopFilter->lookupSnoop(pkt);
snoop_response_latency += sf_res.second * clockPeriod();
DPRINTF(CoherentBus, "%s: src %s %s 0x%x SF size: %i lat: %i\n",
DPRINTF(CoherentXBar, "%s: src %s %s 0x%x SF size: %i lat: %i\n",
__func__, masterPorts[master_port_id]->name(), pkt->cmdString(),
pkt->getAddr(), sf_res.first.size(), sf_res.second);
snoop_result = forwardAtomic(pkt, InvalidPortID, master_port_id,
@ -622,17 +626,16 @@ CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
// add the response snoop data
if (pkt->isResponse()) {
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
snoopsThroughBus++;
snoops++;
}
// @todo: Not setting first-word time
pkt->busLastWordDelay = snoop_response_latency;
pkt->lastWordDelay = snoop_response_latency;
return snoop_response_latency;
}
std::pair<MemCmd, Tick>
CoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id,
CoherentXBar::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id,
PortID source_master_port_id,
const std::vector<SlavePort*>& dests)
{
@ -648,8 +651,7 @@ CoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id,
unsigned fanout = 0;
for (SlavePortConstIter s = dests.begin(); s != dests.end(); ++s) {
SlavePort *p = *s;
for (const auto& p: dests) {
// we could have gotten this request from a snooping master
// (corresponding to our own slave port that is also in
// snoopPorts) and should not send it back to where it came
@ -704,11 +706,11 @@ CoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id,
}
void
CoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id)
CoherentXBar::recvFunctional(PacketPtr pkt, PortID slave_port_id)
{
if (!pkt->isPrint()) {
// don't do DPRINTFs on PrintReq as it clutters up the output
DPRINTF(CoherentBus,
DPRINTF(CoherentXBar,
"recvFunctional: packet src %s addr 0x%x cmd %s\n",
slavePorts[slave_port_id]->name(), pkt->getAddr(),
pkt->cmdString());
@ -730,11 +732,11 @@ CoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id)
}
void
CoherentBus::recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id)
CoherentXBar::recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id)
{
if (!pkt->isPrint()) {
// don't do DPRINTFs on PrintReq as it clutters up the output
DPRINTF(CoherentBus,
DPRINTF(CoherentXBar,
"recvFunctionalSnoop: packet src %s addr 0x%x cmd %s\n",
masterPorts[master_port_id]->name(), pkt->getAddr(),
pkt->cmdString());
@ -745,13 +747,12 @@ CoherentBus::recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id)
}
void
CoherentBus::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
CoherentXBar::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
{
// snoops should only happen if the system isn't bypassing caches
assert(!system->bypassCaches());
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
SlavePort *p = *s;
for (const auto& p: snoopPorts) {
// we could have gotten this request from a snooping master
// (corresponding to our own slave port that is also in
// snoopPorts) and should not send it back to where it came
@ -768,43 +769,33 @@ CoherentBus::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
}
unsigned int
CoherentBus::drain(DrainManager *dm)
CoherentXBar::drain(DrainManager *dm)
{
// sum up the individual layers
unsigned int total = 0;
for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
total += (*l)->drain(dm);
for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
total += (*l)->drain(dm);
for (auto l = snoopLayers.begin(); l != snoopLayers.end(); ++l)
total += (*l)->drain(dm);
for (auto l: reqLayers)
total += l->drain(dm);
for (auto l: respLayers)
total += l->drain(dm);
for (auto l: snoopLayers)
total += l->drain(dm);
return total;
}
void
CoherentBus::regStats()
CoherentXBar::regStats()
{
// register the stats of the base class and our three bus layers
BaseBus::regStats();
for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
(*l)->regStats();
for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
(*l)->regStats();
for (auto l = snoopLayers.begin(); l != snoopLayers.end(); ++l)
(*l)->regStats();
// register the stats of the base class and our layers
BaseXBar::regStats();
for (auto l: reqLayers)
l->regStats();
for (auto l: respLayers)
l->regStats();
for (auto l: snoopLayers)
l->regStats();
dataThroughBus
.name(name() + ".data_through_bus")
.desc("Total data (bytes)")
;
snoopDataThroughBus
.name(name() + ".snoop_data_through_bus")
.desc("Total snoop data (bytes)")
;
snoopsThroughBus
.name(name() + ".snoops_through_bus")
snoops
.name(name() + ".snoops")
.desc("Total snoops (count)")
;
@ -813,18 +804,10 @@ CoherentBus::regStats()
.name(name() + ".snoop_fanout")
.desc("Request fanout histogram")
;
throughput
.name(name() + ".throughput")
.desc("Throughput (bytes/s)")
.precision(0)
;
throughput = (dataThroughBus + snoopDataThroughBus) / simSeconds;
}
CoherentBus *
CoherentBusParams::create()
CoherentXBar *
CoherentXBarParams::create()
{
return new CoherentBus(this);
return new CoherentXBar(this);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2013 ARM Limited
* Copyright (c) 2011-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -45,36 +45,36 @@
/**
* @file
* Declaration of a coherent bus.
* Declaration of a coherent crossbar.
*/
#ifndef __MEM_COHERENT_BUS_HH__
#define __MEM_COHERENT_BUS_HH__
#ifndef __MEM_COHERENT_XBAR_HH__
#define __MEM_COHERENT_XBAR_HH__
#include "base/hashmap.hh"
#include "mem/bus.hh"
#include "mem/snoop_filter.hh"
#include "params/CoherentBus.hh"
#include "mem/xbar.hh"
#include "params/CoherentXBar.hh"
/**
* A coherent bus connects a number of (potentially) snooping masters
* and slaves, and routes the request and response packets based on
* the address, and also forwards all requests to the snoopers and
* deals with the snoop responses.
* A coherent crossbar connects a number of (potentially) snooping
* masters and slaves, and routes the request and response packets
* based on the address, and also forwards all requests to the
* snoopers and deals with the snoop responses.
*
* The coherent bus can be used as a template for modelling QPI,
* HyperTransport, ACE and coherent OCP buses, and is typically used
* for the L1-to-L2 buses and as the main system interconnect.
* @sa \ref gem5MemorySystem "gem5 Memory System"
* The coherent crossbar can be used as a template for modelling QPI,
* HyperTransport, ACE and coherent OCP buses, and is typically used
* for the L1-to-L2 buses and as the main system interconnect. @sa
* \ref gem5MemorySystem "gem5 Memory System"
*/
class CoherentBus : public BaseBus
class CoherentXBar : public BaseXBar
{
protected:
/**
* Declare the layers of this bus, one vector for requests, one
* for responses, and one for snoop responses
* Declare the layers of this crossbar, one vector for requests,
* one for responses, and one for snoop responses
*/
typedef Layer<SlavePort,MasterPort> ReqLayer;
typedef Layer<MasterPort,SlavePort> RespLayer;
@ -84,88 +84,88 @@ class CoherentBus : public BaseBus
std::vector<SnoopLayer*> snoopLayers;
/**
* Declaration of the coherent bus slave port type, one will be
* instantiated for each of the master ports connecting to the
* bus.
* Declaration of the coherent crossbar slave port type, one will
* be instantiated for each of the master ports connecting to the
* crossbar.
*/
class CoherentBusSlavePort : public SlavePort
class CoherentXBarSlavePort : public SlavePort
{
private:
/** A reference to the bus to which this port belongs. */
CoherentBus &bus;
/** A reference to the crossbar to which this port belongs. */
CoherentXBar &xbar;
public:
CoherentBusSlavePort(const std::string &_name,
CoherentBus &_bus, PortID _id)
: SlavePort(_name, &_bus, _id), bus(_bus)
CoherentXBarSlavePort(const std::string &_name,
CoherentXBar &_xbar, PortID _id)
: SlavePort(_name, &_xbar, _id), xbar(_xbar)
{ }
protected:
/**
* When receiving a timing request, pass it to the bus.
* When receiving a timing request, pass it to the crossbar.
*/
virtual bool recvTimingReq(PacketPtr pkt)
{ return bus.recvTimingReq(pkt, id); }
{ return xbar.recvTimingReq(pkt, id); }
/**
* When receiving a timing snoop response, pass it to the bus.
* When receiving a timing snoop response, pass it to the crossbar.
*/
virtual bool recvTimingSnoopResp(PacketPtr pkt)
{ return bus.recvTimingSnoopResp(pkt, id); }
{ return xbar.recvTimingSnoopResp(pkt, id); }
/**
* When receiving an atomic request, pass it to the bus.
* When receiving an atomic request, pass it to the crossbar.
*/
virtual Tick recvAtomic(PacketPtr pkt)
{ return bus.recvAtomic(pkt, id); }
{ return xbar.recvAtomic(pkt, id); }
/**
* When receiving a functional request, pass it to the bus.
* When receiving a functional request, pass it to the crossbar.
*/
virtual void recvFunctional(PacketPtr pkt)
{ bus.recvFunctional(pkt, id); }
{ xbar.recvFunctional(pkt, id); }
/**
* When receiving a retry, pass it to the bus.
* When receiving a retry, pass it to the crossbar.
*/
virtual void recvRetry()
{ panic("Bus slave ports always succeed and should never retry.\n"); }
{ panic("Crossbar slave ports should never retry.\n"); }
/**
* Return the union of all adress ranges seen by this bus.
* Return the union of all adress ranges seen by this crossbar.
*/
virtual AddrRangeList getAddrRanges() const
{ return bus.getAddrRanges(); }
{ return xbar.getAddrRanges(); }
};
/**
* Declaration of the coherent bus master port type, one will be
* Declaration of the coherent crossbar master port type, one will be
* instantiated for each of the slave interfaces connecting to the
* bus.
* crossbar.
*/
class CoherentBusMasterPort : public MasterPort
class CoherentXBarMasterPort : public MasterPort
{
private:
/** A reference to the bus to which this port belongs. */
CoherentBus &bus;
/** A reference to the crossbar to which this port belongs. */
CoherentXBar &xbar;
public:
CoherentBusMasterPort(const std::string &_name,
CoherentBus &_bus, PortID _id)
: MasterPort(_name, &_bus, _id), bus(_bus)
CoherentXBarMasterPort(const std::string &_name,
CoherentXBar &_xbar, PortID _id)
: MasterPort(_name, &_xbar, _id), xbar(_xbar)
{ }
protected:
/**
* Determine if this port should be considered a snooper. For
* a coherent bus master port this is always true.
* a coherent crossbar master port this is always true.
*
* @return a boolean that is true if this port is snooping
*/
@ -173,38 +173,38 @@ class CoherentBus : public BaseBus
{ return true; }
/**
* When receiving a timing response, pass it to the bus.
* When receiving a timing response, pass it to the crossbar.
*/
virtual bool recvTimingResp(PacketPtr pkt)
{ return bus.recvTimingResp(pkt, id); }
{ return xbar.recvTimingResp(pkt, id); }
/**
* When receiving a timing snoop request, pass it to the bus.
* When receiving a timing snoop request, pass it to the crossbar.
*/
virtual void recvTimingSnoopReq(PacketPtr pkt)
{ return bus.recvTimingSnoopReq(pkt, id); }
{ return xbar.recvTimingSnoopReq(pkt, id); }
/**
* When receiving an atomic snoop request, pass it to the bus.
* When receiving an atomic snoop request, pass it to the crossbar.
*/
virtual Tick recvAtomicSnoop(PacketPtr pkt)
{ return bus.recvAtomicSnoop(pkt, id); }
{ return xbar.recvAtomicSnoop(pkt, id); }
/**
* When receiving a functional snoop request, pass it to the bus.
* When receiving a functional snoop request, pass it to the crossbar.
*/
virtual void recvFunctionalSnoop(PacketPtr pkt)
{ bus.recvFunctionalSnoop(pkt, id); }
{ xbar.recvFunctionalSnoop(pkt, id); }
/** When reciving a range change from the peer port (at id),
pass it to the bus. */
pass it to the crossbar. */
virtual void recvRangeChange()
{ bus.recvRangeChange(id); }
{ xbar.recvRangeChange(id); }
/** When reciving a retry from the peer port (at id),
pass it to the bus. */
pass it to the crossbar. */
virtual void recvRetry()
{ bus.recvRetry(id); }
{ xbar.recvRetry(id); }
};
@ -226,8 +226,8 @@ class CoherentBus : public BaseBus
/**
* Create a snoop response port that mirrors a given slave port.
*/
SnoopRespPort(SlavePort& slave_port, CoherentBus& _bus) :
MasterPort(slave_port.name() + ".snoopRespPort", &_bus),
SnoopRespPort(SlavePort& slave_port, CoherentXBar& _xbar) :
MasterPort(slave_port.name() + ".snoopRespPort", &_xbar),
slavePort(slave_port) { }
/**
@ -261,7 +261,7 @@ class CoherentBus : public BaseBus
/**
* Store the outstanding requests so we can determine which ones
* we generated and which ones were merely forwarded. This is used
* in the coherent bus when coherency responses come back.
* in the coherent crossbar when coherency responses come back.
*/
m5::hash_set<RequestPtr> outstandingReq;
@ -275,19 +275,19 @@ class CoherentBus : public BaseBus
* broadcast needed for probes. NULL denotes an absent filter. */
SnoopFilter *snoopFilter;
/** Function called by the port when the bus is recieving a Timing
/** Function called by the port when the crossbar is recieving a Timing
request packet.*/
bool recvTimingReq(PacketPtr pkt, PortID slave_port_id);
/** Function called by the port when the bus is recieving a Timing
/** Function called by the port when the crossbar is recieving a Timing
response packet.*/
bool recvTimingResp(PacketPtr pkt, PortID master_port_id);
/** Function called by the port when the bus is recieving a timing
/** Function called by the port when the crossbar is recieving a timing
snoop request.*/
void recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id);
/** Function called by the port when the bus is recieving a timing
/** Function called by the port when the crossbar is recieving a timing
snoop response.*/
bool recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id);
@ -319,11 +319,11 @@ class CoherentBus : public BaseBus
void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
const std::vector<SlavePort*>& dests);
/** Function called by the port when the bus is recieving a Atomic
/** Function called by the port when the crossbar is recieving a Atomic
transaction.*/
Tick recvAtomic(PacketPtr pkt, PortID slave_port_id);
/** Function called by the port when the bus is recieving an
/** Function called by the port when the crossbar is recieving an
atomic snoop transaction.*/
Tick recvAtomicSnoop(PacketPtr pkt, PortID master_port_id);
@ -360,11 +360,11 @@ class CoherentBus : public BaseBus
PortID source_master_port_id,
const std::vector<SlavePort*>& dests);
/** Function called by the port when the bus is recieving a Functional
/** Function called by the port when the crossbar is recieving a Functional
transaction.*/
void recvFunctional(PacketPtr pkt, PortID slave_port_id);
/** Function called by the port when the bus is recieving a functional
/** Function called by the port when the crossbar is recieving a functional
snoop transaction.*/
void recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id);
@ -378,22 +378,20 @@ class CoherentBus : public BaseBus
*/
void forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id);
Stats::Scalar dataThroughBus;
Stats::Scalar snoopDataThroughBus;
Stats::Scalar snoopsThroughBus;
Stats::Scalar snoops;
Stats::Distribution snoopFanout;
public:
virtual void init();
CoherentBus(const CoherentBusParams *p);
CoherentXBar(const CoherentXBarParams *p);
virtual ~CoherentBus();
virtual ~CoherentXBar();
unsigned int drain(DrainManager *dm);
virtual void regStats();
};
#endif //__MEM_COHERENT_BUS_HH__
#endif //__MEM_COHERENT_XBAR_HH__

View file

@ -819,7 +819,7 @@ DRAMCtrl::accessAndRespond(PacketPtr pkt, Tick static_latency)
assert(pkt->isResponse());
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
// queue the packet in the response queue to be sent out after
// the static latency has passed

View file

@ -268,7 +268,7 @@ DRAMSim2::accessAndRespond(PacketPtr pkt)
assert(pkt->isResponse());
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
DPRINTF(DRAMSim2, "Queuing response for address %lld\n",
pkt->getAddr());

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2013 ARM Limited
* Copyright (c) 2011-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -44,25 +44,24 @@
/**
* @file
* Definition of a bus object.
* Definition of a non-coherent crossbar object.
*/
#include "base/misc.hh"
#include "base/trace.hh"
#include "debug/Bus.hh"
#include "debug/BusAddrRanges.hh"
#include "debug/NoncoherentBus.hh"
#include "mem/noncoherent_bus.hh"
#include "debug/NoncoherentXBar.hh"
#include "debug/XBar.hh"
#include "mem/noncoherent_xbar.hh"
NoncoherentBus::NoncoherentBus(const NoncoherentBusParams *p)
: BaseBus(p)
NoncoherentXBar::NoncoherentXBar(const NoncoherentXBarParams *p)
: BaseXBar(p)
{
// create the ports based on the size of the master and slave
// vector ports, and the presence of the default port, the ports
// are enumerated starting from zero
for (int i = 0; i < p->port_master_connection_count; ++i) {
std::string portName = csprintf("%s.master[%d]", name(), i);
MasterPort* bp = new NoncoherentBusMasterPort(portName, *this, i);
MasterPort* bp = new NoncoherentXBarMasterPort(portName, *this, i);
masterPorts.push_back(bp);
reqLayers.push_back(new ReqLayer(*bp, *this,
csprintf(".reqLayer%d", i)));
@ -73,7 +72,7 @@ NoncoherentBus::NoncoherentBus(const NoncoherentBusParams *p)
if (p->port_default_connection_count) {
defaultPortID = masterPorts.size();
std::string portName = name() + ".default";
MasterPort* bp = new NoncoherentBusMasterPort(portName, *this,
MasterPort* bp = new NoncoherentXBarMasterPort(portName, *this,
defaultPortID);
masterPorts.push_back(bp);
reqLayers.push_back(new ReqLayer(*bp, *this, csprintf(".reqLayer%d",
@ -83,7 +82,7 @@ NoncoherentBus::NoncoherentBus(const NoncoherentBusParams *p)
// create the slave ports, once again starting at zero
for (int i = 0; i < p->port_slave_connection_count; ++i) {
std::string portName = csprintf("%s.slave[%d]", name(), i);
SlavePort* bp = new NoncoherentBusSlavePort(portName, *this, i);
SlavePort* bp = new NoncoherentXBarSlavePort(portName, *this, i);
slavePorts.push_back(bp);
respLayers.push_back(new RespLayer(*bp, *this,
csprintf(".respLayer%d", i)));
@ -92,35 +91,35 @@ NoncoherentBus::NoncoherentBus(const NoncoherentBusParams *p)
clearPortCache();
}
NoncoherentBus::~NoncoherentBus()
NoncoherentXBar::~NoncoherentXBar()
{
for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
delete *l;
for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
delete *l;
for (auto l: reqLayers)
delete l;
for (auto l: respLayers)
delete l;
}
bool
NoncoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
NoncoherentXBar::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
{
// determine the source port based on the id
SlavePort *src_port = slavePorts[slave_port_id];
// we should never see express snoops on a non-coherent bus
// we should never see express snoops on a non-coherent crossbar
assert(!pkt->isExpressSnoop());
// determine the destination based on the address
PortID master_port_id = findPort(pkt->getAddr());
// test if the bus should be considered occupied for the current
// test if the layer should be considered occupied for the current
// port
if (!reqLayers[master_port_id]->tryTiming(src_port)) {
DPRINTF(NoncoherentBus, "recvTimingReq: src %s %s 0x%x BUSY\n",
DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
}
DPRINTF(NoncoherentBus, "recvTimingReq: src %s %s 0x%x\n",
DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
// store size and command as they might be modified when
@ -132,7 +131,7 @@ NoncoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
pkt->setSrc(slave_port_id);
calcPacketTiming(pkt);
Tick packetFinishTime = pkt->busLastWordDelay + curTick();
Tick packetFinishTime = pkt->lastWordDelay + curTick();
// since it is a normal request, attempt to send the packet
bool success = masterPorts[master_port_id]->sendTimingReq(pkt);
@ -141,11 +140,11 @@ NoncoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
// inhibited packets should never be forced to retry
assert(!pkt->memInhibitAsserted());
DPRINTF(NoncoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n",
DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
// undo the calculation so we can check for 0 again
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
// occupy until the header is sent
reqLayers[master_port_id]->failedTiming(src_port,
@ -157,16 +156,15 @@ NoncoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
reqLayers[master_port_id]->succeededTiming(packetFinishTime);
// stats updates
dataThroughBus += pkt_size;
pktCount[slave_port_id][master_port_id]++;
totPktSize[slave_port_id][master_port_id] += pkt_size;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
return true;
}
bool
NoncoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
NoncoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id)
{
// determine the source port based on the id
MasterPort *src_port = masterPorts[master_port_id];
@ -174,15 +172,15 @@ NoncoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
// determine the destination based on what is stored in the packet
PortID slave_port_id = pkt->getDest();
// test if the bus should be considered occupied for the current
// test if the layer should be considered occupied for the current
// port
if (!respLayers[slave_port_id]->tryTiming(src_port)) {
DPRINTF(NoncoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n",
DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
}
DPRINTF(NoncoherentBus, "recvTimingResp: src %s %s 0x%x\n",
DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
// store size and command as they might be modified when
@ -191,7 +189,7 @@ NoncoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
unsigned int pkt_cmd = pkt->cmdToIndex();
calcPacketTiming(pkt);
Tick packetFinishTime = pkt->busLastWordDelay + curTick();
Tick packetFinishTime = pkt->lastWordDelay + curTick();
// send the packet through the destination slave port
bool success M5_VAR_USED = slavePorts[slave_port_id]->sendTimingResp(pkt);
@ -203,16 +201,15 @@ NoncoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
respLayers[slave_port_id]->succeededTiming(packetFinishTime);
// stats updates
dataThroughBus += pkt_size;
pktCount[slave_port_id][master_port_id]++;
totPktSize[slave_port_id][master_port_id] += pkt_size;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
return true;
}
void
NoncoherentBus::recvRetry(PortID master_port_id)
NoncoherentXBar::recvRetry(PortID master_port_id)
{
// responses never block on forwarding them, so the retry will
// always be coming from a port to which we tried to forward a
@ -221,36 +218,48 @@ NoncoherentBus::recvRetry(PortID master_port_id)
}
Tick
NoncoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id)
NoncoherentXBar::recvAtomic(PacketPtr pkt, PortID slave_port_id)
{
DPRINTF(NoncoherentBus, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
DPRINTF(NoncoherentXBar, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
slavePorts[slave_port_id]->name(), pkt->getAddr(),
pkt->cmdString());
// add the request data
dataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
unsigned int pkt_cmd = pkt->cmdToIndex();
// determine the destination port
PortID dest_id = findPort(pkt->getAddr());
PortID master_port_id = findPort(pkt->getAddr());
// stats updates for the request
pktCount[slave_port_id][master_port_id]++;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
// forward the request to the appropriate destination
Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt);
Tick response_latency = masterPorts[master_port_id]->sendAtomic(pkt);
// add the response data
if (pkt->isResponse())
dataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
if (pkt->isResponse()) {
pkt_size = pkt->hasData() ? pkt->getSize() : 0;
pkt_cmd = pkt->cmdToIndex();
// stats updates
pktCount[slave_port_id][master_port_id]++;
pktSize[slave_port_id][master_port_id] += pkt_size;
transDist[pkt_cmd]++;
}
// @todo: Not setting first-word time
pkt->busLastWordDelay = response_latency;
pkt->lastWordDelay = response_latency;
return response_latency;
}
void
NoncoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id)
NoncoherentXBar::recvFunctional(PacketPtr pkt, PortID slave_port_id)
{
if (!pkt->isPrint()) {
// don't do DPRINTFs on PrintReq as it clutters up the output
DPRINTF(NoncoherentBus,
DPRINTF(NoncoherentXBar,
"recvFunctional: packet src %s addr 0x%x cmd %s\n",
slavePorts[slave_port_id]->name(), pkt->getAddr(),
pkt->cmdString());
@ -264,43 +273,30 @@ NoncoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id)
}
unsigned int
NoncoherentBus::drain(DrainManager *dm)
NoncoherentXBar::drain(DrainManager *dm)
{
// sum up the individual layers
unsigned int total = 0;
for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
total += (*l)->drain(dm);
for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
total += (*l)->drain(dm);
for (auto l: reqLayers)
total += l->drain(dm);
for (auto l: respLayers)
total += l->drain(dm);
return total;
}
NoncoherentBus*
NoncoherentBusParams::create()
NoncoherentXBar*
NoncoherentXBarParams::create()
{
return new NoncoherentBus(this);
return new NoncoherentXBar(this);
}
void
NoncoherentBus::regStats()
NoncoherentXBar::regStats()
{
// register the stats of the base class and our two bus layers
BaseBus::regStats();
for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
(*l)->regStats();
for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
(*l)->regStats();
dataThroughBus
.name(name() + ".data_through_bus")
.desc("Total data (bytes)")
;
throughput
.name(name() + ".throughput")
.desc("Throughput (bytes/s)")
.precision(0)
;
throughput = dataThroughBus / simSeconds;
// register the stats of the base class and our layers
BaseXBar::regStats();
for (auto l: reqLayers)
l->regStats();
for (auto l: respLayers)
l->regStats();
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2013 ARM Limited
* Copyright (c) 2011-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -45,36 +45,36 @@
/**
* @file
* Declaration of a non-coherent bus.
* Declaration of a non-coherent crossbar.
*/
#ifndef __MEM_NONCOHERENT_BUS_HH__
#define __MEM_NONCOHERENT_BUS_HH__
#ifndef __MEM_NONCOHERENT_XBAR_HH__
#define __MEM_NONCOHERENT_XBAR_HH__
#include "mem/bus.hh"
#include "params/NoncoherentBus.hh"
#include "mem/xbar.hh"
#include "params/NoncoherentXBar.hh"
/**
* A non-coherent bus connects a number of non-snooping masters and
* slaves, and routes the request and response packets based on the
* address. The request packets issued by the master connected to a
* non-coherent bus could still snoop in caches attached to a coherent
* bus, as is the case with the I/O bus and memory bus in most system
* configurations. No snoops will, however, reach any master on the
* non-coherent bus itself.
* A non-coherent crossbar connects a number of non-snooping masters
* and slaves, and routes the request and response packets based on
* the address. The request packets issued by the master connected to
* a non-coherent crossbar could still snoop in caches attached to a
* coherent crossbar, as is the case with the I/O bus and memory bus
* in most system configurations. No snoops will, however, reach any
* master on the non-coherent crossbar itself.
*
* The non-coherent bus can be used as a template for modelling PCI,
* The non-coherent crossbar can be used as a template for modelling
* PCIe, and non-coherent AMBA and OCP buses, and is typically used
* for the I/O buses.
*/
class NoncoherentBus : public BaseBus
class NoncoherentXBar : public BaseXBar
{
protected:
/**
* Declare the layers of this bus, one vector for requests and one
* for responses.
* Declare the layers of this crossbar, one vector for requests
* and one for responses.
*/
typedef Layer<SlavePort,MasterPort> ReqLayer;
typedef Layer<MasterPort,SlavePort> RespLayer;
@ -82,102 +82,102 @@ class NoncoherentBus : public BaseBus
std::vector<RespLayer*> respLayers;
/**
* Declaration of the non-coherent bus slave port type, one will
* be instantiated for each of the master ports connecting to the
* bus.
* Declaration of the non-coherent crossbar slave port type, one
* will be instantiated for each of the master ports connecting to
* the crossbar.
*/
class NoncoherentBusSlavePort : public SlavePort
class NoncoherentXBarSlavePort : public SlavePort
{
private:
/** A reference to the bus to which this port belongs. */
NoncoherentBus &bus;
/** A reference to the crossbar to which this port belongs. */
NoncoherentXBar &xbar;
public:
NoncoherentBusSlavePort(const std::string &_name,
NoncoherentBus &_bus, PortID _id)
: SlavePort(_name, &_bus, _id), bus(_bus)
NoncoherentXBarSlavePort(const std::string &_name,
NoncoherentXBar &_xbar, PortID _id)
: SlavePort(_name, &_xbar, _id), xbar(_xbar)
{ }
protected:
/**
* When receiving a timing request, pass it to the bus.
* When receiving a timing request, pass it to the crossbar.
*/
virtual bool recvTimingReq(PacketPtr pkt)
{ return bus.recvTimingReq(pkt, id); }
{ return xbar.recvTimingReq(pkt, id); }
/**
* When receiving an atomic request, pass it to the bus.
* When receiving an atomic request, pass it to the crossbar.
*/
virtual Tick recvAtomic(PacketPtr pkt)
{ return bus.recvAtomic(pkt, id); }
{ return xbar.recvAtomic(pkt, id); }
/**
* When receiving a functional request, pass it to the bus.
* When receiving a functional request, pass it to the crossbar.
*/
virtual void recvFunctional(PacketPtr pkt)
{ bus.recvFunctional(pkt, id); }
{ xbar.recvFunctional(pkt, id); }
/**
* When receiving a retry, pass it to the bus.
* When receiving a retry, pass it to the crossbar.
*/
virtual void recvRetry()
{ panic("Bus slave ports always succeed and should never retry.\n"); }
{ panic("Crossbar slave ports should never retry.\n"); }
/**
* Return the union of all adress ranges seen by this bus.
* Return the union of all adress ranges seen by this crossbar.
*/
virtual AddrRangeList getAddrRanges() const
{ return bus.getAddrRanges(); }
{ return xbar.getAddrRanges(); }
};
/**
* Declaration of the bus master port type, one will be
* Declaration of the crossbar master port type, one will be
* instantiated for each of the slave ports connecting to the
* bus.
* crossbar.
*/
class NoncoherentBusMasterPort : public MasterPort
class NoncoherentXBarMasterPort : public MasterPort
{
private:
/** A reference to the bus to which this port belongs. */
NoncoherentBus &bus;
/** A reference to the crossbar to which this port belongs. */
NoncoherentXBar &xbar;
public:
NoncoherentBusMasterPort(const std::string &_name,
NoncoherentBus &_bus, PortID _id)
: MasterPort(_name, &_bus, _id), bus(_bus)
NoncoherentXBarMasterPort(const std::string &_name,
NoncoherentXBar &_xbar, PortID _id)
: MasterPort(_name, &_xbar, _id), xbar(_xbar)
{ }
protected:
/**
* When receiving a timing response, pass it to the bus.
* When receiving a timing response, pass it to the crossbar.
*/
virtual bool recvTimingResp(PacketPtr pkt)
{ return bus.recvTimingResp(pkt, id); }
{ return xbar.recvTimingResp(pkt, id); }
/** When reciving a range change from the peer port (at id),
pass it to the bus. */
pass it to the crossbar. */
virtual void recvRangeChange()
{ bus.recvRangeChange(id); }
{ xbar.recvRangeChange(id); }
/** When reciving a retry from the peer port (at id),
pass it to the bus. */
pass it to the crossbar. */
virtual void recvRetry()
{ bus.recvRetry(id); }
{ xbar.recvRetry(id); }
};
/** Function called by the port when the bus is recieving a Timing
/** Function called by the port when the crossbar is recieving a Timing
request packet.*/
virtual bool recvTimingReq(PacketPtr pkt, PortID slave_port_id);
/** Function called by the port when the bus is recieving a Timing
/** Function called by the port when the crossbar is recieving a Timing
response packet.*/
virtual bool recvTimingResp(PacketPtr pkt, PortID master_port_id);
@ -185,19 +185,19 @@ class NoncoherentBus : public BaseBus
* requests. */
void recvRetry(PortID master_port_id);
/** Function called by the port when the bus is recieving a Atomic
/** Function called by the port when the crossbar is recieving a Atomic
transaction.*/
Tick recvAtomic(PacketPtr pkt, PortID slave_port_id);
/** Function called by the port when the bus is recieving a Functional
/** Function called by the port when the crossbar is recieving a Functional
transaction.*/
void recvFunctional(PacketPtr pkt, PortID slave_port_id);
public:
NoncoherentBus(const NoncoherentBusParams *p);
NoncoherentXBar(const NoncoherentXBarParams *p);
virtual ~NoncoherentBus();
virtual ~NoncoherentXBar();
unsigned int drain(DrainManager *dm);
@ -205,7 +205,7 @@ class NoncoherentBus : public BaseBus
* stats
*/
virtual void regStats();
Stats::Scalar dataThroughBus;
Stats::Scalar totPktSize;
};
#endif //__MEM_NONCOHERENT_BUS_HH__
#endif //__MEM_NONCOHERENT_XBAR_HH__

View file

@ -293,14 +293,14 @@ class Packet : public Printable
/**
* Source port identifier set on a request packet to enable
* appropriate routing of the responses. The source port
* identifier is set by any multiplexing component, e.g. a bus, as
* the timing responses need this information to be routed back to
* the appropriate port at a later point in time. The field can be
* updated (over-written) as the request packet passes through
* additional multiplexing components, and it is their
* responsibility to remember the original source port identifier,
* for example by using an appropriate sender state. The latter is
* done in the cache and bridge.
* identifier is set by any multiplexing component, e.g. a
* crossbar, as the timing responses need this information to be
* routed back to the appropriate port at a later point in
* time. The field can be updated (over-written) as the request
* packet passes through additional multiplexing components, and
* it is their responsibility to remember the original source port
* identifier, for example by using an appropriate sender
* state. The latter is done in the cache and bridge.
*/
PortID src;
@ -309,7 +309,7 @@ class Packet : public Printable
* packets that passed through a multiplexing component as a
* request packet. The source port identifier is turned into a
* destination port identifier when the packet is turned into a
* response, and the destination is used, e.g. by the bus, to
* response, and the destination is used, e.g. by the crossbar, to
* select the appropriate path through the interconnect.
*/
PortID dest;
@ -333,21 +333,22 @@ class Packet : public Printable
/**
* The extra delay from seeing the packet until the first word is
* transmitted by the bus that provided it (if any). This delay is
* used to communicate the bus waiting time to the neighbouring
* object (e.g. a cache) that actually makes the packet wait. As
* the delay is relative, a 32-bit unsigned should be sufficient.
*/
uint32_t busFirstWordDelay;
/**
* The extra delay from seeing the packet until the last word is
* transmitted by the bus that provided it (if any). Similar to
* the first word time, this is used to make up for the fact that
* the bus does not make the packet wait. As the delay is relative,
* transmitted. This delay is used to communicate the crossbar
* forwarding latency to the neighbouring object (e.g. a cache)
* that actually makes the packet wait. As the delay is relative,
* a 32-bit unsigned should be sufficient.
*/
uint32_t busLastWordDelay;
uint32_t firstWordDelay;
/**
* The extra pipelining delay from seeing the packet until the
* last word is transmitted by the component that provided it (if
* any). This includes the first word delay. Similar to the first
* word delay, this is used to make up for the fact that the
* crossbar does not make the packet wait. As the delay is
* relative, a 32-bit unsigned should be sufficient.
*/
uint32_t lastWordDelay;
/**
* A virtual base opaque structure used to hold state associated
@ -541,8 +542,6 @@ class Packet : public Printable
PortID getSrc() const { assert(isSrcValid()); return src; }
/// Accessor function to set the source index of the packet.
void setSrc(PortID _src) { src = _src; }
/// Reset source field, e.g. to retransmit packet on different bus.
void clearSrc() { src = InvalidPortID; }
bool isDestValid() const { return dest != InvalidPortID; }
/// Accessor function for the destination index of the packet.
@ -604,7 +603,7 @@ class Packet : public Printable
: cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
src(InvalidPortID), dest(InvalidPortID),
bytesValidStart(0), bytesValidEnd(0),
busFirstWordDelay(0), busLastWordDelay(0),
firstWordDelay(0), lastWordDelay(0),
senderState(NULL)
{
if (req->hasPaddr()) {
@ -627,7 +626,7 @@ class Packet : public Printable
: cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
src(InvalidPortID), dest(InvalidPortID),
bytesValidStart(0), bytesValidEnd(0),
busFirstWordDelay(0), busLastWordDelay(0),
firstWordDelay(0), lastWordDelay(0),
senderState(NULL)
{
if (req->hasPaddr()) {
@ -653,8 +652,8 @@ class Packet : public Printable
src(pkt->src), dest(pkt->dest),
bytesValidStart(pkt->bytesValidStart),
bytesValidEnd(pkt->bytesValidEnd),
busFirstWordDelay(pkt->busFirstWordDelay),
busLastWordDelay(pkt->busLastWordDelay),
firstWordDelay(pkt->firstWordDelay),
lastWordDelay(pkt->lastWordDelay),
senderState(pkt->senderState)
{
if (!clearFlags)
@ -739,8 +738,8 @@ class Packet : public Printable
dest = InvalidPortID;
bytesValidStart = 0;
bytesValidEnd = 0;
busFirstWordDelay = 0;
busLastWordDelay = 0;
firstWordDelay = 0;
lastWordDelay = 0;
flags.set(VALID_ADDR|VALID_SIZE);
deleteData();
@ -766,7 +765,7 @@ class Packet : public Printable
flags.clear(EXPRESS_SNOOP);
dest = src;
clearSrc();
src = InvalidPortID;
}
void

View file

@ -51,7 +51,7 @@
#include <string>
#include "base/trace.hh"
#include "debug/BusAddrRanges.hh"
#include "debug/AddrRanges.hh"
#include "debug/Checkpoint.hh"
#include "mem/abstract_mem.hh"
#include "mem/physical.hh"
@ -79,7 +79,7 @@ PhysicalMemory::PhysicalMemory(const string& _name,
fatal("Memory address range for %s is overlapping\n",
(*m)->name());
} else {
DPRINTF(BusAddrRanges,
DPRINTF(AddrRanges,
"Skipping memory %s that is not in global address map\n",
(*m)->name());
// this type of memory is used e.g. as reference memory by
@ -144,7 +144,7 @@ PhysicalMemory::createBackingStore(AddrRange range,
range.to_string());
// perform the actual mmap
DPRINTF(BusAddrRanges, "Creating backing store for range %s with size %d\n",
DPRINTF(AddrRanges, "Creating backing store for range %s with size %d\n",
range.to_string(), range.size());
int map_flags = MAP_ANON | MAP_PRIVATE;
uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(),
@ -164,7 +164,7 @@ PhysicalMemory::createBackingStore(AddrRange range,
// point the memories to their backing store
for (vector<AbstractMemory*>::const_iterator m = _memories.begin();
m != _memories.end(); ++m) {
DPRINTF(BusAddrRanges, "Mapping memory %s to backing store\n",
DPRINTF(AddrRanges, "Mapping memory %s to backing store\n",
(*m)->name());
(*m)->setBackingStore(pmem);
}

View file

@ -122,7 +122,7 @@ SimpleMemory::recvTimingReq(PacketPtr pkt)
}
// @todo someone should pay for this
pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
pkt->firstWordDelay = pkt->lastWordDelay = 0;
// update the release time according to the bandwidth limit, and
// do so with respect to the time it takes to finish this request

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2013 ARM Limited
* Copyright (c) 2011-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -44,17 +44,17 @@
/**
* @file
* Definition of a bus object.
* Definition of a crossbar object.
*/
#include "base/misc.hh"
#include "base/trace.hh"
#include "debug/Bus.hh"
#include "debug/BusAddrRanges.hh"
#include "debug/AddrRanges.hh"
#include "debug/Drain.hh"
#include "mem/bus.hh"
#include "debug/XBar.hh"
#include "mem/xbar.hh"
BaseBus::BaseBus(const BaseBusParams *p)
BaseXBar::BaseXBar(const BaseXBarParams *p)
: MemObject(p),
headerCycles(p->header_cycles), width(p->width),
gotAddrRanges(p->port_default_connection_count +
@ -63,26 +63,22 @@ BaseBus::BaseBus(const BaseBusParams *p)
useDefaultRange(p->use_default_range)
{}
BaseBus::~BaseBus()
BaseXBar::~BaseXBar()
{
for (MasterPortIter m = masterPorts.begin(); m != masterPorts.end();
++m) {
delete *m;
}
for (auto m: masterPorts)
delete m;
for (SlavePortIter s = slavePorts.begin(); s != slavePorts.end();
++s) {
delete *s;
}
for (auto s: slavePorts)
delete s;
}
void
BaseBus::init()
BaseXBar::init()
{
}
BaseMasterPort &
BaseBus::getMasterPort(const std::string &if_name, PortID idx)
BaseXBar::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "master" && idx < masterPorts.size()) {
// the master port index translates directly to the vector position
@ -95,7 +91,7 @@ BaseBus::getMasterPort(const std::string &if_name, PortID idx)
}
BaseSlavePort &
BaseBus::getSlavePort(const std::string &if_name, PortID idx)
BaseXBar::getSlavePort(const std::string &if_name, PortID idx)
{
if (if_name == "slave" && idx < slavePorts.size()) {
// the slave port index translates directly to the vector position
@ -106,9 +102,9 @@ BaseBus::getSlavePort(const std::string &if_name, PortID idx)
}
void
BaseBus::calcPacketTiming(PacketPtr pkt)
BaseXBar::calcPacketTiming(PacketPtr pkt)
{
// the bus will be called at a time that is not necessarily
// the crossbar will be called at a time that is not necessarily
// coinciding with its own clock, so start by determining how long
// until the next clock edge (could be zero)
Tick offset = clockEdge() - curTick();
@ -117,58 +113,58 @@ BaseBus::calcPacketTiming(PacketPtr pkt)
unsigned dataCycles = pkt->hasData() ? divCeil(pkt->getSize(), width) : 0;
// before setting the bus delay fields of the packet, ensure that
// the delay from any previous bus has been accounted for
if (pkt->busFirstWordDelay != 0 || pkt->busLastWordDelay != 0)
panic("Packet %s already has bus delay (%d, %d) that should be "
"accounted for.\n", pkt->cmdString(), pkt->busFirstWordDelay,
pkt->busLastWordDelay);
// the delay from any previous crossbar has been accounted for
if (pkt->firstWordDelay != 0 || pkt->lastWordDelay != 0)
panic("Packet %s already has delay (%d, %d) that should be "
"accounted for.\n", pkt->cmdString(), pkt->firstWordDelay,
pkt->lastWordDelay);
// The first word will be delivered on the cycle after the header.
pkt->busFirstWordDelay = (headerCycles + 1) * clockPeriod() + offset;
pkt->firstWordDelay = (headerCycles + 1) * clockPeriod() + offset;
// Note that currently busLastWordDelay can be smaller than
// busFirstWordDelay if the packet has no data
pkt->busLastWordDelay = (headerCycles + dataCycles) * clockPeriod() +
// Note that currently lastWordDelay can be smaller than
// firstWordDelay if the packet has no data
pkt->lastWordDelay = (headerCycles + dataCycles) * clockPeriod() +
offset;
}
template <typename SrcType, typename DstType>
BaseBus::Layer<SrcType,DstType>::Layer(DstType& _port, BaseBus& _bus,
BaseXBar::Layer<SrcType,DstType>::Layer(DstType& _port, BaseXBar& _xbar,
const std::string& _name) :
port(_port), bus(_bus), _name(_name), state(IDLE), drainManager(NULL),
port(_port), xbar(_xbar), _name(_name), state(IDLE), drainManager(NULL),
waitingForPeer(NULL), releaseEvent(this)
{
}
template <typename SrcType, typename DstType>
void BaseBus::Layer<SrcType,DstType>::occupyLayer(Tick until)
void BaseXBar::Layer<SrcType,DstType>::occupyLayer(Tick until)
{
// ensure the state is busy at this point, as the bus should
// ensure the state is busy at this point, as the layer should
// transition from idle as soon as it has decided to forward the
// packet to prevent any follow-on calls to sendTiming seeing an
// unoccupied bus
// unoccupied layer
assert(state == BUSY);
// until should never be 0 as express snoops never occupy the bus
// until should never be 0 as express snoops never occupy the layer
assert(until != 0);
bus.schedule(releaseEvent, until);
xbar.schedule(releaseEvent, until);
// account for the occupied ticks
occupancy += until - curTick();
DPRINTF(BaseBus, "The bus is now busy from tick %d to %d\n",
DPRINTF(BaseXBar, "The crossbar layer is now busy from tick %d to %d\n",
curTick(), until);
}
template <typename SrcType, typename DstType>
bool
BaseBus::Layer<SrcType,DstType>::tryTiming(SrcType* src_port)
BaseXBar::Layer<SrcType,DstType>::tryTiming(SrcType* src_port)
{
// if we are in the retry state, we will not see anything but the
// retrying port (or in the case of the snoop ports the snoop
// response port that mirrors the actual slave port) as we leave
// this state again in zero time if the peer does not immediately
// call the bus when receiving the retry
// call the layer when receiving the retry
// first we see if the layer is busy, next we check if the
// destination port is already engaged in a transaction waiting
@ -180,13 +176,12 @@ BaseBus::Layer<SrcType,DstType>::tryTiming(SrcType* src_port)
// put the port at the end of the retry list waiting for the
// layer to be freed up (and in the case of a busy peer, for
// that transaction to go through, and then the bus to free
// that transaction to go through, and then the layer to free
// up)
waitingForLayer.push_back(src_port);
return false;
}
// update the state to busy
state = BUSY;
return true;
@ -194,19 +189,19 @@ BaseBus::Layer<SrcType,DstType>::tryTiming(SrcType* src_port)
template <typename SrcType, typename DstType>
void
BaseBus::Layer<SrcType,DstType>::succeededTiming(Tick busy_time)
BaseXBar::Layer<SrcType,DstType>::succeededTiming(Tick busy_time)
{
// we should have gone from idle or retry to busy in the tryTiming
// test
assert(state == BUSY);
// occupy the bus accordingly
// occupy the layer accordingly
occupyLayer(busy_time);
}
template <typename SrcType, typename DstType>
void
BaseBus::Layer<SrcType,DstType>::failedTiming(SrcType* src_port,
BaseXBar::Layer<SrcType,DstType>::failedTiming(SrcType* src_port,
Tick busy_time)
{
// ensure no one got in between and tried to send something to
@ -228,7 +223,7 @@ BaseBus::Layer<SrcType,DstType>::failedTiming(SrcType* src_port,
template <typename SrcType, typename DstType>
void
BaseBus::Layer<SrcType,DstType>::releaseLayer()
BaseXBar::Layer<SrcType,DstType>::releaseLayer()
{
// releasing the bus means we should now be idle
assert(state == BUSY);
@ -244,7 +239,7 @@ BaseBus::Layer<SrcType,DstType>::releaseLayer()
if (waitingForPeer == NULL)
retryWaiting();
} else if (waitingForPeer == NULL && drainManager) {
DPRINTF(Drain, "Bus done draining, signaling drain manager\n");
DPRINTF(Drain, "Crossbar done draining, signaling drain manager\n");
//If we weren't able to drain before, do it now.
drainManager->signalDrainDone();
// Clear the drain event once we're done with it.
@ -254,7 +249,7 @@ BaseBus::Layer<SrcType,DstType>::releaseLayer()
template <typename SrcType, typename DstType>
void
BaseBus::Layer<SrcType,DstType>::retryWaiting()
BaseXBar::Layer<SrcType,DstType>::retryWaiting()
{
// this should never be called with no one waiting
assert(!waitingForLayer.empty());
@ -271,24 +266,24 @@ BaseBus::Layer<SrcType,DstType>::retryWaiting()
waitingForLayer.pop_front();
// tell the port to retry, which in some cases ends up calling the
// bus
// layer again
retryingPort->sendRetry();
// If the bus is still in the retry state, sendTiming wasn't
// If the layer is still in the retry state, sendTiming wasn't
// called in zero time (e.g. the cache does this), burn a cycle
if (state == RETRY) {
// update the state to busy and reset the retrying port, we
// have done our bit and sent the retry
state = BUSY;
// occupy the bus layer until the next cycle ends
occupyLayer(bus.clockEdge(Cycles(1)));
// occupy the crossbar layer until the next cycle ends
occupyLayer(xbar.clockEdge(Cycles(1)));
}
}
template <typename SrcType, typename DstType>
void
BaseBus::Layer<SrcType,DstType>::recvRetry()
BaseXBar::Layer<SrcType,DstType>::recvRetry()
{
// we should never get a retry without having failed to forward
// something to this port
@ -296,13 +291,13 @@ BaseBus::Layer<SrcType,DstType>::recvRetry()
// add the port where the failed packet originated to the front of
// the waiting ports for the layer, this allows us to call retry
// on the port immediately if the bus layer is idle
// on the port immediately if the crossbar layer is idle
waitingForLayer.push_front(waitingForPeer);
// we are no longer waiting for the peer
waitingForPeer = NULL;
// if the bus layer is idle, retry this port straight away, if we
// if the layer is idle, retry this port straight away, if we
// are busy, then simply let the port wait for its turn
if (state == IDLE) {
retryWaiting();
@ -312,7 +307,7 @@ BaseBus::Layer<SrcType,DstType>::recvRetry()
}
PortID
BaseBus::findPort(Addr addr)
BaseXBar::findPort(Addr addr)
{
// we should never see any address lookups before we've got the
// ranges of all connected slave modules
@ -324,7 +319,7 @@ BaseBus::findPort(Addr addr)
return dest_id;
// Check the address map interval tree
PortMapConstIter i = portMap.find(addr);
auto i = portMap.find(addr);
if (i != portMap.end()) {
dest_id = i->second;
updatePortCache(dest_id, i->first);
@ -334,27 +329,27 @@ BaseBus::findPort(Addr addr)
// Check if this matches the default range
if (useDefaultRange) {
if (defaultRange.contains(addr)) {
DPRINTF(BusAddrRanges, " found addr %#llx on default\n",
DPRINTF(AddrRanges, " found addr %#llx on default\n",
addr);
return defaultPortID;
}
} else if (defaultPortID != InvalidPortID) {
DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, "
DPRINTF(AddrRanges, "Unable to find destination for addr %#llx, "
"will use default port\n", addr);
return defaultPortID;
}
// we should use the range for the default port and it did not
// match, or the default port is not set
fatal("Unable to find destination for addr %#llx on bus %s\n", addr,
fatal("Unable to find destination for addr %#llx on %s\n", addr,
name());
}
/** Function called by the port when the bus is receiving a range change.*/
/** Function called by the port when the crossbar is receiving a range change.*/
void
BaseBus::recvRangeChange(PortID master_port_id)
BaseXBar::recvRangeChange(PortID master_port_id)
{
DPRINTF(BusAddrRanges, "Received range change from slave port %s\n",
DPRINTF(AddrRanges, "Received range change from slave port %s\n",
masterPorts[master_port_id]->getSlavePort().name());
// remember that we got a range from this master port and thus the
@ -371,7 +366,7 @@ BaseBus::recvRangeChange(PortID master_port_id)
gotAllAddrRanges &= *r++;
}
if (gotAllAddrRanges)
DPRINTF(BusAddrRanges, "Got address ranges from all slaves\n");
DPRINTF(AddrRanges, "Got address ranges from all slaves\n");
}
// note that we could get the range from the default port at any
@ -386,7 +381,7 @@ BaseBus::recvRangeChange(PortID master_port_id)
AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
if (ranges.size() != 1)
fatal("Bus %s may only have a single default range",
fatal("Crossbar %s may only have a single default range",
name());
defaultRange = ranges.front();
@ -395,7 +390,7 @@ BaseBus::recvRangeChange(PortID master_port_id)
// the ports are allowed to update their address ranges
// dynamically, so remove any existing entries
if (gotAddrRanges[master_port_id]) {
for (PortMapIter p = portMap.begin(); p != portMap.end(); ) {
for (auto p = portMap.begin(); p != portMap.end(); ) {
if (p->second == master_port_id)
// erasing invalidates the iterator, so advance it
// before the deletion takes place
@ -407,11 +402,11 @@ BaseBus::recvRangeChange(PortID master_port_id)
AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
for (AddrRangeConstIter r = ranges.begin(); r != ranges.end(); ++r) {
DPRINTF(BusAddrRanges, "Adding range %s for id %d\n",
r->to_string(), master_port_id);
if (portMap.insert(*r, master_port_id) == portMap.end()) {
PortID conflict_id = portMap.find(*r)->second;
for (const auto& r: ranges) {
DPRINTF(AddrRanges, "Adding range %s for id %d\n",
r.to_string(), master_port_id);
if (portMap.insert(r, master_port_id) == portMap.end()) {
PortID conflict_id = portMap.find(r)->second;
fatal("%s has two ports with same range:\n\t%s\n\t%s\n",
name(),
masterPorts[master_port_id]->getSlavePort().name(),
@ -424,52 +419,51 @@ BaseBus::recvRangeChange(PortID master_port_id)
// modules, go ahead and tell our connected master modules in
// turn, this effectively assumes a tree structure of the system
if (gotAllAddrRanges) {
DPRINTF(BusAddrRanges, "Aggregating bus ranges\n");
busRanges.clear();
DPRINTF(AddrRanges, "Aggregating address ranges\n");
xbarRanges.clear();
// start out with the default range
if (useDefaultRange) {
if (!gotAddrRanges[defaultPortID])
fatal("Bus %s uses default range, but none provided",
fatal("Crossbar %s uses default range, but none provided",
name());
busRanges.push_back(defaultRange);
DPRINTF(BusAddrRanges, "-- Adding default %s\n",
xbarRanges.push_back(defaultRange);
DPRINTF(AddrRanges, "-- Adding default %s\n",
defaultRange.to_string());
}
// merge all interleaved ranges and add any range that is not
// a subset of the default range
std::vector<AddrRange> intlv_ranges;
for (AddrRangeMap<PortID>::const_iterator r = portMap.begin();
r != portMap.end(); ++r) {
for (const auto& r: portMap) {
// if the range is interleaved then save it for now
if (r->first.interleaved()) {
if (r.first.interleaved()) {
// if we already got interleaved ranges that are not
// part of the same range, then first do a merge
// before we add the new one
if (!intlv_ranges.empty() &&
!intlv_ranges.back().mergesWith(r->first)) {
DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
!intlv_ranges.back().mergesWith(r.first)) {
DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
intlv_ranges.size());
AddrRange merged_range(intlv_ranges);
// next decide if we keep the merged range or not
if (!(useDefaultRange &&
merged_range.isSubset(defaultRange))) {
busRanges.push_back(merged_range);
DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
xbarRanges.push_back(merged_range);
DPRINTF(AddrRanges, "-- Adding merged range %s\n",
merged_range.to_string());
}
intlv_ranges.clear();
}
intlv_ranges.push_back(r->first);
intlv_ranges.push_back(r.first);
} else {
// keep the current range if not a subset of the default
if (!(useDefaultRange &&
r->first.isSubset(defaultRange))) {
busRanges.push_back(r->first);
DPRINTF(BusAddrRanges, "-- Adding range %s\n",
r->first.to_string());
r.first.isSubset(defaultRange))) {
xbarRanges.push_back(r.first);
DPRINTF(AddrRanges, "-- Adding range %s\n",
r.first.to_string());
}
}
}
@ -477,12 +471,12 @@ BaseBus::recvRangeChange(PortID master_port_id)
// if there is still interleaved ranges waiting to be merged,
// go ahead and do it
if (!intlv_ranges.empty()) {
DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
intlv_ranges.size());
AddrRange merged_range(intlv_ranges);
if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
busRanges.push_back(merged_range);
DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
xbarRanges.push_back(merged_range);
DPRINTF(AddrRanges, "-- Adding merged range %s\n",
merged_range.to_string());
}
}
@ -492,30 +486,28 @@ BaseBus::recvRangeChange(PortID master_port_id)
// as there are no guarantees for when the default range is
// update with respect to the other ones
if (useDefaultRange) {
for (AddrRangeConstIter r = busRanges.begin();
r != busRanges.end(); ++r) {
for (const auto& r: xbarRanges) {
// see if the new range is partially
// overlapping the default range
if (r->intersects(defaultRange) &&
!r->isSubset(defaultRange))
if (r.intersects(defaultRange) &&
!r.isSubset(defaultRange))
fatal("Range %s intersects the " \
"default range of %s but is not a " \
"subset\n", r->to_string(), name());
"subset\n", r.to_string(), name());
}
}
// tell all our neighbouring master ports that our address
// ranges have changed
for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end();
++s)
(*s)->sendRangeChange();
for (const auto& s: slavePorts)
s->sendRangeChange();
}
clearPortCache();
}
AddrRangeList
BaseBus::getAddrRanges() const
BaseXBar::getAddrRanges() const
{
// we should never be asked without first having sent a range
// change, and the latter is only done once we have all the ranges
@ -523,17 +515,17 @@ BaseBus::getAddrRanges() const
assert(gotAllAddrRanges);
// at the moment, this never happens, as there are no cycles in
// the range queries and no devices on the master side of a bus
// the range queries and no devices on the master side of a crossbar
// (CPU, cache, bridge etc) actually care about the ranges of the
// ports they are connected to
DPRINTF(BusAddrRanges, "Received address range request\n");
DPRINTF(AddrRanges, "Received address range request\n");
return busRanges;
return xbarRanges;
}
void
BaseBus::regStats()
BaseXBar::regStats()
{
using namespace Stats;
@ -556,9 +548,9 @@ BaseBus::regStats()
.desc("Packet count per connected master and slave (bytes)")
.flags(total | nozero | nonan);
totPktSize
pktSize
.init(slavePorts.size(), masterPorts.size())
.name(name() + ".tot_pkt_size")
.name(name() + ".pkt_size")
.desc("Cumulative packet size per connected master and slave (bytes)")
.flags(total | nozero | nonan);
@ -570,23 +562,23 @@ BaseBus::regStats()
// forwarded to the master (responses and snoop requests)
for (int i = 0; i < slavePorts.size(); i++) {
pktCount.subname(i, slavePorts[i]->getMasterPort().name());
totPktSize.subname(i, slavePorts[i]->getMasterPort().name());
pktSize.subname(i, slavePorts[i]->getMasterPort().name());
for (int j = 0; j < masterPorts.size(); j++) {
pktCount.ysubname(j, masterPorts[j]->getSlavePort().name());
totPktSize.ysubname(j, masterPorts[j]->getSlavePort().name());
pktSize.ysubname(j, masterPorts[j]->getSlavePort().name());
}
}
}
template <typename SrcType, typename DstType>
unsigned int
BaseBus::Layer<SrcType,DstType>::drain(DrainManager *dm)
BaseXBar::Layer<SrcType,DstType>::drain(DrainManager *dm)
{
//We should check that we're not "doing" anything, and that noone is
//waiting. We might be idle but have someone waiting if the device we
//contacted for a retry didn't actually retry.
if (state != IDLE) {
DPRINTF(Drain, "Bus not drained\n");
DPRINTF(Drain, "Crossbar not drained\n");
drainManager = dm;
return 1;
}
@ -595,7 +587,7 @@ BaseBus::Layer<SrcType,DstType>::drain(DrainManager *dm)
template <typename SrcType, typename DstType>
void
BaseBus::Layer<SrcType,DstType>::regStats()
BaseXBar::Layer<SrcType,DstType>::regStats()
{
using namespace Stats;
@ -614,9 +606,9 @@ BaseBus::Layer<SrcType,DstType>::regStats()
}
/**
* Bus layer template instantiations. Could be removed with _impl.hh
* Crossbar layer template instantiations. Could be removed with _impl.hh
* file, but since there are only two given options (MasterPort and
* SlavePort) it seems a bit excessive at this point.
*/
template class BaseBus::Layer<SlavePort,MasterPort>;
template class BaseBus::Layer<MasterPort,SlavePort>;
template class BaseXBar::Layer<SlavePort,MasterPort>;
template class BaseXBar::Layer<MasterPort,SlavePort>;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2013 ARM Limited
* Copyright (c) 2011-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -45,53 +45,47 @@
/**
* @file
* Declaration of an abstract bus base class.
* Declaration of an abstract crossbar base class.
*/
#ifndef __MEM_BUS_HH__
#define __MEM_BUS_HH__
#ifndef __MEM_XBAR_HH__
#define __MEM_XBAR_HH__
#include <deque>
#include "base/addr_range_map.hh"
#include "base/types.hh"
#include "mem/mem_object.hh"
#include "params/BaseBus.hh"
#include "params/BaseXBar.hh"
#include "sim/stats.hh"
/**
* The base bus contains the common elements of the non-coherent and
* coherent bus. It is an abstract class that does not have any of the
* functionality relating to the actual reception and transmission of
* packets, as this is left for the subclasses.
* The base crossbar contains the common elements of the non-coherent
* and coherent crossbar. It is an abstract class that does not have
* any of the functionality relating to the actual reception and
* transmission of packets, as this is left for the subclasses.
*
* The BaseBus is responsible for the basic flow control (busy or
* The BaseXBar is responsible for the basic flow control (busy or
* not), the administration of retries, and the address decoding.
*/
class BaseBus : public MemObject
class BaseXBar : public MemObject
{
protected:
/**
* A bus layer is an internal bus structure with its own flow
* control and arbitration. Hence, a single-layer bus mimics a
* traditional off-chip tri-state bus (like PCI), where only one
* set of wires are shared. For on-chip buses, a good starting
* point is to have three layers, for requests, responses, and
* snoop responses respectively (snoop requests are instantaneous
* and do not need any flow control or arbitration). This case is
* similar to AHB and some OCP configurations.
*
* As a further extensions beyond the three-layer bus, a future
* multi-layer bus has with one layer per connected slave port
* provides a full or partial crossbar, like AXI, OCP, PCIe etc.
* A layer is an internal crossbar arbitration point with its own
* flow control. Each layer is a converging multiplexer tree. By
* instantiating one layer per destination port (and per packet
* type, i.e. request, response, snoop request and snoop
* response), we model full crossbar structures like AXI, ACE,
* PCIe, etc.
*
* The template parameter, PortClass, indicates the destination
* port type for the bus. The retry list holds either master ports
* or slave ports, depending on the direction of the layer. Thus,
* a request layer has a retry list containing slave ports,
* whereas a response layer holds master ports.
* port type for the layer. The retry list holds either master
* ports or slave ports, depending on the direction of the
* layer. Thus, a request layer has a retry list containing slave
* ports, whereas a response layer holds master ports.
*/
template <typename SrcType, typename DstType>
class Layer : public Drainable
@ -100,17 +94,17 @@ class BaseBus : public MemObject
public:
/**
* Create a bus layer and give it a name. The bus layer uses
* the bus an event manager.
* Create a layer and give it a name. The layer uses
* the crossbar an event manager.
*
* @param _port destination port the layer converges at
* @param _bus the bus this layer belongs to
* @param _xbar the crossbar this layer belongs to
* @param _name the layer's name
*/
Layer(DstType& _port, BaseBus& _bus, const std::string& _name);
Layer(DstType& _port, BaseXBar& _xbar, const std::string& _name);
/**
* Drain according to the normal semantics, so that the bus
* Drain according to the normal semantics, so that the crossbar
* can tell the layer to drain, and pass an event to signal
* back when drained.
*
@ -121,27 +115,27 @@ class BaseBus : public MemObject
unsigned int drain(DrainManager *dm);
/**
* Get the bus layer's name
* Get the crossbar layer's name
*/
const std::string name() const { return bus.name() + _name; }
const std::string name() const { return xbar.name() + _name; }
/**
* Determine if the bus layer accepts a packet from a specific
* Determine if the layer accepts a packet from a specific
* port. If not, the port in question is also added to the
* retry list. In either case the state of the layer is
* updated accordingly.
*
* @param port Source port presenting the packet
*
* @return True if the bus layer accepts the packet
* @return True if the layer accepts the packet
*/
bool tryTiming(SrcType* src_port);
/**
* Deal with a destination port accepting a packet by potentially
* removing the source port from the retry list (if retrying) and
* occupying the bus layer accordingly.
* occupying the layer accordingly.
*
* @param busy_time Time to spend as a result of a successful send
*/
@ -150,7 +144,7 @@ class BaseBus : public MemObject
/**
* Deal with a destination port not accepting a packet by
* potentially adding the source port to the retry list (if
* not already at the front) and occupying the bus layer
* not already at the front) and occupying the layer
* accordingly.
*
* @param src_port Source port
@ -158,7 +152,7 @@ class BaseBus : public MemObject
*/
void failedTiming(SrcType* src_port, Tick busy_time);
/** Occupy the bus layer until until */
/** Occupy the layer until until */
void occupyLayer(Tick until);
/**
@ -184,31 +178,31 @@ class BaseBus : public MemObject
/** The destination port this layer converges at. */
DstType& port;
/** The bus this layer is a part of. */
BaseBus& bus;
/** The crossbar this layer is a part of. */
BaseXBar& xbar;
/** A name for this layer. */
std::string _name;
/**
* We declare an enum to track the state of the bus layer. The
* starting point is an idle state where the bus layer is
* waiting for a packet to arrive. Upon arrival, the bus layer
* We declare an enum to track the state of the layer. The
* starting point is an idle state where the layer is waiting
* for a packet to arrive. Upon arrival, the layer
* transitions to the busy state, where it remains either
* until the packet transfer is done, or the header time is
* spent. Once the bus layer leaves the busy state, it can
* spent. Once the layer leaves the busy state, it can
* either go back to idle, if no packets have arrived while it
* was busy, or the bus layer goes on to retry the first port
* was busy, or the layer goes on to retry the first port
* in waitingForLayer. A similar transition takes place from
* idle to retry if the bus layer receives a retry from one of
* idle to retry if the layer receives a retry from one of
* its connected ports. The retry state lasts until the port
* in questions calls sendTiming and returns control to the
* bus layer, or goes to a busy state if the port does not
* layer, or goes to a busy state if the port does not
* immediately react to the retry by calling sendTiming.
*/
enum State { IDLE, BUSY, RETRY };
/** track the state of the bus layer */
/** track the state of the layer */
State state;
/** manager to signal when drained */
@ -227,7 +221,7 @@ class BaseBus : public MemObject
SrcType* waitingForPeer;
/**
* Release the bus layer after being occupied and return to an
* Release the layer after being occupied and return to an
* idle state where we proceed to send a retry to any
* potential waiting port, or drain if asked to do so.
*/
@ -238,7 +232,7 @@ class BaseBus : public MemObject
/**
* Stats for occupancy and utilization. These stats capture
* the time the bus spends in the busy state and are thus only
* the time the layer spends in the busy state and are thus only
* relevant when the memory system is in timing mode.
*/
Stats::Scalar occupancy;
@ -248,27 +242,27 @@ class BaseBus : public MemObject
/** cycles of overhead per transaction */
const Cycles headerCycles;
/** the width of the bus in bytes */
/** the width of the xbar in bytes */
const uint32_t width;
typedef AddrRangeMap<PortID>::iterator PortMapIter;
typedef AddrRangeMap<PortID>::const_iterator PortMapConstIter;
AddrRangeMap<PortID> portMap;
/** all contigous ranges seen by this bus */
AddrRangeList busRanges;
/** all contigous ranges seen by this crossbar */
AddrRangeList xbarRanges;
AddrRange defaultRange;
/**
* Function called by the port when the bus is recieving a range change.
* Function called by the port when the crossbar is recieving a
* range change.
*
* @param master_port_id id of the port that received the change
*/
void recvRangeChange(PortID master_port_id);
/** Find which port connected to this bus (if any) should be given a packet
* with this address.
/** Find which port connected to this crossbar (if any) should be
* given a packet with this address.
*
* @param addr Address to find port for.
* @return id of port that the packet should be sent out of.
*/
@ -322,7 +316,7 @@ class BaseBus : public MemObject
}
/**
* Return the address ranges the bus is responsible for.
* Return the address ranges the crossbar is responsible for.
*
* @return a list of non-overlapping address ranges
*/
@ -330,31 +324,25 @@ class BaseBus : public MemObject
/**
* Calculate the timing parameters for the packet. Updates the
* busFirstWordDelay and busLastWordDelay fields of the packet
* firstWordDelay and lastWordDelay fields of the packet
* object with the relative number of ticks required to transmit
* the header and the first word, and the last word, respectively.
*/
void calcPacketTiming(PacketPtr pkt);
/**
* Remember for each of the master ports of the bus if we got an
* address range from the connected slave. For convenience, also
* keep track of if we got ranges from all the slave modules or
* not.
* Remember for each of the master ports of the crossbar if we got
* an address range from the connected slave. For convenience,
* also keep track of if we got ranges from all the slave modules
* or not.
*/
std::vector<bool> gotAddrRanges;
bool gotAllAddrRanges;
/** The master and slave ports of the bus */
/** The master and slave ports of the crossbar */
std::vector<SlavePort*> slavePorts;
std::vector<MasterPort*> masterPorts;
/** Convenience typedefs. */
typedef std::vector<SlavePort*>::iterator SlavePortIter;
typedef std::vector<MasterPort*>::iterator MasterPortIter;
typedef std::vector<SlavePort*>::const_iterator SlavePortConstIter;
typedef std::vector<MasterPort*>::const_iterator MasterPortConstIter;
/** Port that handles requests that don't match any of the interfaces.*/
PortID defaultPortID;
@ -364,29 +352,28 @@ class BaseBus : public MemObject
addresses not handled by another port to default device. */
const bool useDefaultRange;
BaseBus(const BaseBusParams *p);
BaseXBar(const BaseXBarParams *p);
virtual ~BaseBus();
virtual ~BaseXBar();
/**
* Stats for transaction distribution and data passing through the
* bus. The transaction distribution is globally counting
* crossbar. The transaction distribution is globally counting
* different types of commands. The packet count and total packet
* size are two-dimensional vectors that are indexed by the bus
* size are two-dimensional vectors that are indexed by the
* slave port and master port id (thus the neighbouring master and
* neighbouring slave), summing up both directions (request and
* response).
*/
Stats::Formula throughput;
Stats::Vector transDist;
Stats::Vector2d pktCount;
Stats::Vector2d totPktSize;
Stats::Vector2d pktSize;
public:
virtual void init();
/** A function used to return the port associated with this bus object. */
/** A function used to return the port associated with this object. */
BaseMasterPort& getMasterPort(const std::string& if_name,
PortID idx = InvalidPortID);
BaseSlavePort& getSlavePort(const std::string& if_name,
@ -398,4 +385,4 @@ class BaseBus : public MemObject
};
#endif //__MEM_BUS_HH__
#endif //__MEM_XBAR_HH__

View file

@ -1870,7 +1870,7 @@ class SlavePort(Port):
raise TypeError, 'wrong number of arguments'
# VectorPort description object. Like Port, but represents a vector
# of connections (e.g., as on a Bus).
# of connections (e.g., as on a XBar).
class VectorPort(Port):
def __init__(self, *args):
self.isVec = True

View file

@ -173,7 +173,7 @@ def dot_create_node(simNode, full_path, label):
class NodeType:
SYS = 0
CPU = 1
BUS = 2
XBAR = 2
MEM = 3
DEV = 4
OTHER = 5
@ -190,8 +190,8 @@ def get_node_type(simNode):
elif 'PioDevice' in dir(m5.objects) and \
isinstance(simNode, m5.objects.PioDevice):
return NodeType.DEV
elif isinstance(simNode, m5.objects.BaseBus):
return NodeType.BUS
elif isinstance(simNode, m5.objects.BaseXBar):
return NodeType.XBAR
elif isinstance(simNode, m5.objects.AbstractMemory):
return NodeType.MEM
else:
@ -205,7 +205,7 @@ def get_type_colour(nodeType):
return (228, 231, 235)
elif nodeType == NodeType.CPU:
return (187, 198, 217)
elif nodeType == NodeType.BUS:
elif nodeType == NodeType.XBAR:
return (111, 121, 140)
elif nodeType == NodeType.MEM:
return (94, 89, 88)

View file

@ -102,7 +102,7 @@ class BaseSystem(object):
Returns:
A bus that CPUs should use to connect to the shared cache.
"""
system.toL2Bus = CoherentBus(clk_domain=system.cpu_clk_domain)
system.toL2Bus = CoherentXBar(clk_domain=system.cpu_clk_domain)
system.l2c = L2Cache(clk_domain=system.cpu_clk_domain,
size='4MB', assoc=8)
system.l2c.cpu_side = system.toL2Bus.master
@ -184,7 +184,7 @@ class BaseSESystem(BaseSystem):
def create_system(self):
system = System(physmem = self.mem_class(),
membus = CoherentBus(),
membus = CoherentXBar(),
mem_mode = self.mem_mode)
system.system_port = system.membus.slave
system.physmem.port = system.membus.master

View file

@ -37,9 +37,9 @@ cpus = [ MemTest() for i in xrange(nb_cores) ]
# system simulated
system = System(cpu = cpus, funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
funcbus = NoncoherentXBar(),
physmem = SimpleMemory(),
membus = CoherentBus(width=16, snoop_filter = SnoopFilter()))
membus = CoherentXBar(width=16, snoop_filter = SnoopFilter()))
# Dummy voltage domain for all our clock domains
system.voltage_domain = VoltageDomain()
system.clk_domain = SrcClockDomain(clock = '1GHz',
@ -50,7 +50,7 @@ system.clk_domain = SrcClockDomain(clock = '1GHz',
system.cpu_clk_domain = SrcClockDomain(clock = '2GHz',
voltage_domain = system.voltage_domain)
system.toL2Bus = CoherentBus(clk_domain = system.cpu_clk_domain, width=16,
system.toL2Bus = CoherentXBar(clk_domain = system.cpu_clk_domain, width=16,
snoop_filter = SnoopFilter())
system.l2c = L2Cache(clk_domain = system.cpu_clk_domain, size='64kB', assoc=8)
system.l2c.cpu_side = system.toL2Bus.master

View file

@ -81,7 +81,7 @@ options.num_cpus = nb_cores
system = System(cpu = cpus,
funcmem = SimpleMemory(in_addr_map = False),
physmem = SimpleMemory(null = True),
funcbus = NoncoherentBus())
funcbus = NoncoherentXBar())
# Dummy voltage domain for all our clock domains
system.voltage_domain = VoltageDomain()
system.clk_domain = SrcClockDomain(clock = '1GHz',

View file

@ -37,9 +37,9 @@ cpus = [ MemTest() for i in xrange(nb_cores) ]
# system simulated
system = System(cpu = cpus, funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
funcbus = NoncoherentXBar(),
physmem = SimpleMemory(),
membus = CoherentBus(width=16))
membus = CoherentXBar(width=16))
# Dummy voltage domain for all our clock domains
system.voltage_domain = VoltageDomain()
system.clk_domain = SrcClockDomain(clock = '1GHz',
@ -50,7 +50,7 @@ system.clk_domain = SrcClockDomain(clock = '1GHz',
system.cpu_clk_domain = SrcClockDomain(clock = '2GHz',
voltage_domain = system.voltage_domain)
system.toL2Bus = CoherentBus(clk_domain = system.cpu_clk_domain, width=16)
system.toL2Bus = CoherentXBar(clk_domain = system.cpu_clk_domain, width=16)
system.l2c = L2Cache(clk_domain = system.cpu_clk_domain, size='64kB', assoc=8)
system.l2c.cpu_side = system.toL2Bus.master

View file

@ -38,7 +38,7 @@ import ruby_config
ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", nb_cores)
# system simulated
system = System(cpu = cpus, physmem = ruby_memory, membus = CoherentBus(),
system = System(cpu = cpus, physmem = ruby_memory, membus = CoherentXBar(),
mem_mode = "timing",
clk_domain = SrcClockDomain(clock = '1GHz'))

View file

@ -39,7 +39,7 @@ cpu = DerivO3CPU(cpu_id=0)
system = System(cpu = cpu,
physmem = ruby_memory,
membus = CoherentBus(),
membus = CoherentXBar(),
mem_mode = "timing",
clk_domain = SrcClockDomain(clock = '1GHz'))

View file

@ -38,7 +38,7 @@ import ruby_config
ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", nb_cores)
# system simulated
system = System(cpu = cpus, physmem = ruby_memory, membus = CoherentBus(),
system = System(cpu = cpus, physmem = ruby_memory, membus = CoherentXBar(),
clk_domain = SrcClockDomain(clock = '1GHz'))
# Create a seperate clock domain for components that should run at

View file

@ -49,7 +49,7 @@ cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-dram-ctrl.cfg")
# system simulated
system = System(cpu = cpu, physmem = DDR3_1600_x64(),
membus = NoncoherentBus(width = 16),
membus = NoncoherentXBar(width = 16),
clk_domain = SrcClockDomain(clock = '1GHz',
voltage_domain =
VoltageDomain()))

View file

@ -49,7 +49,7 @@ cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-mem.cfg")
# system simulated
system = System(cpu = cpu, physmem = SimpleMemory(),
membus = NoncoherentBus(width = 16),
membus = NoncoherentXBar(width = 16),
clk_domain = SrcClockDomain(clock = '1GHz',
voltage_domain =
VoltageDomain()))