ruby: FS support using the new configuration system

This commit is contained in:
Brad Beckmann 2010-01-29 20:29:21 -08:00
parent dc758641c9
commit ce2d13195b
9 changed files with 108 additions and 152 deletions

View file

@ -79,14 +79,14 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
return self
def makeLinuxAlphaRubySystem(mem_mode, rubymem, mdesc = None):
def makeLinuxAlphaRubySystem(mem_mode, phys_mem, mdesc = None):
class BaseTsunami(Tsunami):
ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0)
ide = IdeController(disks=[Parent.disk0, Parent.disk2],
pci_func=0, pci_dev=0, pci_bus=0)
self = LinuxAlphaSystem(physmem = rubymem)
self = LinuxAlphaSystem(physmem = phys_mem)
if not mdesc:
# generic system
mdesc = SysConfig()
@ -95,6 +95,13 @@ def makeLinuxAlphaRubySystem(mem_mode, rubymem, mdesc = None):
# Create pio bus to connect all device pio ports to rubymem's pio port
self.piobus = Bus(bus_id=0)
#
# Pio functional accesses from devices need direct access to memory
# RubyPort currently does support functional accesses. Therefore provide
# the piobus a direct connection to physical memory
#
self.piobus.port = phys_mem.port
self.disk0 = CowIdeDisk(driveID='master')
self.disk2 = CowIdeDisk(driveID='master')
self.disk0.childImage(mdesc.disk())
@ -104,12 +111,10 @@ def makeLinuxAlphaRubySystem(mem_mode, rubymem, mdesc = None):
self.tsunami.ide.pio = self.piobus.port
self.tsunami.ethernet.pio = self.piobus.port
# connect the dma ports directly to ruby dma ports
self.tsunami.ide.dma = self.physmem.dma_port
self.tsunami.ethernet.dma = self.physmem.dma_port
# connect the pio bus to rubymem
self.physmem.pio_port = self.piobus.port
#
# store the dma devices for later connection to dma ruby ports
#
self.dma_devices = [self.tsunami.ide, self.tsunami.ethernet]
self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(),
read_only = True))

View file

