1 # Copyright (c) 2014-2015, 2017 ARM Limited
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.
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.
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.
36 # Authors: Radhika Jagtap
39 from __future__
import print_function
44 from m5
.objects
import *
45 from m5
.util
import addToPath
46 from m5
.stats
import periodicStatDump
48 addToPath(os
.getcwd() + '/configs/common')
51 # This script aims at triggering low power state transitions in the DRAM
52 # controller. The traffic generator is used in DRAM mode and traffic
53 # states target a different levels of bank utilization and strides.
54 # At the end after sweeping through bank utilization and strides, we go
55 # through an idle state with no requests to enforce self-refresh.
57 parser
= argparse
.ArgumentParser(
58 formatter_class
=argparse
.ArgumentDefaultsHelpFormatter
)
60 # Use a single-channel DDR4-2400 in 16x4 configuration by default
61 parser
.add_argument("--mem-type", default
="DDR4_2400_16x4",
62 choices
=MemConfig
.mem_names(),
63 help = "type of memory to use")
65 parser
.add_argument("--mem-ranks", "-r", type=int, default
=1,
66 help = "Number of ranks to iterate across")
68 parser
.add_argument("--page-policy", "-p",
69 choices
=["close_adaptive", "open_adaptive"],
70 default
="close_adaptive", help="controller page policy")
72 parser
.add_argument("--itt-list", "-t", default
="1 20 100",
73 help="a list of multipliers for the max value of itt, " \
76 parser
.add_argument("--rd-perc", type=int, default
=100,
77 help = "Percentage of read commands")
79 parser
.add_argument("--addr-map", type=int, default
=1,
80 help = "0: RoCoRaBaCh; 1: RoRaBaCoCh/RoRaBaChCo")
82 parser
.add_argument("--idle-end", type=int, default
=50000000,
83 help = "time in ps of an idle period at the end ")
85 args
= parser
.parse_args()
87 # Start with the system itself, using a multi-layer 2.0 GHz
88 # crossbar, delivering 64 bytes / 3 cycles (one header cycle)
89 # which amounts to 42.7 GByte/s per layer and thus per port.
90 system
= System(membus
= IOXBar(width
= 32))
91 system
.clk_domain
= SrcClockDomain(clock
= '2.0GHz',
93 VoltageDomain(voltage
= '1V'))
95 # We are fine with 256 MB memory for now.
96 mem_range
= AddrRange('256MB')
98 system
.mem_ranges
= [mem_range
]
100 # Do not worry about reserving space for the backing store
101 system
.mmap_using_noreserve
= True
103 # Force a single channel to match the assumptions in the DRAM traffic
105 args
.mem_channels
= 1
106 args
.external_memory_system
= 0
108 args
.elastic_trace_en
= 0
109 MemConfig
.config_mem(args
, system
)
111 # Sanity check for memory controller class.
112 if not isinstance(system
.mem_ctrls
[0], m5
.objects
.DRAMCtrl
):
113 fatal("This script assumes the memory is a DRAMCtrl subclass")
115 # There is no point slowing things down by saving any data.
116 system
.mem_ctrls
[0].null
= True
118 # Set the address mapping based on input argument
119 # Default to RoRaBaCoCh
120 if args
.addr_map
== 0:
121 system
.mem_ctrls
[0].addr_mapping
= "RoCoRaBaCh"
122 elif args
.addr_map
== 1:
123 system
.mem_ctrls
[0].addr_mapping
= "RoRaBaCoCh"
125 fatal("Did not specify a valid address map argument")
127 system
.mem_ctrls
[0].page_policy
= args
.page_policy
129 # We create a traffic generator state for each param combination we want to
130 # test. Each traffic generator state is specified in the config file and the
131 # generator remains in the state for specific period. This period is 0.25 ms.
132 # Stats are dumped and reset at the state transition.
135 # We specify the states in a config file input to the traffic generator.
136 cfg_file_name
= "configs/dram/lowp_sweep.cfg"
137 cfg_file
= open(cfg_file_name
, 'w')
139 # Get the number of banks
140 nbr_banks
= int(system
.mem_ctrls
[0].banks_per_rank
.value
)
142 # determine the burst size in bytes
143 burst_size
= int((system
.mem_ctrls
[0].devices_per_rank
.value
*
144 system
.mem_ctrls
[0].device_bus_width
.value
*
145 system
.mem_ctrls
[0].burst_length
.value
) / 8)
147 # next, get the page size in bytes (the rowbuffer size is already in bytes)
148 page_size
= system
.mem_ctrls
[0].devices_per_rank
.value
* \
149 system
.mem_ctrls
[0].device_rowbuffer_size
.value
151 # Inter-request delay should be such that we can hit as many transitions
152 # to/from low power states as possible to. We provide a min and max itt to the
153 # traffic generator and it randomises in the range. The parameter is in
154 # seconds and we need it in ticks (ps).
155 itt_min
= system
.mem_ctrls
[0].tBURST
.value
* 1000000000000
157 #The itt value when set to (tRAS + tRP + tCK) covers the case where
158 # a read command is delayed beyond the delay from ACT to PRE_PDN entry of the
159 # previous command. For write command followed by precharge, this delay
160 # between a write and power down entry will be tRCD + tCL + tWR + tRP + tCK.
161 # As we use this delay as a unit and create multiples of it as bigger delays
162 # for the sweep, this parameter works for reads, writes and mix of them.
163 pd_entry_time
= (system
.mem_ctrls
[0].tRAS
.value
+
164 system
.mem_ctrls
[0].tRP
.value
+
165 system
.mem_ctrls
[0].tCK
.value
) * 1000000000000
167 # We sweep itt max using the multipliers specified by the user.
168 itt_max_str
= args
.itt_list
.strip().split()
169 itt_max_multiples
= map(lambda x
: int(x
), itt_max_str
)
170 if len(itt_max_multiples
) == 0:
171 fatal("String for itt-max-list detected empty\n")
173 itt_max_values
= map(lambda m
: pd_entry_time
* m
, itt_max_multiples
)
175 # Generate request addresses in the entire range, assume we start at 0
176 max_addr
= mem_range
.end
178 # For max stride, use min of the page size and 512 bytes as that should be
180 max_stride
= min(512, page_size
)
181 mid_stride
= 4 * burst_size
182 stride_values
= [burst_size
, mid_stride
, max_stride
]
184 # be selective about bank utilization instead of going from 1 to the number of
186 bank_util_values
= [1, int(nbr_banks
/2), nbr_banks
]
188 # Next we create the config file, but first a comment
189 cfg_file
.write("""# STATE state# period mode=DRAM
190 # read_percent start_addr end_addr req_size min_itt max_itt data_limit
191 # stride_size page_size #banks #banks_util addr_map #ranks\n""")
194 for itt_max
in itt_max_values
:
195 for bank
in bank_util_values
:
196 for stride_size
in stride_values
:
197 cfg_file
.write("STATE %d %d %s %d 0 %d %d "
198 "%d %d %d %d %d %d %d %d %d\n" %
199 (nxt_state
, period
, "DRAM", args
.rd_perc
, max_addr
,
200 burst_size
, itt_min
, itt_max
, 0, stride_size
,
201 page_size
, nbr_banks
, bank
, args
.addr_map
,
203 nxt_state
= nxt_state
+ 1
205 # State for idle period
206 idle_period
= args
.idle_end
207 cfg_file
.write("STATE %d %d IDLE\n" % (nxt_state
, idle_period
))
209 # Init state is state 0
210 cfg_file
.write("INIT 0\n")
212 # Go through the states one by one
213 for state
in range(1, nxt_state
+ 1):
214 cfg_file
.write("TRANSITION %d %d 1\n" % (state
- 1, state
))
216 # Transition from last state to itself to not break the probability math
217 cfg_file
.write("TRANSITION %d %d 1\n" % (nxt_state
, nxt_state
))
220 # create a traffic generator, and point it to the file we just created
221 system
.tgen
= TrafficGen(config_file
= cfg_file_name
)
223 # add a communication monitor
224 system
.monitor
= CommMonitor()
226 # connect the traffic generator to the bus via a communication monitor
227 system
.tgen
.port
= system
.monitor
.slave
228 system
.monitor
.master
= system
.membus
.slave
230 # connect the system port even if it is not used in this example
231 system
.system_port
= system
.membus
.slave
233 # every period, dump and reset all stats
234 periodicStatDump(period
)
236 root
= Root(full_system
= False, system
= system
)
237 root
.system
.mem_mode
= 'timing'
241 # Simulate for exactly as long as it takes to go through all the states
242 # This is why sim exists.
243 m5
.simulate(nxt_state
* period
+ idle_period
)
244 print("--- Done DRAM low power sweep ---")
245 print("Fixed params - ")
246 print("\tburst: %d, banks: %d, max stride: %d, itt min: %s ns" % \
247 (burst_size
, nbr_banks
, max_stride
, itt_min
))
248 print("Swept params - ")
249 print("\titt max multiples input:", itt_max_multiples
)
250 print("\titt max values", itt_max_values
)
251 print("\tbank utilization values", bank_util_values
)
252 print("\tstride values:", stride_values
)
253 print("Traffic gen config file:", cfg_file_name
)