low_power_sweep.py revision 13774
112469Sglenn.bergmans@arm.com# Copyright (c) 2014-2015, 2017 ARM Limited 212469Sglenn.bergmans@arm.com# All rights reserved. 312469Sglenn.bergmans@arm.com# 412469Sglenn.bergmans@arm.com# The license below extends only to copyright in the software and shall 512469Sglenn.bergmans@arm.com# not be construed as granting a license to any other intellectual 612469Sglenn.bergmans@arm.com# property including but not limited to intellectual property relating 712469Sglenn.bergmans@arm.com# to a hardware implementation of the functionality of the software 812469Sglenn.bergmans@arm.com# licensed hereunder. You may use the software subject to the license 912469Sglenn.bergmans@arm.com# terms below provided that you ensure that this notice is replicated 1012469Sglenn.bergmans@arm.com# unmodified and in its entirety in all distributions of the software, 1112469Sglenn.bergmans@arm.com# modified or unmodified, in source code or in binary form. 1212469Sglenn.bergmans@arm.com# 1312469Sglenn.bergmans@arm.com# Redistribution and use in source and binary forms, with or without 1412469Sglenn.bergmans@arm.com# modification, are permitted provided that the following conditions are 1512469Sglenn.bergmans@arm.com# met: redistributions of source code must retain the above copyright 1612469Sglenn.bergmans@arm.com# notice, this list of conditions and the following disclaimer; 1712469Sglenn.bergmans@arm.com# redistributions in binary form must reproduce the above copyright 1812469Sglenn.bergmans@arm.com# notice, this list of conditions and the following disclaimer in the 1912469Sglenn.bergmans@arm.com# documentation and/or other materials provided with the distribution; 2012469Sglenn.bergmans@arm.com# neither the name of the copyright holders nor the names of its 2112469Sglenn.bergmans@arm.com# contributors may be used to endorse or promote products derived from 2212469Sglenn.bergmans@arm.com# this software without specific prior written permission. 2312469Sglenn.bergmans@arm.com# 2412469Sglenn.bergmans@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2512469Sglenn.bergmans@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2612469Sglenn.bergmans@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2712469Sglenn.bergmans@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2812469Sglenn.bergmans@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2912469Sglenn.bergmans@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3012469Sglenn.bergmans@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3112469Sglenn.bergmans@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3212469Sglenn.bergmans@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3312469Sglenn.bergmans@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3412469Sglenn.bergmans@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3512469Sglenn.bergmans@arm.com# 3612469Sglenn.bergmans@arm.com# Authors: Radhika Jagtap 3712469Sglenn.bergmans@arm.com# Andreas Hansson 3813719Sandreas.sandberg@arm.com 3913719Sandreas.sandberg@arm.comfrom __future__ import print_function 4013719Sandreas.sandberg@arm.comfrom __future__ import absolute_import 4113719Sandreas.sandberg@arm.com 4212469Sglenn.bergmans@arm.comimport argparse 4312469Sglenn.bergmans@arm.com 4412469Sglenn.bergmans@arm.comimport m5 4512469Sglenn.bergmans@arm.comfrom m5.objects import * 4612469Sglenn.bergmans@arm.comfrom m5.util import addToPath 4712469Sglenn.bergmans@arm.comfrom m5.stats import periodicStatDump 4812469Sglenn.bergmans@arm.com 4912469Sglenn.bergmans@arm.comaddToPath('../') 5012469Sglenn.bergmans@arm.com 5112469Sglenn.bergmans@arm.comfrom common import MemConfig 5212469Sglenn.bergmans@arm.com 5312469Sglenn.bergmans@arm.com# This script aims at triggering low power state transitions in the DRAM 5412469Sglenn.bergmans@arm.com# controller. The traffic generator is used in DRAM mode and traffic 5512469Sglenn.bergmans@arm.com# states target a different levels of bank utilization and strides. 5612469Sglenn.bergmans@arm.com# At the end after sweeping through bank utilization and strides, we go 5712469Sglenn.bergmans@arm.com# through an idle state with no requests to enforce self-refresh. 5812469Sglenn.bergmans@arm.com 5912469Sglenn.bergmans@arm.comparser = argparse.ArgumentParser( 6012469Sglenn.bergmans@arm.com formatter_class=argparse.ArgumentDefaultsHelpFormatter) 6112469Sglenn.bergmans@arm.com 6212469Sglenn.bergmans@arm.com# Use a single-channel DDR4-2400 in 16x4 configuration by default 6312469Sglenn.bergmans@arm.comparser.add_argument("--mem-type", default="DDR4_2400_16x4", 6412469Sglenn.bergmans@arm.com choices=MemConfig.mem_names(), 6512469Sglenn.bergmans@arm.com help = "type of memory to use") 6612469Sglenn.bergmans@arm.com 6712469Sglenn.bergmans@arm.comparser.add_argument("--mem-ranks", "-r", type=int, default=1, 6812469Sglenn.bergmans@arm.com help = "Number of ranks to iterate across") 6912469Sglenn.bergmans@arm.com 7012469Sglenn.bergmans@arm.comparser.add_argument("--page-policy", "-p", 7112469Sglenn.bergmans@arm.com choices=["close_adaptive", "open_adaptive"], 7212469Sglenn.bergmans@arm.com default="close_adaptive", help="controller page policy") 7312469Sglenn.bergmans@arm.com 7412469Sglenn.bergmans@arm.comparser.add_argument("--itt-list", "-t", default="1 20 100", 7512469Sglenn.bergmans@arm.com help="a list of multipliers for the max value of itt, " \ 7612469Sglenn.bergmans@arm.com "e.g. \"1 20 100\"") 7712469Sglenn.bergmans@arm.com 7812469Sglenn.bergmans@arm.comparser.add_argument("--rd-perc", type=int, default=100, 7912469Sglenn.bergmans@arm.com help = "Percentage of read commands") 8012469Sglenn.bergmans@arm.com 8112469Sglenn.bergmans@arm.comparser.add_argument("--addr-map", type=int, default=1, 8212469Sglenn.bergmans@arm.com help = "0: RoCoRaBaCh; 1: RoRaBaCoCh/RoRaBaChCo") 8312469Sglenn.bergmans@arm.com 8412469Sglenn.bergmans@arm.comparser.add_argument("--idle-end", type=int, default=50000000, 8512469Sglenn.bergmans@arm.com help = "time in ps of an idle period at the end ") 8612469Sglenn.bergmans@arm.com 8712469Sglenn.bergmans@arm.comargs = parser.parse_args() 8812469Sglenn.bergmans@arm.com 8912469Sglenn.bergmans@arm.com# Start with the system itself, using a multi-layer 2.0 GHz 9012469Sglenn.bergmans@arm.com# crossbar, delivering 64 bytes / 3 cycles (one header cycle) 9112469Sglenn.bergmans@arm.com# which amounts to 42.7 GByte/s per layer and thus per port. 9212469Sglenn.bergmans@arm.comsystem = System(membus = IOXBar(width = 32)) 9312469Sglenn.bergmans@arm.comsystem.clk_domain = SrcClockDomain(clock = '2.0GHz', 9412469Sglenn.bergmans@arm.com voltage_domain = 9512469Sglenn.bergmans@arm.com VoltageDomain(voltage = '1V')) 9612469Sglenn.bergmans@arm.com 9712469Sglenn.bergmans@arm.com# We are fine with 256 MB memory for now. 9812469Sglenn.bergmans@arm.commem_range = AddrRange('256MB') 9912469Sglenn.bergmans@arm.com# Start address is 0 10012469Sglenn.bergmans@arm.comsystem.mem_ranges = [mem_range] 10112469Sglenn.bergmans@arm.com 10212469Sglenn.bergmans@arm.com# Do not worry about reserving space for the backing store 10312469Sglenn.bergmans@arm.comsystem.mmap_using_noreserve = True 10412469Sglenn.bergmans@arm.com 10512469Sglenn.bergmans@arm.com# Force a single channel to match the assumptions in the DRAM traffic 10612469Sglenn.bergmans@arm.com# generator 10712469Sglenn.bergmans@arm.comargs.mem_channels = 1 10812469Sglenn.bergmans@arm.comargs.external_memory_system = 0 10912469Sglenn.bergmans@arm.comargs.tlm_memory = 0 11012469Sglenn.bergmans@arm.comargs.elastic_trace_en = 0 11112469Sglenn.bergmans@arm.comMemConfig.config_mem(args, system) 11212469Sglenn.bergmans@arm.com 11312469Sglenn.bergmans@arm.com# Sanity check for memory controller class. 11412469Sglenn.bergmans@arm.comif not isinstance(system.mem_ctrls[0], m5.objects.DRAMCtrl): 11512469Sglenn.bergmans@arm.com fatal("This script assumes the memory is a DRAMCtrl subclass") 11612469Sglenn.bergmans@arm.com 11712469Sglenn.bergmans@arm.com# There is no point slowing things down by saving any data. 11812469Sglenn.bergmans@arm.comsystem.mem_ctrls[0].null = True 11912469Sglenn.bergmans@arm.com 12012469Sglenn.bergmans@arm.com# Set the address mapping based on input argument 12112469Sglenn.bergmans@arm.com# Default to RoRaBaCoCh 12212469Sglenn.bergmans@arm.comif args.addr_map == 0: 12312469Sglenn.bergmans@arm.com system.mem_ctrls[0].addr_mapping = "RoCoRaBaCh" 12412469Sglenn.bergmans@arm.comelif args.addr_map == 1: 12512469Sglenn.bergmans@arm.com system.mem_ctrls[0].addr_mapping = "RoRaBaCoCh" 12612469Sglenn.bergmans@arm.comelse: 12712469Sglenn.bergmans@arm.com fatal("Did not specify a valid address map argument") 12812469Sglenn.bergmans@arm.com 12912469Sglenn.bergmans@arm.comsystem.mem_ctrls[0].page_policy = args.page_policy 13012469Sglenn.bergmans@arm.com 13112469Sglenn.bergmans@arm.com# We create a traffic generator state for each param combination we want to 13212469Sglenn.bergmans@arm.com# test. Each traffic generator state is specified in the config file and the 13312469Sglenn.bergmans@arm.com# generator remains in the state for specific period. This period is 0.25 ms. 13412469Sglenn.bergmans@arm.com# Stats are dumped and reset at the state transition. 13512469Sglenn.bergmans@arm.comperiod = 250000000 13612469Sglenn.bergmans@arm.com 13712469Sglenn.bergmans@arm.com# We specify the states in a config file input to the traffic generator. 13812469Sglenn.bergmans@arm.comcfg_file_name = "configs/dram/lowp_sweep.cfg" 13912469Sglenn.bergmans@arm.comcfg_file = open(cfg_file_name, 'w') 14012469Sglenn.bergmans@arm.com 14112469Sglenn.bergmans@arm.com# Get the number of banks 14212469Sglenn.bergmans@arm.comnbr_banks = int(system.mem_ctrls[0].banks_per_rank.value) 14312469Sglenn.bergmans@arm.com 14412469Sglenn.bergmans@arm.com# determine the burst size in bytes 14512469Sglenn.bergmans@arm.comburst_size = int((system.mem_ctrls[0].devices_per_rank.value * 14612469Sglenn.bergmans@arm.com system.mem_ctrls[0].device_bus_width.value * 14712469Sglenn.bergmans@arm.com system.mem_ctrls[0].burst_length.value) / 8) 14812469Sglenn.bergmans@arm.com 14912469Sglenn.bergmans@arm.com# next, get the page size in bytes (the rowbuffer size is already in bytes) 15012469Sglenn.bergmans@arm.compage_size = system.mem_ctrls[0].devices_per_rank.value * \ 15112469Sglenn.bergmans@arm.com system.mem_ctrls[0].device_rowbuffer_size.value 15212469Sglenn.bergmans@arm.com 15312469Sglenn.bergmans@arm.com# Inter-request delay should be such that we can hit as many transitions 15412469Sglenn.bergmans@arm.com# to/from low power states as possible to. We provide a min and max itt to the 15512469Sglenn.bergmans@arm.com# traffic generator and it randomises in the range. The parameter is in 15612469Sglenn.bergmans@arm.com# seconds and we need it in ticks (ps). 15712469Sglenn.bergmans@arm.comitt_min = system.mem_ctrls[0].tBURST.value * 1000000000000 15812469Sglenn.bergmans@arm.com 15912469Sglenn.bergmans@arm.com#The itt value when set to (tRAS + tRP + tCK) covers the case where 16012469Sglenn.bergmans@arm.com# a read command is delayed beyond the delay from ACT to PRE_PDN entry of the 16112469Sglenn.bergmans@arm.com# previous command. For write command followed by precharge, this delay 16212469Sglenn.bergmans@arm.com# between a write and power down entry will be tRCD + tCL + tWR + tRP + tCK. 16312469Sglenn.bergmans@arm.com# As we use this delay as a unit and create multiples of it as bigger delays 16412469Sglenn.bergmans@arm.com# for the sweep, this parameter works for reads, writes and mix of them. 16512469Sglenn.bergmans@arm.compd_entry_time = (system.mem_ctrls[0].tRAS.value + 16612469Sglenn.bergmans@arm.com system.mem_ctrls[0].tRP.value + 16712469Sglenn.bergmans@arm.com system.mem_ctrls[0].tCK.value) * 1000000000000 16812469Sglenn.bergmans@arm.com 16912469Sglenn.bergmans@arm.com# We sweep itt max using the multipliers specified by the user. 17012469Sglenn.bergmans@arm.comitt_max_str = args.itt_list.strip().split() 17112469Sglenn.bergmans@arm.comitt_max_multiples = [ int(x) for x in itt_max_str ] 17212469Sglenn.bergmans@arm.comif len(itt_max_multiples) == 0: 17312469Sglenn.bergmans@arm.com fatal("String for itt-max-list detected empty\n") 17412469Sglenn.bergmans@arm.com 17512469Sglenn.bergmans@arm.comitt_max_values = [ pd_entry_time * m for m in itt_max_multiples ] 17612469Sglenn.bergmans@arm.com 17712469Sglenn.bergmans@arm.com# Generate request addresses in the entire range, assume we start at 0 17812469Sglenn.bergmans@arm.commax_addr = mem_range.end 17912469Sglenn.bergmans@arm.com 18012469Sglenn.bergmans@arm.com# For max stride, use min of the page size and 512 bytes as that should be 18112469Sglenn.bergmans@arm.com# more than enough 18212469Sglenn.bergmans@arm.commax_stride = min(512, page_size) 18312469Sglenn.bergmans@arm.commid_stride = 4 * burst_size 18412469Sglenn.bergmans@arm.comstride_values = [burst_size, mid_stride, max_stride] 18512469Sglenn.bergmans@arm.com 18612469Sglenn.bergmans@arm.com# be selective about bank utilization instead of going from 1 to the number of 18712469Sglenn.bergmans@arm.com# banks 18812469Sglenn.bergmans@arm.combank_util_values = [1, int(nbr_banks/2), nbr_banks] 18912469Sglenn.bergmans@arm.com 19012469Sglenn.bergmans@arm.com# Next we create the config file, but first a comment 19112469Sglenn.bergmans@arm.comcfg_file.write("""# STATE state# period mode=DRAM 19212469Sglenn.bergmans@arm.com# read_percent start_addr end_addr req_size min_itt max_itt data_limit 19312469Sglenn.bergmans@arm.com# stride_size page_size #banks #banks_util addr_map #ranks\n""") 19412469Sglenn.bergmans@arm.com 19512469Sglenn.bergmans@arm.comnxt_state = 0 19612469Sglenn.bergmans@arm.comfor itt_max in itt_max_values: 19712469Sglenn.bergmans@arm.com for bank in bank_util_values: 19812469Sglenn.bergmans@arm.com for stride_size in stride_values: 19912469Sglenn.bergmans@arm.com cfg_file.write("STATE %d %d %s %d 0 %d %d " 20012469Sglenn.bergmans@arm.com "%d %d %d %d %d %d %d %d %d\n" % 20112469Sglenn.bergmans@arm.com (nxt_state, period, "DRAM", args.rd_perc, max_addr, 20212469Sglenn.bergmans@arm.com burst_size, itt_min, itt_max, 0, stride_size, 20312469Sglenn.bergmans@arm.com page_size, nbr_banks, bank, args.addr_map, 20412469Sglenn.bergmans@arm.com args.mem_ranks)) 20512469Sglenn.bergmans@arm.com nxt_state = nxt_state + 1 20612469Sglenn.bergmans@arm.com 20712469Sglenn.bergmans@arm.com# State for idle period 20812469Sglenn.bergmans@arm.comidle_period = args.idle_end 20912469Sglenn.bergmans@arm.comcfg_file.write("STATE %d %d IDLE\n" % (nxt_state, idle_period)) 21012469Sglenn.bergmans@arm.com 21112469Sglenn.bergmans@arm.com# Init state is state 0 21212469Sglenn.bergmans@arm.comcfg_file.write("INIT 0\n") 21312469Sglenn.bergmans@arm.com 21412469Sglenn.bergmans@arm.com# Go through the states one by one 21512469Sglenn.bergmans@arm.comfor state in range(1, nxt_state + 1): 21612469Sglenn.bergmans@arm.com cfg_file.write("TRANSITION %d %d 1\n" % (state - 1, state)) 21712469Sglenn.bergmans@arm.com 21812469Sglenn.bergmans@arm.com# Transition from last state to itself to not break the probability math 21912469Sglenn.bergmans@arm.comcfg_file.write("TRANSITION %d %d 1\n" % (nxt_state, nxt_state)) 22012469Sglenn.bergmans@arm.comcfg_file.close() 22112469Sglenn.bergmans@arm.com 22212469Sglenn.bergmans@arm.com# create a traffic generator, and point it to the file we just created 22312469Sglenn.bergmans@arm.comsystem.tgen = TrafficGen(config_file = cfg_file_name) 22412469Sglenn.bergmans@arm.com 22512469Sglenn.bergmans@arm.com# add a communication monitor 22612469Sglenn.bergmans@arm.comsystem.monitor = CommMonitor() 22712469Sglenn.bergmans@arm.com 22812469Sglenn.bergmans@arm.com# connect the traffic generator to the bus via a communication monitor 22912469Sglenn.bergmans@arm.comsystem.tgen.port = system.monitor.slave 23012469Sglenn.bergmans@arm.comsystem.monitor.master = system.membus.slave 23112469Sglenn.bergmans@arm.com 23212469Sglenn.bergmans@arm.com# connect the system port even if it is not used in this example 23312469Sglenn.bergmans@arm.comsystem.system_port = system.membus.slave 23412469Sglenn.bergmans@arm.com 23512469Sglenn.bergmans@arm.com# every period, dump and reset all stats 23612469Sglenn.bergmans@arm.comperiodicStatDump(period) 23712469Sglenn.bergmans@arm.com 23812469Sglenn.bergmans@arm.comroot = Root(full_system = False, system = system) 23912469Sglenn.bergmans@arm.comroot.system.mem_mode = 'timing' 24012469Sglenn.bergmans@arm.com 24112469Sglenn.bergmans@arm.comm5.instantiate() 24212469Sglenn.bergmans@arm.com 24312469Sglenn.bergmans@arm.com# Simulate for exactly as long as it takes to go through all the states 24412469Sglenn.bergmans@arm.com# This is why sim exists. 24512469Sglenn.bergmans@arm.comm5.simulate(nxt_state * period + idle_period) 24612469Sglenn.bergmans@arm.comprint("--- Done DRAM low power sweep ---") 24712469Sglenn.bergmans@arm.comprint("Fixed params - ") 24812469Sglenn.bergmans@arm.comprint("\tburst: %d, banks: %d, max stride: %d, itt min: %s ns" % \ 24912469Sglenn.bergmans@arm.com (burst_size, nbr_banks, max_stride, itt_min)) 25012469Sglenn.bergmans@arm.comprint("Swept params - ") 25112469Sglenn.bergmans@arm.comprint("\titt max multiples input:", itt_max_multiples) 25212469Sglenn.bergmans@arm.comprint("\titt max values", itt_max_values) 25312469Sglenn.bergmans@arm.comprint("\tbank utilization values", bank_util_values) 25412469Sglenn.bergmans@arm.comprint("\tstride values:", stride_values) 25512469Sglenn.bergmans@arm.comprint("Traffic gen config file:", cfg_file_name) 25612469Sglenn.bergmans@arm.com