ext: Add DRAMPower to enable on-line DRAM power modelling

This patch adds the open-source (BSD 3-clause) tool DRAMPower, commit
8d3cf4bbb10aa202d850ef5e5e3e4f53aa668fa6, to be built as a part of the
simulator. We have chosen this specific version of DRAMPower as it
provides the necessary functionality, and future updates will be
coordinated with the DRAMPower development team. The files added only
include the bits needed to build the library, thus excluding all
memory specifications, traces, and the stand-alone DRAMPower
command-line tool.

A future patch includes the DRAMPower functionality in the DRAM
controller, to enable on-line DRAM power modelling, and avoid using
post-processing of traces.
This commit is contained in:
Andreas Hansson 2014-10-09 17:52:03 -04:00
parent c81517c293
commit e0e8b08a42
33 changed files with 5347 additions and 0 deletions

View file

@ -1175,6 +1175,10 @@ main.SConscript('ext/fputils/SConscript',
main.SConscript('ext/dramsim2/SConscript',
variant_dir = joinpath(build_root, 'dramsim2'))
# DRAMPower build is shared across all configs in the build root.
main.SConscript('ext/drampower/SConscript',
variant_dir = joinpath(build_root, 'drampower'))
###################################################
#
# This function is used to set up a directory with switching headers

121
ext/drampower/ChangeLog Normal file
View file

@ -0,0 +1,121 @@
Change Log:
DRAMPower v4.0 - * DRAMPower can now be compiled as a library. This enables a user
to access the tool through an API and log commands and their
corresponding time stamps, removing the need to store large
command traces on disk. In addition, cycle counting variables
have been changed to int64 to support longer simulations.
The library can be compiled without Xerces to remove an optional
dependency and reduce the size of the binary.
* Improved robustness. The latest build is automatically checked
out on a test server, compiled, and tested to verify that the
output matches an expected reference. The code is also compiled
with a large number of warning flags enabled and treats all
warnings as errors.
* Bug fix: Fixed bug in io/termination energy calculation.
* Bug fix: Fixed bug in calculation of auto precharge cycle.
DRAMPower v3.1 - * Added IO and Termination Power measures from Micron's DRAM Power
Calculator, for all supported DRAM generations. In the case of
Wide IO DRAMs, these measures are already included in the provided
current specifications. This feature enables support for multi-rank
DRAM DIMMs (DDR2/3/4) and stacking of multiple Wide IO DRAM dies
(equivalent to ranks). To indicate use of multi-rank DRAMs or
multiple Wide IO DRAM dies/layers, the 'nbrOfRanks' parameter in
the memory specification XMLs can be employed. Note: The DRAM
command scheduler does not support multi-rank/multi-die DRAMs yet.
Only the power estimation component of DRAMPower has been updated
to support them. The current measures for dual-rank DRAMs only
reflect those for the active rank and not the idle rank. The
default state of the idle rank is assumed to be the same as the
current memory state, for background power estimation. Hence,
rank information in the command trace is not required.
* Added warning messages: New warning messages are provided, to
identify if the memory or bank state is inconsistent in the
user-defined traces. Towards this, a state check is performed on
every memory command issued.
* Improved run-time options: Users can now point directly to the
memory specification XML, instead of just the memory ID. Also,
users can optionally include IO and termination power estimates
(for both single and dual rank DRAMs) using '-r' flag in the
command line options.
* Bug fixes: (1) Refresh handler in the DRAM Command Scheduler was
kept ON in the Self-Refresh mode, when it can be turned OFF. This
bug has now been fixed. (2) Precharge All (PREA) always considered
precharging of all banks. It has now been modified to consider
precharging of the open/active banks alone.
DRAMPower v3.0 - * Added support for LPDDR3 and DDR4 memories, besides the already
supported DDR2/DDR3, LPDDR/LPDDR2 and WIDE IO DRAM memories.
* Added DRAM Command Scheduler: To support users of DRAMPower
without access to DRAM controllers, we have added a simple DRAM
command scheduler that dynamically schedules DRAM commands as if
it were a memory controller. The scheduler assumes closed-page
policy, employs ASAP scheduling for DRAM commands (i.e. schedules
commands as soon as timing constraints are met), performs FCFS
scheduling on DRAM transactions and supports all the different
DRAM generations supported by the power model. The generated DRAM
command schedule is also analyzable for real-time applications.
Users can also select speculative usage of power-down or
self-refresh modes (if needed) for idle periods between
transactions. It should be noted that using this command scheduler
is optional and it can be (de-)selected during run-time and users
can switch back to the previously used DRAM command interface as
in the earlier versions.
* Improved run-time options: Users can specify the memory and the
trace file to be used by DRAMPower using command line options.
Additionally, if the DRAM command scheduler is being used, the
users can specify the degree of bank interleaving required, the
request size and power-down or self-refresh options. Also, for
DDR4 memories the bank group interleaving can be specified using
command line options.
* Bug fixes: (1) For command traces ending with a RD/WR/RDA/WRA
command, the tool did not consider completion of operations when
estimating the total trace energy. The missing cycles are now
taken into account.
(2) The IDD5 (REF current) specification for WIDE IO SDR memory
specifications only included 2 banks for refreshes instead of all
four. We would like to thank David Roberts from AMD for spotting
the issue in our DATE'13 article. These measures have been updated.
(3) When estimating precharge cycle for commands with
auto-precharge, (RDA/WRA), the command analysis tool employed the
last activation cycle in the entire DRAM instead of the particular
DRAM bank. This bug has been fixed in this release.
DRAMPower v2.1 - * Added support for variation-aware power estimation, for a
selection of DDR3 memories manufactured using 50nm process
technology, based on the Monte-Carlo analysis presented in our
DAC'13 article.
DRAMPower v2.0 - * Added support for LPDDR/LPDDR2 and WIDE IO DRAM memories, besides
the already supported DDR2/DDR3 memories.
* Faster analysis: The trace analysis component in DRAMPower v2.0
triggers the evaluation only during memory state transitions
(between active, precharged, active and precharged power-down,
refresh, self-refresh and power-up states) and not on every clock
cycle, as was the case till the last version. This optimization
speeds up the power simulations using DRAMPower by several times
over cycle-accurate analysis, resulting in fast power analysis,
without affecting the accuracy of the trace analysis or the
reported power and energy estimates.
* Verification effort: Our power model was verified by the
Microelectronic System Design group at TU Kaiserslautern using
circuit-level SPICE simulations of a DRAM cross-section. As a
result of this verification effort, a couple of power equations
have been modified for Refresh and Self-refresh operations. The
difference between the power and energy estimates reported by our
updated model and the equivalent circuit-level simulations is
< 2% for all memory operations of any granularity for all memories
supported by DRAMPower.
DRAMPower v1.2 - * Supports different power-down and self-refresh modes in DDR2 and
DDR3 DRAM memories.
* Bug fix: Refresh power consumption equation in DRAMPower v1,
incorrectly subtracted IDD2n (precharge background current)
instead of IDD3n (active background current) from IDD5 (total
refresh current). This error has been rectified in this version.
DRAMPower v1.0 - * Performs cycle-accurate memory command trace analysis and estimates
power and energy consumption numbers for the trace.
* It supports the basic memory operations like read, write, refresh,
activate and (auto) precharge in DDR2 and DDR3 memories.

298
ext/drampower/README.md Normal file
View file

@ -0,0 +1,298 @@
# DRAM Power Model (DRAMPower)
[![Build Status](https://travis-ci.org/ravenrd/DRAMPower.svg?branch=master)](https://travis-ci.org/ravenrd/DRAMPower)
[![Coverage Status](https://coveralls.io/repos/ravenrd/DRAMPower/badge.png?branch=master)](https://coveralls.io/r/ravenrd/DRAMPower?branch=master)
## 0. Releases
The last official release can be found here:
https://github.com/ravenrd/DRAMPower/releases/tag/4.0
The master branch of the repository should be regarded as the bleeding-edge version, which has all the latest features, but also all the latest bugs. Use at your own discretion.
## 1. Installation
Clone the repository, or download the zip file of the release you would like to use. The source code is available in src folder. src/cli/drampower.cc file gives the user interface, where the user can specify the memory to be employed and the command/transaction trace to be analyzed. To build, use:
```bash
make -j4
```
This command will download a set of trace files from https://github.com/Sv3n/DRAMPowerTraces which can be used as test input for the tool.
## 2. Required Packages
The tool was verified on Ubuntu 14.04 using:
* xerces-c (libxerces-c-dev) - v3.1 with Xerces development package
* gcc - v4.4.3
## 3. Directory Structure
* src/: contains the source code of the DRAMPower tool that covers the power model, the command scheduler and the trace analysis tool.
* memspecs/ : contains the memory specification XMLs, which give the architectural, timing and current/voltage details for different DRAM memories.
* traces/ : contains 4 sample DRAM transaction traces and 1 sample command trace (after the installation / compilation)
* test/ : contains test script and reference output
## 4. Trace Specification
### Command Traces
If the command-level interface is being used, a command trace can be logged in a file.
An example is given in ```traces/commands.trace```
The format it uses is: ```<timestamp>,<command>,<bank>```.
For example, "500,ACT,2", where ACT is the command and 2 is the bank. Timestamp is in clock cycles (cc), the list of supported commands is
mentioned in src/MemCommand.h and the bank is the target bank number. For non-bank-specific commands, bank can be set to 0. Rank need not be
specified. The timing correctness of the trace is not verified by the tool and is assumed to be accurate. However, warning messages are provided, to identify if the memory or bank state is inconsistent in the trace. A sample command trace is provided in the traces/ folder.
### Transaction Traces
If the transaction-level interface is being used, a transaction trace can be logged.
The format it uses is: ```<timestamp>,<transaction_type>,<address>```.
For example, "35,READ,0x80028", where READ/WRITE can be the transaction type and the logical address (32-bits long and byte addressable) less than the maximum supported DRAM capacity of 4GB (32Gb).
The tool uses a flexible and efficient memory map as follows: specified in HEX (0x). Timestamp is in clock cycles (cc) and maximum {row}-{bank}-{column}-{BI}-{BC}-{BGI}-{BL}
Here, BI gives the degree of bank interleaving, BC gives the burst size (count), BGI gives the degree of bank group interleaving (for DDR4) and BL gives the burst length used by the device.
Dual-Rank addressing is not yet supported. The BC and BL address bits are derived from the column address bits, whereas the BI and BGI bits are derived from the bank address bits.
Four sample MediaBench application transaction traces have been provided. The MediaBench applications include: (1) EPIC Encoder, (2) JPEG Encoder, (3) H263 Encoder and (4) MPEG2 Encoder. These applications were independently executed on the SimpleScalar simulator with a 16KB L1 D-cache, 16KB L1 I-cache, 128KB L2 cache and 64-byte cache line configuration. We filtered out the L2 cache misses meant for the DRAM and logged them as transaction traces. These can be used with our command scheduler to generate equivalent command traces for any DRAM memory specified.
## 5. Usage
src/cli/drampower.cc is the main interface file, which accepts user inputs to specify memory to be employed and the command or transaction trace to be analyzed. If the transaction trace (DRAM command scheduler) is being used, the users can specify the degree of bank interleaving required, the request size and the use of power-down or self-refresh options. Also, for DDR4 memories bank group interleaving can be specified. Dual-rank DRAMs are not yet supported by the command scheduler. Note: Speculative use of power-down or self-refresh modes will increase the trace length due to the power-up latencies of these power-saving modes.
To use DRAMPower at the command-level (command trace), after make, use the following:
```bash
./drampower -m <memory spec (ID)> -c <commands trace>
```
To use DRAMPower at the transaction-level (command scheduler), after make, use the
following:
```bash
./drampower -m <memory spec (ID)> -t <transactions trace>
```
Additional options when using transactions trace [-t] include:
* [-i] ```<interleaving>```
* [-s] ```<request size>```
* [-g] ```<DDR4 bank group interleaving>```
* [-p] ```<0 - No Power-Down, 1 - Power-Down, 2 - Self-Refresh>```
Also, when using either the commands trace or the transactions trace, the user can
optionally include IO and Termination power estimates (obtained from Micron's DRAM
Power Calculator). To enable the same, the '-r' flag can be employed in command line.
If these options are not used, the default values assumed are:
* interleaving = 1
* request size = burst length * I/O width / 8 (in bytes) (from memory XMLs)
* power saving = No power-down
* bank group interleaving = 1
* IO and termination = OFF (0)
* Burst size (count) of 1
## 6. Memory Specifications
36 sample memory specifications are given in the XMLs targeting DDR2/DDR3/DDR4, LPDDR/LPDDR2/LPDDR3 and WIDE IO DRAM devices. The memory specifications are based on 1Gb DDR2, 1Gb & 2Gb DDR3, 2Gb LPDDR/LPDDR2 and 4Gb DDR4/LPDDR3 Micron datasheets and the 256Mb Wide IO SDR specifications are based on JEDEC timing specifications and circuit-level IDD measurements by TU Kaiserslautern, inplace of the as yet unavailable vendor datasheets. 4 of the memory specifications target dual-rank DDR3 DIMMs.
Note: The timing specifications in the XMLs are in clock cycles (cc). The current specifications for Reading and Writing do not include the I/O consumption. They are computed and included seperately based on Micron Power Calculator. The IDD measures associated with different power supply sources of equal measure (VDD2, VDDCA and VDDQ) for LPDDR2, LPDDR3, DDR4 and WIDE IO memories have been added up together for simplicity, since it does not impact power computation accuracy. The current measures for dual-rank DIMMs reflect only the measures for the active rank. The default state of the idle rank is assumed to be the same as the complete memory state, for background power estimation. Accordingly, in all dual-rank memory specifications, IDD2P0 has been subtracted from the active currents and all background currents have been halved. They are also accounted for seperately by the power model. Stacking multiple Wide IO DRAM dies can also be captured by the nbrOfRanks parameter.
## 7. Variation-aware Power And Energy Estimation
15 of the included datasheets reflect the impact of process-variations on DRAM currents for a selection of DDR3 memories manufactured at 50nm process technology. These memories include:
(1) MICRON_128MB_DDR3-1066_8bit - revision G
(2) MICRON_128MB_DDR3-1066_16bit - revision G
(3) MICRON_128MB_DDR3-1600_8bit - revision G
(4) MICRON_256MB_DDR3-1066_8bit - revision D
(5) MICRON_256MB_DDR3-1600_16bit - revision D
The original vendor-provided datasheet current specifications are given in XMLs
without suffixes such as _mu, _2s and _3s. XMLs including suffixes indicate that the
current measures are either: (1) typical (mu), or (2) include +2 sigma variation (2s),
or (3) include +3 sigma variation (3s). These measures are derived based on the
Monte-Carlo analysis performed on our SPICE-based DRAM cross-section.
To include these XMLs in your simulations, simply use them as the target memory.
## 8. Example Usage
An example of using this tool is provided below. To compile the example,
use the Makefile and make sure the Gcc and Xerces-c are installed. Then, run:
```
make -j4
```
This should show the following compilation message on the screen:
```
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/xmlparser/MemSpecParser.d -iquote src -o src/xmlparser/MemSpecParser.o -c src/xmlparser/MemSpecParser.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/xmlparser/XMLHandler.d -iquote src -o src/xmlparser/XMLHandler.o -c src/xmlparser/XMLHandler.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/xmlparser/XMLParser.d -iquote src -o src/xmlparser/XMLParser.o -c src/xmlparser/XMLParser.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/CmdScheduler.d -iquote src -o src/CmdScheduler.o -c src/CmdScheduler.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/CommandAnalysis.d -iquote src -o src/CommandAnalysis.o -c src/CommandAnalysis.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/MemArchitectureSpec.d -iquote src -o src/MemArchitectureSpec.o -c src/MemArchitectureSpec.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/MemCommand.d -iquote src -o src/MemCommand.o -c src/MemCommand.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/MemoryPowerModel.d -iquote src -o src/MemoryPowerModel.o -c src/MemoryPowerModel.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/MemorySpecification.d -iquote src -o src/MemorySpecification.o -c src/MemorySpecification.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/MemPowerSpec.d -iquote src -o src/MemPowerSpec.o -c src/MemPowerSpec.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/MemTimingSpec.d -iquote src -o src/MemTimingSpec.o -c src/MemTimingSpec.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/Parameter.d -iquote src -o src/Parameter.o -c src/Parameter.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/Parametrisable.d -iquote src -o src/Parametrisable.o -c src/Parametrisable.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/TraceParser.d -iquote src -o src/TraceParser.o -c src/TraceParser.cc
g++ -O -W -pedantic-errors -Wextra -Werror -Wformat -Wformat-nonliteral -Wpointer-arith -Wcast-align -Wconversion -g -std=c++98 -MMD -MF src/libdrampower/LibDRAMPower.d -iquote src -o src/libdrampower/LibDRAMPower.o -c src/libdrampower/LibDRAMPower.cc
ar -cvr src/libdrampowerxml.a src/xmlparser/MemSpecParser.o src/xmlparser/XMLHandler.o src/xmlparser/XMLParser.o
a - src/xmlparser/MemSpecParser.o
a - src/xmlparser/XMLHandler.o
a - src/xmlparser/XMLParser.o
g++ -Wall -o drampower src/xmlparser/MemSpecParser.o src/xmlparser/XMLHandler.o src/xmlparser/XMLParser.o src/CmdScheduler.o src/CommandAnalysis.o src/MemArchitectureSpec.o src/MemCommand.o src/MemoryPowerModel.o src/MemorySpecification.o src/MemPowerSpec.o src/MemTimingSpec.o src/Parameter.o src/Parametrisable.o src/TraceParser.o -L/usr/lib -lxerces-c
ar -cvr src/libdrampower.a src/CmdScheduler.o src/CommandAnalysis.o src/MemArchitectureSpec.o src/MemCommand.o src/MemoryPowerModel.o src/MemorySpecification.o src/MemPowerSpec.o src/MemTimingSpec.o src/Parameter.o src/Parametrisable.o src/TraceParser.o src/libdrampower/LibDRAMPower.o
a - src/CmdScheduler.o
a - src/CommandAnalysis.o
a - src/MemArchitectureSpec.o
a - src/MemCommand.o
a - src/MemoryPowerModel.o
a - src/MemorySpecification.o
a - src/MemPowerSpec.o
a - src/MemTimingSpec.o
a - src/Parameter.o
a - src/Parametrisable.o
a - src/TraceParser.o
a - src/libdrampower/LibDRAMPower.o
```
After this, run with the command trace or the transaction trace, as described before:
```
./drampower -m memspecs/MICRON_1Gb_DDR3-1066_8bit_G.xml -t traces/mediabench-epic.trace -r
```
The output should be something like this:
```
* Parsing memspecs/MICRON_1Gb_DDR3-1066_8bit_G.xml
* Analysis start time: Thu Nov 14 01:44:24 2013
* Analyzing the input trace
* Analysis End Time: Thu Nov 14 01:44:26 2013
* Power Computation Start time: Thu Nov 14 01:44:26 2013
* Trace Details:
Number of Activates: 96984
Number of Reads: 67179
Number of Writes: 29805
Number of Precharges: 96984
Number of Refreshes: 13168
Number of Active Cycles: 2519793
Number of Active Idle Cycles: 196851
Number of Active Power-Up Cycles: 0
Number of Auto-Refresh Active cycles during Self-Refresh Power-Up: 0
Number of Precharged Cycles: 52261474
Number of Precharged Idle Cycles: 51649664
Number of Precharged Power-Up Cycles: 0
Number of Auto-Refresh Precharged cycles during Self-Refresh Power-Up: 0
Number of Self-Refresh Power-Up Cycles: 0
Total Idle Cycles (Active + Precharged): 51846515
Number of Power-Downs: 0
Number of Active Fast-exit Power-Downs: 0
Number of Active Slow-exit Power-Downs: 0
Number of Precharged Fast-exit Power-Downs: 0
Number of Precharged Slow-exit Power-Downs: 0
Number of Power-Down Cycles: 0
Number of Active Fast-exit Power-Down Cycles: 0
Number of Active Slow-exit Power-Down Cycles: 0
Number of Auto-Refresh Active cycles during Self-Refresh: 0
Number of Precharged Fast-exit Power-Down Cycles: 0
Number of Precharged Slow-exit Power-Down Cycles: 0
Number of Auto-Refresh Precharged cycles during Self-Refresh: 0
Number of Auto-Refresh Cycles: 776912
Number of Self-Refreshes: 0
Number of Self-Refresh Cycles: 0
----------------------------------------
Total Trace Length (clock cycles): 54781267
----------------------------------------
* Trace Power and Energy Estimates:
ACT Cmd Energy: 109175234.52 pJ
PRE Cmd Energy: 47764165.10 pJ
RD Cmd Energy: 49155365.85 pJ
WR Cmd Energy: 23486116.32 pJ
RD I/O Energy: 22249684.80 pJ
WR Termination Energy: 50549280.00 pJ
ACT Stdby Energy: 283653996.25 pJ
Active Idle Energy: 22159587.24 pJ
Active Power-Up Energy: 0.00 pJ
Active Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: 0.00 pJ
PRE Stdby Energy: 5147706163.23 pJ
Precharge Idle Energy: 5087443452.16 pJ
Precharged Power-Up Energy: 0.00 pJ
Precharge Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: 0.00 pJ
Self-Refresh Power-Up Energy: 0.00 pJ
Total Idle Energy (Active + Precharged): 5109603039.40 pJ
Total Power-Down Energy: 0.00 pJ
Fast-Exit Active Power-Down Energy: 0.00 pJ
Slow-Exit Active Power-Down Energy: 0.00 pJ
Slow-Exit Active Power-Down Energy during Auto-Refresh cycles in Self-Refresh: 0.00 pJ
Fast-Exit Precharged Power-Down Energy: 0.00 pJ
Slow-Exit Precharged Power-Down Energy: 0.00 pJ
Slow-Exit Precharged Power-Down Energy during Auto-Refresh cycles in Self-Refresh: 0.00 pJ
Auto-Refresh Energy: 262371782.36 pJ
Self-Refresh Energy: 0.00 pJ
----------------------------------------
Total Trace Energy: 5996111788.44 pJ
Average Power: 58.34 mW
----------------------------------------
* Power Computation End time: Thu Nov 14 01:44:27 2013
* Total Simulation time: 3.51 seconds
*
```
As can be noticed, the tool performs DRAM command scheduling and reports the number
of activates, precharges, reads, writes, refreshes, power-downs and self-refreshes
besides the number of clock cycles spent in the active and precharged states, in the
power-down (fast/slow-exit) and self-refresh states and in the idle mode. It also
reports the energy consumption of these components, besides the IO and Termination
components in pJ (pico Joules) and the average power consumption of the trace in mW.
It also reports the simulation start/end times and the total simulation time in seconds.
## 9. DRAMPower Library
The DRAMPower tool has an additional feature and can be used as a library.
In order to use the library run "make lib", include src/libdrampower/LibDRAMPower.h in your project and
link the file src/libdrampower.a with your project.
An example for the usuage of the library can be found in the folder test/libdrampowertest/lib_test.cc
## 10. Authors & Acknowledgment
The tool is based on the DRAM power model developed jointly by the Computer Engineering Research Group at TU Delft and the Electronic Systems Group at TU Eindhoven and verified by the Microelectronic System Design Research Group at TU Kaiserslautern with equivalent circuit-level simulations. This tool has been developed by Karthik Chandrasekar with Yonghui Li under the supervision of Dr. Benny Akesson and Prof. Kees Goossens. The IO and Termination Power measures have been employed from Micron's DRAM Power Calculator. If you decide to use DRAMPower in your research, please cite one of the following references:
**To cite the DRAMPower Tool:**
```
[1] "DRAMPower: Open-source DRAM power & energy estimation tool"
Karthik Chandrasekar, Christian Weis, Yonghui Li, Benny Akesson, Norbert Wehn, and Kees Goossens
URL: http://www.drampower.info
```
**To cite the DRAM power model:**
```
[2] "Improved Power Modeling of DDR SDRAMs"
Karthik Chandrasekar, Benny Akesson, and Kees Goossens
In Proc. 14th Euromicro Conference on Digital System Design (DSD), 2011
```
**To cite the 3D-DRAM power model:**
```
[3] "System and Circuit Level Power Modeling of Energy-Efficient 3D-Stacked Wide I/O DRAMs"
Karthik Chandrasekar, Christian Weis, Benny Akesson, Norbert Wehn, and Kees Goossens
In Proc. Design, Automation and Test in Europe (DATE), 2013
```
**To cite variation-aware DRAM power estimation:**
```
[4] "Towards Variation-Aware System-Level Power Estimation of DRAMs: An Empirical Approach"
Karthik Chandrasekar, Christian Weis, Benny Akesson, Norbert Wehn, and Kees Goossens
In Proc. Design Automation Conference (DAC), 2013
```
## 11. Contact Information
Further questions about the tool and the power model can be directed to:
Benny Akesson (k.b.akesson@tue.nl)
Feel free to ask for updates to the tool's features and please do report any bugs
and errors you encounter. This will encourage us to continuously improve the tool.
## Disclaimer
The tool does not check the timing accuracy of the user's memory command trace
and the use of commands and memory modes. It is expected that the user employs
a valid trace generated using a DRAM memory controller or simulator, which
satisfies all memory timing constraints and other requirements. The user DOES
NOT get ANY WARRANTIES when using this tool. This software is released under the
BSD 3-Clause License. By using this software, the user implicitly agrees to the
licensing terms.

66
ext/drampower/SConscript Normal file
View file

@ -0,0 +1,66 @@
# -*- mode:python -*-
# Copyright (c) 2014 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Andreas Hansson
import os
Import('main')
main.Prepend(CPPPATH=Dir('./src'))
# Add the appropriate files for the library
drampower_files = []
def DRAMPowerFile(filename):
drampower_files.append(File('./src/' + filename))
DRAMPowerFile('CommandAnalysis.cc')
DRAMPowerFile('MemArchitectureSpec.cc')
DRAMPowerFile('MemCommand.cc')
DRAMPowerFile('MemPowerSpec.cc')
DRAMPowerFile('MemTimingSpec.cc')
DRAMPowerFile('MemoryPowerModel.cc')
DRAMPowerFile('MemorySpecification.cc')
DRAMPowerFile('Parameter.cc')
DRAMPowerFile('Parametrisable.cc')
DRAMPowerFile('libdrampower/LibDRAMPower.cc')
main.Library('drampower', [main.SharedObject(f) for f in drampower_files])
main.Append(LIBS=['drampower'])
main.Prepend(LIBPATH=[Dir('.')])

View file

@ -0,0 +1,659 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "CmdScheduler.h"
#include <cassert>
#include <cmath> // For log2
#include <algorithm> // For max
using namespace std;
using namespace Data;
// Read the traces and get the transaction. Each transaction is executed by
// scheduling a number of commands to the memory. Hence, the transactions are
// translated into a sequence of commands which will be used for power analysis.
void cmdScheduler::transTranslation(MemorySpecification memSpec,
ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown)
{
commands.open("commands.trace", ifstream::out);
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
nBanks = memArchSpec.nbrOfBanks;
nColumns = memArchSpec.nbrOfColumns;
burstLength = memArchSpec.burstLength;
nbrOfBankGroups = memArchSpec.nbrOfBankGroups;
BGI = grouping;
BI = interleaving;
BC = burst;
power_down = powerdown;
schedulingInitialization(memSpec);
getTrans(trans_trace, memSpec);
trans_trace.close();
commands.close();
ACT.erase(ACT.begin(), ACT.end());
PRE.erase(PRE.begin(), PRE.end());
RDWR.erase(RDWR.begin(), RDWR.end());
cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
cmdList.erase(cmdList.begin(), cmdList.end());
transTrace.erase(transTrace.begin(), transTrace.end());
} // cmdScheduler::transTranslation
// initialize the variables and vectors for starting command scheduling.
void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
{
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
ACT.resize(2 * memSpec.memArchSpec.nbrOfBanks);
RDWR.resize(2 * memSpec.memArchSpec.nbrOfBanks);
PRE.resize(memSpec.memArchSpec.nbrOfBanks);
bankaccess = memSpec.memArchSpec.nbrOfBanks;
if (!ACT.empty()) {
ACT.erase(ACT.begin(), ACT.end());
}
if (!PRE.empty()) {
PRE.erase(PRE.begin(), PRE.end());
}
if (!RDWR.empty()) {
RDWR.erase(RDWR.begin(), RDWR.end());
}
///////////////initialization//////////////
for (unsigned i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) {
cmd.Type = PRECHARGE;
cmd.bank = i;
cmd.name = "PRE";
if (memSpec.id == "WIDEIO_SDR")
cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.TAW);
else
cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.FAW);
PRE.push_back(cmd);
cmd.Type = ACTIVATE;
cmd.name = "ACT";
ACT.push_back(cmd);
cmd.Type = WRITE;
cmd.name = "WRITE";
cmd.time = -1;
RDWR[i].push_back(cmd);
}
tREF = memTimingSpec.REFI;
transFinish.time = 0;
transFinish.bank = 0;
PreRDWR.bank = -1;
PreRDWR.Type = READ;
PreRDWR.name = "RD";
PreRDWR.time = -1;
startTime = 0;
} // cmdScheduler::schedulingInitialization
// transactions are generated according to the information read from the traces.
// Then the command scheduling function is triggered to generate commands and
// schedule them to the memory according to the timing constraints.
void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memSpec)
{
std::string line;
transTime = 0;
unsigned newtranstime;
unsigned transAddr;
unsigned transType = 1;
trans TransItem;
if (!transTrace.empty()) {
transTrace.erase(transTrace.begin(), transTrace.end());
}
while (getline(trans_trace, line)) {
istringstream linestream(line);
string item;
unsigned itemnum = 0;
while (getline(linestream, item, ',')) {
if (itemnum == 0) {
stringstream timestamp(item);
timestamp >> newtranstime;
transTime = transTime + newtranstime;
} else if (itemnum == 1) {
if (item == "write" || item == "WRITE") {
transType = WRITE;
} else {
transType = READ;
}
} else if (itemnum == 2) {
stringstream timestamp(item);
timestamp >> std::hex >> transAddr;
}
itemnum++;
}
// generate a transaction
TransItem.timeStamp = transTime;
TransItem.logicalAddress = transAddr;
TransItem.type = transType;
transTrace.push_back(TransItem);
if (transTrace.size() == MILLION) {
// The scheduling is implemented for every MILLION transactions.
// It is used to reduce the used memory during the running of this tool.
analyticalScheduling(memSpec);
transTrace.erase(transTrace.begin(), transTrace.end());
}
}
if ((transTrace.size() < MILLION) && (!transTrace.empty())) {
analyticalScheduling(memSpec);
transTrace.erase(transTrace.begin(), transTrace.end());
}
} // cmdScheduler::getTrans
// Transactions are executed individually and the command scheduling is
// independent between transactions. The commands for a new transaction cannot
// be scheduled until all the commands for the current one are scheduled.
// After the scheduling, a sequence of commands are obtained and they are written
// into commands.txt which will be used for power analysis.
void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
{
int Bs = -1;
int transType = -1;
double timer = 0;
int bankGroupPointer = 0;
int bankGroupAddr = 0;
bool collisionFound;
physicalAddr PhysicalAddress;
bool bankGroupSwitch = false;
std::vector<unsigned> bankPointer(nbrOfBankGroups, 0);
std::vector<int> bankAccessNum(nBanks, -1);
std::vector<bool> ACTSchedule(nBanks, false);
int bankAddr = -1;
double endTime = 0;
double tComing_REF = 0;
Inselfrefresh = 0;
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
for (unsigned t = 0; t < transTrace.size(); t++) {
cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
for (unsigned i = 0; i < nBanks; i++) {
ACTSchedule[i] = false;
bankAccessNum[i] = -1;
}
timingsGet = false;
timer = transTrace[t].timeStamp;
PhysicalAddress = memoryMap(transTrace[t], memSpec);
for (unsigned i = 0; i < nbrOfBankGroups; i++) {
bankPointer[i] = PhysicalAddress.bankAddr; // the bank pointer per group.
}
bankGroupPointer = PhysicalAddress.bankGroupAddr;
endTime = max(transFinish.time, PRE[transFinish.bank].time +
static_cast<int>(memTimingSpec.RP));
// Before starting the scheduling for the next transaction, it has to
// check whether it is necessary for implementing power down.
if (power_down == SELF_REFRESH)
pdScheduling(endTime, timer, memSpec);
else if (power_down == POWER_DOWN)
pdScheduling(endTime, min(timer, tREF), memSpec);
tComing_REF = tREF;
///////////////Scheduling Refresh////////////////////////
if (((transFinish.time >= tREF) || (timer >= tREF))) {
for (double i = 0; i <= ((timer - tComing_REF) > 0 ? (timer - tComing_REF) /
memTimingSpec.REFI : 0); i++) {
cmd.bank = 0;
cmd.name = "REF";
cmd.time = max(max(max(transFinish.time, PRE[transFinish.bank].time
+ static_cast<int>(memTimingSpec.RP)), tREF), startTime);
if (((power_down == SELF_REFRESH) && !Inselfrefresh) ||
(power_down != SELF_REFRESH)) {
cmdScheduling.push_back(cmd);
startTime = cmd.time + memTimingSpec.RFC;
}
tREF = tREF + memTimingSpec.REFI;
// during the refreshing, power down should be taken into account.
if (!Inselfrefresh)
pdScheduling(endTime, min(timer, tREF), memSpec);
}
}
///////////////Execution Transactions///////////////////
Bs = PhysicalAddress.bankAddr;
transType = transTrace[t].type;
tRWTP = getRWTP(transType, memSpec);
for (int i = 0; i < BI; i++) {
for (int k = 0; k < BC; k++) {
if (memSpec.memoryType == MemoryType::DDR4) {
bankGroupPointer = PhysicalAddress.bankGroupAddr;
}
for (int j = 0; j < BGI; j++) {
bankGroupSwitch = false;
if (memSpec.memoryType == MemoryType::DDR4) {
if (bankGroupPointer != bankGroupAddr) {
bankGroupSwitch = true;
}
// update to the current bank group address.
bankGroupAddr = PhysicalAddress.bankGroupAddr + j;
bankAddr = bankGroupAddr * nBanks / nbrOfBankGroups +
bankPointer[bankGroupAddr];
} else {
bankAddr = Bs + i;
}
if (!timingsGet) {
getTimingConstraints(bankGroupSwitch, memSpec,
PreRDWR.Type, transType);
}
////////////////ACT Scheduling///////////////////
if (!ACTSchedule[bankAddr]) {
cmd.bank = bankAddr;
cmd.PhysicalAddr.bankAddr = cmd.bank;
cmd.PhysicalAddr.rowAddr = PhysicalAddress.rowAddr;
cmd.Type = ACTIVATE;
cmd.name = "ACT";
Inselfrefresh = 0;
cmd.time = max(max(ACT[bankaccess - 1].time + tRRD_init,
PRE[cmd.bank].time + static_cast<int>(memTimingSpec.RP)),
ACT[bankaccess - 4].time +
static_cast<int>(memTimingSpec.FAW));
if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
cmd.time = max(max(ACT[bankaccess - 1].time + tRRD_init,
PRE[cmd.bank].time + static_cast<int>(memTimingSpec.RP)),
ACT[bankaccess - 2].time +
static_cast<int>(memTimingSpec.TAW));
}
if ((i == 0) && (j == 0)) {
cmd.time = max(cmd.time, PreRDWR.time + 1);
cmd.time = max(cmd.time, timer);
cmd.time = max(startTime, cmd.time);
}
//////////collision detection////////////////////
for (int n = 1; n <= i * BGI + j; n++) {
collisionFound = false;
for (unsigned m = 0; m < RDWR[bankaccess - n].size(); m++) {
if (RDWR[bankaccess - n][m].time == cmd.time) {
cmd.time += 1; // ACT is shifted
collisionFound = true;
break;
}
}
if (collisionFound) {
break;
}
}
ACT.push_back(cmd);
cmdScheduling.push_back(cmd);
ACTSchedule[bankAddr] = true;
bankAccessNum[bankAddr] = bankaccess;
bankaccess++;
}
/////RDWR Scheduling//////
cmd.bank = bankAddr;
cmd.PhysicalAddr.bankAddr = cmd.bank;
cmd.PhysicalAddr.rowAddr = PhysicalAddress.rowAddr;
cmd.PhysicalAddr.colAddr = PhysicalAddress.colAddr + k * burstLength;
cmd.Type = transType;
switch (transType) {
case READ:
cmd.name = "RD";
break;
case WRITE:
cmd.name = "WR";
break;
}
for (int ACTBank = static_cast<int>(ACT.size() - 1);
ACTBank >= 0; ACTBank--) {
if (ACT[ACTBank].bank == bankAddr) {
cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time
+ static_cast<int>(memTimingSpec.RCD));
break;
}
}
if ((i == BI - 1) && (k == BC - 1) && (j == BGI - 1)) {
transFinish.time = cmd.time + 1;
transFinish.bank = bankAddr;
}
if (k == BC - 1) {
switch (transType) {
case READ:
cmd.name = "RDA";
break;
case WRITE:
cmd.name = "WRA";
break;
}
}
PreRDWR = cmd;
RDWR[bankAccessNum[bankAddr]].push_back(cmd);
cmdScheduling.push_back(cmd);
////////////////PRE Scheduling////////////////////
if (k == BC - 1) {
PRE[bankAddr].bank = bankAddr;
PRE[bankAddr].Type = PRECHARGE;
PRE[bankAddr].name = "PRE";
for (int ACTBank = static_cast<int>(ACT.size() - 1);
ACTBank >= 0; ACTBank--) {
if (ACT[ACTBank].bank == bankAddr) {
PRE[bankAddr].time = max(ACT.back().time +
static_cast<int>(memTimingSpec.RAS),
PreRDWR.time + tRWTP);
break;
}
}
bankPointer[bankGroupAddr] = bankPointer[bankGroupAddr] + 1;
}
bankGroupPointer++;
}
}
}
// make sure the scheduled commands are stored with an ascending scheduling time
sort(cmdScheduling.begin(), cmdScheduling.end(),
commandItem::commandItemSorter());
// write the scheduled commands into commands.txt.
for (unsigned i = 0; i < cmdScheduling.size(); i++) {
cmdList.push_back(cmdScheduling[i]);
}
/////////////Update Vector Length/////////////////
// the vector length is reduced so that less memory is used for running
// this tool.
if (ACT.size() >= memSpec.memArchSpec.nbrOfBanks) {
for (int m = 0; m < BI * BGI; m++) {
ACT.erase(ACT.begin());
RDWR[0].erase(RDWR[0].begin(), RDWR[0].end());
for (int h = 0; h < bankaccess - 1 - m; h++) {
RDWR[h].insert(RDWR[h].begin(), RDWR[h + 1].begin(), RDWR[h + 1].end());
RDWR[h + 1].resize(0);
}
}
bankaccess = bankaccess - (BI * BGI);
}
}
for (unsigned j = 0; j < cmdList.size(); j++) {
commands.precision(0);
commands << fixed << cmdList[j].time << "," << cmdList[j].name << "," <<
cmdList[j].bank << endl;
}
cmdList.erase(cmdList.begin(), cmdList.end());
} // cmdScheduler::analyticalScheduling
// to add the power down/up during the command scheduling for transactions.
// It is called when the command scheduling for a transaction is finished, and it
// is also called if there is a refresh.
void cmdScheduler::pdScheduling(double endTime, double timer,
MemorySpecification memSpec)
{
double ZERO = 0;
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
endTime = max(endTime, startTime);
double pdTime = max(ZERO, timer - endTime);
if ((timer > (endTime + memTimingSpec.CKE)) && (power_down == POWER_DOWN)) {
cmd.bank = 0;
cmd.name = "PDN_S_PRE";
cmd.time = endTime;
cmdScheduling.push_back(cmd);
cmd.name = "PUP_PRE";
if (pdTime > memTimingSpec.REFI)
cmd.time = cmd.time + memTimingSpec.REFI;
else
cmd.time = cmd.time + pdTime;
if (memSpec.memoryType.isLPDDRFamily())
startTime = cmd.time + memTimingSpec.XP;
else
startTime = cmd.time + memTimingSpec.XPDLL - memTimingSpec.RCD;
cmdScheduling.push_back(cmd);
} else if ((timer > (endTime + memTimingSpec.CKESR)) && (power_down == SELF_REFRESH)) {
cmd.bank = 0;
cmd.name = "SREN";
cmd.time = endTime;
cmdScheduling.push_back(cmd);
Inselfrefresh = 1;
cmd.name = "SREX";
cmd.time = cmd.time + pdTime;
if (memSpec.memoryType.isLPDDRFamily())
startTime = cmd.time + memTimingSpec.XS;
else
startTime = cmd.time + memTimingSpec.XSDLL - memTimingSpec.RCD;
cmdScheduling.push_back(cmd);
}
} // cmdScheduler::pdScheduling
// get the time when a precharge occurs after a read/write command is scheduled.
// In addition, it copes with different kind of memories.
int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
{
int tRWTP_init = 0;
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
if (transType == READ) {
switch (memSpec.memoryType) {
case MemoryType::LPDDR:
case MemoryType::WIDEIO_SDR:
tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate;
break;
case MemoryType::LPDDR2:
case MemoryType::LPDDR3:
tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate +
max(0, static_cast<int>(memTimingSpec.RTP - 2));
break;
case MemoryType::DDR2:
tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength /
memArchSpec.dataRate +
max(static_cast<int>(memTimingSpec.RTP), 2) - 2;
break;
case MemoryType::DDR3:
case MemoryType::DDR4:
tRWTP_init = memTimingSpec.RTP;
break;
default:
assert("Unknown memory type" && false);
} // switch
} else if (transType == WRITE) {
if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate - 1 + memSpec.memTimingSpec.WR;
} else {
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate + memSpec.memTimingSpec.WR;
}
if ((memSpec.memoryType == MemoryType::LPDDR2) ||
(memSpec.memoryType == MemoryType::LPDDR3)) {
tRWTP_init = tRWTP_init + 1;
}
}
return tRWTP_init;
} // cmdScheduler::getRWTP
// get the timings for command scheduling according to different memories.
// In particular, tSwitch_init is generally used to provide the timings for
// scheduling a read/write command after a read/write command which have been
// scheduled to any possible banks within any possible bank groups (DDR4).
void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSpec,
int PreType, int CurrentType)
{
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
if (memSpec.memoryType != MemoryType::DDR4) {
tRRD_init = memTimingSpec.RRD;
if (PreType == CurrentType) {
tSwitch_init = memTimingSpec.CCD;
timingsGet = true;
}
if ((PreType == WRITE) && (CurrentType == READ)) {
if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate - 1 + memTimingSpec.WTR;
} else {
tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate + memTimingSpec.WTR;
}
if ((memSpec.memoryType == MemoryType::LPDDR2) ||
(memSpec.memoryType == MemoryType::LPDDR3)) {
tSwitch_init = tSwitch_init + 1;
}
}
}
if (memSpec.memoryType == MemoryType::DDR4) {
if (BGSwitch) {
tCCD_init = memTimingSpec.CCD_S;
tRRD_init = memTimingSpec.RRD_S;
tWTR_init = memTimingSpec.WTR_S;
} else {
tCCD_init = memTimingSpec.CCD_L;
tRRD_init = memTimingSpec.RRD_L;
tWTR_init = memTimingSpec.WTR_L;
}
if (PreType == CurrentType) {
tSwitch_init = tCCD_init;
timingsGet = true;
} else if ((PreType == WRITE) && (CurrentType == READ)) {
tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate + tWTR_init;
}
}
if ((PreType == READ) && (CurrentType == WRITE)) {
tSwitch_init = memTimingSpec.RL + memArchSpec.burstLength /
memArchSpec.dataRate + 2 - memTimingSpec.WL;
}
} // cmdScheduler::getTimingConstraints
// The logical address of each transaction is translated into a physical address
// which consists of bank group (for DDR4), bank, row and column addresses.
cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans Trans,
MemorySpecification memSpec)
{
int DecLogic;
physicalAddr PhysicalAddr;
DecLogic = Trans.logicalAddress;
// row-bank-column-BI-BC-BGI-BL
if ((BGI > 1) && (memSpec.memoryType == MemoryType::DDR4)) {
unsigned colBits = static_cast<unsigned>(log2(nColumns));
unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0)
+ ((BGI > 1) ? log2(BGI) : 0));
unsigned bankMask = static_cast<unsigned>(nBanks / (BI * nbrOfBankGroups) - 1)
<< bankShift;
unsigned bankAddr = (DecLogic & bankMask) >>
static_cast<unsigned>(colBits + ((BGI > 1) ? log2(BGI) : 0));
PhysicalAddr.bankAddr = bankAddr;
unsigned bankGroupShift = static_cast<unsigned>(log2(burstLength));
unsigned bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
unsigned bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift;
PhysicalAddr.bankGroupAddr = bankGroupAddr;
unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) +
((BI > 1) ? log2(BI) : 0) + ((BGI > 1) ? log2(BGI) : 0));
unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
<< colShift;
unsigned colAddr = (DecLogic & colMask) >>
static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
PhysicalAddr.colAddr = colAddr;
} else {
unsigned colBits = static_cast<unsigned>(log2(nColumns));
unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0));
unsigned bankMask = static_cast<unsigned>(nBanks / BI - 1) << bankShift;
unsigned bankAddr = (DecLogic & bankMask) >> colBits;
PhysicalAddr.bankAddr = bankAddr;
unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) +
((BI > 1) ? log2(BI) : 0));
unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
<< colShift;
unsigned colAddr = (DecLogic & colMask) >>
static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
PhysicalAddr.colAddr = colAddr;
PhysicalAddr.bankGroupAddr = 0;
}
unsigned rowShift = static_cast<unsigned>(log2(nColumns * nBanks));
unsigned rowMask = static_cast<unsigned>(memSpec.memArchSpec.nbrOfRows - 1)
<< rowShift;
unsigned rowAddr = (DecLogic & rowMask) >> rowShift;
PhysicalAddr.rowAddr = rowAddr;
return PhysicalAddr;
} // cmdScheduler::memoryMap

