gem5/src/mem/bus.cc

207 lines
6.5 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file Definition of a bus object.
*/
#include "base/trace.hh"
#include "mem/bus.hh"
#include "sim/builder.hh"
Port *
Bus::getPort(const std::string &if_name)
{
// if_name ignored? forced to be empty?
int id = interfaces.size();
BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
interfaces.push_back(bp);
return bp;
}
/** Get the ranges of anyone that we are connected to. */
void
Bus::init()
{
std::vector<Port*>::iterator intIter;
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
(*intIter)->sendStatusChange(Port::RangeChange);
}
/** Function called by the port when the bus is receiving a Timing
* transaction.*/
bool
Bus::recvTiming(Packet *pkt)
{
Split SimpleCPU into two different models, AtomicSimpleCPU and TimingSimpleCPU, which use atomic and timing memory accesses respectively. Common code is factored into the BaseSimpleCPU class. AtomicSimpleCPU includes an option (simulate_stalls) to add delays based on the estimated latency reported by the atomic accesses. Plain old "SimpleCPU" is gone; I have not updated all the config files (just test/test.py). Also fixes to get timing accesses working in new memory model and to get split-phase memory instruction definitions working with new memory model as well. arch/alpha/isa/main.isa: Need to include packet_impl.h for functions that use Packet objects. arch/alpha/isa/mem.isa: Change completeAcc() methods to take Packet object pointers. Also split out StoreCond template for completeAcc(), since that's the only one that needs write_result and we get an unused variable warning if we always have it in there. build/SConstruct: Update list of recognized CPU model names. configs/test/test.py: Change SimpleCPU to AtomicSimpleCPU. cpu/SConscript: Define sources for new CPU models. Add split memory access methods to CPU model signatures. cpu/cpu_models.py: cpu/static_inst.hh: Define new CPU models. cpu/simple/base.cc: cpu/simple/base.hh: Factor out pieces specific to Atomic or Timing models. mem/bus.cc: Bus needs to be able to route timing packets based on explicit dest so responses can get back to requester. Set dest to Packet::Broadcast to indicate that dest should be derived from address. Also set packet src field based on port from which packet is sent. mem/bus.hh: Set packet src field based on port from which packet is sent. mem/packet.hh: Define Broadcast destination address to indicate that packet should be routed based on address. mem/physical.cc: Set packet dest on response so packet is routed back to requester properly. mem/port.cc: Flag blob packets as Broadcast. python/m5/objects/PhysicalMemory.py: Change default latency to be 1 cycle. --HG-- rename : cpu/simple/cpu.cc => cpu/simple/base.cc rename : cpu/simple/cpu.hh => cpu/simple/base.hh extra : convert_revision : e9646af6406a20c8c605087936dc4683375c2132
2006-05-16 23:36:50 +02:00
Port *port;
DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
short dest = pkt->getDest();
if (dest == Packet::Broadcast) {
port = findPort(pkt->getAddr(), pkt->getSrc());
Split SimpleCPU into two different models, AtomicSimpleCPU and TimingSimpleCPU, which use atomic and timing memory accesses respectively. Common code is factored into the BaseSimpleCPU class. AtomicSimpleCPU includes an option (simulate_stalls) to add delays based on the estimated latency reported by the atomic accesses. Plain old "SimpleCPU" is gone; I have not updated all the config files (just test/test.py). Also fixes to get timing accesses working in new memory model and to get split-phase memory instruction definitions working with new memory model as well. arch/alpha/isa/main.isa: Need to include packet_impl.h for functions that use Packet objects. arch/alpha/isa/mem.isa: Change completeAcc() methods to take Packet object pointers. Also split out StoreCond template for completeAcc(), since that's the only one that needs write_result and we get an unused variable warning if we always have it in there. build/SConstruct: Update list of recognized CPU model names. configs/test/test.py: Change SimpleCPU to AtomicSimpleCPU. cpu/SConscript: Define sources for new CPU models. Add split memory access methods to CPU model signatures. cpu/cpu_models.py: cpu/static_inst.hh: Define new CPU models. cpu/simple/base.cc: cpu/simple/base.hh: Factor out pieces specific to Atomic or Timing models. mem/bus.cc: Bus needs to be able to route timing packets based on explicit dest so responses can get back to requester. Set dest to Packet::Broadcast to indicate that dest should be derived from address. Also set packet src field based on port from which packet is sent. mem/bus.hh: Set packet src field based on port from which packet is sent. mem/packet.hh: Define Broadcast destination address to indicate that packet should be routed based on address. mem/physical.cc: Set packet dest on response so packet is routed back to requester properly. mem/port.cc: Flag blob packets as Broadcast. python/m5/objects/PhysicalMemory.py: Change default latency to be 1 cycle. --HG-- rename : cpu/simple/cpu.cc => cpu/simple/base.cc rename : cpu/simple/cpu.hh => cpu/simple/base.hh extra : convert_revision : e9646af6406a20c8c605087936dc4683375c2132
2006-05-16 23:36:50 +02:00
} else {
assert(dest >= 0 && dest < interfaces.size());
assert(dest != pkt->getSrc()); // catch infinite loops
port = interfaces[dest];
Split SimpleCPU into two different models, AtomicSimpleCPU and TimingSimpleCPU, which use atomic and timing memory accesses respectively. Common code is factored into the BaseSimpleCPU class. AtomicSimpleCPU includes an option (simulate_stalls) to add delays based on the estimated latency reported by the atomic accesses. Plain old "SimpleCPU" is gone; I have not updated all the config files (just test/test.py). Also fixes to get timing accesses working in new memory model and to get split-phase memory instruction definitions working with new memory model as well. arch/alpha/isa/main.isa: Need to include packet_impl.h for functions that use Packet objects. arch/alpha/isa/mem.isa: Change completeAcc() methods to take Packet object pointers. Also split out StoreCond template for completeAcc(), since that's the only one that needs write_result and we get an unused variable warning if we always have it in there. build/SConstruct: Update list of recognized CPU model names. configs/test/test.py: Change SimpleCPU to AtomicSimpleCPU. cpu/SConscript: Define sources for new CPU models. Add split memory access methods to CPU model signatures. cpu/cpu_models.py: cpu/static_inst.hh: Define new CPU models. cpu/simple/base.cc: cpu/simple/base.hh: Factor out pieces specific to Atomic or Timing models. mem/bus.cc: Bus needs to be able to route timing packets based on explicit dest so responses can get back to requester. Set dest to Packet::Broadcast to indicate that dest should be derived from address. Also set packet src field based on port from which packet is sent. mem/bus.hh: Set packet src field based on port from which packet is sent. mem/packet.hh: Define Broadcast destination address to indicate that packet should be routed based on address. mem/physical.cc: Set packet dest on response so packet is routed back to requester properly. mem/port.cc: Flag blob packets as Broadcast. python/m5/objects/PhysicalMemory.py: Change default latency to be 1 cycle. --HG-- rename : cpu/simple/cpu.cc => cpu/simple/base.cc rename : cpu/simple/cpu.hh => cpu/simple/base.hh extra : convert_revision : e9646af6406a20c8c605087936dc4683375c2132
2006-05-16 23:36:50 +02:00
}
return port->sendTiming(pkt);
}
Port *
Bus::findPort(Addr addr, int id)
{
/* An interval tree would be a better way to do this. --ali. */
int dest_id = -1;
int i = 0;
bool found = false;
while (i < portList.size() && !found)
{
if (portList[i].range == addr) {
dest_id = portList[i].portId;
found = true;
DPRINTF(Bus, " found addr 0x%llx on device %d\n", addr, dest_id);
}
i++;
}
if (dest_id == -1)
panic("Unable to find destination for addr: %llx", addr);
// we shouldn't be sending this back to where it came from
assert(dest_id != id);
return interfaces[dest_id];
}
/** Function called by the port when the bus is receiving a Atomic
* transaction.*/
Tick
Bus::recvAtomic(Packet *pkt)
{
DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
assert(pkt->getDest() == Packet::Broadcast);
return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
}
/** Function called by the port when the bus is receiving a Functional
* transaction.*/
void
Bus::recvFunctional(Packet *pkt)
{
DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
assert(pkt->getDest() == Packet::Broadcast);
findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt);
}
/** Function called by the port when the bus is receiving a status change.*/
void
Bus::recvStatusChange(Port::Status status, int id)
{
assert(status == Port::RangeChange &&
"The other statuses need to be implemented.");
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
assert(id < interfaces.size() && id >= 0);
int x;
Port *port = interfaces[id];
AddrRangeList ranges;
fixes for new memory system SConscript: comment out most devices add vport.cc arch/alpha/arguments.cc: arch/alpha/arguments.hh: push in alpha name space fix for new memory system arch/alpha/faults.cc: arch/alpha/faults.hh: Added an unimplemented fault that can be returned if a certain function isn't implemented arch/alpha/freebsd/system.cc: arch/alpha/linux/system.cc: arch/alpha/stacktrace.cc: arch/alpha/system.cc: arch/alpha/tlb.hh: arch/alpha/tru64/system.cc: fixed for new memory system arch/alpha/tlb.cc: fixed for new memory system removed code that seems to have no purpose arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: fixed for new memory system put in namespace AlphaISA base/remote_gdb.cc: fix for new memory system cpu/cpu_exec_context.cc: cpu/cpu_exec_context.hh: cpu/exec_context.hh: create two ports one of physical accesses and one for superpage accesses Add functions getVirtPort() getPhysPort() delVirtPort(). To get statically allocated physical or virtual ports or if an execcontext is passed in get a dynamically allocated virtual port dev/alpha_console.cc: dev/alpha_console.hh: Redo for new memory system dev/io_device.cc: dev/io_device.hh: new I/O devices for new memory system kern/linux/events.cc: kern/linux/printk.cc: kern/linux/printk.hh: kern/tru64/dump_mbuf.hh: kern/tru64/printf.cc: kern/tru64/printf.hh: Arguments now in namespaces kern/tru64/tru64_events.cc: mem/bus.cc: fix for new memory syste mem/physical.hh: new addressranges function getPort should be public mem/port.hh: Add write/read methods to functional port update getDeviceAddrRanges to have a list of both snoops and response lists sim/pseudo_inst.cc: sim/system.cc: sim/system.hh: Update for new mem system sim/vptr.hh: comment out code and replace with panics This will need to be fixed at some point, but it's not easy. --HG-- extra : convert_revision : 41f41f422cfbab3751284d55cccb6ea64a7956e2
2006-04-06 06:51:46 +02:00
AddrRangeList snoops;
AddrRangeIter iter;
std::vector<DevMap>::iterator portIter;
// Clean out any previously existent ids
for (portIter = portList.begin(); portIter != portList.end(); ) {
if (portIter->portId == id)
portIter = portList.erase(portIter);
else
portIter++;
}
fixes for new memory system SConscript: comment out most devices add vport.cc arch/alpha/arguments.cc: arch/alpha/arguments.hh: push in alpha name space fix for new memory system arch/alpha/faults.cc: arch/alpha/faults.hh: Added an unimplemented fault that can be returned if a certain function isn't implemented arch/alpha/freebsd/system.cc: arch/alpha/linux/system.cc: arch/alpha/stacktrace.cc: arch/alpha/system.cc: arch/alpha/tlb.hh: arch/alpha/tru64/system.cc: fixed for new memory system arch/alpha/tlb.cc: fixed for new memory system removed code that seems to have no purpose arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: fixed for new memory system put in namespace AlphaISA base/remote_gdb.cc: fix for new memory system cpu/cpu_exec_context.cc: cpu/cpu_exec_context.hh: cpu/exec_context.hh: create two ports one of physical accesses and one for superpage accesses Add functions getVirtPort() getPhysPort() delVirtPort(). To get statically allocated physical or virtual ports or if an execcontext is passed in get a dynamically allocated virtual port dev/alpha_console.cc: dev/alpha_console.hh: Redo for new memory system dev/io_device.cc: dev/io_device.hh: new I/O devices for new memory system kern/linux/events.cc: kern/linux/printk.cc: kern/linux/printk.hh: kern/tru64/dump_mbuf.hh: kern/tru64/printf.cc: kern/tru64/printf.hh: Arguments now in namespaces kern/tru64/tru64_events.cc: mem/bus.cc: fix for new memory syste mem/physical.hh: new addressranges function getPort should be public mem/port.hh: Add write/read methods to functional port update getDeviceAddrRanges to have a list of both snoops and response lists sim/pseudo_inst.cc: sim/system.cc: sim/system.hh: Update for new mem system sim/vptr.hh: comment out code and replace with panics This will need to be fixed at some point, but it's not easy. --HG-- extra : convert_revision : 41f41f422cfbab3751284d55cccb6ea64a7956e2
2006-04-06 06:51:46 +02:00
port->getPeerAddressRanges(ranges, snoops);
// not dealing with snooping yet either
fixes for new memory system SConscript: comment out most devices add vport.cc arch/alpha/arguments.cc: arch/alpha/arguments.hh: push in alpha name space fix for new memory system arch/alpha/faults.cc: arch/alpha/faults.hh: Added an unimplemented fault that can be returned if a certain function isn't implemented arch/alpha/freebsd/system.cc: arch/alpha/linux/system.cc: arch/alpha/stacktrace.cc: arch/alpha/system.cc: arch/alpha/tlb.hh: arch/alpha/tru64/system.cc: fixed for new memory system arch/alpha/tlb.cc: fixed for new memory system removed code that seems to have no purpose arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: fixed for new memory system put in namespace AlphaISA base/remote_gdb.cc: fix for new memory system cpu/cpu_exec_context.cc: cpu/cpu_exec_context.hh: cpu/exec_context.hh: create two ports one of physical accesses and one for superpage accesses Add functions getVirtPort() getPhysPort() delVirtPort(). To get statically allocated physical or virtual ports or if an execcontext is passed in get a dynamically allocated virtual port dev/alpha_console.cc: dev/alpha_console.hh: Redo for new memory system dev/io_device.cc: dev/io_device.hh: new I/O devices for new memory system kern/linux/events.cc: kern/linux/printk.cc: kern/linux/printk.hh: kern/tru64/dump_mbuf.hh: kern/tru64/printf.cc: kern/tru64/printf.hh: Arguments now in namespaces kern/tru64/tru64_events.cc: mem/bus.cc: fix for new memory syste mem/physical.hh: new addressranges function getPort should be public mem/port.hh: Add write/read methods to functional port update getDeviceAddrRanges to have a list of both snoops and response lists sim/pseudo_inst.cc: sim/system.cc: sim/system.hh: Update for new mem system sim/vptr.hh: comment out code and replace with panics This will need to be fixed at some point, but it's not easy. --HG-- extra : convert_revision : 41f41f422cfbab3751284d55cccb6ea64a7956e2
2006-04-06 06:51:46 +02:00
assert(snoops.size() == 0);
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
DevMap dm;
dm.portId = id;
dm.range = *iter;
DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n",
dm.range.start, dm.range.end, id);
portList.push_back(dm);
}
DPRINTF(MMU, "port list has %d entries\n", portList.size());
// tell all our peers that our address range has changed.
// Don't tell the device that caused this change, it already knows
for (x = 0; x < interfaces.size(); x++)
if (x != id)
interfaces[x]->sendStatusChange(Port::RangeChange);
}
void
Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
{
std::vector<DevMap>::iterator portIter;
resp.clear();
snoop.clear();
DPRINTF(BusAddrRanges, "received address range request, returning:\n");
for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
if (portIter->portId != id) {
resp.push_back(portIter->range);
DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",
portIter->range.start, portIter->range.end);
}
}
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
Param<int> bus_id;
END_DECLARE_SIM_OBJECT_PARAMS(Bus)
BEGIN_INIT_SIM_OBJECT_PARAMS(Bus)
INIT_PARAM(bus_id, "a globally unique bus id")
END_INIT_SIM_OBJECT_PARAMS(Bus)
CREATE_SIM_OBJECT(Bus)
{
return new Bus(getInstanceName(), bus_id);
}
REGISTER_SIM_OBJECT("Bus", Bus)