low_power_sweep.py revision 12267
112267Sradhika.jagtap@arm.com# Copyright (c) 2014-2015, 2017 ARM Limited
212267Sradhika.jagtap@arm.com# All rights reserved.
312267Sradhika.jagtap@arm.com#
412267Sradhika.jagtap@arm.com# The license below extends only to copyright in the software and shall
512267Sradhika.jagtap@arm.com# not be construed as granting a license to any other intellectual
612267Sradhika.jagtap@arm.com# property including but not limited to intellectual property relating
712267Sradhika.jagtap@arm.com# to a hardware implementation of the functionality of the software
812267Sradhika.jagtap@arm.com# licensed hereunder.  You may use the software subject to the license
912267Sradhika.jagtap@arm.com# terms below provided that you ensure that this notice is replicated
1012267Sradhika.jagtap@arm.com# unmodified and in its entirety in all distributions of the software,
1112267Sradhika.jagtap@arm.com# modified or unmodified, in source code or in binary form.
1212267Sradhika.jagtap@arm.com#
1312267Sradhika.jagtap@arm.com# Redistribution and use in source and binary forms, with or without
1412267Sradhika.jagtap@arm.com# modification, are permitted provided that the following conditions are
1512267Sradhika.jagtap@arm.com# met: redistributions of source code must retain the above copyright
1612267Sradhika.jagtap@arm.com# notice, this list of conditions and the following disclaimer;
1712267Sradhika.jagtap@arm.com# redistributions in binary form must reproduce the above copyright
1812267Sradhika.jagtap@arm.com# notice, this list of conditions and the following disclaimer in the
1912267Sradhika.jagtap@arm.com# documentation and/or other materials provided with the distribution;
2012267Sradhika.jagtap@arm.com# neither the name of the copyright holders nor the names of its
2112267Sradhika.jagtap@arm.com# contributors may be used to endorse or promote products derived from
2212267Sradhika.jagtap@arm.com# this software without specific prior written permission.
2312267Sradhika.jagtap@arm.com#
2412267Sradhika.jagtap@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2512267Sradhika.jagtap@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2612267Sradhika.jagtap@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2712267Sradhika.jagtap@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2812267Sradhika.jagtap@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2912267Sradhika.jagtap@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3012267Sradhika.jagtap@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3112267Sradhika.jagtap@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3212267Sradhika.jagtap@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3312267Sradhika.jagtap@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3412267Sradhika.jagtap@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3512267Sradhika.jagtap@arm.com#
3612267Sradhika.jagtap@arm.com# Authors: Radhika Jagtap
3712267Sradhika.jagtap@arm.com#          Andreas Hansson
3812267Sradhika.jagtap@arm.com
3912267Sradhika.jagtap@arm.comimport argparse
4012267Sradhika.jagtap@arm.com
4112267Sradhika.jagtap@arm.comimport m5
4212267Sradhika.jagtap@arm.comfrom m5.objects import *
4312267Sradhika.jagtap@arm.comfrom m5.util import addToPath
4412267Sradhika.jagtap@arm.comfrom m5.stats import periodicStatDump
4512267Sradhika.jagtap@arm.com
4612267Sradhika.jagtap@arm.comaddToPath('../common')
4712267Sradhika.jagtap@arm.comimport MemConfig
4812267Sradhika.jagtap@arm.com
4912267Sradhika.jagtap@arm.com# This script aims at triggering low power state transitions in the DRAM
5012267Sradhika.jagtap@arm.com# controller. The traffic generator is used in DRAM mode and traffic
5112267Sradhika.jagtap@arm.com# states target a different levels of bank utilization and strides.
5212267Sradhika.jagtap@arm.com# At the end after sweeping through bank utilization and strides, we go
5312267Sradhika.jagtap@arm.com# through an idle state with no requests to enforce self-refresh.
5412267Sradhika.jagtap@arm.com
5512267Sradhika.jagtap@arm.comparser = argparse.ArgumentParser(
5612267Sradhika.jagtap@arm.com  formatter_class=argparse.ArgumentDefaultsHelpFormatter)
5712267Sradhika.jagtap@arm.com
5812267Sradhika.jagtap@arm.com# Use a single-channel DDR4-2400 in 16x4 configuration by default
5912267Sradhika.jagtap@arm.comparser.add_argument("--mem-type", default="DDR4_2400_16x4",
6012267Sradhika.jagtap@arm.com                    choices=MemConfig.mem_names(),
6112267Sradhika.jagtap@arm.com                    help = "type of memory to use")
6212267Sradhika.jagtap@arm.com
6312267Sradhika.jagtap@arm.comparser.add_argument("--mem-ranks", "-r", type=int, default=1,
6412267Sradhika.jagtap@arm.com                    help = "Number of ranks to iterate across")
6512267Sradhika.jagtap@arm.com
6612267Sradhika.jagtap@arm.comparser.add_argument("--page-policy", "-p",
6712267Sradhika.jagtap@arm.com                    choices=["close_adaptive", "open_adaptive"],
6812267Sradhika.jagtap@arm.com                    default="close_adaptive", help="controller page policy")
6912267Sradhika.jagtap@arm.com
7012267Sradhika.jagtap@arm.comparser.add_argument("--itt-list", "-t", default="1 20 100",
7112267Sradhika.jagtap@arm.com                    help="a list of multipliers for the max value of itt, " \
7212267Sradhika.jagtap@arm.com                    "e.g. \"1 20 100\"")
7312267Sradhika.jagtap@arm.com
7412267Sradhika.jagtap@arm.comparser.add_argument("--rd-perc", type=int, default=100,
7512267Sradhika.jagtap@arm.com                    help = "Percentage of read commands")
7612267Sradhika.jagtap@arm.com
7712267Sradhika.jagtap@arm.comparser.add_argument("--addr-map", type=int, default=1,
7812267Sradhika.jagtap@arm.com                    help = "0: RoCoRaBaCh; 1: RoRaBaCoCh/RoRaBaChCo")
7912267Sradhika.jagtap@arm.com
8012267Sradhika.jagtap@arm.comparser.add_argument("--idle-end", type=int, default=50000000,
8112267Sradhika.jagtap@arm.com                    help = "time in ps of an idle period at the end ")
8212267Sradhika.jagtap@arm.com
8312267Sradhika.jagtap@arm.comargs = parser.parse_args()
8412267Sradhika.jagtap@arm.com
8512267Sradhika.jagtap@arm.com# Start with the system itself, using a multi-layer 2.0 GHz
8612267Sradhika.jagtap@arm.com# crossbar, delivering 64 bytes / 3 cycles (one header cycle)
8712267Sradhika.jagtap@arm.com# which amounts to 42.7 GByte/s per layer and thus per port.
8812267Sradhika.jagtap@arm.comsystem = System(membus = IOXBar(width = 32))
8912267Sradhika.jagtap@arm.comsystem.clk_domain = SrcClockDomain(clock = '2.0GHz',
9012267Sradhika.jagtap@arm.com                                   voltage_domain =
9112267Sradhika.jagtap@arm.com                                   VoltageDomain(voltage = '1V'))
9212267Sradhika.jagtap@arm.com
9312267Sradhika.jagtap@arm.com# We are fine with 256 MB memory for now.
9412267Sradhika.jagtap@arm.commem_range = AddrRange('256MB')
9512267Sradhika.jagtap@arm.com# Start address is 0
9612267Sradhika.jagtap@arm.comsystem.mem_ranges = [mem_range]
9712267Sradhika.jagtap@arm.com
9812267Sradhika.jagtap@arm.com# Do not worry about reserving space for the backing store
9912267Sradhika.jagtap@arm.comsystem.mmap_using_noreserve = True
10012267Sradhika.jagtap@arm.com
10112267Sradhika.jagtap@arm.com# Force a single channel to match the assumptions in the DRAM traffic
10212267Sradhika.jagtap@arm.com# generator
10312267Sradhika.jagtap@arm.comargs.mem_channels = 1
10412267Sradhika.jagtap@arm.comargs.external_memory_system = 0
10512267Sradhika.jagtap@arm.comargs.tlm_memory = 0
10612267Sradhika.jagtap@arm.comargs.elastic_trace_en = 0
10712267Sradhika.jagtap@arm.comMemConfig.config_mem(args, system)
10812267Sradhika.jagtap@arm.com
10912267Sradhika.jagtap@arm.com# Sanity check for memory controller class.
11012267Sradhika.jagtap@arm.comif not isinstance(system.mem_ctrls[0], m5.objects.DRAMCtrl):
11112267Sradhika.jagtap@arm.com    fatal("This script assumes the memory is a DRAMCtrl subclass")
11212267Sradhika.jagtap@arm.com
11312267Sradhika.jagtap@arm.com# There is no point slowing things down by saving any data.
11412267Sradhika.jagtap@arm.comsystem.mem_ctrls[0].null = True
11512267Sradhika.jagtap@arm.com
11612267Sradhika.jagtap@arm.com# Set the address mapping based on input argument
11712267Sradhika.jagtap@arm.com# Default to RoRaBaCoCh
11812267Sradhika.jagtap@arm.comif args.addr_map == 0:
11912267Sradhika.jagtap@arm.com   system.mem_ctrls[0].addr_mapping = "RoCoRaBaCh"
12012267Sradhika.jagtap@arm.comelif args.addr_map == 1:
12112267Sradhika.jagtap@arm.com   system.mem_ctrls[0].addr_mapping = "RoRaBaCoCh"
12212267Sradhika.jagtap@arm.comelse:
12312267Sradhika.jagtap@arm.com    fatal("Did not specify a valid address map argument")
12412267Sradhika.jagtap@arm.com
12512267Sradhika.jagtap@arm.comsystem.mem_ctrls[0].page_policy = args.page_policy
12612267Sradhika.jagtap@arm.com
12712267Sradhika.jagtap@arm.com# We create a traffic generator state for each param combination we want to
12812267Sradhika.jagtap@arm.com# test. Each traffic generator state is specified in the config file and the
12912267Sradhika.jagtap@arm.com# generator remains in the state for specific period. This period is 0.25 ms.
13012267Sradhika.jagtap@arm.com# Stats are dumped and reset at the state transition.
13112267Sradhika.jagtap@arm.comperiod = 250000000
13212267Sradhika.jagtap@arm.com
13312267Sradhika.jagtap@arm.com# We specify the states in a config file input to the traffic generator.
13412267Sradhika.jagtap@arm.comcfg_file_name = "configs/dram/lowp_sweep.cfg"
13512267Sradhika.jagtap@arm.comcfg_file = open(cfg_file_name, 'w')
13612267Sradhika.jagtap@arm.com
13712267Sradhika.jagtap@arm.com# Get the number of banks
13812267Sradhika.jagtap@arm.comnbr_banks = int(system.mem_ctrls[0].banks_per_rank.value)
13912267Sradhika.jagtap@arm.com
14012267Sradhika.jagtap@arm.com# determine the burst size in bytes
14112267Sradhika.jagtap@arm.comburst_size = int((system.mem_ctrls[0].devices_per_rank.value *
14212267Sradhika.jagtap@arm.com                  system.mem_ctrls[0].device_bus_width.value *
14312267Sradhika.jagtap@arm.com                  system.mem_ctrls[0].burst_length.value) / 8)
14412267Sradhika.jagtap@arm.com
14512267Sradhika.jagtap@arm.com# next, get the page size in bytes (the rowbuffer size is already in bytes)
14612267Sradhika.jagtap@arm.compage_size = system.mem_ctrls[0].devices_per_rank.value * \
14712267Sradhika.jagtap@arm.com    system.mem_ctrls[0].device_rowbuffer_size.value
14812267Sradhika.jagtap@arm.com
14912267Sradhika.jagtap@arm.com# Inter-request delay should be such that we can hit as many transitions
15012267Sradhika.jagtap@arm.com# to/from low power states as possible to. We provide a min and max itt to the
15112267Sradhika.jagtap@arm.com# traffic generator and it randomises in the range. The parameter is in
15212267Sradhika.jagtap@arm.com# seconds and we need it in ticks (ps).
15312267Sradhika.jagtap@arm.comitt_min = system.mem_ctrls[0].tBURST.value * 1000000000000
15412267Sradhika.jagtap@arm.com
15512267Sradhika.jagtap@arm.com#The itt value when set to (tRAS + tRP + tCK) covers the case where
15612267Sradhika.jagtap@arm.com# a read command is delayed beyond the delay from ACT to PRE_PDN entry of the
15712267Sradhika.jagtap@arm.com# previous command. For write command followed by precharge, this delay
15812267Sradhika.jagtap@arm.com# between a write and power down entry will be tRCD + tCL + tWR + tRP + tCK.
15912267Sradhika.jagtap@arm.com# As we use this delay as a unit and create multiples of it as bigger delays
16012267Sradhika.jagtap@arm.com# for the sweep, this parameter works for reads, writes and mix of them.
16112267Sradhika.jagtap@arm.compd_entry_time = (system.mem_ctrls[0].tRAS.value +
16212267Sradhika.jagtap@arm.com                 system.mem_ctrls[0].tRP.value +
16312267Sradhika.jagtap@arm.com                 system.mem_ctrls[0].tCK.value) * 1000000000000
16412267Sradhika.jagtap@arm.com
16512267Sradhika.jagtap@arm.com# We sweep itt max using the multipliers specified by the user.
16612267Sradhika.jagtap@arm.comitt_max_str = args.itt_list.strip().split()
16712267Sradhika.jagtap@arm.comitt_max_multiples = map(lambda x : int(x), itt_max_str)
16812267Sradhika.jagtap@arm.comif len(itt_max_multiples) == 0:
16912267Sradhika.jagtap@arm.com    fatal("String for itt-max-list detected empty\n")
17012267Sradhika.jagtap@arm.com
17112267Sradhika.jagtap@arm.comitt_max_values = map(lambda m : pd_entry_time * m, itt_max_multiples)
17212267Sradhika.jagtap@arm.com
17312267Sradhika.jagtap@arm.com# Generate request addresses in the entire range, assume we start at 0
17412267Sradhika.jagtap@arm.commax_addr = mem_range.end
17512267Sradhika.jagtap@arm.com
17612267Sradhika.jagtap@arm.com# For max stride, use min of the page size and 512 bytes as that should be
17712267Sradhika.jagtap@arm.com# more than enough
17812267Sradhika.jagtap@arm.commax_stride = min(512, page_size)
17912267Sradhika.jagtap@arm.commid_stride = 4 * burst_size
18012267Sradhika.jagtap@arm.comstride_values = [burst_size, mid_stride, max_stride]
18112267Sradhika.jagtap@arm.com
18212267Sradhika.jagtap@arm.com# be selective about bank utilization instead of going from 1 to the number of
18312267Sradhika.jagtap@arm.com# banks
18412267Sradhika.jagtap@arm.combank_util_values = [1, int(nbr_banks/2), nbr_banks]
18512267Sradhika.jagtap@arm.com
18612267Sradhika.jagtap@arm.com# Next we create the config file, but first a comment
18712267Sradhika.jagtap@arm.comcfg_file.write("""# STATE state# period mode=DRAM
18812267Sradhika.jagtap@arm.com# read_percent start_addr end_addr req_size min_itt max_itt data_limit
18912267Sradhika.jagtap@arm.com# stride_size page_size #banks #banks_util addr_map #ranks\n""")
19012267Sradhika.jagtap@arm.com
19112267Sradhika.jagtap@arm.comnxt_state = 0
19212267Sradhika.jagtap@arm.comfor itt_max in itt_max_values:
19312267Sradhika.jagtap@arm.com    for bank in bank_util_values:
19412267Sradhika.jagtap@arm.com        for stride_size in stride_values:
19512267Sradhika.jagtap@arm.com            cfg_file.write("STATE %d %d %s %d 0 %d %d "
19612267Sradhika.jagtap@arm.com                           "%d %d %d %d %d %d %d %d %d\n" %
19712267Sradhika.jagtap@arm.com                           (nxt_state, period, "DRAM", args.rd_perc, max_addr,
19812267Sradhika.jagtap@arm.com                            burst_size, itt_min, itt_max, 0, stride_size,
19912267Sradhika.jagtap@arm.com                            page_size, nbr_banks, bank, args.addr_map,
20012267Sradhika.jagtap@arm.com                            args.mem_ranks))
20112267Sradhika.jagtap@arm.com            nxt_state = nxt_state + 1
20212267Sradhika.jagtap@arm.com
20312267Sradhika.jagtap@arm.com# State for idle period
20412267Sradhika.jagtap@arm.comidle_period = args.idle_end
20512267Sradhika.jagtap@arm.comcfg_file.write("STATE %d %d IDLE\n" % (nxt_state, idle_period))
20612267Sradhika.jagtap@arm.com
20712267Sradhika.jagtap@arm.com# Init state is state 0
20812267Sradhika.jagtap@arm.comcfg_file.write("INIT 0\n")
20912267Sradhika.jagtap@arm.com
21012267Sradhika.jagtap@arm.com# Go through the states one by one
21112267Sradhika.jagtap@arm.comfor state in range(1, nxt_state + 1):
21212267Sradhika.jagtap@arm.com    cfg_file.write("TRANSITION %d %d 1\n" % (state - 1, state))
21312267Sradhika.jagtap@arm.com
21412267Sradhika.jagtap@arm.com# Transition from last state to itself to not break the probability math
21512267Sradhika.jagtap@arm.comcfg_file.write("TRANSITION %d %d 1\n" % (nxt_state, nxt_state))
21612267Sradhika.jagtap@arm.comcfg_file.close()
21712267Sradhika.jagtap@arm.com
21812267Sradhika.jagtap@arm.com# create a traffic generator, and point it to the file we just created
21912267Sradhika.jagtap@arm.comsystem.tgen = TrafficGen(config_file = cfg_file_name)
22012267Sradhika.jagtap@arm.com
22112267Sradhika.jagtap@arm.com# add a communication monitor
22212267Sradhika.jagtap@arm.comsystem.monitor = CommMonitor()
22312267Sradhika.jagtap@arm.com
22412267Sradhika.jagtap@arm.com# connect the traffic generator to the bus via a communication monitor
22512267Sradhika.jagtap@arm.comsystem.tgen.port = system.monitor.slave
22612267Sradhika.jagtap@arm.comsystem.monitor.master = system.membus.slave
22712267Sradhika.jagtap@arm.com
22812267Sradhika.jagtap@arm.com# connect the system port even if it is not used in this example
22912267Sradhika.jagtap@arm.comsystem.system_port = system.membus.slave
23012267Sradhika.jagtap@arm.com
23112267Sradhika.jagtap@arm.com# every period, dump and reset all stats
23212267Sradhika.jagtap@arm.comperiodicStatDump(period)
23312267Sradhika.jagtap@arm.com
23412267Sradhika.jagtap@arm.comroot = Root(full_system = False, system = system)
23512267Sradhika.jagtap@arm.comroot.system.mem_mode = 'timing'
23612267Sradhika.jagtap@arm.com
23712267Sradhika.jagtap@arm.comm5.instantiate()
23812267Sradhika.jagtap@arm.com
23912267Sradhika.jagtap@arm.com# Simulate for exactly as long as it takes to go through all the states
24012267Sradhika.jagtap@arm.com# This is why sim exists.
24112267Sradhika.jagtap@arm.comm5.simulate(nxt_state * period + idle_period)
24212267Sradhika.jagtap@arm.comprint "--- Done DRAM low power sweep ---"
24312267Sradhika.jagtap@arm.comprint "Fixed params - "
24412267Sradhika.jagtap@arm.comprint "\tburst: %d, banks: %d, max stride: %d, itt min: %s ns" %  \
24512267Sradhika.jagtap@arm.com  (burst_size, nbr_banks, max_stride, itt_min)
24612267Sradhika.jagtap@arm.comprint "Swept params - "
24712267Sradhika.jagtap@arm.comprint "\titt max multiples input:", itt_max_multiples
24812267Sradhika.jagtap@arm.comprint "\titt max values", itt_max_values
24912267Sradhika.jagtap@arm.comprint "\tbank utilization values", bank_util_values
25012267Sradhika.jagtap@arm.comprint "\tstride values:", stride_values
25112267Sradhika.jagtap@arm.comprint "Traffic gen config file:", cfg_file_name
252