@ -34,6 +34,8 @@ parser.add_option("-n", "--num-cpus", type="int", default=1)
parser.add_option("--caches", action="store_true")
parser.add_option("--l2cache", action="store_true")
parser.add_option("--fastmem", action="store_true")
parser.add_option("--clock", action="store", type="string", default='1GHz')
parser.add_option("--num-dirs", type="int", default=1)
# Run duration options
parser.add_option("-m", "--maxtick", type="int", default=m5.MaxTick,

View file

@ -43,10 +43,10 @@ from m5.util import addToPath, panic
if not buildEnv['FULL_SYSTEM']:
panic("This script requires full-system mode (*_FS).")
addToPath('../../tests/configs/')
addToPath('../common')
addToPath('../ruby')
import ruby_config
import Ruby
from FSConfig import *
from SysPaths import *
@ -72,12 +72,6 @@ parser.add_option("-i", "--input", default="", help="Read stdin from a file.")
parser.add_option("--output", default="", help="Redirect stdout to a file.")
parser.add_option("--errout", default="", help="Redirect stderr to a file.")
# ruby options
parser.add_option("--ruby-debug", action="store_true")
parser.add_option("--ruby-debug-file", default="", help="Ruby debug out file (stdout if blank)")
parser.add_option("--protocol", default="", help="Ruby protocol compiled into binary")
# ruby host memory experimentation
parser.add_option("--cache_size", type="int")
parser.add_option("--cache_assoc", type="int")
@ -114,87 +108,25 @@ class CPUClass(TimingSimpleCPU): pass
test_mem_mode = 'timing'
FutureClass = None
CPUClass.clock = '1GHz'
CPUClass.clock = options.clock
#
# Since we are running in timing mode, set the number of M5 ticks to ruby ticks
# to the cpu clock frequency
#
M5_to_ruby_tick = '1000t'
physmem = PhysicalMemory()
np = options.num_cpus
system = makeLinuxAlphaRubySystem(test_mem_mode, physmem, bm[0])
# check for max instruction count
if options.max_inst:
max_inst = options.max_inst
else:
max_inst = 0
system.ruby = Ruby.create_system(options,
physmem,
system.piobus,
system.dma_devices)
# set cache size
if options.cache_size:
cache_size = options.cache_size
else:
cache_size = 32768 # 32 kB is default
system.cpu = [CPUClass(cpu_id=i) for i in xrange(options.num_cpus)]
# set cache assoc
if options.cache_assoc:
cache_assoc = options.cache_assoc
else:
cache_assoc = 8 # 8 is default
# set map levels
if options.map_levels:
map_levels = options.map_levels
else:
map_levels = 4 # 4 levels is the default
if options.protocol == "MOESI_hammer":
ruby_config_file = "MOESI_hammer-homogeneous.rb"
elif options.protocol == "MOESI_CMP_token":
ruby_config_file = "TwoLevel_SplitL1UnifiedL2.rb"
elif options.protocol == "MI_example":
ruby_config_file = "MI_example-homogeneous.rb"
else:
print "Error: unsupported ruby protocol"
sys.exit(1)
#
# Currently, since ruby configuraiton is separate from m5, we need to manually
# tell ruby that two dma ports are created by makeLinuxAlphaRubySystem().
# Eventually, this will be fix with a unified configuration system.
#
rubymem = ruby_config.generate(ruby_config_file,
np,
np,
128,
False,
cache_size,
cache_assoc,
map_levels,
2,
M5_to_ruby_tick)
if options.ruby_debug == True:
rubymem.debug = True
rubymem.debug_file = options.ruby_debug_file
system = makeLinuxAlphaRubySystem(test_mem_mode, rubymem, bm[0])
system.cpu = [CPUClass(cpu_id=i) for i in xrange(np)]
if options.l2cache:
print "Error: -l2cache incompatible with ruby, must configure it ruby-style"
sys.exit(1)
if options.caches:
print "Error: -caches incompatible with ruby, must configure it ruby-style"
sys.exit(1)
for i in xrange(np):
system.cpu[i].connectMemPorts(system.physmem)
if options.fastmem:
system.cpu[i].physmem_port = system.physmem.port
for (i, cpu) in enumerate(system.cpu):
#
# Tie the cpu ports to the correct ruby system ports
#
cpu.icache_port = system.ruby.cpu_ruby_ports[i].port
cpu.dcache_port = system.ruby.cpu_ruby_ports[i].port
root = Root(system = system)

View file

@ -49,12 +49,13 @@ class L2Cache(RubyCache):
latency = 15
size = 1048576
def create_system(options, physmem):
def create_system(options, phys_mem, piobus, dma_devices):
if buildEnv['PROTOCOL'] != 'MOESI_hammer':
panic("This script requires the MOESI_hammer protocol to be built.")
sequencers = []
cpu_sequencers = []
#
# The ruby network creation expects the list of nodes in the system to be
# consistent with the NetDest list. Therefore the l1 controller nodes must be
@ -68,11 +69,10 @@ def create_system(options, physmem):
# Must create the individual controllers before the network to ensure the
# controller constructors are called before the network constructor
#
for i in range(options.num_cpus):
for i in xrange(options.num_cpus):
#
# First create the Ruby objects associated with this cpu
# Eventually this code should go in a python file specific to the
# MOESI_hammer protocol
#
l1i_profiler = CacheProfiler(description = ("l1i_%s_profiler" % i))
l1i_cache = L1Cache(cache_profiler = l1i_profiler)
@ -85,33 +85,51 @@ def create_system(options, physmem):
cpu_seq = RubySequencer(icache = l1i_cache,
dcache = l1d_cache,
funcmem_port = physmem.port)
physMemPort = phys_mem.port,
physmem = phys_mem)
if piobus != None:
cpu_seq.pio_port = piobus.port
l1_cntrl = L1Cache_Controller(version = i,
sequencer = cpu_seq,
L1IcacheMemory = l1i_cache,
L1DcacheMemory = l1d_cache,
L2cacheMemory = l2_cache)
#
# Add controllers and sequencers to the appropriate lists
#
cpu_sequencers.append(cpu_seq)
l1_cntrl_nodes.append(l1_cntrl)
for i in xrange(options.num_dirs):
#
# Create the Ruby objects associated with the directory controller
#
mem_cntrl = RubyMemoryControl(version = i)
dir_cntrl = Directory_Controller(version = i,
directory = RubyDirectoryMemory(),
directory = \
RubyDirectoryMemory(version = i),
memBuffer = mem_cntrl)
dma_cntrl = DMA_Controller(version = i,
dma_sequencer = DMASequencer())
#
# Add controllers and sequencers to the appropriate lists
# As noted above: Independent list are track to maintain the order of
# nodes/controllers assumed by the ruby network
#
sequencers.append(cpu_seq)
l1_cntrl_nodes.append(l1_cntrl)
dir_cntrl_nodes.append(dir_cntrl)
for i, dma_device in enumerate(dma_devices):
#
# Create the Ruby objects associated with the dma controller
#
dma_seq = DMASequencer(version = i,
physMemPort = phys_mem.port,
physmem = phys_mem)
dma_cntrl = DMA_Controller(version = i,
dma_sequencer = dma_seq)
dma_cntrl.dma_sequencer.port = dma_device.dma
dma_cntrl_nodes.append(dma_cntrl)
all_cntrls = l1_cntrl_nodes + dir_cntrl_nodes + dma_cntrl_nodes
return (sequencers, dir_cntrl_nodes, all_cntrls)
return (cpu_sequencers, dir_cntrl_nodes, all_cntrls)