View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#ifndef CMDSCHEDULER_H
#define CMDSCHEDULER_H
#include <string>
#include <vector>
#include <functional> // for binary_function<>
#include <fstream>
#include "MemorySpecification.h"
#include "Utils.h"
namespace Data {
class cmdScheduler {
public:
#define READ 0
#define WRITE 1
#define ACTIVATE 2
#define PRECHARGE 3
#define POWER_DOWN 1
#define SELF_REFRESH 2
// the format of a transaction.
class trans {
public:
int type;
double timeStamp;
unsigned logicalAddress;
};
std::vector<trans> transTrace; // to store the transactions.
// the format of physical address.
class physicalAddr {
public:
unsigned rowAddr;
unsigned bankAddr;
unsigned bankGroupAddr;
unsigned colAddr;
};
// the format of a command.
class commandItem {
public:
int Type;
int bank;
double time;
std::string name;
physicalAddr PhysicalAddr;
// sorting the commands according to their scheduling time.
struct commandItemSorter : public std::binary_function<commandItem&,
commandItem&, bool>{
bool operator()(const commandItem& lhs,
const commandItem& rhs) const
{
return lhs.time < rhs.time;
}
};
};
commandItem cmd;
commandItem transFinish; // the last scheduled command for a transaction.
commandItem PreRDWR; // the latest scheduled READ or WRITE command.
// the scheduled ACTIVATE commands are stored in ACT.
std::vector<commandItem> ACT;
// PRE is sued to keep recording the time when a precharge occurs.
std::vector<commandItem> PRE;
// the scheduled READ or WRITE commands are stored in RDWR.
std::vector<std::vector<commandItem> > RDWR;
// all the scheduled commands for a transaction is stored by cmdScheduling.
std::vector<commandItem> cmdScheduling;
std::vector<commandItem> cmdList;
unsigned elements;
int BI, BC, BGI;
// the function used to translate a transaction into a sequence of
// commands which are scheduled to the memory.
void transTranslation(Data::MemorySpecification memSpec,
std::ifstream& trans_trace,
int grouping,
int interleaving,
int burst,
int powerdown);
// get the transactions by reading the traces.
void getTrans(std::ifstream& pwr_trace,
MemorySpecification memSpec);
// the initialization function for scheduling.
void schedulingInitialization(MemorySpecification memSpec);
// the function used to schedule commands according to the timing constraints.
void analyticalScheduling(MemorySpecification memSpec);
// translate the logical address into physical address.
physicalAddr memoryMap(trans Trans,
MemorySpecification memSpec);
// the power down and power up are scheduled by pdScheduling
void pdScheduling(double endTime,
double timer,
MemorySpecification memSpec);
// get the timings for scheduling a precharge since a read or write command
// is scheduled.
int getRWTP(int transType,
MemorySpecification memSpec);
// get different kind of timing constraints according to the used memory.
void getTimingConstraints(bool BGSwitch,
MemorySpecification memSpec,
int PreType,
int CurrentType);
double transTime;
// the flag for power down.
int power_down;
int Inselfrefresh;
int tRRD_init;
int tCCD_init;
int tWTR_init;
double tREF;
double tSwitch_init;
double tRWTP;
int bankaccess;
unsigned nBanks;
unsigned nColumns;
unsigned burstLength;
unsigned nbrOfBankGroups;
bool timingsGet;
double startTime;
// the scheduling results for all the transactions are written into
// commands which will be used by the power analysis part.
std::ofstream commands;
};
}
#endif // ifndef CMDSCHEDULER_H

