Repository: tukl-msd/DRAMPower
Branch: master
Commit: 8b0dedaf45f9
Files: 255
Total size: 1.5 MB
Directory structure:
gitextract_nfddae32/
├── .clang-format
├── .clang-tidy
├── .github/
│ └── workflows/
│ └── CI.yml
├── .gitignore
├── CMakeLists.txt
├── CMakePresets.json
├── LICENSE.txt
├── README.md
├── benches/
│ ├── CMakeLists.txt
│ ├── main.cpp
│ └── simulation.cpp
├── cmake/
│ ├── build_source_group.cmake
│ ├── diagnostics_print.cmake
│ ├── enable_clang_format.cmake
│ ├── enable_clang_tidy.cmake
│ └── enable_cppcheck.cmake
├── lib/
│ ├── cli11/
│ │ └── CMakeLists.txt
│ └── spdlog/
│ └── CMakeLists.txt
├── src/
│ ├── DRAMPower/
│ │ ├── CMakeLists.txt
│ │ └── DRAMPower/
│ │ ├── Exceptions.h
│ │ ├── Types.h
│ │ ├── command/
│ │ │ ├── CmdType.h
│ │ │ ├── Command.cpp
│ │ │ ├── Command.h
│ │ │ ├── Pattern.cpp
│ │ │ └── Pattern.h
│ │ ├── data/
│ │ │ ├── energy.cpp
│ │ │ ├── energy.h
│ │ │ └── stats.h
│ │ ├── dram/
│ │ │ ├── Bank.h
│ │ │ ├── Interface.cpp
│ │ │ ├── Interface.h
│ │ │ ├── Rank.cpp
│ │ │ ├── Rank.h
│ │ │ └── dram_base.h
│ │ ├── memspec/
│ │ │ ├── MemSpec.h
│ │ │ ├── MemSpecDDR4.cpp
│ │ │ ├── MemSpecDDR4.h
│ │ │ ├── MemSpecDDR5.cpp
│ │ │ ├── MemSpecDDR5.h
│ │ │ ├── MemSpecLPDDR4.cpp
│ │ │ ├── MemSpecLPDDR4.h
│ │ │ ├── MemSpecLPDDR5.cpp
│ │ │ └── MemSpecLPDDR5.h
│ │ ├── simconfig/
│ │ │ └── simconfig.h
│ │ ├── standards/
│ │ │ ├── ddr4/
│ │ │ │ ├── DDR4.cpp
│ │ │ │ ├── DDR4.h
│ │ │ │ ├── DDR4Core.cpp
│ │ │ │ ├── DDR4Core.h
│ │ │ │ ├── DDR4Interface.cpp
│ │ │ │ ├── DDR4Interface.h
│ │ │ │ ├── core_calculation_DDR4.cpp
│ │ │ │ ├── core_calculation_DDR4.h
│ │ │ │ ├── interface_calculation_DDR4.cpp
│ │ │ │ ├── interface_calculation_DDR4.h
│ │ │ │ └── types.h
│ │ │ ├── ddr5/
│ │ │ │ ├── DDR5.cpp
│ │ │ │ ├── DDR5.h
│ │ │ │ ├── DDR5Core.cpp
│ │ │ │ ├── DDR5Core.h
│ │ │ │ ├── DDR5Interface.cpp
│ │ │ │ ├── DDR5Interface.h
│ │ │ │ ├── core_calculation_DDR5.cpp
│ │ │ │ ├── core_calculation_DDR5.h
│ │ │ │ ├── interface_calculation_DDR5.cpp
│ │ │ │ ├── interface_calculation_DDR5.h
│ │ │ │ └── types.h
│ │ │ ├── lpddr4/
│ │ │ │ ├── LPDDR4.cpp
│ │ │ │ ├── LPDDR4.h
│ │ │ │ ├── LPDDR4Core.cpp
│ │ │ │ ├── LPDDR4Core.h
│ │ │ │ ├── LPDDR4Interface.cpp
│ │ │ │ ├── LPDDR4Interface.h
│ │ │ │ ├── core_calculation_LPDDR4.cpp
│ │ │ │ ├── core_calculation_LPDDR4.h
│ │ │ │ ├── interface_calculation_LPDDR4.cpp
│ │ │ │ ├── interface_calculation_LPDDR4.h
│ │ │ │ └── types.h
│ │ │ ├── lpddr5/
│ │ │ │ ├── LPDDR5.cpp
│ │ │ │ ├── LPDDR5.h
│ │ │ │ ├── LPDDR5Core.cpp
│ │ │ │ ├── LPDDR5Core.h
│ │ │ │ ├── LPDDR5Interface.cpp
│ │ │ │ ├── LPDDR5Interface.h
│ │ │ │ ├── core_calculation_LPDDR5.cpp
│ │ │ │ ├── core_calculation_LPDDR5.h
│ │ │ │ ├── interface_calculation_LPDDR5.cpp
│ │ │ │ ├── interface_calculation_LPDDR5.h
│ │ │ │ └── types.h
│ │ │ └── test_accessor.h
│ │ └── util/
│ │ ├── Deserialize.h
│ │ ├── ImplicitCommandHandler.h
│ │ ├── PatternHandler.h
│ │ ├── RegisterHelper.h
│ │ ├── Router.h
│ │ ├── Serialize.h
│ │ ├── binary_ops.h
│ │ ├── burst_storage.h
│ │ ├── bus.cpp
│ │ ├── bus.h
│ │ ├── bus_types.h
│ │ ├── cli_architecture_config.h
│ │ ├── clock.h
│ │ ├── command_counter.h
│ │ ├── cycle_stats.h
│ │ ├── databus.h
│ │ ├── databus_presets.h
│ │ ├── databus_types.h
│ │ ├── dbi.h
│ │ ├── dbialgos.h
│ │ ├── dbihelpers.h
│ │ ├── dbitypes.h
│ │ ├── dynamic_bitset.h
│ │ ├── extension_base.h
│ │ ├── extension_manager.h
│ │ ├── extension_manager_static.h
│ │ ├── extensions.cpp
│ │ ├── extensions.h
│ │ ├── pending_stats.h
│ │ ├── pin.h
│ │ ├── pin_types.h
│ │ └── sub_bitset.h
│ └── cli/
│ ├── CMakeLists.txt
│ ├── lib/
│ │ ├── CMakeLists.txt
│ │ └── DRAMPower/
│ │ └── cli/
│ │ ├── config.h
│ │ ├── csv.hpp
│ │ ├── run.cpp
│ │ ├── run.hpp
│ │ ├── util.cpp
│ │ └── util.hpp
│ └── main/
│ ├── CMakeLists.txt
│ ├── main.cpp
│ ├── validators.cpp
│ └── validators.h
└── tests/
├── CMakeLists.txt
├── tests_drampower/
│ ├── CMakeLists.txt
│ ├── base/
│ │ ├── test_ddr_base.cpp
│ │ ├── test_ddr_data.cpp
│ │ ├── test_ddr_serialize.cpp
│ │ └── test_pattern_pre_cycles.cpp
│ ├── core/
│ │ ├── DDR4/
│ │ │ ├── ddr4_multidevice_tests.cpp
│ │ │ ├── ddr4_multirank_tests.cpp
│ │ │ ├── ddr4_test_pattern_0.cpp
│ │ │ ├── ddr4_test_pattern_1.cpp
│ │ │ ├── ddr4_test_pattern_10.cpp
│ │ │ ├── ddr4_test_pattern_11.cpp
│ │ │ ├── ddr4_test_pattern_12.cpp
│ │ │ ├── ddr4_test_pattern_13.cpp
│ │ │ ├── ddr4_test_pattern_14.cpp
│ │ │ ├── ddr4_test_pattern_15.cpp
│ │ │ ├── ddr4_test_pattern_2.cpp
│ │ │ ├── ddr4_test_pattern_3.cpp
│ │ │ ├── ddr4_test_pattern_4.cpp
│ │ │ ├── ddr4_test_pattern_5.cpp
│ │ │ ├── ddr4_test_pattern_6.cpp
│ │ │ ├── ddr4_test_pattern_7.cpp
│ │ │ ├── ddr4_test_pattern_8.cpp
│ │ │ └── ddr4_test_pattern_9.cpp
│ │ ├── DDR5/
│ │ │ ├── ddr5_multidevice_tests.cpp
│ │ │ ├── ddr5_multirank_tests.cpp
│ │ │ ├── ddr5_test_pattern_0.cpp
│ │ │ ├── ddr5_test_pattern_1.cpp
│ │ │ ├── ddr5_test_pattern_10.cpp
│ │ │ ├── ddr5_test_pattern_11.cpp
│ │ │ ├── ddr5_test_pattern_12.cpp
│ │ │ ├── ddr5_test_pattern_13.cpp
│ │ │ ├── ddr5_test_pattern_14.cpp
│ │ │ ├── ddr5_test_pattern_15.cpp
│ │ │ ├── ddr5_test_pattern_16.cpp
│ │ │ ├── ddr5_test_pattern_17.cpp
│ │ │ ├── ddr5_test_pattern_18.cpp
│ │ │ ├── ddr5_test_pattern_2.cpp
│ │ │ ├── ddr5_test_pattern_3.cpp
│ │ │ ├── ddr5_test_pattern_4.cpp
│ │ │ ├── ddr5_test_pattern_5.cpp
│ │ │ ├── ddr5_test_pattern_6.cpp
│ │ │ ├── ddr5_test_pattern_7.cpp
│ │ │ ├── ddr5_test_pattern_8.cpp
│ │ │ └── ddr5_test_pattern_9.cpp
│ │ ├── LPDDR4/
│ │ │ ├── lpddr4_multidevice_tests.cpp
│ │ │ ├── lpddr4_multirank_tests.cpp
│ │ │ ├── lpddr4_test_pattern_0.cpp
│ │ │ ├── lpddr4_test_pattern_1.cpp
│ │ │ ├── lpddr4_test_pattern_10.cpp
│ │ │ ├── lpddr4_test_pattern_11.cpp
│ │ │ ├── lpddr4_test_pattern_12.cpp
│ │ │ ├── lpddr4_test_pattern_13.cpp
│ │ │ ├── lpddr4_test_pattern_14.cpp
│ │ │ ├── lpddr4_test_pattern_15.cpp
│ │ │ ├── lpddr4_test_pattern_16.cpp
│ │ │ ├── lpddr4_test_pattern_17.cpp
│ │ │ ├── lpddr4_test_pattern_18.cpp
│ │ │ ├── lpddr4_test_pattern_2.cpp
│ │ │ ├── lpddr4_test_pattern_3.cpp
│ │ │ ├── lpddr4_test_pattern_4.cpp
│ │ │ ├── lpddr4_test_pattern_5.cpp
│ │ │ ├── lpddr4_test_pattern_6.cpp
│ │ │ ├── lpddr4_test_pattern_7.cpp
│ │ │ ├── lpddr4_test_pattern_8.cpp
│ │ │ └── lpddr4_test_pattern_9.cpp
│ │ └── LPDDR5/
│ │ ├── lpddr5_multidevice_tests.cpp
│ │ ├── lpddr5_multirank_tests.cpp
│ │ ├── lpddr5_test_pattern_0.cpp
│ │ ├── lpddr5_test_pattern_1.cpp
│ │ ├── lpddr5_test_pattern_10.cpp
│ │ ├── lpddr5_test_pattern_11.cpp
│ │ ├── lpddr5_test_pattern_12.cpp
│ │ ├── lpddr5_test_pattern_13.cpp
│ │ ├── lpddr5_test_pattern_14.cpp
│ │ ├── lpddr5_test_pattern_15.cpp
│ │ ├── lpddr5_test_pattern_16.cpp
│ │ ├── lpddr5_test_pattern_17.cpp
│ │ ├── lpddr5_test_pattern_18.cpp
│ │ ├── lpddr5_test_pattern_19.cpp
│ │ ├── lpddr5_test_pattern_2.cpp
│ │ ├── lpddr5_test_pattern_20.cpp
│ │ ├── lpddr5_test_pattern_21.cpp
│ │ ├── lpddr5_test_pattern_3.cpp
│ │ ├── lpddr5_test_pattern_4.cpp
│ │ ├── lpddr5_test_pattern_5.cpp
│ │ ├── lpddr5_test_pattern_6.cpp
│ │ ├── lpddr5_test_pattern_7.cpp
│ │ ├── lpddr5_test_pattern_8.cpp
│ │ └── lpddr5_test_pattern_9.cpp
│ ├── interface/
│ │ ├── test_dbi_ddr4.cpp
│ │ ├── test_dbi_lpddr4.cpp
│ │ ├── test_dbi_lpddr5.cpp
│ │ ├── test_interface_ddr4.cpp
│ │ ├── test_interface_ddr5.cpp
│ │ ├── test_interface_lpddr4.cpp
│ │ ├── test_interface_lpddr5.cpp
│ │ ├── test_togglingrate_ddr4.cpp
│ │ ├── test_togglingrate_ddr5.cpp
│ │ ├── test_togglingrate_lpddr4.cpp
│ │ └── test_togglingrate_lpddr5.cpp
│ └── resources/
│ ├── cliconfig.json
│ ├── ddr4.csv
│ ├── ddr4.json
│ ├── ddr5.csv
│ ├── ddr5.json
│ ├── lpddr4.csv
│ ├── lpddr4.json
│ ├── lpddr5.csv
│ └── lpddr5.json
└── tests_misc/
├── CMakeLists.txt
├── test_bus.cpp
├── test_bus_extended.cpp
├── test_clock.cpp
├── test_dynamic_bitset.cpp
├── test_dynamic_extension_manager.cpp
├── test_interval.cpp
├── test_misc.cpp
├── test_pattern.cpp
├── test_pin.cpp
└── test_static_extension_manager.cpp
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
AccessModifierOffset: '-4'
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: Never
BinPackArguments: 'false'
BinPackParameters: 'false'
BreakBeforeBraces: Allman
BreakConstructorInitializers: AfterColon
ColumnLimit: '100'
IndentWidth: '4'
PackConstructorInitializers: CurrentLine
PointerAlignment: Left
================================================
FILE: .clang-tidy
================================================
Checks: >
clang-diagnostic-*,
clang-analyzer-*,
modernize-*,
bugprone-*,
concurrency-*,
cppcoreguidelines-*,
performance-*,
portability-*,
readability-*,
-modernize-use-trailing-return-type,
-readability-braces-around-statements,
-readability-identifier-length,
-readability-function-cognitive-complexity
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: file
================================================
FILE: .github/workflows/CI.yml
================================================
name: Continuous Integration
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
# Compile and test project on Linux based builds
build-gcc:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake --preset ci-unix
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j4
- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}
# Compile and test project on Linux based builds using clang
build-clang:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest
env:
CC: clang
CXX: clang++
steps:
- uses: actions/checkout@v4
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake --preset ci-unix
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j4
- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}
# Compile and test project on Windows based builds
build-msvc:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Configure CMake
# Configure CMake in a 'build' subdirectory.
run: cmake --preset ci-msvc
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j4
- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}
================================================
FILE: .gitignore
================================================
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.app
# Common project files
.DS_Store
.project
.cproject
compile_commands.json
.clangd/
.vscode
.idea
build*/
bin/
*.swp
.~*
cmake-build-debug
cmake-build-release
.cache
================================================
FILE: CMakeLists.txt
================================================
# Copyright (c) 2022, Fraunhofer IESE
# 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.
#
# Author:
# Thomas Psota
# Marco Mörz
#########################################
### DRAMPower ###
#########################################
cmake_minimum_required(VERSION 3.22.0)
# TODO change for release
set(DRAMPOWER_VERSION_MAJOR 6)
set(DRAMPOWER_VERSION_MINOR 0)
set(DRAMPOWER_VERSION_PATCH 0)
set(DRAMPOWER_VERSION_STRING "${DRAMPOWER_VERSION_MAJOR}.${DRAMPOWER_VERSION_MINOR}.${DRAMPOWER_VERSION_PATCH}")
add_compile_definitions(DRAMPOWER_VERSION_STRING="${DRAMPOWER_VERSION_STRING}")
set(PROJECT_NAME "DRAMPower ${DRAMPOWER_VERSION_STRING}")
set(PROJECT_SHORTNAME "DRAMPower")
project(${PROJECT_NAME} VERSION ${DRAMPOWER_VERSION_MAJOR}.${DRAMPOWER_VERSION_MINOR}.${DRAMPOWER_VERSION_PATCH} LANGUAGES CXX)
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
### CMake settings ###
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
include(build_source_group)
include(diagnostics_print)
include(enable_clang_format)
include(enable_clang_tidy)
include(enable_cppcheck)
if (PROJECT_IS_TOP_LEVEL)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
# set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
### Project settings ###
message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
message(STATUS "" )
### Build options ###
option(DRAMPOWER_BUILD_CLI "Build DRAMPower Command Line Tool" ${PROJECT_IS_TOP_LEVEL})
option(DRAMPOWER_BUILD_BENCHMARKS "Build DRAMPower Command Line Tool" OFF)
option(DRAMPOWER_BUILD_TESTS "Build DRAMPower unit tests" OFF)
### Compiler optimization settings ###
if(PROJECT_IS_TOP_LEVEL)
option(OPTIMIZE_FOR_NATIVE "Build with -march=native (overrides CPU_TYPE if enabled)" ON)
set(CPU_TYPE "" CACHE STRING "CPU type for -march=CPU_TYPE and -mtune=CPU_TYPE compile options")
# Set CPU_TYPE to native if OPTIMIZE_FOR_NATIVE is enabled
if(OPTIMIZE_FOR_NATIVE)
if(CPU_TYPE)
message(NOTICE "OPTIMIZE_FOR_NATIVE is enabled. Overriding CPU_TYPE from \"${CPU_TYPE}\" to \"native\".")
endif()
set(CPU_TYPE "native")
endif()
# add CPU_TYPE to cmake cxx flags
if(CPU_TYPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${CPU_TYPE} -mtune=${CPU_TYPE}")
endif()
endif()
# Use sane defaults for FetchContent:
# In case we are the top-level project, get everything by default
# In case we are included in another project, the user might want to provide their own system dependencies
option(DRAMPOWER_USE_FETCH_CONTENT "Enable the FetchContent module" ${PROJECT_IS_TOP_LEVEL})
option(DRAMPOWER_USE_FETCH_CONTENT_INTERNAL "Enable FetchContent to provide internal dependencies" ${DRAMPOWER_USE_FETCH_CONTENT})
option(DRAMPOWER_USE_FETCH_CONTENT_CLI11 "Enable FetchContent to provide CLI11" ${DRAMPOWER_USE_FETCH_CONTENT})
option(DRAMPOWER_USE_FETCH_CONTENT_SPDLOG "Enable FetchContent to provide spdlog" ${DRAMPOWER_USE_FETCH_CONTENT})
option(DRAMPOWER_USE_FETCH_CONTENT_NLOHMANN_JSON "Enable FetchContent to provide nlohmann json" ${DRAMPOWER_USE_FETCH_CONTENT})
### DRAMPower directories ###
set(DRAMPOWER_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(DRAMPOWER_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
set(DRAMPOWER_TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests")
###############################################
### Library Settings ###
###############################################
### Detect OS threading library ###
find_package(Threads)
if (DRAMPOWER_USE_FETCH_CONTENT)
include(FetchContent)
# nlohmann_json for DRAMUtils
if (DRAMPOWER_USE_FETCH_CONTENT_NLOHMANN_JSON)
FetchContent_Declare(nlohmann_json
URL "https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz"
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(nlohmann_json)
endif()
# DRAMUtils
if (DRAMPOWER_USE_FETCH_CONTENT_INTERNAL)
FetchContent_Declare(
DRAMUtils
URL "https://github.com/tukl-msd/DRAMUtils/archive/refs/tags/v1.12.1.tar.gz"
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(DRAMUtils)
endif()
# cli11
if (DRAMPOWER_USE_FETCH_CONTENT_CLI11 AND DRAMPOWER_BUILD_CLI)
add_subdirectory(${DRAMPOWER_LIBRARY_DIR}/cli11)
endif()
# spdlog
if (DRAMPOWER_USE_FETCH_CONTENT_SPDLOG AND (DRAMPOWER_BUILD_CLI OR DRAMPOWER_BUILD_BENCHMARKS))
add_subdirectory(${DRAMPOWER_LIBRARY_DIR}/spdlog)
endif()
endif()
###############################################
### Source Directory ###
###############################################
add_subdirectory(src/DRAMPower)
if(DRAMPOWER_BUILD_CLI OR DRAMPOWER_BUILD_BENCHMARKS)
add_subdirectory(src/cli)
endif()
###############################################
### Test Directory ###
###############################################
if(DRAMPOWER_BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
###############################################
### Benchmark Directory ###
###############################################
if(DRAMPOWER_BUILD_BENCHMARKS)
add_subdirectory(benches)
endif()
###############################################
### Utility Projects ###
###############################################
if(${DRAMPOWER_UTILITY_PROJECTS})
enable_clang_format()
enable_clang_tidy()
enable_cppcheck()
endif()
================================================
FILE: CMakePresets.json
================================================
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 14,
"patch": 0
},
"configurePresets": [
{
"name": "cmake-pedantic",
"hidden": true,
"warnings": {
"dev": true,
"deprecated": true,
"unusedCli": true,
"systemVars": false
}
},
{
"name": "dev-mode",
"hidden": true,
"binaryDir": "${sourceDir}/build",
"inherits": "cmake-pedantic",
"cacheVariables": {
"DRAMPOWER_BUILD_TESTS": "ON",
"CMAKE_BUILD_PARALLEL_LEVEL": "",
"DRAMPOWER_BUILD_CLI": "ON",
"DRAMPOWER_BUILD_BENCHMARKS": "ON"
}
},
{
"name": "ci-common",
"inherits": [
"dev-mode"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "ci-unix",
"generator": "Unix Makefiles",
"inherits": [
"ci-common"
]
},
{
"name": "ci-msvc",
"generator": "Visual Studio 17 2022",
"inherits": [
"ci-common"
],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "/DWIN32 /D_WINDOWS /W3 /GR /EHsc /MP"
}
},
{
"name": "dev-unix",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"inherits": [
"dev-mode"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic"
}
},
{
"name": "dev-msvc",
"generator": "Visual Studio 17 2022",
"inherits": [
"dev-mode"
],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "/DWIN32 /D_WINDOWS /W3 /GR /EHsc /MP"
}
}
]
}
================================================
FILE: LICENSE.txt
================================================
Copyright (c) 2022, Technische Universität Kaiserslautern, Fraunhofer IESE
All rights reserved.
This software is released under the BSD 3-Clause License.
By using this software, the user implicitly agrees to the licensing terms.
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.
================================================
FILE: README.md
================================================
# DRAM Power Model (DRAMPower 6.0.0)
- [Releases](#releases)
- [Installation of the DRAMPower library](#installation-of-the-drampower-library)
- [Installation of the DRAMPower Command Line application](#installation-of-the-drampower-command-line-application)
- [Project structure](#project-structure)
- [Dependencies](#dependencies)
- [Usage of the DRAMPower library](#usage-of-the-drampower-library)
- [Usage of the DRAMPower Command Line application](#usage-of-the-drampower-command-line-application)
- [Memory Specifications](#memory-specifications)
- [Variation-aware Power And Energy Estimation](#variation-aware-power-and-energy-estimation)
- [Authors & Acknowledgment](#authors--acknowledgment)
- [Contact Information](#contact-information)
## Releases
The last official release can be found here: https://github.com/tukl-msd/DRAMPower/releases/tag/v6.0.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.
## Installation of the DRAMPower library
CMake is required for the building of DRAMPower. If DRAMPower is the top level project DRAMPower fetches the required dependencies.
If DRAMPower is not the top level project, the dependencies have to be fetched manually, provided by the top level project or the DRAMPower library can fetch the dependencies. Fetching content is enabled by the following cmake flag:
```console
$ -D DRAMPOWER_USE_FETCH_CONTENT=Y
```
By default DRAMPower fetches all dependencies if `DRAMPOWER_USE_FETCH_CONTENT` is enabled. If you want to disable the fetching of a specific dependency, you can set the respective flag to N. The following flags are available:
- `DRAMPOWER_USE_FETCH_CONTENT_INTERNAL` Fetches the internal dependencies of DRAMPower (DRAMUtils)
- `DRAMPOWER_USE_FETCH_CONTENT_SPDLOG` Fetches the spdlog library used by the command line application
- `DRAMPOWER_USE_FETCH_CONTENT_CLI11` Fetches the CLI11 library used by the command line application
- `DRAMPOWER_USE_FETCH_CONTENT_NLOHMANN_JSON` Fetches the nlohmann_json library used by DRAMUtils
The following cmake flags show an example of how to disable the fetching of the spdlog and CLI11 libraries:
```console
$ -D DRAMPOWER_USE_FETCH_CONTENT=Y -D DRAMPOWER_USE_FETCH_CONTENT_SPDLOG=N -D DRAMPOWER_USE_FETCH_CONTENT_CLI11=N
```
For building DRAMPower clone the repository, or download the zip file of the release you would like to use and use CMake to generate the build files, e.g.
```console
$ cd DRAMPower
$ cmake -S . -B build
$ cmake --build build --parallel
```
Optionally, test cases can be built by toggling the `DRAMPOWER_BUILD_TESTS` flag with CMake.
## Installation of the DRAMPower Command Line application
The command line application is automatically build if DRAMPower is the top level project (see [Installation of the DRAMPower library](#installation-of-the-drampower-library)).
Alternatively, the `DRAMPOWER_BUILD_CLI` flag can be set to Y to force the build of the command line tool.
Clone the repository, or download the zip file of the release you would like to use and use CMake to generate the build files. The following commands force the build of the command line application:
```console
$ cd DRAMPower
$ cmake -S . -B build -D DRAMPOWER_BUILD_CLI=Y
$ cmake --build build
```
## Project structure
The project is structured in a library part, a (optional) test part and an (optional) Command Line application.
Integration of DRAMPower in other projects can be easily achieved by including it as a git submodule or by using the CMake FetchContent directive.
This repository contains the following sub-directoires
DRAMPower # top directory
└── cmake # cmake scripts used by configuration step
├── lib # contains bundled dependencies of the project
├── src # top level directory containing the actual sources
├── DRAMPower # source code of the actual DRAMPower library
└── cli # the optional Command Line tool
└── tests # test cases used by the project
## Dependencies
DRAMPower comes bundled with all necessary libraries and no installation of further system packages is required. DRAMPower uses the following libraries:
- [DRAMUtils](https://github.com/tukl-msd/DRAMUtils)
The DRAMPower cli tool uses the following libraries:
- DRAMPower
- [DRAMUtils](https://github.com/tukl-msd/DRAMUtils)
- [spdlog](https://github.com/gabime/spdlog/releases/tag/v1.9.2)
- [CLI11 (CLI11 2.2 Copyright (c) 2017-2024 University of Cincinnati, developed by Henry Schreiner under NSF AWARD 1414736. All rights reserved.)](https://github.com/CLIUtils/CLI11/releases/tag/v2.4.2)
## Usage of the DRAMPower library
The project is [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) ready and can be easily included in any other CMake based project.
```cmake
include(FetchContent)
FetchContent_Declare(
drampower
GIT_REPOSITORY https://github.com/tukl-msd/DRAMPower
GIT_TAG master)
FetchContent_MakeAvailable(drampower)
```
The library target DRAMPower is then available to the rest of the project and can be consumed by any other target, e.g.
```cmake
add_executable(drampower_app ${SOURCE_FILES})
target_link_libraries(drampower_app PRIVATE DRAMPower::DRAMPower)
```
All constructs inside DRAMPower are exposed through the DRAMPower namespace.
Therefore all the following examples will refer to them with the implied usage of their namespace.
```cpp
using namespace DRAMPower;
```
To use the actual DRAM calculations, first a memspec has to be supplied. Some example memspecs are supplied in the [tests directory](https://github.com/tukl-msd/DRAMPower/tree/master/tests/tests_drampower/resources). The values in the memspecs are in SI units.
An example snippet to initialize a DDR4 based DRAM spec can look like this (only the DRAMPower related includes are shown):
```cpp
#include
#include
#include
// optional for simulation with toggling rates
#include
// Use DRAMUtils library to parse the memspec
auto memspec = DRAMUtils::parse_memspec_from_file(
std::filesystem::path("tests/tests_drampower/resources/ddr4.json")
);
if (!memspec) {
throw std::runtime_error("Could not parse memspec");
}
// Make the DRAMPower specific memspec from the parsed memspec and initialize the DRAM
// The next line can throw std::bad_variant_access if the memspec is not a DDR4 memspec
// or an exception derived from std::exception if the json object is not valid
DDR4 dram(MemSpecDDR4::from_memspec(*memspec));
// Optionally use toggle rates if no data is available for the traces
// dram.setToggleRate(DRAMUtils::Config::ToggleRateDefinition{
// 0.5, // togglingRateRead 0.0 to 1.0
// 0.5, // togglingRateWrite 0.0 to 1.0
// 0.5, // dutyCycleRead 0.0 to 1.0
// 0.5, // dutyCycleWrite 0.0 to 1.0
// TogglingRateIdlePattern::H, // idlePatternRead H, L, Z
// TogglingRateIdlePattern::H // idlePatternWrite H, L, Z
// });
```
The created DRAM simulator then has to be fed with commands, e.g.
```cpp
#include
#define SZ_BITS(x) sizeof(x)*8
uint8_t rd_data[] = {
0, 0, 0, 0, 0, 0, 0, 1,
};
std::vector testPattern = {
// {timestamp, commandtype, {bank_id, bank_group_id, rank_id, row_id}
{ 0, CmdType::ACT, {0, 0, 0, 0}},
// {timestamp, commandtype, {bank_id, bank_group_id, rank_id, row_id, column_id}, data, data_size}
{ 15, CmdType::RD , {0, 0, 0, 0, 16}, rd_data, SZ_BITS(rd_data)},
// optional for simulation with toggling rates (dram.setToggleRate() was called)
// { 15, CmdType::RD , {0, 0, 0, 0, 16}, nullptr, 64},
{ 35, CmdType::PRE, {0, 0, 0, 0}},
{ 45, CmdType::END_OF_SIMULATION },
};
for (const auto& command : testPattern) {
dram.doCoreInterfaceCommand(command);
};
```
The bank stats and energy calculations can then be accessed through their respective methods.
In the example energy_core holds the individual bank energy measures. total_energy_core holds the accumulated energy measures accessable through the energy type (e.g E_act, E_pre, E_RD, E_bg_act, E_bg_pre). total_core, total_interface and total_all hold the total energy measures for the core, interface and the sum of both as double values.
All values are returned in their respective SI units.
```cpp
auto stats = dram.getStats();
stats.bank[0].counter.act; // 1;
stats.bank[0].counter.reads; // 1;
stats.bank[0].counter.pre; // 1;
stats.rank_total[0].cycles.act; // 35;
stats.rank_total[0].cycles.pre; // 10;
stats.bank[0].cycles.act; // 35;
stats.bank[0].cycles.pre; // 10;
// Core energy
auto energy_core = dram.calcCoreEnergy(dram.getLastCommandTime());
// Interface energy
auto energy_interface = dram.calcInterfaceEnergy(dram.getLastCommandTime());
// Total energy with core and interface energy
// Accummulated bank energy
// Note: total_core_detailed.E_bg_act holds holds the accumulated backgound activation energy plus the shared background activation energy
auto total_energy_core = energy_core.total_energy();
energy_core.bank_energy[0].E_act; // 1.7949519230769228e-10 J
total_energy_core.E_act; // 1.7949519230769228e-10 J
energy_core.E_bg_act_shared; // 1.1832692307692309e-09 J
energy_core.bank_energy[0].E_bg_act; // 5.8052884615384527e-12 J
total_energy_core.E_bg_act; // 1.1890745192307694e-09 J (5.8052884615384527e-12 J + 1.1832692307692309e-09 J)
total_energy_core.E_pre; // 2.076923076923077e-10 J
energy_core.bank_energy[0].E_pre; // 2.076923076923077e-10 J
total_energy_core.E_bg_pre; // 3.1153846153846144e-10 J
energy_core.bank_energy[0].E_bg_pre; // 1.9471153846153847e-11 J
total_energy_core.E_RD; // 4.3569230769230762e-10 J
energy_core.bank_energy[0].E_RD; // 4.3569230769230762e-10 J
double total_core = core_energy.total(); // 2.3234927884615384e-09 J
double total_interface = interface_energy.total(); // 1.1102233846153846e-10 J
double total_all = dram.getTotalEnergy(dram.getLastCommandTime()); // 2.4345151269230767e-09 J
```
## Usage of the DRAMPower Command Line application
The Command Line application can be built directly by setting the DRAMPOWER_BUILD_CLI flag with CMake (see [Installation Command Line application](#installation-command-line-application)).
The Command Line application can be used to calculate energy consumption of a DRAM memory using a command trace. The output can be printed to the console or written as a JSON file. The application needs the following arguments:
- -m, --memspec (required): The path to the memory specification file (JSON format)
- -c, --config (required): Configuration file for the Command Line application (JSON format)
- -t, --trace (required): The path to the command trace file (CSV format) (see [tests directory](https://github.com/tukl-msd/DRAMPower/tree/master/tests/tests_drampower/resources))
- -j, --json (optional): The path to the output JSON file (default: print to console) (the output JSON file must exist and will be overwritten)
The configuration file has the following format:
```json
{
"useToggleRate": false, // true or false
"toggleRateConfig": {
"togglingRateRead": 0.5, // 0.0 to 1.0
"togglingRateWrite": 0.5, // 0.0 to 1.0
"dutyCycleRead": 0.5, // 0.0 to 1.0
"dutyCycleWrite": 0.5, // 0.0 to 1.0
"idlePatternRead": "H", // "H", "L" or "Z"
"idlePatternWrite": "H" // "H", "L" or "Z"
}
}
```
The Command Line application can be used as follows (in the following example the executable drampower_cli is located in the DRAMPower/build/bin directory):
```console
$ cd build/bin
$ touch output.json
$ touch config.json
$ # The configuration file config.json must be filled with a valid configuration (see above)
$ ./drampower_cli -c config.json -m ../../tests/tests_drampower/resources/ddr4.json -t ../../tests/tests_drampower/resources/ddr4.csv
$ ./drampower_cli -c config.json -m ../../tests/tests_drampower/resources/ddr4.json -t ../../tests/tests_drampower/resources/ddr4.csv -j output.json
```
## Memory Specifications
Note: The timing specifications in the JSONs 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. The IDD measures associated with different power supply sources of equal measure (VDD2, VDDCA and VDDQ). 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.
## 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.
## 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, Sven Goossens, Matthias Jung, Omar Naji, 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
```
## Contact Information
Further questions about the tool and the power model can be directed to:
Matthias Jung (matthias.jung@iese.fraunhofer.de)
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.
================================================
FILE: benches/CMakeLists.txt
================================================
# Copyright (c) 2024, RPTU Kaiserslautern-Landau
# 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:
# Derek Christ
# Marco Mörz
###############################################
### benches_drampower ###
###############################################
option(DRAMPOWER_USE_FETCH_CONTENT_GOOGLE_BENCHMARK "Enable FetchContent to provide Google Benchmark" ${DRAMPOWER_USE_FETCH_CONTENT})
if(DRAMPOWER_USE_FETCH_CONTENT)
if(DRAMPOWER_USE_FETCH_CONTENT_GOOGLE_BENCHMARK AND DRAMPOWER_BUILD_BENCHMARKS)
set(BENCHMARK_ENABLE_TESTING OFF)
FetchContent_Declare(
benchmark
URL "https://github.com/google/benchmark/archive/refs/tags/v1.8.3.tar.gz"
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(benchmark)
endif()
endif()
find_package(benchmark REQUIRED)
add_executable(benches_drampower
main.cpp
simulation.cpp
)
target_link_libraries(benches_drampower
PRIVATE
DRAMPower::DRAMPower
DRAMPower::cli_lib
DRAMUtils::DRAMUtils
benchmark::benchmark
)
target_compile_definitions(benches_drampower PUBLIC DRAMPOWER_BENCHMARK_CONFIGS_DIR="${CMAKE_SOURCE_DIR}/tests/tests_drampower/resources")
================================================
FILE: benches/main.cpp
================================================
/*
* Copyright (c) 2023, RPTU Kaiserslautern-Landau
* 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:
* Derek Christ
* Marco Mörz
*/
#include
int main(int argc, char** argv)
{
::benchmark::Initialize(&argc, argv);
::benchmark::RunSpecifiedBenchmarks();
return 0;
}
================================================
FILE: benches/simulation.cpp
================================================
/*
* Copyright (c) 2023, RPTU Kaiserslautern-Landau
* 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:
* Derek Christ
* Marco Mörz
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class LPDDR4_Bench : public benchmark::Fixture
{
public:
using Command = DRAMPower::Command;
using CmdType = DRAMPower::CmdType;
using CommandList_t = std::vector>>;
using BaseDDR_t = DRAMPower::dram_base;
void SetUp(::benchmark::State&) {
std::string memspecFile{DRAMPOWER_BENCHMARK_CONFIGS_DIR"/lpddr4.json"};
std::string commandFile{DRAMPOWER_BENCHMARK_CONFIGS_DIR"/lpddr4.csv"};
// Get dram
// auto ddr = DRAMPower::CLI::getMemory(memspecFile, std::nullopt);
auto memspeccontainer = DRAMUtils::parse_memspec_from_file(memspecFile);
if(!memspeccontainer)
{
throw std::runtime_error("Failed to parse memspec from file");
}
memspec = std::make_unique(DRAMPower::MemSpecLPDDR4::from_memspec(*memspeccontainer));
// Parse command list
if (!DRAMPower::DRAMPowerCLI::parse_command_list(commandFile, commandlist))
{
throw std::runtime_error("Failed to parse command list");
}
}
void TearDown(::benchmark::State&) {
commandlist.clear();
}
std::unique_ptr memspec;
CommandList_t commandlist;
};
BENCHMARK_DEFINE_F(LPDDR4_Bench, lpddr4PowerSimulation)(benchmark::State& state)
{
auto rdbuf = std::cout.rdbuf(nullptr);
for (auto _ : state)
{
std::unique_ptr ddr = std::make_unique(*memspec);
DRAMPower::DRAMPowerCLI::runCommands(ddr, commandlist);
}
std::cout.rdbuf(rdbuf);
}
BENCHMARK_REGISTER_F(LPDDR4_Bench, lpddr4PowerSimulation)->Unit(benchmark::kMicrosecond)->Iterations(10);
BENCHMARK_DEFINE_F(LPDDR4_Bench, lpddr4PowerSimulationToggling)(benchmark::State& state)
{
auto rdbuf = std::cout.rdbuf(nullptr);
for (auto _ : state)
{
auto trd = DRAMUtils::Config::ToggleRateDefinition{
0.5, // togglingRateRead
0.5, // togglingRateWrite
0.5, // dutyCycleRead
0.5, // dutyCycleWrite
DRAMUtils::Config::TogglingRateIdlePattern::L, // idlePatternRead
DRAMUtils::Config::TogglingRateIdlePattern::L // idlePatternWrite
};
std::unique_ptr ddr = std::make_unique(*memspec, DRAMPower::config::SimConfig{trd});
DRAMPower::DRAMPowerCLI::runCommands(ddr, commandlist);
}
std::cout.rdbuf(rdbuf);
}
BENCHMARK_REGISTER_F(LPDDR4_Bench, lpddr4PowerSimulationToggling)->Unit(benchmark::kMicrosecond)->Iterations(10);
================================================
FILE: cmake/build_source_group.cmake
================================================
###############################################
### build_source_group ###
###############################################
###
### Builds a source group from a set of files
### for nicer display in IDEs
###
function( build_source_group )
file(GLOB_RECURSE files ${CMAKE_CURRENT_SOURCE_DIR}/*.* )
list(REMOVE_ITEM files "CMakeLists.txt")
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "[src]" FILES ${files})
endfunction()
================================================
FILE: cmake/diagnostics_print.cmake
================================================
###############################################
### diagnostics_print ###
###############################################
###
### Prints different diagnostics and infos
### about the specified target
###
function( diagnostics_print target_name )
message(STATUS "${target_name} settings:")
message(STATUS "==============\n")
message(STATUS "Source Files:")
get_target_property(SOURCE_FILES ${target_name} SOURCES)
if(SOURCE_FILES)
message(STATUS "${SOURCE_FILES}")
endif()
message(STATUS "\nInclude Directories:")
get_target_property(HEADER_DIR ${target_name} INCLUDE_DIRECTORIES)
if(HEADER_DIR)
message(STATUS "${HEADER_DIR}")
endif()
message(STATUS "\nLink Libraries:")
get_target_property(LINKED_LIBS ${target_name} LINK_LIBRARIES)
if(LINKED_LIBS)
message(STATUS "${LINKED_LIBS}")
endif()
message(STATUS "\n")
endfunction()
================================================
FILE: cmake/enable_clang_format.cmake
================================================
###############################################
### enable_clang_format ###
###############################################
###
### Enables a clang-format target, if
### clang-format is installed, automatically
### formatting all sources in the tree
###
function( enable_clang_format )
endfunction()
================================================
FILE: cmake/enable_clang_tidy.cmake
================================================
###############################################
### enable_clang_tidy ###
###############################################
###
### Enables a clang-tidy target, if
### clang-tidy is installed, to run static
### code analysis on all sources
###
function( enable_clang_tidy )
file(GLOB_RECURSE SOURCE_FILES src/*.c src/*.cpp src/*.cxx src/*.cc )
file(GLOB_RECURSE HEADER_FILES src/*.h src/*.hpp src/*.hxx src/*.hh )
find_program(UTIL_TIDY_PATH clang-tidy)
if(UTIL_TIDY_PATH)
message(STATUS "Using clang-tidy static-analysis: yes")
add_custom_target(clang-tidy
COMMAND ${UTIL_TIDY_PATH} ${SOURCE_FILES} ${HEADER_FILES} -p=./ )
else()
message(STATUS "Using clang-tidy static-analysis: no")
endif()
endfunction()
================================================
FILE: cmake/enable_cppcheck.cmake
================================================
###############################################
### enable_cppcheck ###
###############################################
###
### Enables a cppcheck target, if
### cppcheck is installed, to run static
### analysis on all sources
###
function( enable_cppcheck )
file(GLOB_RECURSE SOURCE_FILES src/*.c src/*.cpp src/*.cxx src/*.cc )
file(GLOB_RECURSE HEADER_FILES src/*.h src/*.hpp src/*.hxx src/*.hh )
find_program(UTIL_CPPCHECK_PATH cppcheck)
if(UTIL_CPPCHECK_PATH)
message(STATUS "Using cppcheck static-analysis: yes ")
add_custom_target(
cppcheck
COMMAND ${UTIL_CPPCHECK_PATH}
--enable=warning,performance,portability,information,missingInclude
--language=c++
--std=c++11
--template=gcc
--verbose
--quiet
${SOURCE_FILES} ${HEADER_FILES}
)
else()
message(STATUS "Using cppcheck static-analysis: no ")
endif()
endfunction()
================================================
FILE: lib/cli11/CMakeLists.txt
================================================
########################################
### CLI11 ###
########################################
FetchContent_Declare(cli11
URL "https://github.com/CLIUtils/CLI11/archive/refs/tags/v2.4.2.tar.gz"
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(cli11)
================================================
FILE: lib/spdlog/CMakeLists.txt
================================================
########################################
### spdlog ###
########################################
FetchContent_Declare(spdlog
URL "https://github.com/gabime/spdlog/archive/refs/tags/v1.9.2.tar.gz"
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(spdlog)
================================================
FILE: src/DRAMPower/CMakeLists.txt
================================================
########################################
### DRAMPower ###
########################################
find_package(DRAMUtils REQUIRED)
add_library(DRAMPower
DRAMPower/command/Command.cpp
DRAMPower/command/Pattern.cpp
DRAMPower/data/energy.cpp
DRAMPower/dram/Interface.cpp
DRAMPower/dram/Rank.cpp
DRAMPower/memspec/MemSpecDDR4.cpp
DRAMPower/memspec/MemSpecDDR5.cpp
DRAMPower/memspec/MemSpecLPDDR4.cpp
DRAMPower/memspec/MemSpecLPDDR5.cpp
DRAMPower/standards/ddr4/core_calculation_DDR4.cpp
DRAMPower/standards/ddr4/DDR4.cpp
DRAMPower/standards/ddr4/DDR4Core.cpp
DRAMPower/standards/ddr4/DDR4Interface.cpp
DRAMPower/standards/ddr4/interface_calculation_DDR4.cpp
DRAMPower/standards/ddr5/core_calculation_DDR5.cpp
DRAMPower/standards/ddr5/DDR5.cpp
DRAMPower/standards/ddr5/DDR5Core.cpp
DRAMPower/standards/ddr5/DDR5Interface.cpp
DRAMPower/standards/ddr5/interface_calculation_DDR5.cpp
DRAMPower/standards/lpddr4/core_calculation_LPDDR4.cpp
DRAMPower/standards/lpddr4/LPDDR4.cpp
DRAMPower/standards/lpddr4/LPDDR4Core.cpp
DRAMPower/standards/lpddr4/LPDDR4Interface.cpp
DRAMPower/standards/lpddr4/interface_calculation_LPDDR4.cpp
DRAMPower/standards/lpddr5/core_calculation_LPDDR5.cpp
DRAMPower/standards/lpddr5/LPDDR5.cpp
DRAMPower/standards/lpddr5/LPDDR5Core.cpp
DRAMPower/standards/lpddr5/LPDDR5Interface.cpp
DRAMPower/standards/lpddr5/interface_calculation_LPDDR5.cpp
DRAMPower/util/extensions.cpp
)
target_sources(DRAMPower
PUBLIC
FILE_SET api
TYPE HEADERS
FILES
DRAMPower/Types.h
DRAMPower/Exceptions.h
DRAMPower/dram/dram_base.h
DRAMPower/simconfig/simconfig.h
DRAMPower/command/Command.h
DRAMPower/data/energy.h
DRAMPower/data/stats.h
DRAMPower/util/extension_manager.h
DRAMPower/util/extensions.h
DRAMPower/memspec/MemSpec.h
DRAMPower/memspec/MemSpecDDR4.h
DRAMPower/standards/ddr4/DDR4.h
DRAMPower/standards/ddr4/DDR4Core.h
DRAMPower/standards/ddr4/DDR4Interface.h
DRAMPower/standards/ddr4/core_calculation_DDR4.h
DRAMPower/standards/ddr4/interface_calculation_DDR4.h
DRAMPower/standards/ddr4/types.h
DRAMPower/memspec/MemSpecDDR5.h
DRAMPower/standards/ddr5/DDR5.h
DRAMPower/standards/ddr5/DDR5Core.h
DRAMPower/standards/ddr5/DDR5Interface.h
DRAMPower/standards/ddr5/core_calculation_DDR5.h
DRAMPower/standards/ddr5/interface_calculation_DDR5.h
DRAMPower/standards/ddr5/types.h
DRAMPower/memspec/MemSpecLPDDR4.h
DRAMPower/standards/lpddr4/LPDDR4.h
DRAMPower/standards/lpddr4/LPDDR4Core.h
DRAMPower/standards/lpddr4/LPDDR4Interface.h
DRAMPower/standards/lpddr4/core_calculation_LPDDR4.h
DRAMPower/standards/lpddr4/interface_calculation_LPDDR4.h
DRAMPower/standards/lpddr4/types.h
DRAMPower/memspec/MemSpecLPDDR5.h
DRAMPower/standards/lpddr5/LPDDR5.h
DRAMPower/standards/lpddr5/LPDDR5Core.h
DRAMPower/standards/lpddr5/LPDDR5Interface.h
DRAMPower/standards/lpddr5/core_calculation_LPDDR5.h
DRAMPower/standards/lpddr5/interface_calculation_LPDDR5.h
DRAMPower/standards/lpddr5/types.h
DRAMPower/util/Serialize.h
DRAMPower/util/Deserialize.h
)
target_include_directories(DRAMPower PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_features(DRAMPower PUBLIC cxx_std_17)
set_target_properties(DRAMPower PROPERTIES CXX_EXTENSIONS OFF)
set_target_properties(DRAMPower PROPERTIES CXX_STANDARD_REQUIRED ON)
target_link_libraries(DRAMPower
PUBLIC
DRAMUtils::DRAMUtils
)
# Add test functions
if(DRAMPOWER_BUILD_TESTS)
target_compile_definitions(DRAMPower PUBLIC DRAMPOWER_TESTING)
endif()
add_library(DRAMPower::DRAMPower ALIAS DRAMPower)
install(TARGETS DRAMPower FILE_SET api)
================================================
FILE: src/DRAMPower/DRAMPower/Exceptions.h
================================================
#ifndef DRAMPOWER_EXCEPTIONS_H
#define DRAMPOWER_EXCEPTIONS_H
#include
#include
namespace DRAMPower {
class Exception : public std::exception {
// protected constructors
protected:
// public constructors
public:
// Constructors with message
explicit Exception(const std::string &message) : m_message(message) {}
explicit Exception(std::string &&message) : m_message(std::move(message)) {}
// Exception without message should not be allowed
Exception() = delete;
// Copy and move constructors and assignment operators
Exception(const Exception &other) = default;
Exception &operator=(const Exception &other) = default;
Exception(Exception &&other) = default;
Exception &operator=(Exception &&other) = default;
// Destructor
virtual ~Exception() noexcept = default;
// Public member functions
public:
const char *what() const noexcept override {
return m_message.c_str();
}
// Private member variables
private:
std::string m_message;
};
} // namespace DRAMPower
#endif /* DRAMPOWER_EXCEPTIONS_H */
================================================
FILE: src/DRAMPower/DRAMPower/Types.h
================================================
#ifndef DRAMPOWER_TYPES_H
#define DRAMPOWER_TYPES_H
#include
#include
namespace DRAMPower {
using timestamp_t = uint64_t;
using interval_t = util::interval_counter;
}
#endif /* DRAMPOWER_TYPES_H */
================================================
FILE: src/DRAMPower/DRAMPower/command/CmdType.h
================================================
#ifndef DRAMPOWER_COMMAND_CMDTYPE_H
#define DRAMPOWER_COMMAND_CMDTYPE_H
#include
#include
namespace DRAMPower
{
// Taken from DRAM 4.0
// DRAMSys
// \ \__> DRAMPower
// \ \_v
// \_______> DRAMCommon
enum class CmdType {
NOP = 0, // 0
RD, // 1
WR, // 2
RDA, // 3
WRA, // 4
ACT, // 5
PRE, // 6
REFB, // 7
REFP2B, // 8
PRESB, // 9
REFSB, // 10
PREA, // 11
REFA, // 12
PDEA, // 13
PDEP, // 14
PDXA, // 15
PDXP, // 16
SREFEN, // 17
SREFEX, // 18
DSMEN, // 19
DSMEX, // 20
END_OF_SIMULATION, // 21
COUNT, // 22
};
namespace CmdTypeUtil
{
constexpr bool needs_data(CmdType cmd)
{
switch (cmd)
{
case CmdType::RD:
case CmdType::RDA:
case CmdType::WR:
case CmdType::WRA:
return true;
default:
return false;
};
};
constexpr CmdType from_string(const std::string_view& str)
{
if (str == "NOP")
return CmdType::NOP;
if (str == "ACT")
return CmdType::ACT;
if (str == "PRE")
return CmdType::PRE;
if (str == "PREA")
return CmdType::PREA;
if (str == "PRESB")
return CmdType::PRESB;
if (str == "REFA")
return CmdType::REFA;
if (str == "REFB")
return CmdType::REFB;
if (str == "REFSB")
return CmdType::REFSB;
if (str == "REFP2B")
return CmdType::REFP2B;
if (str == "RD")
return CmdType::RD;
if (str == "RDA")
return CmdType::RDA;
if (str == "WR")
return CmdType::WR;
if (str == "WRA")
return CmdType::WRA;
if (str == "PDEA")
return CmdType::PDEA;
if (str == "PDEP")
return CmdType::PDEP;
if (str == "PDXA")
return CmdType::PDXA;
if (str == "PDXP")
return CmdType::PDXP;
if (str == "SREFEN")
return CmdType::SREFEN;
if (str == "SREFEX")
return CmdType::SREFEX;
if (str == "DSMEN")
return CmdType::DSMEN;
if (str == "DSMEX")
return CmdType::DSMEX;
if (str == "END")
return CmdType::END_OF_SIMULATION;
return CmdType::NOP;
};
constexpr const char * to_string(CmdType cmd)
{
switch (cmd)
{
case CmdType::NOP:
return "NOP";
case CmdType::ACT:
return "ACT";
case CmdType::PRE:
return "PRE";
case CmdType::PREA:
return "PREA";
case CmdType::REFA:
return "REFA";
case CmdType::REFB:
return "REFB";
case CmdType::RD:
return "RD";
case CmdType::RDA:
return "RDA";
case CmdType::WR:
return "WR";
case CmdType::WRA:
return "WRA";
case CmdType::REFSB:
return "REFSB";
case CmdType::REFP2B:
return "REFP2B";
case CmdType::PRESB:
return "PRESB";
case CmdType::PDEA:
return "PDEA";
case CmdType::PDEP:
return "PDEP";
case CmdType::PDXA:
return "PDXA";
case CmdType::PDXP:
return "PDXP";
case CmdType::SREFEN:
return "SREFEN";
case CmdType::SREFEX:
return "SREFEX";
case CmdType::DSMEN:
return "DSMEN";
case CmdType::DSMEX:
return "DSMEX";
case CmdType::END_OF_SIMULATION:
return "END_OF_SIMULATION";
default:
return "to_string()";
}
}
inline std::ostream& operator<<(std::ostream& os, CmdType cmd) {
return os << to_string(cmd);
}
}
}
#endif /* DRAMPOWER_COMMAND_CMDTYPE_H */
================================================
FILE: src/DRAMPower/DRAMPower/command/Command.cpp
================================================
#include "Command.h"
namespace DRAMPower {
TargetCoordinate::TargetCoordinate(std::size_t bank_id, std::size_t bank_group_id, std::size_t rank_id)
: bank(bank_id), bankGroup(bank_group_id), rank(rank_id)
{};
TargetCoordinate::TargetCoordinate(std::size_t bank_id, std::size_t bank_group_id, std::size_t rank_id, std::size_t row_id)
: bank(bank_id), bankGroup(bank_group_id), rank(rank_id), row(row_id)
{};
TargetCoordinate::TargetCoordinate(std::size_t bank_id, std::size_t bank_group_id, std::size_t rank_id, std::size_t row_id, std::size_t column_id)
: bank(bank_id), bankGroup(bank_group_id), rank(rank_id), row(row_id), column(column_id)
{};
Command::Command(timestamp_t timestamp, CmdType type, TargetCoordinate targetCoord, const uint8_t * data, std::size_t sz_bits)
: timestamp(timestamp)
, type(type)
, targetCoordinate(targetCoord)
, data(data)
, sz_bits(sz_bits)
{};
} // namespace DRAMPower
================================================
FILE: src/DRAMPower/DRAMPower/command/Command.h
================================================
#ifndef DRAMPOWER_COMMAND_COMMAND_H
#define DRAMPOWER_COMMAND_COMMAND_H
#include
#include
#include
namespace DRAMPower {
struct TargetCoordinate {
std::size_t bank = 0;
std::size_t bankGroup = 0;
std::size_t rank = 0;
std::size_t row = 0;
std::size_t column = 0;
TargetCoordinate() = default;
TargetCoordinate(std::size_t bank_id, std::size_t bank_group_id, std::size_t rank_id);
TargetCoordinate(std::size_t bank_id, std::size_t bank_group_id, std::size_t rank_id, std::size_t row_id);
TargetCoordinate(std::size_t bank_id, std::size_t bank_group_id, std::size_t rank_id, std::size_t row_id, std::size_t column_id);
};
class Command {
public:
Command() = default;
Command(timestamp_t timestamp, CmdType type, TargetCoordinate targetCoord = {}, const uint8_t * data = nullptr, std::size_t sz_bits = 0);
public:
timestamp_t timestamp = 0;
CmdType type;
TargetCoordinate targetCoordinate;
const uint8_t * data = 0x00;
std::size_t sz_bits;
//uint64_t burstLength;
public:
};
}
#endif /* DRAMPOWER_COMMAND_COMMAND_H */
================================================
FILE: src/DRAMPower/DRAMPower/command/Pattern.cpp
================================================
#include "Pattern.h"
#include
#include
#include
namespace DRAMPower {
PatternEncoderOverrides::PatternEncoderOverrides(std::initializer_list _settings)
{
for (const auto &setting : _settings)
{
this->settings.emplace(setting.descriptor, setting.bitSpec);
}
}
void PatternEncoderOverrides::updateSettings(std::initializer_list _settings)
{
// Update settings if descriptor is already present
for (const auto &setting : _settings)
{
this->settings[setting.descriptor] = setting.bitSpec;
}
}
std::unordered_map PatternEncoderOverrides::getSettings()
{
return this->settings;
}
const std::unordered_map& PatternEncoderOverrides::getSettings() const {
return this->settings;
}
PatternEncoderBitSpec PatternEncoderOverrides::getSetting(pattern_descriptor::t descriptor)
{
if (this->settings.find(descriptor) != this->settings.end())
{
return this->settings.at(descriptor);
}
return PatternEncoderBitSpec::INVALID;
}
bool PatternEncoderOverrides::hasSetting(pattern_descriptor::t descriptor)
{
return this->settings.find(descriptor) != this->settings.end();
}
bool PatternEncoderOverrides::removeSetting(pattern_descriptor::t descriptor)
{
return this->settings.erase(descriptor) > 0;
}
PatternEncoder::PatternEncoder(PatternEncoderOverrides settings)
: settings(settings)
{}
inline bool PatternEncoder::applyBitSpec(
PatternEncoderOverrides &spec,
pattern_descriptor::t descriptor,
bool LAST_BIT,
bool default_bit
)
{
auto setting = spec.getSetting(descriptor);
switch (setting)
{
case PatternEncoderBitSpec::L:
return false;
case PatternEncoderBitSpec::H:
return true;
case PatternEncoderBitSpec::LAST_BIT:
return LAST_BIT;
case PatternEncoderBitSpec::INVALID:
return default_bit;
default:
assert(false);
break;
}
return false;
}
uint64_t PatternEncoder::encode(const Command& cmd, const std::vector& pattern, const uint64_t lastpattern)
{
return encode(cmd.targetCoordinate, pattern, lastpattern);
}
uint64_t PatternEncoder::encode(const TargetCoordinate& targetCoordinate, const std::vector& pattern, const uint64_t lastpattern)
{
using namespace pattern_descriptor;
std::bitset<64> bitset(0);
std::bitset<32> bank_bits(targetCoordinate.bank);
std::bitset<32> row_bits(targetCoordinate.row);
std::bitset<32> column_bits(targetCoordinate.column);
std::bitset<32> bank_group_bits(targetCoordinate.bankGroup);
std::size_t n = pattern.size() - 1;
uint64_t opcodeshifter = 1;
uint16_t opcodecount = 0;
assert(n < 64);
for (const auto descriptor : pattern) {
// assert(n >= 0); // std::size_t is unsigned
switch (descriptor) {
case H:
bitset[n] = true;
break;
case L:
bitset[n] = false;
break;
// Command bits
case BL:
case CID0:
case CID1:
case CID2:
case CID3:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, true);
break;
case V:
case X:
case AP:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, false);
break;
// Target Coordinate bits
// Bank bits
case BA0:
bitset[n] = bank_bits[0];
break;
case BA1:
bitset[n] = bank_bits[1];
break;
case BA2:
bitset[n] = bank_bits[2];
break;
case BA3:
bitset[n] = bank_bits[3];
break;
case BA4:
bitset[n] = bank_bits[4];
break;
case BA5:
bitset[n] = bank_bits[5];
break;
case BA6:
bitset[n] = bank_bits[6];
break;
case BA7:
bitset[n] = bank_bits[7];
break;
case BA8:
bitset[n] = bank_bits[8];
break;
// BG bits
case BG0:
bitset[n] = bank_group_bits[0];
break;
case BG1:
bitset[n] = bank_group_bits[1];
break;
case BG2:
bitset[n] = bank_group_bits[2];
break;
case C0:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, column_bits[0]);
break;
case C1:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, column_bits[1]);
break;
case C2:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, column_bits[2]);
break;
case C3:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, column_bits[3]);
break;
case C4:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, column_bits[4]);
break;
case C5:
bitset[n] = column_bits[5];
break;
case C6:
bitset[n] = column_bits[6];
break;
case C7:
bitset[n] = column_bits[7];
break;
case C8:
bitset[n] = column_bits[8];
break;
case C9:
bitset[n] = column_bits[9];
break;
case C10:
bitset[n] = applyBitSpec(settings, descriptor, ((lastpattern >> n) & 1) == 1, column_bits[10]);
break;
case C11:
bitset[n] = column_bits[C11];
break;
case C12:
bitset[n] = column_bits[C12];
break;
case C13:
bitset[n] = column_bits[C13];
break;
case C14:
bitset[n] = column_bits[C14];
break;
case C15:
bitset[n] = column_bits[C15];
break;
case C16:
bitset[n] = column_bits[C16];
break;
// Row bits
case R0:
bitset[n] = row_bits[0];
break;
case R1:
bitset[n] = row_bits[1];
break;
case R2:
bitset[n] = row_bits[2];
break;
case R3:
bitset[n] = row_bits[3];
break;
case R4:
bitset[n] = row_bits[4];
break;
case R5:
bitset[n] = row_bits[5];
break;
case R6:
bitset[n] = row_bits[6];
break;
case R7:
bitset[n] = row_bits[7];
break;
case R8:
bitset[n] = row_bits[8];
break;
case R9:
bitset[n] = row_bits[9];
break;
case R10:
bitset[n] = row_bits[10];
break;
case R11:
bitset[n] = row_bits[11];
break;
case R12:
bitset[n] = row_bits[12];
break;
case R13:
bitset[n] = row_bits[13];
break;
case R14:
bitset[n] = row_bits[14];
break;
case R15:
bitset[n] = row_bits[15];
break;
case R16:
bitset[n] = row_bits[16];
break;
case R17:
bitset[n] = row_bits[17];
break;
case OPCODE:
// Example: opcode 0x31 results in pattern 0b0011'0001
assert(m_opcodeLength > opcodecount);
bitset[n] = m_opcode & opcodeshifter;
opcodeshifter <<= 1;
++opcodecount;
break;
default:
break;
}
--n;
}
return bitset.to_ullong();
}
void PatternEncoder::setOpcode(uint64_t opcode, uint16_t opcodeLength) {
m_opcode = opcode;
m_opcodeLength = opcodeLength;
}
uint64_t PatternEncoder::getOpcode() const {
return m_opcode;
}
uint16_t PatternEncoder::getOpcodeLength() const {
return m_opcodeLength;
}
void PatternEncoder::serialize(std::ostream& stream) const {
stream.write(reinterpret_cast(&m_opcode), sizeof(m_opcode));
stream.write(reinterpret_cast(&m_opcodeLength), sizeof(m_opcodeLength));
// settings
const std::size_t settingsSize = settings.getSettings().size();
stream.write(reinterpret_cast(&settingsSize), sizeof(settingsSize));
for (const auto& [descriptor, bitSpec] : settings.getSettings()) {
stream.write(reinterpret_cast(&descriptor), sizeof(descriptor));
stream.write(reinterpret_cast(&bitSpec), sizeof(bitSpec));
}
}
void PatternEncoder::deserialize(std::istream& stream) {
stream.read(reinterpret_cast(&m_opcode), sizeof(m_opcode));
stream.read(reinterpret_cast(&m_opcodeLength), sizeof(m_opcodeLength));
// settings
std::size_t settingsSize = 0;
stream.read(reinterpret_cast(&settingsSize), sizeof(settingsSize));
settings = PatternEncoderOverrides{};
for (std::size_t i = 0; i < settingsSize; ++i) {
pattern_descriptor::t descriptor;
PatternEncoderBitSpec bitSpec;
stream.read(reinterpret_cast(&descriptor), sizeof(descriptor));
stream.read(reinterpret_cast(&bitSpec), sizeof(bitSpec));
settings.updateSettings({{descriptor, bitSpec}});
}
}
} // namespace DRAMPower
================================================
FILE: src/DRAMPower/DRAMPower/command/Pattern.h
================================================
#ifndef DRAMPOWER_COMMAND_PATTERN_H
#define DRAMPOWER_COMMAND_PATTERN_H
#include
#include
#include
#include
#include
namespace DRAMPower {
namespace pattern_descriptor {
enum t {
H, L,
V, X,
A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17,
BG0, BG1, BG2, BA0, BA1, BA2, BA3, BA4, BA5, BA6, BA7, BA8,
C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16,
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23,
CID0, CID1, CID2, CID3,
AP,
BL,
OPCODE, // Example: opcode 0x03 pattern: {H, L, OPCODE, OPCODE, OPCODE, OPCODE} result in 0b100011
};
}
enum class PatternEncoderBitSpec
{
L = 0,
H = 1,
LAST_BIT = 2,
INVALID = -1
};
// struct for initializer list in PatternEncoderSettings
struct PatternEncoderSettingsEntry {
pattern_descriptor::t descriptor;
PatternEncoderBitSpec bitSpec;
};
// class to store pattern descriptor overrides
class PatternEncoderOverrides
{
private:
std::unordered_map settings;
public:
// Constructor with initializer list for settings
PatternEncoderOverrides() = default;
PatternEncoderOverrides(std::initializer_list _settings);
public:
void updateSettings(std::initializer_list _settings);
std::unordered_map getSettings();
PatternEncoderBitSpec getSetting(pattern_descriptor::t descriptor);
const std::unordered_map& getSettings() const;
bool hasSetting(pattern_descriptor::t descriptor);
bool removeSetting(pattern_descriptor::t descriptor);
};
class PatternEncoder : public util::Serialize, public util::Deserialize // Currently LPDDR4
{
public:
PatternEncoderOverrides settings;
PatternEncoder(PatternEncoderOverrides settings);
private:
inline bool applyBitSpec(
PatternEncoderOverrides &spec,
pattern_descriptor::t descriptor,
bool LAST_BIT,
bool default_bit
);
public:
void setOpcode(uint64_t opcode, uint16_t opcodeLength);
uint64_t getOpcode() const;
uint16_t getOpcodeLength() const;
// Overrides
public:
void serialize(std::ostream& stream) const override;
void deserialize(std::istream& stream) override;
public:
uint64_t encode(const Command& cmd, const std::vector& pattern, const uint64_t lastpattern);
uint64_t encode(const TargetCoordinate& coordinate, const std::vector& pattern, const uint64_t lastpattern);
// Private member variables
private:
uint64_t m_opcode = 0;
uint16_t m_opcodeLength = 0;
};
} // namespace DRAMPower
#endif /* DRAMPOWER_COMMAND_PATTERN_H */
================================================
FILE: src/DRAMPower/DRAMPower/data/energy.cpp
================================================
#include "energy.h"
using namespace DRAMPower;
double energy_info_t::total() const
{
auto total = E_act
+ E_pre
+ E_bg_act
+ E_bg_pre
+ E_RD
+ E_WR
+ E_RDA
+ E_WRA
//+ E_pre_RDA
//+ E_pre_WRA
+ E_ref_AB
+ E_ref_PB
+ E_ref_SB
+ E_ref_2B;
return total;
};
void energy_info_t::to_json(json_t &j) const
{
j = nlohmann::json{
{"ACT", E_act},
{"PRE", E_pre},
{"BG_ACT", E_bg_act},
{"BG_PRE", E_bg_pre},
{"RD", E_RD},
{"WR", E_WR},
{"RDA", E_RDA},
{"WRA", E_WRA},
{"PRE_RDA", E_pre_RDA},
{"PRE_WRA", E_pre_WRA},
{"REF_AB", E_ref_AB},
{"REF_PB", E_ref_PB},
{"REF_SB", E_ref_SB},
{"REF_2B", E_ref_2B}
};
}
energy_info_t& energy_info_t::operator+=(const DRAMPower::energy_info_t& other)
{
this->E_act += other.E_act;
this->E_pre += other.E_pre;
this->E_bg_act += other.E_bg_act;
this->E_bg_pre += other.E_bg_pre;
this->E_RD += other.E_RD;
this->E_WR += other.E_WR;
this->E_RDA += other.E_RDA;
this->E_WRA += other.E_WRA;
this->E_pre_RDA += other.E_pre_RDA;
this->E_pre_WRA += other.E_pre_WRA;
this->E_ref_AB += other.E_ref_AB;
this->E_ref_PB += other.E_ref_PB;
this->E_ref_SB += other.E_ref_SB;
this->E_ref_2B += other.E_ref_2B;
return *this;
}
double DRAMPower::energy_t::total() const
{
double total = 0.0;
energy_info_t bank_energy_total;
for (const auto& bank_e : this->bank_energy)
bank_energy_total += bank_e;
total += bank_energy_total.total() + E_bg_act_shared + E_PDNA + E_PDNP + E_sref + E_dsm + E_refab;
return total;
}
void DRAMPower::interface_energy_info_t::to_json(json_t &j) const
{
j = nlohmann::json{};
j["controller"]["dynamicEnergy"] = controller.dynamicEnergy;
j["controller"]["staticEnergy"] = controller.staticEnergy;
j["dram"]["dynamicEnergy"] = dram.dynamicEnergy;
j["dram"]["staticEnergy"] = dram.staticEnergy;
}
void DRAMPower::energy_t::to_json(json_t &j) const
{
j = nlohmann::json{
{"E_bg_act_shared", E_bg_act_shared},
{"E_PDNA", E_PDNA},
{"E_PDNP", E_PDNP},
{"E_sref", E_sref},
{"E_dsm", E_dsm},
{"E_refab", E_refab}
};
// Bank energy
auto energy_arr = nlohmann::json::array();
for (const energy_info_t& energy : bank_energy)
{
json_t bank_energy_json;
energy.to_json(bank_energy_json);
energy_arr.push_back(bank_energy_json);
}
j[this->get_Bank_energy_keyword()] = energy_arr;
}
energy_info_t DRAMPower::energy_t::aggregated_bank_energy() const
{
energy_info_t total;
for (const auto& bank_e : this->bank_energy)
total += bank_e;
total.E_bg_act += this->E_bg_act_shared;
return total;
}
================================================
FILE: src/DRAMPower/DRAMPower/data/energy.h
================================================
#ifndef DRAMPOWER_CALCULATION_ENERGY_H
#define DRAMPOWER_CALCULATION_ENERGY_H
#pragma once
#include
#include
#include
namespace DRAMPower {
struct energy_info_t
{
double E_act = 0.0;
double E_pre = 0.0;
double E_bg_act = 0.0;
double E_bg_pre = 0.0;
double E_RD = 0.0;
double E_WR = 0.0;
double E_RDA = 0.0;
double E_WRA = 0.0;
double E_pre_RDA = 0.0;
double E_pre_WRA = 0.0;
double E_ref_AB = 0.0;
double E_ref_PB = 0.0;
double E_ref_SB = 0.0;
double E_ref_2B = 0.0;
double total() const;
void to_json(json_t &j) const;
energy_info_t& operator+=(const energy_info_t & other);
// Operator << for std::cout
friend std::ostream & operator<<(std::ostream & os, const energy_info_t & ei)
{
os << "ACT: " << ei.E_act << " ";
os << "PRE: " << ei.E_pre << " ";
os << "BG_ACT: " << ei.E_bg_act << " ";
os << "BG_PRE: " << ei.E_bg_pre << " ";
os << "RD: " << ei.E_RD << " ";
os << "WR: " << ei.E_WR << " ";
os << "RDA: " << ei.E_RDA << " ";
os << "WRA: " << ei.E_WRA << " ";
os << "PRE_RDA: " << ei.E_pre_RDA << " ";
os << "PRE_WRA: " << ei.E_pre_WRA << " ";
os << "REF_AB: " << ei.E_ref_AB << " ";
os << "REF_PB: " << ei.E_ref_PB << " ";
os << "REF_SB: " << ei.E_ref_SB << " ";
os << "REF_2B: " << ei.E_ref_2B << " ";
return os;
}
};
struct energy_t
{
std::vector bank_energy;
energy_info_t aggregated_bank_energy() const;
void to_json(json_t &j) const;
constexpr inline const char * get_Bank_energy_keyword() const
{
return "BankEnergy";
}
double E_bg_act_shared = 0.0;
double E_PDNA = 0.0;
double E_PDNP = 0.0;
double E_sref = 0.0;
double E_dsm = 0.0;
double E_refab = 0.0;
energy_t(std::size_t num_banks) : bank_energy(num_banks) {};
// get fields of os stream output
friend std::ostream & operator<<(std::ostream & os, const energy_t & e)
{
os << "E_bg_act_shared: " << e.E_bg_act_shared << " ";
os << "E_PDNA: " << e.E_PDNA << " ";
os << "E_PDNP: " << e.E_PDNP << " ";
os << "E_sref: " << e.E_sref << " ";
os << "E_dsm: " << e.E_dsm << " ";
os << "E_refab: " << e.E_refab << " ";
return os;
}
double total() const;
};
struct interface_energy_t
{
double dynamicEnergy = 0.0;
double staticEnergy = 0.0;
interface_energy_t &operator+=(const interface_energy_t &rhs) {
dynamicEnergy += rhs.dynamicEnergy;
staticEnergy += rhs.staticEnergy;
return *this;
}
friend interface_energy_t operator+(interface_energy_t lhs, const interface_energy_t &rhs) {
lhs += rhs;
return lhs;
}
};
struct interface_energy_info_t
{
interface_energy_t controller;
interface_energy_t dram;
double total() const {
return controller.dynamicEnergy + controller.staticEnergy + dram.dynamicEnergy + dram.staticEnergy;
}
interface_energy_info_t &operator+=(const interface_energy_info_t &rhs) {
controller += rhs.controller;
dram += rhs.dram;
return *this;
}
friend interface_energy_info_t operator+(interface_energy_info_t lhs,
const interface_energy_info_t &rhs) {
lhs += rhs;
return lhs;
}
friend std::ostream & operator<<(std::ostream & os, const interface_energy_info_t & e)
{
os << "Controller: dynamicEnergy: " << e.controller.dynamicEnergy << " ";
os << "staticEnergy: " << e.controller.staticEnergy << std::endl;
os << "DRAM: dynamicEnergy: " << e.dram.dynamicEnergy << " ";
os << "staticEnergy: " << e.dram.staticEnergy << std::endl;
os << "Total: " << e.total();
return os;
}
void to_json(json_t &j) const;
};
};
#endif /* DRAMPOWER_CALCULATION_ENERGY_H */
================================================
FILE: src/DRAMPower/DRAMPower/data/stats.h
================================================
#ifndef DRAMPOWER_DATA_STATS_H
#define DRAMPOWER_DATA_STATS_H
#include
#include
#include
#include
#include
namespace DRAMPower
{
struct CycleStats : public util::Serialize, public util::Deserialize
{
struct command_stats_t : public util::Serialize, public util::Deserialize {
uint64_t act = 0;
uint64_t pre = 0;
uint64_t preSameBank = 0;
uint64_t reads = 0;
uint64_t writes = 0;
uint64_t refAllBank = 0;
uint64_t refPerBank = 0;
uint64_t refPerTwoBanks = 0;
uint64_t refSameBank = 0;
uint64_t readAuto = 0;
uint64_t writeAuto = 0;
void serialize(std::ostream& stream) const override {
stream.write(reinterpret_cast(&act), sizeof(act));
stream.write(reinterpret_cast(&pre), sizeof(pre));
stream.write(reinterpret_cast(&preSameBank), sizeof(preSameBank));
stream.write(reinterpret_cast(&reads), sizeof(reads));
stream.write(reinterpret_cast(&writes), sizeof(writes));
stream.write(reinterpret_cast(&refAllBank), sizeof(refAllBank));
stream.write(reinterpret_cast(&refPerBank), sizeof(refPerBank));
stream.write(reinterpret_cast(&refPerTwoBanks), sizeof(refPerTwoBanks));
stream.write(reinterpret_cast(&refSameBank), sizeof(refSameBank));
stream.write(reinterpret_cast(&readAuto), sizeof(readAuto));
stream.write(reinterpret_cast(&writeAuto), sizeof(writeAuto));
}
void deserialize(std::istream& stream) override {
stream.read(reinterpret_cast(&act), sizeof(act));
stream.read(reinterpret_cast(&pre), sizeof(pre));
stream.read(reinterpret_cast(&preSameBank), sizeof(preSameBank));
stream.read(reinterpret_cast(&reads), sizeof(reads));
stream.read(reinterpret_cast(&writes), sizeof(writes));
stream.read(reinterpret_cast(&refAllBank), sizeof(refAllBank));
stream.read(reinterpret_cast(&refPerBank), sizeof(refPerBank));
stream.read(reinterpret_cast(&refPerTwoBanks), sizeof(refPerTwoBanks));
stream.read(reinterpret_cast(&refSameBank), sizeof(refSameBank));
stream.read(reinterpret_cast(&readAuto), sizeof(readAuto));
stream.read(reinterpret_cast(&writeAuto), sizeof(writeAuto));
}
// operator ==
bool operator==(const command_stats_t& rhs) const {
return act == rhs.act &&
pre == rhs.pre &&
preSameBank == rhs.preSameBank &&
reads == rhs.reads &&
writes == rhs.writes &&
refAllBank == rhs.refAllBank &&
refPerBank == rhs.refPerBank &&
refPerTwoBanks == rhs.refPerTwoBanks &&
refSameBank == rhs.refSameBank &&
readAuto == rhs.readAuto &&
writeAuto == rhs.writeAuto;
}
} counter;
struct cycles_t : public util::Serialize, public util::Deserialize {
uint64_t act = 0;
uint64_t pre = 0;
uint64_t powerDownAct = 0;
uint64_t powerDownPre = 0;
uint64_t selfRefresh = 0;
uint64_t deepSleepMode = 0;
uint64_t activeTime() const { return act; };
//uint64_t prechargeTime;
void serialize(std::ostream& stream) const override {
stream.write(reinterpret_cast(&act), sizeof(act));
stream.write(reinterpret_cast(&pre), sizeof(pre));
stream.write(reinterpret_cast(&powerDownAct), sizeof(powerDownAct));
stream.write(reinterpret_cast(&powerDownPre), sizeof(powerDownPre));
stream.write(reinterpret_cast(&selfRefresh), sizeof(selfRefresh));
stream.write(reinterpret_cast(&deepSleepMode), sizeof(deepSleepMode));
}
void deserialize(std::istream& stream) override {
stream.read(reinterpret_cast(&act), sizeof(act));
stream.read(reinterpret_cast(&pre), sizeof(pre));
stream.read(reinterpret_cast(&powerDownAct), sizeof(powerDownAct));
stream.read(reinterpret_cast(&powerDownPre), sizeof(powerDownPre));
stream.read(reinterpret_cast(&selfRefresh), sizeof(selfRefresh));
stream.read(reinterpret_cast(&deepSleepMode), sizeof(deepSleepMode));
}
// operator ==
bool operator==(const cycles_t& rhs) const {
return act == rhs.act &&
pre == rhs.pre &&
powerDownAct == rhs.powerDownAct &&
powerDownPre == rhs.powerDownPre &&
selfRefresh == rhs.selfRefresh &&
deepSleepMode == rhs.deepSleepMode;
}
} cycles;
struct prepos_t : public util::Serialize, public util::Deserialize {
uint64_t readMerged = 0;
uint64_t readMergedTime = 0;
uint64_t writeMerged = 0;
uint64_t writeMergedTime = 0;
uint64_t readSeamless = 0;
uint64_t writeSeamless = 0;
void serialize(std::ostream& stream) const override {
stream.write(reinterpret_cast(&readMerged), sizeof(readMerged));
stream.write(reinterpret_cast(&readMergedTime), sizeof(readMergedTime));
stream.write(reinterpret_cast(&writeMerged), sizeof(writeMerged));
stream.write(reinterpret_cast(&writeMergedTime), sizeof(writeMergedTime));
stream.write(reinterpret_cast(&readSeamless), sizeof(readSeamless));
stream.write(reinterpret_cast(&writeSeamless), sizeof(writeSeamless));
}
void deserialize(std::istream& stream) override {
stream.read(reinterpret_cast(&readMerged), sizeof(readMerged));
stream.read(reinterpret_cast(&readMergedTime), sizeof(readMergedTime));
stream.read(reinterpret_cast(&writeMerged), sizeof(writeMerged));
stream.read(reinterpret_cast(&writeMergedTime), sizeof(writeMergedTime));
stream.read(reinterpret_cast(&readSeamless), sizeof(readSeamless));
stream.read(reinterpret_cast(&writeSeamless), sizeof(writeSeamless));
}
// operator ==
bool operator==(const prepos_t& rhs) const {
return readMerged == rhs.readMerged &&
readMergedTime == rhs.readMergedTime &&
writeMerged == rhs.writeMerged &&
writeMergedTime == rhs.writeMergedTime &&
readSeamless == rhs.readSeamless &&
writeSeamless == rhs.writeSeamless;
}
} prepos;
void serialize(std::ostream& stream) const override {
counter.serialize(stream);
cycles.serialize(stream);
prepos.serialize(stream);
}
void deserialize(std::istream& stream) override {
counter.deserialize(stream);
cycles.deserialize(stream);
prepos.deserialize(stream);
}
// operator ==
bool operator==(const CycleStats& rhs) const {
return counter == rhs.counter &&
cycles == rhs.cycles &&
prepos == rhs.prepos;
}
};
struct TogglingStats
{
util::bus_stats_t read;
util::bus_stats_t write;
};
struct SimulationStats
{
util::bus_stats_t commandBus;
util::bus_stats_t readBus;
util::bus_stats_t writeBus;
util::bus_stats_t clockStats;
util::bus_stats_t wClockStats;
util::bus_stats_t readDBI;
util::bus_stats_t writeDBI;
TogglingStats togglingStats;
util::bus_stats_t readDQSStats;
util::bus_stats_t writeDQSStats;
std::vector bank;
std::vector rank_total;
// Operator ==
bool operator==(const SimulationStats& other) const {
// Compare banks
bool banksEqual = true;
if (bank.size() != other.bank.size()) {
banksEqual = false;
} else {
for (size_t i = 0; i < bank.size(); ++i) {
if (!(bank[i] == other.bank[i])) {
banksEqual = false;
break;
}
}
}
bool rank_totalEqual = true;
if (rank_total.size() != other.rank_total.size()) {
rank_totalEqual = false;
} else {
for (size_t i = 0; i < rank_total.size(); ++i) {
if (!(rank_total[i] == other.rank_total[i])) {
rank_totalEqual = false;
break;
}
}
}
return commandBus == other.commandBus &&
readBus == other.readBus &&
writeBus == other.writeBus &&
clockStats == other.clockStats &&
wClockStats == other.wClockStats &&
readDBI == other.readDBI &&
writeDBI == other.writeDBI &&
togglingStats.read == other.togglingStats.read &&
togglingStats.write == other.togglingStats.write &&
readDQSStats == other.readDQSStats &&
writeDQSStats == other.writeDQSStats &&
banksEqual &&
rank_totalEqual;
}
};
};
#endif /* DRAMPOWER_DATA_STATS_H */
================================================
FILE: src/DRAMPower/DRAMPower/dram/Bank.h
================================================
#ifndef DRAMPOWER_DDR_BANK_H
#define DRAMPOWER_DDR_BANK_H
#include
#include
#include
#include
#include
namespace DRAMPower {
struct Bank : public util::Serialize, public util::Deserialize {
public:
enum class BankState {
BANK_PRECHARGED = 0,
BANK_ACTIVE = 1,
};
public:
CycleStats::command_stats_t counter;
struct {
interval_t act;
interval_t powerDownAct;
interval_t powerDownPre;
} cycles;
BankState bankState;
public:
timestamp_t latestPre = 0;
timestamp_t refreshEndTime = 0;
void serialize(std::ostream& stream) const override {
stream.write(reinterpret_cast(&bankState), sizeof(bankState));
stream.write(reinterpret_cast(&latestPre), sizeof(latestPre));
stream.write(reinterpret_cast(&refreshEndTime), sizeof(refreshEndTime));
cycles.act.serialize(stream);
cycles.powerDownAct.serialize(stream);
cycles.powerDownPre.serialize(stream);
counter.serialize(stream);
}
void deserialize(std::istream& stream) override {
stream.read(reinterpret_cast(&bankState), sizeof(bankState));
stream.read(reinterpret_cast(&latestPre), sizeof(latestPre));
stream.read(reinterpret_cast(&refreshEndTime), sizeof(refreshEndTime));
cycles.act.deserialize(stream);
cycles.powerDownAct.deserialize(stream);
cycles.powerDownPre.deserialize(stream);
counter.deserialize(stream);
}
};
}
#endif /* DRAMPOWER_DDR_BANK_H */
================================================
FILE: src/DRAMPower/DRAMPower/dram/Interface.cpp
================================================
#include "Interface.h"
namespace DRAMPower {
using namespace DRAMUtils::Config;
void TogglingHandle::TogglingHandleLastBurst::serialize(std::ostream &stream) const
{
stream.write(reinterpret_cast(&last_length), sizeof(last_length));
stream.write(reinterpret_cast(&last_load), sizeof(last_load));
stream.write(reinterpret_cast(&handled), sizeof(handled));
}
void TogglingHandle::TogglingHandleLastBurst::deserialize(std::istream &stream) {
stream.read(reinterpret_cast(&last_length), sizeof(last_length));
stream.read(reinterpret_cast(&last_load), sizeof(last_load));
stream.read(reinterpret_cast(&handled), sizeof(handled));
}
TogglingHandle::TogglingHandle(const uint64_t width, const uint64_t datarate, const double toggling_rate, const double duty_cycle, const bool enabled)
: width(width)
, datarate(datarate)
, toggling_rate(toggling_rate)
, duty_cycle(duty_cycle)
, enableflag(enabled)
{
assert(width > 0); // Check bounds
assert(datarate > 0); // Check bounds
assert(duty_cycle >= 0 && duty_cycle <= 1); // Check bounds
assert(toggling_rate >= 0 && toggling_rate <= 1); // Check bounds
}
TogglingHandle::TogglingHandle(const uint64_t width, const uint64_t datarate, const double toggling_rate, const double duty_cycle, DRAMUtils::Config::TogglingRateIdlePattern idlepattern, const bool enabled)
: width(width)
, datarate(datarate)
, toggling_rate(toggling_rate)
, duty_cycle(duty_cycle)
, enableflag(enabled)
, idlepattern(idlepattern)
{
assert(width > 0); // Check bounds
assert(datarate > 0); // Check bounds
assert(duty_cycle >= 0 && duty_cycle <= 1); // Check bounds
assert(toggling_rate >= 0 && toggling_rate <= 1); // Check bounds
}
void TogglingHandle::disable(timestamp_t timestamp)
{
timestamp_t virtualtimestamp = timestamp * this->datarate;
if(!this->enableflag) {
return;
}
if (this->last_burst) {
if(virtualtimestamp >= this->last_burst.last_length + this->last_burst.last_load) {
this->count += this->last_burst.last_length;
} else {
// Partial burst is lost
this->count += virtualtimestamp - this->last_burst.last_load;
}
this->last_burst.handled = true;
}
this->disable_timestamp = virtualtimestamp;
this->enableflag = false;
}
void TogglingHandle::enable(timestamp_t timestamp)
{
if (this->enableflag) {
return;
}
this->disable_time += timestamp * this->datarate - this->disable_timestamp;
this->enableflag = true;
}
bool TogglingHandle::isEnabled() const
{
return this->enableflag;
}
double TogglingHandle::getTogglingRate() const
{
return this->toggling_rate;
}
double TogglingHandle::getDutyCycle() const
{
return this->duty_cycle;
}
uint64_t TogglingHandle::getWidth() const
{
return this->width;
}
void TogglingHandle::setWidth(const uint64_t width)
{
this->width = width;
}
uint64_t TogglingHandle::getDatarate() const
{
return this->datarate;
}
void TogglingHandle::setDataRate(const uint64_t datarate)
{
this->datarate = datarate;
}
void TogglingHandle::setTogglingRateAndDutyCycle(const double toggling_rate, const double duty_cycle, const TogglingRateIdlePattern idlepattern)
{
this->toggling_rate = toggling_rate;
this->duty_cycle = duty_cycle;
this->idlepattern = idlepattern;
}
uint64_t TogglingHandle::getCount() const
{
return this->count;
}
// Returns timestamp of last burst
timestamp_t TogglingHandle::get_lastburst_timestamp(bool relative_to_clock) const
{
timestamp_t lastburst = this->last_burst.last_load + this->last_burst.last_length;
if (relative_to_clock) {
auto remainder = lastburst % this->datarate;
if (remainder != 0) {
lastburst += this->datarate - remainder;
}
return lastburst / this->datarate;
}
return lastburst;
}
void TogglingHandle::incCountBurstLength(timestamp_t timestamp, uint64_t burstlength)
{
// Convert to bus timings
timestamp_t virtual_timestamp = timestamp * this->datarate;
assert(virtual_timestamp / this->datarate == timestamp); // No overflow
assert(
(this->last_burst && (virtual_timestamp >= (this->last_burst.last_length + this->last_burst.last_load)))
|| !this->last_burst
);
// Add last burst
if (!this->last_burst.handled) {
// Add last burst to count
this->count += this->last_burst.last_length;
}
// Store burst in last_length and last_load if enabled
if (this->enableflag) {
// Set last_length and last_load to new burst_length
this->last_burst = TogglingHandleLastBurst {
burstlength, // last_length
virtual_timestamp, // last_load
false // handled
};
} else {
// Clear last_burst
this->last_burst.handled = true;
}
}
void TogglingHandle::incCountBitLength(timestamp_t timestamp, uint64_t bitlength)
{
assert(bitlength % this->width == 0);
this->incCountBurstLength(timestamp, bitlength / this->width);
}
util::bus_stats_t TogglingHandle::get_stats(timestamp_t timestamp) const
{
// Convert to bus timings
timestamp_t virtual_timestamp = timestamp * this->datarate;
assert(virtual_timestamp / this->datarate == timestamp); // No overflow
util::bus_stats_t stats;
uint64_t count = this->count;
timestamp_t disable_time = this->disable_time;
if(this->enableflag) {
// Check if last burst is finished
if ((this->last_burst)
&& (virtual_timestamp < this->last_burst.last_length + this->last_burst.last_load)
) {
// last burst not finished
count += virtual_timestamp - this->last_burst.last_load;
} else if (this->last_burst) {
// last burst finished
count += this->last_burst.last_length;
}
} else {
disable_time += virtual_timestamp - this->disable_timestamp;
}
// Compute toggles
stats.ones = count * this->duty_cycle;
stats.zeroes = count * (1 - this->duty_cycle);
stats.ones_to_zeroes = count * this->toggling_rate / 2; // Round down
// Compute idle
switch (this->idlepattern) {
case TogglingRateIdlePattern::L:
stats.zeroes += virtual_timestamp - disable_time - count;
break;
case TogglingRateIdlePattern::H:
stats.ones += virtual_timestamp - disable_time - count;
break;
case TogglingRateIdlePattern::Invalid:
assert(false); // Fallback to Z
case TogglingRateIdlePattern::Z:
// Nothing to do in high impedance mode
break;
}
// Scale by bus width
stats.ones *= this->width;
stats.zeroes *= this->width;
stats.ones_to_zeroes *= this->width;
// Compute zeroes_to_ones and bit changes
stats.zeroes_to_ones = stats.ones_to_zeroes;
stats.bit_changes = stats.ones_to_zeroes + stats.zeroes_to_ones;
return stats;
}
void TogglingHandle::serialize(std::ostream &stream) const {
stream.write(reinterpret_cast(&width), sizeof(width));
stream.write(reinterpret_cast(&datarate), sizeof(datarate));
stream.write(reinterpret_cast(&toggling_rate), sizeof(toggling_rate));
stream.write(reinterpret_cast(&duty_cycle), sizeof(duty_cycle));
last_burst.serialize(stream);
stream.write(reinterpret_cast(&enableflag), sizeof(enableflag));
stream.write(reinterpret_cast(&count), sizeof(count));
stream.write(reinterpret_cast(&disable_timestamp), sizeof(disable_timestamp));
stream.write(reinterpret_cast(&disable_time), sizeof(disable_time));
stream.write(reinterpret_cast(&idlepattern), sizeof(idlepattern));
}
void TogglingHandle::deserialize(std::istream &stream) {
stream.read(reinterpret_cast(&width), sizeof(width));
stream.read(reinterpret_cast(&datarate), sizeof(datarate));
stream.read(reinterpret_cast(&toggling_rate), sizeof(toggling_rate));
stream.read(reinterpret_cast(&duty_cycle), sizeof(duty_cycle));
last_burst.deserialize(stream);
stream.read(reinterpret_cast(&enableflag), sizeof(enableflag));
stream.read(reinterpret_cast(&count), sizeof(count));
stream.read(reinterpret_cast(&disable_timestamp), sizeof(disable_timestamp));
stream.read(reinterpret_cast(&disable_time), sizeof(disable_time));
stream.read(reinterpret_cast(&idlepattern), sizeof(idlepattern));
}
} // namespace DRAMPower
================================================
FILE: src/DRAMPower/DRAMPower/dram/Interface.h
================================================
#ifndef DRAMPOWER_DDR_INTERFACE_H
#define DRAMPOWER_DDR_INTERFACE_H
#pragma once
#include
#include
#include
#include
#include
#include
#include
namespace DRAMPower {
class TogglingHandle : public util::Serialize, public util::Deserialize
{
struct TogglingHandleLastBurst : public util::Serialize, public util::Deserialize {
uint64_t last_length = 0;
timestamp_t last_load = 0;
bool handled = true;
TogglingHandleLastBurst() = default;
TogglingHandleLastBurst(uint64_t last_length, timestamp_t last_load, bool handled)
: last_length(last_length), last_load(last_load), handled(handled) {}
operator bool() const { return !this->handled; }
void serialize(std::ostream &stream) const override;
void deserialize(std::istream &stream) override;
};
private:
uint64_t width = 0;
uint64_t datarate = 1;
double toggling_rate = 0; // [0, 1] allowed
double duty_cycle = 0.0; // [0, 1] allowed
TogglingHandleLastBurst last_burst;
bool enableflag = false; // default disabled if default constructor is used
uint64_t count = 0;
timestamp_t disable_timestamp = 0;
timestamp_t disable_time = 0;
DRAMUtils::Config::TogglingRateIdlePattern idlepattern = DRAMUtils::Config::TogglingRateIdlePattern::Z;
public:
TogglingHandle(const uint64_t width, const uint64_t datarate, const double toggling_rate, const double duty_cycle, const bool enabled = true);
TogglingHandle(const uint64_t width, const uint64_t datarate, const double toggling_rate, const double duty_cycle, DRAMUtils::Config::TogglingRateIdlePattern idlepattern, const bool enabled = true);
TogglingHandle() = default;
public:
// Getters and Setters
double getTogglingRate() const;
double getDutyCycle() const;
bool isEnabled() const;
uint64_t getWidth() const;
uint64_t getDatarate() const;
timestamp_t get_lastburst_timestamp(bool relative_to_clock = true) const;
void setTogglingRateAndDutyCycle(const double toggling_rate, const double duty_cycle, const DRAMUtils::Config::TogglingRateIdlePattern idlepattern);
void disable(timestamp_t timestamp);
void enable(timestamp_t timestamp);
void setWidth(const uint64_t width);
void setDataRate(const uint64_t datarate);
uint64_t getCount() const;
public:
void incCountBurstLength(timestamp_t timestamp, uint64_t burstlength);
void incCountBitLength(timestamp_t timestamp, uint64_t bitlength);
util::bus_stats_t get_stats(timestamp_t timestamp) const;
// Overrides
void serialize(std::ostream &stream) const override;
void deserialize(std::istream &stream) override;
};
struct interface_stats_t
{
util::bus_stats_t command_bus;
util::bus_stats_t read_bus;
util::bus_stats_t write_bus;
};
} // namespace DRAMPower
#endif /* DRAMPOWER_DDR_INTERFACE_H */
================================================
FILE: src/DRAMPower/DRAMPower/dram/Rank.cpp
================================================
#include "Rank.h"
#include
namespace DRAMPower {
Rank::Rank(std::size_t numBanks)
: banks(numBanks)
{};
bool Rank::isActive(timestamp_t timestamp) {
if ( timestamp < this->endRefreshTime ) {
std::cout << "[WARN] Rank::isActive() -> timestamp (" << timestamp <<") < " << "endRefreshTime (" << this->endRefreshTime << ")" << std::endl;
}
return countActiveBanks() > 0 || timestamp < this->endRefreshTime;
}
std::size_t Rank::countActiveBanks() const {
return (unsigned)std::count_if(banks.begin(), banks.end(),
[](const auto& bank) {
return (bank.bankState == Bank::BankState::BANK_ACTIVE);
});
}
void Rank::serialize(std::ostream& stream) const {
stream.write(reinterpret_cast(&memState), sizeof(memState));
stream.write(reinterpret_cast(&endRefreshTime), sizeof(endRefreshTime));
commandCounter.serialize(stream);
stream.write(reinterpret_cast(&counter.selfRefresh), sizeof(counter.selfRefresh));
stream.write(reinterpret_cast(&counter.deepSleepMode), sizeof(counter.deepSleepMode));
stream.write(reinterpret_cast(&endRefreshTime), sizeof(endRefreshTime));
cycles.pre.serialize(stream);
cycles.act.serialize(stream);
cycles.ref.serialize(stream);
cycles.sref.serialize(stream);
cycles.powerDownAct.serialize(stream);
cycles.powerDownPre.serialize(stream);
cycles.deepSleepMode.serialize(stream);
for (const auto& bank : banks) {
bank.serialize(stream);
}
};
void Rank::deserialize(std::istream& stream) {
stream.read(reinterpret_cast(&memState), sizeof(memState));
stream.read(reinterpret_cast(&endRefreshTime), sizeof(endRefreshTime));
commandCounter.deserialize(stream);
stream.read(reinterpret_cast(&counter.selfRefresh), sizeof(counter.selfRefresh));
stream.read(reinterpret_cast(&counter.deepSleepMode), sizeof(counter.deepSleepMode));
stream.read(reinterpret_cast(&endRefreshTime), sizeof(endRefreshTime));
cycles.pre.deserialize(stream);
cycles.act.deserialize(stream);
cycles.ref.deserialize(stream);
cycles.sref.deserialize(stream);
cycles.powerDownAct.deserialize(stream);
cycles.powerDownPre.deserialize(stream);
cycles.deepSleepMode.deserialize(stream);
for (auto & bank : banks) {
bank.deserialize(stream);
}
};
void RankInterface::serialize(std::ostream& stream) const {
stream.write(reinterpret_cast(&seamlessPrePostambleCounter_read), sizeof(seamlessPrePostambleCounter_read));
stream.write(reinterpret_cast(&seamlessPrePostambleCounter_write), sizeof(seamlessPrePostambleCounter_write));
stream.write(reinterpret_cast(&mergedPrePostambleCounter_read), sizeof(mergedPrePostambleCounter_read));
stream.write(reinterpret_cast(&mergedPrePostambleCounter_write), sizeof(mergedPrePostambleCounter_write));
stream.write(reinterpret_cast(&mergedPrePostambleTime_read), sizeof(mergedPrePostambleTime_read));
stream.write(reinterpret_cast(&mergedPrePostambleTime_write), sizeof(mergedPrePostambleTime_write));
stream.write(reinterpret_cast(&lastReadEnd), sizeof(lastReadEnd));
stream.write(reinterpret_cast(&lastWriteEnd), sizeof(lastWriteEnd));
}
void RankInterface::deserialize(std::istream& stream) {
stream.read(reinterpret_cast(&seamlessPrePostambleCounter_read), sizeof(seamlessPrePostambleCounter_read));
stream.read(reinterpret_cast(&seamlessPrePostambleCounter_write), sizeof(seamlessPrePostambleCounter_write));
stream.read(reinterpret_cast(&mergedPrePostambleCounter_read), sizeof(mergedPrePostambleCounter_read));
stream.read(reinterpret_cast(&mergedPrePostambleCounter_write), sizeof(mergedPrePostambleCounter_write));
stream.read(reinterpret_cast(&mergedPrePostambleTime_read), sizeof(mergedPrePostambleTime_read));
stream.read(reinterpret_cast(&mergedPrePostambleTime_write), sizeof(mergedPrePostambleTime_write));
stream.read(reinterpret_cast(&lastReadEnd), sizeof(lastReadEnd));
stream.read(reinterpret_cast(&lastWriteEnd), sizeof(lastWriteEnd));
}
} // namespace DRAMPower
================================================
FILE: src/DRAMPower/DRAMPower/dram/Rank.h
================================================
#ifndef DRAMPOWER_DDR_RANK_H
#define DRAMPOWER_DDR_RANK_H
#include
#include
#include
#include
#include
#include
#include
namespace DRAMPower {
// Power-Down and Self-refresh related memory states
enum class MemState {
NOT_IN_PD = 0,
PDN_ACT,
PDN_PRE,
SREF,
DSM,
};
struct Rank : public util::Serialize, public util::Deserialize {
// Type aliases
using commandCounter_t = util::CommandCounter;
public:
// Variables
MemState memState = MemState::NOT_IN_PD;
commandCounter_t commandCounter;
struct {
interval_t pre; // useful ???
interval_t act;
interval_t ref;
interval_t sref;
interval_t powerDownAct;
interval_t powerDownPre;
interval_t deepSleepMode;
} cycles;
struct {
uint64_t selfRefresh = 0;
uint64_t deepSleepMode = 0;
} counter = { 0 };
timestamp_t endRefreshTime = 0;
std::vector banks;
public:
// Constructors
Rank(std::size_t numBanks);
// Functions
public:
bool isActive(timestamp_t timestamp);
std::size_t countActiveBanks() const;
// Overrides
void serialize(std::ostream& stream) const override;
void deserialize(std::istream& stream) override;
};
struct RankInterface : public util::Serialize, public util::Deserialize {
uint64_t seamlessPrePostambleCounter_read = 0;
uint64_t seamlessPrePostambleCounter_write = 0;
uint64_t mergedPrePostambleCounter_read = 0;
uint64_t mergedPrePostambleCounter_write = 0;
timestamp_t mergedPrePostambleTime_read = 0;
timestamp_t mergedPrePostambleTime_write = 0;
timestamp_t lastReadEnd = 0;
timestamp_t lastWriteEnd = 0;
// Overrides
void serialize(std::ostream& stream) const override;
void deserialize(std::istream& stream) override;
};
} // namespace DRAMPower
#endif /* DRAMPOWER_DDR_RANK_H */
================================================
FILE: src/DRAMPower/DRAMPower/dram/dram_base.h
================================================
#ifndef DRAMPOWER_DRAM_DRAM_BASE_H
#define DRAMPOWER_DRAM_DRAM_BASE_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace DRAMPower {
using namespace DRAMUtils::Config;
template
class dram_base : public util::Serialize, public util::Deserialize
{
// Public type definitions
public:
using commandEnum_t = CommandEnum;
using commandCount_t = std::vector;
// ExtensionManager
using extension_manager_t = util::extension_manager::ExtensionManager<
extensions::Base
>;
// Public constructors and assignment operators
public:
dram_base(const dram_base&) = default; // copy constructor
dram_base& operator=(const dram_base&) = default; // copy assignment operator
dram_base(dram_base&&) = default; // Move constructor
dram_base& operator=(dram_base&&) = default; // Move assignment operator
virtual ~dram_base() = 0;
// Protected constructors
protected:
dram_base() = default;
// Public member functions
public:
// ExtensionManager
extension_manager_t& getExtensionManager() { return m_extensionManager; }
const extension_manager_t& getExtensionManager() const { return m_extensionManager; }
void doCoreCommand(const Command& command) {
doCoreCommandImpl(command);
}
void doInterfaceCommand(const Command& command) {
doInterfaceCommandImpl(command);
}
void doCommand(const Command& command) {
doCoreCommandImpl(command);
doInterfaceCommandImpl(command);
}
// deprecated
void doCoreInterfaceCommand(const Command& command) {
doCommand(command);
}
timestamp_t getLastCommandTime() const {
return getLastCommandTime_impl();
}
double getTotalEnergy(timestamp_t timestamp) {
return calcCoreEnergy(timestamp).total() + calcInterfaceEnergy(timestamp).total();
};
SimulationStats getStats() {
return getWindowStats(getLastCommandTime());
}
void serialize(std::ostream& stream) const override {
// Serialize the extension manager
m_extensionManager.serialize(stream);
serialize_impl(stream);
}
void deserialize(std::istream& stream) override {
// Deserialize the extension manager
m_extensionManager.deserialize(stream);
deserialize_impl(stream);
}
// Public virtual methods
public:
virtual energy_t calcCoreEnergyStats(const SimulationStats& stats) const = 0;
energy_t calcCoreEnergy(timestamp_t timestamp) {
return calcCoreEnergyStats(getWindowStats(timestamp));
}
virtual interface_energy_info_t calcInterfaceEnergyStats(const SimulationStats& stats) const = 0;
interface_energy_info_t calcInterfaceEnergy(timestamp_t timestamp) {
return calcInterfaceEnergyStats(getWindowStats(timestamp));
}
virtual SimulationStats getWindowStats(timestamp_t timestamp) = 0;
virtual util::CLIArchitectureConfig getCLIArchitectureConfig() = 0;
virtual bool isSerializable() const = 0;
// Private virtual methods
private:
virtual void doCoreCommandImpl(const Command& command) = 0;
virtual void doInterfaceCommandImpl(const Command& command) = 0;
virtual timestamp_t getLastCommandTime_impl() const = 0;
virtual void serialize_impl(std::ostream& stream) const = 0;
virtual void deserialize_impl(std::istream& stream) = 0;
// Private member variables
private:
extension_manager_t m_extensionManager;
};
template
dram_base::~dram_base() = default;
}
#endif /* DRAMPOWER_DDR_DRAM_BASE_H */
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpec.h
================================================
/*
* Copyright (c) 2015-2020, University of Kaiserslautern
* Copyright (c) 2012-2021, Fraunhofer IESE
* 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:
* Janik Schlemminger
* Matthias Jung
* Lukas Steiner
* Luiza Correa
*/
#ifndef DRAMPOWER_MEMSPEC_MEMSPEC_H
#define DRAMPOWER_MEMSPEC_MEMSPEC_H
#include
#include
#include
#include
#include
#include
namespace DRAMPower {
template
class MemSpec
{
T rawmemspec;
public:
uint64_t numberOfBanks;
uint64_t numberOfRows;
uint64_t numberOfColumns;
uint64_t numberOfDevices; // Number of devices per rank
uint64_t burstLength;
uint64_t dataRate;
uint64_t bitWidth;
/* MEMSPEC specific parameters
unsigned numberOfBankGroups;
unsigned numberOfDevicesOnDIMM;
unsigned numberOfRanks;
unsigned banksPerRank;
unsigned groupsPerRank;
unsigned banksPerGroup;
unsigned numberOfChannels;
*/
std::string memoryId;
std::string memoryType;
uint64_t prechargeOffsetRD;
uint64_t prechargeOffsetWR;
MemSpec() = delete;
virtual ~MemSpec() = default;
// MemSpec() = default;
MemSpec(const T &memspec) : rawmemspec(memspec)
{
numberOfBanks = memspec.memarchitecturespec.nbrOfBanks;
numberOfRows = memspec.memarchitecturespec.nbrOfRows;
numberOfColumns = memspec.memarchitecturespec.nbrOfColumns;
numberOfDevices = memspec.memarchitecturespec.nbrOfDevices;
if (numberOfDevices < 1)
{
numberOfDevices = 1;
}
burstLength = memspec.memarchitecturespec.burstLength;
dataRate = memspec.memarchitecturespec.dataRate;
bitWidth = memspec.memarchitecturespec.width;
memoryId = memspec.memoryId;
memoryType = memspec.id;
}
};
} // namespace DRAMPower
#endif /* DRAMPOWER_MEMSPEC_MEMSPEC_H */
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecDDR4.cpp
================================================
/*
* Copyright (c) 2019, University of Kaiserslautern
* Copyright (c) 2012-2021, Fraunhofer IESE
* 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:
* Lukas Steiner
* Luiza Correa
*/
#include "MemSpecDDR4.h"
using namespace DRAMPower;
MemSpecDDR4::MemSpecDDR4(const DRAMUtils::MemSpec::MemSpecDDR4 &memspec)
: MemSpec(memspec)
{
numberOfBankGroups = memspec.memarchitecturespec.nbrOfBankGroups;
numberOfRanks = memspec.memarchitecturespec.nbrOfRanks;
memTimingSpec.tCK = memspec.memtimingspec.tCK;
memTimingSpec.tRAS = memspec.memtimingspec.RAS;
memTimingSpec.tRCD = memspec.memtimingspec.RCD;
memTimingSpec.tRTP = memspec.memtimingspec.RTP;
memTimingSpec.tWL = memspec.memtimingspec.WL;
memTimingSpec.tWR = memspec.memtimingspec.WR;
memTimingSpec.tRP = memspec.memtimingspec.RP;
memTimingSpec.tAL = memspec.memtimingspec.AL;
auto VDD = VoltageDomain::VDD;
auto VPP = VoltageDomain::VPP;
memPowerSpec.push_back(MemPowerSpec());
memPowerSpec[VDD].vXX = memspec.mempowerspec.vdd;
memPowerSpec[VDD].iXX0 = memspec.mempowerspec.idd0;
memPowerSpec[VDD].iXX2N = memspec.mempowerspec.idd2n;
memPowerSpec[VDD].iXX3N = memspec.mempowerspec.idd3n;
memPowerSpec[VDD].iXX4R = memspec.mempowerspec.idd4r;
memPowerSpec[VDD].iXX4W = memspec.mempowerspec.idd4w;
memPowerSpec[VDD].iXX6N = memspec.mempowerspec.idd6n;
memPowerSpec[VDD].iXX2P = memspec.mempowerspec.idd2p;
memPowerSpec[VDD].iXX3P = memspec.mempowerspec.idd3p;
memPowerSpec.push_back(MemPowerSpec());
memPowerSpec[VPP].vXX = memspec.mempowerspec.vpp;
memPowerSpec[VPP].iXX0 = memspec.mempowerspec.ipp0;
memPowerSpec[VPP].iXX2N = memspec.mempowerspec.ipp2n;
memPowerSpec[VPP].iXX3N = memspec.mempowerspec.ipp3n;
memPowerSpec[VPP].iXX4R = memspec.mempowerspec.ipp4r;
memPowerSpec[VPP].iXX4W = memspec.mempowerspec.ipp4w;
memPowerSpec[VPP].iXX6N = memspec.mempowerspec.ipp6n;
memPowerSpec[VPP].iXX2P = memspec.mempowerspec.ipp2p;
memPowerSpec[VPP].iXX3P = memspec.mempowerspec.ipp3p;
vddq = memspec.mempowerspec.vddq;
if (DRAMUtils::MemSpec::RefModeTypeDDR4::REF_MODE_2 == memspec.memarchitecturespec.RefMode) {
memPowerSpec[VDD].iXX5X = memspec.mempowerspec.idd5F2;
memPowerSpec[VPP].iXX5X = memspec.mempowerspec.ipp5F2;
memTimingSpec.tRFC = memspec.memtimingspec.RFC2;
} else if (DRAMUtils::MemSpec::RefModeTypeDDR4::REF_MODE_4 == memspec.memarchitecturespec.RefMode) {
memPowerSpec[VDD].iXX5X = memspec.mempowerspec.idd5F4;
memPowerSpec[VPP].iXX5X = memspec.mempowerspec.ipp5F4;
memTimingSpec.tRFC = memspec.memtimingspec.RFC4;
} else {
// RefModeTypeDDR4::REF_MODE_1 || RefModeTypeDDR4::INVALID
memPowerSpec[VDD].iXX5X = memspec.mempowerspec.idd5B;
memPowerSpec[VPP].iXX5X = memspec.mempowerspec.ipp5B;
memTimingSpec.tRFC = memspec.memtimingspec.RFC1;
}
memPowerSpec[VDD].iBeta = memspec.mempowerspec.iBeta_vdd.value_or(memspec.mempowerspec.idd0);
memPowerSpec[VPP].iBeta = memspec.mempowerspec.iBeta_vpp.value_or(memspec.mempowerspec.ipp0);
if(memspec.bankwisespec.has_value())
{
bwParams.bwPowerFactRho = memspec.bankwisespec.value().factRho.value_or(1);
}
else
{
bwParams.bwPowerFactRho = 1;
}
memTimingSpec.tBurst = burstLength/dataRate;
prechargeOffsetRD = memTimingSpec.tAL + memTimingSpec.tRTP;
prechargeOffsetWR = memTimingSpec.tBurst + memTimingSpec.tWL + memTimingSpec.tWR;
parseImpedanceSpec(memspec);
parsePrePostamble(memspec);
}
void MemSpecDDR4::parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecDDR4 &memspec) {
memImpedanceSpec = memspec.memimpedancespec;
}
void MemSpecDDR4::parsePrePostamble(const DRAMUtils::MemSpec::MemSpecDDR4 &memspec)
{
prePostamble.read_zeroes = memspec.prepostamble.read_zeroes;
prePostamble.write_zeroes = memspec.prepostamble.write_zeroes;
prePostamble.read_ones = memspec.prepostamble.read_ones;
prePostamble.write_ones = memspec.prepostamble.write_ones;
prePostamble.read_zeroes_to_ones = memspec.prepostamble.read_zeroes_to_ones;
prePostamble.write_zeroes_to_ones = memspec.prepostamble.write_zeroes_to_ones;
prePostamble.write_ones_to_zeroes = memspec.prepostamble.write_ones_to_zeroes;
prePostamble.read_ones_to_zeroes = memspec.prepostamble.read_ones_to_zeroes;
prePostamble.readMinTccd = memspec.prepostamble.readMinTccd;
prePostamble.writeMinTccd = memspec.prepostamble.writeMinTccd;;
}
MemSpecDDR4 MemSpecDDR4::from_memspec(const DRAMUtils::MemSpec::MemSpecVariant& memSpec)
{
return std::get(memSpec.getVariant());
}
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecDDR4.h
================================================
/*
* Copyright (c) 2019, University of Kaiserslautern
* Copyright (c) 2012-2021, Fraunhofer IESE
* 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:
* Lukas Steiner
* Luiza Correa
*/
#ifndef DRAMPOWER_MEMSPEC_MEMSPECDDR4_H
#define DRAMPOWER_MEMSPEC_MEMSPECDDR4_H
#include "MemSpec.h"
#include
#include
namespace DRAMPower {
class MemSpecDDR4 final : public MemSpec
{
public:
using MemImpedanceSpec = DRAMUtils::MemSpec::MemImpedanceSpecTypeDDR4;
enum VoltageDomain {
VDD = 0,
VPP = 1,
};
public:
MemSpecDDR4() = delete;
MemSpecDDR4(const DRAMUtils::MemSpec::MemSpecDDR4 &memspec);
MemSpecDDR4(json_t &data) = delete;
MemSpecDDR4(const json_t &data) = delete;
// Copy constructor and assignment operator
MemSpecDDR4(const MemSpecDDR4&) = default;
MemSpecDDR4& operator=(const MemSpecDDR4&) = default;
// Move constructor and assignment operator
MemSpecDDR4(MemSpecDDR4&&) = default;
MemSpecDDR4& operator=(MemSpecDDR4&&) = default;
uint64_t numberOfBankGroups;
uint64_t numberOfRanks;
double vddq;
// Memspec Variables:
struct MemTimingSpec
{
double fck;
double tCK;
uint64_t tRAS;
uint64_t tRCD;
uint64_t tRL;
uint64_t tRTP;
uint64_t tWL;
uint64_t tWR;
uint64_t tRFC;
uint64_t tRP;
uint64_t tAL;
uint64_t tBurst;
};
// Currents and Voltages:
struct MemPowerSpec
{
double iXX0;
double iXX2N;
double iXX3N;
double iXX4R;
double iXX4W;
double iXX5X;
double iXX6N;
double vXX;
double iXX2P;
double iXX3P;
double iBeta;
};
struct BankWiseParams
{
// ACT Standby power factor
double bwPowerFactRho;
};
// Pre and Postamble
// Total number of zero cycles relative to tCK (one cycle = tCK) for example, if tCK = 1ns, and read_zeroes = 2.5, then the total time is 2.5ns
struct PrePostamble
{
// Total number of zero/one cycles per DQs differential pair
// relative to tCK (one cycle = tCK)
// for example, if tCK = 1ns, and read_zeroes = 2.5, then the total time is 2.5ns
double read_zeroes;
double write_zeroes;
double read_ones;
double write_ones;
// Total number of zero to one and one to zero transitions per DQs differential pair
uint64_t read_zeroes_to_ones;
uint64_t write_zeroes_to_ones;
uint64_t write_ones_to_zeroes;
uint64_t read_ones_to_zeroes;
// Minimum time interval between two consecutive read/write commands to prevent merging or seamless transition.
uint64_t readMinTccd;
uint64_t writeMinTccd;
};
uint64_t refreshMode;
MemTimingSpec memTimingSpec;
std::vector memPowerSpec;
MemImpedanceSpec memImpedanceSpec;
PrePostamble prePostamble;
BankWiseParams bwParams;
private:
void parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecDDR4 &memspec);
void parsePrePostamble(const DRAMUtils::MemSpec::MemSpecDDR4 &memspec);
public:
static MemSpecDDR4 from_memspec(const DRAMUtils::MemSpec::MemSpecVariant&);
};
}
#endif /* DRAMPOWER_MEMSPEC_MEMSPECDDR4_H */
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecDDR5.cpp
================================================
#include "MemSpecDDR5.h"
using namespace DRAMPower;
MemSpecDDR5::MemSpecDDR5(const DRAMUtils::MemSpec::MemSpecDDR5 &memspec)
: MemSpec(memspec)
{
numberOfBankGroups = memspec.memarchitecturespec.nbrOfBankGroups;
numberOfRanks = memspec.memarchitecturespec.nbrOfRanks;
banksPerGroup = numberOfBanks / numberOfBankGroups;
memTimingSpec.tCK = memspec.memtimingspec.tCK;
memTimingSpec.tRAS = memspec.memtimingspec.RAS;
memTimingSpec.tRCD = memspec.memtimingspec.RCD;
memTimingSpec.tRTP = memspec.memtimingspec.RTP;
memTimingSpec.tWL = memspec.memtimingspec.WL;
memTimingSpec.tWR = memspec.memtimingspec.WR;
memTimingSpec.tRP = memspec.memtimingspec.RP;
memTimingSpec.tRFCsb = memspec.memtimingspec.RFCsb_slr;
auto VDD = VoltageDomain::VDD;
auto VPP = VoltageDomain::VPP;
memPowerSpec.push_back(MemPowerSpec());
memPowerSpec[VDD].vXX = memspec.mempowerspec.vdd;
memPowerSpec[VDD].iXX0 = memspec.mempowerspec.idd0;
memPowerSpec[VDD].iXX2N = memspec.mempowerspec.idd2n;
memPowerSpec[VDD].iXX3N = memspec.mempowerspec.idd3n;
memPowerSpec[VDD].iXX4R = memspec.mempowerspec.idd4r;
memPowerSpec[VDD].iXX4W = memspec.mempowerspec.idd4w;
memPowerSpec[VDD].iXX5C = memspec.mempowerspec.idd5c;
memPowerSpec[VDD].iXX6N = memspec.mempowerspec.idd6n;
memPowerSpec[VDD].iXX2P = memspec.mempowerspec.idd2p;
memPowerSpec[VDD].iXX3P = memspec.mempowerspec.idd3p;
memPowerSpec.push_back(MemPowerSpec());
memPowerSpec[VPP].vXX = memspec.mempowerspec.vpp;
memPowerSpec[VPP].iXX0 = memspec.mempowerspec.ipp0;
memPowerSpec[VPP].iXX2N = memspec.mempowerspec.ipp2n;
memPowerSpec[VPP].iXX3N = memspec.mempowerspec.ipp3n;
memPowerSpec[VPP].iXX4R = memspec.mempowerspec.ipp4r;
memPowerSpec[VPP].iXX4W = memspec.mempowerspec.ipp4w;
memPowerSpec[VPP].iXX5C = memspec.mempowerspec.ipp5c;
memPowerSpec[VPP].iXX6N = memspec.mempowerspec.ipp6n;
memPowerSpec[VPP].iXX2P = memspec.mempowerspec.ipp2p;
memPowerSpec[VPP].iXX3P = memspec.mempowerspec.ipp3p;
vddq = memspec.mempowerspec.vddq;
if (DRAMUtils::MemSpec::RefModeTypeDDR5::REF_MODE_2 == memspec.memarchitecturespec.RefMode) {
memPowerSpec[VDD].iXX5X = memspec.mempowerspec.idd5f;
memPowerSpec[VPP].iXX5X = memspec.mempowerspec.ipp5f;
memTimingSpec.tRFC = memspec.memtimingspec.RFC2_slr;
} else {
// RefModeTypeDDR5::REF_MODE_1 || RefModeTypeDDR5::INVALID
memPowerSpec[VDD].iXX5X = memspec.mempowerspec.idd5b;
memPowerSpec[VPP].iXX5X = memspec.mempowerspec.ipp5b;
memTimingSpec.tRFC = memspec.memtimingspec.RFC1_slr;
}
memPowerSpec[VDD].iBeta = memspec.mempowerspec.iBeta_vdd.value_or(memspec.mempowerspec.idd0);
memPowerSpec[VPP].iBeta = memspec.mempowerspec.iBeta_vpp.value_or(memspec.mempowerspec.ipp0);
if (memspec.bankwisespec.has_value())
{
bwParams.bwPowerFactRho = memspec.bankwisespec.value().factRho.value_or(1);
}
else
{
bwParams.bwPowerFactRho = 1;
}
memTimingSpec.tBurst = burstLength/dataRate;
prechargeOffsetRD = memTimingSpec.tRTP;
prechargeOffsetWR = memTimingSpec.tBurst + memTimingSpec.tWL + memTimingSpec.tWR;
parseImpedanceSpec(memspec);
parseDataRateSpec(memspec);
}
void MemSpecDDR5::parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecDDR5 &memspec) {
memImpedanceSpec = memspec.memimpedancespec;
}
void MemSpecDDR5::parseDataRateSpec(const DRAMUtils::MemSpec::MemSpecDDR5 &memspec) {
if (!memspec.dataratespec.has_value()) {
dataRateSpec = {2, 2, 2};
return;
}
dataRateSpec.commandBusRate = memspec.dataratespec.value().ca_bus_rate;
dataRateSpec.dataBusRate = memspec.dataratespec.value().dq_bus_rate;
dataRateSpec.dqsBusRate = memspec.dataratespec.value().dqs_bus_rate;
}
MemSpecDDR5 MemSpecDDR5::from_memspec(const DRAMUtils::MemSpec::MemSpecVariant& memSpec)
{
return std::get(memSpec.getVariant());
}
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecDDR5.h
================================================
#ifndef DRAMPOWER_MEMSPEC_MEMSPECDDR5_H
#define DRAMPOWER_MEMSPEC_MEMSPECDDR5_H
#include "MemSpec.h"
#include
namespace DRAMPower {
class MemSpecDDR5 final : public MemSpec {
public:
using MemImpedanceSpec = DRAMUtils::MemSpec::MemImpedanceSpecTypeDDR5;
enum VoltageDomain {
VDD = 0,
VPP = 1,
};
public:
MemSpecDDR5() = delete;
MemSpecDDR5(const DRAMUtils::MemSpec::MemSpecDDR5 &memspec);
MemSpecDDR5(json_t &data) = delete;
MemSpecDDR5(const json_t &data) = delete;
// Copy constructor and assignment operator
MemSpecDDR5(const MemSpecDDR5&) = default;
MemSpecDDR5& operator=(const MemSpecDDR5&) = default;
// Move constructor and assignment operator
MemSpecDDR5(MemSpecDDR5&&) = default;
MemSpecDDR5& operator=(MemSpecDDR5&&) = default;
uint64_t numberOfBankGroups;
uint64_t banksPerGroup;
uint64_t numberOfRanks;
double vddq;
// Memspec Variables:
struct MemTimingSpec
{
double fck;
double tCK;
uint64_t tRAS;
uint64_t tRCD;
uint64_t tRL;
uint64_t tRTP;
uint64_t tWL;
uint64_t tWR;
uint64_t tRFC;
uint64_t tRFCsb;
uint64_t tRP;
uint64_t tBurst;
};
// Currents and Voltages:
struct MemPowerSpec
{
double vXX;
double iXX0;
double iXX2N;
double iXX3N;
double iXX2P;
double iXX3P;
double iXX4R;
double iXX4W;
double iXX5X;
double iXX5C;
double iXX6N;
double iBeta;
};
struct DataRateSpec {
uint64_t commandBusRate;
uint64_t dataBusRate;
uint64_t dqsBusRate;
};
struct BankWiseParams
{
// ACT Standby power factor
double bwPowerFactRho;
};
MemTimingSpec memTimingSpec;
MemImpedanceSpec memImpedanceSpec;
DataRateSpec dataRateSpec;
std::vector memPowerSpec;
BankWiseParams bwParams;
private:
void parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecDDR5 &memspec);
void parseDataRateSpec(const DRAMUtils::MemSpec::MemSpecDDR5 &memspec);
public:
static MemSpecDDR5 from_memspec(const DRAMUtils::MemSpec::MemSpecVariant&);
};
}
#endif /* DRAMPOWER_MEMSPEC_MEMSPECDDR5_H */
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecLPDDR4.cpp
================================================
#include "MemSpecLPDDR4.h"
using namespace DRAMPower;
MemSpecLPDDR4::MemSpecLPDDR4(const DRAMUtils::MemSpec::MemSpecLPDDR4 &memspec)
: MemSpec(memspec), memImpedanceSpec{}
{
numberOfBankGroups = memspec.memarchitecturespec.nbrOfBankGroups;
numberOfRanks = memspec.memarchitecturespec.nbrOfRanks;
banksPerGroup = numberOfBanks / numberOfBankGroups;
memTimingSpec.tCK = memspec.memtimingspec.tCK;
memTimingSpec.tRAS = memspec.memtimingspec.RAS;
memTimingSpec.tRCD = memspec.memtimingspec.RCD;
memTimingSpec.tRL = memspec.memtimingspec.RL;
memTimingSpec.tRTP = memspec.memtimingspec.RTP;
memTimingSpec.tWL = memspec.memtimingspec.WL;
memTimingSpec.tWR = memspec.memtimingspec.WR;
memTimingSpec.tRP = memspec.memtimingspec.RPpb;
memTimingSpec.tRFCPB = memspec.memtimingspec.RFCpb;
memTimingSpec.tRFC = memspec.memtimingspec.RFCab;
memTimingSpec.tREFI = memspec.memtimingspec.REFI;
auto VDD1 = VoltageDomain::VDD1;
auto VDD2 = VoltageDomain::VDD2;
memPowerSpec.push_back(MemPowerSpec());
memPowerSpec.push_back(MemPowerSpec());
memPowerSpec[VDD1].vDDX = memspec.mempowerspec.vdd1;
memPowerSpec[VDD1].iDD0X = memspec.mempowerspec.idd01;
memPowerSpec[VDD1].iDD2NX = memspec.mempowerspec.idd2n1;
memPowerSpec[VDD1].iDD3NX = memspec.mempowerspec.idd3n1;
memPowerSpec[VDD1].iDD4RX = memspec.mempowerspec.idd4r1;
memPowerSpec[VDD1].iDD4WX = memspec.mempowerspec.idd4w1;
memPowerSpec[VDD1].iDD5X = memspec.mempowerspec.idd51;
memPowerSpec[VDD1].iDD5PBX = memspec.mempowerspec.idd5pb1;
memPowerSpec[VDD1].iDD6X = memspec.mempowerspec.idd61;
memPowerSpec[VDD1].iDD2PX = memspec.mempowerspec.idd2p1;
memPowerSpec[VDD1].iDD3PX = memspec.mempowerspec.idd3p1;
memPowerSpec[VDD2].vDDX = memspec.mempowerspec.vdd2;
memPowerSpec[VDD2].iDD0X = memspec.mempowerspec.idd02;
memPowerSpec[VDD2].iDD2NX = memspec.mempowerspec.idd2n2;
memPowerSpec[VDD2].iDD3NX = memspec.mempowerspec.idd3n2;
memPowerSpec[VDD2].iDD4RX = memspec.mempowerspec.idd4r2;
memPowerSpec[VDD2].iDD4WX = memspec.mempowerspec.idd4w2;
memPowerSpec[VDD2].iDD5X = memspec.mempowerspec.idd52;
memPowerSpec[VDD2].iDD5PBX = memspec.mempowerspec.idd5pb2;
memPowerSpec[VDD2].iDD6X = memspec.mempowerspec.idd62;
memPowerSpec[VDD2].iDD2PX = memspec.mempowerspec.idd2p2;
memPowerSpec[VDD2].iDD3PX = memspec.mempowerspec.idd3p2;
vddq = memspec.mempowerspec.vddq;
memPowerSpec[VDD1].iBeta = memspec.mempowerspec.iBeta_vdd1.value_or(memspec.mempowerspec.idd01);
memPowerSpec[VDD2].iBeta = memspec.mempowerspec.iBeta_vdd2.value_or(memspec.mempowerspec.idd02);
if(memspec.bankwisespec.has_value())
{
bwParams.bwPowerFactRho = memspec.bankwisespec.value().factRho.value_or(1);
bwParams.bwPowerFactSigma = memspec.bankwisespec.value().factSigma.value_or(1);
bwParams.flgPASR = memspec.bankwisespec.value().hasPASR.value_or(false);
if (memspec.bankwisespec.value().pasrMode.has_value())
{
if(memspec.bankwisespec.value().pasrMode.value() == DRAMUtils::MemSpec::pasrModesType::Invalid)
{
// pasrMode invalid
bwParams.pasrMode = 0;
}
else
{
// pasrMode valid
bwParams.pasrMode = static_cast(memspec.bankwisespec.value().pasrMode.value());
}
}
else
{
bwParams.pasrMode = 0;
}
}
else
{
bwParams.bwPowerFactRho = 1;
bwParams.bwPowerFactSigma = 1;
bwParams.flgPASR = false;
bwParams.pasrMode = 0;
}
if (bwParams.flgPASR) {
///////////////////////////////////////////////////////////
// Activate banks for self refresh based on the PASR mode
// ACTIVE - X
// NOT ACTIVE - 0
///////////////////////////////////////////////////////////
switch(bwParams.pasrMode) {
case(BankWiseParams::pasrModes::PASR_0): {
// PASR MODE 0
// FULL ARRAY
// |X X X X |
// |X X X X |
bwParams.activeBanks.resize(numberOfBanks);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 0);
break;
}
case(BankWiseParams::pasrModes::PASR_1): {
// PASR MODE 1
// (1/2) ARRAY
// |X X X X |
// |0 0 0 0 |
bwParams.activeBanks.resize(numberOfBanks - 4);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 0);
break;
}
case(BankWiseParams::pasrModes::PASR_2): {
// PASR MODE 2
// (1/4) ARRAY
// |X X 0 0 |
// |0 0 0 0 |
bwParams.activeBanks.resize(numberOfBanks - 6);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 0);
break;
}
case(BankWiseParams::pasrModes::PASR_3): {
// PASR MODE 3
// (1/8) ARRAY
// |X 0 0 0 |
// |0 0 0 0 |
bwParams.activeBanks.resize(numberOfBanks - 7);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 0);
break;
}
case(BankWiseParams::pasrModes::PASR_4): {
// PASR MODE 4
// (3/4) ARRAY
// |0 0 X X |
// |X X X X |
bwParams.activeBanks.resize(numberOfBanks - 2);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 2);
break;
}
case(BankWiseParams::pasrModes::PASR_5): {
// PASR MODE 5
// (1/2) ARRAY
// |0 0 0 0 |
// |X X X X |
bwParams.activeBanks.resize(numberOfBanks - 4);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 4);
break;
}
case(BankWiseParams::pasrModes::PASR_6): {
// PASR MODE 6
// (1/4) ARRAY
// |0 0 0 0 |
// |0 0 X X |
bwParams.activeBanks.resize(numberOfBanks - 6);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 6);
break;
}
case(BankWiseParams::pasrModes::PASR_7): {
// PASR MODE 7
// (1/8) ARRAY
// |0 0 0 0 |
// |0 0 0 X |
bwParams.activeBanks.resize(numberOfBanks - 7);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 7);
break;
}
default: {
// PASR MODE 0
// FULL ARRAY
// |X X X X |
// |X X X X |
bwParams.activeBanks.resize(numberOfBanks);
std::iota(bwParams.activeBanks.begin(), bwParams.activeBanks.end(), 0);
break;
}
} //end switch
} // end IF flgPASR
//Source: JESD209-4 (LPDDR4); Table 21
if(burstLength == 16){
prechargeOffsetRD = memTimingSpec.tRTP;
}else{
prechargeOffsetRD = 8 + memTimingSpec.tRTP;
}
prechargeOffsetWR = memTimingSpec.tWL + burstLength/2 + memTimingSpec.tWR + 1;
parseImpedanceSpec(memspec);
}
bool MemSpecLPDDR4::BankWiseParams::isBankActiveInPasr(const unsigned bankIdx) const
{
return (std::find(activeBanks.begin(), activeBanks.end(), bankIdx)
!= activeBanks.end());
}
void MemSpecLPDDR4::parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecLPDDR4 &memspec) {
memImpedanceSpec = memspec.memimpedancespec;
}
MemSpecLPDDR4 MemSpecLPDDR4::from_memspec(const DRAMUtils::MemSpec::MemSpecVariant& memSpec)
{
return std::get(memSpec.getVariant());
}
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecLPDDR4.h
================================================
#ifndef DRAMPOWER_MEMSPEC_MEMSPECLPDDR4_H
#define DRAMPOWER_MEMSPEC_MEMSPECLPDDR4_H
#include "MemSpec.h"
#include
namespace DRAMPower {
class MemSpecLPDDR4 final : public MemSpec
{
public:
using MemImpedanceSpec = DRAMUtils::MemSpec::MemImpedanceSpecTypeLPDDR4;
enum VoltageDomain {
VDD1 = 0,
VDD2 = 1,
};
public:
MemSpecLPDDR4() = delete;
MemSpecLPDDR4(const DRAMUtils::MemSpec::MemSpecLPDDR4 &memspec);
MemSpecLPDDR4(json_t &data) = delete;
MemSpecLPDDR4(const json_t &data) = delete;
// Copy constructor and assignment operator
MemSpecLPDDR4(const MemSpecLPDDR4&) = default;
MemSpecLPDDR4& operator=(const MemSpecLPDDR4&) = default;
// Move constructor and assignment operator
MemSpecLPDDR4(MemSpecLPDDR4&&) = default;
MemSpecLPDDR4& operator=(MemSpecLPDDR4&&) = default;
~MemSpecLPDDR4() = default;
uint64_t numberOfBankGroups;
uint64_t banksPerGroup;
uint64_t numberOfRanks;
double vddq;
struct MemTimingSpec
{
double fck;
double tCK;
uint64_t tRAS;
uint64_t tRCD;
uint64_t tRL;
uint64_t tRTP;
uint64_t tWL;
uint64_t tWR;
uint64_t tREFI;
uint64_t tRFC;
uint64_t tRFCPB;
uint64_t tRP;
};
// Currents and Voltages:
struct MemPowerSpec
{
double vDDX;
double iDD0X;
double iDD2NX;
double iDD3NX;
double iDD2PX;
double iDD3PX;
double iDD4RX;
double iDD4WX;
double iDD5X;
double iDD5PBX;
double iDD6X;
double iBeta;
};
struct BankWiseParams
{
// Set of possible PASR modes
enum pasrModes {
PASR_0,
PASR_1,
PASR_2,
PASR_3,
PASR_4,
PASR_5,
PASR_6,
PASR_7
};
// List of active banks under the specified PASR mode
std::vector activeBanks;
// ACT Standby power factor
double bwPowerFactRho;
// Self-Refresh power factor
double bwPowerFactSigma;
// Whether PASR is enabled ( true : enabled )
bool flgPASR;
// PASR mode utilized (int 0-7)
uint64_t pasrMode;
// Whether bank is active in PASR
bool isBankActiveInPasr(const unsigned bankIdx) const;
};
MemTimingSpec memTimingSpec;
MemImpedanceSpec memImpedanceSpec;
std::vector memPowerSpec;
BankWiseParams bwParams;
private:
void parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecLPDDR4 &memspec);
public:
static MemSpecLPDDR4 from_memspec(const DRAMUtils::MemSpec::MemSpecVariant&);
};
}
#endif /* DRAMPOWER_MEMSPEC_MEMSPECLPDDR4_H */
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecLPDDR5.cpp
================================================
#include "DRAMPower/memspec/MemSpecLPDDR5.h"
using namespace DRAMPower;
MemSpecLPDDR5::MemSpecLPDDR5(const DRAMUtils::MemSpec::MemSpecLPDDR5 &memspec)
: MemSpec(memspec)
{
numberOfBankGroups = memspec.memarchitecturespec.nbrOfBankGroups;
numberOfRanks = memspec.memarchitecturespec.nbrOfRanks;
banksPerGroup = numberOfBanks / numberOfBankGroups;
memTimingSpec.tCK = memspec.memtimingspec.tCK;
memTimingSpec.WCKtoCK = memspec.memtimingspec.WCK2CK;
memTimingSpec.tWCK = memTimingSpec.tCK / memTimingSpec.WCKtoCK;
memTimingSpec.tRAS = memspec.memtimingspec.RAS;
memTimingSpec.tRCD = memspec.memtimingspec.RCD_S;
memTimingSpec.tRBTP = memspec.memtimingspec.RBTP;
memTimingSpec.tWL = memspec.memtimingspec.WL;
memTimingSpec.tWR = memspec.memtimingspec.WR;
memTimingSpec.tRP = memspec.memtimingspec.RPpb;
memTimingSpec.tRFCPB = memspec.memtimingspec.RFCpb;
memTimingSpec.tRFC = memspec.memtimingspec.RFCab;
memTimingSpec.tREFI = memspec.memtimingspec.REFI;
auto VDD1 = VoltageDomain::VDD1;
auto VDD2H = VoltageDomain::VDD2H;
auto VDD2L = VoltageDomain::VDD2L;
memPowerSpec.push_back(MemPowerSpec()); // VDD1
memPowerSpec.push_back(MemPowerSpec()); // VDD2H
memPowerSpec.push_back(MemPowerSpec()); // VDD2L
memPowerSpec[VDD1].vDDX = memspec.mempowerspec.vdd1;
memPowerSpec[VDD1].iDD0X = memspec.mempowerspec.idd01;
memPowerSpec[VDD1].iDD2NX = memspec.mempowerspec.idd2n1;
memPowerSpec[VDD1].iDD3NX = memspec.mempowerspec.idd3n1;
memPowerSpec[VDD1].iDD4RX = memspec.mempowerspec.idd4r1;
memPowerSpec[VDD1].iDD4WX = memspec.mempowerspec.idd4w1;
memPowerSpec[VDD1].iDD5X = memspec.mempowerspec.idd51;
memPowerSpec[VDD1].iDD5PBX = memspec.mempowerspec.idd5pb1;
memPowerSpec[VDD1].iDD6X = memspec.mempowerspec.idd61;
memPowerSpec[VDD1].iDD6DSX = memspec.mempowerspec.idd6ds1;
memPowerSpec[VDD1].iDD2PX = memspec.mempowerspec.idd2p1;
memPowerSpec[VDD1].iDD3PX = memspec.mempowerspec.idd3p1;
memPowerSpec[VDD2H].vDDX = memspec.mempowerspec.vdd2h;
memPowerSpec[VDD2H].iDD0X = memspec.mempowerspec.idd02h;
memPowerSpec[VDD2H].iDD2NX = memspec.mempowerspec.idd2n2h;
memPowerSpec[VDD2H].iDD3NX = memspec.mempowerspec.idd3n2h;
memPowerSpec[VDD2H].iDD4RX = memspec.mempowerspec.idd4r2h;
memPowerSpec[VDD2H].iDD4WX = memspec.mempowerspec.idd4w2h;
memPowerSpec[VDD2H].iDD5X = memspec.mempowerspec.idd52h;
memPowerSpec[VDD2H].iDD5PBX = memspec.mempowerspec.idd5pb2h;
memPowerSpec[VDD2H].iDD6X = memspec.mempowerspec.idd62h;
memPowerSpec[VDD2H].iDD6DSX = memspec.mempowerspec.idd6ds2h;
memPowerSpec[VDD2H].iDD2PX = memspec.mempowerspec.idd2p2h;
memPowerSpec[VDD2H].iDD3PX = memspec.mempowerspec.idd3p2h;
memPowerSpec[VDD2L].vDDX = memspec.mempowerspec.vdd2l;
memPowerSpec[VDD2L].iDD0X = memspec.mempowerspec.idd02l;
memPowerSpec[VDD2L].iDD2NX = memspec.mempowerspec.idd2n2l;
memPowerSpec[VDD2L].iDD3NX = memspec.mempowerspec.idd3n2l;
memPowerSpec[VDD2L].iDD4RX = memspec.mempowerspec.idd4r2l;
memPowerSpec[VDD2L].iDD4WX = memspec.mempowerspec.idd4w2l;
memPowerSpec[VDD2L].iDD5X = memspec.mempowerspec.idd52l;
memPowerSpec[VDD2L].iDD5PBX = memspec.mempowerspec.idd5pb2l;
memPowerSpec[VDD2L].iDD6X = memspec.mempowerspec.idd62l;
memPowerSpec[VDD2L].iDD6DSX = memspec.mempowerspec.idd6ds2l;
memPowerSpec[VDD2L].iDD2PX = memspec.mempowerspec.idd2p2l;
memPowerSpec[VDD2L].iDD3PX = memspec.mempowerspec.idd3p2l;
vddq = memspec.mempowerspec.vddq;
memPowerSpec[VDD1].iBeta = memspec.mempowerspec.iBeta_vdd1.value_or(memspec.mempowerspec.idd01);
memPowerSpec[VDD2H].iBeta = memspec.mempowerspec.iBeta_vdd2h.value_or(memspec.mempowerspec.idd02h);
memPowerSpec[VDD2L].iBeta = memspec.mempowerspec.iBeta_vdd2l.value_or(memspec.mempowerspec.idd02l);
if (memspec.bankwisespec.has_value()) {
bwParams.bwPowerFactRho = memspec.bankwisespec.value().factRho.value_or(1);
}
else {
bwParams.bwPowerFactRho = 1;
}
auto BankArchError = [this]() {
std::cout << "Invalid bank architecture selected" << std::endl;
std::cout << "Selected values:" << std::endl;
std::cout << " - Number of banks: " << numberOfBanks << std::endl;
std::cout << " - Number of bank groups: " << numberOfBankGroups << std::endl;
std::cout << "Valid values are 16|1 (16B mode), 16|4 (BG mode) or 8|1 (8B mode)" << std::endl;
std::cout << std::endl << "Assuming 16B architecture." << std::endl;
bank_arch = BankArchitectureMode::M16B;
numberOfBanks = 16;
numberOfBankGroups = 1;
};
if (numberOfBanks == 16) {
if (numberOfBankGroups == 1 || numberOfBankGroups == 0) {
bank_arch = BankArchitectureMode::M16B;
} else if (numberOfBankGroups == 4) {
bank_arch = BankArchitectureMode::MBG;
} else {
BankArchError();
}
} else if (numberOfBanks == 8) {
if (numberOfBankGroups > 1) {
BankArchError();
} else {
bank_arch = BankArchitectureMode::M8B;
}
} else {
BankArchError();
}
// Source: LPDDR5 standard; table 312
memTimingSpec.tBurst = burstLength/(dataRate * memTimingSpec.WCKtoCK);
// Source: LPDDR5 standard; figure 96
prechargeOffsetRD = memTimingSpec.tBurst + memTimingSpec.tRBTP;
// Source: LPDDR5 standard; figure 97
prechargeOffsetWR = memTimingSpec.tWL + memTimingSpec.tBurst + 1 + memTimingSpec.tWR;
wckAlwaysOnMode = memspec.memarchitecturespec.WCKalwaysOn;
parseImpedanceSpec(memspec);
}
void MemSpecLPDDR5::parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecLPDDR5 &memspec) {
memImpedanceSpec = memspec.memimpedancespec;
}
MemSpecLPDDR5 MemSpecLPDDR5::from_memspec(const DRAMUtils::MemSpec::MemSpecVariant& memSpec)
{
return std::get(memSpec.getVariant());
}
================================================
FILE: src/DRAMPower/DRAMPower/memspec/MemSpecLPDDR5.h
================================================
#ifndef DRAMPOWER_MEMSPEC_MEMSPECLPDDR5_H
#define DRAMPOWER_MEMSPEC_MEMSPECLPDDR5_H
#include "MemSpec.h"
#include
namespace DRAMPower {
class MemSpecLPDDR5 final : public MemSpec {
public:
using MemImpedanceSpec = DRAMUtils::MemSpec::MemImpedanceSpecTypeLPDDR5;
enum VoltageDomain {
VDD1 = 0,
VDD2H,
VDD2L,
};
enum BankArchitectureMode {
MBG, // 4 banks, 4 bank groups
M16B, // 16 banks, no bank groups
M8B // 8 banks, no bank groups
};
public:
MemSpecLPDDR5() = delete;
MemSpecLPDDR5(const DRAMUtils::MemSpec::MemSpecLPDDR5 &memspec);
MemSpecLPDDR5(json_t &data) = delete;
MemSpecLPDDR5(const json_t &data) = delete;
// Copy constructor and assignment operator
MemSpecLPDDR5(const MemSpecLPDDR5&) = default;
MemSpecLPDDR5& operator=(const MemSpecLPDDR5&) = default;
// Move constructor and assignment operator
MemSpecLPDDR5(MemSpecLPDDR5&&) = default;
MemSpecLPDDR5& operator=(MemSpecLPDDR5&&) = default;
~MemSpecLPDDR5() = default;
uint64_t numberOfBankGroups;
uint64_t banksPerGroup;
uint64_t numberOfRanks;
std::size_t perTwoBankOffset = 8;
BankArchitectureMode bank_arch;
bool wckAlwaysOnMode;
double vddq;
// Memspec Variables:
struct MemTimingSpec
{
double fck;
double tCK;
double tWCK;
uint64_t WCKtoCK;
uint64_t tRAS;
uint64_t tRCD;
uint64_t tRL;
uint64_t tWL;
uint64_t tWR;
uint64_t tRFC;
uint64_t tRFCPB;
uint64_t tREFI;
uint64_t tRP;
uint64_t tRBTP;
uint64_t tBurst;
};
// Currents and Voltages:
struct MemPowerSpec
{
double vDDX;
double iDD0X;
double iDD2NX;
double iDD3NX;
double iDD2PX;
double iDD3PX;
double iDD4RX;
double iDD4WX;
double iDD5X;
double iDD5PBX;
double iDD6X;
double iDD6DSX;
double iBeta;
};
struct BankWiseParams {
// ACT Standby power factor
double bwPowerFactRho;
};
MemTimingSpec memTimingSpec;
MemImpedanceSpec memImpedanceSpec;
std::vector memPowerSpec;
BankWiseParams bwParams;
private:
void parseImpedanceSpec(const DRAMUtils::MemSpec::MemSpecLPDDR5 &memspec);
public:
static MemSpecLPDDR5 from_memspec(const DRAMUtils::MemSpec::MemSpecVariant&);
};
} // namespace DRAMPower
#endif /* DRAMPOWER_MEMSPEC_MEMSPECLPDDR5_H */
================================================
FILE: src/DRAMPower/DRAMPower/simconfig/simconfig.h
================================================
#ifndef DRAMPOWER_SIMCONFIG_SIMCONFIG_H
#define DRAMPOWER_SIMCONFIG_SIMCONFIG_H
#include "DRAMUtils/util/json_utils.h"
#include "DRAMUtils/config/toggling_rate.h"
namespace DRAMPower::config {
struct SimConfig {
// Public type definitions
public:
using ToggleRateDefinition_t = DRAMUtils::Config::ToggleRateDefinition;
// Public Constructors
public:
SimConfig() = default;
// Public members
public:
std::optional toggleRateDefinition;
};
NLOHMANN_JSONIFY_ALL_THINGS(SimConfig, toggleRateDefinition);
} // DRAMPower::config
#endif /* DRAMPOWER_SIMCONFIG_SIMCONFIG_H */
================================================
FILE: src/DRAMPower/DRAMPower/standards/ddr4/DDR4.cpp
================================================
#include "DDR4.h"
#include "DRAMPower/Types.h"
#include "DRAMPower/data/stats.h"
#include "DRAMPower/memspec/MemSpecDDR4.h"
#include "DRAMPower/standards/ddr4/DDR4Interface.h"
#include "DRAMPower/standards/ddr4/core_calculation_DDR4.h"
#include "DRAMPower/standards/ddr4/interface_calculation_DDR4.h"
#include "DRAMPower/util/cli_architecture_config.h"
#include
#include
namespace DRAMPower {
using namespace DRAMUtils::Config;
DDR4::DDR4(const MemSpecDDR4 &memSpec, const config::SimConfig &simConfig)
: m_memSpec(memSpec)
, m_interface(m_memSpec, simConfig)
, m_core(m_memSpec)
{
this->registerExtensions();
}
// Extensions
void DDR4::registerExtensions() {
getExtensionManager().registerExtension