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()
# 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())
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
+ #
+ # store the dma devices for later connection to dma ruby ports
+ #
+ self.dma_devices = [self.tsunami.ide, self.tsunami.ethernet]
- # connect the pio bus to rubymem
- self.physmem.pio_port = self.piobus.port
-
self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(),
read_only = True))
self.intrctrl = IntrControl()
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,
metavar="T",
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 *
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")
test_mem_mode = 'timing'
FutureClass = None
-CPUClass.clock = '1GHz'
-
-#
-# 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'
-
-np = options.num_cpus
+CPUClass.clock = options.clock
-# check for max instruction count
-if options.max_inst:
- max_inst = options.max_inst
-else:
- max_inst = 0
-
-# set cache size
-if options.cache_size:
- cache_size = options.cache_size
-else:
- cache_size = 32768 # 32 kB is default
-
-# 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)
+physmem = PhysicalMemory()
-#
-# 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)
+system = makeLinuxAlphaRubySystem(test_mem_mode, physmem, bm[0])
-if options.caches:
- print "Error: -caches incompatible with ruby, must configure it ruby-style"
- sys.exit(1)
+system.ruby = Ruby.create_system(options,
+ physmem,
+ system.piobus,
+ system.dma_devices)
-for i in xrange(np):
- system.cpu[i].connectMemPorts(system.physmem)
+system.cpu = [CPUClass(cpu_id=i) for i in xrange(options.num_cpus)]
- 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)
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
# 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)
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())
+ dir_cntrl_nodes.append(dir_cntrl)
+ for i, dma_device in enumerate(dma_devices):
#
- # 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
+ # Create the Ruby objects associated with the dma controller
#
- sequencers.append(cpu_seq)
- l1_cntrl_nodes.append(l1_cntrl)
- dir_cntrl_nodes.append(dir_cntrl)
+ 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)
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)
ranks_per_dimm = ranksPerDimm,
dimms_per_channel = dimmsPerChannel)
- ruby = RubySystem(clock = '1GHz',
+ ruby = RubySystem(clock = options.clock,
network = network,
profiler = ruby_profiler,
tracer = RubyTracer(),
protocol_trace = False),
mem_size_mb = mem_size_mb)
- ruby.cpu_ruby_ports = sequencers
+ ruby.cpu_ruby_ports = cpu_sequencers
return ruby
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;
m_request_cnt = 0;
m_hit_callback = ruby_hit_callback;
pio_port = NULL;
+ physMemPort = NULL;
assert(m_num_ports <= 2048); // see below for reason
}
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;
}
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");
{
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++) {
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;
-}
-
#include "mem/mem_object.hh"
#include "mem/tport.hh"
+#include "mem/physical.hh"
#include "params/RubyPort.hh"
virtual Tick recvAtomic(PacketPtr pkt);
private:
- bool isPioAddress(Addr addr);
bool isPhysMemAddress(Addr addr);
};
static RequestMap pending_cpu_requests;
static void ruby_hit_callback(int64_t req_id);
- FunctionalPort funcMemPort;
+ M5Port* physMemPort;
+
+ PhysicalMemory* physmem;
};
#endif
// 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);
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'
"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'