View file

@ -0,0 +1,666 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji, Sven Goossens
*
*/
#include <fstream>
#include <algorithm>
#include <sstream>
#include "CommandAnalysis.h"
#include "CmdScheduler.h"
using namespace Data;
using namespace std;
CommandAnalysis::CommandAnalysis()
{
}
CommandAnalysis::CommandAnalysis(const int nbrofBanks)
{
// Initializing all counters and variables
numberofacts = 0;
numberofpres = 0;
numberofreads = 0;
numberofwrites = 0;
numberofrefs = 0;
f_act_pdns = 0;
s_act_pdns = 0;
f_pre_pdns = 0;
s_pre_pdns = 0;
numberofsrefs = 0;
pop = 0;
init = 0;
zero = 0;
actcycles = 0;
precycles = 0;
f_act_pdcycles = 0;
s_act_pdcycles = 0;
f_pre_pdcycles = 0;
s_pre_pdcycles = 0;
pup_act_cycles = 0;
pup_pre_cycles = 0;
sref_cycles = 0;
spup_cycles = 0;
sref_ref_act_cycles = 0;
sref_ref_pre_cycles = 0;
spup_ref_act_cycles = 0;
spup_ref_pre_cycles = 0;
idlecycles_act = 0;
idlecycles_pre = 0;
latest_act_cycle = -1;
latest_pre_cycle = -1;
latest_read_cycle = -1;
latest_write_cycle = -1;
end_read_op = 0;
end_write_op = 0;
end_act_op = 0;
first_act_cycle = 0;
last_pre_cycle = 0;
bankstate.resize(nbrofBanks, 0);
last_states.resize(nbrofBanks);
mem_state = 0;
sref_cycle = 0;
pdn_cycle = 0;
cmd_list.clear();
full_cmd_list.resize(1, MemCommand::PRE);
cached_cmd.clear();
activation_cycle.resize(nbrofBanks, 0);
}
// function to clear all arrays
void CommandAnalysis::clear()
{
cached_cmd.clear();
cmd_list.clear();
full_cmd_list.clear();
last_states.clear();
bankstate.clear();
}
// Reads through the trace file, identifies the timestamp, command and bank
// If the issued command includes an auto-precharge, adds an explicit
// precharge to a cached command list and computes the precharge offset from the
// issued command timestamp, when the auto-precharge would kick in
void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
const int nbrofBanks, std::vector<MemCommand>& list, bool lastupdate)
{
for (vector<MemCommand>::const_iterator i = list.begin(); i != list.end(); ++i) {
const MemCommand& cmd = *i;
cmd_list.push_back(cmd);
MemCommand::cmds cmdType = cmd.getType();
if (cmdType == MemCommand::ACT) {
activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
} else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
// Remove auto-precharge flag from command
cmd_list.back().setType(cmd.typeWithoutAutoPrechargeFlag());
// Add the auto precharge to the list of cached_cmds
int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
cached_cmd.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), static_cast<double>(preTime)));
}
}
pop = 0;
// Note: the extra pre-cmds at the end of the lists, and the cast to double
// of the size vector is probably not desirable.
cmd_list.push_back(MemCommand::PRE);
cached_cmd.push_back(MemCommand::PRE);
analyse_commands(nbrofBanks, memSpec, cmd_list.size()-1,
cached_cmd.size()-1, lastupdate);
cmd_list.clear();
cached_cmd.clear();
} // CommandAnalysis::getCommands
// Checks the auto-precharge cached command list and inserts the explicit
// precharges with the appropriate timestamp in the original command list
// (by merging) based on their offset from the issuing command. Calls the
// evaluate function to analyse this expanded list of commands.
void CommandAnalysis::analyse_commands(const int nbrofBanks,
Data::MemorySpecification memSpec, int64_t nCommands, int64_t nCached, bool lastupdate)
{
full_cmd_list.resize(1, MemCommand::PRE);
unsigned mCommands = 0;
unsigned mCached = 0;
for (unsigned i = 0; i < nCommands + nCached + 1; i++) {
if (cached_cmd.size() > 1) {
if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
full_cmd_list[i].setType(MemCommand::PREA);
init = 1;
pop = 1;
} else {
init = 1;
if ((cached_cmd[mCached].getTime() > 0) && (cmd_list.
at(mCommands).getTime() < cached_cmd[mCached].
getTime()) && ((cmd_list[mCommands].getTime() > 0) ||
((cmd_list[mCommands].getTime() == 0) && (cmd_list[mCommands].
getType() != MemCommand::PRE)))) {
full_cmd_list[i] = cmd_list[mCommands];
mCommands++;
} else if ((cached_cmd[mCached].getTime() > 0) && (cmd_list[mCommands].
getTime() >= cached_cmd[mCached].getTime())) {
full_cmd_list[i] = cached_cmd[mCached];
mCached++;
} else if (cached_cmd[mCached].getTime() == 0) {
if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list[mCommands].
getTime() == 0) && (cmd_list[mCommands].
getType() != MemCommand::PRE))) {
full_cmd_list[i] = cmd_list[mCommands];
mCommands++;
}
} else if (cmd_list[mCommands].getTime() == 0) {
full_cmd_list[i] = cached_cmd[mCached];
mCached++;
}
}
} else {
if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
full_cmd_list[i].setType(MemCommand::PREA);
init = 1;
pop = 1;
} else {
init = 1;
if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list.
at(mCommands).getTime() == 0) && (cmd_list[mCommands].
getType() != MemCommand::PRE))) {
full_cmd_list[i] = cmd_list[mCommands];
mCommands++;
}
}
}
full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::PRE);
}
full_cmd_list.pop_back();
if (pop == 0) {
full_cmd_list.pop_back();
}
if (lastupdate) {
full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::NOP);
full_cmd_list[full_cmd_list.size() - 1].setTime(full_cmd_list
[full_cmd_list.size() - 2].getTime() + timeToCompletion(memSpec,
full_cmd_list[full_cmd_list.size() - 2].getType()) - 1);
}
evaluate(memSpec, full_cmd_list, nbrofBanks);
} // CommandAnalysis::analyse_commands
// To get the time of completion of the issued command
// Derived based on JEDEC specifications
int CommandAnalysis::timeToCompletion(const MemorySpecification&
memSpec, MemCommand::cmds type)
{
int offset = 0;
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
if (type == MemCommand::RD) {
offset = static_cast<int>(memTimingSpec.RL +
memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
memArchSpec.dataRate));
} else if (type == MemCommand::WR) {
offset = static_cast<int>(memTimingSpec.WL +
(memArchSpec.burstLength / memArchSpec.dataRate) +
memTimingSpec.WR);
} else if (type == MemCommand::ACT) {
offset = static_cast<int>(memTimingSpec.RCD);
} else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
offset = static_cast<int>(memTimingSpec.RP);
}
return offset;
} // CommandAnalysis::timeToCompletion
// Used to analyse a given list of commands and identify command timings
// and memory state transitions
void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
vector<MemCommand>& cmd_list, int nbrofBanks)
{
// for each command identify timestamp, type and bank
for (unsigned cmd_list_counter = 0; cmd_list_counter < cmd_list.size();
cmd_list_counter++) {
// For command type
int type = cmd_list[cmd_list_counter].getType();
// For command bank
int bank = cmd_list[cmd_list_counter].getBank();
// Command Issue timestamp in clock cycles (cc)
int64_t timestamp = cmd_list[cmd_list_counter].getTimeInt64();
if (type == MemCommand::ACT) {
// If command is ACT - update number of acts, bank state of the
// target bank, first and latest activation cycle and the memory
// state. Update the number of precharged/idle-precharged cycles.
numberofacts++;
if (bankstate[bank] == 1) {
printWarning("Bank is already active!", type, timestamp, bank);
}
bankstate[bank] = 1;
if (mem_state == 0) {
first_act_cycle = timestamp;
precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
}
latest_act_cycle = timestamp;
mem_state++;
} else if (type == MemCommand::RD) {
// If command is RD - update number of reads and read cycle. Check
// for active idle cycles (if any).
if (bankstate[bank] == 0) {
printWarning("Bank is not active!", type, timestamp, bank);
}
numberofreads++;
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp);
latest_read_cycle = timestamp;
} else if (type == MemCommand::WR) {
// If command is WR - update number of writes and write cycle. Check
// for active idle cycles (if any).
if (bankstate[bank] == 0) {
printWarning("Bank is not active!", type, timestamp, bank);
}
numberofwrites++;
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp);
latest_write_cycle = timestamp;
} else if (type == MemCommand::REF) {
// If command is REF - update number of refreshes, set bank state of
// all banks to ACT, set the last PRE cycles at RFC-RP cycles from
// timestamp, set the number of active cycles to RFC-RP and check
// for active and precharged cycles and idle active and idle
// precharged cycles before refresh. Change memory state to 0.
printWarningIfActive("One or more banks are active! REF requires all banks to be precharged.", type, timestamp, bank);
numberofrefs++;
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
first_act_cycle = timestamp;
precycles += max(zero, timestamp - last_pre_cycle);
last_pre_cycle = timestamp + memSpec.memTimingSpec.RFC -
memSpec.memTimingSpec.RP;
latest_pre_cycle = last_pre_cycle;
actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
mem_state = 0;
for (int j = 0; j < nbrofBanks; j++) {
bankstate[j] = 0;
}
} else if (type == MemCommand::PRE) {
// If command is explicit PRE - update number of precharges, bank
// state of the target bank and last and latest precharge cycle.
// Calculate the number of active cycles if the memory was in the
// active state before, but there is a state transition to PRE now.
// If not, update the number of precharged cycles and idle cycles.
// Update memory state if needed.
if (bankstate[bank] == 1) {
numberofpres++;
}
bankstate[bank] = 0;
if (mem_state == 1) {
actcycles += max(zero, timestamp - first_act_cycle);
last_pre_cycle = timestamp;
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp);
} else if (mem_state == 0) {
precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
last_pre_cycle = timestamp;
}
latest_pre_cycle = timestamp;
if (mem_state > 0) {
mem_state--;
} else {
mem_state = 0;
}
} else if (type == MemCommand::PREA) {
// If command is explicit PREA (precharge all banks) - update
// number of precharges by the number of banks, update the bank
// state of all banks to PRE and set the precharge cycle.
// Calculate the number of active cycles if the memory was in the
// active state before, but there is a state transition to PRE now.
// If not, update the number of precharged cycles and idle cycles.
if (timestamp == 0) {
numberofpres += 0;
} else {
numberofpres += mem_state;
}
if (mem_state > 0) {
actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp);
} else if (mem_state == 0) {
precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
}
latest_pre_cycle = timestamp;
last_pre_cycle = timestamp;
mem_state = 0;
for (int j = 0; j < nbrofBanks; j++) {
bankstate[j] = 0;
}
} else if (type == MemCommand::PDN_F_ACT) {
// If command is fast-exit active power-down - update number of
// power-downs, set the power-down cycle and the memory mode to
// fast-exit active power-down. Save states of all the banks from
// the cycle before entering active power-down, to be returned to
// after powering-up. Update active and active idle cycles.
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
f_act_pdns++;
for (int j = 0; j < nbrofBanks; j++) {
last_states[j] = bankstate[j];
}
pdn_cycle = timestamp;
actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp);
mem_state = CommandAnalysis::MS_PDN_F_ACT;
} else if (type == MemCommand::PDN_S_ACT) {
// If command is slow-exit active power-down - update number of
// power-downs, set the power-down cycle and the memory mode to
// slow-exit active power-down. Save states of all the banks from
// the cycle before entering active power-down, to be returned to
// after powering-up. Update active and active idle cycles.
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
s_act_pdns++;
for (int j = 0; j < nbrofBanks; j++) {
last_states[j] = bankstate[j];
}
pdn_cycle = timestamp;
actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp);
mem_state = CommandAnalysis::MS_PDN_S_ACT;
} else if (type == MemCommand::PDN_F_PRE) {
// If command is fast-exit precharged power-down - update number of
// power-downs, set the power-down cycle and the memory mode to
// fast-exit precahrged power-down. Update precharged and precharged
// idle cycles.
printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank);
f_pre_pdns++;
pdn_cycle = timestamp;
precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
mem_state = CommandAnalysis::MS_PDN_F_PRE;
} else if (type == MemCommand::PDN_S_PRE) {
// If command is slow-exit precharged power-down - update number of
// power-downs, set the power-down cycle and the memory mode to
// slow-exit precahrged power-down. Update precharged and precharged
// idle cycles.
printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank);
s_pre_pdns++;
pdn_cycle = timestamp;
precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
mem_state = CommandAnalysis::MS_PDN_S_PRE;
} else if (type == MemCommand::PUP_ACT) {
// If command is power-up in the active mode - check the power-down
// exit-mode employed (fast or slow), update the number of power-down
// and power-up cycles and the latest and first act cycle. Also, reset
// all the individual bank states to the respective saved states
// before entering power-down.
if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
f_act_pdcycles += max(zero, timestamp - pdn_cycle);
pup_act_cycles += memSpec.memTimingSpec.XP;
latest_act_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD);
} else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
s_act_pdcycles += max(zero, timestamp - pdn_cycle);
if (memSpec.memArchSpec.dll == false) {
pup_act_cycles += memSpec.memTimingSpec.XP;
latest_act_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD);
} else {
pup_act_cycles += memSpec.memTimingSpec.XPDLL -
memSpec.memTimingSpec.RCD;
latest_act_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XPDLL -
(2 * memSpec.memTimingSpec.RCD));
}
} else if ((mem_state != CommandAnalysis::MS_PDN_S_ACT) || (mem_state !=
CommandAnalysis::MS_PDN_F_ACT)) {
cerr << "Incorrect use of Active Power-Up!" << endl;
}
mem_state = 0;
for (int j = 0; j < nbrofBanks; j++) {
bankstate[j] = last_states[j];
mem_state += last_states[j];
}
first_act_cycle = timestamp;
} else if (type == MemCommand::PUP_PRE) {
// If command is power-up in the precharged mode - check the power-down
// exit-mode employed (fast or slow), update the number of power-down
// and power-up cycles and the latest and last pre cycle.
if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
f_pre_pdcycles += max(zero, timestamp - pdn_cycle);
pup_pre_cycles += memSpec.memTimingSpec.XP;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP);
} else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
s_pre_pdcycles += max(zero, timestamp - pdn_cycle);
if (memSpec.memArchSpec.dll == false) {
pup_pre_cycles += memSpec.memTimingSpec.XP;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP);
} else {
pup_pre_cycles += memSpec.memTimingSpec.XPDLL -
memSpec.memTimingSpec.RCD;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD -
memSpec.memTimingSpec.RP);
}
} else if ((mem_state != CommandAnalysis::MS_PDN_S_PRE) || (mem_state !=
CommandAnalysis::MS_PDN_F_PRE)) {
cerr << "Incorrect use of Precharged Power-Up!" << endl;
}
mem_state = 0;
last_pre_cycle = timestamp;
} else if (type == MemCommand::SREN) {
// If command is self-refresh - update number of self-refreshes,
// set memory state to SREF, update precharge and idle precharge
// cycles and set the self-refresh cycle.
printWarningIfActive("One or more banks are active! SREF requires all banks to be precharged.", type, timestamp, bank);
numberofsrefs++;
sref_cycle = timestamp;
precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
mem_state = CommandAnalysis::MS_SREF;
} else if (type == MemCommand::SREX) {
// If command is self-refresh exit - update the number of self-refresh
// clock cycles, number of active and precharged auto-refresh clock
// cycles during self-refresh and self-refresh exit based on the number
// of cycles in the self-refresh mode and auto-refresh duration (RFC).
// Set the last and latest precharge cycle accordingly and set the
// memory state to 0.
if (mem_state != CommandAnalysis::MS_SREF) {
cerr << "Incorrect use of Self-Refresh Power-Up!" << endl;
}
if (max(zero, timestamp - sref_cycle) >= memSpec.memTimingSpec.RFC) {
sref_cycles += max(zero, timestamp - sref_cycle
- memSpec.memTimingSpec.RFC);
sref_ref_act_cycles += memSpec.memTimingSpec.RFC -
memSpec.memTimingSpec.RP;
sref_ref_pre_cycles += memSpec.memTimingSpec.RP;
last_pre_cycle = timestamp;
if (memSpec.memArchSpec.dll == false) {
spup_cycles += memSpec.memTimingSpec.XS;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XS - memSpec.memTimingSpec.RP);
} else {
spup_cycles += memSpec.memTimingSpec.XSDLL -
memSpec.memTimingSpec.RCD;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD
- memSpec.memTimingSpec.RP);
}
} else {
int64_t sref_diff = memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
int64_t sref_pre = max(zero, timestamp - sref_cycle - sref_diff);
int64_t spup_pre = memSpec.memTimingSpec.RP - sref_pre;
int64_t sref_act = max(zero, timestamp - sref_cycle);
int64_t spup_act = memSpec.memTimingSpec.RFC - sref_act;
if (max(zero, timestamp - sref_cycle) >= sref_diff) {
sref_ref_act_cycles += sref_diff;
sref_ref_pre_cycles += sref_pre;
spup_ref_pre_cycles += spup_pre;
last_pre_cycle = timestamp + spup_pre;
if (memSpec.memArchSpec.dll == false) {
spup_cycles += memSpec.memTimingSpec.XS - spup_pre;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XS - spup_pre -
memSpec.memTimingSpec.RP);
} else {
spup_cycles += memSpec.memTimingSpec.XSDLL -
memSpec.memTimingSpec.RCD - spup_pre;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD -
spup_pre - memSpec.memTimingSpec.RP);
}
} else {
sref_ref_act_cycles += sref_act;
spup_ref_act_cycles += spup_act;
spup_ref_pre_cycles += memSpec.memTimingSpec.RP;
last_pre_cycle = timestamp + spup_act + memSpec.memTimingSpec.RP;
if (memSpec.memArchSpec.dll == false) {
spup_cycles += memSpec.memTimingSpec.XS - spup_act -
memSpec.memTimingSpec.RP;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XS - spup_act -
(2 * memSpec.memTimingSpec.RP));
} else {
spup_cycles += memSpec.memTimingSpec.XSDLL -
memSpec.memTimingSpec.RCD - spup_act -
memSpec.memTimingSpec.RP;
latest_pre_cycle = max(timestamp, timestamp +
memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD -
spup_act - (2 * memSpec.memTimingSpec.RP));
}
}
}
mem_state = 0;
} else if ((type == MemCommand::END) || (type == MemCommand::NOP)) {
// May be optionally used at the end of memory trace for better accuracy
// Update all counters based on completion of operations.
if ((mem_state > 0) && (mem_state < 9)) {
actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp);
} else if (mem_state == 0) {
precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
} else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
f_act_pdcycles += max(zero, timestamp - pdn_cycle);
} else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
s_act_pdcycles += max(zero, timestamp - pdn_cycle);
} else if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
f_pre_pdcycles += max(zero, timestamp - pdn_cycle);
} else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
s_pre_pdcycles += max(zero, timestamp - pdn_cycle);
} else if (mem_state == CommandAnalysis::MS_SREF) {
sref_cycles += max(zero, timestamp - sref_cycle);
}
}
}
} // CommandAnalysis::evaluate
// To update idle period information whenever active cycles may be idle
void CommandAnalysis::idle_act_update(const MemorySpecification& memSpec,
int64_t latest_read_cycle, int64_t latest_write_cycle,
int64_t latest_act_cycle, int64_t timestamp)
{
if (latest_read_cycle >= 0) {
end_read_op = latest_read_cycle + timeToCompletion(memSpec,
MemCommand::RD) - 1;
}
if (latest_write_cycle >= 0) {
end_write_op = latest_write_cycle + timeToCompletion(memSpec,
MemCommand::WR) - 1;
}
if (latest_act_cycle >= 0) {
end_act_op = latest_act_cycle + timeToCompletion(memSpec,
MemCommand::ACT) - 1;
}
idlecycles_act += max(zero, timestamp - max(max(end_read_op, end_write_op),
end_act_op));
} // CommandAnalysis::idle_act_update
// To update idle period information whenever precharged cycles may be idle
void CommandAnalysis::idle_pre_update(const MemorySpecification& memSpec,
int64_t timestamp, int64_t latest_pre_cycle)
{
if (latest_pre_cycle > 0) {
idlecycles_pre += max(zero, timestamp - latest_pre_cycle -
memSpec.memTimingSpec.RP);
} else if (latest_pre_cycle == 0) {
idlecycles_pre += max(zero, timestamp - latest_pre_cycle);
}
}
void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank)
{
if (mem_state != 0) {
printWarning(warning, type, timestamp, bank);
}
}
void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int bank)
{
if (mem_state == 0) {
printWarning(warning, type, timestamp, bank);
}
}
void CommandAnalysis::printWarning(const string& warning, int type, int64_t timestamp, int bank)
{
cerr << "WARNING: " << warning << endl;
cerr << "Command: " << type << ", Timestamp: " << timestamp <<
", Bank: " << bank << endl;
}

