configs: Use absolute import paths
[gem5.git] / configs / dram / low_power_sweep.py
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
39 from __future__ import print_function
40 from __future__ import absolute_import
41
42 import argparse
43
44 import m5
45 from m5.objects import *
46 from m5.util import addToPath
47 from m5.stats import periodicStatDump
48
49 addToPath('../')
50
51 from 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
59 parser = argparse.ArgumentParser(
60 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
61
62 # Use a single-channel DDR4-2400 in 16x4 configuration by default
63 parser.add_argument("--mem-type", default="DDR4_2400_16x4",
64 choices=MemConfig.mem_names(),
65 help = "type of memory to use")
66
67 parser.add_argument("--mem-ranks", "-r", type=int, default=1,
68 help = "Number of ranks to iterate across")
69
70 parser.add_argument("--page-policy", "-p",
71 choices=["close_adaptive", "open_adaptive"],
72 default="close_adaptive", help="controller page policy")
73
74 parser.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
78 parser.add_argument("--rd-perc", type=int, default=100,
79 help = "Percentage of read commands")
80
81 parser.add_argument("--addr-map", type=int, default=1,
82 help = "0: RoCoRaBaCh; 1: RoRaBaCoCh/RoRaBaChCo")
83
84 parser.add_argument("--idle-end", type=int, default=50000000,
85 help = "time in ps of an idle period at the end ")
86
87 args = 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.
92 system = System(membus = IOXBar(width = 32))
93 system.clk_domain = SrcClockDomain(clock = '2.0GHz',
94 voltage_domain =
95 VoltageDomain(voltage = '1V'))
96
97 # We are fine with 256 MB memory for now.
98 mem_range = AddrRange('256MB')
99 # Start address is 0
100 system.mem_ranges = [mem_range]
101
102 # Do not worry about reserving space for the backing store
103 system.mmap_using_noreserve = True
104
105 # Force a single channel to match the assumptions in the DRAM traffic
106 # generator
107 args.mem_channels = 1
108 args.external_memory_system = 0
109 args.tlm_memory = 0
110 args.elastic_trace_en = 0
111 MemConfig.config_mem(args, system)
112
113 # Sanity check for memory controller class.
114 if 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.
118 system.mem_ctrls[0].null = True
119
120 # Set the address mapping based on input argument
121 # Default to RoRaBaCoCh
122 if args.addr_map == 0:
123 system.mem_ctrls[0].addr_mapping = "RoCoRaBaCh"
124 elif args.addr_map == 1:
125 system.mem_ctrls[0].addr_mapping = "RoRaBaCoCh"
126 else:
127 fatal("Did not specify a valid address map argument")
128
129 system.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.
135 period = 250000000
136
137 # We specify the states in a config file input to the traffic generator.
138 cfg_file_name = "configs/dram/lowp_sweep.cfg"
139 cfg_file = open(cfg_file_name, 'w')
140
141 # Get the number of banks
142 nbr_banks = int(system.mem_ctrls[0].banks_per_rank.value)
143
144 # determine the burst size in bytes
145 burst_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)
150 page_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).
157 itt_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.
165 pd_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.
170 itt_max_str = args.itt_list.strip().split()
171 itt_max_multiples = [ int(x) for x in itt_max_str ]
172 if len(itt_max_multiples) == 0:
173 fatal("String for itt-max-list detected empty\n")
174
175 itt_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
178 max_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
182 max_stride = min(512, page_size)
183 mid_stride = 4 * burst_size
184 stride_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
188 bank_util_values = [1, int(nbr_banks/2), nbr_banks]
189
190 # Next we create the config file, but first a comment
191 cfg_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
195 nxt_state = 0
196 for 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
208 idle_period = args.idle_end
209 cfg_file.write("STATE %d %d IDLE\n" % (nxt_state, idle_period))
210
211 # Init state is state 0
212 cfg_file.write("INIT 0\n")
213
214 # Go through the states one by one
215 for 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
219 cfg_file.write("TRANSITION %d %d 1\n" % (nxt_state, nxt_state))
220 cfg_file.close()
221
222 # create a traffic generator, and point it to the file we just created
223 system.tgen = TrafficGen(config_file = cfg_file_name)
224
225 # add a communication monitor
226 system.monitor = CommMonitor()
227
228 # connect the traffic generator to the bus via a communication monitor
229 system.tgen.port = system.monitor.slave
230 system.monitor.master = system.membus.slave
231
232 # connect the system port even if it is not used in this example
233 system.system_port = system.membus.slave
234
235 # every period, dump and reset all stats
236 periodicStatDump(period)
237
238 root = Root(full_system = False, system = system)
239 root.system.mem_mode = 'timing'
240
241 m5.instantiate()
242
243 # Simulate for exactly as long as it takes to go through all the states
244 # This is why sim exists.
245 m5.simulate(nxt_state * period + idle_period)
246 print("--- Done DRAM low power sweep ---")
247 print("Fixed params - ")
248 print("\tburst: %d, banks: %d, max stride: %d, itt min: %s ns" % \
249 (burst_size, nbr_banks, max_stride, itt_min))
250 print("Swept params - ")
251 print("\titt max multiples input:", itt_max_multiples)
252 print("\titt max values", itt_max_values)
253 print("\tbank utilization values", bank_util_values)
254 print("\tstride values:", stride_values)
255 print("Traffic gen config file:", cfg_file_name)