View file

@ -34,13 +34,16 @@ from m5.util import addToPath
import MOESI_hammer
def create_system(options, physmem):
def create_system(options, physmem, piobus = None, dma_devices = []):
protocol = buildEnv['PROTOCOL']
if protocol == "MOESI_hammer":
(sequencers, dir_cntrls, all_cntrls) = MOESI_hammer.create_system( \
options, physmem)
(cpu_sequencers, dir_cntrls, all_cntrls) = \
MOESI_hammer.create_system(options, \
physmem, \
piobus, \
dma_devices)
else:
print "Error: unsupported ruby protocol"
sys.exit(1)
@ -68,7 +71,7 @@ def create_system(options, physmem):
ranks_per_dimm = ranksPerDimm,
dimms_per_channel = dimmsPerChannel)
ruby = RubySystem(clock = '1GHz',
ruby = RubySystem(clock = options.clock,
network = network,
profiler = ruby_profiler,
tracer = RubyTracer(),
@ -77,6 +80,6 @@ def create_system(options, physmem):
protocol_trace = False),
mem_size_mb = mem_size_mb)
ruby.cpu_ruby_ports = sequencers
ruby.cpu_ruby_ports = cpu_sequencers
return ruby

View file

@ -36,12 +36,13 @@ uint16_t RubyPort::m_num_ports = 0;
RubyPort::RequestMap RubyPort::pending_cpu_requests;
RubyPort::RubyPort(const Params *p)
: MemObject(p),
funcMemPort(csprintf("%s-funcmem_port", name()), this)
: MemObject(p)
{
m_version = p->version;
assert(m_version != -1);
physmem = p->physmem;
m_controller = NULL;
m_mandatory_q_ptr = NULL;
@ -49,6 +50,7 @@ RubyPort::RubyPort(const Params *p)
m_request_cnt = 0;
m_hit_callback = ruby_hit_callback;
pio_port = NULL;
physMemPort = NULL;
assert(m_num_ports <= 2048); // see below for reason
}
@ -73,8 +75,23 @@ RubyPort::getPort(const std::string &if_name, int idx)
this);
return pio_port;
} else if (if_name == "funcmem_port") {
return &funcMemPort;
} else if (if_name == "physMemPort") {
//
// RubyPort should only have one port to physical memory
//
assert (physMemPort == NULL);
physMemPort = new M5Port(csprintf("%s-physMemPort", name()),
this);
return physMemPort;
} else if (if_name == "functional") {
//
// Calls for the functional port only want to access functional memory.
// Therefore, directly pass these calls ports to physmem.
//
assert(physmem != NULL);
return physmem->getPort(if_name, idx);
}
return NULL;
}
@ -248,11 +265,11 @@ RubyPort::M5Port::hitCallback(PacketPtr pkt)
DPRINTF(MemoryAccess, "Hit callback needs response %d\n",
needsResponse);
ruby_port->funcMemPort.sendFunctional(pkt);
ruby_port->physMemPort->sendAtomic(pkt);
// turn packet around to go back to requester if response expected
if (needsResponse) {
// recvAtomic() should already have turned packet into
// sendAtomic() should already have turned packet into
// atomic response
assert(pkt->isResponse());
DPRINTF(MemoryAccess, "Sending packet back over port\n");
@ -282,7 +299,7 @@ RubyPort::M5Port::isPhysMemAddress(Addr addr)
{
AddrRangeList physMemAddrList;
bool snoop = false;
ruby_port->funcMemPort.getPeerAddressRanges(physMemAddrList, snoop);
ruby_port->physMemPort->getPeerAddressRanges(physMemAddrList, snoop);
for(AddrRangeIter iter = physMemAddrList.begin();
iter != physMemAddrList.end();
iter++) {
@ -292,29 +309,5 @@ RubyPort::M5Port::isPhysMemAddress(Addr addr)
return true;
}
}
assert(isPioAddress(addr));
return false;
}
bool
RubyPort::M5Port::isPioAddress(Addr addr)
{
AddrRangeList pioAddrList;
bool snoop = false;
if (ruby_port->pio_port == NULL) {
return false;
}
ruby_port->pio_port->getPeerAddressRanges(pioAddrList, snoop);
for(AddrRangeIter iter = pioAddrList.begin();
iter != pioAddrList.end();
iter++) {
if (addr >= iter->start && addr <= iter->end) {
DPRINTF(MemoryAccess, "Pio request found in %#llx - %#llx range\n",
iter->start, iter->end);
return true;
}
}
return false;
}