View file

@ -0,0 +1,213 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji
*
*/
#ifndef COMMAND_TIMINGS_H
#define COMMAND_TIMINGS_H
#include <stdint.h>
#include <vector>
#include <iostream>
#include <deque>
#include <string>
#include "MemCommand.h"
#include "MemorySpecification.h"
#include "Utils.h"
namespace Data {
class CommandAnalysis {
public:
// Power-Down and Self-refresh related memory states
enum memstate {
MS_PDN_F_ACT = 10, MS_PDN_S_ACT = 11, MS_PDN_F_PRE = 12,
MS_PDN_S_PRE = 13, MS_SREF = 14
};
CommandAnalysis();
// Returns number of reads, writes, acts, pres and refs in the trace
CommandAnalysis(const int nbrofBanks);
// Number of activate commands
int64_t numberofacts;
// Number of precharge commands
int64_t numberofpres;
// Number of reads commands
int64_t numberofreads;
// Number of writes commands
int64_t numberofwrites;
// Number of refresh commands
int64_t numberofrefs;
// Number of precharge cycles
int64_t precycles;
// Number of active cycles
int64_t actcycles;
// Number of Idle cycles in the active state
int64_t idlecycles_act;
// Number of Idle cycles in the precharge state
int64_t idlecycles_pre;
// Number of fast-exit activate power-downs
int64_t f_act_pdns;
// Number of slow-exit activate power-downs
int64_t s_act_pdns;
// Number of fast-exit precharged power-downs
int64_t f_pre_pdns;
// Number of slow-exit activate power-downs
int64_t s_pre_pdns;
// Number of self-refresh commands
int64_t numberofsrefs;
// Number of clock cycles in fast-exit activate power-down mode
int64_t f_act_pdcycles;
// Number of clock cycles in slow-exit activate power-down mode
int64_t s_act_pdcycles;
// Number of clock cycles in fast-exit precharged power-down mode
int64_t f_pre_pdcycles;
// Number of clock cycles in slow-exit precharged power-down mode
int64_t s_pre_pdcycles;
// Number of clock cycles in self-refresh mode
int64_t sref_cycles;
// Number of clock cycles in activate power-up mode
int64_t pup_act_cycles;
// Number of clock cycles in precharged power-up mode
int64_t pup_pre_cycles;
// Number of clock cycles in self-refresh power-up mode
int64_t spup_cycles;
// Number of active auto-refresh cycles in self-refresh mode
int64_t sref_ref_act_cycles;
// Number of precharged auto-refresh cycles in self-refresh mode
int64_t sref_ref_pre_cycles;
// Number of active auto-refresh cycles during self-refresh exit
int64_t spup_ref_act_cycles;
// Number of precharged auto-refresh cycles during self-refresh exit
int64_t spup_ref_pre_cycles;
// function for clearing arrays
void clear();
// To identify auto-precharges
void getCommands(const MemorySpecification& memSpec,
const int
nbrofBanks,
std::vector<MemCommand>& list,
bool lastupdate);
private:
unsigned init;
int64_t zero;
unsigned pop;
// Cached last read command from the file
std::vector<MemCommand> cached_cmd;
// Stores the memory commands for analysis
std::vector<MemCommand> cmd_list;
// Stores all memory commands for analysis
std::vector<MemCommand> full_cmd_list;
// To save states of the different banks, before entering active
// power-down mode (slow/fast-exit).
std::vector<int> last_states;
// Bank state vector
std::vector<int> bankstate;
std::vector<int64_t> activation_cycle;
// To keep track of the last ACT cycle
int64_t latest_act_cycle;
// To keep track of the last PRE cycle
int64_t latest_pre_cycle;
// To keep track of the last READ cycle
int64_t latest_read_cycle;
// To keep track of the last WRITE cycle
int64_t latest_write_cycle;
// To calculate end of READ operation
int64_t end_read_op;
// To calculate end of WRITE operation
int64_t end_write_op;
// To calculate end of ACT operation
int64_t end_act_op;
// Clock cycle when self-refresh was issued
int64_t sref_cycle;
// Clock cycle when the latest power-down was issued
int64_t pdn_cycle;
// Memory State
unsigned mem_state;
// Clock cycle of first activate command when memory state changes to ACT
int64_t first_act_cycle;
// Clock cycle of last precharge command when memory state changes to PRE
int64_t last_pre_cycle;
// To collect and analyse all commands including auto-precharges
void analyse_commands(const int nbrofBanks,
Data::MemorySpecification
memSpec,
int64_t nCommands,
int64_t nCached,
bool lastupdate);
// To perform timing analysis of a given set of commands and update command counters
void evaluate(const MemorySpecification& memSpec,
std::vector<MemCommand>& cmd_list,
int nbrofBanks);
// To calculate time of completion of any issued command
int timeToCompletion(const MemorySpecification& memSpec,
MemCommand::cmds type);
// To update idle period information whenever active cycles may be idle
void idle_act_update(const MemorySpecification& memSpec,
int64_t latest_read_cycle,
int64_t latest_write_cycle,
int64_t latest_act_cycle,
int64_t timestamp);
// To update idle period information whenever precharged cycles may be idle
void idle_pre_update(const MemorySpecification& memSpec,
int64_t timestamp,
int64_t latest_pre_cycle);
void printWarningIfActive(const std::string& warning, int type, int64_t timestamp, int bank);
void printWarningIfNotActive(const std::string& warning, int type, int64_t timestamp, int bank);
void printWarning(const std::string& warning, int type, int64_t timestamp, int bank);
};
}
#endif // ifndef COMMAND_TIMINGS_H

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "MemArchitectureSpec.h"
#include <cassert>
using namespace Data;
MemArchitectureSpec::MemArchitectureSpec() :
burstLength(0),
nbrOfBanks(0),
nbrOfRanks(0),
dataRate(0),
nbrOfColumns(0),
nbrOfRows(0),
width(0),
nbrOfBankGroups(0),
dll(false),
twoVoltageDomains(false),
termination(false)
{
}
void MemArchitectureSpec::processParameters()
{
// Load all parameters in our member variables
nbrOfBanks = getParamValWithDefault("nbrOfBanks", 1);
nbrOfRanks = getParamValWithDefault("nbrOfRanks", 1);
nbrOfBankGroups = getParamValWithDefault("nbrOfBankGroups", 1);
dataRate = getParamValWithDefault("dataRate", 1);
burstLength = getParamValWithDefault("burstLength", 1);
nbrOfColumns = getParamValWithDefault("nbrOfColumns", 1);
nbrOfRows = getParamValWithDefault("nbrOfRows", 1);
width = getParamValWithDefault("width", 1);
assert("memory width should be a multiple of 8" && (width % 8) == 0);
dll = getParamValWithDefault("dll", false);
twoVoltageDomains = getParamValWithDefault("twoVoltageDomains", false);
termination = getParamValWithDefault("termination", false);
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H
#define TOOLS_MEM_ARCHITECTURE_SPEC_H
#include "Parametrisable.h"
namespace Data {
class MemArchitectureSpec : public virtual Parametrisable {
public:
MemArchitectureSpec();
void processParameters();
unsigned int burstLength;
unsigned nbrOfBanks;
unsigned nbrOfRanks;
unsigned dataRate;
unsigned nbrOfColumns;
unsigned nbrOfRows;
unsigned width;
unsigned nbrOfBankGroups;
bool dll;
bool twoVoltageDomains;
bool termination;
};
}
#endif // ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "MemCommand.h"
#include <algorithm> // for max
#include "MemorySpecification.h"
using namespace Data;
using namespace std;
MemCommand::MemCommand() :
type(MemCommand::PRE),
bank(0),
timestamp(0)
{
}
MemCommand::MemCommand(MemCommand::cmds type,
unsigned bank, double timestamp) :
type(type),
bank(bank),
timestamp(timestamp)
{
}
void MemCommand::setType(MemCommand::cmds _type)
{
type = _type;
}
MemCommand::cmds MemCommand::getType() const
{
return type;
}
void MemCommand::setBank(unsigned _bank)
{
bank = _bank;
}
unsigned MemCommand::getBank() const
{
return bank;
}
// For auto-precharge with read or write - to calculate cycle of precharge
int MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
MemCommand::cmds type) const
{
int precharge_offset = 0;
int BL(static_cast<int>(memSpec.memArchSpec.burstLength));
int RTP(static_cast<int>(memSpec.memTimingSpec.RTP));
int dataRate(static_cast<int>(memSpec.memArchSpec.dataRate));
int AL(static_cast<int>(memSpec.memTimingSpec.AL));
int WL(static_cast<int>(memSpec.memTimingSpec.WL));
int WR(static_cast<int>(memSpec.memTimingSpec.WR));
int B = BL/dataRate;
const MemoryType::MemoryType_t& memType = memSpec.memoryType;
// Read with auto-precharge
if (type == MemCommand::RDA) {
if (memType == MemoryType::DDR2) {
precharge_offset = B + AL - 2 + max(RTP, 2);
} else if (memType == MemoryType::DDR3) {
precharge_offset = AL + max(RTP, 4);
} else if (memType == MemoryType::DDR4) {
precharge_offset = AL + RTP;
} else if (memType == MemoryType::LPDDR) {
precharge_offset = B;
} else if (memType == MemoryType::LPDDR2) {
precharge_offset = B + max(0, RTP - 2);
} else if (memType == MemoryType::LPDDR3) {
precharge_offset = B + max(0, RTP - 4);
} else if (memType == MemoryType::WIDEIO_SDR) {
precharge_offset = B;
}
} else if (type == MemCommand::WRA) { // Write with auto-precharge
if (memType == MemoryType::DDR2) {
precharge_offset = B + WL + WR;
} else if (memType == MemoryType::DDR3) {
precharge_offset = B + WL + WR;
} else if (memType == MemoryType::DDR4) {
precharge_offset = B + WL + WR;
} else if (memType == MemoryType::LPDDR) {
precharge_offset = B + WR; // + DQSS actually, but we don't have that parameter.
} else if (memType == MemoryType::LPDDR2) {
precharge_offset = B + WL + WR + 1;
} else if (memType == MemoryType::LPDDR3) {
precharge_offset = B + WL + WR + 1;
} else if (memType == MemoryType::WIDEIO_SDR) {
precharge_offset = B + WL + WR - 1;
}
}
return precharge_offset;
} // MemCommand::getPrechargeOffset
void MemCommand::setTime(double _timestamp)
{
timestamp = _timestamp;
}
double MemCommand::getTime() const
{
return timestamp;
}
int64_t MemCommand::getTimeInt64() const
{
return static_cast<int64_t>(timestamp);
}
MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const
{
if (type == MemCommand::RDA) {
return MemCommand::RD;
} else if (type == MemCommand::WRA) {
return MemCommand::WR;
}
return type;
}

