From ce2d13195ba14766e7ac7f093b369865b6c92cac Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Fri, 29 Jan 2010 20:29:21 -0800 Subject: [PATCH] ruby: FS support using the new configuration system --- configs/common/FSConfig.py | 23 ++++--- configs/common/Options.py | 4 +- configs/example/ruby_fs.py | 100 +++++-------------------------- configs/ruby/MOESI_hammer.py | 50 +++++++++++----- configs/ruby/Ruby.py | 13 ++-- src/mem/ruby/system/RubyPort.cc | 55 ++++++++--------- src/mem/ruby/system/RubyPort.hh | 6 +- src/mem/ruby/system/Sequencer.cc | 2 +- src/mem/ruby/system/Sequencer.py | 3 +- 9 files changed, 106 insertions(+), 150 deletions(-) diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index cf4c9b6f5..f1c905fd8 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -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() @@ -94,7 +94,14 @@ 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,13 +111,11 @@ 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 + # + # 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() diff --git a/configs/common/Options.py b/configs/common/Options.py index d38943644..8b4fc2ce1 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -34,7 +34,9 @@ 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, metavar="T", diff --git a/configs/example/ruby_fs.py b/configs/example/ruby_fs.py index a4831f3bb..e30f40bd5 100644 --- a/configs/example/ruby_fs.py +++ b/configs/example/ruby_fs.py @@ -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' - -# -# 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) diff --git a/configs/ruby/MOESI_hammer.py b/configs/ruby/MOESI_hammer.py index 41c507503..f35ab20c4 100644 --- a/configs/ruby/MOESI_hammer.py +++ b/configs/ruby/MOESI_hammer.py @@ -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()) + 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) diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index 415cb5545..4504bda85 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -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 diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index d8fb6b470..692c9ea81 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -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; -} - diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index a03c4dce2..e57f663c9 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -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 diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 23a6b44e2..00ae5364c 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -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); diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py index 1333204a2..30cb9add0 100644 --- a/src/mem/ruby/system/Sequencer.py +++ b/src/mem/ruby/system/Sequencer.py @@ -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' -- 2.30.2