View file

@ -36,6 +36,7 @@
#include "mem/mem_object.hh"
#include "mem/tport.hh"
#include "mem/physical.hh"
#include "params/RubyPort.hh"
@ -63,7 +64,6 @@ public:
virtual Tick recvAtomic(PacketPtr pkt);
private:
bool isPioAddress(Addr addr);
bool isPhysMemAddress(Addr addr);
};
@ -169,7 +169,9 @@ private:
static RequestMap pending_cpu_requests;
static void ruby_hit_callback(int64_t req_id);
FunctionalPort funcMemPort;
M5Port* physMemPort;
PhysicalMemory* physmem;
};
#endif

View file

@ -197,7 +197,7 @@ bool Sequencer::insertRequest(SequencerRequest* request) {
// See if we should schedule a deadlock check
if (deadlockCheckEvent.scheduled() == false) {
schedule(deadlockCheckEvent, m_deadlock_threshold);
schedule(deadlockCheckEvent, m_deadlock_threshold + curTick);
}
Address line_addr(request->ruby_request.paddr);

View file

@ -8,6 +8,8 @@ class RubyPort(MemObject):
port = VectorPort("M5 port")
version = Param.Int(0, "")
pio_port = Port("Ruby_pio_port")
physmem = Param.PhysicalMemory("")
physMemPort = Port("port to physical memory")
class RubySequencer(RubyPort):
type = 'RubySequencer'
@ -18,7 +20,6 @@ class RubySequencer(RubyPort):
"max requests (incl. prefetches) outstanding")
deadlock_threshold = Param.Int(500000,
"max outstanding cycles for a request before deadlock/livelock declared")
funcmem_port = Port("port to functional memory")
class DMASequencer(RubyPort):
type = 'DMASequencer'