View file

@ -0,0 +1,170 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#ifndef MEMCOMMAND_H
#define MEMCOMMAND_H
#include <stdint.h>
#include <cassert>
#include <string>
#include "MemorySpecification.h"
namespace Data {
class MemCommand {
public:
/*
* 1. ACT - Activate
* 2. RD - Read
* 3. WR - Write
* 4. PRE - Explicit Precharge per bank
* 5. REF - Refresh all banks
* 6. END - To indicate end of trace
* 7. RDA - Read with auto-precharge
* 8. WRA - Write with auto-precharge
* 9. PREA - Precharge all banks
* 10. PDN_F_PRE - Precharge Power-down Entry command (Fast-Exit)
* 11. PDN_S_PRE - Precharge Power-down Entry command (Slow-Exit)
* 12. PDN_F_ACT - Active Power-down Entry command (Fast-Exit)
* 13. PDN_S_ACT - Active Power-down Entry command (Slow-Exit)
* 14. PUP_PRE - Precharge Power-down Exit
* 15. PUP_ACT - Active Power-down Exit
* 16. SREN - Self-Refresh Entry command
* 17. SREX - Self-refresh Exit
* 18. NOP - To indicate end of trace
*/
enum cmds {
ACT = 0,
RD = 1,
WR = 2,
PRE = 3,
REF = 4,
END = 5,
RDA = 6,
WRA = 7,
PREA = 8,
PDN_F_PRE = 9,
PDN_S_PRE = 10,
PDN_F_ACT = 11,
PDN_S_ACT = 12,
PUP_PRE = 13,
PUP_ACT = 14,
SREN = 15,
SREX = 16,
NOP = 17
};
MemCommand();
MemCommand(
// Command Type
MemCommand::cmds type,
// Target Bank
unsigned bank = 0,
// Command Issue Timestamp (in cc)
double timestamp = 0);
// Get command type
cmds getType() const;
// Set command type
void setType(MemCommand::cmds type);
// Set target Bank
void setBank(unsigned bank);
// Get target Bank
unsigned getBank() const;
// Set timestamp
void setTime(double _timestamp);
// Get timestamp
double getTime() const;
int64_t getTimeInt64() const;
cmds typeWithoutAutoPrechargeFlag() const;
// To calculate precharge offset after read or write with auto-precharge
int getPrechargeOffset(const MemorySpecification& memSpec,
MemCommand::cmds type) const;
// To check for equivalence
bool operator==(const MemCommand& other) const
{
if ((getType() == other.getType()) &&
(getBank() == other.getBank())
) {
return true;
} else {
return false;
}
}
static const unsigned int nCommands = 18;
static std::string* getCommandTypeStrings()
{
static std::string type_map[nCommands] = { "ACT", "RD", "WR", "PRE", "REF",
"END", "RDA", "WRA", "PREA", "PDN_F_PRE","PDN_S_PRE", "PDN_F_ACT",
"PDN_S_ACT", "PUP_PRE", "PUP_ACT", "SREN", "SREX", "NOP" };
return type_map;
}
// To identify command type from name
static cmds getTypeFromName(const std::string name)
{
std::string* typeStrings = getCommandTypeStrings();
for (size_t typeId = 0; typeId < nCommands; typeId++) {
if (typeStrings[typeId] == name) {
cmds commandType = static_cast<cmds>(typeId);
return commandType;
}
}
assert(false); // Unknown name.
}
private:
MemCommand::cmds type;
unsigned bank;
double timestamp;
};
}
#endif // ifndef MEMCOMMAND_H

