ruby: FS support using the new configuration system
This commit is contained in:
parent
dc758641c9
commit
ce2d13195b
9 changed files with 108 additions and 152 deletions
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in a new issue