1# Copyright (c) 2014-2015, 2017 ARM Limited 2# All rights reserved. 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Redistribution and use in source and binary forms, with or without 14# modification, are permitted provided that the following conditions are 15# met: redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer; 17# redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution; 20# neither the name of the copyright holders nor the names of its 21# contributors may be used to endorse or promote products derived from 22# this software without specific prior written permission. 23# 24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35# 36# Authors: Radhika Jagtap 37# Andreas Hansson 38 39from __future__ import print_function 40from __future__ import absolute_import 41 42import argparse 43 44import m5 45from m5.objects import * 46from m5.util import addToPath 47from m5.stats import periodicStatDump 48 49addToPath('../') 50 51from common import MemConfig 52 53# This script aims at triggering low power state transitions in the DRAM 54# controller. The traffic generator is used in DRAM mode and traffic 55# states target a different levels of bank utilization and strides. 56# At the end after sweeping through bank utilization and strides, we go 57# through an idle state with no requests to enforce self-refresh. 58 59parser = argparse.ArgumentParser( 60 formatter_class=argparse.ArgumentDefaultsHelpFormatter) 61 62# Use a single-channel DDR4-2400 in 16x4 configuration by default 63parser.add_argument("--mem-type", default="DDR4_2400_16x4", 64 choices=MemConfig.mem_names(), 65 help = "type of memory to use") 66 67parser.add_argument("--mem-ranks", "-r", type=int, default=1, 68 help = "Number of ranks to iterate across") 69 70parser.add_argument("--page-policy", "-p", 71 choices=["close_adaptive", "open_adaptive"], 72 default="close_adaptive", help="controller page policy") 73 74parser.add_argument("--itt-list", "-t", default="1 20 100", 75 help="a list of multipliers for the max value of itt, " \ 76 "e.g. \"1 20 100\"") 77 78parser.add_argument("--rd-perc", type=int, default=100, 79 help = "Percentage of read commands") 80 81parser.add_argument("--addr-map", type=int, default=1, 82 help = "0: RoCoRaBaCh; 1: RoRaBaCoCh/RoRaBaChCo") 83 84parser.add_argument("--idle-end", type=int, default=50000000, 85 help = "time in ps of an idle period at the end ") 86 87args = parser.parse_args() 88 89# Start with the system itself, using a multi-layer 2.0 GHz 90# crossbar, delivering 64 bytes / 3 cycles (one header cycle) 91# which amounts to 42.7 GByte/s per layer and thus per port. 92system = System(membus = IOXBar(width = 32)) 93system.clk_domain = SrcClockDomain(clock = '2.0GHz', 94 voltage_domain = 95 VoltageDomain(voltage = '1V')) 96 97# We are fine with 256 MB memory for now. 98mem_range = AddrRange('256MB') 99# Start address is 0 100system.mem_ranges = [mem_range] 101 102# Do not worry about reserving space for the backing store 103system.mmap_using_noreserve = True 104 105# Force a single channel to match the assumptions in the DRAM traffic 106# generator 107args.mem_channels = 1 108args.external_memory_system = 0 109args.tlm_memory = 0 110args.elastic_trace_en = 0 111MemConfig.config_mem(args, system) 112 113# Sanity check for memory controller class. 114if not isinstance(system.mem_ctrls[0], m5.objects.DRAMCtrl): 115 fatal("This script assumes the memory is a DRAMCtrl subclass") 116 117# There is no point slowing things down by saving any data. 118system.mem_ctrls[0].null = True 119 120# Set the address mapping based on input argument 121# Default to RoRaBaCoCh 122if args.addr_map == 0: 123 system.mem_ctrls[0].addr_mapping = "RoCoRaBaCh" 124elif args.addr_map == 1: 125 system.mem_ctrls[0].addr_mapping = "RoRaBaCoCh" 126else: 127 fatal("Did not specify a valid address map argument") 128 129system.mem_ctrls[0].page_policy = args.page_policy 130 131# We create a traffic generator state for each param combination we want to 132# test. Each traffic generator state is specified in the config file and the 133# generator remains in the state for specific period. This period is 0.25 ms. 134# Stats are dumped and reset at the state transition. 135period = 250000000 136 137# We specify the states in a config file input to the traffic generator. 138cfg_file_name = "configs/dram/lowp_sweep.cfg" 139cfg_file = open(cfg_file_name, 'w') 140 141# Get the number of banks 142nbr_banks = int(system.mem_ctrls[0].banks_per_rank.value) 143 144# determine the burst size in bytes 145burst_size = int((system.mem_ctrls[0].devices_per_rank.value * 146 system.mem_ctrls[0].device_bus_width.value * 147 system.mem_ctrls[0].burst_length.value) / 8) 148 149# next, get the page size in bytes (the rowbuffer size is already in bytes) 150page_size = system.mem_ctrls[0].devices_per_rank.value * \ 151 system.mem_ctrls[0].device_rowbuffer_size.value 152 153# Inter-request delay should be such that we can hit as many transitions 154# to/from low power states as possible to. We provide a min and max itt to the 155# traffic generator and it randomises in the range. The parameter is in 156# seconds and we need it in ticks (ps). 157itt_min = system.mem_ctrls[0].tBURST.value * 1000000000000 158 159#The itt value when set to (tRAS + tRP + tCK) covers the case where 160# a read command is delayed beyond the delay from ACT to PRE_PDN entry of the 161# previous command. For write command followed by precharge, this delay 162# between a write and power down entry will be tRCD + tCL + tWR + tRP + tCK. 163# As we use this delay as a unit and create multiples of it as bigger delays 164# for the sweep, this parameter works for reads, writes and mix of them. 165pd_entry_time = (system.mem_ctrls[0].tRAS.value + 166 system.mem_ctrls[0].tRP.value + 167 system.mem_ctrls[0].tCK.value) * 1000000000000 168 169# We sweep itt max using the multipliers specified by the user. 170itt_max_str = args.itt_list.strip().split() 171itt_max_multiples = [ int(x) for x in itt_max_str ] 172if len(itt_max_multiples) == 0: 173 fatal("String for itt-max-list detected empty\n") 174 175itt_max_values = [ pd_entry_time * m for m in itt_max_multiples ] 176 177# Generate request addresses in the entire range, assume we start at 0 178max_addr = mem_range.end 179 180# For max stride, use min of the page size and 512 bytes as that should be 181# more than enough 182max_stride = min(512, page_size) 183mid_stride = 4 * burst_size 184stride_values = [burst_size, mid_stride, max_stride] 185 186# be selective about bank utilization instead of going from 1 to the number of 187# banks 188bank_util_values = [1, int(nbr_banks/2), nbr_banks] 189 190# Next we create the config file, but first a comment 191cfg_file.write("""# STATE state# period mode=DRAM 192# read_percent start_addr end_addr req_size min_itt max_itt data_limit 193# stride_size page_size #banks #banks_util addr_map #ranks\n""") 194 195nxt_state = 0 196for itt_max in itt_max_values: 197 for bank in bank_util_values: 198 for stride_size in stride_values: 199 cfg_file.write("STATE %d %d %s %d 0 %d %d " 200 "%d %d %d %d %d %d %d %d %d\n" % 201 (nxt_state, period, "DRAM", args.rd_perc, max_addr, 202 burst_size, itt_min, itt_max, 0, stride_size, 203 page_size, nbr_banks, bank, args.addr_map, 204 args.mem_ranks)) 205 nxt_state = nxt_state + 1 206 207# State for idle period 208idle_period = args.idle_end 209cfg_file.write("STATE %d %d IDLE\n" % (nxt_state, idle_period)) 210 211# Init state is state 0 212cfg_file.write("INIT 0\n") 213 214# Go through the states one by one 215for state in range(1, nxt_state + 1): 216 cfg_file.write("TRANSITION %d %d 1\n" % (state - 1, state)) 217 218# Transition from last state to itself to not break the probability math 219cfg_file.write("TRANSITION %d %d 1\n" % (nxt_state, nxt_state)) 220cfg_file.close() 221 222# create a traffic generator, and point it to the file we just created 223system.tgen = TrafficGen(config_file = cfg_file_name) 224 225# add a communication monitor 226system.monitor = CommMonitor() 227 228# connect the traffic generator to the bus via a communication monitor 229system.tgen.port = system.monitor.slave 230system.monitor.master = system.membus.slave 231 232# connect the system port even if it is not used in this example 233system.system_port = system.membus.slave 234 235# every period, dump and reset all stats 236periodicStatDump(period) 237 238root = Root(full_system = False, system = system) 239root.system.mem_mode = 'timing' 240 241m5.instantiate() 242 243# Simulate for exactly as long as it takes to go through all the states 244# This is why sim exists. 245m5.simulate(nxt_state * period + idle_period) 246print("--- Done DRAM low power sweep ---") 247print("Fixed params - ") 248print("\tburst: %d, banks: %d, max stride: %d, itt min: %s ns" % \ 249 (burst_size, nbr_banks, max_stride, itt_min)) 250print("Swept params - ") 251print("\titt max multiples input:", itt_max_multiples) 252print("\titt max values", itt_max_values) 253print("\tbank utilization values", bank_util_values) 254print("\tstride values:", stride_values) 255print("Traffic gen config file:", cfg_file_name) 256