View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "MemPowerSpec.h"
using namespace Data;
MemPowerSpec::MemPowerSpec() :
idd0(0.0),
idd02(0.0),
idd2p0(0.0),
idd2p02(0.0),
idd2p1(0.0),
idd2p12(0.0),
idd2n(0.0),
idd2n2(0.0),
idd3p0(0.0),
idd3p02(0.0),
idd3p1(0.0),
idd3p12(0.0),
idd3n(0.0),
idd3n2(0.0),
idd4r(0.0),
idd4r2(0.0),
idd4w(0.0),
idd4w2(0.0),
idd5(0.0),
idd52(0.0),
idd6(0.0),
idd62(0.0),
vdd(0.0),
vdd2(0.0),
capacitance(0.0),
ioPower(0.0),
wrOdtPower(0.0),
termRdPower(0.0),
termWrPower(0.0)
{
}
void MemPowerSpec::processParameters()
{
idd0 = getParamValWithDefault("idd0", 0.0);
idd02 = getParamValWithDefault("idd02", 0.0);
idd2p0 = getParamValWithDefault("idd2p0", 0.0);
idd2p02 = getParamValWithDefault("idd2p02", 0.0);
idd2p1 = getParamValWithDefault("idd2p1", 0.0);
idd2p12 = getParamValWithDefault("idd2p12", 0.0);
idd2n = getParamValWithDefault("idd2n", 0.0);
idd2n2 = getParamValWithDefault("idd2n2", 0.0);
idd3p0 = getParamValWithDefault("idd3p0", 0.0);
idd3p02 = getParamValWithDefault("idd3p02", 0.0);
idd3p1 = getParamValWithDefault("idd3p1", 0.0);
idd3p12 = getParamValWithDefault("idd3p12", 0.0);
idd3n = getParamValWithDefault("idd3n", 0.0);
idd3n2 = getParamValWithDefault("idd3n2", 0.0);
idd4r = getParamValWithDefault("idd4r", 0.0);
idd4r2 = getParamValWithDefault("idd4r2", 0.0);
idd4w = getParamValWithDefault("idd4w", 0.0);
idd4w2 = getParamValWithDefault("idd4w2", 0.0);
idd5 = getParamValWithDefault("idd5", 0.0);
idd52 = getParamValWithDefault("idd52", 0.0);
idd6 = getParamValWithDefault("idd6", 0.0);
idd62 = getParamValWithDefault("idd62", 0.0);
vdd = getParamValWithDefault("vdd", 0.0);
vdd2 = getParamValWithDefault("vdd2", 0.0);
capacitance = getParamValWithDefault("capacitance", 0.0);
ioPower = getParamValWithDefault("ioPower", 0.0);
wrOdtPower = getParamValWithDefault("wrOdtPower", 0.0);
termRdPower = getParamValWithDefault("termRdPower", 0.0);
termWrPower = getParamValWithDefault("termWrPower", 0.0);
} // MemPowerSpec::processParameters

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "Parametrisable.h"
namespace Data {
class MemPowerSpec : public virtual Parametrisable {
public:
MemPowerSpec();
void processParameters();
double idd0;
double idd02;
double idd2p0;
double idd2p02;
double idd2p1;
double idd2p12;
double idd2n;
double idd2n2;
double idd3p0;
double idd3p02;
double idd3p1;
double idd3p12;
double idd3n;
double idd3n2;
double idd4r;
double idd4r2;
double idd4w;
double idd4w2;
double idd5;
double idd52;
double idd6;
double idd62;
double vdd;
double vdd2;
double capacitance;
double ioPower;
double wrOdtPower;
double termRdPower;
double termWrPower;
};
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "MemTimingSpec.h"
using namespace Data;
MemTimingSpec::MemTimingSpec() :
clkMhz(0.0),
RC(0),
RCD(0),
CCD(0),
CCD_S(0),
CCD_L(0),
RRD(0),
RRD_S(0),
RRD_L(0),
FAW(0),
TAW(0),
WTR(0),
WTR_S(0),
WTR_L(0),
REFI(0),
RL(0),
RP(0),
RFC(0),
RAS(0),
WL(0),
AL(0),
DQSCK(0),
RTP(0),
WR(0),
XP(0),
XPDLL(0),
XS(0),
XSDLL(0),
CKE(0),
CKESR(0),
clkPeriod(0.0)
{
}
void MemTimingSpec::processParameters()
{
clkMhz = getParamValWithDefault("clkMhz", 0.0);
RC = getParamValWithDefault("RC", 0);
RCD = getParamValWithDefault("RCD", 0);
CCD = getParamValWithDefault("CCD", 0);
RRD = getParamValWithDefault("RRD", 0);
WTR = getParamValWithDefault("WTR", 0);
CCD_S = getParamValWithDefault("CCD_S", 0);
CCD_L = getParamValWithDefault("CCD_L", 0);
RRD_S = getParamValWithDefault("RRD_S", 0);
RRD_L = getParamValWithDefault("RRD_L", 0);
WTR_S = getParamValWithDefault("WTR_S", 0);
WTR_L = getParamValWithDefault("WTR_L", 0);
TAW = getParamValWithDefault("TAW", 0);
FAW = getParamValWithDefault("FAW", 0);
REFI = getParamValWithDefault("REFI", 0);
RL = getParamValWithDefault("RL", 0);
RP = getParamValWithDefault("RP", 0);
RFC = getParamValWithDefault("RFC", 0);
RAS = getParamValWithDefault("RAS", 0);
WL = getParamValWithDefault("WL", 0);
AL = getParamValWithDefault("AL", 0);
DQSCK = getParamValWithDefault("DQSCK", 0);
RTP = getParamValWithDefault("RTP", 0);
WR = getParamValWithDefault("WR", 0);
XP = getParamValWithDefault("XP", 0);
XPDLL = getParamValWithDefault("XPDLL", 0);
XS = getParamValWithDefault("XS", 0);
XSDLL = getParamValWithDefault("XSDLL", 0);
CKE = getParamValWithDefault("CKE", 0);
CKESR = getParamValWithDefault("CKESR", 0);
clkPeriod = 1000.0 / clkMhz;
} // MemTimingSpec::processParameters

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "Parametrisable.h"
namespace Data {
class MemTimingSpec : public virtual Parametrisable {
public:
MemTimingSpec();
void processParameters();
double clkMhz;
unsigned RC;
unsigned RCD;
unsigned CCD;
unsigned CCD_S;
unsigned CCD_L;
unsigned RRD;
unsigned RRD_S;
unsigned RRD_L;
unsigned FAW;
unsigned TAW;
unsigned WTR;
unsigned WTR_S;
unsigned WTR_L;
unsigned REFI;
unsigned RL;
unsigned RP;
unsigned RFC;
unsigned RAS;
unsigned WL;
unsigned AL;
unsigned DQSCK;
unsigned RTP;
unsigned WR;
unsigned XP;
unsigned XPDLL;
unsigned XS;
unsigned XSDLL;
unsigned CKE;
unsigned CKESR;
double clkPeriod;
};
}

View file

@ -0,0 +1,428 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji
*
*/
#include "MemoryPowerModel.h"
#include <cmath> // For pow
#include <stdint.h>
using namespace std;
using namespace Data;
// Calculate energy and average power consumption for the given command trace
void MemoryPowerModel::power_calc(MemorySpecification memSpec,
const CommandAnalysis& counters,
int term)
{
MemTimingSpec& t = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
MemPowerSpec& mps = memSpec.memPowerSpec;
energy.act_energy = 0.0;
energy.pre_energy = 0.0;
energy.read_energy = 0.0;
energy.write_energy = 0.0;
energy.ref_energy = 0.0;
energy.act_stdby_energy = 0.0;
energy.pre_stdby_energy = 0.0;
energy.idle_energy_act = 0.0;
energy.idle_energy_pre = 0.0;
energy.total_energy = 0.0;
energy.f_act_pd_energy = 0.0;
energy.f_pre_pd_energy = 0.0;
energy.s_act_pd_energy = 0.0;
energy.s_pre_pd_energy = 0.0;
energy.sref_energy = 0.0;
energy.sref_ref_energy = 0.0;
energy.sref_ref_act_energy = 0.0;
energy.sref_ref_pre_energy = 0.0;
energy.spup_energy = 0.0;
energy.spup_ref_energy = 0.0;
energy.spup_ref_act_energy = 0.0;
energy.spup_ref_pre_energy = 0.0;
energy.pup_act_energy = 0.0;
energy.pup_pre_energy = 0.0;
power.IO_power = 0.0;
power.WR_ODT_power = 0.0;
power.TermRD_power = 0.0;
power.TermWR_power = 0.0;
energy.read_io_energy = 0.0;
energy.write_term_energy = 0.0;
energy.read_oterm_energy = 0.0;
energy.write_oterm_energy = 0.0;
energy.io_term_energy = 0.0;
// How long a single burst takes, measured in command-clock cycles.
int64_t burstCc = memArchSpec.burstLength / memArchSpec.dataRate;
// IO and Termination Power measures are included, if required.
if (term) {
io_term_power(memSpec);
// memArchSpec.width represents the number of data (dq) pins.
// 1 DQS pin is associated with every data byte
int64_t dqPlusDqsBits = memArchSpec.width + memArchSpec.width / 8;
// 1 DQS and 1 DM pin is associated with every data byte
int64_t dqPlusDqsPlusMaskBits = memArchSpec.width + memArchSpec.width / 8 + memArchSpec.width / 8;
// Size of one clock period for the data bus.
double ddrPeriod = t.clkPeriod / memArchSpec.dataRate;
// Read IO power is consumed by each DQ (data) and DQS (data strobe) pin
energy.read_io_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength,
ddrPeriod,
power.IO_power,
dqPlusDqsBits);
// Write ODT power is consumed by each DQ (data), DQS (data strobe) and DM
energy.write_term_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength,
ddrPeriod,
power.WR_ODT_power,
dqPlusDqsPlusMaskBits);
if (memArchSpec.nbrOfRanks > 1) {
// Termination power consumed in the idle rank during reads on the active
// rank by each DQ (data) and DQS (data strobe) pin.
energy.read_oterm_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength,
ddrPeriod,
power.TermRD_power,
dqPlusDqsBits);
// Termination power consumed in the idle rank during writes on the active
// rank by each DQ (data), DQS (data strobe) and DM (data mask) pin.
energy.write_oterm_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength,
ddrPeriod,
power.TermWR_power,
dqPlusDqsPlusMaskBits);
}
// Sum of all IO and termination energy
energy.io_term_energy = energy.read_io_energy + energy.write_term_energy
+ energy.read_oterm_energy + energy.write_oterm_energy;
}
total_cycles = counters.actcycles + counters.precycles +
counters.f_act_pdcycles + counters.f_pre_pdcycles +
counters.s_act_pdcycles + counters.s_pre_pdcycles + counters.sref_cycles
+ counters.sref_ref_act_cycles + counters.sref_ref_pre_cycles +
counters.spup_ref_act_cycles + counters.spup_ref_pre_cycles;
EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod);
energy.act_energy = vdd0Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd0 - mps.idd3n);
energy.pre_energy = vdd0Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
energy.read_energy = vdd0Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r - mps.idd3n);
energy.write_energy = vdd0Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w - mps.idd3n);
energy.ref_energy = vdd0Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd5 - mps.idd3n);
energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(counters.precycles, mps.idd2n);
energy.act_stdby_energy = vdd0Domain.calcTivEnergy(counters.actcycles, mps.idd3n);
// Idle energy in the active standby clock cycles
energy.idle_energy_act = vdd0Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n);
// Idle energy in the precharge standby clock cycles
energy.idle_energy_pre = vdd0Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n);
// fast-exit active power-down cycles energy
energy.f_act_pd_energy = vdd0Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p1);
// fast-exit precharged power-down cycles energy
energy.f_pre_pd_energy = vdd0Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p1);
// slow-exit active power-down cycles energy
energy.s_act_pd_energy = vdd0Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p0);
// slow-exit precharged power-down cycles energy
energy.s_pre_pd_energy = vdd0Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p0);
// self-refresh cycles energy including a refresh per self-refresh entry
energy.sref_energy = engy_sref(mps.idd6, mps.idd3n,
mps.idd5, mps.vdd,
static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles),
static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles),
static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod);
// background energy during active auto-refresh cycles in self-refresh
energy.sref_ref_act_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p0);
// background energy during precharged auto-refresh cycles in self-refresh
energy.sref_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p0);
// background energy during active auto-refresh cycles in self-refresh exit
energy.spup_ref_act_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n);
// background energy during precharged auto-refresh cycles in self-refresh exit
energy.spup_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n);
// self-refresh power-up cycles energy -- included
energy.spup_energy = vdd0Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n);
// active power-up cycles energy - same as active standby -- included
energy.pup_act_energy = vdd0Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n);
// precharged power-up cycles energy - same as precharged standby -- included
energy.pup_pre_energy = vdd0Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n);
// similar equations as before to support multiple voltage domains in LPDDR2
// and WIDEIO memories
if (memArchSpec.twoVoltageDomains) {
EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod);
energy.act_energy += vdd2Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd02 - mps.idd3n2);
energy.pre_energy += vdd2Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
energy.read_energy += vdd2Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r2 - mps.idd3n2);
energy.write_energy += vdd2Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w2 - mps.idd3n2);
energy.ref_energy += vdd2Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd52 - mps.idd3n2);
energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(counters.precycles, mps.idd2n2);
energy.act_stdby_energy += vdd2Domain.calcTivEnergy(counters.actcycles, mps.idd3n2);
// Idle energy in the active standby clock cycles
energy.idle_energy_act += vdd2Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n2);
// Idle energy in the precharge standby clock cycles
energy.idle_energy_pre += vdd2Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n2);
// fast-exit active power-down cycles energy
energy.f_act_pd_energy += vdd2Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p12);
// fast-exit precharged power-down cycles energy
energy.f_pre_pd_energy += vdd2Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p12);
// slow-exit active power-down cycles energy
energy.s_act_pd_energy += vdd2Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p02);
// slow-exit precharged power-down cycles energy
energy.s_pre_pd_energy += vdd2Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p02);
energy.sref_energy += engy_sref(mps.idd62, mps.idd3n2,
mps.idd52, mps.vdd2,
static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles),
static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles),
static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod);
// background energy during active auto-refresh cycles in self-refresh
energy.sref_ref_act_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p02);
// background energy during precharged auto-refresh cycles in self-refresh
energy.sref_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p02);
// background energy during active auto-refresh cycles in self-refresh exit
energy.spup_ref_act_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n2);
// background energy during precharged auto-refresh cycles in self-refresh exit
energy.spup_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n2);
// self-refresh power-up cycles energy -- included
energy.spup_energy += vdd2Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n2);
// active power-up cycles energy - same as active standby -- included
energy.pup_act_energy += vdd2Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n2);
// precharged power-up cycles energy - same as precharged standby -- included
energy.pup_pre_energy += vdd2Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n2);
}
// auto-refresh energy during self-refresh cycles
energy.sref_ref_energy = energy.sref_ref_act_energy + energy.sref_ref_pre_energy;
// auto-refresh energy during self-refresh exit cycles
energy.spup_ref_energy = energy.spup_ref_act_energy + energy.spup_ref_pre_energy;
// adding all energy components for the active rank and all background and idle
// energy components for both ranks (in a dual-rank system)
energy.total_energy = energy.act_energy + energy.pre_energy + energy.read_energy +
energy.write_energy + energy.ref_energy + energy.io_term_energy +
memArchSpec.nbrOfRanks * (energy.act_stdby_energy +
energy.pre_stdby_energy + energy.sref_energy +
energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy
+ energy.s_pre_pd_energy + energy.sref_ref_energy + energy.spup_ref_energy);
// Calculate the average power consumption
power.average_power = energy.total_energy / (static_cast<double>(total_cycles) * t.clkPeriod);
} // MemoryPowerModel::power_calc
void MemoryPowerModel::power_print(MemorySpecification memSpec, int term, const CommandAnalysis& counters) const
{
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
cout.precision(0);
cout << "* Trace Details:" << endl;
cout << "Number of Activates: " << fixed << counters.numberofacts << endl;
cout << "Number of Reads: " << counters.numberofreads << endl;
cout << "Number of Writes: " << counters.numberofwrites << endl;
cout << "Number of Precharges: " << counters.numberofpres << endl;
cout << "Number of Refreshes: " << counters.numberofrefs << endl;
cout << "Number of Active Cycles: " << counters.actcycles << endl;
cout << " Number of Active Idle Cycles: " << counters.idlecycles_act << endl;
cout << " Number of Active Power-Up Cycles: " << counters.pup_act_cycles << endl;
cout << " Number of Auto-Refresh Active cycles during Self-Refresh " <<
"Power-Up: " << counters.spup_ref_act_cycles << endl;
cout << "Number of Precharged Cycles: " << counters.precycles << endl;
cout << " Number of Precharged Idle Cycles: " << counters.idlecycles_pre << endl;
cout << " Number of Precharged Power-Up Cycles: " << counters.pup_pre_cycles
<< endl;
cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh"
<< " Power-Up: " << counters.spup_ref_pre_cycles << endl;
cout << " Number of Self-Refresh Power-Up Cycles: " << counters.spup_cycles
<< endl;
cout << "Total Idle Cycles (Active + Precharged): " <<
counters.idlecycles_act + counters.idlecycles_pre << endl;
cout << "Number of Power-Downs: " << counters.f_act_pdns +
counters.s_act_pdns + counters.f_pre_pdns + counters.s_pre_pdns << endl;
cout << " Number of Active Fast-exit Power-Downs: " << counters.f_act_pdns
<< endl;
cout << " Number of Active Slow-exit Power-Downs: " << counters.s_act_pdns
<< endl;
cout << " Number of Precharged Fast-exit Power-Downs: " <<
counters.f_pre_pdns << endl;
cout << " Number of Precharged Slow-exit Power-Downs: " <<
counters.s_pre_pdns << endl;
cout << "Number of Power-Down Cycles: " << counters.f_act_pdcycles +
counters.s_act_pdcycles + counters.f_pre_pdcycles + counters.s_pre_pdcycles << endl;
cout << " Number of Active Fast-exit Power-Down Cycles: " <<
counters.f_act_pdcycles << endl;
cout << " Number of Active Slow-exit Power-Down Cycles: " <<
counters.s_act_pdcycles << endl;
cout << " Number of Auto-Refresh Active cycles during Self-Refresh: " <<
counters.sref_ref_act_cycles << endl;
cout << " Number of Precharged Fast-exit Power-Down Cycles: " <<
counters.f_pre_pdcycles << endl;
cout << " Number of Precharged Slow-exit Power-Down Cycles: " <<
counters.s_pre_pdcycles << endl;
cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh: " <<
counters.sref_ref_pre_cycles << endl;
cout << "Number of Auto-Refresh Cycles: " << counters.numberofrefs *
memTimingSpec.RFC << endl;
cout << "Number of Self-Refreshes: " << counters.numberofsrefs << endl;
cout << "Number of Self-Refresh Cycles: " << counters.sref_cycles << endl;
cout << "----------------------------------------" << endl;
cout << "Total Trace Length (clock cycles): " << total_cycles << endl;
cout << "----------------------------------------" << endl;
cout.precision(2);
cout << "\n* Trace Power and Energy Estimates:" << endl;
cout << "ACT Cmd Energy: " << energy.act_energy << " pJ" << endl;
cout << "PRE Cmd Energy: " << energy.pre_energy << " pJ" << endl;
cout << "RD Cmd Energy: " << energy.read_energy << " pJ" << endl;
cout << "WR Cmd Energy: " << energy.write_energy << " pJ" << endl;
if (term) {
cout << "RD I/O Energy: " << energy.read_io_energy << " pJ" << endl;
// No Termination for LPDDR/2/3 and DDR memories
if (memSpec.memArchSpec.termination) {
cout << "WR Termination Energy: " << energy.write_term_energy << " pJ" << endl;
}
if ((memArchSpec.nbrOfRanks > 1) && memSpec.memArchSpec.termination) {
cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy
<< " pJ" << endl;
cout << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy
<< " pJ" << endl;
}
}
cout << "ACT Stdby Energy: " << memArchSpec.nbrOfRanks * energy.act_stdby_energy <<
" pJ" << endl;
cout << " Active Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_act <<
" pJ" << endl;
cout << " Active Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_act_energy <<
" pJ" << endl;
cout << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh"
<< " Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_act_energy <<
" pJ" << endl;
cout << "PRE Stdby Energy: " << memArchSpec.nbrOfRanks * energy.pre_stdby_energy <<
" pJ" << endl;
cout << " Precharge Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_pre <<
" pJ" << endl;
cout << " Precharged Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_pre_energy <<
" pJ" << endl;
cout << " Precharge Stdby Energy during Auto-Refresh cycles " <<
"in Self-Refresh Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_pre_energy <<
" pJ" << endl;
cout << " Self-Refresh Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.spup_energy <<
" pJ" << endl;
cout << "Total Idle Energy (Active + Precharged): " << memArchSpec.nbrOfRanks *
(energy.idle_energy_act + energy.idle_energy_pre) << " pJ" << endl;
cout << "Total Power-Down Energy: " << memArchSpec.nbrOfRanks * (energy.f_act_pd_energy +
energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << " pJ" << endl;
cout << " Fast-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
energy.f_act_pd_energy << " pJ" << endl;
cout << " Slow-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
energy.s_act_pd_energy << " pJ" << endl;
cout << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles "
<< "in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_act_energy <<
" pJ" << endl;
cout << " Fast-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
energy.f_pre_pd_energy << " pJ" << endl;
cout << " Slow-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
energy.s_pre_pd_energy << " pJ" << endl;
cout << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh " <<
"cycles in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_pre_energy <<
" pJ" << endl;
cout << "Auto-Refresh Energy: " << energy.ref_energy << " pJ" << endl;
cout << "Self-Refresh Energy: " << memArchSpec.nbrOfRanks * energy.sref_energy <<
" pJ" << endl;
cout << "----------------------------------------" << endl;
cout << "Total Trace Energy: " << energy.total_energy << " pJ" << endl;
cout << "Average Power: " << power.average_power << " mW" << endl;
cout << "----------------------------------------" << endl;
} // MemoryPowerModel::power_print
// Self-refresh active energy estimation (not including background energy)
double MemoryPowerModel::engy_sref(double idd6, double idd3n, double idd5,
double vdd, double sref_cycles, double sref_ref_act_cycles,
double sref_ref_pre_cycles, double spup_ref_act_cycles,
double spup_ref_pre_cycles, double clk)
{
double sref_energy;
sref_energy = ((idd6 * sref_cycles) + ((idd5 - idd3n) * (sref_ref_act_cycles
+ spup_ref_act_cycles + sref_ref_pre_cycles + spup_ref_pre_cycles)))
* vdd * clk;
return sref_energy;
}
// IO and Termination power calculation based on Micron Power Calculators
// Absolute power measures are obtained from Micron Power Calculator (mentioned in mW)
void MemoryPowerModel::io_term_power(MemorySpecification memSpec)
{
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
MemPowerSpec& memPowerSpec = memSpec.memPowerSpec;
power.IO_power = memPowerSpec.ioPower; // in mW
power.WR_ODT_power = memPowerSpec.wrOdtPower; // in mW
if (memArchSpec.nbrOfRanks > 1) {
power.TermRD_power = memPowerSpec.termRdPower; // in mW
power.TermWR_power = memPowerSpec.termWrPower; // in mW
}
if (memPowerSpec.capacitance != 0.0) {
// If capacity is given, then IO Power depends on DRAM clock frequency.
power.IO_power = memPowerSpec.capacitance * 0.5 * pow(memPowerSpec.vdd2, 2.0) * memTimingSpec.clkMhz * 1000000;
}
} // MemoryPowerModel::io_term_power
double MemoryPowerModel::calcIoTermEnergy(int64_t cycles, double period, double power, int64_t numBits) const
{
return static_cast<double>(cycles) * period * power * static_cast<double>(numBits);
}
// time (t) * current (I) * voltage (V) energy calculation
double EnergyDomain::calcTivEnergy(int64_t cycles, double current) const
{
return static_cast<double>(cycles) * clkPeriod * current * voltage;
}

View file

@ -0,0 +1,176 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji
*
*/
#ifndef MEMORY_POWER_MODEL_H
#define MEMORY_POWER_MODEL_H
#include "MemorySpecification.h"
#include "CommandAnalysis.h"
namespace Data {
class MemoryPowerModel {
public:
// Calculate energy and average power consumption for the given memory
// command trace
void power_calc(MemorySpecification memSpec,
const CommandAnalysis& counters,
int term);
// Used to calculate self-refresh active energy
static double engy_sref(double idd6,
double idd3n,
double idd5,
double vdd,
double sref_cycles,
double sref_ref_act_cycles,
double sref_ref_pre_cycles,
double spup_ref_act_cycles,
double spup_ref_pre_cycles,
double clk);
int64_t total_cycles;
struct Energy {
// Total energy of all activates
double act_energy;
// Total energy of all precharges
double pre_energy;
// Total energy of all reads
double read_energy;
// Total energy of all writes
double write_energy;
// Total energy of all refreshes
double ref_energy;
// Total background energy of all active standby cycles
double act_stdby_energy;
// Total background energy of all precharge standby cycles
double pre_stdby_energy;
// Total energy of idle cycles in the active mode
double idle_energy_act;
// Total energy of idle cycles in the precharge mode
double idle_energy_pre;
// Total trace/pattern energy
double total_energy;
// Average Power
double average_power;
// Energy consumed in active/precharged fast/slow-exit modes
double f_act_pd_energy;
double f_pre_pd_energy;
double s_act_pd_energy;
double s_pre_pd_energy;
// Energy consumed in self-refresh mode
double sref_energy;
// Energy consumed in auto-refresh during self-refresh mode
double sref_ref_energy;
double sref_ref_act_energy;
double sref_ref_pre_energy;
// Energy consumed in powering-up from self-refresh mode
double spup_energy;
// Energy consumed in auto-refresh during self-refresh power-up
double spup_ref_energy;
double spup_ref_act_energy;
double spup_ref_pre_energy;
// Energy consumed in powering-up from active/precharged power-down modes
double pup_act_energy;
double pup_pre_energy;
// Energy consumed by IO and Termination
double read_io_energy; // Read IO Energy
double write_term_energy; // Write Termination Energy
double read_oterm_energy; // Read Termination Energy from idle rank
double write_oterm_energy; // Write Termination Energy from idle rank
// Total IO and Termination Energy
double io_term_energy;
};
struct Power {
// Power measures corresponding to IO and Termination
double IO_power; // Read IO Power
double WR_ODT_power; // Write ODT Power
double TermRD_power; // Read Termination in idle rank (in dual-rank systems)
double TermWR_power; // Write Termination in idle rank (in dual-rank systems)
// Average Power
double average_power;
};
// Print the power and energy
void power_print(MemorySpecification memSpec,
int term,
const CommandAnalysis& counters) const;
// To derive IO and Termination Power measures using DRAM specification
void io_term_power(MemorySpecification memSpec);
Energy energy;
Power power;
private:
double calcIoTermEnergy(int64_t cycles, double period, double power, int64_t numBits) const;
};
class EnergyDomain {
public:
EnergyDomain(double voltage, double clkPeriod) :
voltage(voltage),
clkPeriod(clkPeriod)
{}
double calcTivEnergy(int64_t cycles, double current) const;
private:
const double voltage;
const double clkPeriod;
};
}
#endif // ifndef MEMORY_POWER_MODEL_H

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#include "MemorySpecification.h"
using namespace std;
using namespace Data;
// Set variable values from XML
void MemorySpecification::processParameters()
{
setVarFromParam(&id,"memoryId");
memoryType = getParamValWithDefault("memoryType", string("DDR3"));
if (hasParameter("memoryType")) {
memArchSpec.twoVoltageDomains = memoryType.hasTwoVoltageDomains();
memArchSpec.dll = memoryType.hasDll();
memArchSpec.termination = memoryType.hasTermination();
memPowerSpec.capacitance = memoryType.getCapacitance();
memPowerSpec.ioPower = memoryType.getIoPower();
memPowerSpec.wrOdtPower = memoryType.getWrOdtPower();
memPowerSpec.termRdPower = memoryType.getTermRdPower();
memPowerSpec.termWrPower = memoryType.getTermWrPower();
}
}

View file

@ -0,0 +1,239 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Karthik Chandrasekar
*
*/
#ifndef TOOLS_MEMORY_SPECIFICATION_H
#define TOOLS_MEMORY_SPECIFICATION_H
#include <cassert>
#include <string>
#include "MemArchitectureSpec.h"
#include "MemTimingSpec.h"
#include "MemPowerSpec.h"
#include "Parametrisable.h"
namespace Data {
// Supported memory types
class MemoryType {
public:
enum MemoryType_t {
DDR2 = 0,
DDR3,
DDR4,
LPDDR,
LPDDR2,
LPDDR3,
WIDEIO_SDR,
MEMORY_TYPE_INVALID
};
MemoryType(MemoryType_t _val) :
val(_val)
{
}
MemoryType() :
val(MEMORY_TYPE_INVALID)
{
}
MemoryType(const std::string& _val) :
val(MEMORY_TYPE_INVALID)
{
if (_val == "DDR2") {
val = DDR2;
} else if (_val == "DDR3") {
val = DDR3;
} else if (_val == "DDR4") {
val = DDR4;
} else if (_val == "LPDDR") {
val = LPDDR;
} else if (_val == "LPDDR2") {
val = LPDDR2;
} else if (_val == "LPDDR3") {
val = LPDDR3;
} else if (_val == "WIDEIO_SDR") {
val = WIDEIO_SDR;
}
assert("Unknown memory type." && val != MEMORY_TYPE_INVALID);
}
bool isLPDDRFamily() const
{
return val == LPDDR ||
val == LPDDR2 ||
val == LPDDR3 ||
val == WIDEIO_SDR;
}
bool hasTwoVoltageDomains() const
{
return val == LPDDR ||
val == LPDDR2 ||
val == LPDDR3 ||
val == WIDEIO_SDR;
}
bool isDDRFamily() const
{
return val == DDR2 ||
val == DDR3 ||
val == DDR4;
}
bool hasDll() const
{
return val == DDR2 ||
val == DDR3 ||
val == DDR4;
}
bool hasTermination() const
{
return val == DDR2 ||
val == DDR3 ||
val == DDR4;
}
double getCapacitance() const
{
// LPDDR/2/3 and DDR memories only have IO Power (no ODT)
// Conservative estimates based on Micron Mobile LPDDR2 Power Calculator
// LPDDR/2/3 IO Capacitance in mF
if (val == LPDDR) {
return 0.0000000045;
} else if (val == LPDDR2) {
return 0.0000000025;
} else if (val == LPDDR3) {
return 0.0000000018;
} else {
return 0.0;
}
}
double getIoPower() const
{
if (val == DDR2) {
// Conservative estimates based on Micron DDR2 Power Calculator
return 1.5; // in mW
} else if (val == DDR3) {
// Conservative estimates based on Micron DDR3 Power Calculator
return 4.6; // in mW
} else if (val == DDR4) {
// Conservative estimates based on Micron DDR3 Power Calculator
// using available termination resistance values from Micron DDR4 Datasheets
return 3.7; // in mW
} else {
return 0.0;
}
}
double getWrOdtPower() const
{
if (val == DDR2) {
// Conservative estimates based on Micron DDR2 Power Calculator
return 8.2; // in mW
} else if (val == DDR3) {
// Conservative estimates based on Micron DDR3 Power Calculator
return 21.2; // in mW
} else if (val == DDR4) {
// Conservative estimates based on Micron DDR3 Power Calculator
// using available termination resistance values from Micron DDR4 Datasheets
return 17.0; // in mW
} else {
return 0.0;
}
}
double getTermRdPower() const
{
if (val == DDR2) {
// Conservative estimates based on Micron DDR2 Power Calculator
return 13.1; // in mW
} else if (val == DDR3) {
// Conservative estimates based on Micron DDR3 Power Calculator
return 15.5; // in mW
} else if (val == DDR4) {
// Conservative estimates based on Micron DDR3 Power Calculator
// using available termination resistance values from Micron DDR4 Datasheets
return 12.4; // in mW
} else {
return 0.0;
}
}
double getTermWrPower() const
{
if (val == DDR2) {
// Conservative estimates based on Micron DDR2 Power Calculator
return 14.6; // in mW
} else if (val == DDR3) {
// Conservative estimates based on Micron DDR3 Power Calculator
return 15.4; // in mW
} else if (val == DDR4) {
// Conservative estimates based on Micron DDR3 Power Calculator
// using available termination resistance values from Micron DDR4 Datasheets
return 12.3; // in mW
} else {
return 0.0;
}
}
operator MemoryType_t() const {
return val;
}
private:
MemoryType_t val;
};
class MemorySpecification : public virtual Parametrisable {
public:
std::string id;
MemoryType memoryType;
MemArchitectureSpec memArchSpec;
MemTimingSpec memTimingSpec;
MemPowerSpec memPowerSpec;
void processParameters();
static MemorySpecification getMemSpecFromXML(const std::string& id);
};
} // namespace Data
#endif // ifndef TOOLS_MEMORY_SPECIFICATION_H

View file

@ -0,0 +1,121 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Hansson
*
*/
#include "Parameter.h"
#include <iomanip>
#include "Utils.h"
using namespace Data;
using namespace std;
Parameter::Parameter(const string& id, const string& type,
const string& value) : id(id), type(type), value(value)
{
}
string Parameter::getId() const
{
return id;
}
string Parameter::getType() const
{
return type;
}
int Parameter::getIntValue() const
{
return fromString<int>(value);
}
unsigned int Parameter::getUIntValue() const
{
bool isHex = value.size() > 1 && value[0] == '0' && value[1] == 'x';
return fromString<unsigned int>(value, isHex ? std::hex : std::dec);
}
#ifdef _LP64
size_t Parameter::getSizeTValue() const
{
bool isHex = value.size() > 1 && value[0] == '0' && value[1] == 'x';
return fromString<size_t>(value, isHex ? std::hex : std::dec);
}
#endif
double Parameter::getDoubleValue() const
{
return fromString<double>(value);
}
bool Parameter::getBoolValue() const
{
return fromString<bool>(value);
}
string Parameter::getValue() const
{
return value;
}
Parameter Data::HexParameter(const string& id, int value)
{
std::ostringstream ss;
ss << "0x" << hex << setw(8) << setfill('0') << value;
return Parameter(id, "int", ss.str());
}
Parameter Data::StringParameter(const string& id, const string& value)
{
return Parameter(id, "string", value);
}
ostream& Data::operator<<(ostream& os, const Parameter& parameter)
{
os << "<parameter " <<
"id=\"" << parameter.getId() << "\" " <<
"type=\"" << parameter.getType() << "\" "
"value=\"" << parameter.getValue() << "\" />";
return os;
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Hansson
*
*/
#ifndef DATA_PARAMETER_H
#define DATA_PARAMETER_H
#include <string>
#include <ostream>
namespace Data {
class Parameter {
public:
Parameter(const std::string& id, const std::string& type,
const std::string& value);
std::string getId() const;
std::string getType() const;
std::string getValue() const;
int getIntValue() const;
unsigned int getUIntValue() const;
size_t getSizeTValue() const;
double getDoubleValue() const;
bool getBoolValue() const;
operator int() const {
return getIntValue();
}
operator unsigned int() const {
return getUIntValue();
}
#ifdef _LP64
operator size_t() const {
return getSizeTValue();
}
#endif
operator double() const {
return getDoubleValue();
}
operator bool() const {
return getBoolValue();
}
operator std::string() const {
return getValue();
}
private:
std::string id;
std::string type;
std::string value;
};
Parameter HexParameter(const std::string& id,
int value);
Parameter StringParameter(const std::string& id,
const std::string& value);
std::ostream& operator<<(std::ostream& os,
const Parameter& parameter);
}
#endif // ifndef DATA_PARAMETER_H

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Hansson
*
*/
#include "Parametrisable.h"
#include <iostream>
#include <cstdlib>
using namespace Data;
using namespace std;
void Parametrisable::pushParameter(const Parameter& parameter)
{
parameters.push_back(parameter);
}
void Parametrisable::setParameter(const Parameter& parameter,
unsigned int index)
{
unsigned int count = 0;
vector<Parameter>::iterator p = parameters.begin();
while (p != parameters.end() && !(p->getId() == parameter.getId() &&
index == count)) {
if (p->getId() == parameter.getId())
++count;
++p;
}
if (p == parameters.end()) {
parameters.push_back(parameter);
} else {
p = parameters.erase(p);
parameters.insert(p, parameter);
}
} // Parametrisable::setParameter
bool Parametrisable::removeParameter(const string& id, unsigned int index)
{
unsigned int count = 0;
for (vector<Parameter>::iterator p = parameters.begin();
p != parameters.end(); ++p) {
if ((p->getId() == id) && (index == count++)) {
parameters.erase(p);
return true;
}
}
return false;
}
/**
* Get a parameter with a specific id. Should there be a multiplicity,
* then the index is used to determine which instance is returned, in
* order traversal.
*/
Parameter Parametrisable::getParameter(const string& id,
unsigned int index) const
{
unsigned int count = 0;
for (vector<Parameter>::const_iterator p = parameters.begin();
p != parameters.end(); ++p) {
if ((p->getId() == id) && (index == count++)) {
return *p;
}
}
cerr << "Could not find parameter '" << id << "' (" << index << ")" << endl;
cerr << "Stored parameters are: " << endl;
for (vector<Parameter>::const_iterator p = parameters.begin();
p != parameters.end(); ++p) {
cerr << " " << p->getId() << ": " << p->getValue() << endl;
}
exit(1);
return Parameter("", "", "");
} // Parametrisable::getParameter
vector<Parameter> Parametrisable::getParameters() const
{
return parameters;
}
bool Parametrisable::hasParameter(const string& id, unsigned int index) const
{
unsigned int count = 0;
for (vector<Parameter>::const_iterator p = parameters.begin();
p != parameters.end(); ++p) {
if ((p->getId() == id) && (index == count++)) {
return true;
}
}
return false;
}

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Hansson
*
*/
#ifndef DATA_PARAMETRISABLE_H
#define DATA_PARAMETRISABLE_H
#include <string>
#include <vector>
#include "Parameter.h"
namespace Data {
/**
* Convenience class for the architectural components that are
* parametrisable. The interface is shared and implemented only in
* this class.
*/
class Parametrisable {
public:
Parametrisable()
{
}
virtual ~Parametrisable()
{
}
/**
* Push a new parameter into the in-order vector without checking
* for duplicates.
*/
virtual void pushParameter(const Parameter& parameter);
/**
* Set a parameter with a given index (default 0). This could for
* example be a queue size for a given channel id.
*/
void setParameter(const Parameter& parameter,
unsigned int index = 0);
/**
* Get a parameter of a given name and of a certain index. Calling
* this method on an object that has no parameter of that name
* will result in application exit.
*/
Parameter getParameter(const std::string& id,
unsigned int index = 0) const;
/**
* Remove a parameter with a specific name and index. If a parameter
* is removed this method returns true, otherwise false.
*/
bool removeParameter(const std::string& id,
unsigned int index = 0);
/**
* Simply get all the parameters.
*/
std::vector<Parameter> getParameters() const;
/**
* Check if a parameter of a certain name exists in the object.
*/
bool hasParameter(const std::string& id,
unsigned int index = 0) const;
/**
* Convenience function to set a variable to the value stored in a parameter
* with built in error detection/assertion. Returns true if the value was
* successfully set.
* @param m
* @param paramName
* @param assertOnFail
* @return
*/
template<typename T>
bool setVarFromParam(T* m, const char* paramName)
{
if (hasParameter(paramName)) {
*m = static_cast<T>(getParameter(paramName));
return true;
} else {
*m = static_cast<T>(0);
return false;
}
}
template<typename T>
T getParamValWithDefault(const char* paramName, T defaultVal) const
{
if (hasParameter(paramName)) {
return static_cast<T>(getParameter(paramName));
} else {
return defaultVal;
}
}
protected:
std::vector<Parameter> parameters;
};
}
#endif // ifndef DATA_PARAMETRISABLE_H

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Omar Naji
*
*/
#include "TraceParser.h"
#include "CommandAnalysis.h"
#include "CmdScheduler.h"
using namespace Data;
using namespace std;
Data::MemCommand TraceParser::parseLine(std::string line)
{
MemCommand memcmd;
istringstream linestream(line);
string item;
double item_val;
unsigned itemnum = 0;
MemCommand::cmds type = MemCommand::NOP; // Initialized to prevent warning
while (getline(linestream, item, ',')) {
if (itemnum == 0) {
stringstream timestamp(item);
timestamp >> item_val;
memcmd.setTime(item_val);
} else if (itemnum == 1) {
item_val = MemCommand::getTypeFromName(item);
memcmd.setType(static_cast<MemCommand::cmds>(item_val));
} else if (itemnum == 2) {
stringstream bank(item);
bank >> item_val;
memcmd.setType(type);
memcmd.setBank(static_cast<unsigned>(item_val));
}
type = memcmd.getType();
itemnum++;
}
return memcmd;
} // TraceParser::parseLine
void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
int window, int grouping, int interleaving, int burst,
int powerdown, int trans)
{
ifstream pwr_trace;
counters = CommandAnalysis(memSpec.memArchSpec.nbrOfBanks);
int nCommands = 0;
bool lastupdate = false;
if (trans) {
cmdScheduler cmdsched;
cmdsched.transTranslation(memSpec, trace, grouping, interleaving, burst, powerdown);
pwr_trace.open("commands.trace", ifstream::in);
std::string line;
while (getline(pwr_trace, line)) {
MemCommand cmdline = parseLine(line);
cmd_list.push_back(cmdline);
nCommands++;
if (nCommands == window) {
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
nCommands = 0;
cmd_list.clear();
}
}
lastupdate = true;
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
cmd_list.clear();
pwr_trace.close();
} else {
std::string line;
while (getline(trace, line)) {
MemCommand cmdline = parseLine(line);
cmd_list.push_back(cmdline);
nCommands++;
if (nCommands == window) {
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
nCommands = 0;
cmd_list.clear();
}
}
lastupdate = true;
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
cmd_list.clear();
}
counters.clear();
trace.close();
} // TraceParser::parseFile

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Omar Naji
*
*/
#ifndef TRACE_PARSER_H
#define TRACE_PARSER_H
#include <vector>
#include <string>
#include "MemCommand.h"
#include "MemorySpecification.h"
#include "CommandAnalysis.h"
class TraceParser {
public:
// list of parsed commands
std::vector<Data::MemCommand> cmd_list;
// function for parsing one line of the trace
Data::MemCommand parseLine(std::string line);
Data::CommandAnalysis counters;
// function for parsing the whole file.
// use this function for small traces ( no out-of-memory issue )
void parseFile(Data::MemorySpecification memSpec,
std::ifstream& trace,
int window,
int grouping,
int interleaving,
int burst,
int powerdown,
int trans);
};
#endif // ifndef TRACE_PARSER_H

64
ext/drampower/src/Utils.h Normal file
View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Hansson
*
*/
#ifndef UTILS_H
#define UTILS_H
#include <string>
#include <sstream>
#include <stdexcept>
#include <typeinfo>
#define MILLION 1000000
template<typename T>
T fromString(const std::string& s,
std::ios_base& (*f)(std::ios_base &) = std::dec)
throw(std::runtime_error)
{
std::istringstream is(s);
T t;
if (!(is >> f >> t)) {
throw std::runtime_error("Cannot convert '" + s + "' to " +
typeid(t).name() + " using fromString");
}
return t;
}
#endif /* UTILS_H */

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Matthias Jung, Omar Naji
*
*/
#include "LibDRAMPower.h"
using namespace Data;
libDRAMPower::libDRAMPower(const MemorySpecification& memSpec, bool includeIoAndTermination) :
memSpec(memSpec),
counters(CommandAnalysis(memSpec.memArchSpec.nbrOfBanks)),
includeIoAndTermination(includeIoAndTermination)
{
}
libDRAMPower::~libDRAMPower()
{
}
void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp)
{
MemCommand cmd(type, static_cast<unsigned>(bank), static_cast<double>(timestamp));
cmdList.push_back(cmd);
}
void libDRAMPower::updateCounters(bool lastUpdate)
{
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmdList, lastUpdate);
cmdList.clear();
}
void libDRAMPower::calcEnergy()
{
mpm.power_calc(memSpec, counters, includeIoAndTermination);
}
void libDRAMPower::clearState()
{
counters.clear();
}
const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const
{
return mpm.energy;
}
const Data::MemoryPowerModel::Power& libDRAMPower::getPower() const
{
return mpm.power;
}

