class BankedL3Cache(SubSystem): """An L3 cache that is made up of multiple L3CacheBanks This class creates mulitple banks that add up to a total L3 cache size. The current interleaving works on a cache line granularity with no upper-order xor bits. Note: We cannot use the default prefetchers with a banked cache. """ SimpleOpts.add_option('--l3_size', default='4MB', help="L3 cache size. Default: 4MB") SimpleOpts.add_option('--l3_banks', default=4, type='int', help="L3 cache banks. Default: 4") def __init__(self, opts): super(BankedL3Cache, self).__init__() total_size = toMemorySize(opts.l3_size) if total_size % opts.l3_banks: m5.fatal("The L3 size must be divisible by number of banks") bank_size = MemorySize(opts.l3_size) / opts.l3_banks self.banks = [ L3CacheBank(size=bank_size) for i in range(opts.l3_banks) ] ranges = self._getInterleaveRanges(AllMemory, opts.l3_banks, 7, 20) for i, bank in enumerate(self.banks): bank.addr_ranges = ranges[i] def connectCPUSideBus(self, bus): for bank in self.banks: bank.connectCPUSideBus(bus) def connectMemSideBus(self, bus): for bank in self.banks: bank.connectMemSideBus(bus) def _getInterleaveRanges(self, rng, num, intlv_low_bit, xor_low_bit): from math import log bits = int(log(num, 2)) if 2**bits != num: m5.fatal("Non-power of two number of memory ranges") intlv_bits = bits ranges = [ AddrRange(start=rng.start, end=rng.end, intlvHighBit=intlv_low_bit + intlv_bits - 1, xorHighBit=xor_low_bit + intlv_bits - 1, intlvBits=intlv_bits, intlvMatch=i) for i in range(num) ] return ranges
class L2Cache(PrefetchCache): """Simple L2 Cache with default values""" # Default parameters size = '256kB' assoc = 16 tag_latency = 10 data_latency = 10 response_latency = 1 mshrs = 20 tgts_per_mshr = 12 writeback_clean = True SimpleOpts.add_option('--l2_size', help="L2 cache size. Default: %s" % size) def __init__(self, opts=None): super(L2Cache, self).__init__(opts) if not opts or not opts.l2_size: return self.size = opts.l2_size def connectCPUSideBus(self, bus): self.cpu_side = bus.master def connectMemSideBus(self, bus): self.mem_side = bus.slave
class L3Cache(Cache): """Simple L3 Cache bank with default values This assumes that the L3 is made up of multiple banks. This cannot be used as a standalone L3 cache. """ SimpleOpts.add_option('--l3_size', default='4MB', help="L3 cache size. Default: 4MB") # Default parameters assoc = 32 tag_latency = 40 data_latency = 40 response_latency = 10 mshrs = 256 tgts_per_mshr = 12 clusivity = 'mostly_excl' def __init__(self, opts): super(L3Cache, self).__init__() self.size = (opts.l3_size) def connectCPUSideBus(self, bus): self.cpu_side = bus.mem_side_ports def connectMemSideBus(self, bus): self.mem_side = bus.cpu_side_ports
class PrefetchCache(Cache): SimpleOpts.add_option("--no_prefetchers", default=False, action="store_true", help="Enable prefectchers on the caches") def __init__(self, options): super(PrefetchCache, self).__init__() if not options or options.no_prefetchers: return self.prefetcher = StridePrefetcher()
class L1ICache(L1Cache): """Simple L1 instruction cache with default values""" # Set the default size size = '32kB' SimpleOpts.add_option('--l1i_size', help="L1 instruction cache size. Default: %s" % size) def __init__(self, opts=None): super(L1ICache, self).__init__(opts) if not opts or not opts.l1i_size: return self.size = opts.l1i_size def connectCPU(self, cpu): """Connect this cache's port to a CPU icache port""" self.cpu_side = cpu.icache_port
class L1DCache(L1Cache): """Simple L1 data cache with default values""" # Set the default size size = '64kB' SimpleOpts.add_option('--l1d_size', help="L1 data cache size. Default: %s" % size) def __init__(self, opts=None): super(L1DCache, self).__init__(opts) if not opts or not opts.l1d_size: return self.size = opts.l1d_size def connectCPU(self, cpu): """Connect this cache's port to a CPU dcache port""" for my_cpu in cpu: self.cpu_side = my_cpu.dcache_port
import sys import m5 from m5.objects import * sys.path.append('configs/common/') import SimpleOpts from system import MySystem SimpleOpts.add_option("--script", default='', help="Script to execute in the simulated system") if __name__ == "__m5_main__": (opts, args) = SimpleOpts.parse_args() system = MySystem(opts) system.readfile = opts.script root = Root(full_system=True, system=system) m5.instantiate() print("Running the simulation") exit_event = m5.simulate() print('Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause()))
import sys import time import m5 import m5.ticks from m5.objects import * sys.path.append('gem5/configs/common/') # For the next line... import SimpleOpts from system import * SimpleOpts.set_usage( "usage: %prog [options] kernel disk cpu_type mem_sys num_cpus boot_type") SimpleOpts.add_option("--allow_listeners", default=False, action="store_true", help="Listeners disabled by default") if __name__ == "__m5_main__": (opts, args) = SimpleOpts.parse_args() if len(args) != 6: SimpleOpts.print_help() m5.fatal("Bad arguments") kernel, disk, cpu_type, mem_sys, num_cpus, boot_type = args num_cpus = int(num_cpus) # create the system we are going to simulate ruby_protocols = [ "MI_example", "MESI_Two_Level", "MOESI_CMP_directory"] if mem_sys == "classic": system = MySystem(kernel, disk, cpu_type, num_cpus, opts)
import sys import m5 from m5.objects import * sys.path.append('configs/common/') # For the next line... import SimpleOpts from system import MySystem SimpleOpts.add_option("--script", default='', help="Script to execute in the simulated system") SimpleOpts.add_option("--n", default='1', help="No of processors") if __name__ == "__m5_main__": (opts, args) = SimpleOpts.parse_args() # create the system we are going to simulate system = MySystem(opts) # Read in the script file passed in via an option. # This file gets read and executed by the simulated system after boot. # Note: The disk image needs to be configured to do this. system.readfile = opts.script # set up the root SimObject and start the simulation root = Root(full_system = True, system = system) # instantiate all of the objects we've created above m5.instantiate()
import sys import m5 from m5.objects import * sys.path.append('configs/common/') # For the next line... import SimpleOpts from system import MySystem SimpleOpts.add_option("--script", default='', help="Script to execute in the simulated system") SimpleOpts.add_option("--n", default='1', help="No of processors") if __name__ == "__m5_main__": (opts, args) = SimpleOpts.parse_args() # create the system we are going to simulate system = MySystem(opts) # Read in the script file passed in via an option. # This file gets read and executed by the simulated system after boot. # Note: The disk image needs to be configured to do this. system.readfile = opts.script # set up the root SimObject and start the simulation root = Root(full_system=True, system=system) # instantiate all of the objects we've created above m5.instantiate()
# 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. # # Authors: Jason Lowe-Power import SimpleOpts import MemConfig # Define common general options # Note that not all optionsa are used by all systems. The actually used options # depend on the system being used. # Simulator options SimpleOpts.add_option("--script", default='', help="Script to execute in the simulated system") SimpleOpts.add_option("--kernel", default='', help="Linux kernel") SimpleOpts.add_option("--disk-image", default='', help="Disk image") SimpleOpts.add_option("--second_disk", default='', help="The second disk image to mount (/dev/hdb)") SimpleOpts.add_option("--checkpoint-dir", default='', help="Checkpoint home directory") SimpleOpts.add_option("--no_host_parallel", default=False, action="store_true", help="Do NOT run gem5 on multiple host threads "\ "(kvm only)") # FIXME: Understand what this does SimpleOpts.add_option("--enable_tuntap", action='store_true',
class SimSystem(LinuxX86System): SimpleOpts.add_option( "--no_host_parallel", default=False, action="store_true", help="Do NOT run gem5 on multiple host threads (kvm only)") SimpleOpts.add_option("--cpus", default=2, type="int", help="Number of CPUs in the system") def __init__(self, opts, no_kvm=False): super(SimSystem, self).__init__() self._opts = opts self._no_kvm = no_kvm self._host_parallel = (not self._opts.no_host_parallel) & (not no_kvm) # Set up the clock domain and the voltage domain self.clk_domain = SrcClockDomain() self.clk_domain.clock = '3GHz' self.clk_domain.voltage_domain = VoltageDomain() # For x86, there is an I/O gap from 3GB to 4GB. # We can have at most 3GB of memory unless we do something special # to account for this I/O gap. For simplicity, this is omitted. mem_size = '2048MB' self.mem_ranges = [ AddrRange(mem_size), AddrRange(0xC0000000, size=0x100000), # For I/0 ] # Create the main memory bus # This connects to main memory self.membus = SystemXBar(width=64) self.membus.badaddr_responder = BadAddr() self.membus.default = self.membus.badaddr_responder.pio # Set up the system port for functional access from the simulator self.system_port = self.membus.slave # This will initialize most of the x86-specific system parameters # This includes things like the I/O, multiprocessor support, BIOS... x86_mp.init_fs(self, self.membus, self._opts.cpus) #x86.init_fs(self, self.membus) # Change this path to point to the kernel you want to use # Kernel from http://www.m5sim.org/dist/current/x86/x86-system.tar.bz2 self.kernel = 'linux/vmlinux' # Options specified on the kernel command line boot_options = [ 'earlyprintk=ttyS0', 'console=ttyS0', 'lpj=7999923', 'root=/dev/hda1' ] self.boot_osflags = ' '.join(boot_options) # Replace these paths with the path to your disk images. # The first disk is the root disk. The second could be used for swap # or anything else. # Disks from http://www.m5sim.org/dist/current/x86/x86-system.tar.bz2 self.setDiskImage('ubuntu-1604.X86.img') # Create the CPU for our system. self.createCPU() # Create the cache heirarchy for the system. self.createCacheHierarchy() # Create the memory controller for the sytem self.createMemoryControllers() # Set up the interrupt controllers for the system (x86 specific) self.setupInterrupts() if self._host_parallel: # To get the KVM CPUs to run on different host CPUs # Specify a different event queue for each CPU for i, cpu in enumerate(self.cpu): for obj in cpu.descendants(): obj.eventq_index = 0 cpu.eventq_index = i + 1 def getHostParallel(self): return self._host_parallel def createCPU(self): """ Create a CPU for the system """ # This defaults to one simple atomic CPU. Using other CPU models # and using timing memory is possible as well. # Also, changing this to using multiple CPUs is also possible # Note: If you use multiple CPUs, then the BIOS config needs to be # updated as well. if self._no_kvm: self.cpu = [ AtomicSimpleCPU(cpu_id=i, switched_out=False) for i in range(self._opts.cpus) ] self.mem_mode = 'atomic' else: # Note KVM needs a VM and atomic_noncaching self.cpu = [X86KvmCPU(cpu_id=i) for i in range(self._opts.cpus)] self.kvm_vm = KvmVM() self.mem_mode = 'atomic_noncaching' self.atomicCpu = [ AtomicSimpleCPU(cpu_id=i, switched_out=True) for i in range(self._opts.cpus) ] for cpu in self.atomicCpu: cpu.createThreads() self.timingCpu = [ DerivO3CPU(cpu_id=i, switched_out=True) for i in range(self._opts.cpus) ] for cpu in self.timingCpu: cpu.createThreads() for cpu in self.cpu: cpu.createThreads() def switchCpus(self, old, new): assert (new[0].switchedOut()) m5.switchCpus(self, zip(old, new)) def setDiskImage(self, img_path): """ Set the disk image @param img_path path on the host to the image file for the disk """ # Can have up to two master disk images. # This can be enabled with up to 4 images if using master-slave pairs disk0 = CowDisk(img_path) self.pc.south_bridge.ide.disks = [disk0] def createCacheHierarchy(self): """ Create a simple cache heirarchy with the caches""" # Create an L3 cache (with crossbar) self.l3bus = L2XBar(width=64, snoop_filter=SnoopFilter(max_capacity='32MB')) for cpu in self.cpu: # Create a memory bus, a coherent crossbar, in this case cpu.l2bus = L2XBar() # Create an L1 instruction and data cache cpu.icache = L1ICache(self._opts) cpu.dcache = L1DCache(self._opts) cpu.mmucache = MMUCache() # Connect the instruction and data caches to the CPU cpu.icache.connectCPU(cpu) cpu.dcache.connectCPU(cpu) cpu.mmucache.connectCPU(cpu) # Hook the CPU ports up to the l2bus cpu.icache.connectBus(cpu.l2bus) cpu.dcache.connectBus(cpu.l2bus) cpu.mmucache.connectBus(cpu.l2bus) # Create an L2 cache and connect it to the l2bus cpu.l2cache = L2Cache(self._opts) cpu.l2cache.connectCPUSideBus(cpu.l2bus) # Connect the L2 cache to the L3 bus cpu.l2cache.connectMemSideBus(self.l3bus) self.l3cache = L3Cache(self._opts) #self.l3cache = L3Cache(self._opts) self.l3cache.connectCPUSideBus(self.l3bus) # Connect the L3 cache to the membus self.l3cache.connectMemSideBus(self.membus) def createMemoryControllers(self): """ Create the memory controller for the system """ # Just create a controller for the first range, assuming the memory # size is < 3GB this will work. If it's > 3GB or if you want to use # mulitple or interleaved memory controllers then this should be # updated accordingly self.mem_cntrl = DDR3_1600_8x8(range=self.mem_ranges[0], port=self.membus.master) def setupInterrupts(self): """ Create the interrupt controller for the CPU """ for cpu in self.cpu: # create the interrupt controller CPU and connect to the membus cpu.createInterruptController() # For x86 only, connect interrupts to the memory # Note: these are directly connected to the memory bus and # not cached cpu.interrupts[0].pio = self.membus.master cpu.interrupts[0].int_master = self.membus.slave cpu.interrupts[0].int_slave = self.membus.master
import sys import m5 from m5.objects import * sys.path.append('configs/common/') # For the next line... import SimpleOpts from system import MySystem SimpleOpts.add_option("--script", default='', help="Script to execute in the simulated system") if __name__ == "__m5_main__": (opts, args) = SimpleOpts.parse_args() # create the system we are going to simulate system = MySystem(opts) # Read in the script file passed in via an option. # This file gets read and executed by the simulated system after boot. # Note: The disk image needs to be configured to do this. system.readfile = opts.script # set up the root SimObject and start the simulation root = Root(full_system = True, system = system) # instantiate all of the objects we've created above m5.instantiate() # Keep running until we are done.
""" import sys import time import m5 import m5.ticks from m5.objects import * sys.path.append('configs/common/') # For the next line... import SimpleOpts from system import MySystem SimpleOpts.add_option("--script", default='', help="Script to execute in the simulated system") SimpleOpts.add_option("--kernel", default='', help="Linux kernel") SimpleOpts.add_option("--disk-image", default='', help="Disk image") if __name__ == "__m5_main__": (opts, args) = SimpleOpts.parse_args() # create the system we are going to simulate system = MySystem(opts) # For workitems to work correctly # This will cause the simulator to exit simulation when the first work # item is reached and when the first work item is finished. system.work_begin_exit_count = 1 system.work_end_exit_count = 1