def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): cpu_config = [ CpuConfig.get("minor"), devices.L1I, devices.L1D, devices.WalkCache, devices.L2 ] super(LittleCluster, self).__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config)
def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): cpu_config = [ CpuConfig.get("arm_detailed"), devices.L1I, devices.L1D, devices.WalkCache, devices.L2 ] super(BigCluster, self).__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config)
def getCPUClass(cpu_type): """Returns the required cpu class and the mode of operation.""" cls = CpuConfig.get(cpu_type) return cls, cls.memory_mode()
def main(): parser = argparse.ArgumentParser( description="Generic ARM big.LITTLE configuration") parser.add_argument("--restore-from", type=str, default=None, help="Restore from checkpoint") parser.add_argument("--dtb", type=str, default=default_dtb, help="DTB file to load") parser.add_argument("--kernel", type=str, default=default_kernel, help="Linux kernel") parser.add_argument("--disk", action="append", type=str, default=[], help="Disks to instantiate") parser.add_argument("--bootscript", type=str, default=default_rcs, help="Linux bootscript") parser.add_argument("--atomic", action="store_true", default=False, help="Use atomic CPUs") parser.add_argument("--kernel-init", type=str, default="/sbin/init", help="Override init") parser.add_argument("--big-cpus", type=int, default=1, help="Number of big CPUs to instantiate") parser.add_argument("--little-cpus", type=int, default=1, help="Number of little CPUs to instantiate") parser.add_argument("--caches", action="store_true", default=False, help="Instantiate caches") parser.add_argument("--last-cache-level", type=int, default=2, help="Last level of caches (e.g. 3 for L3)") parser.add_argument("--big-cpu-clock", type=str, default="2GHz", help="Big CPU clock frequency") parser.add_argument("--little-cpu-clock", type=str, default="1GHz", help="Little CPU clock frequency") m5.ticks.fixGlobalFrequency() options = parser.parse_args() if options.atomic: cpu_config = { 'cpu' : AtomicSimpleCPU } big_cpu_config, little_cpu_config = cpu_config, cpu_config else: big_cpu_config = { 'cpu' : CpuConfig.get("arm_detailed"), 'l1i' : devices.L1I, 'l1d' : devices.L1D, 'wcache' : devices.WalkCache, 'l2' : devices.L2 } little_cpu_config = { 'cpu' : MinorCPU, 'l1i' : devices.L1I, 'l1d' : devices.L1D, 'wcache' : devices.WalkCache, 'l2' : devices.L2 } big_cpu_class = big_cpu_config['cpu'] little_cpu_class = little_cpu_config['cpu'] kernel_cmd = [ "earlyprintk=pl011,0x1c090000", "console=ttyAMA0", "lpj=19988480", "norandmaps", "loglevel=8", "mem=%s" % default_mem_size, "root=/dev/vda1", "rw", "init=%s" % options.kernel_init, "vmalloc=768MB", ] root = Root(full_system=True) assert big_cpu_class.memory_mode() == little_cpu_class.memory_mode() disks = default_disk if len(options.disk) == 0 else options.disk system = createSystem(options.kernel, big_cpu_class.memory_mode(), options.bootscript, disks=disks) root.system = system system.boot_osflags = " ".join(kernel_cmd) # big cluster if options.big_cpus > 0: system.bigCluster = CpuCluster() system.bigCluster.addCPUs(big_cpu_config, options.big_cpus, options.big_cpu_clock) # LITTLE cluster if options.little_cpus > 0: system.littleCluster = CpuCluster() system.littleCluster.addCPUs(little_cpu_config, options.little_cpus, options.little_cpu_clock) # add caches if options.caches: cluster_mem_bus = addCaches(system, options.last_cache_level) else: if big_cpu_class.require_caches(): m5.util.panic("CPU model %s requires caches" % str(big_cpu_class)) if little_cpu_class.require_caches(): m5.util.panic("CPU model %s requires caches" % str(little_cpu_class)) cluster_mem_bus = system.membus # connect each cluster to the memory hierarchy for cluster in system._clusters: cluster.connectMemSide(cluster_mem_bus) # Linux device tree system.dtb_filename = SysPaths.binary(options.dtb) # Get and load from the chkpt or simpoint checkpoint if options.restore_from is not None: m5.instantiate(options.restore_from) else: m5.instantiate() # start simulation (and drop checkpoints when requested) while True: event = m5.simulate() exit_msg = event.getCause() if exit_msg == "checkpoint": print "Dropping checkpoint at tick %d" % m5.curTick() cpt_dir = os.path.join(m5.options.outdir, "cpt.%d" % m5.curTick()) m5.checkpoint(os.path.join(cpt_dir)) print "Checkpoint done." else: print exit_msg, " @ ", m5.curTick() break sys.exit(event.getCode())
def createCorePE(root, options, no, cmdline, memPE, l1size=None, l2size=None, spmsize='8MB'): CPUClass = CpuConfig.get(options.cpu_type) pe = createPE(root=root, options=options, no=no, mem=False, l1size=l1size, l2size=l2size, spmsize=spmsize, memPE=memPE) pe.readfile = "/dev/stdin" pe.cpu = CPUClass() pe.cpu.cpu_id = 0 pe.cpu.clk_domain = root.cpu_clk_domain pe.dtu.icache_slave_port = pe.cpu.icache_port pe.dtu.dcache_slave_port = pe.cpu.dcache_port if "kernel" in cmdline: pe.mod_offset = mod_offset pe.mod_size = mod_size # Command line pe.kernel = cmdline.split(' ')[0] pe.boot_osflags = cmdline print "PE%02d: %s" % (no, cmdline) print ' core =%s x86' % (options.cpu_type) try: print ' L1cache=%d KiB' % (pe.dtu.l1cache.size.value / 1024) if not l2size is None: print ' L2cache=%d KiB' % (pe.dtu.l2cache.size.value / 1024) except: print ' memsize=%d KiB' % (int(pe.spm.range.end + 1) / 1024) print ' bufsize=%d B, blocksize=%d B, count=%d' % \ (pe.dtu.buf_size.value, pe.dtu.block_size.value, pe.dtu.buf_count) debug.setRemoteGDBPort(options.remote_gdb_port) # if specified, let this PE wait for GDB if options.pausepe == no: print ' waiting for GDB' # = 0, because for us, it's always the first context pe.rgdb_wait = 0 print # connect the IO space via bridge to the root NoC pe.bridge = Bridge(delay='50ns') pe.bridge.master = root.noc.slave pe.bridge.slave = pe.xbar.master pe.bridge.ranges = \ [ AddrRange(IO_address_space_base, interrupts_address_space_base - 1) ] pe.cpu.createInterruptController() pe.cpu.interrupts.pio = pe.xbar.master pe.cpu.interrupts.int_slave = pe.dtu.irq_master_port pe.cpu.interrupts.int_master = pe.xbar.slave pe.cpu.itb.walker.port = pe.xbar.slave pe.cpu.dtb.walker.port = pe.xbar.slave return pe
def createPE(root, options, no, mem, l1size, l2size, spmsize, memPE): if not spmsize is None: if convert.toMemorySize(spmsize) > pe_size: print("PE%02d is too large. Maximum allowed SPM size: %dMB" % (no, pe_size / (1024 * 1024))) fatal("PE%02d is too large. Maximum allowed SPM size: %dMB" % (no, pe_size / (1024 * 1024))) CPUClass = CpuConfig.get(options.cpu_type) # each PE is represented by it's own subsystem if mem: pe = MemSystem(mem_mode=CPUClass.memory_mode()) else: pe = M3X86System(mem_mode=CPUClass.memory_mode()) pe.core_id = no setattr(root, 'pe%02d' % no, pe) # TODO set latencies pe.xbar = NoncoherentXBar(forward_latency=0, frontend_latency=0, response_latency=1, width=16) pe.xbar.clk_domain = root.cpu_clk_domain pe.pseudo_mem_ops = False pe.mmap_using_noreserve = True pe.dtu = Dtu() pe.dtu.core_id = no pe.dtu.clk_domain = root.cpu_clk_domain pe.dtu.regfile_base_addr = 0x5C0000000 pe.dtu.rw_barrier = 0x5B0000000 pe.dtu.max_noc_packet_size = "4kB" pe.dtu.num_endpoints = 16 pe.dtu.icache_master_port = pe.xbar.slave pe.dtu.dcache_master_port = pe.xbar.slave pe.dtu.noc_master_port = root.noc.slave pe.dtu.noc_slave_port = root.noc.master if not mem: if not l1size is None: pe.dtu.l1cache = L1Cache(size=l1size) pe.dtu.l1cache.forward_snoops = False pe.dtu.l1cache.addr_ranges = [AddrRange(0, 0x1000000000000000 - 1)] pe.dtu.l1cache.cpu_side = pe.xbar.master if not l2size is None: pe.dtu.l2cache = L2Cache(size=l2size) pe.dtu.l2cache.forward_snoops = False pe.dtu.l2cache.addr_ranges = [ AddrRange(0, 0x1000000000000000 - 1) ] pe.dtu.l2cache.cpu_side = pe.dtu.l1cache.mem_side pe.dtu.l2cache.mem_side = pe.dtu.cache_mem_slave_port else: pe.dtu.l1cache.mem_side = pe.dtu.cache_mem_slave_port # don't check whether the kernel is in memory because a PE does not have memory in this # case, but just a cache that is connected to a different PE pe.kernel_addr_check = False else: pe.spm = Scratchpad(in_addr_map="true") pe.spm.cpu_port = pe.xbar.master pe.spm.range = spmsize pe.memory_pe = memPE pe.memory_offset = pe_offset + (pe_size * no) pe.memory_size = pe_size else: pe.dtu.buf_count = 8 # for memory PEs or PEs with SPM, we do not need a buffer. for the sake of an easy implementation # we just make the buffer very large and the block size as well, so that we can read a packet # from SPM/DRAM into the buffer and send it from there. Since that costs no simulated time, # it is the same as having no buffer. if mem or l1size is None: pe.dtu.block_size = pe.dtu.max_noc_packet_size pe.dtu.buf_size = pe.dtu.max_noc_packet_size # disable the TLB pe.dtu.tlb_entries = 0 pe.system_port = pe.xbar.slave if not mem: pe.noc_master_port = root.noc.slave return pe
def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): cpu_config = [CpuConfig.get("atomic"), None, None, None, None] super(AtomicCluster, self).__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config)