View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 2012-2014, TU Delft
* Copyright (c) 2012-2014, TU Eindhoven
* Copyright (c) 2012-2014, TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Matthias Jung, Omar Naji
*
*/
#ifndef LIB_DRAM_POWER_H
#define LIB_DRAM_POWER_H
#include <stdint.h>
#include <vector>
#include "CommandAnalysis.h"
#include "MemoryPowerModel.h"
#include "MemCommand.h"
class libDRAMPower {
public:
libDRAMPower(const Data::MemorySpecification& memSpec, bool includeIoAndTermination);
~libDRAMPower();
void doCommand(Data::MemCommand::cmds type,
int bank,
int64_t timestamp);
void updateCounters(bool lastUpdate);
void clearState();
void calcEnergy();
const Data::MemoryPowerModel::Energy& getEnergy() const;
const Data::MemoryPowerModel::Power& getPower() const;
// list of all commands
std::vector<Data::MemCommand> cmdList;
private:
Data::MemorySpecification memSpec;
public:
Data::CommandAnalysis counters;
private:
bool includeIoAndTermination;
// Object of MemoryPowerModel which contains the results
// Energies(pJ) stored in energy, Powers(mW) stored in power. Number of
// each command stored in timings.
Data::MemoryPowerModel mpm;
};
#endif // ifndef LIB_DRAM_POWER_H

