diff options
author | Andreas Hansson <andreas.hansson@arm.com> | 2014-10-09 17:52:03 -0400 |
---|---|---|
committer | Andreas Hansson <andreas.hansson@arm.com> | 2014-10-09 17:52:03 -0400 |
commit | e0e8b08a42210011205b52c3628749f60658e58c (patch) | |
tree | e6daae3c8cd249f52c6504ee2b7fc07805085429 /ext | |
parent | c81517c293cdd3f612efae94d1143fb0cf002287 (diff) | |
download | gem5-e0e8b08a42210011205b52c3628749f60658e58c.tar.xz |
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.
Diffstat (limited to 'ext')
32 files changed, 5343 insertions, 0 deletions
diff --git a/ext/drampower/ChangeLog b/ext/drampower/ChangeLog new file mode 100644 index 000000000..e05228e48 --- /dev/null +++ b/ext/drampower/ChangeLog @@ -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. diff --git a/ext/drampower/README.md b/ext/drampower/README.md new file mode 100644 index 000000000..a43298b01 --- /dev/null +++ b/ext/drampower/README.md @@ -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. diff --git a/ext/drampower/SConscript b/ext/drampower/SConscript new file mode 100644 index 000000000..2330aa85f --- /dev/null +++ b/ext/drampower/SConscript @@ -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('.')]) diff --git a/ext/drampower/src/CmdScheduler.cc b/ext/drampower/src/CmdScheduler.cc new file mode 100644 index 000000000..bffc5d3bb --- /dev/null +++ b/ext/drampower/src/CmdScheduler.cc @@ -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 diff --git a/ext/drampower/src/CmdScheduler.h b/ext/drampower/src/CmdScheduler.h new file mode 100644 index 000000000..3c60ea886 --- /dev/null +++ b/ext/drampower/src/CmdScheduler.h @@ -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 diff --git a/ext/drampower/src/CommandAnalysis.cc b/ext/drampower/src/CommandAnalysis.cc new file mode 100644 index 000000000..4dea5c101 --- /dev/null +++ b/ext/drampower/src/CommandAnalysis.cc @@ -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; +} diff --git a/ext/drampower/src/CommandAnalysis.h b/ext/drampower/src/CommandAnalysis.h new file mode 100644 index 000000000..b5c7ac778 --- /dev/null +++ b/ext/drampower/src/CommandAnalysis.h @@ -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 diff --git a/ext/drampower/src/MemArchitectureSpec.cc b/ext/drampower/src/MemArchitectureSpec.cc new file mode 100644 index 000000000..f3155853d --- /dev/null +++ b/ext/drampower/src/MemArchitectureSpec.cc @@ -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); +} diff --git a/ext/drampower/src/MemArchitectureSpec.h b/ext/drampower/src/MemArchitectureSpec.h new file mode 100644 index 000000000..ca79edc91 --- /dev/null +++ b/ext/drampower/src/MemArchitectureSpec.h @@ -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 diff --git a/ext/drampower/src/MemCommand.cc b/ext/drampower/src/MemCommand.cc new file mode 100644 index 000000000..156716c2f --- /dev/null +++ b/ext/drampower/src/MemCommand.cc @@ -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; +} diff --git a/ext/drampower/src/MemCommand.h b/ext/drampower/src/MemCommand.h new file mode 100644 index 000000000..4159fe008 --- /dev/null +++ b/ext/drampower/src/MemCommand.h @@ -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 diff --git a/ext/drampower/src/MemPowerSpec.cc b/ext/drampower/src/MemPowerSpec.cc new file mode 100644 index 000000000..3fbc53992 --- /dev/null +++ b/ext/drampower/src/MemPowerSpec.cc @@ -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 diff --git a/ext/drampower/src/MemPowerSpec.h b/ext/drampower/src/MemPowerSpec.h new file mode 100644 index 000000000..f6958820d --- /dev/null +++ b/ext/drampower/src/MemPowerSpec.h @@ -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; +}; +} diff --git a/ext/drampower/src/MemTimingSpec.cc b/ext/drampower/src/MemTimingSpec.cc new file mode 100644 index 000000000..cf18c5f7b --- /dev/null +++ b/ext/drampower/src/MemTimingSpec.cc @@ -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 diff --git a/ext/drampower/src/MemTimingSpec.h b/ext/drampower/src/MemTimingSpec.h new file mode 100644 index 000000000..1c3a80c6e --- /dev/null +++ b/ext/drampower/src/MemTimingSpec.h @@ -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; +}; +} diff --git a/ext/drampower/src/MemoryPowerModel.cc b/ext/drampower/src/MemoryPowerModel.cc new file mode 100644 index 000000000..4817d1bb5 --- /dev/null +++ b/ext/drampower/src/MemoryPowerModel.cc @@ -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; +} diff --git a/ext/drampower/src/MemoryPowerModel.h b/ext/drampower/src/MemoryPowerModel.h new file mode 100644 index 000000000..b894f67dd --- /dev/null +++ b/ext/drampower/src/MemoryPowerModel.h @@ -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 diff --git a/ext/drampower/src/MemorySpecification.cc b/ext/drampower/src/MemorySpecification.cc new file mode 100644 index 000000000..3f9f18811 --- /dev/null +++ b/ext/drampower/src/MemorySpecification.cc @@ -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(); + } +} diff --git a/ext/drampower/src/MemorySpecification.h b/ext/drampower/src/MemorySpecification.h new file mode 100644 index 000000000..149d41c28 --- /dev/null +++ b/ext/drampower/src/MemorySpecification.h @@ -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 diff --git a/ext/drampower/src/Parameter.cc b/ext/drampower/src/Parameter.cc new file mode 100644 index 000000000..9767e1c94 --- /dev/null +++ b/ext/drampower/src/Parameter.cc @@ -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; +} diff --git a/ext/drampower/src/Parameter.h b/ext/drampower/src/Parameter.h new file mode 100644 index 000000000..2c9623eeb --- /dev/null +++ b/ext/drampower/src/Parameter.h @@ -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 diff --git a/ext/drampower/src/Parametrisable.cc b/ext/drampower/src/Parametrisable.cc new file mode 100644 index 000000000..a348fd86e --- /dev/null +++ b/ext/drampower/src/Parametrisable.cc @@ -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; +} diff --git a/ext/drampower/src/Parametrisable.h b/ext/drampower/src/Parametrisable.h new file mode 100644 index 000000000..31a69190f --- /dev/null +++ b/ext/drampower/src/Parametrisable.h @@ -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 diff --git a/ext/drampower/src/TraceParser.cc b/ext/drampower/src/TraceParser.cc new file mode 100644 index 000000000..ec87f06da --- /dev/null +++ b/ext/drampower/src/TraceParser.cc @@ -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 diff --git a/ext/drampower/src/TraceParser.h b/ext/drampower/src/TraceParser.h new file mode 100644 index 000000000..cabfcd395 --- /dev/null +++ b/ext/drampower/src/TraceParser.h @@ -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 diff --git a/ext/drampower/src/Utils.h b/ext/drampower/src/Utils.h new file mode 100644 index 000000000..3fba0961f --- /dev/null +++ b/ext/drampower/src/Utils.h @@ -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 */ diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.cc b/ext/drampower/src/libdrampower/LibDRAMPower.cc new file mode 100644 index 000000000..ac16f948b --- /dev/null +++ b/ext/drampower/src/libdrampower/LibDRAMPower.cc @@ -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; +} diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.h b/ext/drampower/src/libdrampower/LibDRAMPower.h new file mode 100644 index 000000000..9dea8b0f5 --- /dev/null +++ b/ext/drampower/src/libdrampower/LibDRAMPower.h @@ -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 diff --git a/ext/drampower/src/uncrustify.cfg b/ext/drampower/src/uncrustify.cfg new file mode 100644 index 000000000..ffe0e5f9c --- /dev/null +++ b/ext/drampower/src/uncrustify.cfg @@ -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 diff --git a/ext/drampower/test/libdrampowertest/Makefile b/ext/drampower/test/libdrampowertest/Makefile new file mode 100644 index 000000000..354309fd4 --- /dev/null +++ b/ext/drampower/test/libdrampowertest/Makefile @@ -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 diff --git a/ext/drampower/test/libdrampowertest/commands.trace b/ext/drampower/test/libdrampowertest/commands.trace new file mode 100644 index 000000000..3463586de --- /dev/null +++ b/ext/drampower/test/libdrampowertest/commands.trace @@ -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 diff --git a/ext/drampower/test/libdrampowertest/lib_test.cc b/ext/drampower/test/libdrampowertest/lib_test.cc new file mode 100644 index 000000000..f382a727e --- /dev/null +++ b/ext/drampower/test/libdrampowertest/lib_test.cc @@ -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; +} |