View file

@ -0,0 +1,280 @@
tok_split_gte=false
utf8_byte=false
utf8_force=false
indent_cmt_with_tabs=false
indent_align_string=true
indent_braces=false
indent_braces_no_func=false
indent_braces_no_class=false
indent_braces_no_struct=false
indent_brace_parent=false
indent_namespace=false
indent_extern=false
indent_class=true
indent_class_colon=true
indent_else_if=false
indent_var_def_cont=false
indent_func_call_param=false
indent_func_def_param=false
indent_func_proto_param=false
indent_func_class_param=false
indent_func_ctor_var_param=false
indent_template_param=false
indent_func_param_double=false
indent_relative_single_line_comments=false
indent_col1_comment=true
indent_access_spec_body=false
indent_paren_nl=false
indent_comma_paren=false
indent_bool_paren=false
indent_first_bool_expr=false
indent_square_nl=false
indent_preserve_sql=false
indent_align_assign=true
sp_balance_nested_parens=false
align_keep_tabs=false
align_with_tabs=false
align_on_tabstop=false
align_number_left=true
align_func_params=true
align_same_func_call_params=true
align_var_def_colon=true
align_var_def_attribute=true
align_var_def_inline=true
align_right_cmt_mix=false
align_on_operator=true
align_mix_var_proto=false
align_single_line_func=true
align_single_line_brace=true
align_nl_cont=true
align_left_shift=true
align_oc_decl_colon=false
nl_collapse_empty_body=false
nl_assign_leave_one_liners=false
nl_class_leave_one_liners=false
nl_enum_leave_one_liners=false
nl_getset_leave_one_liners=false
nl_func_leave_one_liners=false
nl_if_leave_one_liners=false
nl_multi_line_cond=false
nl_multi_line_define=false
nl_before_case=true
nl_after_case=false
nl_after_return=true
nl_after_semicolon=true
nl_after_brace_open=false
nl_after_brace_open_cmt=false
nl_after_vbrace_open=false
nl_after_vbrace_open_empty=false
nl_after_brace_close=false
nl_after_vbrace_close=false
nl_define_macro=true
nl_squeeze_ifdef=false
nl_ds_struct_enum_cmt=true
nl_ds_struct_enum_close_brace=true
nl_create_if_one_liner=false
nl_create_for_one_liner=false
nl_create_while_one_liner=false
ls_for_split_full=false
ls_func_split_full=false
nl_after_multiline_comment=true
eat_blanks_after_open_brace=true
eat_blanks_before_close_brace=true
mod_full_brace_if_chain=true
mod_pawn_semicolon=false
mod_full_paren_if_bool=true
mod_remove_extra_semicolon=true
mod_sort_import=false
mod_sort_using=false
mod_sort_include=false
mod_move_case_break=true
mod_remove_empty_return=true
cmt_indent_multi=true
cmt_c_group=false
cmt_c_nl_start=false
cmt_c_nl_end=false
cmt_cpp_group=false
cmt_cpp_nl_start=false
cmt_cpp_nl_end=false
cmt_cpp_to_c=false
cmt_star_cont=false
cmt_multi_check_last=true
cmt_insert_before_preproc=false
pp_indent_at_level=false
pp_region_indent_code=false
pp_if_indent_code=false
pp_define_at_level=false
output_tab_size=2
indent_columns=2
indent_namespace_level=0
indent_namespace_limit=0
indent_access_spec=-1
align_var_def_span=2
align_var_def_star_style=0
align_var_def_amp_style=0
align_var_def_thresh=2
align_var_def_gap=1
align_assign_span=3
align_assign_thresh=12
align_enum_equ_span=1
align_var_struct_span=1
align_struct_init_span=1
align_typedef_span=1
align_typedef_star_style=2
align_typedef_amp_style=2
align_right_cmt_span=4
align_right_cmt_at_col=1
align_func_proto_span=1
nl_end_of_file_min=1
nl_func_var_def_blk=1
nl_max=2
nl_after_func_proto=0
nl_after_func_body=2
nl_after_func_body_class=2
nl_after_func_body_one_liner=2
nl_before_access_spec=2
nl_after_access_spec=1
nl_comment_func_def=1
nl_after_try_catch_finally=1
mod_full_brace_nl=1
mod_add_long_function_closebrace_comment=16
mod_add_long_switch_closebrace_comment=16
mod_add_long_ifdef_endif_comment=16
mod_add_long_ifdef_else_comment=16
newlines=auto
indent_with_tabs=0
sp_arith=add
sp_assign=add
sp_enum_assign=add
sp_pp_concat=add
sp_pp_stringify=add
sp_bool=add
sp_compare=add
sp_inside_paren=remove
sp_paren_paren=remove
sp_paren_brace=add
sp_before_ptr_star=remove
sp_before_unnamed_ptr_star=remove
sp_between_ptr_star=remove
sp_after_ptr_star=force
sp_after_ptr_star_func=force
sp_before_ptr_star_func=remove
sp_before_byref=remove
sp_before_unnamed_byref=remove
sp_after_byref=add
sp_after_byref_func=add
sp_before_byref_func=remove
sp_after_type=add
sp_before_angle=remove
sp_inside_angle=remove
sp_after_angle=remove
sp_angle_paren=remove
sp_angle_word=force
sp_before_sparen=force
sp_inside_sparen=remove
sp_after_sparen=remove
sp_sparen_brace=add
sp_special_semi=remove
sp_before_semi=remove
sp_before_semi_for=remove
sp_before_semi_for_empty=remove
sp_after_semi_for_empty=remove
sp_before_square=remove
sp_before_squares=remove
sp_inside_square=remove
sp_after_comma=add
sp_before_comma=remove
sp_after_class_colon=add
sp_before_class_colon=add
sp_before_case_colon=remove
sp_after_operator=remove
sp_after_operator_sym=remove
sp_after_cast=remove
sp_inside_paren_cast=remove
sp_cpp_cast_paren=remove
sp_sizeof_paren=remove
sp_inside_braces_enum=add
sp_inside_braces_struct=add
sp_inside_braces=add
sp_inside_braces_empty=remove
sp_type_func=add
sp_func_proto_paren=remove
sp_func_def_paren=remove
sp_inside_fparens=remove
sp_inside_fparen=remove
sp_square_fparen=remove
sp_fparen_brace=add
sp_func_call_paren=remove
sp_func_call_user_paren=remove
sp_func_class_paren=remove
sp_return_paren=add
sp_attribute_paren=remove
sp_defined_paren=remove
sp_throw_paren=remove
sp_macro=add
sp_macro_func=remove
sp_else_brace=add
sp_brace_else=add
sp_brace_typedef=add
sp_catch_brace=add
sp_brace_catch=add
sp_finally_brace=add
sp_brace_finally=add
sp_try_brace=add
sp_getset_brace=add
sp_before_dc=remove
sp_after_dc=remove
sp_not=remove
sp_inv=remove
sp_addr=remove
sp_member=remove
sp_deref=remove
sp_sign=remove
sp_incdec=remove
sp_before_nl_cont=remove
sp_after_oc_scope=remove
sp_after_oc_colon=remove
sp_before_oc_colon=remove
sp_after_send_oc_colon=add
sp_before_send_oc_colon=remove
sp_after_oc_type=remove
sp_cond_colon=add
sp_cond_question=add
sp_cmt_cpp_start=add
nl_start_of_file=remove
nl_end_of_file=force
nl_fcall_brace=force
nl_if_brace=remove
nl_brace_else=remove
nl_elseif_brace=remove
nl_else_brace=remove
nl_else_if=remove
nl_for_brace=remove
nl_while_brace=remove
nl_do_brace=remove
nl_switch_brace=remove
nl_namespace_brace=remove
nl_class_brace=remove
nl_class_init_args=add
nl_func_def_paren=remove
nl_func_decl_start=remove
nl_func_decl_args=add
nl_fdef_brace=force
nl_before_if=ignore
nl_after_if=ignore
nl_before_for=ignore
nl_after_for=ignore
nl_before_while=ignore
nl_after_while=ignore
nl_before_switch=ignore
nl_after_switch=ignore
nl_before_do=ignore
nl_after_do=ignore
mod_full_brace_do=force
mod_full_brace_for=force
mod_full_brace_function=force
mod_full_brace_if=force
mod_full_brace_while=force
mod_full_brace_using=remove
mod_paren_on_return=remove
pp_space=force

View file

@ -0,0 +1,82 @@
# Copyright (c) 2012-2014, TU Delft
# Copyright (c) 2012-2014, TU Eindhoven
# Copyright (c) 2012-2014, TU Kaiserslautern
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Matthias Jung, Omar Naji, Sven Goossens
#
ifeq ($(COVERAGE),1)
GCOVFLAGS := -fprofile-arcs -ftest-coverage
else
GCOVFLAGS :=
endif
# Optimization flags. Usually you should not optimize until you have finished
# debugging, except when you want to detect dead code.
OPTCXXFLAGS ?=
# Debugging flags.
DBGCXXFLAGS ?= -g ${GCOVFLAGS}
# Common warning flags shared by both C and C++.
WARNFLAGS := -W -pedantic-errors -Wextra -Werror \
-Wformat -Wformat-nonliteral -Wpointer-arith \
-Wcast-align -Wconversion -Wall -Werror
# Sum up the flags.
CXXFLAGS := -O ${WARNFLAGS} ${DBGCXXFLAGS} ${OPTCXXFLAGS} -std=c++98
DRAMPOWER_PATH ?= ../..
MYPATH := ${DRAMPOWER_PATH}/test/libdrampowertest
USE_XERCES ?= 1
# Name of the generated binary.
BINARY := ${MYPATH}/library_test
ifeq ($(USE_XERCES),1)
LIBS := -lxerces-c -ldrampowerxml -ldrampower
else
LIBS := -ldrampower
endif
all:
g++ ${MYPATH}/lib_test.cc ${CXXFLAGS} -iquote ${DRAMPOWER_PATH}/src -DUSE_XERCES=${USE_XERCES} -L${DRAMPOWER_PATH}/src/ ${LIBS} -o $(BINARY)
clean:
rm -f $(BINARY)
coverageclean:
$(RM) lib_test.gcno lib_test.gcda
test: all
./$(BINARY) ${DRAMPOWER_PATH}/memspecs/MICRON_1Gb_DDR2-1066_16bit_H.xml
.PHONY: clean test

View file

@ -0,0 +1,19 @@
35,ACT,0
50,RDA,0
51,ACT,4
66,RDA,4
86,ACT,0
101,RDA,0
102,ACT,2
117,RDA,2
119,ACT,5
134,RDA,5
137,ACT,0
152,RDA,0
159,ACT,3
174,RDA,3
195,ACT,0
210,RDA,0
232,ACT,4
247,WRA,4
248,PDN_F_ACT,3

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2014, TU Delft, TU Eindhoven and TU Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Matthias Jung, Omar Naji
*
*/
#include <string>
#include "libdrampower/LibDRAMPower.h"
#if USE_XERCES
#include "xmlparser/MemSpecParser.h"
#endif
using namespace std;
using namespace Data;
int main(int argc, char* argv[])
{
assert(argc == 2);
//Setup of DRAMPower for your simulation
string filename;
//type path to memspec file
filename = argv[1];
//Parsing the Memspec specification of found in memspec folder
#if USE_XERCES
MemorySpecification memSpec(MemSpecParser::getMemSpecFromXML(filename));
#else
MemorySpecification memSpec;
#endif
libDRAMPower test = libDRAMPower(memSpec, 0);
// During the simulation you can report activity
// to DRAMPower with the doCommand(...) function:
test.doCommand(MemCommand::ACT,0,35);
test.doCommand(MemCommand::RDA,0,50);
test.doCommand(MemCommand::ACT,4,51);
test.doCommand(MemCommand::RDA,4,66);
test.doCommand(MemCommand::ACT,0,86);
test.doCommand(MemCommand::RDA,0,101);
test.doCommand(MemCommand::ACT,2,102);
//This functionality is still not implemented.
test.updateCounters(false);
test.doCommand(MemCommand::RDA,2,117);
test.doCommand(MemCommand::ACT,5,119);
test.doCommand(MemCommand::RDA,5,134);
test.doCommand(MemCommand::ACT,0,137);
test.doCommand(MemCommand::RDA,0,152);
test.doCommand(MemCommand::ACT,3,159);
test.doCommand(MemCommand::RDA,3,174);
test.doCommand(MemCommand::ACT,0,195);
test.doCommand(MemCommand::RDA,0,210);
test.doCommand(MemCommand::ACT,4,232);
test.doCommand(MemCommand::WRA,4,247);
test.doCommand(MemCommand::PDN_F_ACT,3,248);
//set bool to true when this is the last update of the counters
test.updateCounters(true);
// At the end of your simulation call the getEnergy(...)
// function to print the power report
test.calcEnergy();
// Accesing the results:
// Number of issued Commands
std::cout << "# of acts" << "\t" <<test.counters.numberofacts << endl;
std::cout << "# of reads" << "\t" <<test.counters.numberofreads << endl;
std::cout << "# of precharges" << "\t" <<test.counters.numberofpres << endl;
// many other timing parameters in test.mpm.timings
//ENERGIES per Rank
std::cout << "ACT Cmd Energy" << "\t" << test.getEnergy().act_energy << endl;
std::cout << "PRE Cmd Energy" << "\t" << test.getEnergy().pre_energy << endl;
std::cout << "Read Cmd Energy" << "\t" << test.getEnergy().read_energy << endl;
std::cout << "Write Cmd Energy" << "\t" << test.getEnergy().write_energy << endl;
//Standby Energy for 1 rank
//In total energy calculated for both ranks= test.memSpec.memArchSpec *
//test.getEnergy().act_stdby_energy
std::cout << "ACT Std Energy" << "\t" << test.getEnergy().act_stdby_energy << endl;
//total active standby energy for both ranks
std::cout << "ACT Std Energy total ranks" << "\t" << memSpec.memArchSpec.nbrOfRanks *
test.getEnergy().act_stdby_energy << "\n" ;
std::cout << "PRE Std Energy" << "\t" << test.getEnergy().pre_stdby_energy << endl;
std::cout << "Total Energy" << "\t" << test.getEnergy().total_energy << endl;
//many other energies in test.mpm.energy
//Powers per Rank
std::cout << "Average Power" << "\t" << test.getPower().average_power << endl;
//many other powers in test.getPower()
// Test clearState function.
test.clearState();
return 0;
}