diff --git a/.gitignore b/.gitignore index c7425d6f..99b20805 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ /dram/debug /dram/release /dram/build -*pro.user* +*.user *.tdb *.tdb-journal *.out diff --git a/.gitmodules b/.gitmodules index 458b70e3..13b67848 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,7 +4,13 @@ [submodule "DRAMSys/library/src/common/third_party/DRAMPower"] path = DRAMSys/library/src/common/third_party/DRAMPower url = https://github.com/tukl-msd/DRAMPower.git - branch = master + branch = rgr [submodule "DRAMSys/unitTests/googletest"] path = DRAMSys/unitTests/googletest url = https://github.com/google/googletest.git +[submodule "DRAMSys/library/src/common/third_party/systemc"] + path = DRAMSys/library/src/common/third_party/systemc + url = https://github.com/accellera-official/systemc.git +[submodule "DRAMSys/library/src/common/third_party/sqlite-amalgamation"] + path = DRAMSys/library/src/common/third_party/sqlite-amalgamation + url = https://github.com/azadkuh/sqlite-amalgamation.git diff --git a/utils/getqwt.sh b/DRAMSys/CMakeLists.txt old mode 100755 new mode 100644 similarity index 64% rename from utils/getqwt.sh rename to DRAMSys/CMakeLists.txt index b3f43208..9ce35df7 --- a/utils/getqwt.sh +++ b/DRAMSys/CMakeLists.txt @@ -1,6 +1,4 @@ -#!/usr/bin/env bash - -# Copyright (c) 2017, University of Kaiserslautern +# Copyright (c) 2020, Fraunhofer IESE # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,16 +28,33 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# Author: Éder F. Zulian +# Author: Matthias Jung + +cmake_minimum_required(VERSION 3.10) + +# Project Name: +project(DRAMSys) + +# Configuration: +set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ Version") +set(DCMAKE_SH "CMAKE_SH-NOTFOUND" CACHE STRING "Ignore sh.exe error on Windows") + +# Add sqlite3 Dependency: +set(BUILD_ENABLE_RTREE ON CACHE BOOL "Enable R-Tree Feature") +set(BUILD_ENABLE_RTREE ON) +add_subdirectory(library/src/common/third_party/sqlite-amalgamation) + +# Add DRAMSysLibrary: +add_subdirectory(library) + +# Add TraceAnalyzer: +add_subdirectory(traceAnalyzer) + +# Build: +add_executable(DRAMSys simulator/main.cpp) +target_include_directories(DRAMSys + PUBLIC library/src/simulation/ + PUBLIC library/src/common/third_party/sqlite-amalgamation/ +) +target_link_libraries(DRAMSys sqlite3::sqlite3 systemc DRAMSysLibrary) -dest=$HOME/qwt-6.1 -svn checkout svn://svn.code.sf.net/p/qwt/code/branches/qwt-6.1 $dest -cd $dest -svn up -r 2481 -if [[ $(hostname -s) =~ ^head[0-9]+$ ]] || [[ $(hostname -s) =~ ^node[0-9]+$ ]]; then - # Elwetritsch cluster - heads or nodes - module load qt/5.5 -fi -qmake qwt.pro -make -echo "Done." diff --git a/DRAMSys/DRAMSys.pro b/DRAMSys/DRAMSys.pro deleted file mode 100644 index d4a5e29e..00000000 --- a/DRAMSys/DRAMSys.pro +++ /dev/null @@ -1,58 +0,0 @@ -TEMPLATE = subdirs - -thermalsim = $$(THERMALSIM) -isEmpty(thermalsim) { - thermalsim = false -} - -$$eval(thermalsim) { - message(Thermal Simulation Feature Enabled) -} else { - message(Thermal Simulation Feature Disabled) -} - -dramsys_disable_coverage_check = $$(DRAMSYS_DISABLE_COVERAGE_CHECK) -isEmpty(dramsys_disable_coverage_check) { - message(Coverage check ENABLED) -} else { - message(Coverage check DISABLED) -} - -systemc_home = $$(SYSTEMC_HOME) -isEmpty(systemc_home) { - systemc_home = /opt/systemc -} -message(SystemC home is $${systemc_home}) - -SUBDIRS += library -SUBDIRS += unitTests -SUBDIRS += simulator -SUBDIRS += traceAnalyzer - -library.subdir = library -unitTests.subdir = unitTests -simulator.subdir = simulator -traceAnalyzer.subdir = traceAnalyzer - -# Check if gem5 is installed: -gem5 = $$(GEM5) -isEmpty(gem5) { - message(GEM5 environment variable not found) - message(Gem5 Simulation Disabled) -} else { - message(Gem5 Simulation Feature Enabled) - message(Gem5 home is $${gem5}) - DEFINES += DRAMSYS_GEM5 - SUBDIRS += gem5 - gem5.subdir = gem5 - gem5.depends = library simulator -} - -# Define Build Order -simulator.depends = library - -# Additional Files: -# tests folder (DRAMSys/tests) -include(tests/tests.pri) - -DISTFILES += ../README.md diff --git a/DRAMSys/library/CMakeLists.txt b/DRAMSys/library/CMakeLists.txt new file mode 100644 index 00000000..e43b84a8 --- /dev/null +++ b/DRAMSys/library/CMakeLists.txt @@ -0,0 +1,146 @@ +# Copyright (c) 2020, 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: Matthias Jung + +cmake_minimum_required(VERSION 3.10) + +# Project Name +project(DRAMSysLibrary) + +# Add DRAMPower: +add_subdirectory(src/common/third_party/DRAMPower) + +# Add SystemC: +set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Shared Libs") +add_subdirectory(src/common/third_party/systemc) + +# Configuration: +set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ Version") +set(DCMAKE_SH="CMAKE_SH-NOTFOUND") + +include_directories( + src/simulation + src/simulation/dram + src/controller + src/controller/checker + src/controller/cmdmux + src/controller/powerdown + src/controller/refresh + src/controller/scheduler + src/common + src/common/third_party/DRAMPower/src + src/configuration + src/configuration/memspec + src/error + src/error/ECC +) + +add_library(DRAMSysLibrary + src/common/third_party/tinyxml2/tinyxml2.cpp + src/common/TlmRecorder.cpp + src/common/DebugManager.cpp + src/configuration/Configuration.cpp + src/simulation/MemoryManager.cpp + src/simulation/TemperatureController.cpp + src/configuration/ConfigurationLoader.cpp + src/controller/Command.cpp + src/error/errormodel.cpp + src/simulation/TracePlayer.cpp + src/simulation/TraceSetup.cpp + src/simulation/DRAMSys.cpp + src/simulation/Setup.cpp + src/error/ECC/Bit.cpp + src/error/ECC/ECC.cpp + src/error/ECC/Word.cpp + src/error/eccbaseclass.cpp + src/error/ecchamming.cpp + src/common/AddressDecoder.cpp + src/simulation/dram/Dram.cpp + src/simulation/Arbiter.cpp + src/common/CongenAddressDecoder.cpp + src/common/XmlAddressDecoder.cpp + src/common/timingCalculations.cpp + src/common/dramExtensions.cpp + src/common/utils.cpp + src/simulation/dram/DramDDR3.cpp + src/simulation/dram/DramDDR4.cpp + src/simulation/dram/DramRecordable.cpp + src/simulation/dram/DramWideIO.cpp + src/configuration/memspec/MemSpec.cpp + src/controller/BankMachine.cpp + src/controller/Controller.cpp + src/controller/scheduler/SchedulerFifo.cpp + src/controller/scheduler/SchedulerFrFcfs.cpp + src/controller/cmdmux/CmdMuxStrict.cpp + src/controller/cmdmux/CmdMuxOldest.cpp + src/controller/ControllerRecordable.cpp + src/controller/checker/CheckerDDR3.cpp + src/controller/refresh/RefreshManager.cpp + src/controller/refresh/RefreshManagerDummy.cpp + src/controller/refresh/RefreshManagerBankwise.cpp + src/controller/checker/CheckerWideIO.cpp + src/configuration/memspec/MemSpecDDR3.cpp + src/configuration/memspec/MemSpecDDR4.cpp + src/configuration/memspec/MemSpecWideIO.cpp + src/configuration/memspec/MemSpecLPDDR4.cpp + src/controller/checker/CheckerDDR4.cpp + src/simulation/dram/DramLPDDR4.cpp + src/controller/checker/CheckerLPDDR4.cpp + src/configuration/memspec/MemSpecWideIO2.cpp + src/simulation/dram/DramWideIO2.cpp + src/controller/checker/CheckerWideIO2.cpp + src/configuration/memspec/MemSpecHBM2.cpp + src/simulation/dram/DramHBM2.cpp + src/controller/checker/CheckerHBM2.cpp + src/configuration/memspec/MemSpecGDDR5.cpp + src/configuration/memspec/MemSpecGDDR5X.cpp + src/configuration/memspec/MemSpecGDDR6.cpp + src/controller/checker/CheckerGDDR5.cpp + src/controller/checker/CheckerGDDR5X.cpp + src/controller/checker/CheckerGDDR6.cpp + src/simulation/dram/DramGDDR5.cpp + src/simulation/dram/DramGDDR5X.cpp + src/simulation/dram/DramGDDR6.cpp + src/controller/powerdown/PowerDownManagerStaggered.cpp + src/controller/powerdown/PowerDownManagerDummy.cpp +) + +# Build: +target_include_directories(DRAMSysLibrary + PUBLIC src/common/third_party/DRAMPower/src + PUBLIC src/common/third_party/sqlite-amalgamation/ +) +target_link_libraries(DRAMSysLibrary + SystemC::systemc + sqlite3::sqlite3 + DRAMPower +) + diff --git a/DRAMSys/library/library.pro b/DRAMSys/library/library.pro deleted file mode 100644 index ea30b870..00000000 --- a/DRAMSys/library/library.pro +++ /dev/null @@ -1,275 +0,0 @@ -TARGET = DRAMSys - -TEMPLATE = lib -CONFIG += staticlib -CONFIG += console -CONFIG -= app_bundle -CONFIG -= qt - -system(cd ../../DRAMSys/library/src/common/third_party/DRAMPower; make src/libdrampower.a;) - -systemc_home = $$(SYSTEMC_HOME) -isEmpty(systemc_home) { - systemc_home = /opt/systemc -} - -# Check if PCT's SystemC should be used? -dramsys_pct = $$(DRAMSYS_PCT) -isEmpty(dramsys_pct) { - dramsys_pct = false -} - -$$eval(dramsys_pct) { - # PCT: - message(PCT Simulation Feature Enabled) - systemc_home = /software/Synopsys_CoWare/K-2015.12-SP1/SLS/linux/common - INCLUDEPATH += $${systemc_home}/include/tlm - - DEFINES += DRAMSYS_PCT -} - -# Check if gem5 should be used -gem5 = $$(GEM5) -isEmpty(gem5) { - message(GEM5 environment variable not found) - message(Gem5 Simulation Disabled) -} else { - message(Gem5 Simulation Feature Enabled) - message(Gem5 home is $${gem5}) - DEFINES += DRAMSYS_GEM5 -} - -message(SystemC home is $${systemc_home}) - -systemc_target_arch = $$(SYSTEMC_TARGET_ARCH) -isEmpty(systemc_target_arch) { - systemc_target_arch = linux64 -} -message(SystemC target architecture is $${systemc_target_arch}) - -INCLUDEPATH += $${systemc_home}/include - -INCLUDEPATH += src/common/third_party/DRAMPower/src -INCLUDEPATH += src/common/third_party/DRAMPower/src/libdrampower -INCLUDEPATH += src/common/third_party/json/include - -DEFINES += TIXML_USE_STL -DEFINES += SC_INCLUDE_DYNAMIC_PROCESSES - -dramsys_disable_coverage_check = $$(DRAMSYS_DISABLE_COVERAGE_CHECK) -isEmpty(dramsys_disable_coverage_check) { - coverage_check = true - message(Coverage check ENABLED) -} else { - coverage_check = false - message(Coverage check DISABLED) -} - -unix:!macx { - QMAKE_CXXFLAGS += -std=c++11 -O0 -g - $$eval(coverage_check) { - QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -fPIC -O0 - QMAKE_LFLAGS += -lgcov --coverage - } -} - -macx: { - CONFIG += c++11 - QMAKE_CXXFLAGS += -std=c++0x -stdlib=libc++ -O0 -g - QMAKE_MACOSX_DEPLOYMENT_TARGET=10.14 - $$eval(coverage_check) { - QMAKE_CXXFLAGS += --coverage - QMAKE_LFLAGS += --coverage - } -} - -QMAKE_CXXFLAGS += -isystem $${systemc_home}/include - -SOURCES += \ - src/common/third_party/tinyxml2/tinyxml2.cpp \ - src/common/TlmRecorder.cpp \ - src/common/DebugManager.cpp \ - src/controller/core/configuration/Configuration.cpp \ - src/controller/core/powerdown/PowerDownManagerTimeout.cpp \ - src/controller/core/powerdown/PowerDownManagerBankwise.cpp \ - src/controller/core/powerdown/PowerDownManager.cpp \ - src/controller/scheduler/FrFcfs.cpp \ - src/controller/scheduler/Fifo.cpp \ - src/controller/scheduler/SMS.cpp \ - src/controller/core/refresh/RefreshManagerBankwise.cpp \ - src/controller/core/refresh/RefreshManager.cpp \ - src/controller/core/refresh/RGR.cpp \ - src/controller/core/scheduling/checker/WriteChecker.cpp \ - src/controller/core/scheduling/checker/RefreshChecker.cpp \ - src/controller/core/scheduling/checker/ReadChecker.cpp \ - src/controller/core/scheduling/checker/PrechargeChecker.cpp \ - src/controller/core/scheduling/checker/PrechargeAllChecker.cpp \ - src/controller/core/scheduling/checker/PowerDownChecker.cpp \ - src/controller/core/scheduling/checker/ActivateChecker.cpp \ - src/controller/core/scheduling/checker/PreBChecker.cpp \ - src/controller/core/scheduling/checker/ActBChecker.cpp \ - src/controller/core/scheduling/ScheduledCommand.cpp \ - src/controller/core/Slots.cpp \ - src/controller/core/ControllerCore.cpp \ - src/simulation/MemoryManager.cpp \ - src/simulation/TemperatureController.cpp \ - src/controller/core/configuration/ConfigurationLoader.cpp \ - src/controller/core/powerdown/NoPowerDown.cpp \ - src/controller/Command.cpp \ - src/controller/ControllerState.cpp \ - src/controller/RowBufferStates.cpp \ - src/controller/scheduler/IScheduler.cpp \ - src/controller/scheduler/FifoStrict.cpp \ - src/error/errormodel.cpp \ - src/controller/Controller.cpp \ - src/simulation/TracePlayer.cpp \ - src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp \ - src/simulation/TraceSetup.cpp \ - src/simulation/DRAMSys.cpp \ - src/simulation/Setup.cpp \ - src/error/ECC/Bit.cpp \ - src/error/ECC/ECC.cpp \ - src/error/ECC/Word.cpp \ - src/error/eccbaseclass.cpp \ - src/error/ecchamming.cpp \ - src/controller/scheduler/FrFcfsRp.cpp \ - src/controller/scheduler/FrFcfsGrp.cpp \ - src/controller/scheduler/Grp.cpp \ - src/controller/RecordableController.cpp \ - src/common/AddressDecoder.cpp \ - src/simulation/Dram.cpp \ - src/simulation/RecordableDram.cpp \ - src/simulation/Arbiter.cpp \ - src/common/CongenAddressDecoder.cpp \ - src/common/XmlAddressDecoder.cpp \ - src/controller/core/timingCalculations.cpp \ - src/common/dramExtensions.cpp \ - src/common/utils.cpp \ - src/simulation/DramDDR3.cpp \ - src/simulation/DramDDR4.cpp \ - src/simulation/DramRecordable.cpp \ - src/simulation/DramWideIO.cpp - -HEADERS += \ - src/common/third_party/tinyxml2/tinyxml2.h \ - src/common/TlmRecorder.h \ - src/common/tlm2_base_protocol_checker.h \ - src/common/protocol.h \ - src/common/DebugManager.h \ - src/controller/core/configuration/Configuration.h \ - src/controller/core/powerdown/PowerDownManagerTimeout.h \ - src/controller/core/powerdown/PowerDownManagerBankwise.h \ - src/controller/core/powerdown/PowerDownManager.h \ - src/controller/scheduler/FrFcfs.h \ - src/controller/scheduler/Fifo.h \ - src/controller/scheduler/SMS.h \ - src/controller/Controller.h \ - src/controller/core/refresh/RefreshManagerBankwise.h \ - src/controller/core/refresh/RefreshManager.h \ - src/controller/core/refresh/IRefreshManager.h \ - src/controller/core/refresh/RGR.h \ - src/controller/core/scheduling/checker/WriteChecker.h \ - src/controller/core/scheduling/checker/RefreshChecker.h \ - src/controller/core/scheduling/checker/ReadChecker.h \ - src/controller/core/scheduling/checker/PrechargeChecker.h \ - src/controller/core/scheduling/checker/PrechargeAllChecker.h \ - src/controller/core/scheduling/checker/PowerDownChecker.h \ - src/controller/core/scheduling/checker/ICommandChecker.h \ - src/controller/core/scheduling/checker/ActivateChecker.h \ - src/controller/core/scheduling/checker/PreBChecker.h \ - src/controller/core/scheduling/checker/ActBChecker.h \ - src/controller/core/scheduling/ScheduledCommand.h \ - src/controller/core/Slots.h \ - src/controller/core/ControllerCore.h \ - src/simulation/TracePlayer.h \ - src/simulation/MemoryManager.h \ - src/simulation/Dram.h \ - src/simulation/Arbiter.h \ - src/common/libDRAMPower.h \ - src/simulation/ReorderBuffer.h \ - src/controller/core/configuration/MemSpec.h \ - src/simulation/StlPlayer.h \ - src/simulation/TracePlayerListener.h \ - src/simulation/TraceGenerator.h \ - src/simulation/TemperatureController.h \ - src/controller/core/powerdown/NoPowerDown.h \ - src/controller/Command.h \ - src/controller/RowBufferStates.h \ - src/controller/ControllerState.h \ - src/controller/core/powerdown/IPowerDownManager.h \ - src/controller/scheduler/IScheduler.h \ - src/controller/scheduler/FifoStrict.h \ - src/controller/IController.h \ - src/controller/core/configuration/ConfigurationLoader.h \ - src/error/errormodel.h \ - src/simulation/ExampleInitiator.h \ - src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.h \ - src/simulation/TraceSetup.h \ - src/simulation/DRAMSys.h \ - src/simulation/Setup.h \ - src/error/ECC/Bit.h \ - src/error/ECC/ECC.h \ - src/error/ECC/Word.h \ - src/error/eccbaseclass.h \ - src/error/ecchamming.h \ - src/controller/scheduler/FrFcfsRp.h \ - src/controller/scheduler/FrFcfsGrp.h \ - src/controller/scheduler/Grp.h \ - src/simulation/IArbiter.h \ - src/simulation/SimpleArbiter.h \ - src/controller/RecordableController.h \ - src/simulation/RecordableDram.h \ - src/common/AddressDecoder.h \ - src/common/CongenAddressDecoder.h \ - src/common/XmlAddressDecoder.h \ - src/controller/core/timingCalculations.h \ - src/common/dramExtensions.h \ - src/common/utils.h \ - src/controller/core/configuration/TemperatureSimConfig.h \ - src/simulation/DramDDR3.h \ - src/simulation/DramDDR4.h \ - src/simulation/DramRecordable.h \ - src/simulation/DramWideIO.h - #src/common/third_party/json/include/nlohmann/json.hpp \ - -thermalsim = $$(THERMALSIM) -isEmpty(thermalsim) { - thermalsim = false -} - -$$eval(thermalsim) { - message(Thermal Simulation Feature Enabled) - - libthreed_ice_home = $$(LIBTHREED_ICE_HOME) - isEmpty(libthreed_ice_home) { - libthreed_ice_home = /opt/3D-ICE/ - } - message(LIBTHREED_ICE_HOME path is $${libthreed_ice_home}) - - libsuperlu_home = $$(LIBSUPERLU_HOME) - isEmpty(libsuperlu_home) { - libsuperlu_home = /opt/SuperLU_4.3/ - } - message(LIBSUPERLU_HOME path is $${libthreed_ice_home}) - - LIBS += -L$${libthreed_ice_home}/lib -lthreed-ice-2.2.4 - LIBS += -L$${libsuperlu_home}/lib -lsuperlu_4.3 - LIBS += -lblas - message(Libraries: $${LIBS}) - - INCLUDEPATH += $${libthreed_ice_home}/include - INCLUDEPATH += $${libsuperlu_home}/SRC - INCLUDEPATH += $${systemc_home}/include - message(Include paths: $${INCLUDEPATH}) - - QMAKE_CXXFLAGS += -DTHERMALSIM - message(Compiler flags: $${QMAKE_CXXFLAGS}) - -} else { - message(Thermal Simulation Feature Disabled) -} - -# Additional Files: -include(resources/resources.pri) - -DISTFILES += ../DRAMSys.astylerc diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3.xml index 497a2388..8d73c4c5 100755 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3.xml @@ -1,5 +1,4 @@ - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_1Gbx8_p1KB_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_1Gbx8_p1KB_brc.xml index a508caa7..7b392322 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_1Gbx8_p1KB_brc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_1Gbx8_p1KB_brc.xml @@ -14,7 +14,6 @@ B B B | R R R R R R R R R R R R R R | C C C C C C C C C C | --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_brc.xml index 2422faf3..886385fe 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_brc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_brc.xml @@ -26,7 +26,6 @@ --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.xml index 7ba3e518..48f2962a 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.xml @@ -26,7 +26,6 @@ --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_brc.xml index 39d66692..5500c9ae 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_brc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_brc.xml @@ -16,7 +16,6 @@ B B B | R R R R R R R R R R R R R R | C C C C C C C C C C | Y Y Y --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.xml index 46cb5158..fb4d44ed 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.xml @@ -16,7 +16,6 @@ R R R R R R R R R R R R R R | B B B | C C C C C C C C C C | Y Y Y --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_brc.xml index 6f384970..0106b60d 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_brc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_brc.xml @@ -16,7 +16,6 @@ B B B | R R R R R R R R R R R R R R R | C C C C C C C C C C | Y Y Y --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.xml index 7f9e64fe..c87cdd44 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.xml @@ -16,7 +16,6 @@ R R R R R R R R R R R R R R R | B B B | C C C C C C C C C C | Y Y Y --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_brc.xml index dfddfbc9..66341554 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_brc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_brc.xml @@ -1,5 +1,4 @@ - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_rbc.xml index 8323d7b5..cb042a68 100644 --- a/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_rbc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr3_x16_rbc.xml @@ -1,5 +1,4 @@ - diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr4_8x4Gbx8_dimm_p1KB_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_ddr4_8x4Gbx8_dimm_p1KB_brc.xml new file mode 100644 index 00000000..83fa9e4c --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr4_8x4Gbx8_dimm_p1KB_brc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_hbm2_8Gb_pc_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_hbm2_8Gb_pc_brc.xml new file mode 100644 index 00000000..24cf9469 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_hbm2_8Gb_pc_brc.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_lpddr4_8Gbx16_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_lpddr4_8Gbx16_brc.xml new file mode 100644 index 00000000..4844bbf4 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_lpddr4_8Gbx16_brc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_lpddr4_8Gbx16_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_lpddr4_8Gbx16_rbc.xml new file mode 100644 index 00000000..c4ae7d76 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_lpddr4_8Gbx16_rbc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ranktest.xml b/DRAMSys/library/resources/configs/amconfigs/am_ranktest.xml new file mode 100644 index 00000000..e0a858fe --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_ranktest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio2_4x64_4x2Gb_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio2_4x64_4x2Gb_brc.xml new file mode 100644 index 00000000..63c29bfc --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio2_4x64_4x2Gb_brc.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio2_4x64_4x2Gb_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio2_4x64_4x2Gb_rbc.xml new file mode 100644 index 00000000..fc952eba --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio2_4x64_4x2Gb_rbc.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x1Gb_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x1Gb_brc.xml new file mode 100644 index 00000000..ffce3d26 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x1Gb_brc.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x1Gb_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x1Gb_rbc.xml new file mode 100644 index 00000000..cbed2266 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x1Gb_rbc.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x256Mb_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x256Mb_brc.xml new file mode 100644 index 00000000..71f71bc8 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x256Mb_brc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x256Mb_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x256Mb_rbc.xml new file mode 100644 index 00000000..49e1a0ba --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x256Mb_rbc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x2Gb_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x2Gb_brc.xml new file mode 100644 index 00000000..bbf25e41 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x2Gb_brc.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x2Gb_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x2Gb_rbc.xml new file mode 100644 index 00000000..cd213a33 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x2Gb_rbc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x4Gb_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x4Gb_brc.xml new file mode 100644 index 00000000..b330b0cd --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x4Gb_brc.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x4Gb_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x4Gb_rbc.xml new file mode 100644 index 00000000..7973505e --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x4Gb_rbc.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x512Mb_brc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x512Mb_brc.xml new file mode 100644 index 00000000..b6de91b9 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x512Mb_brc.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x512Mb_rbc.xml b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x512Mb_rbc.xml new file mode 100644 index 00000000..52235bd4 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_wideio_4x512Mb_rbc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/orgr_ddr4_4x16Gbx16_dimm_p2KB_brc.xml b/DRAMSys/library/resources/configs/amconfigs/orgr_ddr4_4x16Gbx16_dimm_p2KB_brc.xml index b387e522..a4d04ebe 100644 --- a/DRAMSys/library/resources/configs/amconfigs/orgr_ddr4_4x16Gbx16_dimm_p2KB_brc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/orgr_ddr4_4x16Gbx16_dimm_p2KB_brc.xml @@ -11,7 +11,6 @@ --> - diff --git a/DRAMSys/library/resources/configs/amconfigs/rgram-rbc.xml b/DRAMSys/library/resources/configs/amconfigs/rgram-rbc.xml index 689aad68..c616ec0c 100644 --- a/DRAMSys/library/resources/configs/amconfigs/rgram-rbc.xml +++ b/DRAMSys/library/resources/configs/amconfigs/rgram-rbc.xml @@ -1,5 +1,4 @@ - diff --git a/DRAMSys/library/resources/configs/amconfigs/rgram.xml b/DRAMSys/library/resources/configs/amconfigs/rgram.xml index b5e85906..82e8bea2 100644 --- a/DRAMSys/library/resources/configs/amconfigs/rgram.xml +++ b/DRAMSys/library/resources/configs/amconfigs/rgram.xml @@ -1,5 +1,4 @@ - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fifo.xml b/DRAMSys/library/resources/configs/mcconfigs/fifo.xml index d01b9248..fc05a577 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fifo.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fifo.xml @@ -34,13 +34,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml b/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml index ed869b57..1226d09a 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml @@ -1,5 +1,6 @@ + @@ -34,13 +35,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml b/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml index d01b9248..fc05a577 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml @@ -34,13 +34,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml index 20db08cd..35e118dc 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml @@ -1,5 +1,6 @@ + @@ -34,13 +35,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16.xml index 61221894..d92d32da 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16.xml @@ -33,13 +33,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16_close_page.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16_close_page.xml index ff37370c..d4aa4a4c 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16_close_page.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_bw_buffer16_close_page.xml @@ -33,13 +33,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_grp.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_grp.xml index dad77bf6..042cc5fb 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_grp.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_grp.xml @@ -34,13 +34,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16.xml index d6410aea..7cb5befd 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16.xml @@ -17,22 +17,6 @@ - - - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16_close_page.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16_close_page.xml index c8dd13c2..aa65b3ff 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16_close_page.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_nbw_buffer16_close_page.xml @@ -33,13 +33,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_rp.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_rp.xml index 3f636ba0..4c0b43c6 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_rp.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_rp.xml @@ -34,13 +34,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/grp.xml b/DRAMSys/library/resources/configs/mcconfigs/grp.xml index 753cca46..8b34759d 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/grp.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/grp.xml @@ -34,13 +34,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml b/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml index 478ec618..aaec39ca 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml @@ -34,13 +34,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/rgrmccfg.xml b/DRAMSys/library/resources/configs/mcconfigs/rgrmccfg.xml index b17e59ce..2f8fb337 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/rgrmccfg.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/rgrmccfg.xml @@ -33,13 +33,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/mcconfigs/sms.xml b/DRAMSys/library/resources/configs/mcconfigs/sms.xml index e1ccb478..3d9433da 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/sms.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/sms.xml @@ -34,13 +34,6 @@ - - - - - - - diff --git a/DRAMSys/library/resources/configs/memspecs/HBM2.xml b/DRAMSys/library/resources/configs/memspecs/HBM2.xml new file mode 100644 index 00000000..9760bfbf --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/HBM2.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_256Mb_WIDEIO-200_128bit.xml b/DRAMSys/library/resources/configs/memspecs/JEDEC_256Mb_WIDEIO-200_128bit.xml new file mode 100644 index 00000000..99fc35e7 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_256Mb_WIDEIO-200_128bit.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_256Mb_WIDEIO-266_128bit.xml b/DRAMSys/library/resources/configs/memspecs/JEDEC_256Mb_WIDEIO-266_128bit.xml new file mode 100644 index 00000000..62abc699 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_256Mb_WIDEIO-266_128bit.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.xml b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.xml new file mode 100644 index 00000000..d4801b92 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-2400_8bit_A.xml b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-2400_8bit_A.xml new file mode 100644 index 00000000..49b10280 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-2400_8bit_A.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_4x64_2Gb_WIDEIO2-400_64bit.xml b/DRAMSys/library/resources/configs/memspecs/JEDEC_4x64_2Gb_WIDEIO2-400_64bit.xml new file mode 100644 index 00000000..d2c14626 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_4x64_2Gb_WIDEIO2-400_64bit.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_4x64_2Gb_WIDEIO2-533_64bit.xml b/DRAMSys/library/resources/configs/memspecs/JEDEC_4x64_2Gb_WIDEIO2-533_64bit.xml new file mode 100644 index 00000000..901e0b21 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_4x64_2Gb_WIDEIO2-533_64bit.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_8Gb_LPDDR4-3200_16bit.xml b/DRAMSys/library/resources/configs/memspecs/JEDEC_8Gb_LPDDR4-3200_16bit.xml new file mode 100644 index 00000000..562e1e07 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_8Gb_LPDDR4-3200_16bit.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/MICRON_1Gb_DDR3-800_8bit_G.xml b/DRAMSys/library/resources/configs/memspecs/MICRON_1Gb_DDR3-800_8bit_G.xml new file mode 100644 index 00000000..262feb17 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/MICRON_1Gb_DDR3-800_8bit_G.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/MICRON_6Gb_LPDDR4-3200_32bit_A.xml b/DRAMSys/library/resources/configs/memspecs/MICRON_6Gb_LPDDR4-3200_32bit_A.xml new file mode 100644 index 00000000..506e20b7 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/MICRON_6Gb_LPDDR4-3200_32bit_A.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/memspecs/memspec_ranktest.xml b/DRAMSys/library/resources/configs/memspecs/memspec_ranktest.xml new file mode 100644 index 00000000..b4e43e4d --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/memspec_ranktest.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/simulator/ddr3.xml b/DRAMSys/library/resources/configs/simulator/ddr3.xml index 1613737f..276dde8e 100644 --- a/DRAMSys/library/resources/configs/simulator/ddr3.xml +++ b/DRAMSys/library/resources/configs/simulator/ddr3.xml @@ -2,8 +2,8 @@ - - + + diff --git a/DRAMSys/library/resources/configs/simulator/ddr4.xml b/DRAMSys/library/resources/configs/simulator/ddr4.xml new file mode 100644 index 00000000..8975c326 --- /dev/null +++ b/DRAMSys/library/resources/configs/simulator/ddr4.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/simulator/hbm2.xml b/DRAMSys/library/resources/configs/simulator/hbm2.xml new file mode 100644 index 00000000..3bf50046 --- /dev/null +++ b/DRAMSys/library/resources/configs/simulator/hbm2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/configs/simulator/lpddr4.xml b/DRAMSys/library/resources/configs/simulator/lpddr4.xml new file mode 100644 index 00000000..87b02763 --- /dev/null +++ b/DRAMSys/library/resources/configs/simulator/lpddr4.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/scripts/createTraceDB.sql b/DRAMSys/library/resources/scripts/createTraceDB.sql index 1ba6c3aa..7a127fac 100644 --- a/DRAMSys/library/resources/scripts/createTraceDB.sql +++ b/DRAMSys/library/resources/scripts/createTraceDB.sql @@ -1,5 +1,6 @@ DROP TABLE IF EXISTS Phases; DROP TABLE IF EXISTS GeneralInfo; +DROP TABLE IF EXISTS CommandLengths; DROP TABLE IF EXISTS Comments; DROP TABLE IF EXISTS ranges; DROP TABLE IF EXISTS Transactions; @@ -17,6 +18,7 @@ CREATE TABLE Phases( CREATE TABLE GeneralInfo( NumberOfTransactions INTEGER, TraceEnd INTEGER, + NumberOfRanks INTEGER, NumberOfBanks INTEGER, clk INTEGER, UnitOfTime TEXT, @@ -29,6 +31,24 @@ CREATE TABLE GeneralInfo( ControllerThread INTEGER ); +CREATE TABLE CommandLengths( + ACT INTEGER, + PRE INTEGER, + PREA INTEGER, + RD INTEGER, + RDA INTEGER, + WR INTEGER, + WRA INTEGER, + REFA INTEGER, + REFB INTEGER, + PDEA INTEGER, + PDXA INTEGER, + PDEP INTEGER, + PDXP INTEGER, + SREFEN INTEGER, + SREFEX INTEGER +); + CREATE TABLE Power( time DOUBLE, AveragePower DOUBLE @@ -58,8 +78,9 @@ CREATE TABLE Transactions( Burstlength INTEGER, TThread INTEGER, TChannel INTEGER, - TBank INTEGER, + TRank INTEGER, TBankgroup INTEGER, + TBank INTEGER, TRow INTEGER, TColumn INTEGER, DataStrobeBegin INTEGER, diff --git a/DRAMSys/library/resources/simulations/ddr4-example.xml b/DRAMSys/library/resources/simulations/ddr4-example.xml new file mode 100644 index 00000000..0d0606db --- /dev/null +++ b/DRAMSys/library/resources/simulations/ddr4-example.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + ddr3_example.stl + + diff --git a/DRAMSys/library/resources/simulations/hbm2-example.xml b/DRAMSys/library/resources/simulations/hbm2-example.xml new file mode 100644 index 00000000..2fac2e74 --- /dev/null +++ b/DRAMSys/library/resources/simulations/hbm2-example.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + ddr3_example.stl + + diff --git a/DRAMSys/library/resources/simulations/lpddr4-example.xml b/DRAMSys/library/resources/simulations/lpddr4-example.xml new file mode 100644 index 00000000..6f227578 --- /dev/null +++ b/DRAMSys/library/resources/simulations/lpddr4-example.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + ddr3_example.stl + + diff --git a/DRAMSys/library/resources/simulations/ranktest.xml b/DRAMSys/library/resources/simulations/ranktest.xml new file mode 100644 index 00000000..23de6d07 --- /dev/null +++ b/DRAMSys/library/resources/simulations/ranktest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + ranktest.stl + + diff --git a/DRAMSys/library/src/common/AddressDecoder.cpp b/DRAMSys/library/src/common/AddressDecoder.cpp index b0a3b98f..81ea1252 100644 --- a/DRAMSys/library/src/common/AddressDecoder.cpp +++ b/DRAMSys/library/src/common/AddressDecoder.cpp @@ -60,8 +60,3 @@ void AddressDecoder::createInstance(Type t) break; } } - -AddressDecoder::AddressDecoder() -{ - -} diff --git a/DRAMSys/library/src/common/AddressDecoder.h b/DRAMSys/library/src/common/AddressDecoder.h index d240088b..b49f6e81 100644 --- a/DRAMSys/library/src/common/AddressDecoder.h +++ b/DRAMSys/library/src/common/AddressDecoder.h @@ -71,7 +71,7 @@ public: }; protected: - AddressDecoder(); + AddressDecoder() {} static AddressDecoder *m_pInstance; public: @@ -80,12 +80,21 @@ public: virtual void setConfiguration(std::string url) = 0; - virtual DecodedAddress decodeAddress(sc_dt::uint64 addr) = 0; - virtual sc_dt::uint64 encodeAddress(DecodedAddress n) = 0; + virtual DecodedAddress decodeAddress(uint64_t addr) = 0; + virtual uint64_t encodeAddress(DecodedAddress n) = 0; virtual void print() = 0; - std::map amount; + struct Amount + { + unsigned channel = 1; + unsigned rank = 1; + unsigned bankgroup = 1; + unsigned bank = 1; + unsigned row = 1; + unsigned column = 1; + unsigned bytes = 1; + } amount; }; #endif // ADDRESSDECODER_H diff --git a/DRAMSys/library/src/common/CongenAddressDecoder.cpp b/DRAMSys/library/src/common/CongenAddressDecoder.cpp index ea11dcbc..fca1ea3b 100644 --- a/DRAMSys/library/src/common/CongenAddressDecoder.cpp +++ b/DRAMSys/library/src/common/CongenAddressDecoder.cpp @@ -188,14 +188,14 @@ void CongenAddressDecoder::setConfiguration(std::string url) } // Fill the amount map. This is copied from xmlAddressDecoder without further investigation - amount["channel"] = 1; - amount["bank"] = pow(2.0, m_vBankBits.size()); - amount["row"] = pow(2.0, m_vRowBits.size()); - amount["column"] = pow(2.0, m_vColumnBits.size()); - amount["bytes"] = pow(2.0, m_nByteBits); + amount.channel = 1; + amount.bank = pow(2.0, m_vBankBits.size()); + amount.row = pow(2.0, m_vRowBits.size()); + amount.column = pow(2.0, m_vColumnBits.size()); + amount.bytes = pow(2.0, m_nByteBits); } -DecodedAddress CongenAddressDecoder::decodeAddress(sc_dt::uint64 addr) +DecodedAddress CongenAddressDecoder::decodeAddress(uint64_t addr) { DecodedAddress result; @@ -251,9 +251,9 @@ DecodedAddress CongenAddressDecoder::decodeAddress(sc_dt::uint64 addr) return result; } -sc_dt::uint64 CongenAddressDecoder::encodeAddress(DecodedAddress n) +uint64_t CongenAddressDecoder::encodeAddress(DecodedAddress n) { - sc_dt::uint64 address = 0; + uint64_t address = 0; // Bank // it->first: position of the target bit in the DecodedAddress struct field diff --git a/DRAMSys/library/src/common/CongenAddressDecoder.h b/DRAMSys/library/src/common/CongenAddressDecoder.h index 51778ecf..ed523d9d 100644 --- a/DRAMSys/library/src/common/CongenAddressDecoder.h +++ b/DRAMSys/library/src/common/CongenAddressDecoder.h @@ -101,8 +101,8 @@ public: virtual void setConfiguration(std::string url); - virtual DecodedAddress decodeAddress(sc_dt::uint64 addr); - virtual sc_dt::uint64 encodeAddress(DecodedAddress n); + virtual DecodedAddress decodeAddress(uint64_t addr); + virtual uint64_t encodeAddress(DecodedAddress n); static bool testConfigFile(std::string url); diff --git a/DRAMSys/library/src/common/DebugManager.cpp b/DRAMSys/library/src/common/DebugManager.cpp index 51e2380e..ec50b87e 100644 --- a/DRAMSys/library/src/common/DebugManager.cpp +++ b/DRAMSys/library/src/common/DebugManager.cpp @@ -35,7 +35,10 @@ */ #include "DebugManager.h" -#include "../controller/core/configuration/Configuration.h" + +#ifdef DEBUGGING + +#include "../configuration/Configuration.h" using namespace std; void DebugManager::printDebugMessage(string sender, string message) @@ -65,7 +68,7 @@ void DebugManager::openDebugFile(string filename) } DebugManager::DebugManager() : - writeToConsole(true), writeToFile(true) + writeToConsole(false), writeToFile(false) { } @@ -76,3 +79,4 @@ DebugManager::~DebugManager() debugFile.close(); } } +#endif diff --git a/DRAMSys/library/src/common/DebugManager.h b/DRAMSys/library/src/common/DebugManager.h index dd35b796..ca3b1fec 100644 --- a/DRAMSys/library/src/common/DebugManager.h +++ b/DRAMSys/library/src/common/DebugManager.h @@ -37,6 +37,13 @@ #ifndef DEBUGMANAGER_H #define DEBUGMANAGER_H +//#define DEBUGGING + +#ifndef DEBUGGING +#define PRINTDEBUGMESSAGE(sender, message) {} +#else +#define PRINTDEBUGMESSAGE(sender, message) DebugManager::getInstance().printDebugMessage(sender, message) + #include #include #include @@ -62,5 +69,6 @@ private: ofstream debugFile; }; +#endif #endif // DEBUGMANAGER_H diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index c4b626fb..d917d47c 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -43,15 +43,13 @@ #include "protocol.h" #include "dramExtensions.h" #include "XmlAddressDecoder.h" -#include "../controller/core/configuration/Configuration.h" -#include "../controller/Controller.h" +#include "../configuration/Configuration.h" -using namespace std; +using namespace tlm; - -TlmRecorder::TlmRecorder(sc_module_name /*name*/, string uri, - string dbname) : sqlScriptURI(uri), dbName(dbname), totalNumTransactions(1), - simulationTimeCoveredByRecording(SC_ZERO_TIME) +TlmRecorder::TlmRecorder(std::string name, std::string uri, std::string dbname) : + name(name), sqlScriptURI(uri), dbName(dbname), + totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME) { recordedData.reserve(transactionCommitRate); setUpTransactionTerminatingPhases(); @@ -66,7 +64,7 @@ TlmRecorder::TlmRecorder(sc_module_name /*name*/, string uri, createTables(TlmRecorder::sqlScriptURI); prepareSqlStatements(); - printDebugMessage("Starting new database transaction"); + PRINTDEBUGMESSAGE(name, "Starting new database transaction"); } TlmRecorder::~TlmRecorder() @@ -79,6 +77,7 @@ TlmRecorder::~TlmRecorder() sqlite3_finalize(insertPhaseStatement); sqlite3_finalize(updatePhaseStatement); sqlite3_finalize(insertGeneralInfoStatement); + sqlite3_finalize(insertCommandLengthsStatement); sqlite3_finalize(insertDebugMessageStatement); sqlite3_finalize(updateDataStrobeStatement); sqlite3_finalize(insertPowerStatement); @@ -91,15 +90,15 @@ void TlmRecorder::recordPower(double timeInSeconds, double averagePower) executeSqlStatement(insertPowerStatement); } -void TlmRecorder::recordPhase(tlm::tlm_generic_payload &trans, - tlm::tlm_phase phase, sc_time time) +void TlmRecorder::recordPhase(tlm_generic_payload &trans, + tlm_phase phase, sc_time time) { if (currentTransactionsInSystem.count(&trans) == 0) introduceTransactionSystem(trans); - string phaseName = phaseNameToString(phase); - string phaseBeginPrefix = "BEGIN_"; - string phaseEndPrefix = "END_"; + std::string phaseName = phaseNameToString(phase); + std::string phaseBeginPrefix = "BEGIN_"; + std::string phaseEndPrefix = "END_"; if (phaseName.find(phaseBeginPrefix) != string::npos) { phaseName.erase(0, phaseBeginPrefix.length()); @@ -111,7 +110,7 @@ void TlmRecorder::recordPhase(tlm::tlm_generic_payload &trans, currentTransactionsInSystem[&trans].setPhaseEnd(phaseName, time); } - bool phaseTerminatesTransaction = count(transactionTerminatingPhases.begin(), + bool phaseTerminatesTransaction = std::count(transactionTerminatingPhases.begin(), transactionTerminatingPhases.end(), phase) == 1; if (phaseTerminatesTransaction) removeTransactionFromSystem(trans); @@ -121,7 +120,7 @@ void TlmRecorder::recordPhase(tlm::tlm_generic_payload &trans, void TlmRecorder::updateDataStrobe(const sc_time &begin, const sc_time &end, - tlm::tlm_generic_payload &trans) + tlm_generic_payload &trans) { assert(currentTransactionsInSystem.count(&trans) != 0); currentTransactionsInSystem[&trans].timeOnDataStrobe.start = begin; @@ -137,7 +136,7 @@ void TlmRecorder::recordDebugMessage(std::string message, sc_time time) // ------------- internal ----------------------- -void TlmRecorder::introduceTransactionSystem(tlm::tlm_generic_payload &trans) +void TlmRecorder::introduceTransactionSystem(tlm_generic_payload &trans) { unsigned int id = totalNumTransactions++; currentTransactionsInSystem[&trans].id = id; @@ -148,30 +147,28 @@ void TlmRecorder::introduceTransactionSystem(tlm::tlm_generic_payload &trans) currentTransactionsInSystem[&trans].dramExtension = DramExtension::getExtension( trans); - if (DramExtension::getExtension(trans).getThread().ID() == - Controller::ControllerThreadId()) + if (DramExtension::getExtension(trans).getThread().ID() == UINT_MAX) currentTransactionsInSystem[&trans].timeOfGeneration = SC_ZERO_TIME; else currentTransactionsInSystem[&trans].timeOfGeneration = GenerationExtension::getExtension(&trans).TimeOfGeneration(); - printDebugMessage("New transaction #" + to_string(id) + " generation time " + + PRINTDEBUGMESSAGE(name, "New transaction #" + to_string(id) + " generation time " + currentTransactionsInSystem[&trans].timeOfGeneration.to_string()); if (id % transactionCommitRate == 0) { - printDebugMessage( - "Committing transactions " + to_string(id - transactionCommitRate + 1) + " - " - + to_string(id)); + PRINTDEBUGMESSAGE(name, "Committing transactions " + + to_string(id - transactionCommitRate + 1) + " - " + to_string(id)); commitRecordedDataToDB(); } } -void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload &trans) +void TlmRecorder::removeTransactionFromSystem(tlm_generic_payload &trans) { assert(currentTransactionsInSystem.count(&trans) != 0); - printDebugMessage("Removing transaction #" + to_string( - currentTransactionsInSystem[&trans].id)); + PRINTDEBUGMESSAGE(name, "Removing transaction #" + + to_string(currentTransactionsInSystem[&trans].id)); Transaction &recordingData = currentTransactionsInSystem[&trans]; recordedData.push_back(recordingData); @@ -199,16 +196,16 @@ void TlmRecorder::commitRecordedDataToDB() } -void TlmRecorder::Transaction::insertPhase(string name, sc_time begin) +void TlmRecorder::Transaction::insertPhase(std::string name, sc_time begin) { recordedPhases.push_back(Phase(name, begin)); } -void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end) +void TlmRecorder::Transaction::setPhaseEnd(std::string name, sc_time end) { // Find the latest recorder phase for that transaction with a matching name and update it - // Note: Transaction have the same phase multiple times (e.g. PRE->ACT->REF->ACT->RD) only update the latest - // one that has been recorder + // Note: Transactions might have the same phase multiple times (e.g. PRE->ACT->REF->ACT->RD) + // only update the latest one that has been recorded for (int i = recordedPhases.size() - 1; i >= 0; i--) { Phase &data = recordedPhases[i]; if (data.name == name) { @@ -223,7 +220,7 @@ void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end) void TlmRecorder::openDB(std::string name) { - ifstream f(name.c_str()); + std::ifstream f(name.c_str()); if (f.good()) { if (remove(name.c_str()) != 0) { SC_REPORT_FATAL("TlmRecorder", "Error deleting file" ); @@ -237,49 +234,46 @@ void TlmRecorder::openDB(std::string name) } -void TlmRecorder::createTables(string pathToURI) +void TlmRecorder::createTables(std::string pathToURI) { - string initial = loadTextFileContents(pathToURI); + std::string initial = loadTextFileContents(pathToURI); executeSqlCommand(initial); } void TlmRecorder::setUpTransactionTerminatingPhases() { - transactionTerminatingPhases.push_back(tlm::END_RESP); + transactionTerminatingPhases.push_back(END_RESP); // Refresh All - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_REFA)); // Refresh Bank - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_REFB)); - transactionTerminatingPhases.push_back(static_cast - (END_ACTB)); - transactionTerminatingPhases.push_back(static_cast - (END_PREB)); // Phases for Power Down - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_PDNA)); - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_PDNP)); - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_SREF)); // Phases for Power Down Bankwise - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_PDNAB)); - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_PDNPB)); - transactionTerminatingPhases.push_back(static_cast + transactionTerminatingPhases.push_back(static_cast (END_SREFB)); } void TlmRecorder::prepareSqlStatements() { insertTransactionString = - "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:bankgroup,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)"; + "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:rank," + ":bankgroup,:bank,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)"; insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)"; updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id"; updateDataStrobeString = @@ -290,8 +284,12 @@ void TlmRecorder::prepareSqlStatements() updatePhaseString = "UPDATE Phases SET PhaseEnd = :end WHERE Transact = :trans AND PhaseName = :name"; insertGeneralInfoString = - "INSERT INTO GeneralInfo (NumberOfTransactions,TraceEnd,NumberOfBanks,clk,UnitOfTime,MCconfig,Memspec,Traces, WindowSize, FlexibleRefresh, MaxRefBurst, ControllerThread) VALUES" - "(:numberOfTransactions,:end,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec,:traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread)"; + "INSERT INTO GeneralInfo VALUES" + "(:numberOfTransactions,:end,:numberOfRanks,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec," + ":traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread)"; + insertCommandLengthsString = + "INSERT INTO CommandLengths VALUES" + "(:ACT, :PRE, :PREA, :RD, :RDA, :WR, :WRA, :REFA, :REFB, :PDEA, :PDXA, :PDEP, :PDXP, :SREFEN, :SREFEX)"; insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)"; insertPowerString = "INSERT INTO Power VALUES (:time,:averagePower)"; @@ -306,12 +304,14 @@ void TlmRecorder::prepareSqlStatements() &updateDataStrobeStatement, 0); sqlite3_prepare_v2(db, insertGeneralInfoString.c_str(), -1, &insertGeneralInfoStatement, 0); + sqlite3_prepare_v2(db, insertCommandLengthsString.c_str(), -1, + &insertCommandLengthsStatement, 0); sqlite3_prepare_v2(db, insertDebugMessageString.c_str(), -1, &insertDebugMessageStatement, 0); sqlite3_prepare_v2(db, insertPowerString.c_str(), -1, &insertPowerStatement, 0); } -void TlmRecorder::insertDebugMessageInDB(string message, const sc_time &time) +void TlmRecorder::insertDebugMessageInDB(std::string message, const sc_time &time) { sqlite3_bind_int64(insertDebugMessageStatement, 1, time.value()); sqlite3_bind_text(insertDebugMessageStatement, 2, message.c_str(), @@ -325,37 +325,61 @@ void TlmRecorder::insertGeneralInfo() sqlite3_bind_int64(insertGeneralInfoStatement, 2, simulationTimeCoveredByRecording.value()); sqlite3_bind_int(insertGeneralInfoStatement, 3, - Configuration::getInstance().memSpec->NumberOfBanks); + Configuration::getInstance().memSpec->NumberOfRanks); sqlite3_bind_int(insertGeneralInfoStatement, 4, + Configuration::getInstance().memSpec->NumberOfBanks); + sqlite3_bind_int(insertGeneralInfoStatement, 5, Configuration::getInstance().memSpec->clk.value()); - sqlite3_bind_text(insertGeneralInfoStatement, 5, "PS", 2, NULL); - sqlite3_bind_text(insertGeneralInfoStatement, 6, mcconfig.c_str(), + sqlite3_bind_text(insertGeneralInfoStatement, 6, "PS", 2, NULL); + sqlite3_bind_text(insertGeneralInfoStatement, 7, mcconfig.c_str(), mcconfig.length(), NULL); - sqlite3_bind_text(insertGeneralInfoStatement, 7, memspec.c_str(), + sqlite3_bind_text(insertGeneralInfoStatement, 8, memspec.c_str(), memspec.length(), NULL); - sqlite3_bind_text(insertGeneralInfoStatement, 8, traces.c_str(), + sqlite3_bind_text(insertGeneralInfoStatement, 9, traces.c_str(), traces.length(), NULL); if (!Configuration::getInstance().EnableWindowing) - sqlite3_bind_int64(insertGeneralInfoStatement, 9, 0); + sqlite3_bind_int64(insertGeneralInfoStatement, 10, 0); else - sqlite3_bind_int64(insertGeneralInfoStatement, 9, + sqlite3_bind_int64(insertGeneralInfoStatement, 10, (Configuration::getInstance().memSpec->clk * Configuration::getInstance().WindowSize).value()); if (Configuration::getInstance().ControllerCoreRefEnablePostpone || Configuration::getInstance().ControllerCoreRefEnablePullIn) { - sqlite3_bind_int(insertGeneralInfoStatement, 10, 1); - sqlite3_bind_int(insertGeneralInfoStatement, 11, + sqlite3_bind_int(insertGeneralInfoStatement, 11, 1); + sqlite3_bind_int(insertGeneralInfoStatement, 12, std::max(Configuration::getInstance().ControllerCoreRefMaxPulledIn, Configuration::getInstance().ControllerCoreRefMaxPostponed)); } else { - sqlite3_bind_int(insertGeneralInfoStatement, 10, 0); sqlite3_bind_int(insertGeneralInfoStatement, 11, 0); + sqlite3_bind_int(insertGeneralInfoStatement, 12, 0); } - sqlite3_bind_int(insertGeneralInfoStatement, 12, - Controller::ControllerThreadId()); ; + sqlite3_bind_int(insertGeneralInfoStatement, 13, UINT_MAX); executeSqlStatement(insertGeneralInfoStatement); } +void TlmRecorder::insertCommandLengths() +{ + MemSpec *memSpec = Configuration::getInstance().memSpec; + + sqlite3_bind_int(insertCommandLengthsStatement, 1, memSpec->commandLength[Command::ACT]); + sqlite3_bind_int(insertCommandLengthsStatement, 2, memSpec->commandLength[Command::PRE]); + sqlite3_bind_int(insertCommandLengthsStatement, 3, memSpec->commandLength[Command::PREA]); + sqlite3_bind_int(insertCommandLengthsStatement, 4, memSpec->commandLength[Command::RD]); + sqlite3_bind_int(insertCommandLengthsStatement, 5, memSpec->commandLength[Command::RDA]); + sqlite3_bind_int(insertCommandLengthsStatement, 6, memSpec->commandLength[Command::WR]); + sqlite3_bind_int(insertCommandLengthsStatement, 7, memSpec->commandLength[Command::WRA]); + sqlite3_bind_int(insertCommandLengthsStatement, 8, memSpec->commandLength[Command::REFA]); + sqlite3_bind_int(insertCommandLengthsStatement, 9, memSpec->commandLength[Command::REFB]); + sqlite3_bind_int(insertCommandLengthsStatement, 10, memSpec->commandLength[Command::PDEA]); + sqlite3_bind_int(insertCommandLengthsStatement, 11, memSpec->commandLength[Command::PDXA]); + sqlite3_bind_int(insertCommandLengthsStatement, 12, memSpec->commandLength[Command::PDEP]); + sqlite3_bind_int(insertCommandLengthsStatement, 13, memSpec->commandLength[Command::PDXP]); + sqlite3_bind_int(insertCommandLengthsStatement, 14, memSpec->commandLength[Command::SREFEN]); + sqlite3_bind_int(insertCommandLengthsStatement, 15, memSpec->commandLength[Command::SREFEX]); + + executeSqlStatement(insertCommandLengthsStatement); +} + void TlmRecorder::insertTransactionInDB(Transaction &recordingData) { sqlite3_bind_int(insertTransactionStatement, 1, recordingData.id); @@ -367,20 +391,22 @@ void TlmRecorder::insertTransactionInDB(Transaction &recordingData) sqlite3_bind_int(insertTransactionStatement, 6, recordingData.dramExtension.getChannel().ID()); sqlite3_bind_int(insertTransactionStatement, 7, - recordingData.dramExtension.getBank().ID()); + recordingData.dramExtension.getRank().ID()); sqlite3_bind_int(insertTransactionStatement, 8, recordingData.dramExtension.getBankGroup().ID()); sqlite3_bind_int(insertTransactionStatement, 9, - recordingData.dramExtension.getRow().ID()); + recordingData.dramExtension.getBank().ID()); sqlite3_bind_int(insertTransactionStatement, 10, + recordingData.dramExtension.getRow().ID()); + sqlite3_bind_int(insertTransactionStatement, 11, recordingData.dramExtension.getColumn().ID()); - sqlite3_bind_int64(insertTransactionStatement, 11, - recordingData.timeOnDataStrobe.start.value()); sqlite3_bind_int64(insertTransactionStatement, 12, - recordingData.timeOnDataStrobe.end.value()); + recordingData.timeOnDataStrobe.start.value()); sqlite3_bind_int64(insertTransactionStatement, 13, + recordingData.timeOnDataStrobe.end.value()); + sqlite3_bind_int64(insertTransactionStatement, 14, recordingData.timeOfGeneration.value()); - sqlite3_bind_text(insertTransactionStatement, 14, + sqlite3_bind_text(insertTransactionStatement, 15, recordingData.cmd.c_str(), recordingData.cmd.length(), NULL); executeSqlStatement(insertTransactionStatement); @@ -395,7 +421,7 @@ void TlmRecorder::insertRangeInDB(unsigned int id, const sc_time &begin, sqlite3_bind_int64(insertRangeStatement, 3, end.value()); executeSqlStatement(insertRangeStatement); } -void TlmRecorder::insertPhaseInDB(string phaseName, const sc_time &begin, +void TlmRecorder::insertPhaseInDB(std::string phaseName, const sc_time &begin, const sc_time &end, unsigned int transactionID) { @@ -418,9 +444,9 @@ void TlmRecorder::executeSqlStatement(sqlite3_stmt *statement) sqlite3_reset(statement); } -void TlmRecorder::executeSqlCommand(string command) +void TlmRecorder::executeSqlCommand(std::string command) { - printDebugMessage("Creating database by running provided sql script"); + PRINTDEBUGMESSAGE(name, "Creating database by running provided sql script"); char *errMsg = 0; int rc = sqlite3_exec(db, command.c_str(), NULL, 0, &errMsg); @@ -429,22 +455,17 @@ void TlmRecorder::executeSqlCommand(string command) sqlite3_free(errMsg); } - printDebugMessage("Database created successfully"); -} - -void TlmRecorder::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); + PRINTDEBUGMESSAGE(name, "Database created successfully"); } void TlmRecorder::closeConnection() { commitRecordedDataToDB(); insertGeneralInfo(); - printDebugMessage( - "Number of transactions written to DB: " + std::to_string( - totalNumTransactions - 1)); - printDebugMessage("tlmPhaseRecorder:\tEnd Recording"); + insertCommandLengths(); + PRINTDEBUGMESSAGE(name, "Number of transactions written to DB: " + + std::to_string(totalNumTransactions - 1)); + PRINTDEBUGMESSAGE(name, "tlmPhaseRecorder:\tEnd Recording"); sqlite3_close(db); db = NULL; } diff --git a/DRAMSys/library/src/common/TlmRecorder.h b/DRAMSys/library/src/common/TlmRecorder.h index 683988a9..9c6e75e3 100644 --- a/DRAMSys/library/src/common/TlmRecorder.h +++ b/DRAMSys/library/src/common/TlmRecorder.h @@ -53,40 +53,39 @@ #include "DebugManager.h" #include "utils.h" -using namespace std; +using namespace tlm; -class TlmRecorder : public sc_module +class TlmRecorder { public: std::string sqlScriptURI; std::string dbName; - TlmRecorder(sc_module_name /*name*/, string uri, string dbname); + TlmRecorder(std::string name, std::string uri, std::string dbname); ~TlmRecorder(); - void recordMCconfig(string mcconfig) + void recordMCconfig(std::string mcconfig) { this->mcconfig = mcconfig; } - void recordMemspec(string memspec) + void recordMemspec(std::string memspec) { this->memspec = memspec; } - void recordTracenames(string traces) + void recordTracenames(std::string traces) { this->traces = traces; } - void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, + void recordPhase(tlm_generic_payload &trans, tlm_phase phase, sc_time time); void recordPower(double timeInSeconds, double averagePower); void recordDebugMessage(std::string message, sc_time time); void updateDataStrobe(const sc_time &begin, const sc_time &end, - tlm::tlm_generic_payload &trans); + tlm_generic_payload &trans); void closeConnection(); private: - struct Transaction { Transaction() {} Transaction(unsigned int id): id(id) {} @@ -100,16 +99,18 @@ private: TimeInterval timeOnDataStrobe; struct Phase { - Phase(string name, sc_time begin): name(name), interval(begin, SC_ZERO_TIME) {} - string name; + Phase(std::string name, sc_time begin): name(name), interval(begin, SC_ZERO_TIME) {} + std::string name; TimeInterval interval; }; std::vector recordedPhases; - void insertPhase(string name, sc_time begin); - void setPhaseEnd(string name, sc_time end); + void insertPhase(std::string name, sc_time begin); + void setPhaseEnd(std::string name, sc_time end); }; + std::string name; + std::string mcconfig, memspec, traces; void prepareSqlStatements(); @@ -120,35 +121,34 @@ private: void createTables(std::string pathToURI); void setUpTransactionTerminatingPhases(); - void introduceTransactionSystem(tlm::tlm_generic_payload &trans); - void removeTransactionFromSystem(tlm::tlm_generic_payload &trans); + void introduceTransactionSystem(tlm_generic_payload &trans); + void removeTransactionFromSystem(tlm_generic_payload &trans); void commitRecordedDataToDB(); void insertGeneralInfo(); + void insertCommandLengths(); void insertTransactionInDB(Transaction &recordingData); void insertRangeInDB(unsigned int id, const sc_time &begin, const sc_time &end); - void insertPhaseInDB(string phaseName, const sc_time &begin, const sc_time &end, + void insertPhaseInDB(std::string phaseName, const sc_time &begin, const sc_time &end, unsigned int transactionID); - void insertDebugMessageInDB(string message, const sc_time &time); - - void printDebugMessage(std::string message); + void insertDebugMessageInDB(std::string message, const sc_time &time); static const int transactionCommitRate = 1000; - vector recordedData; - map currentTransactionsInSystem; + std::vector recordedData; + std::map currentTransactionsInSystem; unsigned int totalNumTransactions; sc_time simulationTimeCoveredByRecording; - std::vector transactionTerminatingPhases; + std::vector transactionTerminatingPhases; sqlite3 *db = NULL; sqlite3_stmt *insertTransactionStatement, *insertRangeStatement, - *updateRangeStatement, - *insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, + *updateRangeStatement, *insertPhaseStatement, *updatePhaseStatement, + *insertGeneralInfoStatement, *insertCommandLengthsStatement, *insertDebugMessageStatement, *updateDataStrobeStatement, *insertPowerStatement; - std::string insertTransactionString, insertRangeString, updateRangeString, - insertPhaseString, updatePhaseString, insertGeneralInfoString, - insertDebugMessageString, updateDataStrobeString, insertPowerString; + std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, + updatePhaseString, insertGeneralInfoString, insertCommandLengthsString, + insertDebugMessageString, updateDataStrobeString, insertPowerString; }; #endif // TLMRECORDER_H diff --git a/DRAMSys/library/src/common/XmlAddressDecoder.cpp b/DRAMSys/library/src/common/XmlAddressDecoder.cpp index dfbb4dd8..0dcc2d5d 100644 --- a/DRAMSys/library/src/common/XmlAddressDecoder.cpp +++ b/DRAMSys/library/src/common/XmlAddressDecoder.cpp @@ -39,9 +39,8 @@ #include #include "utils.h" #include "bitset" -#include "../controller/core/configuration/Configuration.h" +#include "../configuration/Configuration.h" -using namespace std; using namespace tinyxml2; XmlAddressDecoder::XmlAddressDecoder() @@ -56,51 +55,110 @@ void XmlAddressDecoder::setConfiguration(std::string addressConfigURI) tinyxml2::XMLElement *addressMap = doc.RootElement(); string xmlNodeName(addressMap->Name()); - if ( xmlNodeName != "addressmapping") { + if (xmlNodeName != "addressmapping") reportFatal("AddressDecorder", "addressmap node expected"); - } for (XMLElement *child = addressMap->FirstChildElement(); - child != NULL; - child = child->NextSiblingElement()) { - int from; - int to; + child != NULL; child = child->NextSiblingElement()) + { + unsigned from; + unsigned to; child->QueryAttribute("from", &from); child->QueryAttribute("to", &to); - shifts[child->Name()] = from; - masks[child->Name()] = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); - amount[child->Name()] = pow(2.0, to - from + 1.0); + if (std::strcmp(child->Name(), "channel") == 0) + { + shifts.channel = from; + masks.channel = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); + amount.channel = pow(2.0, to - from + 1.0); + } + else if (std::strcmp(child->Name(), "rank") == 0) + { + shifts.rank = from; + masks.rank = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); + amount.rank = pow(2.0, to - from + 1.0); + } + else if (std::strcmp(child->Name(), "bankgroup") == 0) + { + shifts.bankgroup = from; + masks.bankgroup = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); + amount.bankgroup = pow(2.0, to - from + 1.0); + } + else if (std::strcmp(child->Name(), "bank") == 0) + { + shifts.bank = from; + masks.bank = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); + amount.bank = pow(2.0, to - from + 1.0); + } + else if (std::strcmp(child->Name(), "row") == 0) + { + shifts.row = from; + masks.row = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); + amount.row = pow(2.0, to - from + 1.0); + } + else if (std::strcmp(child->Name(), "column") == 0) + { + shifts.column = from; + masks.column = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); + amount.column = pow(2.0, to - from + 1.0); + } + else if (std::strcmp(child->Name(), "bytes") == 0) + { + shifts.bytes = from; + masks.bytes = pow(2.0, to + 1.0) - pow(2.0, from + 0.0); + amount.bytes = pow(2.0, to - from + 1.0); + } + else + SC_REPORT_FATAL("XmlAddressDecoder", ("Unknown field " + std::string(child->Name())).c_str()); } + + banksPerGroup = amount.bank; + amount.bank = banksPerGroup * amount.bankgroup * amount.rank; + + bankgroupsPerRank = amount.bankgroup; + amount.bankgroup = bankgroupsPerRank * amount.rank; + + maximumAddress = amount.bytes * amount.column * amount.row * banksPerGroup * bankgroupsPerRank * amount.rank * amount.channel - 1; + + Configuration &config = Configuration::getInstance(); + MemSpec *memSpec = config.memSpec; + + if (config.NumberOfMemChannels != amount.channel || memSpec->NumberOfRanks != amount.rank + || memSpec->NumberOfBankGroups != amount.bankgroup || memSpec->NumberOfBanks != amount.bank + || memSpec->NumberOfRows != amount.row || memSpec->NumberOfColumns != amount.column + || config.NumberOfDevicesOnDIMM * memSpec->bitWidth != amount.bytes * 8) + SC_REPORT_FATAL("XmlAddressDecoder", "Memspec and addressmapping do not match"); } -DecodedAddress XmlAddressDecoder::decodeAddress(sc_dt::uint64 addr) +DecodedAddress XmlAddressDecoder::decodeAddress(uint64_t addr) { + if (addr > maximumAddress) + SC_REPORT_WARNING("XmlAddressDecoder", ("Address " + std::to_string(addr) + " out of range (maximum address is " + std::to_string(maximumAddress) + ")").c_str()); + DecodedAddress result; - result.channel = (addr & masks["channel"]) >> shifts["channel"]; - //result.rank = (addr & masks["rank"]) >> shifts["rank"]; - //result.bankgroup = (addr & masks["bankgroup"]) >> shifts["bankgroup"]; - result.bank = (addr & masks["bank"]) >> shifts["bank"]; - result.bankgroup = result.bank % - Configuration::getInstance().memSpec->NumberOfBankGroups; - result.rank = result.bank % Configuration::getInstance().memSpec->NumberOfRanks; - result.row = (addr & masks["row"]) >> shifts["row"]; - result.column = (addr & masks["column"]) >> shifts["column"]; - result.bytes = (addr & masks["bytes"]) >> shifts["bytes"]; + result.channel = (addr & masks.channel) >> shifts.channel; + result.rank = (addr & masks.rank) >> shifts.rank; + result.bankgroup = ((addr & masks.bankgroup) >> shifts.bankgroup) + + result.rank * bankgroupsPerRank; + result.bank = ((addr & masks.bank) >> shifts.bank) + + result.bankgroup * banksPerGroup; + result.row = (addr & masks.row) >> shifts.row; + result.column = (addr & masks.column) >> shifts.column; + result.bytes = (addr & masks.bytes) >> shifts.bytes; return result; } -sc_dt::uint64 XmlAddressDecoder::encodeAddress(DecodedAddress n) +uint64_t XmlAddressDecoder::encodeAddress(DecodedAddress n) { - return n.channel << shifts["channel"] | - n.rank << shifts["rank"] | - n.bankgroup << shifts["bankgroup"] | - n.row << shifts["row"] | - n.bank << shifts["bank"] | - n.column << shifts["column"] | - n.bytes << shifts["bytes"]; + return (n.channel << shifts.channel) | + (n.rank << shifts.rank) | + ((n.bankgroup % bankgroupsPerRank) << shifts.bankgroup) | + ((n.bank % banksPerGroup) << shifts.bank) | + (n.row << shifts.row) | + (n.column << shifts.column) | + (n.bytes << shifts.bytes); } bool XmlAddressDecoder::testConfigFile(std::string url) @@ -117,10 +175,14 @@ bool XmlAddressDecoder::testConfigFile(std::string url) void XmlAddressDecoder::print() { - cout << headline << endl; - cout << "Address Mapping:" << endl << endl; - for (auto &pair : masks) { - cout << std::setw(16) << pair.first << ": " << bitset<48>(pair.second) << endl; - } - cout << endl; + std::cout << headline << std::endl; + std::cout << "Address Mapping:" << std::endl << std::endl; + std::cout << " channel: " << std::bitset<64>(masks.channel) << std::endl; + std::cout << " rank: " << std::bitset<64>(masks.rank) << std::endl; + std::cout << " bankgroup: " << std::bitset<64>(masks.bankgroup) << std::endl; + std::cout << " bank: " << std::bitset<64>(masks.bank) << std::endl; + std::cout << " row: " << std::bitset<64>(masks.row) << std::endl; + std::cout << " column: " << std::bitset<64>(masks.column) << std::endl; + std::cout << " bytes: " << std::bitset<64>(masks.bytes) << std::endl; + std::cout << std::endl; } diff --git a/DRAMSys/library/src/common/XmlAddressDecoder.h b/DRAMSys/library/src/common/XmlAddressDecoder.h index dfd65072..21befb9f 100644 --- a/DRAMSys/library/src/common/XmlAddressDecoder.h +++ b/DRAMSys/library/src/common/XmlAddressDecoder.h @@ -51,16 +51,40 @@ class XmlAddressDecoder : private AddressDecoder friend class AddressDecoder; private: - std::map masks; - std::map shifts; + struct Masks + { + uint64_t channel = 0; + uint64_t rank = 0; + uint64_t bankgroup = 0; + uint64_t bank = 0; + uint64_t row = 0; + uint64_t column = 0; + uint64_t bytes = 0; + } masks; + + struct Shifts + { + unsigned channel = 0; + unsigned rank = 0; + unsigned bankgroup = 0; + unsigned bank = 0; + unsigned row = 0; + unsigned column = 0; + unsigned bytes = 0; + } shifts; + + unsigned banksPerGroup; + unsigned banksPerRank; + unsigned bankgroupsPerRank; tinyxml2::XMLElement *addressmapping; + uint64_t maximumAddress; public: XmlAddressDecoder(); - virtual DecodedAddress decodeAddress(sc_dt::uint64 addr); - virtual sc_dt::uint64 encodeAddress(DecodedAddress n); + virtual DecodedAddress decodeAddress(uint64_t addr); + virtual uint64_t encodeAddress(DecodedAddress n); void setConfiguration(std::string url); diff --git a/DRAMSys/library/src/common/dramExtensions.cpp b/DRAMSys/library/src/common/dramExtensions.cpp index ed1d0b0d..d49666bf 100644 --- a/DRAMSys/library/src/common/dramExtensions.cpp +++ b/DRAMSys/library/src/common/dramExtensions.cpp @@ -36,33 +36,27 @@ */ #include "dramExtensions.h" -#include "../controller/core/configuration/Configuration.h" +#include "../configuration/Configuration.h" #include "map" #include "utils.h" using namespace tlm; - DramExtension::DramExtension() : - thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0) -{ -} + thread(0), channel(0), rank(0), bankgroup(0), bank(0), + row(0), column(0), burstlength(0), payloadID(0) {} -DramExtension::DramExtension(const Thread &thread, const Bank &bank, - const BankGroup &bankgroup, const Row &row, const Column &column, - unsigned int burstlength) : - thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), - column(column), burstlength(burstlength) -{ -} +DramExtension::DramExtension(const Thread &thread, const Rank &rank, const BankGroup &bankgroup, + const Bank &bank, const Row &row, const Column &column, + unsigned int burstlength, uint64_t payloadID) : + thread(thread), channel(0), rank(rank), bankgroup(bankgroup), bank(bank), + row(row), column(column), burstlength(burstlength), payloadID(payloadID) {} -DramExtension::DramExtension(const Thread &thread, const Channel &channel, - const Bank &bank, const BankGroup &bankgroup, const Row &row, - const Column &column, unsigned int burstlength) : - thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), - column(column), burstlength(burstlength) -{ -} +DramExtension::DramExtension(const Thread &thread, const Channel &channel, const Rank &rank, + const BankGroup &bankgroup, const Bank &bank, const Row &row, + const Column &column, unsigned int burstlength, uint64_t payloadID) : + thread(thread), channel(channel), rank(rank), bankgroup(bankgroup), bank(bank), + row(row), column(column), burstlength(burstlength), payloadID(payloadID) {} DramExtension &DramExtension::getExtension(const tlm_generic_payload *payload) { @@ -78,14 +72,14 @@ DramExtension &DramExtension::getExtension(const tlm_generic_payload &payload) return DramExtension::getExtension(&payload); } -Bank DramExtension::getBank(const tlm_generic_payload *payload) +Thread DramExtension::getThread(const tlm_generic_payload *payload) { - return DramExtension::getExtension(payload).getBank(); + return DramExtension::getExtension(payload).getThread(); } -Bank DramExtension::getBank(const tlm_generic_payload &payload) +Thread DramExtension::getThread(const tlm_generic_payload &payload) { - return DramExtension::getBank(&payload); + return DramExtension::getThread(&payload); } Channel DramExtension::getChannel(const tlm_generic_payload *payload) @@ -98,14 +92,34 @@ Channel DramExtension::getChannel(const tlm_generic_payload &payload) return DramExtension::getChannel(&payload); } -Thread DramExtension::getThread(const tlm_generic_payload *payload) +Rank DramExtension::getRank(const tlm_generic_payload *payload) { - return DramExtension::getExtension(payload).getThread(); + return DramExtension::getExtension(payload).getRank(); } -Thread DramExtension::getThread(const tlm_generic_payload &payload) +Rank DramExtension::getRank(const tlm_generic_payload &payload) { - return DramExtension::getThread(&payload); + return DramExtension::getRank(&payload); +} + +BankGroup DramExtension::getBankGroup(const tlm_generic_payload *payload) +{ + return DramExtension::getExtension(payload).getBankGroup(); +} + +BankGroup DramExtension::getBankGroup(const tlm_generic_payload &payload) +{ + return DramExtension::getBankGroup(&payload); +} + +Bank DramExtension::getBank(const tlm_generic_payload *payload) +{ + return DramExtension::getExtension(payload).getBank(); +} + +Bank DramExtension::getBank(const tlm_generic_payload &payload) +{ + return DramExtension::getBank(&payload); } Row DramExtension::getRow(const tlm_generic_payload *payload) @@ -118,18 +132,39 @@ Row DramExtension::getRow(const tlm_generic_payload &payload) return DramExtension::getRow(&payload); } +Column DramExtension::getColumn(const tlm_generic_payload *payload) +{ + return DramExtension::getExtension(payload).getColumn(); +} + +Column DramExtension::getColumn(const tlm_generic_payload &payload) +{ + return DramExtension::getColumn(&payload); +} + +uint64_t DramExtension::getPayloadID(const tlm_generic_payload *payload) +{ + return DramExtension::getExtension(payload).getPayloadID(); +} + +uint64_t DramExtension::getPayloadID(const tlm_generic_payload &payload) +{ + return DramExtension::getPayloadID(&payload); +} tlm_extension_base *DramExtension::clone() const { - return new DramExtension(thread, bank, bankgroup, row, column, burstlength); + return new DramExtension(thread, channel, rank, bankgroup, bank, row, column, burstlength, payloadID); } void DramExtension::copy_from(const tlm_extension_base &ext) { const DramExtension &cpyFrom = static_cast(ext); thread = cpyFrom.thread; - bank = cpyFrom.bank; + channel = cpyFrom.channel; + rank = cpyFrom.rank; bankgroup = cpyFrom.bankgroup; + bank = cpyFrom.bank; row = cpyFrom.row; column = cpyFrom.column; burstlength = cpyFrom.burstlength; @@ -145,9 +180,9 @@ Channel DramExtension::getChannel() const return channel; } -Bank DramExtension::getBank() const +Rank DramExtension::getRank() const { - return bank; + return rank; } BankGroup DramExtension::getBankGroup() const @@ -155,6 +190,11 @@ BankGroup DramExtension::getBankGroup() const return bankgroup; } +Bank DramExtension::getBank() const +{ + return bank; +} + Row DramExtension::getRow() const { return row; @@ -170,6 +210,11 @@ unsigned int DramExtension::getBurstlength() const return burstlength; } +uint64_t DramExtension::getPayloadID() const +{ + return payloadID; +} + void DramExtension::incrementRow() { ++row; @@ -182,14 +227,12 @@ tlm_extension_base *GenerationExtension::clone() const void GenerationExtension::copy_from(const tlm_extension_base &ext) { - const GenerationExtension &cpyFrom = static_cast - (ext); + const GenerationExtension &cpyFrom = static_cast(ext); timeOfGeneration = cpyFrom.timeOfGeneration; } -GenerationExtension &GenerationExtension::getExtension(const - tlm::tlm_generic_payload *payload) +GenerationExtension &GenerationExtension::getExtension(const tlm_generic_payload *payload) { GenerationExtension *result = NULL; payload->get_extension(result); @@ -197,14 +240,12 @@ GenerationExtension &GenerationExtension::getExtension(const return *result; } -sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload - *payload) +sc_time GenerationExtension::getTimeOfGeneration(const tlm_generic_payload *payload) { return GenerationExtension::getExtension(payload).TimeOfGeneration(); } -sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload - &payload) +sc_time GenerationExtension::getTimeOfGeneration(const tlm_generic_payload &payload) { return GenerationExtension::getTimeOfGeneration(&payload); } @@ -236,6 +277,16 @@ bool operator !=(const Channel &lhs, const Channel &rhs) return !(lhs == rhs); } +//RANK +bool operator ==(const Rank &lhs, const Rank &rhs) +{ + return lhs.ID() == rhs.ID(); +} + +bool operator !=(const Rank &lhs, const Rank &rhs) +{ + return !(lhs == rhs); +} //BANKGROUP bool operator ==(const BankGroup &lhs, const BankGroup &rhs) diff --git a/DRAMSys/library/src/common/dramExtensions.h b/DRAMSys/library/src/common/dramExtensions.h index 3a4b1a51..0bb74af1 100644 --- a/DRAMSys/library/src/common/dramExtensions.h +++ b/DRAMSys/library/src/common/dramExtensions.h @@ -41,6 +41,8 @@ #include #include +using namespace tlm; + class Thread { public: @@ -69,6 +71,20 @@ private: unsigned int id; }; +class Rank +{ +public: + explicit Rank(unsigned int id) : id(id) {} + + unsigned int ID() const + { + return id; + } + +private: + unsigned int id; +}; + class BankGroup { public: @@ -145,72 +161,84 @@ private: }; -class DramExtension : public tlm::tlm_extension +class DramExtension : public tlm_extension { public: DramExtension(); - DramExtension(const Thread &thread, const Bank &bank, - const BankGroup &bankgroup, const Row &row, const Column &column, - unsigned int burstlength = 0); - DramExtension(const Thread &thread, const Channel &channel, const Bank &bank, - const BankGroup &bankgroup, const Row &row, - const Column &column, unsigned int burstlength = 0); + DramExtension(const Thread &thread, const Rank &rank, const BankGroup &bankgroup, + const Bank &bank, const Row &row, const Column &column, + unsigned int burstlength, uint64_t payloadID); + DramExtension(const Thread &thread, const Channel &channel, const Rank &rank, + const BankGroup &bankgroup, const Bank &bank, const Row &row, + const Column &column, unsigned int burstlength, uint64_t payloadID); virtual tlm_extension_base *clone() const; virtual void copy_from(const tlm_extension_base &ext); - static DramExtension &getExtension(const tlm::tlm_generic_payload *payload); - static DramExtension &getExtension(const tlm::tlm_generic_payload &payload); + static DramExtension &getExtension(const tlm_generic_payload *payload); + static DramExtension &getExtension(const tlm_generic_payload &payload); // Used for convience, caller could also use getExtension(..) to access these field - static Bank getBank(const tlm::tlm_generic_payload *payload); - static Bank getBank(const tlm::tlm_generic_payload &payload); - static Channel getChannel(const tlm::tlm_generic_payload *payload); - static Channel getChannel(const tlm::tlm_generic_payload &payload); - static Thread getThread(const tlm::tlm_generic_payload *payload); - static Thread getThread(const tlm::tlm_generic_payload &payload); - static Row getRow(const tlm::tlm_generic_payload *payload); - static Row getRow(const tlm::tlm_generic_payload &payload); + static Thread getThread(const tlm_generic_payload *payload); + static Thread getThread(const tlm_generic_payload &payload); + static Channel getChannel(const tlm_generic_payload *payload); + static Channel getChannel(const tlm_generic_payload &payload); + static Rank getRank(const tlm_generic_payload *payload); + static Rank getRank(const tlm_generic_payload &payload); + static BankGroup getBankGroup(const tlm_generic_payload *payload); + static BankGroup getBankGroup(const tlm_generic_payload &payload); + static Bank getBank(const tlm_generic_payload *payload); + static Bank getBank(const tlm_generic_payload &payload); + static Row getRow(const tlm_generic_payload *payload); + static Row getRow(const tlm_generic_payload &payload); + static Column getColumn(const tlm_generic_payload *payload); + static Column getColumn(const tlm_generic_payload &payload); + static uint64_t getPayloadID(const tlm_generic_payload *payload); + static uint64_t getPayloadID(const tlm_generic_payload &payload); Thread getThread() const; Channel getChannel() const; - Bank getBank() const; + Rank getRank() const; BankGroup getBankGroup() const; + Bank getBank() const; Row getRow() const; Column getColumn() const; unsigned int getBurstlength() const; + uint64_t getPayloadID() const; void incrementRow(); private: Thread thread; Channel channel; - Bank bank; + Rank rank; BankGroup bankgroup; + Bank bank; Row row; Column column; unsigned int burstlength; + uint64_t payloadID; }; // Used to indicate the time when a payload is created (in a traceplayer or in a core) // Note that this time can be different from the time the payload enters the DRAM system //(at that time the phase BEGIN_REQ is recorded), so timeOfGeneration =< time(BEGIN_REQ) -class GenerationExtension : public tlm::tlm_extension +class GenerationExtension : public tlm_extension { public: - GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration( - timeOfGeneration) {} + GenerationExtension(sc_time timeOfGeneration) + : timeOfGeneration(timeOfGeneration) {} virtual tlm_extension_base *clone() const; virtual void copy_from(const tlm_extension_base &ext); - static GenerationExtension &getExtension(const tlm::tlm_generic_payload - *payload); + static GenerationExtension + &getExtension(const tlm_generic_payload *payload); sc_time TimeOfGeneration() const { return timeOfGeneration; } - static sc_time getTimeOfGeneration(const tlm::tlm_generic_payload *payload); - static sc_time getTimeOfGeneration(const tlm::tlm_generic_payload &payload); + static sc_time getTimeOfGeneration(const tlm_generic_payload *payload); + static sc_time getTimeOfGeneration(const tlm_generic_payload &payload); private: sc_time timeOfGeneration; @@ -224,6 +252,9 @@ bool operator<(const Thread &lhs, const Thread &rhs); bool operator==(const Channel &lhs, const Channel &rhs); bool operator!=(const Channel &lhs, const Channel &rhs); +bool operator==(const Rank &lhs, const Rank &rhs); +bool operator!=(const Rank &lhs, const Rank &rhs); + bool operator==(const BankGroup &lhs, const BankGroup &rhs); bool operator!=(const BankGroup &lhs, const BankGroup &rhs); diff --git a/DRAMSys/library/src/common/protocol.h b/DRAMSys/library/src/common/protocol.h index 06af9c30..986ef847 100644 --- a/DRAMSys/library/src/common/protocol.h +++ b/DRAMSys/library/src/common/protocol.h @@ -39,17 +39,11 @@ #define PROTOCOL_H // DRAM Control Phases -DECLARE_EXTENDED_PHASE(BEGIN_PREB); -DECLARE_EXTENDED_PHASE(END_PREB); - DECLARE_EXTENDED_PHASE(BEGIN_PRE); DECLARE_EXTENDED_PHASE(END_PRE); -DECLARE_EXTENDED_PHASE(BEGIN_PRE_ALL); -DECLARE_EXTENDED_PHASE(END_PRE_ALL); - -DECLARE_EXTENDED_PHASE(BEGIN_ACTB); -DECLARE_EXTENDED_PHASE(END_ACTB); +DECLARE_EXTENDED_PHASE(BEGIN_PREA); +DECLARE_EXTENDED_PHASE(END_PREA); DECLARE_EXTENDED_PHASE(BEGIN_ACT); DECLARE_EXTENDED_PHASE(END_ACT); @@ -60,7 +54,6 @@ DECLARE_EXTENDED_PHASE(END_REFA); DECLARE_EXTENDED_PHASE(BEGIN_REFB); DECLARE_EXTENDED_PHASE(END_REFB); - // Phases for Read and Write DECLARE_EXTENDED_PHASE(BEGIN_WR); DECLARE_EXTENDED_PHASE(END_WR); @@ -94,11 +87,5 @@ DECLARE_EXTENDED_PHASE(END_PDNAB); DECLARE_EXTENDED_PHASE(BEGIN_SREFB); DECLARE_EXTENDED_PHASE(END_SREFB); - -//Triggers -DECLARE_EXTENDED_PHASE(REF_TRIGGER); -DECLARE_EXTENDED_PHASE(PDN_TRIGGER); - - #endif // PROTOCOL_H diff --git a/DRAMSys/library/src/common/third_party/DRAMPower b/DRAMSys/library/src/common/third_party/DRAMPower index 746d56ea..1ddc48a3 160000 --- a/DRAMSys/library/src/common/third_party/DRAMPower +++ b/DRAMSys/library/src/common/third_party/DRAMPower @@ -1 +1 @@ -Subproject commit 746d56ea53c5227428fff3e13716a68f259ad243 +Subproject commit 1ddc48a3872d93e2a60fc8c53348e0c2ed95fae1 diff --git a/DRAMSys/library/src/common/third_party/sqlite-amalgamation b/DRAMSys/library/src/common/third_party/sqlite-amalgamation new file mode 160000 index 00000000..9be05e13 --- /dev/null +++ b/DRAMSys/library/src/common/third_party/sqlite-amalgamation @@ -0,0 +1 @@ +Subproject commit 9be05e13408dd8cf8dafe8f11b1700a28194e07e diff --git a/DRAMSys/library/src/common/third_party/systemc b/DRAMSys/library/src/common/third_party/systemc new file mode 160000 index 00000000..60418250 --- /dev/null +++ b/DRAMSys/library/src/common/third_party/systemc @@ -0,0 +1 @@ +Subproject commit 604182509559ae42c34e878f508bae7c18abbbd6 diff --git a/DRAMSys/library/src/controller/core/powerdown/NoPowerDown.cpp b/DRAMSys/library/src/common/timingCalculations.cpp similarity index 67% rename from DRAMSys/library/src/controller/core/powerdown/NoPowerDown.cpp rename to DRAMSys/library/src/common/timingCalculations.cpp index d148c8c0..be69fb44 100644 --- a/DRAMSys/library/src/controller/core/powerdown/NoPowerDown.cpp +++ b/DRAMSys/library/src/common/timingCalculations.cpp @@ -31,33 +31,41 @@ * * Authors: * Janik Schlemminger - * Robert Gernhardt * Matthias Jung */ -#include "NoPowerDown.h" +#include "timingCalculations.h" +#include "../configuration/memspec/MemSpec.h" +#include "DebugManager.h" +#include "../configuration/Configuration.h" +#include "utils.h" -void NoPowerDown::triggerSleep(Bank /*bank*/, sc_time /*time*/) +sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, + sc_time constraint) { - return; + if (previous + constraint > start) + return previous + constraint - start; + else + return SC_ZERO_TIME; } -void NoPowerDown::sleep(Bank /*bank*/, sc_time /*time*/) +const sc_time FrequencyToClk(double frequencyMhz) { - return; + return sc_time(1 / frequencyMhz, SC_US); } -void NoPowerDown::wakeUp(Bank /*bank*/, sc_time /*time*/) +const sc_time clkAlign(sc_time time, Alignment alignment) { - return; + sc_time clk = Configuration::getInstance().memSpec->clk; + if (alignment == UP) + return ceil(time / clk) * clk; + else + return floor(time / clk) * clk; } -void NoPowerDown::wakeUpForRefresh(Bank /*bank*/, sc_time /*time*/) +bool isClkAligned(sc_time time, sc_time clk) { - return; + return !((time / clk) - ceil(time / clk)); } -bool NoPowerDown::isInSelfRefresh(Bank /*bank*/) -{ - return false; -} + diff --git a/DRAMSys/library/src/controller/core/timingCalculations.h b/DRAMSys/library/src/common/timingCalculations.h similarity index 88% rename from DRAMSys/library/src/controller/core/timingCalculations.h rename to DRAMSys/library/src/common/timingCalculations.h index e9f80d4e..7288b93c 100644 --- a/DRAMSys/library/src/controller/core/timingCalculations.h +++ b/DRAMSys/library/src/common/timingCalculations.h @@ -39,14 +39,8 @@ #include #include -#include "../../common/dramExtensions.h" -#include "../Command.h" +#include "dramExtensions.h" -sc_time getMinExecutionTimeForPowerDownCmd(Command command); -sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload); - -sc_time getReadAccessTime(); -sc_time getWriteAccessTime(); sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint); diff --git a/DRAMSys/library/src/common/utils.cpp b/DRAMSys/library/src/common/utils.cpp index 69c6f899..3b9cdc1e 100644 --- a/DRAMSys/library/src/common/utils.cpp +++ b/DRAMSys/library/src/common/utils.cpp @@ -40,10 +40,11 @@ #include #include #include "dramExtensions.h" -#include "../controller/Controller.h" +#include using namespace std; using namespace tinyxml2; +using namespace tlm; bool TimeInterval::timeIsInInterval(sc_time time) { @@ -69,7 +70,7 @@ void reportFatal(std::string sender, std::string message) SC_REPORT_FATAL(sender.c_str(), message.c_str()); } -std::string phaseNameToString(tlm::tlm_phase phase) +std::string phaseNameToString(tlm_phase phase) { std::ostringstream oss; oss << phase; @@ -236,19 +237,19 @@ string loadTextFileContents(string filename) } } -void setUpDummy(tlm::tlm_generic_payload &payload, Bank &bank) +void setUpDummy(tlm_generic_payload &payload, Rank rank, Bank bank) { payload.set_address(bank.getStartAddress()); - payload.set_command(tlm::TLM_READ_COMMAND); + payload.set_command(TLM_READ_COMMAND); payload.set_data_length(0); - payload.set_response_status(tlm::TLM_OK_RESPONSE); + payload.set_response_status(TLM_OK_RESPONSE); payload.set_dmi_allowed(false); payload.set_byte_enable_length(0); payload.set_streaming_width(0); - payload.set_extension(new DramExtension(Thread( - Controller::ControllerThreadId()), bank, BankGroup(0), Row(0), - Column(0))); //payload takes ownership - //TODO .. Dummies muessen noch banggruppe und rank sauber bekommen .. noch was ueberlegen!!! + payload.set_extension(new DramExtension(Thread(UINT_MAX), rank, BankGroup(0), + bank, Row(0), Column(0), 0, 0)); + // payload takes ownership + // TODO: Dummies muessen noch banggruppe und rank sauber bekommen .. noch was ueberlegen!!! } std::string getFileName(std::string uri) diff --git a/DRAMSys/library/src/common/utils.h b/DRAMSys/library/src/common/utils.h index 79bf1c5b..9def2069 100644 --- a/DRAMSys/library/src/common/utils.h +++ b/DRAMSys/library/src/common/utils.h @@ -92,7 +92,7 @@ bool isIn(const T &value, const std::vector &collection) } constexpr const char headline[] = - "========================================================="; + "==========================================================================="; static inline void loadbar(unsigned int x, unsigned int n, @@ -146,7 +146,7 @@ std::string queryStringParameter(tinyxml2::XMLElement *node, std::string name); bool queryBoolParameter(tinyxml2::XMLElement *node, std::string name); double queryDoubleParameter(tinyxml2::XMLElement *node, std::string name); -void setUpDummy(tlm::tlm_generic_payload &payload, Bank &bank); +void setUpDummy(tlm::tlm_generic_payload &payload, Rank rank = Rank(0), Bank bank = Bank(0)); #endif // UTILS_H diff --git a/DRAMSys/library/src/controller/core/configuration/Configuration.cpp b/DRAMSys/library/src/configuration/Configuration.cpp similarity index 79% rename from DRAMSys/library/src/controller/core/configuration/Configuration.cpp rename to DRAMSys/library/src/configuration/Configuration.cpp index eb0918f3..826343d6 100644 --- a/DRAMSys/library/src/controller/core/configuration/Configuration.cpp +++ b/DRAMSys/library/src/configuration/Configuration.cpp @@ -40,17 +40,13 @@ #include "Configuration.h" #include "ConfigurationLoader.h" -#include "../../../common/XmlAddressDecoder.h" +#include "../common/XmlAddressDecoder.h" using namespace std; string Configuration::memspecUri = ""; string Configuration::mcconfigUri = ""; -Configuration::Configuration() -{ -} - bool string2bool(string s) { if (s.compare("0") == 0) { @@ -142,18 +138,21 @@ void Configuration::setParameter(std::string name, std::string value) BankwiseLogic = string2bool(value); else if (name == "OpenPagePolicy") OpenPagePolicy = string2bool(value); + else if (name == "AdaptivePagePolicy") + AdaptivePagePolicy = string2bool(value); else if (name == "MaxNrOfTransactions") MaxNrOfTransactions = string2int(value); else if (name == "Scheduler") Scheduler = value; else if (name == "SJFProbability") - if (string2int(value) > 100 || string2int(value) < 0) { + { + if (string2int(value) > 100 || string2int(value) < 0) SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be between 0 and 100.").c_str()); - } else { + else SJFProbability = string2int(value); - } + } else if (name == "RequestBufferSize") RequestBufferSize = string2int(value); else if (name == "Capsize") @@ -177,36 +176,31 @@ void Configuration::setParameter(std::string name, std::string value) else if (name == "EnableWindowing") EnableWindowing = string2bool(value); else if (name == "WindowSize") - if (string2int(value) < 1) { + { + if (string2int(value) < 1) SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be at least one.").c_str()); - } else + else WindowSize = string2int(value); + } else if (name == "Debug") Debug = string2bool(value); - else if (name == "NumberOfMemChannels") { + else if (name == "NumberOfMemChannels") NumberOfMemChannels = string2int(value); - unsigned int maxNumberofMemChannels = - AddressDecoder::getInstance().amount["channel"]; - if (NumberOfMemChannels > maxNumberofMemChannels) { - SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " - + name - + ". Value is out of range. The maximum value according to " - + "the address mapping configuration file is " - + std::to_string(maxNumberofMemChannels) + ".").c_str()); - } - } else if (name == "ControllerCoreRefDisable") + else if (name == "ControllerCoreRefDisable") ControllerCoreRefDisable = string2bool(value); else if (name == "ControllerCoreRGR") RowGranularRef = string2bool(value); else if (name == "ControllerCoreRGRRowInc") RowInc = string2int(value); - else if (name == "ControllerCoreRefMode") { + else if (name == "ControllerCoreRefMode") + { RefMode = string2int(value); if (RefMode != 1 && RefMode != 2 && RefMode != 4) SC_REPORT_FATAL("Configuration", (name + " invalid value.").c_str()); - } else if (name == "ControllerCoreRefNumARCmdsIntREFI") + } + else if (name == "ControllerCoreRefNumARCmdsIntREFI") NumAR = string2int(value); else if (name == "ControllerCoreRGRB0") RGRB0 = string2bool(value); @@ -240,25 +234,13 @@ void Configuration::setParameter(std::string name, std::string value) RGRB14 = string2bool(value); else if (name == "ControllerCoreRGRB15") RGRB15 = string2bool(value); - else if (name == "ControllerCoreRGRtRASBInClkCycles") - trasbclk = string2int(value); - else if (name == "ControllerCoreRGRtRRDB_LInClkCycles") - trrdblclk = string2int(value); - else if (name == "ControllerCoreRGRtRRDB_SInClkCycles") - trrdbsclk = string2int(value); - else if (name == "ControllerCoreRGRtRPBInClkCycles") - trpbclk = string2int(value); - else if (name == "ControllerCoreRGRtRCBInClkCycles") - trcbclk = string2int(value); - else if (name == "ControllerCoreRGRtFAWBInClkCycles") - tfawbclk = string2int(value); else if (name == "ControllerCoreRefForceMaxPostponeBurst") ControllerCoreRefForceMaxPostponeBurst = string2bool(value); - else if (name == "ControllerCoreRefEnablePostpone") { + else if (name == "ControllerCoreRefEnablePostpone") ControllerCoreRefEnablePostpone = string2bool(value); - } else if (name == "ControllerCoreRefEnablePullIn") { + else if (name == "ControllerCoreRefEnablePullIn") ControllerCoreRefEnablePullIn = string2bool(value); - } else if (name == "ControllerCoreRefMaxPostponed") + else if (name == "ControllerCoreRefMaxPostponed") ControllerCoreRefMaxPostponed = string2int(value); else if (name == "ControllerCoreRefMaxPulledIn") ControllerCoreRefMaxPulledIn = string2int(value); @@ -267,21 +249,25 @@ void Configuration::setParameter(std::string name, std::string value) else if (name == "SimulationProgressBar") SimulationProgressBar = string2bool(value); else if (name == "NumberOfDevicesOnDIMM") - if (string2int(value) < 1) { + { + if (string2int(value) < 1) SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be at least one.").c_str()); - } else + else NumberOfDevicesOnDIMM = string2int(value); - else if (name == "AddressOffset") { + } + else if (name == "AddressOffset") + { #ifdef DRAMSYS_GEM5 AddressOffset = string2ull(value); #else AddressOffset = 0; #endif - } else if (name == "UseMalloc") { + } + else if (name == "UseMalloc") UseMalloc = string2bool(value); - } else if (name == "CheckTLM2Protocol") + else if (name == "CheckTLM2Protocol") CheckTLM2Protocol = string2bool(value); else if (name == "ECCControllerMode") ECCMode = string2ECCControllerMode(value); @@ -293,22 +279,25 @@ void Configuration::setParameter(std::string name, std::string value) else if (name == "StoreMode") StoreMode = string2StoreMode(value); // Temperature Simulation related - else if (name == "TemperatureScale") { - if (value != "Celsius" && value != "Fahrenheit" && value != "Kelvin") { + else if (name == "TemperatureScale") + { + if (value != "Celsius" && value != "Fahrenheit" && value != "Kelvin") SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ".").c_str()); - } temperatureSim.TemperatureScale = value; - } else if (name == "StaticTemperatureDefaultValue") + } + else if (name == "StaticTemperatureDefaultValue") temperatureSim.StaticTemperatureDefaultValue = string2int(value); else if (name == "ThermalSimPeriod") temperatureSim.ThermalSimPeriod = std::stod(value.c_str()); else if (name == "ThermalSimUnit") temperatureSim.ThermalSimUnit = string2TimeUnit(value); - else if (name == "PowerInfoFile") { + else if (name == "PowerInfoFile") + { temperatureSim.powerInfoFile = value; temperatureSim.parsePowerInfoFile(); - } else if (name == "IceServerIp") + } + else if (name == "IceServerIp") temperatureSim.IceServerIp = value; else if (name == "IceServerPort") temperatureSim.IceServerPort = string2int(value); @@ -320,10 +309,9 @@ void Configuration::setParameter(std::string name, std::string value) temperatureSim.GenerateTemperatureMap = string2bool(value); else if (name == "GeneratePowerMap") temperatureSim.GeneratePowerMap = string2bool(value); - else { + else SC_REPORT_FATAL("Configuration", ("Parameter " + name + " not defined in Configuration").c_str()); - } } void Configuration::setPathToResources(std::string path) @@ -336,7 +324,7 @@ std::string Configuration::getPathToResources() { return pathToResources; } - +// TODO: Never used void Configuration::setParameters(std::map parameterMap) { @@ -349,6 +337,9 @@ void Configuration::setParameters(std::map std::uint64_t Configuration::getSimMemSizeInBytes() { // 1. Get number of banks, rows, columns and data width in bits for one die (or chip) + std::string type = memSpec->MemoryType; + std::uint64_t ranks = memSpec->NumberOfRanks; + std::uint64_t bankgroups = memSpec->NumberOfBankGroups; std::uint64_t banks = memSpec->NumberOfBanks; std::uint64_t rows = memSpec->NumberOfRows; std::uint64_t columns = memSpec->NumberOfColumns; @@ -360,15 +351,19 @@ std::uint64_t Configuration::getSimMemSizeInBytes() // 4. Total memory size in Bytes of one DIMM (with only support of 1 rank on a DIMM) std::uint64_t memorySize = chipSize * NumberOfDevicesOnDIMM; - std::cout << headline << std::endl << std::endl; - std::cout << std::setw(24) << "Memory size in bytes : " << memorySize << std::endl; - std::cout << std::setw(24) << "Number of banks : " << banks << std::endl; - std::cout << std::setw(24) << "Number of rows : " << rows << std::endl; - std::cout << std::setw(24) << "Number of columns : " << columns << std::endl; - std::cout << std::setw(24) << "Chip data bus width : " << bitWidth << std::endl; - std::cout << std::setw(24) << "Chip size in bits : " << chipBitSize << std::endl; - std::cout << std::setw(24) << "Chip Size in bytes : " << chipSize << std::endl; - std::cout << std::setw(24) << "Devices/Chips on DIMM: " << NumberOfDevicesOnDIMM << std::endl; + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << type << std::endl; + std::cout << " Memory size in bytes: " << memorySize << std::endl; + std::cout << " Number of ranks: " << ranks << std::endl; + std::cout << " Number of bankgroups: " << bankgroups << std::endl; + std::cout << " Number of banks: " << banks << std::endl; + std::cout << " Number of rows: " << rows << std::endl; + std::cout << " Number of columns: " << columns << std::endl; + std::cout << " Chip data bus width: " << bitWidth << std::endl; + std::cout << " Chip size in bits: " << chipBitSize << std::endl; + std::cout << " Chip Size in bytes: " << chipSize << std::endl; + std::cout << " Devices/Chips on DIMM: " << NumberOfDevicesOnDIMM << std::endl; std::cout << std::endl; assert(memorySize > 0); @@ -398,37 +393,13 @@ unsigned int Configuration::getBytesPerBurst() // offset of the N-byte-wide memory module (DIMM) (a single data word // or burst element has N bytes. N = 2^(# bits for byte offset)). unsigned int burstElementSizeInBytes = - AddressDecoder::getInstance().amount["bytes"]; + AddressDecoder::getInstance().amount.bytes; assert(bytesPerBurst == (burstElementSizeInBytes * memSpec->BurstLength)); } return bytesPerBurst; } -sc_time Configuration::getTrasb() -{ - return trasbclk * memSpec->clk; -} -sc_time Configuration::getTrrdb_L() -{ - return trrdblclk * memSpec->clk; -} -sc_time Configuration::getTrrdb_S() -{ - return trrdbsclk * memSpec->clk; -} -sc_time Configuration::getTrpb() -{ - return trpbclk * memSpec->clk; -} -sc_time Configuration::getTrcb() -{ - return trcbclk * memSpec->clk; -} -sc_time Configuration::getTfawb() -{ - return tfawbclk * memSpec->clk; -} bool Configuration::getRGRBank(unsigned int w) { bool flg = w == 0 ? RGRB0 : w == 1 ? RGRB1 : w == 2 ? RGRB2 : w == 3 ? RGRB3 : w diff --git a/DRAMSys/library/src/controller/core/configuration/Configuration.h b/DRAMSys/library/src/configuration/Configuration.h similarity index 91% rename from DRAMSys/library/src/controller/core/configuration/Configuration.h rename to DRAMSys/library/src/configuration/Configuration.h index 51d4079e..e8fb6bc6 100644 --- a/DRAMSys/library/src/controller/core/configuration/Configuration.h +++ b/DRAMSys/library/src/configuration/Configuration.h @@ -42,11 +42,11 @@ #include #include #include -#include "MemSpec.h" +#include "memspec/MemSpec.h" #include "TemperatureSimConfig.h" -#include "../../../common/utils.h" +#include "../common/utils.h" -#include "../../../error/eccbaseclass.h" +#include "../error/eccbaseclass.h" enum class StorageMode {NoStorage, Store, ErrorModel}; @@ -65,6 +65,7 @@ struct Configuration // MCConfig: bool BankwiseLogic = false; bool OpenPagePolicy = true; + bool AdaptivePagePolicy = false; unsigned int MaxNrOfTransactions = 8; std::string Scheduler; unsigned int SJFProbability; @@ -88,18 +89,6 @@ struct Configuration unsigned int NumberOfMemChannels = 1; bool ControllerCoreRefDisable = false; bool RowGranularRef = false; - unsigned int trasbclk = 0; - sc_time getTrasb(); - unsigned int trrdblclk = 0; - sc_time getTrrdb_L(); - unsigned int trrdbsclk = 0; - sc_time getTrrdb_S(); - unsigned int trpbclk = 0; - sc_time getTrpb(); - unsigned int trcbclk = 0; - sc_time getTrcb(); - unsigned int tfawbclk = 0; - sc_time getTfawb(); bool RGRB0 = true; bool RGRB1 = true; bool RGRB2 = true; @@ -160,7 +149,7 @@ struct Configuration std::string getPathToResources(); private: - Configuration(); + Configuration() {} unsigned int powerDownTimeoutInClk = 3; }; diff --git a/DRAMSys/library/src/configuration/ConfigurationLoader.cpp b/DRAMSys/library/src/configuration/ConfigurationLoader.cpp new file mode 100644 index 00000000..29a46b3e --- /dev/null +++ b/DRAMSys/library/src/configuration/ConfigurationLoader.cpp @@ -0,0 +1,775 @@ +/* + * Copyright (c) 2015, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Janik Schlemminger + * Matthias Jung + * Lukas Steiner + */ + +#include "ConfigurationLoader.h" +#include "memspec/MemSpec.h" +#include "memspec/MemSpecDDR3.h" +#include "memspec/MemSpecDDR4.h" +#include "memspec/MemSpecWideIO.h" +#include "memspec/MemSpecLPDDR4.h" +#include "memspec/MemSpecWideIO2.h" +#include "memspec/MemSpecHBM2.h" +#include "memspec/MemSpecGDDR5.h" +#include "memspec/MemSpecGDDR5X.h" +#include "memspec/MemSpecGDDR6.h" +#include "../common/timingCalculations.h" + +using namespace tinyxml2; +using namespace std; + +void ConfigurationLoader::loadSimConfig(Configuration &config, + string simconfigUri) +{ + tinyxml2::XMLDocument doc; + + loadXML(simconfigUri, doc); + XMLElement *simconfig = doc.FirstChildElement("simconfig"); + loadConfig(config, simconfig); +} + +void ConfigurationLoader::loadSimConfig(Configuration &config, + XMLElement *simconfig) +{ + if (simconfig->Attribute("src")) { + XMLDocument doc; + string src(simconfig->Attribute("src")); + loadXML(src, doc); + loadSimConfig(config, doc.FirstChildElement("simconfig")); + } + loadConfig(config, simconfig); +} + +void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config, + std::string thermalsimconfigUri) +{ + loadConfigFromUri(config, thermalsimconfigUri, "thermalsimconfig"); +} + +void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config, + XMLElement *thermalsimconfig) +{ + if (thermalsimconfig->Attribute("src")) { + // Configuration is inside another a file + std::string uri(thermalsimconfig->Attribute("src")); + loadConfigFromUri(config, uri, "thermalsimconfig"); + } else { + loadConfig(config, thermalsimconfig); + } +} + +void ConfigurationLoader::loadConfig(Configuration &config, + XMLElement *configNode) +{ + XMLElement *element; + for (element = configNode->FirstChildElement(); element != NULL; + element = element->NextSiblingElement()) { + config.setParameter(element->Name(), element->Attribute("value")); + + } +} + +void ConfigurationLoader::loadConfigFromUri(Configuration &config, + std::string uri, std::string first_element) +{ + tinyxml2::XMLDocument doc; + loadXML(uri, doc); + XMLElement *e = doc.FirstChildElement(first_element.c_str()); + loadConfig(config, e); +} + +void ConfigurationLoader::loadMCConfig(Configuration &config, + string mcconfigUri) +{ + tinyxml2::XMLDocument doc; + config.mcconfigUri = mcconfigUri; + loadXML(mcconfigUri, doc); + XMLElement *mcconfig = doc.FirstChildElement("mcconfig"); + loadConfig(config, mcconfig); +} + +void ConfigurationLoader::loadMCConfig(Configuration &config, + XMLElement *mcconfig) +{ + if (mcconfig->Attribute("src")) + { + XMLDocument doc; + string src(mcconfig->Attribute("src")); + config.mcconfigUri = src; + loadXML(src, doc); + loadMCConfig(config, doc.FirstChildElement("mcconfig")); + } + else + loadConfig(config, mcconfig); +} + +void ConfigurationLoader::loadMemSpec(Configuration &config, string memspecUri) +{ + tinyxml2::XMLDocument doc; + config.memspecUri = memspecUri; + loadXML(memspecUri, doc); + XMLElement *memspec = doc.FirstChildElement("memspec"); + loadMemSpec(config, memspec); +} + +void ConfigurationLoader::loadMemSpec(Configuration &config, + XMLElement *memspec) +{ + string memoryType = queryStringParameter(memspec, "memoryType"); + if (memoryType == "DDR4") + { + Configuration::getInstance().memSpec = new MemSpecDDR4(); + loadCommons(config, memspec); + loadDDR4(config, memspec); + } + else if (memoryType == "DDR3") + { + Configuration::getInstance().memSpec = new MemSpecDDR3(); + loadCommons(config, memspec); + loadDDR3(config, memspec); + } + else if (memoryType == "LPDDR4") + { + Configuration::getInstance().memSpec = new MemSpecLPDDR4(); + loadCommons(config, memspec); + loadLPDDR4(config, memspec); + } + else if (memoryType == "WIDEIO_SDR") + { + Configuration::getInstance().memSpec = new MemSpecWideIO(); + loadCommons(config, memspec); + loadWideIO(config, memspec); + } + else if (memoryType == "WIDEIO2") + { + Configuration::getInstance().memSpec = new MemSpecWideIO2(); + loadCommons(config, memspec); + loadWideIO2(config, memspec); + } + else if (memoryType == "HBM2") + { + Configuration::getInstance().memSpec = new MemSpecHBM2(); + loadCommons(config, memspec); + loadHBM2(config, memspec); + } + else if (memoryType == "GDDR5") + { + Configuration::getInstance().memSpec = new MemSpecGDDR5(); + loadCommons(config, memspec); + loadGDDR5(config, memspec); + } + else if (memoryType == "GDDR5X") + { + Configuration::getInstance().memSpec = new MemSpecGDDR5X(); + loadCommons(config, memspec); + loadGDDR5X(config, memspec); + } + else if (memoryType == "GDDR6") + { + Configuration::getInstance().memSpec = new MemSpecGDDR6(); + loadCommons(config, memspec); + loadGDDR6(config, memspec); + } + else + reportFatal("ConfigurationLoader", "Unsupported DRAM type"); +} + +void ConfigurationLoader::loadCommons(Configuration &config, XMLElement *xmlSpec) +{ + MemSpec *memSpec = config.memSpec; + + memSpec->MemoryId = queryStringParameter(xmlSpec, "memoryId"); + memSpec->MemoryType = queryStringParameter(xmlSpec, "memoryType"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->BurstLength = queryUIntParameter(architecture, "burstLength"); + memSpec->DataRate = queryUIntParameter(architecture, "dataRate"); + memSpec->NumberOfRows = queryUIntParameter(architecture, "nbrOfRows"); + memSpec->NumberOfColumns = queryUIntParameter(architecture, "nbrOfColumns"); + memSpec->bitWidth = queryUIntParameter(architecture, "width"); + + // Clock + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + memSpec->clkMHz = queryDoubleParameter(timings, "clkMhz"); + memSpec->clk = FrequencyToClk(memSpec->clkMHz); +} + +void ConfigurationLoader::loadDDR3(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecDDR3 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = 1; + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for DDR3 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); + //memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tCCD = clk * queryUIntParameter(timings, "CCD"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRRD = clk * queryUIntParameter(timings, "RRD"); + memSpec->tWTR = clk * queryUIntParameter(timings, "WTR"); + memSpec->tAL = clk * queryUIntParameter(timings, "AL"); + memSpec->tXPDLL = clk * queryUIntParameter(timings, "XPDLL"); + memSpec->tXSDLL = clk * queryUIntParameter(timings, "XSDLL"); + + // Currents and voltages + XMLElement *powers = xmlSpec->FirstChildElement("mempowerspec"); + memSpec->iDD0 = queryDoubleParameter(powers, "idd0"); + memSpec->iDD2N = queryDoubleParameter(powers, "idd2n"); + memSpec->iDD3N = queryDoubleParameter(powers, "idd3n"); + memSpec->iDD4R = queryDoubleParameter(powers, "idd4r"); + memSpec->iDD4W = queryDoubleParameter(powers, "idd4w"); + memSpec->iDD5 = queryDoubleParameter(powers, "idd5"); + memSpec->iDD6 = queryDoubleParameter(powers, "idd6"); + memSpec->vDD = queryDoubleParameter(powers, "vdd"); + memSpec->iDD2P0 = queryDoubleParameter(powers, "idd2p0"); + memSpec->iDD2P1 = queryDoubleParameter(powers, "idd2p1"); + memSpec->iDD3P0 = queryDoubleParameter(powers, "idd3p0"); + memSpec->iDD3P1 = queryDoubleParameter(powers, "idd3p1"); +} + +void ConfigurationLoader::loadDDR4(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecDDR4 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for DDR4 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); + //memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tCCD_S = clk * queryUIntParameter(timings, "CCD_S"); + memSpec->tCCD_L = clk * queryUIntParameter(timings, "CCD_L"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + unsigned refMode = Configuration::getInstance().getRefMode(); + if (refMode == 1) + { + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + } + else if (refMode == 2) + { + memSpec->tREFI = clk * (queryUIntParameter(timings, "REFI") / 2); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC2"); + } + else if (refMode == 4) + { + memSpec->tREFI = clk * (queryUIntParameter(timings, "REFI") / 2); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC4"); + } + else + SC_REPORT_FATAL("ConfigurationLoader", "Refresh Mode not supported"); + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRRD_S = clk * queryUIntParameter(timings, "RRD_S"); + memSpec->tRRD_L = clk * queryUIntParameter(timings, "RRD_L"); + memSpec->tWTR_S = clk * queryUIntParameter(timings, "WTR_S"); + memSpec->tWTR_L = clk * queryUIntParameter(timings, "WTR_L"); + memSpec->tAL = clk * queryUIntParameter(timings, "AL"); + memSpec->tXPDLL = clk * queryUIntParameter(timings, "XPDLL"); + memSpec->tXSDLL = clk * queryUIntParameter(timings, "XSDLL"); + + // Currents and voltages + XMLElement *powers = xmlSpec->FirstChildElement("mempowerspec"); + memSpec->iDD0 = queryDoubleParameter(powers, "idd0"); + memSpec->iDD2N = queryDoubleParameter(powers, "idd2n"); + memSpec->iDD3N = queryDoubleParameter(powers, "idd3n"); + memSpec->iDD4R = queryDoubleParameter(powers, "idd4r"); + memSpec->iDD4W = queryDoubleParameter(powers, "idd4w"); + memSpec->iDD5 = queryDoubleParameter(powers, "idd5"); + memSpec->iDD6 = queryDoubleParameter(powers, "idd6"); + memSpec->vDD = queryDoubleParameter(powers, "vdd"); + memSpec->iDD02 = queryDoubleParameter(powers, "idd02"); + memSpec->iDD2P0 = queryDoubleParameter(powers, "idd2p0"); + memSpec->iDD2P1 = queryDoubleParameter(powers, "idd2p1"); + memSpec->iDD3P0 = queryDoubleParameter(powers, "idd3p0"); + memSpec->iDD3P1 = queryDoubleParameter(powers, "idd3p1"); + memSpec->iDD62 = queryDoubleParameter(powers, "idd62"); + memSpec->vDD2 = queryDoubleParameter(powers, "vdd2"); +} + +void ConfigurationLoader::loadLPDDR4(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecLPDDR4 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture: + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = 1; + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for LPDDR4 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIpb = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFCab = clk * queryUIntParameter(timings, "RFCAB"); + memSpec->tRFCpb = clk * queryUIntParameter(timings, "RFCPB"); + memSpec->tRPab = clk * queryUIntParameter(timings, "RPAB"); + memSpec->tRPpb = clk * queryUIntParameter(timings, "RPPB"); + memSpec->tPPD = clk * queryUIntParameter(timings, "PPD"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->tRRD = clk * queryUIntParameter(timings, "RRD"); + memSpec->tCCD = clk * queryUIntParameter(timings, "CCD"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tRPST = clk * queryUIntParameter(timings, "RPST"); + memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tDQSS = clk * queryUIntParameter(timings, "DQSS"); + memSpec->tDQS2DQ = clk * queryUIntParameter(timings, "DQS2DQ"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWPRE = clk * queryUIntParameter(timings, "WPRE"); + memSpec->tWTR = clk * queryUIntParameter(timings, "WTR"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tSR = clk * queryUIntParameter(timings, "SR"); + memSpec->tXSR = clk * queryUIntParameter(timings, "XSR"); + memSpec->tESCKE = clk * queryUIntParameter(timings, "ESCKE"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tCMDCKE = clk * queryUIntParameter(timings, "CMDCKE"); + + // Currents and voltages + // TODO: to be completed +} + +void ConfigurationLoader::loadWideIO(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecWideIO *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = 1; + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for WideIO + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); + memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); + memSpec->tAC = clk * queryUIntParameter(timings, "AC"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tCCD_R = clk * queryUIntParameter(timings, "CCD_R"); + memSpec->tCCD_W = clk * queryUIntParameter(timings, "CCD_W"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRRD = clk * queryUIntParameter(timings, "RRD"); + memSpec->tTAW = clk * queryUIntParameter(timings, "TAW"); + memSpec->tWTR = clk * queryUIntParameter(timings, "WTR"); + + // Currents and voltages + XMLElement *powers = xmlSpec->FirstChildElement("mempowerspec"); + memSpec->iDD0 = queryDoubleParameter(powers, "idd0"); + memSpec->iDD2N = queryDoubleParameter(powers, "idd2n"); + memSpec->iDD3N = queryDoubleParameter(powers, "idd3n"); + memSpec->iDD4R = queryDoubleParameter(powers, "idd4r"); + memSpec->iDD4W = queryDoubleParameter(powers, "idd4w"); + memSpec->iDD5 = queryDoubleParameter(powers, "idd5"); + memSpec->iDD6 = queryDoubleParameter(powers, "idd6"); + memSpec->vDD = queryDoubleParameter(powers, "vdd"); + memSpec->iDD02 = queryDoubleParameter(powers, "idd02"); + memSpec->iDD2P0 = queryDoubleParameter(powers, "idd2p0"); + memSpec->iDD2P02 = queryDoubleParameter(powers, "idd2p02"); + memSpec->iDD2P1 = queryDoubleParameter(powers, "idd2p1"); + memSpec->iDD2P12 = queryDoubleParameter(powers, "idd2p12"); + memSpec->iDD2N2 = queryDoubleParameter(powers, "idd2n2"); + memSpec->iDD3P0 = queryDoubleParameter(powers, "idd3p0"); + memSpec->iDD3P02 = queryDoubleParameter(powers, "idd3p02"); + memSpec->iDD3P1 = queryDoubleParameter(powers, "idd3p1"); + memSpec->iDD3P12 = queryDoubleParameter(powers, "idd3p12"); + memSpec->iDD3N2 = queryDoubleParameter(powers, "idd3n2"); + memSpec->iDD4R2 = queryDoubleParameter(powers, "idd4r2"); + memSpec->iDD4W2 = queryDoubleParameter(powers, "idd4w2"); + memSpec->iDD52 = queryDoubleParameter(powers, "idd52"); + memSpec->iDD62 = queryDoubleParameter(powers, "idd62"); + memSpec->vDD2 = queryDoubleParameter(powers, "vdd2"); +} + +void ConfigurationLoader::loadWideIO2(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecWideIO2 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = 1; + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for WideIO + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); + memSpec->tDQSS = clk * queryUIntParameter(timings, "DQSS"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tRCpb = clk * queryUIntParameter(timings, "RCPB"); + memSpec->tRCab = clk * queryUIntParameter(timings, "RCAB"); + memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); + memSpec->tXSR = clk * queryUIntParameter(timings, "XSR"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tCCD = clk * queryUIntParameter(timings, "CCD"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); + memSpec->tRPpb = clk * queryUIntParameter(timings, "RPPB"); + memSpec->tRPab = clk * queryUIntParameter(timings, "RPAB"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWTR = clk * queryUIntParameter(timings, "WTR"); + memSpec->tRRD = clk * queryUIntParameter(timings, "RRD"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIpb = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFCab = clk * queryUIntParameter(timings, "RFCAB"); + memSpec->tRFCpb = clk * queryUIntParameter(timings, "RFCPB"); + + // Currents and voltages + // TODO: to be completed +} + +void ConfigurationLoader::loadHBM2(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecHBM2 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for HBM2 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); +// memSpec->tDQSQ = clk * queryUIntParameter(timings, "DQSQ"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD"); + memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR"); + memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL"); + memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tPL = clk * queryUIntParameter(timings, "PL"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL"); + memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS"); +// memSpec->tCCDR = clk * queryUIntParameter(timings, "CCDR"); + memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL"); + memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS"); + memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tPD = memSpec->tCKE; + memSpec->tRDPDE = memSpec->tRL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk; + memSpec->tWRPDE = memSpec->tWL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk + memSpec->tWR; + memSpec->tWRAPDE = memSpec->tWL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk + memSpec->tWR; + memSpec->tCKESR = memSpec->tCKE + memSpec->clk; + memSpec->tRDSRE = memSpec->tRL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk; + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRFCSB = clk * queryUIntParameter(timings, "RFCSB"); + memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFISB = clk * queryUIntParameter(timings, "REFISB"); + + // Currents and voltages + // TODO: to be completed +} + +void ConfigurationLoader::loadGDDR5(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecGDDR5 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for GDDR5 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD"); + memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS"); + memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL"); + memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS"); + memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL"); + memSpec->tCL = clk * queryUIntParameter(timings, "CL"); + memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN"); + memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK"); + memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO"); + memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS"); + memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tPD = memSpec->tCKE; + memSpec->tXPN = clk * queryUIntParameter(timings, "XPN"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB"); + memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->t32AW = clk * queryUIntParameter(timings, "32AW"); + memSpec->tRDSRE = memSpec->tCL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tPPD = clk * queryUIntParameter(timings, "PPD"); + memSpec->tLK = clk * queryUIntParameter(timings, "LK"); + + // Currents and voltages + // TODO: to be completed +} + +void ConfigurationLoader::loadGDDR5X(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecGDDR5X *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for GDDR5X + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD"); + memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS"); + memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL"); + memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS"); + memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN"); + memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK"); + memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO"); + memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS"); + memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tPD = memSpec->tCKE; + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB"); + memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->t32AW = clk * queryUIntParameter(timings, "32AW"); + memSpec->tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tPPD = clk * queryUIntParameter(timings, "PPD"); + memSpec->tLK = clk * queryUIntParameter(timings, "LK"); + + // Currents and voltages + // TODO: to be completed +} + +void ConfigurationLoader::loadGDDR6(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecGDDR6 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for GDDR6 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD"); + memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS"); + memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL"); + memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS"); + memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN"); + memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK"); + memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO"); + memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS"); + memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tPD = memSpec->tCKE; + memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB"); + memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tPPD = clk * queryUIntParameter(timings, "PPD"); + memSpec->tLK = clk * queryUIntParameter(timings, "LK"); + memSpec->tACTPDE = clk * queryUIntParameter(timings, "ACTPDE"); + memSpec->tPREPDE = clk * queryUIntParameter(timings, "PREPDE"); + memSpec->tREFPDE = clk * queryUIntParameter(timings, "REFPDE"); + + // Currents and voltages + // TODO: to be completed +} diff --git a/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.h b/DRAMSys/library/src/configuration/ConfigurationLoader.h similarity index 87% rename from DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.h rename to DRAMSys/library/src/configuration/ConfigurationLoader.h index 7a4e0410..b5ea9290 100644 --- a/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.h +++ b/DRAMSys/library/src/configuration/ConfigurationLoader.h @@ -39,8 +39,8 @@ #define CONFIGURATIONLOADER_H #include -#include "../../../common/third_party/tinyxml2/tinyxml2.h" -#include "../../../common/utils.h" +#include "../common/third_party/tinyxml2/tinyxml2.h" +#include "../common/utils.h" #include "Configuration.h" class ConfigurationLoader @@ -73,6 +73,11 @@ private: static void loadDDR4(Configuration &config, tinyxml2::XMLElement *memspec); static void loadLPDDR4(Configuration &config, tinyxml2::XMLElement *memspec); static void loadWideIO(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadWideIO2(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadHBM2(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadGDDR5(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadGDDR5X(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadGDDR6(Configuration &config, tinyxml2::XMLElement *memspec); }; diff --git a/DRAMSys/library/src/controller/core/configuration/TemperatureSimConfig.h b/DRAMSys/library/src/configuration/TemperatureSimConfig.h similarity index 83% rename from DRAMSys/library/src/controller/core/configuration/TemperatureSimConfig.h rename to DRAMSys/library/src/configuration/TemperatureSimConfig.h index b9acd733..a0505bbf 100644 --- a/DRAMSys/library/src/controller/core/configuration/TemperatureSimConfig.h +++ b/DRAMSys/library/src/configuration/TemperatureSimConfig.h @@ -41,9 +41,9 @@ #include #include -#include "../../../common/DebugManager.h" -#include "../../../common/third_party/tinyxml2/tinyxml2.h" -#include "../../../common/utils.h" +#include "../common/DebugManager.h" +#include "../common/third_party/tinyxml2/tinyxml2.h" +#include "../common/utils.h" struct TemperatureSimConfig { @@ -76,7 +76,7 @@ struct TemperatureSimConfig void parsePowerInfoFile() { - printDebugMessage("Power Info File: " + powerInfoFile); + PRINTDEBUGMESSAGE("TemperatureSimConfig", "Power Info File: " + powerInfoFile); powerInfoFile = pathToResources + "/configs/thermalsim/" @@ -90,7 +90,7 @@ struct TemperatureSimConfig if (powInfoElem == NULL) { // Invalid file std::string errormsg = "Invalid Power Info File " + powerInfoFile; - printDebugMessage(errormsg); + PRINTDEBUGMESSAGE("TemperatureSimConfig", errormsg); SC_REPORT_FATAL("Temperature Sim Config", errormsg.c_str()); } @@ -113,23 +113,17 @@ struct TemperatureSimConfig void showTemperatureSimConfig() { - int i = 0; - for (auto e : powerInitialValues) { - printDebugMessage("powerInitialValues[" + std::to_string( - i++) + "]: " + std::to_string(e)); + int i __attribute__((unused)) = 0; + for (auto e __attribute__((unused)) : powerInitialValues) { + PRINTDEBUGMESSAGE("TemperatureSimConfig", "powerInitialValues[" + + std::to_string(i++) + "]: " + std::to_string(e)); } i = 0; - for (auto e : powerThresholds) { - printDebugMessage("powerThreshold[" + std::to_string(i++) + "]: " + - std::to_string(e)); + for (auto e __attribute__((unused)) : powerThresholds) { + PRINTDEBUGMESSAGE("TemperatureSimConfig", "powerThreshold[" + + std::to_string(i++) + "]: " + std::to_string(e)); } } - - void printDebugMessage(std::string message) - { - DebugManager::getInstance().printDebugMessage("Temperature Sim Config", - message); - } }; #endif // TEMPERATURESIMCONFIG_H diff --git a/DRAMSys/library/src/controller/core/Slots.cpp b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp similarity index 58% rename from DRAMSys/library/src/controller/core/Slots.cpp rename to DRAMSys/library/src/configuration/memspec/MemSpec.cpp index d74ce9e9..6e96ff4a 100644 --- a/DRAMSys/library/src/controller/core/Slots.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp @@ -30,58 +30,58 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: - * Robert Gernhardt - * Matthias Jung + * Lukas Steiner */ -#include "Slots.h" -#include "timingCalculations.h" +#include "MemSpec.h" +#include +#include +#include "../../controller/Command.h" +#include "../Configuration.h" -Slots::Slots(sc_time clk) : - clk(clk) +using namespace tlm; + +MemSpec::MemSpec() { - + commandLength = std::vector(numberOfCommands(), 1); } -Slots::~Slots() +const std::vector &MemSpec::getBanks() const { -} - -void Slots::moveCommandToNextFreeSlot(ScheduledCommand &command) -{ - while (!isFree(command.getStart())) - command.delayStart(clk); -} - -void Slots::cleanUpSlots(sc_time time) -{ - slotSet.erase(slotSet.begin(), slotSet.lower_bound(time)); -} - -void Slots::blockSlot(sc_time time) -{ - sc_assert(isClkAligned(time, clk)); - slotSet.insert(time); -} - -bool Slots::isFree(sc_time time) -{ - return (slotSet.count(time) == 0); -} - -void Slots::blockSlots(sc_time begin, sc_time end, bool excludeBorders) -{ - sc_assert(isClkAligned(begin, clk)); - sc_assert(isClkAligned(end, clk)); - - if (excludeBorders) { - begin += clk; - end -= clk; - } - - for (sc_time time = begin; time <= end; time += clk) { - blockSlot(time); + static std::vector banks; + if (banks.size() == 0) { + for (unsigned int i = 0; i < NumberOfBanks; i++) + banks.push_back(Bank(i)); } + return banks; } +sc_time MemSpec::getReadAccessTime() const +{ + return clk * (BurstLength / DataRate); +} + +sc_time MemSpec::getWriteAccessTime() const +{ + return clk * (BurstLength / DataRate); +} + +unsigned MemSpec::getCommandLength(Command command) const +{ + return commandLength[command]; +} + +//sc_time MemSpec::getMinExecutionTimeForPowerDownCmd(Command command) const +//{ +// if (command == Command::PDEA || command == Command::PDEP) +// return tCKE; +// else if (command == Command::SREFEN) +// return tCKESR; +// else +// { +// SC_REPORT_FATAL("getMinimalExecutionTime", +// "command is not know or command has a fixed execution time"); +// return SC_ZERO_TIME; +// } +//} diff --git a/DRAMSys/library/src/controller/scheduler/IScheduler.h b/DRAMSys/library/src/configuration/memspec/MemSpec.h similarity index 54% rename from DRAMSys/library/src/controller/scheduler/IScheduler.h rename to DRAMSys/library/src/configuration/memspec/MemSpec.h index b40f29ec..0e95ed05 100644 --- a/DRAMSys/library/src/controller/scheduler/IScheduler.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.h @@ -31,40 +31,65 @@ * * Authors: * Janik Schlemminger - * Robert Gernhardt * Matthias Jung + * Lukas Steiner */ -#ifndef ISCHEDULER_H -#define ISCHEDULER_H +#ifndef MEMSPEC_H +#define MEMSPEC_H -#include +#include +#include #include "../../common/dramExtensions.h" -#include "../Command.h" -#include "../core/ControllerCore.h" +#include "../../controller/Command.h" +#include "../../common/utils.h" -typedef tlm::tlm_generic_payload gp; +using namespace tlm; -class IScheduler +struct MemSpec { -public: - virtual ~IScheduler() {} - IScheduler(ControllerCore &controllerCore) : controllerCore(controllerCore) {} + MemSpec(); + virtual ~MemSpec() {} - virtual void storeRequest(gp *payload) = 0; - virtual std::pair getNextRequest(Bank bank) = 0; - virtual gp *getPendingRequest(Bank bank) = 0; - static std::string sendername; + const std::vector &getBanks() const; -protected: - void printDebugMessage(std::string message); - Command getNextCommand(gp &payload); - Command getNextCommand(gp *payload); + sc_time getWriteAccessTime() const; + sc_time getReadAccessTime() const; - Command getReadWriteCommand(gp &payload); - Command getReadWriteCommand(gp *payload); + virtual sc_time getRefreshIntervalAB() const = 0; + virtual sc_time getRefreshIntervalPB() const = 0; - ControllerCore &controllerCore; + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const = 0; + virtual TimeInterval getIntervalOnDataStrobe(Command) const = 0; + + unsigned getCommandLength(Command) const; + + // Returns the minimum execution time for commands that have a variable execution time + //virtual sc_time getMinExecutionTimeForPowerDownCmd(Command command) const = 0; + + std::string MemoryId = "not defined."; + std::string MemoryType = "not defined."; + + unsigned int NumberOfRanks; + unsigned int NumberOfBankGroups; + unsigned int NumberOfBanks; + unsigned int NumberOfRows; + unsigned int NumberOfColumns; + unsigned int BurstLength; + unsigned int DataRate; + unsigned int bitWidth; + + unsigned int BanksPerRank; + unsigned int BanksPerGroup; + unsigned int GroupsPerRank; + + // Clock + double clkMHz; + sc_time clk; + + // Command lengths on bus, standardly one clock cycle + std::vector commandLength; }; -#endif // ISCHEDULER_H +#endif // MEMSPEC_H + diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp new file mode 100644 index 00000000..51b21916 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecDDR3.h" + +sc_time MemSpecDDR3::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecDDR3::getRefreshIntervalPB() const +{ + SC_REPORT_FATAL("MemSpecDDR3", "Per bank refresh not supported"); + return SC_ZERO_TIME; +} + +// Returns the execution time for commands that have a fixed execution time +sc_time MemSpecDDR3::getExecutionTime(Command command, const tlm_generic_payload &) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + return tRCD; + else if (command == Command::RD || command == Command::RDA) + return tRL + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFC; + else if (command == Command::PDXA || command == Command::PDXP || command == Command::SREFEX) + return clk; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecDDR3::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL, sc_time_stamp() + tRL + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL, sc_time_stamp() + tWL + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h new file mode 100644 index 00000000..c8c7beac --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECDDR3_H +#define MEMSPECDDR3_H + +#include "MemSpec.h" + +struct MemSpecDDR3 final : public MemSpec +{ + // Memspec Variables: + sc_time tCKE; // min time in pdna or pdnp + sc_time tCKESR; // min time in sref + sc_time tRAS; // active-time (act -> pre same bank) + sc_time tRC; // RAS-cycle-time (min time bw 2 succesive ACT to same bank) + sc_time tRCD; // act -> read/write + sc_time tRL; // read latency (read command start to data strobe) + sc_time tRTP; // read to precharge + sc_time tWL; // write latency + sc_time tWR; // write recovery (write to precharge) + sc_time tXP; // min delay to row access command after pdnpx pdnax + sc_time tXS; // min delay to row access command after srefx + sc_time tREFI; + sc_time tRFC; + sc_time tRP; + sc_time tDQSCK; + sc_time tCCD; + sc_time tFAW; + sc_time tRRD; + sc_time tWTR; + sc_time tXPDLL; + sc_time tXSDLL; + sc_time tAL; + + // Currents and Voltages: + double iDD0; + double iDD2N; + double iDD3N; + double iDD4R; + double iDD4W; + double iDD5; + double iDD6; + double vDD; + double iDD2P0; + double iDD2P1; + double iDD3P0; + double iDD3P1; + + virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalPB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECDDR3_H diff --git a/DRAMSys/library/src/controller/scheduler/IScheduler.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp similarity index 50% rename from DRAMSys/library/src/controller/scheduler/IScheduler.cpp rename to DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp index 2a9b6eff..0fd8bfb9 100644 --- a/DRAMSys/library/src/controller/scheduler/IScheduler.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,67 +30,54 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung + * Lukas Steiner */ -#include "IScheduler.h" -#include "../../common/DebugManager.h" -#include "../core/configuration/Configuration.h" +#include "MemSpecDDR4.h" -std::string IScheduler::sendername = "scheduler"; - -void IScheduler::printDebugMessage(std::string message) +sc_time MemSpecDDR4::getRefreshIntervalAB() const { - DebugManager::getInstance().printDebugMessage(IScheduler::sendername, message); + return tREFI; } -// Get the next command that is necessary to process the request representend by the payload -Command IScheduler::getNextCommand(gp &payload) +sc_time MemSpecDDR4::getRefreshIntervalPB() const { - Bank bank = DramExtension::getBank(payload); - if (!controllerCore.getRowBufferStates().rowBufferIsOpen(bank)) - { - return Command::Activate; - } - else if (controllerCore.getRowBufferStates().rowBufferIsOpen(bank) && - controllerCore.getRowBufferStates().getRowInRowBuffer(bank) != - DramExtension::getRow(payload)) - { - return Command::Precharge; - } + SC_REPORT_FATAL("MemSpecDDR4", "Per bank refresh not supported"); + return SC_ZERO_TIME; +} + +// Returns the execution time for commands that have a fixed execution time +sc_time MemSpecDDR4::getExecutionTime(Command command, const tlm_generic_payload &) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + return tRCD; + else if (command == Command::RD || command == Command::RDA) + return tRL + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFC; else { - return getReadWriteCommand(payload); + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; } } -Command IScheduler::getNextCommand(gp *payload) +TimeInterval MemSpecDDR4::getIntervalOnDataStrobe(Command command) const { - return getNextCommand(*payload); -} - -Command IScheduler::getReadWriteCommand(gp &payload) -{ - if (payload.get_command() == tlm::TLM_READ_COMMAND) - { - if (Configuration::getInstance().OpenPagePolicy) - return Command::Read; - else - return Command::ReadA; - } + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL, sc_time_stamp() + tRL + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL, sc_time_stamp() + tWL + getWriteAccessTime()); else { - if (Configuration::getInstance().OpenPagePolicy) - return Command::Write; - else - return Command::WriteA; + SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); + return TimeInterval(); } } - -Command IScheduler::getReadWriteCommand(gp *payload) -{ - return getReadWriteCommand(*payload); -} - diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h new file mode 100644 index 00000000..ecadfc18 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECDDR4_H +#define MEMSPECDDR4_H + +#include "MemSpec.h" + +struct MemSpecDDR4 final : public MemSpec +{ + // Memspec Variables: + sc_time tCKE; // min time in pdna or pdnp + sc_time tCKESR; // min time in sref + sc_time tRAS; // active-time (act -> pre same bank) + sc_time tRC; // RAS-cycle-time (min time bw 2 succesive ACT to same bank) + sc_time tRCD; // act -> read/write + sc_time tRL; // read latency (read command start to data strobe) + sc_time tRTP; // read to precharge + sc_time tWL; // write latency + sc_time tWR; // write recovery (write to precharge) + sc_time tXP; // min delay to row access command after pdnpx pdnax + sc_time tXS; // min delay to row access command after srefx + sc_time tREFI; + sc_time tRFC; + sc_time tRP; + sc_time tDQSCK; + sc_time tCCD_S; + sc_time tCCD_L; + sc_time tFAW; + sc_time tRRD_S; + sc_time tRRD_L; + sc_time tWTR_S; + sc_time tWTR_L; + sc_time tAL; + sc_time tXPDLL; + sc_time tXSDLL; + + // Currents and Voltages: + double iDD0; + double iDD2N; + double iDD3N; + double iDD4R; + double iDD4W; + double iDD5; + double iDD6; + double vDD; + double iDD02; + double iDD2P0; + double iDD2P1; + double iDD3P0; + double iDD3P1; + double iDD62; + double vDD2; + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECDDR4_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp new file mode 100644 index 00000000..5bcbcbc6 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecGDDR5.h" + +sc_time MemSpecGDDR5::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecGDDR5::getRefreshIntervalPB() const +{ + return tREFIPB; +} + +sc_time MemSpecGDDR5::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + clk; + else + return tRCDWR + clk; + } + else if (command == Command::RD || command == Command::RDA) + return tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFCPB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecGDDR5::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, + sc_time_stamp() + tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI, + sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpecGDDR5", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h new file mode 100644 index 00000000..c04bbfd2 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECGDDR5_H +#define MEMSPECGDDR5_H + +#include "MemSpec.h" + +struct MemSpecGDDR5 final : public MemSpec +{ + // Memspec Variables: + sc_time tRP; + sc_time tRAS; + sc_time tRC; + sc_time tRCDRD; + sc_time tRCDWR; + sc_time tRTP; + sc_time tRRDS; + sc_time tRRDL; + sc_time tCCDS; + sc_time tCCDL; + sc_time tCL; + sc_time tWCK2CKPIN; + sc_time tWCK2CK; + sc_time tWCK2DQO; + sc_time tRTW; + sc_time tWL; + sc_time tWCK2DQI; + sc_time tWR; + sc_time tWTRS; + sc_time tWTRL; + sc_time tCKE; + sc_time tPD; // = tCKE; + sc_time tXPN; + sc_time tREFI; + sc_time tREFIPB; + sc_time tRFC; + sc_time tRFCPB; + sc_time tRREFD; + sc_time tXS; + sc_time tFAW; + sc_time t32AW; + sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK; + sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK; + sc_time tPPD; + sc_time tLK; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECGDDR5_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp new file mode 100644 index 00000000..d7e148f6 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecGDDR5X.h" + +sc_time MemSpecGDDR5X::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecGDDR5X::getRefreshIntervalPB() const +{ + return tREFIPB; +} + +sc_time MemSpecGDDR5X::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + clk; + else + return tRCDWR + clk; + } + else if (command == Command::RD || command == Command::RDA) + return tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFCPB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecGDDR5X::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, + sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI, + sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpecGDDR5X", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h new file mode 100644 index 00000000..a69d76ce --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECGDDR5X_H +#define MEMSPECGDDR5X_H + +#include "MemSpec.h" + +struct MemSpecGDDR5X final : public MemSpec +{ + // Memspec Variables: + sc_time tRP; + sc_time tRAS; + sc_time tRC; + sc_time tRCDRD; + sc_time tRCDWR; + sc_time tRTP; + sc_time tRRDS; + sc_time tRRDL; + sc_time tCCDS; + sc_time tCCDL; + sc_time tRL; + sc_time tWCK2CKPIN; + sc_time tWCK2CK; + sc_time tWCK2DQO; + sc_time tRTW; + sc_time tWL; + sc_time tWCK2DQI; + sc_time tWR; + sc_time tWTRS; + sc_time tWTRL; + sc_time tCKE; + sc_time tPD; // = tCKE; + sc_time tXP; + sc_time tREFI; + sc_time tREFIPB; + sc_time tRFC; + sc_time tRFCPB; + sc_time tRREFD; + sc_time tXS; + sc_time tFAW; + sc_time t32AW; + sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK; + sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK; + sc_time tPPD; + sc_time tLK; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECGDDR5X_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp new file mode 100644 index 00000000..9be62f01 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecGDDR6.h" + +sc_time MemSpecGDDR6::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecGDDR6::getRefreshIntervalPB() const +{ + return tREFIPB; +} + +sc_time MemSpecGDDR6::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + clk; + else + return tRCDWR + clk; + } + else if (command == Command::RD || command == Command::RDA) + return tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFCPB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecGDDR6::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, + sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI, + sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpecGDDR6", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h new file mode 100644 index 00000000..43924408 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECGDDR6_H +#define MEMSPECGDDR6_H + +#include "MemSpec.h" + +struct MemSpecGDDR6 final : public MemSpec +{ + // Memspec Variables: + sc_time tRP; + sc_time tRAS; + sc_time tRC; + sc_time tRCDRD; + sc_time tRCDWR; + sc_time tRTP; + sc_time tRRDS; + sc_time tRRDL; + sc_time tCCDS; + sc_time tCCDL; + sc_time tRL; + sc_time tWCK2CKPIN; + sc_time tWCK2CK; + sc_time tWCK2DQO; + sc_time tRTW; + sc_time tWL; + sc_time tWCK2DQI; + sc_time tWR; + sc_time tWTRS; + sc_time tWTRL; + sc_time tCKE; + sc_time tPD; // = tCKE; + sc_time tCKESR; + sc_time tXP; + sc_time tREFI; + sc_time tREFIPB; + sc_time tRFC; + sc_time tRFCPB; + sc_time tRREFD; + sc_time tXS; + sc_time tFAW; + sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK; + sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK; + sc_time tPPD; + sc_time tLK; + sc_time tACTPDE; + sc_time tPREPDE; + sc_time tREFPDE; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECGDDR6_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp new file mode 100644 index 00000000..7fa61d1b --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecHBM2.h" + +MemSpecHBM2::MemSpecHBM2() +{ + commandLength[Command::ACT] = 2; +} + +sc_time MemSpecHBM2::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecHBM2::getRefreshIntervalPB() const +{ + return tREFISB; +} + +sc_time MemSpecHBM2::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + clk; + else + return tRCDWR + clk; + } + else if (command == Command::RD || command == Command::RDA) + return tRL + tDQSCK + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFCSB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecHBM2::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tDQSCK, + sc_time_stamp() + tRL + tDQSCK + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL, + sc_time_stamp() + tWL + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpecHBM2", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h new file mode 100644 index 00000000..72b96781 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECHBM2_H +#define MEMSPECHBM2_H + +#include "MemSpec.h" + +struct MemSpecHBM2 final : public MemSpec +{ + MemSpecHBM2(); + + // Memspec Variables: + sc_time tDQSCK; +// sc_time tDQSQ; // TODO: check actual value of this parameter + sc_time tRC; + sc_time tRAS; + sc_time tRCDRD; + sc_time tRCDWR; + sc_time tRRDL; + sc_time tRRDS; + sc_time tFAW; + sc_time tRTP; + sc_time tRP; + sc_time tRL; + sc_time tWL; + sc_time tPL; + sc_time tWR; + sc_time tCCDL; + sc_time tCCDS; +// sc_time tCCDR; // TODO: consecutive reads to different stack IDs + sc_time tWTRL; + sc_time tWTRS; + sc_time tRTW; + sc_time tXP; + sc_time tCKE; + sc_time tPD; // = tCKE; + sc_time tRDPDE; // = tRL + tPL + (BurstLength / DataRate) * clk + clk; + sc_time tWRPDE; // = tWL + tPL + (BurstLength / DataRate) * clk + clk + tWR; + sc_time tWRAPDE; // = tWL + tPL + (BurstLength / DataRate) * clk + clk + tWR; + sc_time tCKESR; // = tCKE + clk; + sc_time tRDSRE; // = tRL + tPL + (BurstLength / DataRate) * clk + clk; + sc_time tXS; + sc_time tRFC; + sc_time tRFCSB; + sc_time tRREFD; + sc_time tREFI; + sc_time tREFISB; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECHBM2_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp new file mode 100644 index 00000000..106d3c13 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecLPDDR4.h" + +MemSpecLPDDR4::MemSpecLPDDR4() +{ + commandLength[Command::ACT] = 4; + commandLength[Command::PRE] = 2; + commandLength[Command::PREA] = 2; + commandLength[Command::RD] = 4; + commandLength[Command::RDA] = 4; + commandLength[Command::WR] = 4; + commandLength[Command::WRA] = 4; + commandLength[Command::REFA] = 2; + commandLength[Command::REFB] = 2; + commandLength[Command::SREFEN] = 2; + commandLength[Command::SREFEX] = 2; +} + +sc_time MemSpecLPDDR4::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecLPDDR4::getRefreshIntervalPB() const +{ + return tREFIpb; +} + +sc_time MemSpecLPDDR4::getExecutionTime(Command command, const tlm_generic_payload &) const +{ + if (command == Command::PRE) + return tRPpb + clk; + else if (command == Command::PREA) + return tRPab + clk; + else if (command == Command::ACT) + return tRCD + 3 * clk; + else if (command == Command::RD || command == Command::RDA) + return tRL + tDQSCK + getReadAccessTime() + 3 * clk; + else if (command == Command::WR || command == Command::WRA) + return tWL + tDQSS + tDQS2DQ + getWriteAccessTime() + 3 * clk; + else if (command == Command::REFA) + return tRFCab + clk; + else if (command == Command::REFB) + return tRFCpb + clk; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecLPDDR4::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tDQSCK + 3 * clk, + sc_time_stamp() + tRL + tDQSCK + getReadAccessTime() + 3 * clk); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tDQSS + tDQS2DQ + 3 * clk, + sc_time_stamp() + tWL + tDQSS + tDQS2DQ + getWriteAccessTime() + 3 * clk); + else + { + SC_REPORT_FATAL("MemSpecLPDDR4", "Method was called with invalid argument"); + return TimeInterval(); + } +} + diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h new file mode 100644 index 00000000..67738e4e --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECLPDDR4_H +#define MEMSPECLPDDR4_H + +#include "MemSpec.h" + +struct MemSpecLPDDR4 final : public MemSpec +{ + MemSpecLPDDR4(); + + // Memspec Variables: + sc_time tREFI; + sc_time tREFIpb; + sc_time tRFCab; + sc_time tRFCpb; + sc_time tRPab; + sc_time tRPpb; + sc_time tPPD; + sc_time tRAS; + sc_time tRCD; + sc_time tFAW; + sc_time tRRD; + sc_time tCCD; + sc_time tRL; + sc_time tRPST; + sc_time tDQSCK; + sc_time tRTP; + sc_time tWL; + sc_time tDQSS; + sc_time tDQS2DQ; + sc_time tWR; + sc_time tWPRE; + sc_time tWTR; + sc_time tXP; + sc_time tSR; + sc_time tXSR; + sc_time tESCKE; + sc_time tCKE; + sc_time tCMDCKE; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECLPDDR4_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp new file mode 100644 index 00000000..af3af2b4 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecWideIO.h" + +sc_time MemSpecWideIO::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecWideIO::getRefreshIntervalPB() const +{ + SC_REPORT_FATAL("MemSpecWideIO", "Per bank refresh not supported"); + return SC_ZERO_TIME; +} + +// Returns the execution time for commands that have a fixed execution time +sc_time MemSpecWideIO::getExecutionTime(Command command, const tlm_generic_payload &) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + return tRCD; + else if (command == Command::RD || command == Command::RDA) + return tRL + tAC + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecWideIO::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tAC, + sc_time_stamp() + tRL + tAC + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL, + sc_time_stamp() + tWL + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h new file mode 100644 index 00000000..e504c63b --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECWIDEIO_H +#define MEMSPECWIDEIO_H + +#include "MemSpec.h" + +struct MemSpecWideIO final : public MemSpec +{ + // Memspec Variables: + sc_time tCKE; // min time in pdna or pdnp + sc_time tCKESR; // min time in sref + sc_time tRAS; // active-time (act -> pre same bank) + sc_time tRC; // RAS-cycle-time (min time bw 2 succesive ACT to same bank) + sc_time tRCD; // act -> read/write + sc_time tRL; // read latency (read command start to data strobe) + sc_time tWL; // write latency + sc_time tWR; // write recovery (write to precharge) + sc_time tXP; // min delay to row access command after pdnpx pdnax + sc_time tXS; // min delay to row access command after srefx + sc_time tREFI; + sc_time tRFC; + sc_time tRP; + sc_time tDQSCK; + sc_time tAC; + sc_time tCCD_R; + sc_time tCCD_W; + sc_time tRRD; + sc_time tTAW; + sc_time tWTR; + + // Currents and Voltages: + double iDD0; + double iDD2N; + double iDD3N; + double iDD4R; + double iDD4W; + double iDD5; + double iDD6; + double vDD; + double iDD02; + double iDD2P0; + double iDD2P02; + double iDD2P1; + double iDD2P12; + double iDD2N2; + double iDD3P0; + double iDD3P02; + double iDD3P1; + double iDD3P12; + double iDD3N2; + double iDD4R2; + double iDD4W2; + double iDD52; + double iDD62; + double vDD2; + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECWIDEIO_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp new file mode 100644 index 00000000..7d122e17 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecWideIO2.h" + +sc_time MemSpecWideIO2::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecWideIO2::getRefreshIntervalPB() const +{ + return tREFIpb; +} + +// Returns the execution time for commands that have a fixed execution time +sc_time MemSpecWideIO2::getExecutionTime(Command command, const tlm_generic_payload &) const +{ + if (command == Command::PRE) + return tRPpb; + else if (command == Command::PREA) + return tRPab; + else if (command == Command::ACT) + return tRCD; + else if (command == Command::RD || command == Command::RDA) + return tRL + tDQSCK + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + tDQSS + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFCab; + else if (command == Command::REFB) + return tRFCpb; + else + { + SC_REPORT_FATAL("MemSpecWideIO2::getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecWideIO2::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tDQSCK, + sc_time_stamp() + tRL + tDQSCK + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tDQSS, + sc_time_stamp() + tWL + tDQSS + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h new file mode 100644 index 00000000..4caff1e4 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECWIDEIO2_H +#define MEMSPECWIDEIO2_H + +#include "MemSpec.h" + +struct MemSpecWideIO2 final : public MemSpec +{ + // Memspec Variables: + sc_time tDQSCK; + sc_time tDQSS; + sc_time tCKE; + sc_time tRL; + sc_time tWL; + sc_time tRCpb; + sc_time tRCab; + sc_time tCKESR; + sc_time tXSR; + sc_time tXP; + sc_time tCCD; + sc_time tRTP; + sc_time tRCD; + sc_time tRPpb; + sc_time tRPab; + sc_time tRAS; + sc_time tWR; + sc_time tWTR; + sc_time tRRD; + sc_time tFAW; + sc_time tREFI; + sc_time tREFIpb; + sc_time tRFCab; + sc_time tRFCpb; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECWIDEIO2_H diff --git a/DRAMSys/library/src/controller/BankMachine.cpp b/DRAMSys/library/src/controller/BankMachine.cpp new file mode 100644 index 00000000..c0aaa913 --- /dev/null +++ b/DRAMSys/library/src/controller/BankMachine.cpp @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "BankMachine.h" + +BankMachine::BankMachine(SchedulerIF *scheduler, CheckerIF *checker, Bank bank) + : scheduler(scheduler), checker(checker), bank(bank) +{ + MemSpec *memSpec = Configuration::getInstance().memSpec; + rank = Rank(bank.ID() / memSpec->BanksPerRank); + bankgroup = BankGroup(bank.ID() / memSpec->BanksPerGroup); +} + +std::pair BankMachine::getNextCommand() +{ + if (sc_time_stamp() == timeToSchedule) + return std::pair(nextCommand, currentPayload); + else + return std::pair(Command::NOP, nullptr); +} + +void BankMachine::updateState(Command command) +{ + if (command == Command::ACT) + { + currentState = BmState::Activated; + currentRow = DramExtension::getRow(currentPayload); + } + else if (command == Command::PRE || command == Command::PREA) + currentState = BmState::Precharged; + else if (command == Command::RD || command == Command::WR) + currentPayload = nullptr; + else if (command == Command::RDA || command == Command::WRA) + { + currentState = BmState::Precharged; + currentPayload = nullptr; + } + else if (command == Command::PDEA || command == Command::PDEP || command == Command::SREFEN) + sleeping = true; + else if (command == Command::REFA || command == Command::REFB) + { + sleeping = false; + blocked = false; + } + else if (command == Command::PDXA || command == Command::PDXP) + sleeping = false; +} + +void BankMachine::block() +{ + blocked = true; +} + +Rank BankMachine::getRank() +{ + return rank; +} + +BankGroup BankMachine::getBankGroup() +{ + return bankgroup; +} + +Bank BankMachine::getBank() +{ + return bank; +} + +Row BankMachine::getOpenRow() +{ + return currentRow; +} + +BmState BankMachine::getState() +{ + return currentState; +} + +bool BankMachine::isIdle() +{ + return (currentPayload == nullptr); +} + +BankMachineOpen::BankMachineOpen(SchedulerIF *scheduler, CheckerIF *checker, Bank bank) + : BankMachine(scheduler, checker, bank) {} + +sc_time BankMachineOpen::start() +{ + timeToSchedule = sc_max_time(); + sc_time delay = sc_max_time() - sc_time_stamp(); + + if (sleeping) + return delay; + + if (currentPayload == nullptr) + { + currentPayload = scheduler->getNextRequest(this); + if (currentPayload == nullptr) + return delay; + } + + if (currentState == BmState::Precharged && !blocked) // row miss + { + delay = checker->delayToSatisfyConstraints(Command::ACT, rank, bankgroup, bank); + nextCommand = Command::ACT; + } + else if (currentState == BmState::Activated) + { + if (DramExtension::getRow(currentPayload) == currentRow) // row hit + { + if (currentPayload->get_command() == TLM_READ_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::RD, rank, bankgroup, bank); + nextCommand = Command::RD; + } + else if (currentPayload->get_command() == TLM_WRITE_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::WR, rank, bankgroup, bank); + nextCommand = Command::WR; + } + else + SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); + } + else if (!blocked) // row miss + { + delay = checker->delayToSatisfyConstraints(Command::PRE, rank, bankgroup, bank); + nextCommand = Command::PRE; + } + } + + timeToSchedule = sc_time_stamp() + delay; + return delay; +} + +BankMachineClosed::BankMachineClosed(SchedulerIF *scheduler, CheckerIF *checker, Bank bank) + : BankMachine(scheduler, checker, bank) {} + +sc_time BankMachineClosed::start() +{ + timeToSchedule = sc_max_time(); + sc_time delay = sc_max_time() - sc_time_stamp(); + + if (sleeping) + return delay; + + if (currentPayload == nullptr) + { + currentPayload = scheduler->getNextRequest(this); + if (currentPayload == nullptr) + return delay; + } + + if (currentState == BmState::Precharged && !blocked) // row miss + { + delay = checker->delayToSatisfyConstraints(Command::ACT, rank, bankgroup, bank); + nextCommand = Command::ACT; + } + else if (currentState == BmState::Activated) + { + if (currentPayload->get_command() == TLM_READ_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::RDA, rank, bankgroup, bank); + nextCommand = Command::RDA; + } + else if (currentPayload->get_command() == TLM_WRITE_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::WRA, rank, bankgroup, bank); + nextCommand = Command::WRA; + } + else + SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); + } + timeToSchedule = sc_time_stamp() + delay; + return delay; +} + +BankMachineOpenAdaptive::BankMachineOpenAdaptive(SchedulerIF *scheduler, CheckerIF *checker, Bank bank) + : BankMachine(scheduler, checker, bank) {} + +sc_time BankMachineOpenAdaptive::start() +{ + timeToSchedule = sc_max_time(); + sc_time delay = sc_max_time() - sc_time_stamp(); + + if (sleeping) + return delay; + + if (currentPayload == nullptr) + { + currentPayload = scheduler->getNextRequest(this); + if (currentPayload == nullptr) + return delay; + } + + if (currentState == BmState::Precharged && !blocked) // row miss + { + delay = checker->delayToSatisfyConstraints(Command::ACT, rank, bankgroup, bank); + nextCommand = Command::ACT; + } + else if (currentState == BmState::Activated) + { + if (DramExtension::getRow(currentPayload) == currentRow) // row hit + { + if (scheduler->hasRequest(bank) && !scheduler->hasRowHit(bank, currentRow)) + { + if (currentPayload->get_command() == TLM_READ_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::RDA, rank, bankgroup, bank); + nextCommand = Command::RDA; + } + else if (currentPayload->get_command() == TLM_WRITE_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::WRA, rank, bankgroup, bank); + nextCommand = Command::WRA; + } + else + SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); + } + else + { + if (currentPayload->get_command() == TLM_READ_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::RD, rank, bankgroup, bank); + nextCommand = Command::RD; + } + else if (currentPayload->get_command() == TLM_WRITE_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::WR, rank, bankgroup, bank); + nextCommand = Command::WR; + } + else + SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); + } + } + else if (!blocked) // row miss + { + delay = checker->delayToSatisfyConstraints(Command::PRE, rank, bankgroup, bank); + nextCommand = Command::PRE; + } + } + timeToSchedule = sc_time_stamp() + delay; + return delay; +} + +BankMachineClosedAdaptive::BankMachineClosedAdaptive(SchedulerIF *scheduler, CheckerIF *checker, Bank bank) + : BankMachine(scheduler, checker, bank) {} + +sc_time BankMachineClosedAdaptive::start() +{ + timeToSchedule = sc_max_time(); + sc_time delay = sc_max_time() - sc_time_stamp(); + + if (sleeping) + return delay; + + if (currentPayload == nullptr) + { + currentPayload = scheduler->getNextRequest(this); + if (currentPayload == nullptr) + return delay; + } + + if (currentState == BmState::Precharged && !blocked) // row miss + { + delay = checker->delayToSatisfyConstraints(Command::ACT, rank, bankgroup, bank); + nextCommand = Command::ACT; + } + else if (currentState == BmState::Activated) + { + if (DramExtension::getRow(currentPayload) == currentRow) // row hit + { + if (scheduler->hasRowHit(bank, currentRow)) + { + if (currentPayload->get_command() == TLM_READ_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::RD, rank, bankgroup, bank); + nextCommand = Command::RD; + } + else if (currentPayload->get_command() == TLM_WRITE_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::WR, rank, bankgroup, bank); + nextCommand = Command::WR; + } + else + SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); + } + else + { + if (currentPayload->get_command() == TLM_READ_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::RDA, rank, bankgroup, bank); + nextCommand = Command::RDA; + } + else if (currentPayload->get_command() == TLM_WRITE_COMMAND) + { + delay = checker->delayToSatisfyConstraints(Command::WRA, rank, bankgroup, bank); + nextCommand = Command::WRA; + } + else + SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); + } + } + else if (!blocked) // row miss TODO: remove this, can never happen + { + delay = checker->delayToSatisfyConstraints(Command::PRE, rank, bankgroup, bank); + nextCommand = Command::PRE; + SC_REPORT_FATAL("BankMachine", "Should never be reached for this policy"); + } + } + timeToSchedule = sc_time_stamp() + delay; + return delay; +} diff --git a/DRAMSys/library/src/controller/BankMachine.h b/DRAMSys/library/src/controller/BankMachine.h new file mode 100644 index 00000000..49fce270 --- /dev/null +++ b/DRAMSys/library/src/controller/BankMachine.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef BANKMACHINE_H +#define BANKMACHINE_H + +#include +#include +#include +#include "../common/dramExtensions.h" +#include "Controller.h" +#include "Command.h" +#include "scheduler/SchedulerIF.h" +#include "checker/CheckerIF.h" + +using namespace tlm; + +class SchedulerIF; +class CheckerIF; + +enum class BmState +{ + Precharged, + Activated +}; + +class BankMachine +{ +public: + virtual ~BankMachine() {} + virtual sc_time start() = 0; + std::pair getNextCommand(); + void updateState(Command); + void block(); + + Rank getRank(); + BankGroup getBankGroup(); + Bank getBank(); + Row getOpenRow(); + BmState getState(); + bool isIdle(); + +protected: + BankMachine(SchedulerIF *, CheckerIF *, Bank); + tlm_generic_payload *currentPayload = nullptr; + SchedulerIF *scheduler; + CheckerIF *checker; + Command nextCommand; + BmState currentState = BmState::Precharged; + Row currentRow; + sc_time timeToSchedule = sc_max_time(); + Rank rank = Rank(0); + BankGroup bankgroup = BankGroup(0); + Bank bank; + bool blocked = false; + bool sleeping = false; +}; + +class BankMachineOpen final : public BankMachine +{ +public: + BankMachineOpen(SchedulerIF *, CheckerIF *, Bank); + sc_time start(); +}; + +class BankMachineClosed final : public BankMachine +{ +public: + BankMachineClosed(SchedulerIF *, CheckerIF *, Bank); + sc_time start(); +}; + +class BankMachineOpenAdaptive final : public BankMachine +{ +public: + BankMachineOpenAdaptive(SchedulerIF *, CheckerIF *, Bank); + sc_time start(); +}; + +class BankMachineClosedAdaptive final : public BankMachine +{ +public: + BankMachineClosedAdaptive(SchedulerIF *, CheckerIF *, Bank); + sc_time start(); +}; + +#endif // BANKMACHINE_H diff --git a/DRAMSys/library/src/controller/Command.cpp b/DRAMSys/library/src/controller/Command.cpp index 4ced60b8..290f7c44 100644 --- a/DRAMSys/library/src/controller/Command.cpp +++ b/DRAMSys/library/src/controller/Command.cpp @@ -42,54 +42,50 @@ std::string commandToString(Command command) { switch (command) { - case Command::Read: + case Command::RD: return "RD"; break; - case Command::ReadA: + case Command::RDA: return "RDA"; break; - case Command::Write: + case Command::WR: return "WR"; break; - case Command::WriteA: + case Command::WRA: return "WRA"; break; - case Command::PreB: - return "PREB"; - break; - case Command::Precharge: + case Command::PRE: return "PRE"; break; - case Command::ActB: - return "ACTB"; - break; - case Command::Activate: + case Command::ACT: return "ACT"; break; - case Command::PrechargeAll: - return "PRE_ALL"; + case Command::PREA: + return "PREA"; break; - case Command::AutoRefresh: - return "REF"; + case Command::REFA: + return "REFA"; break; - - case Command::PDNA: - return "PDNA"; + case Command::REFB: + return "REFB"; break; - case Command::PDNAX: - return "PDNAX"; + case Command::PDEA: + return "PDEA"; break; - case Command::PDNP: - return "PDNP"; + case Command::PDXA: + return "PDXA"; break; - case Command::PDNPX: - return "PDNPX"; + case Command::PDEP: + return "PDEP"; break; - case Command::SREF: - return "SREF"; + case Command::PDXP: + return "PDXP"; break; - case Command::SREFX: - return "SREFX"; + case Command::SREFEN: + return "SREFEN"; + break; + case Command::SREFEX: + return "SREFEX"; break; case Command::NOP: @@ -106,26 +102,31 @@ std::string commandToString(Command command) const std::vector &getAllCommands() { - static std::vector allCommands( { Command::PreB, - Command::Precharge, - Command::PrechargeAll, - Command::ActB, - Command::Activate, - Command::Read, - Command::Write, - Command::ReadA, - Command::WriteA, - Command::AutoRefresh, - Command::PDNA, - Command::PDNAX, - Command::PDNP, - Command::PDNPX, - Command::SREF, - Command::SREFX + static std::vector allCommands( { Command::NOP, + Command::RD, + Command::WR, + Command::RDA, + Command::WRA, + Command::PRE, + Command::ACT, + Command::REFB, + Command::PREA, + Command::REFA, + Command::PDEA, + Command::PDXA, + Command::PDEP, + Command::PDXP, + Command::SREFEN, + Command::SREFEX }); return allCommands; } +unsigned numberOfCommands() +{ + return 16; +} + bool commandIsIn(Command command, std::vector commands) { for (Command c : commands) { @@ -134,3 +135,40 @@ bool commandIsIn(Command command, std::vector commands) } return false; } + +std::array phaseOfCommand = {UNINITIALIZED_PHASE, + BEGIN_RD, + BEGIN_WR, + BEGIN_RDA, + BEGIN_WRA, + BEGIN_PRE, + BEGIN_ACT, + BEGIN_REFB, + BEGIN_PREA, + BEGIN_REFA, + BEGIN_PDNA, + END_PDNA, + BEGIN_PDNP, + END_PDNP, + BEGIN_SREF, + END_SREF}; + +bool isBankCommand(Command command) +{ + return (command <= 7); +} + +bool isRankCommand(Command command) +{ + return (command >= 8); +} + +bool isCasCommand(Command command) +{ + return (command <= 4); +} + +bool isRasCommand(Command command) +{ + return (command >= 5); +} diff --git a/DRAMSys/library/src/controller/Command.h b/DRAMSys/library/src/controller/Command.h index e8aa28e7..8365ef4d 100644 --- a/DRAMSys/library/src/controller/Command.h +++ b/DRAMSys/library/src/controller/Command.h @@ -38,29 +38,41 @@ #include #include +#include +#include +#include "../common/protocol.h" -enum class Command { +using namespace tlm; + +enum Command +{ NOP, - PreB, - Precharge, - PrechargeAll, - ActB, - Activate, - Read, - Write, - ReadA, - WriteA, - AutoRefresh, - PDNA, - PDNAX, - PDNP, - PDNPX, - SREF, - SREFX + RD, + WR, + RDA, + WRA, + PRE, + ACT, + REFB, + PREA, + REFA, + PDEA, + PDXA, + PDEP, + PDXP, + SREFEN, + SREFEX }; std::string commandToString(Command command); const std::vector &getAllCommands(); +unsigned numberOfCommands(); bool commandIsIn(Command command, std::vector commands); +bool isBankCommand(Command command); +bool isRankCommand(Command command); +bool isCasCommand(Command command); +bool isRasCommand(Command command); + +extern std::array phaseOfCommand; #endif // COMMAND_H diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 1fac6814..54811455 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,621 +29,425 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Felipe S. Prado + * Author: Lukas Steiner */ -#include "core/configuration/Configuration.h" #include "Controller.h" -#include -Controller::Controller(sc_module_name /*name*/) : - frontendPEQ(this, &Controller::frontendPEQCallback), - dramPEQ(this, &Controller::dramPEQCallback), - controllerCorePEQ(this, &Controller::controllerCorePEQCallback), - debugManager(DebugManager::getInstance()) +#include "../configuration/Configuration.h" +#include "scheduler/SchedulerFifo.h" +#include "scheduler/SchedulerFrFcfs.h" +#include "cmdmux/CmdMuxStrict.h" +#include "cmdmux/CmdMuxOldest.h" +#include "../common/dramExtensions.h" +#include "../common/protocol.h" +#include "checker/CheckerDDR3.h" +#include "checker/CheckerDDR4.h" +#include "checker/CheckerWideIO.h" +#include "checker/CheckerLPDDR4.h" +#include "checker/CheckerWideIO2.h" +#include "checker/CheckerHBM2.h" +#include "checker/CheckerGDDR5.h" +#include "checker/CheckerGDDR5X.h" +#include "checker/CheckerGDDR6.h" +#include "refresh/RefreshManager.h" +#include "refresh/RefreshManagerDummy.h" +#include "refresh/RefreshManagerBankwise.h" +#include "powerdown/PowerDownManagerStaggered.h" +#include "powerdown/PowerDownManagerDummy.h" + +Controller::Controller(sc_module_name name) : + GenericController(name) { - controllerCore = new ControllerCore("core", *this, numberOfPayloadsInSystem); - buildScheduler(); - iSocket.register_nb_transport_bw(this, &Controller::nb_transport_bw); - tSocket.register_nb_transport_fw(this, &Controller::nb_transport_fw); - tSocket.register_transport_dbg(this, &Controller::transport_dbg); + SC_METHOD(controllerMethod); + sensitive << beginReqEvent << endRespEvent << controllerEvent << dataResponseEventQueue; + dont_initialize(); + + Configuration &config = Configuration::getInstance(); + MemSpec *memSpec = config.memSpec; + ranksNumberOfPayloads = std::vector(memSpec->NumberOfRanks); + + // instantiate timing checker + if (memSpec->MemoryType == "DDR3") + checker = new CheckerDDR3(); + else if (memSpec->MemoryType == "DDR4") + checker = new CheckerDDR4(); + else if (memSpec->MemoryType == "WIDEIO_SDR") + checker = new CheckerWideIO(); + else if (memSpec->MemoryType == "LPDDR4") + checker = new CheckerLPDDR4(); + else if (memSpec->MemoryType == "WIDEIO2") + checker = new CheckerWideIO2(); + else if (memSpec->MemoryType == "HBM2") + checker = new CheckerHBM2(); + else if (memSpec->MemoryType == "GDDR5") + checker = new CheckerGDDR5(); + else if (memSpec->MemoryType == "GDDR5X") + checker = new CheckerGDDR5X(); + else if (memSpec->MemoryType == "GDDR6") + checker = new CheckerGDDR6(); + else + SC_REPORT_FATAL("Controller", "Unsupported DRAM type!"); + + // instantiate scheduler and command mux + if (config.Scheduler == "FifoStrict") + { + scheduler = new SchedulerFifo(); + commandMux = new CmdMuxStrict(); + } + else if (config.Scheduler == "FrFcfs") + { + scheduler = new SchedulerFrFcfs(); + commandMux = new CmdMuxOldest(); + } + else + SC_REPORT_FATAL("Controller", "Selected scheduler not supported!"); + + // instantiate bank machines (one per bank) + if (config.OpenPagePolicy) + { + if (config.AdaptivePagePolicy) + { + for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++) + bankMachines.push_back(new BankMachineOpenAdaptive(scheduler, checker, Bank(bankID))); + } + else + { + for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++) + bankMachines.push_back(new BankMachineOpen(scheduler, checker, Bank(bankID))); + } + } + else + { + if (config.AdaptivePagePolicy) + { + for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++) + bankMachines.push_back(new BankMachineClosedAdaptive(scheduler, checker, Bank(bankID))); + } + else + { + for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++) + bankMachines.push_back(new BankMachineClosed(scheduler, checker, Bank(bankID))); + } + } + + for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) + { + bankMachinesOnRank.push_back(std::vector(bankMachines.begin() + rankID * memSpec->BanksPerRank, + bankMachines.begin() + (rankID + 1) * memSpec->BanksPerRank)); + } + + // instantiate power-down managers (one per rank) + if (config.PowerDownMode == EPowerDownMode::NoPowerDown) + { + for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) + { + PowerDownManagerIF *manager = new PowerDownManagerDummy(); + powerDownManagers.push_back(manager); + } + } + else if (config.PowerDownMode == EPowerDownMode::Staggered) + { + for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) + { + PowerDownManagerIF *manager = new PowerDownManagerStaggered(Rank(rankID), checker); + powerDownManagers.push_back(manager); + manager->triggerEntry(TriggerSource::Controller); + controllerEvent.notify(manager->start()); + } + } + else + SC_REPORT_FATAL("Controller", "Selected power-down mode not supported!"); + + // instantiate refresh managers (one per rank) + if (config.ControllerCoreRefDisable) + { + for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) + refreshManagers.push_back(new RefreshManagerDummy()); + } + else if (config.BankwiseLogic) + { + for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) + { + // TODO: remove bankMachines in constructor + RefreshManagerIF *manager = new RefreshManagerBankwise + (bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker); + refreshManagers.push_back(manager); + controllerEvent.notify(manager->start()); + } + } + else + { + for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) + { + RefreshManagerIF *manager = new RefreshManager + (bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker); + refreshManagers.push_back(manager); + controllerEvent.notify(manager->start()); + } + } + + startBandwidthIdleCollector(); } Controller::~Controller() { - // Bandwidth: - sc_time activeTime = numberOfTransactionsServed - * Configuration::getInstance().memSpec->BurstLength - / Configuration::getInstance().memSpec->DataRate - * Configuration::getInstance().memSpec->clk; + endBandwithIdleCollector(); - sc_time idleTime = getIdleTime(); - sc_time endTime = getEndTime(); - sc_time startTime = getStartTime(); - - double bandwidth = (activeTime / (endTime - startTime) * 100); - double bandwidth_IDLE = ((activeTime) / (endTime - startTime - idleTime) * 100); - - double maxBandwidth = ( - // clk in Mhz e.g. 800 [MHz]: - (1000000 / Configuration::getInstance().memSpec->clk.to_double()) - // DataRate e.g. 2 - * Configuration::getInstance().memSpec->DataRate - // BusWidth e.g. 8 or 64 - * Configuration::getInstance().memSpec->bitWidth - // Number of devices on a DIMM e.g. 8 - * Configuration::getInstance().NumberOfDevicesOnDIMM ) / ( 1024 ); - - cout << name() << string(" Total Time: ") - << (endTime - startTime).to_string() - << endl; - cout << name() << string(" AVG BW: ") - << std::fixed << std::setprecision(2) - << ((bandwidth / 100)*maxBandwidth) - << " Gibit/s (" << bandwidth << " %)" - << endl; - cout << name() << string(" AVG BW/IDLE: ") - << std::fixed << std::setprecision(2) - << ((bandwidth_IDLE / 100)*maxBandwidth) - << " Gibit/s (" << (bandwidth_IDLE) << " %)" - << endl; - cout << name() << string(" MAX BW: ") - << std::fixed << std::setprecision(2) - << maxBandwidth << " Gibit/s" - << endl; - - delete controllerCore; + for (auto it : refreshManagers) + delete it; + for (auto it : powerDownManagers) + delete it; + for (auto it : bankMachines) + delete it; + delete commandMux; delete scheduler; + delete checker; } -void Controller::buildScheduler() +void Controller::controllerMethod() { - string selectedScheduler = Configuration::getInstance().Scheduler; + // (1) Release payload if arbiter has accepted the result + if (sc_time_stamp() == timeToRelease && payloadToRelease != nullptr) + releasePayload(); - if (selectedScheduler == "Fifo") { - scheduler = new Fifo(*controllerCore); - } else if (selectedScheduler == "FifoStrict") { - scheduler = new FifoStrict(*this, *controllerCore); - } else if (selectedScheduler == "FrFcfs") { - scheduler = new FrFcfs(*controllerCore); - } else if (selectedScheduler == "FrFcfsRp") { - scheduler = new FrFcfsRp(*controllerCore); - } else if (selectedScheduler == "FrFcfsGrp") { - scheduler = new FrFcfsGrp(*controllerCore, this); - } else if (selectedScheduler == "Grp") { - scheduler = new Grp(*controllerCore, this); - } else if (selectedScheduler == "SMS") { - scheduler = new SMS("SMS", *controllerCore, - Configuration::getInstance().SJFProbability); - } - //else if (selectedScheduler == "PAR_BS") - //{ - // scheduler = new PAR_BS(*controllerCore,Configuration::getInstance().RefreshAwareScheduling, - // Configuration::getInstance().Capsize); - //} - // else if (selectedScheduler == "Grouper") - // { - // scheduler = new ReadWriteGrouper(*controllerCore); - // } - else - reportFatal(name(), "unsupported scheduler: " + selectedScheduler); -} - -//Send the next scheduled command to the DRAM -void Controller::send(const ScheduledCommand &command, - tlm_generic_payload &payload) -{ - sc_assert(command.getStart() >= sc_time_stamp()); - - tlm_phase phase; - - switch (command.getCommand()) + // (2) Send next result to arbiter + if (payloadToRelease == nullptr && !responseQueue.empty()) { - //TODO: refactor tlm recorder - case Command::Read: - phase = BEGIN_RD; - break; - case Command::ReadA: - phase = BEGIN_RDA; - break; - case Command::Write: - phase = BEGIN_WR; - break; - case Command::WriteA: - phase = BEGIN_WRA; - break; - case Command::AutoRefresh: - if (!Configuration::getInstance().BankwiseLogic) - phase = BEGIN_REFA; - else - phase = BEGIN_REFB; - break; - case Command::Activate: - phase = BEGIN_ACT; - break; - case Command::ActB: - phase = BEGIN_ACTB; - break; - case Command::Precharge: - phase = BEGIN_PRE; - break; - case Command::PreB: - phase = BEGIN_PREB; - break; - case Command::PrechargeAll: - phase = BEGIN_PRE_ALL; - break; - case Command::PDNA: - if (!Configuration::getInstance().BankwiseLogic) - phase = BEGIN_PDNA; - else - phase = BEGIN_PDNAB; - break; - case Command::PDNAX: - if (!Configuration::getInstance().BankwiseLogic) - phase = END_PDNA; - else - phase = END_PDNAB; - break; - case Command::PDNP: - if (!Configuration::getInstance().BankwiseLogic) - phase = BEGIN_PDNP; - else - phase = BEGIN_PDNPB; - break; - case Command::PDNPX: - if (!Configuration::getInstance().BankwiseLogic) - phase = END_PDNP; - else - phase = END_PDNPB; - break; - case Command::SREF: - if (!Configuration::getInstance().BankwiseLogic) - phase = BEGIN_SREF; - else - phase = BEGIN_SREFB; - break; - case Command::SREFX: - if (!Configuration::getInstance().BankwiseLogic) - phase = END_SREF; - else - phase = END_SREFB; - break; - default: - SC_REPORT_FATAL(0, "unsupported command was sent by controller"); - break; + std::pair element = responseQueue.front(); + if (sc_time_stamp() >= element.first) + { + payloadToRelease = element.second; + responseQueue.pop(); + sendToFrontend(payloadToRelease, BEGIN_RESP); + } } - sc_time notDelay = command.getStart() - sc_time_stamp(); - printDebugMessage(phaseNameToString(phase) + " notification in " + - notDelay.to_string()); - controllerCorePEQ.notify(payload, phase, notDelay); + // (3) Accept new request from arbiter and start appropriate BM if necessary + if (sc_time_stamp() >= timeToAcquire && payloadToAcquire != nullptr) + { + if (scheduler->hasBufferSpace(payloadToAcquire)) + { + Bank bank = DramExtension::getBank(payloadToAcquire); + acquirePayload(); + + if (bankMachines[bank.ID()]->isIdle()) + bankMachines[bank.ID()]->start(); + } + else + PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!"); + } + + // (4) Start refresh and power-down managers to issue requests for the current time + // TODO: check if the order of start() matters, do I always need to start them at this point? No, only if something happened in steps 1-3!!! + for (auto it : refreshManagers) + it->start(); + for (auto it : powerDownManagers) + it->start(); + + // (5) Choose one request and send it to DRAM + std::pair commandPair; + std::vector> readyCommands; + // (5.1) Check for power-down commands (PDEA/PDEP/SREFEN or PDXA/PDXP/SREFEX) + for (unsigned rankID = 0; rankID < Configuration::getInstance().memSpec->NumberOfRanks; rankID++) + { + commandPair = powerDownManagers[rankID]->getNextCommand(); + if (commandPair.second != nullptr) + readyCommands.push_back(commandPair); + else + { + // (5.2) Check for refresh commands (PREA/PRE or REFA/REFB) + commandPair = refreshManagers[rankID]->getNextCommand(); + if (commandPair.second != nullptr) + readyCommands.push_back(commandPair); + else + { + // (5.3) Check for bank commands (PRE, ACT, RD/RDA or WR/WRA) + for (auto it : bankMachinesOnRank[rankID]) + { + commandPair = it->getNextCommand(); + if (commandPair.second != nullptr) + readyCommands.push_back(commandPair); + } + } + } + } + + bool readyCmdBlocked = false; + if (!readyCommands.empty()) + { + commandPair = commandMux->selectCommand(readyCommands); + if (commandPair.second != nullptr) // can happen with FIFO strict + { + Rank rank = DramExtension::getRank(commandPair.second); + BankGroup bankgroup = DramExtension::getBankGroup(commandPair.second); + Bank bank = DramExtension::getBank(commandPair.second); + + if (isRankCommand(commandPair.first)) + { + for (auto it : bankMachinesOnRank[rank.ID()]) + it->updateState(commandPair.first); + } + else + bankMachines[bank.ID()]->updateState(commandPair.first); + + refreshManagers[rank.ID()]->updateState(commandPair.first, commandPair.second); + powerDownManagers[rank.ID()]->updateState(commandPair.first); + checker->insert(commandPair.first, rank, bankgroup, bank); + + sendToDram(commandPair.first, commandPair.second); + } + else + readyCmdBlocked = true; + } + + // (6) Restart bank machines and refresh managers to issue new requests for the future + // TODO: check if all calls are necessary + sc_time delayForNextTrigger = sc_max_time(); + for (auto it : bankMachines) + { + sc_time localDelay = it->start(); + if (!(localDelay == SC_ZERO_TIME && readyCmdBlocked)) + delayForNextTrigger = std::min(delayForNextTrigger, localDelay); + } + if (payloadToAcquire != nullptr && sc_time_stamp() >= timeToAcquire && scheduler->hasBufferSpace(payloadToAcquire)) + acquirePayload(); + for (auto it : refreshManagers) + delayForNextTrigger = std::min(delayForNextTrigger, it->start()); + for (auto it : powerDownManagers) + delayForNextTrigger = std::min(delayForNextTrigger, it->start()); + + if (!(delayForNextTrigger == (sc_max_time() - sc_time_stamp()))) + controllerEvent.notify(delayForNextTrigger); } -//Trigger the next planned refresh or the power down mode on the DRAM -void Controller::send(Trigger trigger, sc_time time, - tlm_generic_payload &payload) +tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans, + tlm_phase &phase, sc_time &delay) { - sc_assert(time >= sc_time_stamp()); + sc_time notificationDelay = delay; - tlm_phase phase; - - if (trigger == Trigger::REFTrigger) { - phase = REF_TRIGGER; - } else if (trigger == Trigger::PDNTrigger) { - phase = PDN_TRIGGER; - } else { - SC_REPORT_FATAL("controller wrapper", "unknown trigger"); + if (phase == BEGIN_REQ) + { + notificationDelay += Configuration::getInstance().memSpec->clk; + payloadToAcquire = &trans; + timeToAcquire = sc_time_stamp() + notificationDelay; + beginReqEvent.notify(notificationDelay); } + else if (phase = END_RESP) + { + notificationDelay += Configuration::getInstance().memSpec->clk; + timeToRelease = sc_time_stamp() + notificationDelay; + endRespEvent.notify(notificationDelay); + } + else + SC_REPORT_FATAL(0, "nb_transport_fw in controller was triggered with unknown phase"); - sc_time delay = time - sc_time_stamp(); - printDebugMessage(phaseNameToString(phase) + " notification in " + + PRINTDEBUGMESSAGE(name(), "[fw] " + phaseNameToString(phase) + " notification in " + + notificationDelay.to_string()); + + return TLM_ACCEPTED; +} + +tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &trans, + tlm_phase &phase, sc_time &delay) +{ + PRINTDEBUGMESSAGE(name(), "[bw] " + phaseNameToString(phase) + " notification in " + delay.to_string()); - controllerCorePEQ.notify(payload, phase, delay); -} -void Controller::controllerCorePEQCallback(tlm_generic_payload &payload, - const tlm_phase &phase) -{ - if (phase == REF_TRIGGER) + if (phase == END_RD || phase == END_RDA || phase == END_WR || phase == END_WRA) { - controllerCore->triggerRefresh(payload); - } - else if (phase == PDN_TRIGGER) - { - controllerCore->powerDownManager->sleep(DramExtension::getExtension( - payload).getBank(), sc_time_stamp()); - } - else - { - Bank bank = DramExtension::getBank(payload); - sendToDram(payload, phase, SC_ZERO_TIME); + // TODO: check this part (order of responses) + responseQueue.push({(sc_time_stamp() + delay), &trans}); + dataResponseEventQueue.notify(delay); - if (phase == BEGIN_RD || phase == BEGIN_WR) - scheduleNextFromScheduler(DramExtension::getBank(payload)); - else if (phase == BEGIN_REFB) - printDebugMessage("Entering REFB on bank " + to_string(bank.ID())); - else if (phase == BEGIN_REFA) - printDebugMessage("Entering REFA"); - else if (containsPhase(phase, { BEGIN_PDNAB, BEGIN_PDNPB, BEGIN_SREFB })) - printDebugMessage("Entering PowerDown " + phaseNameToString( - phase) + " on bank " + to_string(bank.ID())); - else if (containsPhase(phase, { END_PDNAB, END_PDNPB, END_SREFB })) - printDebugMessage("Leaving PowerDown " + phaseNameToString( - phase) + " on bank " + to_string(bank.ID())); - else if (containsPhase(phase, { BEGIN_PDNA, BEGIN_PDNP, BEGIN_SREF })) - printDebugMessage("Entering PowerDown " + phaseNameToString( - phase) + " on all banks"); - else if (containsPhase(phase, { END_PDNA, END_PDNP, END_SREF })) - printDebugMessage("Leaving PowerDown " + phaseNameToString( - phase) + " on all banks" ); - else if (containsPhase(phase, { BEGIN_RD, BEGIN_WR, BEGIN_ACTB, BEGIN_ACT, BEGIN_PREB, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA })) { - printDebugMessage("Controller has sent to DRAM this: " + phaseNameToString( - phase) + " bank " + to_string(bank.ID())); + Rank rank = DramExtension::getRank(trans); + ranksNumberOfPayloads[rank.ID()]--; + if (ranksNumberOfPayloads[rank.ID()] == 0) + { + refreshManagers[rank.ID()]->notifyIdle(); + powerDownManagers[rank.ID()]->triggerEntry(TriggerSource::Controller); } - else - SC_REPORT_FATAL(0, - "Controller Core PEQ in controller wrapper was triggered with unsupported phase"); } -} - -tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &fwDelay) -{ - sc_time notDelay = fwDelay; - - if (phase == BEGIN_REQ) - { - notDelay += Configuration::getInstance().memSpec->clk; - - // Bandwidth IDLE - if ((getTotalNumberOfPayloadsInSystem() == 0) && idleState) - endBandwidthIdleCollector(); - } - else if (phase == END_RESP) - { - // Bandwidth IDLE - // TODO: getTotalNumberOfPayloadsInSystem() == 1 && !idleState ?? - if (getTotalNumberOfPayloadsInSystem() == 1) - startBandwidthIdleCollector(); - } - - printDebugMessage("[fw] " + phaseNameToString(phase) + " notification in " + - notDelay.to_string()); - frontendPEQ.notify(payload, phase, notDelay); - return TLM_ACCEPTED; } -unsigned int Controller::transport_dbg(tlm::tlm_generic_payload &trans) +unsigned int Controller::transport_dbg(tlm_generic_payload &) { - return iSocket->transport_dbg(trans); + SC_REPORT_FATAL("Controller", "Debug Transport not supported"); + return 0; } -void Controller::frontendPEQCallback(tlm_generic_payload &payload, - const tlm_phase &phase) +void Controller::releasePayload() { - if (phase == BEGIN_REQ) - { - printDebugMessage(string("Payloads in system: ") + - to_string(getTotalNumberOfPayloadsInSystem())); - payload.acquire(); - payloadEntersSystem(payload); + uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToRelease); + PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system."); - if (getTotalNumberOfPayloadsInSystem() > - controllerCore->config.MaxNrOfTransactions) - { - printDebugMessage("##Backpressure: Max number of transactions in system reached"); - backpressure = &payload; - } - else - { - payload.set_response_status(tlm::TLM_OK_RESPONSE); - sendToFrontend(payload, END_REQ, SC_ZERO_TIME); + payloadToRelease->release(); + payloadToRelease = nullptr; + timeToRelease = sc_max_time(); + numberOfTransactionsServed++; - scheduler->storeRequest(&payload); - scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank()); - } - } - else if (phase == PendingRequest) - { - // Schedule a pending request. - scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank()); - } - else if (phase == END_RESP) - { - if (backpressure != NULL) - { - printDebugMessage("##Backpressure released"); - backpressure->set_response_status(tlm::TLM_OK_RESPONSE); - sendToFrontend(*backpressure, END_REQ, SC_ZERO_TIME); - - scheduler->storeRequest(backpressure); - scheduleNextFromScheduler(DramExtension::getExtension(backpressure).getBank()); - backpressure = NULL; - } - - payloadLeavesSystem(payload); - responseQueue.pop(); - payload.release(); - - if(!responseQueue.empty()) - sendToFrontend(*(responseQueue.front()), BEGIN_RESP, SC_ZERO_TIME); - } - else - { - SC_REPORT_FATAL(0, - "Front-end PEQ in controller wrapper was triggered with unknown phase"); - } + totalNumberOfPayloads--; + if (totalNumberOfPayloads == 0) + startBandwidthIdleCollector(); } -void Controller::payloadEntersSystem(tlm_generic_payload &payload) +void Controller::acquirePayload() { - Bank bank = DramExtension::getExtension(payload).getBank(); - numberOfPayloadsInSystem[bank]++; - printDebugMessage( - "Payload enters system on bank " + to_string(bank.ID()) + - ". Total number of payloads in Controller: " - + to_string(getTotalNumberOfPayloadsInSystem())); - // Set Start Time for Simulation - if (!startTimeSet) + uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToAcquire); + PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system."); + + Rank rank = DramExtension::getRank(payloadToAcquire); + + if (totalNumberOfPayloads == 0) + endBandwithIdleCollector(); + totalNumberOfPayloads++; + + if(ranksNumberOfPayloads[rank.ID()] == 0) { - printDebugMessage("Simulation Timer Start"); - startTime = sc_time_stamp() - Configuration::getInstance().memSpec->clk; - startTimeSet = true; + refreshManagers[rank.ID()]->notifyActive(); + powerDownManagers[rank.ID()]->triggerExit(TriggerSource::Controller); } + ranksNumberOfPayloads[rank.ID()]++; + + scheduler->storeRequest(payloadToAcquire); + payloadToAcquire->acquire(); + payloadToAcquire->set_response_status(TLM_OK_RESPONSE); + sendToFrontend(payloadToAcquire, END_REQ); + payloadToAcquire = nullptr; + timeToAcquire = sc_max_time(); } -void Controller::payloadLeavesSystem(tlm_generic_payload &payload) +void Controller::sendToFrontend(tlm_generic_payload *payload, tlm_phase phase) { - Bank bank = DramExtension::getExtension(payload).getBank(); - numberOfPayloadsInSystem[bank]--; - printDebugMessage( - "Payload left system on bank " + to_string(bank.ID()) + - ". Total number of payloads in Controller: " - + to_string(getTotalNumberOfPayloadsInSystem())); - controllerCore->powerDownManager->triggerSleep(bank, sc_time_stamp()); + sc_time delay = SC_ZERO_TIME; + tSocket->nb_transport_bw(*payload, phase, delay); } -unsigned int Controller::getTotalNumberOfPayloadsInSystem() +void Controller::sendToDram(Command command, tlm_generic_payload *payload) { - unsigned int sum = 0; - for (Bank bank : controllerCore->getBanks()) - sum += numberOfPayloadsInSystem[bank]; - return sum; -} + sc_time delay = SC_ZERO_TIME; + tlm_phase phase = phaseOfCommand[command]; -void Controller::scheduleNextFromScheduler(Bank bank) -{ - if (controllerCore->bankIsBusy(bank)) - return; - - // TODO: rescheduled always true? - bool rescheduled = true; - pair nextRequest = - scheduler->getNextRequest(bank); - if (nextRequest.second != NULL) - { - schedule(nextRequest.first, *nextRequest.second); - } - else - { - gp *pendingRequest = scheduler->getPendingRequest(bank); - // TODO: if path (pendingRequest != NULL) is only used by SMS scheduler - if (pendingRequest != NULL) - { - rescheduled = true; - frontendPEQ.notify(*(pendingRequest), PendingRequest, - Configuration::getInstance().memSpec->clk); - } - } - - // TODO: only used with FifoStrict scheduler - queue blocked; - while (!blockedRequests.empty()) - { - bank = blockedRequests.front(); - blockedRequests.pop(); - - pair nextRequest = - scheduler->getNextRequest(bank); - if (nextRequest.second != NULL) - { - schedule(nextRequest.first, *nextRequest.second); - } - else - { - gp *pendingRequest = scheduler->getPendingRequest(bank); - if (pendingRequest != NULL) - { - //Pending request - if (!rescheduled) - { - // TODO: never reached, rescheduled is always true - rescheduled = true; - frontendPEQ.notify(*(pendingRequest), PendingRequest, - Configuration::getInstance().memSpec->clk); - } - else - { - blocked.push(bank); - } - } - } - } - blockedRequests = blocked; -} - -void Controller::schedule(Command command, gp &payload) -{ - controllerCore->powerDownManager->wakeUp(DramExtension::getBank(payload), - sc_time_stamp()); - if (controllerCore->scheduleRequest(command, payload)) - { - printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString( - command) + "] (unblocked)"); - } -} - -void Controller::sendToFrontend(tlm_generic_payload &payload, - const tlm_phase &phase, const sc_time &delay) -{ - tlm_phase TPhase = phase; - sc_time TDelay = delay; - tSocket->nb_transport_bw(payload, TPhase, TDelay); -} - -tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &bwDelay) -{ - printDebugMessage("[bw] " + phaseNameToString(phase) + " notification in " + - bwDelay.to_string()); - dramPEQ.notify(payload, phase, bwDelay); - return TLM_ACCEPTED; -} - -void Controller::dramPEQCallback(tlm_generic_payload &payload, - const tlm_phase &phase) -{ - Bank bank = DramExtension::getExtension(payload).getBank(); - printDebugMessage("Received " + phaseNameToString(phase) + " on bank " + - to_string(bank.ID()) + " from DRAM"); - - if (phase == END_RD || phase == END_WR) - { - if(responseQueue.empty()) - sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME); - - responseQueue.push(&payload); - } - else if (phase == END_RDA || phase == END_WRA) - { - if(responseQueue.empty()) - sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME); - - responseQueue.push(&payload); - scheduleNextFromScheduler(bank); - } - else if (phase == END_REFA) - { - printDebugMessage("Finished auto refresh on all banks "); - - bool sleepy = true; - for (Bank bank : controllerCore->getBanks()) - { - if (numberOfPayloadsInSystem[bank] != 0) - { - sleepy = false; - scheduleNextFromScheduler(bank); - } - } - if (sleepy == true) - controllerCore->powerDownManager->sleep(0, sc_time_stamp()); - } - else if (phase == END_REFB) - { - printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID())); - - if (numberOfPayloadsInSystem[bank] == 0) - controllerCore->powerDownManager->sleep(bank, sc_time_stamp()); - else - scheduleNextFromScheduler(bank); - - scheduleNextFromScheduler(bank); - } - else if (containsPhase(phase, {END_PREB, END_PRE, END_ACTB, END_ACT})) - { - scheduleNextFromScheduler(bank); - } - else if (phase == END_PRE_ALL) - { - // No need to trigger anything for a END_PRE_ALL. It is followed by a AUTO_REFRESH anyway (in our current - // scheduler implementation) - } - else - { - string str = - string("DRAM PEQ in controller wrapper was triggered with unsupported phase ") - + phaseNameToString(phase); - SC_REPORT_FATAL(0, str.c_str()); - } -} - -void Controller::sendToDram(tlm_generic_payload &payload, - const tlm_phase &phase, const sc_time &delay) -{ - tlm_phase TPhase = phase; - sc_time TDelay = delay; - if (phase == BEGIN_WR || phase == BEGIN_RD || phase == BEGIN_WRA || phase == BEGIN_RDA) - numberOfTransactionsServed++; - iSocket->nb_transport_fw(payload, TPhase, TDelay); -} - -void Controller::printDebugMessage(string message) -{ - debugManager.printDebugMessage(name(), message); -} - -bool Controller::containsPhase(tlm_phase phase, std::vector phases) -{ - for (tlm_phase p : phases) { - if (p == phase) - return true; - } - return false; -} - -void Controller::end_of_simulation() -{ - terminateSimulation(); -} - -void Controller::terminateSimulation() -{ - if (Configuration::getInstance().BankwiseLogic) { - for (Bank bank : controllerCore->getBanks()) { - controllerCore->powerDownManager->wakeUp(bank, clkAlign(sc_time_stamp())); - } - } else { - controllerCore->powerDownManager->wakeUp(0, clkAlign(sc_time_stamp())); - } - - endTime = sc_time_stamp(); + iSocket->nb_transport_fw(*payload, phase, delay); } void Controller::startBandwidthIdleCollector() { - printDebugMessage("IDLE Start"); - idleStart = sc_time_stamp(); - endTime = sc_time_stamp(); - idleState = true; + if (!isIdle) + { + PRINTDEBUGMESSAGE(name(), "IDLE start"); + idleStart = sc_time_stamp(); + isIdle = true; + } } -void Controller::endBandwidthIdleCollector() +void Controller::endBandwithIdleCollector() { - printDebugMessage("IDLE End"); - idleTime += sc_time_stamp() - idleStart + - Configuration::getInstance().memSpec->clk; - idleState = false; -} - -sc_time Controller::getIdleTime() -{ - printDebugMessage("IDLE Time: " + idleTime.to_string()); - return idleTime; -} - -sc_time Controller::getEndTime() -{ - printDebugMessage("End Time: " + endTime.to_string()); - return endTime; -} - -sc_time Controller::getStartTime() -{ - printDebugMessage("Start Time: " + startTime.to_string()); - return startTime; + if (isIdle) + { + PRINTDEBUGMESSAGE(name(), "IDLE end"); + idleTime += sc_time_stamp() - idleStart; + isIdle = false; + } } diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index 282a9224..6200bb69 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,143 +29,79 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Eder F. Zulian + * Author: Lukas Steiner */ #ifndef CONTROLLER_H #define CONTROLLER_H -#include -#include +#include #include -#include - -#include -#include -#include +#include +#include +#include #include #include - +#include "GenericController.h" #include "../common/dramExtensions.h" +#include "BankMachine.h" +#include "cmdmux/CmdMuxIF.h" +#include "scheduler/SchedulerIF.h" #include "../common/DebugManager.h" -#include "../common/protocol.h" -#include "../common/TlmRecorder.h" -#include "../common/utils.h" -#include "core/configuration/Configuration.h" -#include "core/configuration/MemSpec.h" -#include "Command.h" -#include "core/ControllerCore.h" -#include "ControllerState.h" -#include "IController.h" -#include "core/powerdown/IPowerDownManager.h" -#include "core/scheduling/ScheduledCommand.h" -#include "core/timingCalculations.h" -#include "scheduler/Fifo.h" -#include "scheduler/Grp.h" -#include "scheduler/FifoStrict.h" -#include "scheduler/FrFcfs.h" -#include "scheduler/FrFcfsRp.h" -#include "scheduler/FrFcfsGrp.h" -#include "scheduler/SMS.h" -#include "scheduler/IScheduler.h" +#include "checker/CheckerIF.h" +#include "refresh/RefreshManagerIF.h" +#include "powerdown/PowerDownManagerIF.h" -using namespace std; using namespace tlm; -DECLARE_EXTENDED_PHASE(PendingRequest); +class BankMachine; +class SchedulerIF; +class PowerDownManagerStaggered; -class Controller : public sc_module, public IController +class Controller : public GenericController { public: Controller(sc_module_name); - + SC_HAS_PROCESS(Controller); virtual ~Controller(); - void terminateSimulation(); - - sc_time getIdleTime(); - sc_time getEndTime(); - sc_time getStartTime(); - - // ------- CONTROLLER CORE --------- - virtual void send(const ScheduledCommand &command, - tlm_generic_payload &payload) override; - virtual void send(Trigger trigger, sc_time time, - tlm_generic_payload &payload) override; - - tlm_utils::simple_target_socket tSocket; - tlm_utils::simple_initiator_socket iSocket; - - unsigned int getTotalNumberOfPayloadsInSystem(); - void scheduleNextFromScheduler(Bank bank) override; - - static unsigned int ControllerThreadId() - { - return controllerThreadId; - } - protected: - void buildScheduler(); - void payloadEntersSystem(tlm_generic_payload &payload); - void payloadLeavesSystem(tlm_generic_payload &payload); + virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &, tlm_phase &, sc_time &); + virtual tlm_sync_enum nb_transport_bw(tlm_generic_payload &, tlm_phase &, sc_time &); + virtual unsigned int transport_dbg(tlm_generic_payload &); - // --- FRONTEND ------ - virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &fwDelay); - virtual unsigned int transport_dbg(tlm::tlm_generic_payload &trans); - void frontendPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase); - virtual void sendToFrontend(tlm_generic_payload &payload, - const tlm_phase &phase, const sc_time &delay); + virtual void sendToFrontend(tlm_generic_payload *, tlm_phase); + virtual void sendToDram(Command, tlm_generic_payload *); - // --- DRAM ------ - virtual tlm_sync_enum nb_transport_bw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &bwDelay); - void dramPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase); - void sendToDram(tlm_generic_payload &payload, const tlm_phase &phase, - const sc_time &delay); +private: + unsigned totalNumberOfPayloads = 0; + std::vector ranksNumberOfPayloads; + tlm_generic_payload *payloadToAcquire = nullptr; + sc_time timeToAcquire = sc_max_time(); + tlm_generic_payload *payloadToRelease = nullptr; + sc_time timeToRelease = sc_max_time(); + std::queue> responseQueue; - // ------- CONTROLLER CORE --------- - virtual void schedule(Command command, gp &payload); - void controllerCorePEQCallback(tlm_generic_payload &payload, - const tlm_phase &phase); + std::vector bankMachines; + std::vector> bankMachinesOnRank; + CmdMuxIF *commandMux; + SchedulerIF *scheduler; + CheckerIF *checker; + std::vector refreshManagers; + std::vector powerDownManagers; - // Helpers TODO move them - void printDebugMessage(string message); - bool containsPhase(tlm_phase phase, std::vector phases); + void releasePayload(); + void acquirePayload(); - ControllerCore *controllerCore; - //Scheduler* scheduler; - IScheduler *scheduler; - std::map numberOfPayloadsInSystem; - std::vector refreshCollisionRequets; - tlm::tlm_generic_payload *backpressure = NULL; - std::queue responseQueue; + void controllerMethod(); + sc_event beginReqEvent, endRespEvent, controllerEvent; + sc_event_queue dataResponseEventQueue; - tlm_utils::peq_with_cb_and_phase frontendPEQ; - tlm_utils::peq_with_cb_and_phase dramPEQ; - tlm_utils::peq_with_cb_and_phase controllerCorePEQ; - - DebugManager &debugManager; - - // Bandwidth realted: + // Bandwidth related sc_time idleStart; - bool idleState = false; - sc_time idleTime; - sc_time endTime; - sc_time startTime; - bool startTimeSet = false; - unsigned long long int numberOfTransactionsServed = 0; + bool isIdle = false; void startBandwidthIdleCollector(); - void endBandwidthIdleCollector(); - - // SystemC related: - virtual void end_of_simulation() override; - - static const unsigned int controllerThreadId = INT_MAX; + void endBandwithIdleCollector(); }; #endif // CONTROLLER_H - diff --git a/DRAMSys/library/src/controller/ControllerRecordable.cpp b/DRAMSys/library/src/controller/ControllerRecordable.cpp new file mode 100644 index 00000000..aa2c7722 --- /dev/null +++ b/DRAMSys/library/src/controller/ControllerRecordable.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "ControllerRecordable.h" + +#include "../common/protocol.h" +#include "../configuration/Configuration.h" + +tlm_sync_enum ControllerRecordable::nb_transport_fw(tlm_generic_payload &trans, + tlm_phase &phase, sc_time &delay) +{ + recordPhase(trans, phase, delay); + return Controller::nb_transport_fw(trans, phase, delay); +} + +tlm_sync_enum ControllerRecordable::nb_transport_bw(tlm_generic_payload &trans, + tlm_phase &phase, sc_time &delay) +{ + recordPhase(trans, phase, delay); + return Controller::nb_transport_bw(trans, phase, delay); +} + +void ControllerRecordable::sendToFrontend(tlm_generic_payload *payload, tlm_phase phase) +{ + sc_time delay = SC_ZERO_TIME; + recordPhase(*payload, phase, delay); + tSocket->nb_transport_bw(*payload, phase, delay); +} + +void ControllerRecordable::sendToDram(Command command, tlm_generic_payload *payload) +{ + if (commandIsIn(command, {Command::RD, Command::RDA, Command::WR, Command::WRA})) + { + TimeInterval dataStrobe = Configuration::getInstance().memSpec->getIntervalOnDataStrobe(command); + tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, *payload); + } + Controller::sendToDram(command, payload); +} + +void ControllerRecordable::recordPhase(tlm_generic_payload &trans, tlm_phase phase, sc_time delay) +{ + sc_time recTime = delay + sc_time_stamp(); + + unsigned int thr __attribute__((unused)) = DramExtension::getExtension(trans).getThread().ID(); + unsigned int ch __attribute__((unused)) = DramExtension::getExtension(trans).getChannel().ID(); + unsigned int bg __attribute__((unused)) = DramExtension::getExtension(trans).getBankGroup().ID(); + unsigned int bank __attribute__((unused)) = DramExtension::getExtension(trans).getBank().ID(); + unsigned int row __attribute__((unused)) = DramExtension::getExtension(trans).getRow().ID(); + unsigned int col __attribute__((unused)) = DramExtension::getExtension(trans).getColumn().ID(); + uint64_t id __attribute__((unused)) = DramExtension::getExtension(trans).getPayloadID(); + + PRINTDEBUGMESSAGE(name(), "Recording " + phaseNameToString(phase) + " thread " + + to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string( + bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " + + to_string(col) + " id " + to_string(id) + " at " + recTime.to_string()); + + tlmRecorder->recordPhase(trans, phase, recTime); +} diff --git a/DRAMSys/library/src/controller/RowBufferStates.h b/DRAMSys/library/src/controller/ControllerRecordable.h similarity index 62% rename from DRAMSys/library/src/controller/RowBufferStates.h rename to DRAMSys/library/src/controller/ControllerRecordable.h index f2670dec..60a70edd 100644 --- a/DRAMSys/library/src/controller/RowBufferStates.h +++ b/DRAMSys/library/src/controller/ControllerRecordable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,36 +29,33 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Robert Gernhardt - * Matthias Jung + * Author: Lukas Steiner */ -#ifndef ROWBUFFERSTATES_H -#define ROWBUFFERSTATES_H +#ifndef CONTROLLERRECORDABLE_H +#define CONTROLLERRECORDABLE_H -#include -#include "../common/dramExtensions.h" +#include "Controller.h" +#include "../common/TlmRecorder.h" -class RowBufferState +class ControllerRecordable final : public Controller { public: - RowBufferState(std::string ownerName); - virtual ~RowBufferState(); - - bool rowBufferIsOpen(Bank bank) const; - bool allRowBuffersAreClosed() const; - Row getRowInRowBuffer(Bank bank) const; - - void openRowInRowBuffer(Bank bank, Row row); - void closeRowBuffer(Bank bank); - void closeAllRowBuffers(); + ControllerRecordable(sc_module_name name, TlmRecorder *tlmRecorder) : + Controller(name), tlmRecorder(tlmRecorder) {} private: - std::string ownerName; - std::map rowsInRowBuffers; - void printDebugMessage(std::string message); + tlm_sync_enum nb_transport_fw(tlm_generic_payload &trans, + tlm_phase &phase, sc_time &delay) override; + tlm_sync_enum nb_transport_bw(tlm_generic_payload &trans, + tlm_phase &phase, sc_time &delay) override; + + void sendToFrontend(tlm_generic_payload *, tlm_phase) override; + void sendToDram(Command, tlm_generic_payload *) override; + + void recordPhase(tlm_generic_payload &trans, tlm_phase phase, sc_time delay); + + TlmRecorder *tlmRecorder; }; -#endif // ROWBUFFERSTATES_H - +#endif // CONTROLLERRECORDABLE_H diff --git a/DRAMSys/library/src/controller/ControllerState.cpp b/DRAMSys/library/src/controller/ControllerState.cpp deleted file mode 100644 index c7318363..00000000 --- a/DRAMSys/library/src/controller/ControllerState.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Felipe S. Prado - */ - -#include "ControllerState.h" -#include -#include "core/timingCalculations.h" - -using namespace std; - -const ScheduledCommand ControllerState::getLastCommand(Command command, - Bank bank) //TODO const reference? and make const -{ - return lastScheduledByCommandAndBank[command][bank]; -} - -const ScheduledCommand ControllerState::getLastCommand(Command command) -{ - ScheduledCommand max; - - for (unsigned int i = 0; i < config->memSpec->NumberOfBanks; ++i) { - ScheduledCommand current = getLastCommand(command, Bank(i)); - if (current.getStart() > max.getStart()) - max = current; - } - - return max; -} - -const ScheduledCommand ControllerState::getLastScheduledCommand() -{ - ScheduledCommand lastCommand; - - for (Command cmd : getAllCommands()) { - for (Bank bank : Configuration::getInstance().memSpec->getBanks()) { - ScheduledCommand ¤t = lastScheduledByCommandAndBank[cmd][bank]; - if (current.getStart() > lastCommand.getStart()) - lastCommand = current; - } - } - - printDebugMessage("Last scheduled command was " + commandToString( - lastCommand.getCommand())); - - return lastCommand; -} - -const ScheduledCommand ControllerState::getLastScheduledCommand(Bank bank) -{ - ScheduledCommand lastCommand; - - for (Command cmd : getAllCommands()) { - ScheduledCommand ¤t = lastScheduledByCommandAndBank[cmd][bank]; - if (current.getStart() > lastCommand.getStart()) - lastCommand = current; - } - - printDebugMessage("Last scheduled command on bank " + to_string( - bank.ID()) + " was " + commandToString(lastCommand.getCommand())); - - return lastCommand; -} - -void ControllerState::change(const ScheduledCommand &scheduledCommand) -{ - bus.blockSlot(scheduledCommand.getStart()); - - printDebugMessage("Changing state on bank " + to_string( - scheduledCommand.getBank().ID()) + " command is " + commandToString( - scheduledCommand.getCommand())); - lastScheduledByCommandAndBank[scheduledCommand.getCommand()][scheduledCommand.getBank()] - = scheduledCommand; - - switch (scheduledCommand.getCommand()) { - case Command::Read: - lastDataStrobeCommands.emplace_back(scheduledCommand); - break; - case Command::ReadA: - rowBufferStates->closeRowBuffer(scheduledCommand.getBank()); - lastDataStrobeCommands.emplace_back(scheduledCommand); - break; - case Command::Write: - lastDataStrobeCommands.emplace_back(scheduledCommand); - break; - case Command::WriteA: - rowBufferStates->closeRowBuffer(scheduledCommand.getBank()); - lastDataStrobeCommands.emplace_back(scheduledCommand); - break; - case Command::AutoRefresh: - break; - case Command::ActB: - rowBufferStates->openRowInRowBuffer(scheduledCommand.getBank(), - scheduledCommand.getRow()); - lastActivatesB.emplace(scheduledCommand.getStart(), scheduledCommand); - break; - case Command::Activate: - rowBufferStates->openRowInRowBuffer(scheduledCommand.getBank(), - scheduledCommand.getRow()); - lastActivates.emplace(scheduledCommand.getStart(), scheduledCommand); - break; - case Command::PreB: - rowBufferStates->closeRowBuffer(scheduledCommand.getBank()); - break; - case Command::Precharge: - rowBufferStates->closeRowBuffer(scheduledCommand.getBank()); - break; - case Command::PrechargeAll: - rowBufferStates->closeAllRowBuffers(); - break; - case Command::SREF: - rowBufferStates->closeRowBuffer(scheduledCommand.getBank()); - break; - default: - break; - } -} - -void ControllerState::cleanUp(sc_time time) -{ - bus.cleanUpSlots(time); - vector tmp; - for (ScheduledCommand &command : lastDataStrobeCommands) { - if (command.getEnd() >= time - || getDistance(command.getEnd(), time) <= config->memSpec->tDataStrobeHistory()) - tmp.push_back(command); - } - lastDataStrobeCommands = tmp; - if (time >= config->memSpec->tActHistory()) - lastActivates.erase(lastActivates.begin(), - lastActivates.lower_bound(time - config->memSpec->tActHistory())); - - if (time >= config->memSpec->tActBHistory()) - lastActivatesB.erase(lastActivatesB.begin(), - lastActivatesB.lower_bound(time - config->memSpec->tActBHistory())); -} - -void ControllerState::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(ownerName, message); -} - diff --git a/DRAMSys/library/src/controller/ControllerState.h b/DRAMSys/library/src/controller/ControllerState.h deleted file mode 100644 index a5d9d609..00000000 --- a/DRAMSys/library/src/controller/ControllerState.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef CONTROLLERSTATE_H -#define CONTROLLERSTATE_H - -#include -#include "RowBufferStates.h" -#include "core/Slots.h" -#include "core/configuration/Configuration.h" -#include -#include -#include - -class ControllerState -{ -public: - ControllerState(std::string ownerName, - Configuration *config) : bus(config->memSpec->clk), ownerName(ownerName), - config(config) - { - rowBufferStates = new RowBufferState(ownerName); - } - virtual ~ControllerState() {} - - const ScheduledCommand getLastCommand(Command command, Bank bank); - const ScheduledCommand getLastCommand(Command command); - const ScheduledCommand getLastScheduledCommand(Bank bank); - const ScheduledCommand getLastScheduledCommand(); - - void change(const ScheduledCommand &scheduledCommand); - void cleanUp(sc_time time); - - RowBufferState *rowBufferStates; - - //used by the various checkers - std::map > - lastScheduledByCommandAndBank; - std::map lastScheduledByCommand; - std::map lastScheduledByBank; - ScheduledCommand lastScheduled; - - Slots bus; - std::vector lastDataStrobeCommands; - std::map lastActivates; - std::map lastActivatesB; - -private: - std::string ownerName; - Configuration *config; - void printDebugMessage(std::string message); -}; - -#endif // CONTROLLERSTATE_H - diff --git a/DRAMSys/library/src/controller/GenericController.h b/DRAMSys/library/src/controller/GenericController.h new file mode 100644 index 00000000..896d6fcd --- /dev/null +++ b/DRAMSys/library/src/controller/GenericController.h @@ -0,0 +1,83 @@ +#ifndef GENERICCONTROLLER_H +#define GENERICCONTROLLER_H + +#include +#include +#include +#include +#include "../configuration/Configuration.h" + +using namespace tlm; + +// Utiliy class to pass around the DRAMSys, without having to propagate the template defintions +// throughout all classes +class GenericController : public sc_module +{ +public: + // Already create and bind sockets to the virtual functions + tlm_utils::simple_target_socket tSocket; // Arbiter side + tlm_utils::simple_initiator_socket iSocket; // DRAM side + + // Destructor + virtual ~GenericController() + { + sc_time activeTime = numberOfTransactionsServed + * Configuration::getInstance().memSpec->BurstLength + / Configuration::getInstance().memSpec->DataRate + * Configuration::getInstance().memSpec->clk; + + double bandwidth = (activeTime / sc_time_stamp() * 100); + double bandwidth_IDLE = ((activeTime) / (sc_time_stamp() - idleTime) * 100); + + double maxBandwidth = ( + // clk in Mhz e.g. 800 [MHz]: + (1000000 / Configuration::getInstance().memSpec->clk.to_double()) + // DataRate e.g. 2 + * Configuration::getInstance().memSpec->DataRate + // BusWidth e.g. 8 or 64 + * Configuration::getInstance().memSpec->bitWidth + // Number of devices on a DIMM e.g. 8 + * Configuration::getInstance().NumberOfDevicesOnDIMM ) / ( 1024 ); + + std::cout << name() << std::string(" Total Time: ") + << sc_time_stamp().to_string() + << std::endl; + std::cout << name() << std::string(" AVG BW: ") + << std::fixed << std::setprecision(2) + << ((bandwidth / 100) * maxBandwidth) + << " Gibit/s (" << bandwidth << " %)" + << std::endl; + std::cout << name() << std::string(" AVG BW\\IDLE: ") + << std::fixed << std::setprecision(2) + << ((bandwidth_IDLE / 100) * maxBandwidth) + << " Gibit/s (" << bandwidth_IDLE << " %)" + << endl; + std::cout << name() << std::string(" MAX BW: ") + << std::fixed << std::setprecision(2) + << maxBandwidth << " Gibit/s" + << std::endl; + } + +protected: + // Bind sockets with virtual functions + GenericController(sc_module_name name) : + sc_module(name), tSocket("tSocket"), iSocket("iSocket") + { + tSocket.register_nb_transport_fw(this, &GenericController::nb_transport_fw); + tSocket.register_transport_dbg(this, &GenericController::transport_dbg); + iSocket.register_nb_transport_bw(this, &GenericController::nb_transport_bw); + } + SC_HAS_PROCESS(GenericController); + + // Virtual transport functions + virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &, tlm_phase &, sc_time &) = 0; + virtual unsigned int transport_dbg(tlm_generic_payload &) = 0; + virtual tlm_sync_enum nb_transport_bw(tlm_generic_payload &, tlm_phase &, sc_time &) = 0; + + // Bandwidth related + sc_time idleTime = SC_ZERO_TIME; + uint64_t numberOfTransactionsServed = 0; +}; + + +#endif // GENERICCONTROLLER_H diff --git a/DRAMSys/library/src/controller/IController.h b/DRAMSys/library/src/controller/IController.h deleted file mode 100644 index b61fc0d7..00000000 --- a/DRAMSys/library/src/controller/IController.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - */ - -#ifndef ICONTROLLER_H -#define ICONTROLLER_H - -#include -#include -#include "core/scheduling/ScheduledCommand.h" -#include "../common/dramExtensions.h" - -enum Trigger {REFTrigger, PDNTrigger}; - -// Utiliy class to pass around the Controller class to the controller Core and various schedulers, without having to propagate the template defintions -// throughout all classes -class IController -{ -public: - virtual ~IController() {} - virtual void send(const ScheduledCommand &command, - tlm::tlm_generic_payload &payload) = 0; - virtual void send(Trigger trigger, sc_time time, - tlm::tlm_generic_payload &payload) = 0; - virtual void scheduleNextFromScheduler(Bank bank) = 0; - - std::queue blockedRequests; -}; - - -#endif // ICONTROLLER_H diff --git a/DRAMSys/library/src/controller/RecordableController.cpp b/DRAMSys/library/src/controller/RecordableController.cpp deleted file mode 100644 index 51ff4f21..00000000 --- a/DRAMSys/library/src/controller/RecordableController.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2018, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Felipe S. Prado - * Matthias Jung - */ - -#include "RecordableController.h" - -tlm_sync_enum RecordableController::nb_transport_fw(tlm_generic_payload - &payload, tlm_phase &phase, sc_time &fwDelay) -{ - recordPhase(payload, phase, fwDelay); - - return Controller::nb_transport_fw(payload, phase, fwDelay); -} - -void RecordableController::sendToFrontend(tlm_generic_payload &payload, - const tlm_phase &phase, const sc_time &delay) -{ - recordPhase(payload, phase, delay); - - Controller::sendToFrontend(payload, phase, delay); -} - -tlm_sync_enum RecordableController::nb_transport_bw(tlm_generic_payload - &payload, tlm_phase &phase, sc_time &bwDelay) -{ - recordPhase(payload, phase, bwDelay); - - return Controller::nb_transport_bw(payload, phase, bwDelay); -} - -void RecordableController::recordPhase(tlm::tlm_generic_payload &trans, - tlm::tlm_phase phase, sc_time delay) -{ - sc_time recTime = delay + sc_time_stamp(); - - unsigned int thr = DramExtension::getExtension(trans).getThread().ID(); - unsigned int ch = DramExtension::getExtension(trans).getChannel().ID(); - unsigned int bg = DramExtension::getExtension(trans).getBankGroup().ID(); - unsigned int bank = DramExtension::getExtension(trans).getBank().ID(); - unsigned int row = DramExtension::getExtension(trans).getRow().ID(); - unsigned int col = DramExtension::getExtension(trans).getColumn().ID(); - - printDebugMessage("Recording " + phaseNameToString(phase) + " thread " + - to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string( - bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " + - to_string(col) + " at " + recTime.to_string()); - - tlmRecorder->recordPhase(trans, phase, recTime); -} - -void RecordableController::schedule(Command command, gp &payload) -{ - Controller::schedule(command, payload); - if (commandIsIn(command, {Command::Read, Command::ReadA, Command::Write, Command::WriteA})) { - ScheduledCommand scheduledCommand = controllerCore->state->getLastCommand( - command, DramExtension::getBank(payload)); - TimeInterval dataStrobe = scheduledCommand.getIntervalOnDataStrobe(); - tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload); - } -} diff --git a/DRAMSys/library/src/controller/RecordableController.h b/DRAMSys/library/src/controller/RecordableController.h deleted file mode 100644 index 3f37870c..00000000 --- a/DRAMSys/library/src/controller/RecordableController.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2018, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Felipe S. Prado - * Matthias Jung - */ - -#ifndef RECORDABLECONTROLLER_H -#define RECORDABLECONTROLLER_H - -#include "Controller.h" - -struct RecordableController: public Controller { -public: - RecordableController(sc_module_name name, TlmRecorder *rec) : - Controller(name), tlmRecorder(rec) - { - } - -protected: - TlmRecorder *tlmRecorder; - - virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &fwDelay) override; - virtual tlm_sync_enum nb_transport_bw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &bwDelay) override; - virtual void sendToFrontend(tlm_generic_payload &payload, - const tlm_phase &phase, const sc_time &delay) override; - virtual void schedule(Command command, tlm_generic_payload &payload) override; - - void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, - sc_time delay); -}; - -#endif // RECORDABLECONTROLLER_H diff --git a/DRAMSys/library/src/controller/RowBufferStates.cpp b/DRAMSys/library/src/controller/RowBufferStates.cpp deleted file mode 100644 index 4db36b8a..00000000 --- a/DRAMSys/library/src/controller/RowBufferStates.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - */ - -#include "RowBufferStates.h" -#include "core/ControllerCore.h" -#include "../common/DebugManager.h" -#include "../common/utils.h" - -using namespace std; - -RowBufferState::RowBufferState(std::string ownerName) : ownerName(ownerName) -{ - closeAllRowBuffers(); -} - -RowBufferState::~RowBufferState() -{ -} - -bool RowBufferState::rowBufferIsOpen(Bank bank) const -{ - return getElementFromMap(rowsInRowBuffers, bank) != Row::NO_ROW; -} - -Row RowBufferState::getRowInRowBuffer(Bank bank) const -{ - return getElementFromMap(rowsInRowBuffers, bank); -} - -void RowBufferState::openRowInRowBuffer(Bank bank, Row row) -{ - printDebugMessage("Row buffer for bank " + to_string(bank.ID()) + - " is now open"); - rowsInRowBuffers[bank] = row; -} - -void RowBufferState::closeRowBuffer(Bank bank) -{ - printDebugMessage("Row buffer for bank " + to_string(bank.ID()) + - " is now closed"); - rowsInRowBuffers[bank] = Row::NO_ROW; -} - -bool RowBufferState::allRowBuffersAreClosed() const -{ - for (unsigned int i = 0; i < Configuration::getInstance().memSpec->NumberOfBanks; - ++i) { - if (rowBufferIsOpen(Bank(i))) - return false; - } - return true; -} - -void RowBufferState::closeAllRowBuffers() -{ - for (unsigned int i = 0; i < Configuration::getInstance().memSpec->NumberOfBanks; - ++i) { - rowsInRowBuffers[Bank(i)] = Row::NO_ROW; - } -} - -void RowBufferState::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(ownerName, message); -} - diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp new file mode 100644 index 00000000..ad58c159 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerDDR3.h" + +CheckerDDR3::CheckerDDR3() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerDDR3", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + +// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + if (lastActivates[rank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTR); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + burstClocks + 2 * memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + burstClocks + 2 * memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::PDEA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + 4 * memSpec->clk + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + 5 * memSpec->clk + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + } + else if (command == Command::PDXA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::PDEA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + } + else if (command == Command::PDEP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + 5 * memSpec->clk + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::PDXP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::PDEP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + } + else if (command == Command::SREFEN) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + std::max(memSpec->tRL + 5 * memSpec->clk, memSpec->tAL + memSpec->tRTP + memSpec->tRP)); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + std::max(memSpec->tWL + 5 * memSpec->clk + memSpec->tWR, memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP)); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::SREFEX) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEN][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKESR); + } + else + reportFatal("CheckerDDR3", "Unknown command!"); + + // Check if command bus is free + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerDDR3::insert(Command command, Rank rank, BankGroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerDDR3", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT) + { + if (lastActivates[rank.ID()].size() == 4) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(sc_time_stamp()); + } +} diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.h b/DRAMSys/library/src/controller/checker/CheckerDDR3.h new file mode 100644 index 00000000..5ee8144b --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERDDR3_H +#define CHECKERDDR3_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecDDR3.h" +#include "../../configuration/Configuration.h" + +class CheckerDDR3 final : public CheckerIF +{ +public: + CheckerDDR3(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecDDR3 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // Four activate window + std::vector> lastActivates; + + sc_time burstClocks; +}; + +#endif // CHECKERDDR3_H diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp new file mode 100644 index 00000000..8576d1b6 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerDDR4.h" + +CheckerDDR4::CheckerDDR4() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerDDR4", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndBankGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBankGroups)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_S); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + if (lastActivates[rank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_L); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_L); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_S); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + + burstClocks + 2 * memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + + burstClocks + 2 * memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWR); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWR); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + } + else + reportFatal("CheckerDDR4", "Unknown command!"); + + // Check if command bus is free + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerDDR4::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerDDR4", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT) + { + if (lastActivates[rank.ID()].size() == 4) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(sc_time_stamp()); + } +} diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.h b/DRAMSys/library/src/controller/checker/CheckerDDR4.h new file mode 100644 index 00000000..2ff961a9 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERDDR4_H +#define CHECKERDDR4_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecDDR4.h" +#include "../../configuration/Configuration.h" + +class CheckerDDR4 final : public CheckerIF +{ +public: + CheckerDDR4(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecDDR4 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // Four activate window + std::vector> lastActivates; + + sc_time burstClocks; +}; + +#endif // CHECKERDDR4_H diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp new file mode 100644 index 00000000..f607942f --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerGDDR5.h" + +CheckerGDDR5::CheckerGDDR5() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerGDDR5", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndBankGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBankGroups)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + last4Activates = std::vector>(memSpec->NumberOfRanks); + last32Activates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerGDDR5::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + +// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + { + if (bankwiseRefreshCounter == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else + { + reportFatal("CheckerGDDR5", "Unknown command!"); + } + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerGDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerGDDR5", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (last4Activates[rank.ID()].size() == 4) + last4Activates[rank.ID()].pop(); + last4Activates[rank.ID()].push(lastCommandOnBus); + + if (last32Activates[rank.ID()].size() == 32) + last32Activates[rank.ID()].pop(); + last32Activates[rank.ID()].push(lastCommandOnBus); + } + + if (command == Command::REFB) + bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank; +} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/WriteChecker.h b/DRAMSys/library/src/controller/checker/CheckerGDDR5.h similarity index 61% rename from DRAMSys/library/src/controller/core/scheduling/checker/WriteChecker.h rename to DRAMSys/library/src/controller/checker/CheckerGDDR5.h index 4bddeb69..a17b7c28 100644 --- a/DRAMSys/library/src/controller/core/scheduling/checker/WriteChecker.h +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,38 +29,41 @@ * 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 + * Author: Lukas Steiner */ -#ifndef WRITECHECKER_H -#define WRITECHECKER_H +#ifndef CHECKERGDDR5_H +#define CHECKERGDDR5_H -#include "ICommandChecker.h" +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecGDDR5.h" #include "../../configuration/Configuration.h" -#include "../../../ControllerState.h" -class WriteChecker : public ICommandChecker +class CheckerGDDR5 final : public CheckerIF { public: - WriteChecker(const Configuration &config, - ControllerState &state) : config(config), state(state) {} - virtual ~WriteChecker() {} + CheckerGDDR5(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; - - static sc_time writeToWrite(ScheduledCommand &firstWrite, - ScheduledCommand &secondWrite); - static sc_time readToWrite(ScheduledCommand &read, ScheduledCommand &write); private: - bool collidesOnDataStrobe(ScheduledCommand &write) const; - bool collidesWithStrobeCommand(ScheduledCommand &write, - ScheduledCommand &strobeCommand) const; - const Configuration &config; - ControllerState &state; + const MemSpecGDDR5 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // 4 and 32 activate window + std::vector> last4Activates; + std::vector> last32Activates; + + sc_time burstClocks; + + unsigned bankwiseRefreshCounter = 0; }; - -#endif // WRITECHECKER_H +#endif // CHECKERGDDR5_H diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp new file mode 100644 index 00000000..1f1aee32 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerGDDR5X.h" + +CheckerGDDR5X::CheckerGDDR5X() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerGDDR5X", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndBankGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBankGroups)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + last4Activates = std::vector>(memSpec->NumberOfRanks); + last32Activates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerGDDR5X::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + +// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + { + if (bankwiseRefreshCounter == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else + { + reportFatal("CheckerGDDR5X", "Unknown command!"); + } + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerGDDR5X::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerGDDR5X", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (last4Activates[rank.ID()].size() == 4) + last4Activates[rank.ID()].pop(); + last4Activates[rank.ID()].push(lastCommandOnBus); + + if (last32Activates[rank.ID()].size() == 32) + last32Activates[rank.ID()].pop(); + last32Activates[rank.ID()].push(lastCommandOnBus); + } + + if (command == Command::REFB) + bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h new file mode 100644 index 00000000..355ca555 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERGDDR5X_H +#define CHECKERGDDR5X_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecGDDR5X.h" +#include "../../configuration/Configuration.h" + +class CheckerGDDR5X final : public CheckerIF +{ +public: + CheckerGDDR5X(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecGDDR5X *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // 4 and 32 activate window + std::vector> last4Activates; + std::vector> last32Activates; + + sc_time burstClocks; + + unsigned bankwiseRefreshCounter = 0; +}; + +#endif // CHECKERGDDR5X_H diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp new file mode 100644 index 00000000..1a1ae3ae --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerGDDR6.h" + +CheckerGDDR6::CheckerGDDR6() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerGDDR6", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndBankGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBankGroups)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerGDDR6::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + +// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + { + if (bankwiseRefreshCounter == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else + { + reportFatal("CheckerGDDR6", "Unknown command!"); + } + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerGDDR6::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerGDDR6", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (lastActivates[rank.ID()].size() == 4) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(lastCommandOnBus); + } + + if (command == Command::REFB) + bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR6.h b/DRAMSys/library/src/controller/checker/CheckerGDDR6.h new file mode 100644 index 00000000..f61007e6 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR6.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERGDDR6_H +#define CHECKERGDDR6_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecGDDR6.h" +#include "../../configuration/Configuration.h" + +class CheckerGDDR6 final : public CheckerIF +{ +public: + CheckerGDDR6(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecGDDR6 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // four activate window + std::vector> lastActivates; + + sc_time burstClocks; + + unsigned bankwiseRefreshCounter = 0; +}; + +#endif // CHECKERGDDR6_H diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM2.cpp b/DRAMSys/library/src/controller/checker/CheckerHBM2.cpp new file mode 100644 index 00000000..31d028e9 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerHBM2.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerHBM2.h" + +CheckerHBM2::CheckerHBM2() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerHBM2", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndBankGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBankGroups)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); + bankwiseRefreshCounter = std::vector(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / 2) * memSpec->clk; +} + +sc_time CheckerHBM2::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRTP + memSpec->tRP - memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP - memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC - memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB - memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD - memSpec->clk); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, + lastActivates[rank.ID()].front() + memSpec->tFAW - memSpec->clk); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRASBus + memSpec->clk); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCASBus + memSpec->clk); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR + memSpec->clk); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCASBus + memSpec->clk); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRASBus + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRASBus + memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRASBus + memSpec->clk); + } + else if (command == Command::REFB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + +// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + { + if (bankwiseRefreshCounter[rank.ID()] == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRASBus + memSpec->clk); + } + else + { + reportFatal("CheckerHBM2", "Unknown command!"); + } + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerHBM2::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerHBM2", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + + if (command == Command::RD || command == Command::RDA || command == Command::WR || command == Command::WRA) + lastCommandOnCASBus = sc_time_stamp(); + else if (command == Command::ACT) + lastCommandOnRASBus = sc_time_stamp() + memSpec->clk; + else + lastCommandOnRASBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (lastActivates[rank.ID()].size() == 4) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(lastCommandOnRASBus); + } + + if (command == Command::REFB) + bankwiseRefreshCounter[rank.ID()] = (bankwiseRefreshCounter[rank.ID()] + 1) % memSpec->BanksPerRank; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM2.h b/DRAMSys/library/src/controller/checker/CheckerHBM2.h new file mode 100644 index 00000000..06c688b2 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerHBM2.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERHBM2_H +#define CHECKERHBM2_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecHBM2.h" +#include "../../configuration/Configuration.h" + +class CheckerHBM2 final : public CheckerIF +{ +public: + CheckerHBM2(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecHBM2 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnRASBus; + sc_time lastCommandOnCASBus; + + // Four activate window + std::vector> lastActivates; + std::vector bankwiseRefreshCounter; + + sc_time burstClocks; +}; + +#endif // CHECKERHBM2_H diff --git a/DRAMSys/library/src/controller/checker/CheckerIF.h b/DRAMSys/library/src/controller/checker/CheckerIF.h new file mode 100644 index 00000000..64e43f5a --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerIF.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERIF_H +#define CHECKERIF_H + +#include +#include +#include "../Command.h" +#include "../../common/dramExtensions.h" +#include "../../common/DebugManager.h" + +class CheckerIF +{ +public: + virtual ~CheckerIF() {} + + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const = 0; + virtual void insert(Command, Rank, BankGroup, Bank) = 0; +}; + +#endif // CHECKERIF_H diff --git a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp new file mode 100644 index 00000000..ed7b9116 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerLPDDR4.h" + +CheckerLPDDR4::CheckerLPDDR4() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerLPDDR4", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); +} + +sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + + memSpec->tWR + memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb - 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab - 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab - 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb - 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD - 2 * memSpec->clk); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW - 3 * memSpec->clk); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->clk + memSpec->tCCD + memSpec->tWTR); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->clk + memSpec->tCCD + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->clk + memSpec->tCCD + memSpec->tWTR); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + memSpec->tDQSCK + memSpec->tCCD - memSpec->tWL + memSpec->tWPRE + memSpec->tRPST); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + memSpec->tDQSCK + memSpec->tCCD - memSpec->tWL + memSpec->tWPRE + memSpec->tRPST); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD + memSpec->tRTP - 6 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + 3 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD + memSpec->tRTP - 6 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD + memSpec->tRTP - 6 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + 3 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + 3 * memSpec->clk); + +// lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tRPpb + 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRPpb + 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + + memSpec->tWR + 3 * memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab); + +// lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); + } + else if (command == Command::REFB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tRPpb + 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD + 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRPpb + 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + + memSpec->tWR + 3 * memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb); + +// lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab); + +// lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW - memSpec->clk); + } + else + { + reportFatal("CheckerLPDDR4", "Unknown command!"); + } + // Check if command bus is free + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerLPDDR4::insert(Command command, Rank rank, BankGroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerLPDDR4", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp() + (memSpec->getCommandLength(command) - 1) * memSpec->clk; + + if (command == Command::ACT || command == Command::REFB) + { + if (lastActivates[rank.ID()].size() == 4) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(lastCommandOnBus); + } +} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PowerDownChecker.h b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h similarity index 66% rename from DRAMSys/library/src/controller/core/scheduling/checker/PowerDownChecker.h rename to DRAMSys/library/src/controller/checker/CheckerLPDDR4.h index a1b5f53d..fbadc16e 100644 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PowerDownChecker.h +++ b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,36 +29,35 @@ * 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 + * Author: Lukas Steiner */ -#ifndef POWERDOWNCHECKER_H -#define POWERDOWNCHECKER_H +#ifndef CHECKERLPDDR4_H +#define CHECKERLPDDR4_H -#include - -#include "../../../ControllerState.h" +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecLPDDR4.h" #include "../../configuration/Configuration.h" -#include "ICommandChecker.h" -class PowerDownChecker : public ICommandChecker +class CheckerLPDDR4 final : public CheckerIF { public: - PowerDownChecker(const Configuration &config, - ControllerState &state) : config(config), state(state) {} - virtual ~PowerDownChecker() {} - - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; + CheckerLPDDR4(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; private: - const Configuration &config; - ControllerState &state; - sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, - Command pdnCmd) const; + const MemSpecLPDDR4 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // Four activate window + std::vector> lastActivates; }; -#endif // POWERDOWNCHECKER_H - +#endif // CHECKERLPDDR4_H diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp new file mode 100644 index 00000000..118abc31 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerWideIO.h" + +CheckerWideIO::CheckerWideIO() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerWideIO", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = memSpec->BurstLength * memSpec->clk; +} + +sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks - memSpec->clk + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + if (lastActivates[rank.ID()].size() >= 2) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tTAW); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWTR); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->clk + memSpec->tWR); + } + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWTR); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + burstClocks + memSpec->clk); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + burstClocks + memSpec->clk); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWR); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWR); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + } + else + { + reportFatal("CheckerWideIO", "Unknown command!"); + } + // Check if command bus is free + earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk); + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerWideIO::insert(Command command, Rank rank, BankGroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerWideIO", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastScheduled = sc_time_stamp(); + + if (command == Command::ACT) + { + if (lastActivates[rank.ID()].size() == 2) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(sc_time_stamp()); + } +} diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.h b/DRAMSys/library/src/controller/checker/CheckerWideIO.h new file mode 100644 index 00000000..6bcc0796 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERWIDEIO_H +#define CHECKERWIDEIO_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecWideIO.h" +#include "../../configuration/Configuration.h" + +class CheckerWideIO final : public CheckerIF +{ +public: + CheckerWideIO(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecWideIO *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastScheduled; + + // Four activate window + std::vector> lastActivates; + + sc_time burstClocks; +}; + +#endif // CHECKERWIDEIO_H diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO2.cpp b/DRAMSys/library/src/controller/checker/CheckerWideIO2.cpp new file mode 100644 index 00000000..463e3eb8 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO2.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "CheckerWideIO2.h" + +CheckerWideIO2::CheckerWideIO2() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerWideIO2", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); +} + +sc_time CheckerWideIO2::delayToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tCCD + memSpec->tRTP - 2 * memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + } + else if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->clk + memSpec->tCCD + memSpec->tWTR); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->clk + memSpec->tCCD + memSpec->tWR - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->clk + memSpec->tCCD + memSpec->tWTR); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + memSpec->tDQSCK + memSpec->tCCD + memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + memSpec->tDQSCK + memSpec->tCCD + memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tCCD + memSpec->tRTP - 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tCCD + memSpec->tRTP - 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tCCD + memSpec->tRTP - 2 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + 2 * memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tCCD + memSpec->tRTP - 2 * memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab); + } + else if (command == Command::REFB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tCCD + memSpec->tRTP - 2 * memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->clk + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + } + else + { + reportFatal("CheckerWideIO2", "Unknown command!"); + } + // Check if command bus is free + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerWideIO2::insert(Command command, Rank rank, BankGroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerWideIO2", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (lastActivates[rank.ID()].size() == 4) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(sc_time_stamp()); + } +} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeChecker.h b/DRAMSys/library/src/controller/checker/CheckerWideIO2.h similarity index 66% rename from DRAMSys/library/src/controller/core/scheduling/checker/PrechargeChecker.h rename to DRAMSys/library/src/controller/checker/CheckerWideIO2.h index 05b94dc1..7c27933d 100644 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeChecker.h +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,31 +29,35 @@ * 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 + * Author: Lukas Steiner */ -#ifndef PRECHARGECHECKER_H -#define PRECHARGECHECKER_H +#ifndef CHECKERWIDEIO2_H +#define CHECKERWIDEIO2_H -#include "ICommandChecker.h" +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecWideIO2.h" #include "../../configuration/Configuration.h" -#include "../../../ControllerState.h" -class PrechargeChecker: public ICommandChecker +class CheckerWideIO2 final : public CheckerIF { public: - PrechargeChecker(const Configuration &config, - ControllerState &state) : config(config), state(state) {} - virtual ~PrechargeChecker() {} - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; + CheckerWideIO2(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; private: - const Configuration &config; - ControllerState &state; + const MemSpecWideIO2 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // Four activate window + std::vector> lastActivates; }; - -#endif // PRECHARGECHECKER_ +#endif // CHECKERWIDEIO2_H diff --git a/DRAMSys/library/src/controller/cmdmux/CmdMuxIF.h b/DRAMSys/library/src/controller/cmdmux/CmdMuxIF.h new file mode 100644 index 00000000..2e599656 --- /dev/null +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxIF.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CMDMUXIF_H +#define CMDMUXIF_H + +#include +#include +#include +#include "../Command.h" + +using namespace tlm; + +class CmdMuxIF +{ +public: + virtual ~CmdMuxIF() {} + virtual std::pair + selectCommand(std::vector> &) = 0; +}; + +#endif // CMDMUXIF_H diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeAllChecker.h b/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.cpp similarity index 69% rename from DRAMSys/library/src/controller/core/scheduling/checker/PrechargeAllChecker.h rename to DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.cpp index 41133b4b..6414c3ce 100644 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeAllChecker.h +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,36 +29,30 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Robert Gernhardt - * Matthias Jung + * Author: Lukas Steiner */ -#ifndef PRECHARGEALLCHECKER_H -#define PRECHARGEALLCHECKER_H +#include "CmdMuxOldest.h" -#include "ICommandChecker.h" -#include "../../configuration/Configuration.h" -#include "../../../ControllerState.h" +#include "../../common/dramExtensions.h" -class PrechargeAllChecker: public ICommandChecker +std::pair +CmdMuxOldest::selectCommand(std::vector> &readyCommands) { -public: - PrechargeAllChecker(const Configuration &config, ControllerState &state) : - config(config), state(state) + auto it = readyCommands.begin(); + auto result = it; + unsigned lastPayloadID = DramExtension::getPayloadID(it->second); + it++; + + while (it != readyCommands.end()) { + unsigned newPayloadID = DramExtension::getPayloadID(it->second); + if (newPayloadID < lastPayloadID) + { + lastPayloadID = newPayloadID; + result = it; + } + it++; } - virtual ~PrechargeAllChecker() - { - } - - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; - -private: - const Configuration &config; - ControllerState &state; -}; - - -#endif // PRECHARGEALLCHECKER_H + return *result; +} diff --git a/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.h b/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.h new file mode 100644 index 00000000..124d056c --- /dev/null +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CMDMUXOLDEST_H +#define CMDMUXOLDEST_H + +#include "CmdMuxIF.h" + +class CmdMuxOldest : public CmdMuxIF +{ +public: + std::pair + selectCommand(std::vector> &); +}; + +#endif // CMDMUXOLDEST_H diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/RefreshChecker.h b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp similarity index 69% rename from DRAMSys/library/src/controller/core/scheduling/checker/RefreshChecker.h rename to DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp index ae7a4c9e..6e2d623e 100644 --- a/DRAMSys/library/src/controller/core/scheduling/checker/RefreshChecker.h +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,38 +29,31 @@ * 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 + * Author: Lukas Steiner */ -#ifndef REFRESHCHECKER_H -#define REFRESHCHECKER_H +#include "CmdMuxStrict.h" -#include "ICommandChecker.h" -#include "../../../ControllerState.h" -#include "../../configuration/Configuration.h" -#include +#include "../../common/dramExtensions.h" -class RefreshChecker : public ICommandChecker +std::pair +CmdMuxStrict::selectCommand(std::vector> &readyCommands) { -public: - RefreshChecker(const Configuration &config, ControllerState &state) : - config(config), state(state) + for (auto it : readyCommands) { + if (isCasCommand(it.first)) + { + if (DramExtension::getPayloadID(it.second) == nextPayloadID) + { + nextPayloadID++; + return it; + } + } } - virtual ~RefreshChecker() + for (auto it : readyCommands) { + if (isRasCommand(it.first)) + return it; } - - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; - -private: - const Configuration &config; - ControllerState &state; - -}; - - -#endif // REFRESHCHECKER_H + return std::pair(Command::NOP, nullptr); +} diff --git a/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.h b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.h new file mode 100644 index 00000000..8c98b8c6 --- /dev/null +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CMDMUXSTRICT_H +#define CMDMUXSTRICT_H + +#include "CmdMuxIF.h" + +class CmdMuxStrict : public CmdMuxIF +{ +public: + std::pair + selectCommand(std::vector> &); + +private: + uint64_t nextPayloadID = 0; +}; + +#endif // CMDMUXSTRICT_H diff --git a/DRAMSys/library/src/controller/core/ControllerCore.cpp b/DRAMSys/library/src/controller/core/ControllerCore.cpp deleted file mode 100644 index 5c43afcc..00000000 --- a/DRAMSys/library/src/controller/core/ControllerCore.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Felipe S. Prado - */ - -#include -#include "ControllerCore.h" -#include "scheduling/checker/ActBChecker.h" -#include "scheduling/checker/ActivateChecker.h" -#include "scheduling/checker/PreBChecker.h" -#include "scheduling/checker/PrechargeChecker.h" -#include "scheduling/checker/PrechargeAllChecker.h" -#include "scheduling/checker/ReadChecker.h" -#include "scheduling/checker/WriteChecker.h" -#include "scheduling/checker/RefreshChecker.h" -#include "scheduling/checker/PowerDownChecker.h" -#include "refresh/RefreshManagerBankwise.h" -#include "refresh/RefreshManager.h" -#include "refresh/RGR.h" -#include "../../common/dramExtensions.h" -#include "../../common/utils.h" -#include "timingCalculations.h" - -#include "powerdown/PowerDownManager.h" -#include "powerdown/PowerDownManagerTimeout.h" -#include "powerdown/PowerDownManagerBankwise.h" -#include "powerdown/PowerDownManagerTimeoutBankwise.h" -#include "powerdown/NoPowerDown.h" -#include "../../common/DebugManager.h" - -ControllerCore::ControllerCore(sc_module_name /*name*/, - IController &wrapperConnector, std::map &numberOfPayloads) : - config(Configuration::getInstance()), controller(wrapperConnector), - numberOfPayloads(numberOfPayloads), commandChecker() -{ - state = new ControllerState(name(), &config); - - commandChecker[Command::ActB] = new ActBChecker(config, *state); - commandChecker[Command::Activate] = new ActivateChecker(config, *state); - commandChecker[Command::PreB] = new PreBChecker(config, *state); - commandChecker[Command::Precharge] = new PrechargeChecker(config, *state); - commandChecker[Command::PrechargeAll] = new PrechargeAllChecker(config, *state); - commandChecker[Command::Read] = new ReadChecker(config, *state); - commandChecker[Command::ReadA] = commandChecker[Command::Read]; - commandChecker[Command::Write] = new WriteChecker(config, *state); - commandChecker[Command::WriteA] = commandChecker[Command::Write]; - - commandChecker[Command::AutoRefresh] = new RefreshChecker(config, *state); - commandChecker[Command::PDNA] = new PowerDownChecker(config, *state); - commandChecker[Command::PDNP] = commandChecker[Command::PDNA]; - commandChecker[Command::SREF] = commandChecker[Command::PDNA]; - commandChecker[Command::PDNAX] = commandChecker[Command::PDNA]; - commandChecker[Command::PDNPX] = commandChecker[Command::PDNA]; - commandChecker[Command::SREFX] = commandChecker[Command::PDNA]; - - if (config.RowGranularRef) { - refreshManager = new RGR("RGR", *this); - // TODO: How to use asserts with new memspec? - /* - assert(config.getTrasb() <= config.memSpec->tRAS); - assert(config.getTrasb() >= config.memSpec->tRCD); - assert(config.getTrrdb_L() <= config.memSpec->tRRD_L); - assert(config.getTrrdb_S() <= config.memSpec->tRRD_S); - assert(config.getTrpb() <= config.memSpec->tRP); - assert(config.getTrcb() <= config.memSpec->tRC); - assert(config.getTfawb() <= config.memSpec->tNAW); - */ - } else { - if (config.BankwiseLogic) { - refreshManager = new RefreshManagerBankwise("refManagerBw", *this); - } else { - refreshManager = new RefreshManager("refManager", *this); - } - } - - if (config.PowerDownMode == EPowerDownMode::Staggered) { - if (config.BankwiseLogic) - powerDownManager = new PowerDownManagerBankwise("pdnManagerBw", *this); - else - powerDownManager = new PowerDownManager("pdnManager", *this); - } else if (config.PowerDownMode == EPowerDownMode::TimeoutPDN - || config.PowerDownMode == EPowerDownMode::TimeoutSREF) { - if (config.BankwiseLogic) - powerDownManager = new PowerDownManagerTimeoutBankwise("pdnManagerBw", *this); - else - powerDownManager = new PowerDownManagerTimeout("pdnManager", *this); - } else if (config.PowerDownMode == EPowerDownMode::NoPowerDown) { - powerDownManager = new NoPowerDown(); - } else { - SC_REPORT_FATAL(0, - "Unsupported powerdown mode in constructor of controller core"); - } -} - -ControllerCore::~ControllerCore() -{ - delete commandChecker[Command::Activate]; - delete commandChecker[Command::Precharge]; - delete commandChecker[Command::PrechargeAll]; - delete commandChecker[Command::Read]; - delete commandChecker[Command::Write]; - delete commandChecker[Command::AutoRefresh]; - delete commandChecker[Command::PDNA]; - delete refreshManager; - delete powerDownManager; - delete state; -} - -void ControllerCore::triggerRefresh(tlm::tlm_generic_payload &payload) -{ - /* Refresh can be disabled for tests purpose */ - if (config.ControllerCoreRefDisable == false) - { - sc_time time = sc_time_stamp(); - Bank bank = DramExtension::getExtension(payload).getBank(); - - state->cleanUp(time); - - if (!refreshManager->isInvalidated(payload, time) - && !powerDownManager->isInSelfRefresh(bank)) - { - printDebugMessage("Triggering refresh on bank " + to_string(bank.ID())); - powerDownManager->wakeUpForRefresh(bank, - time); //expects PDNA and PDNP to exit without delay - bool pdnpToSrefTransition = false; - if (config.PowerDownMode == EPowerDownMode::Staggered) - pdnpToSrefTransition = (state->getLastCommand(Command::PDNPX, - bank).getStart() >= time); - if (pdnpToSrefTransition) - powerDownManager->sleep(bank, time); - else - refreshManager->scheduleRefresh(payload, time); - } - } -} - -bool ControllerCore::scheduleRequest(Command command, - tlm::tlm_generic_payload &payload) -{ - sc_time start = clkAlign(sc_time_stamp()); - state->cleanUp(start); - ScheduledCommand scheduledCommand = schedule(command, start, payload); - if (config.ControllerCoreRefDisable) - { - state->change(scheduledCommand); - controller.send(scheduledCommand, payload); - return true; - } - else - { - if (!((command == Command::Precharge || command == Command::Activate) - && refreshManager->hasCollision(scheduledCommand))) - { - state->change(scheduledCommand); - controller.send(scheduledCommand, payload); - return true; - } - } - return false; -} - -ScheduledCommand ControllerCore::schedule(Command command, sc_time start, - tlm::tlm_generic_payload &payload) -{ - ControllerCore::printDebugMessage("Scheduling command " + commandToString( - command) + " on " + DramExtension::getBank(payload).toString()); - sc_time executionTime = getExecutionTime(command, payload); - ScheduledCommand scheduledCommand(command, start, executionTime, - DramExtension::getExtension(payload)); - getCommandChecker(command).delayToSatisfyConstraints(scheduledCommand); - return scheduledCommand; -} - -bool ControllerCore::hasPendingRequests() -{ - for (Bank bank : getBanks()) - { - if (numberOfPayloads[bank] != 0) - return true; - } - return false; -} - -bool ControllerCore::hasPendingRequests(Bank bank) -{ - return (numberOfPayloads[bank] != 0) ? true : false; -} - -bool ControllerCore::bankIsBusy(Bank bank) -{ - sc_time time = sc_time_stamp(); - ScheduledCommand lastScheduledCommand = state->getLastScheduledCommand(bank); - - if (lastScheduledCommand.isNoCommand()) - { - return false; - } - else if (lastScheduledCommand.commandIsIn({Command::Write, Command::Read})) - { - // Read and writes can overlap, so the bank should not be busy during a rd/wr - return (time < lastScheduledCommand.getStart()); - } - else if (lastScheduledCommand.commandIsIn({Command::WriteA, Command::ReadA, Command::PreB, - Command::Precharge, Command::PrechargeAll, - Command::ActB, Command::Activate})) - { - return (time < lastScheduledCommand.getEnd()); - } - else if (lastScheduledCommand.getCommand() == Command::AutoRefresh) - { - return (time < lastScheduledCommand.getEnd()); - } - else if (lastScheduledCommand.commandIsIn({Command::SREFX, Command::PDNPX, Command::PDNAX, - Command::SREF, Command::PDNP, Command::PDNA})) - { - return false; - } - else - { - SC_REPORT_FATAL("Core", "Last command unkown"); - return false; - } -} - -const std::vector &ControllerCore::getBanks() -{ - static std::vector banks; - - if (banks.size() == 0) { - for (unsigned int i = 0; i < config.memSpec->NumberOfBanks; i++) { - banks.push_back(Bank(i)); - } - } - - return banks; -} - -std::vector ControllerCore::getFreeBanks() -{ - std::vector freeBanks; - for (Bank bank : getBanks()) { - if (!bankIsBusy(bank)) - freeBanks.push_back(bank); - } - return freeBanks; -} - -ICommandChecker &ControllerCore::getCommandChecker(Command command) -{ - return *getElementFromMap(commandChecker, command); -} - -void ControllerCore::printDebugMessage(string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); -} - diff --git a/DRAMSys/library/src/controller/core/ControllerCore.h b/DRAMSys/library/src/controller/core/ControllerCore.h deleted file mode 100644 index f0b7dc99..00000000 --- a/DRAMSys/library/src/controller/core/ControllerCore.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef CONTROLLERCORE_H -#define CONTROLLERCORE_H - -#include -#include -#include -#include -#include "../IController.h" -#include "configuration/Configuration.h" -#include "powerdown/PowerDownManager.h" -#include "refresh/IRefreshManager.h" -#include "scheduling/checker/ICommandChecker.h" -#include "../RowBufferStates.h" -#include "../ControllerState.h" - -using namespace std; - -class ControllerCore : public sc_module -{ -public: - ControllerCore(sc_module_name /*name*/, IController &controller, - std::map &numberOfPayloads); - virtual ~ControllerCore(); - - bool scheduleRequest(Command command, tlm::tlm_generic_payload &payload); - void triggerRefresh(tlm::tlm_generic_payload &payload); - - const std::vector &getBanks(); - std::vector getFreeBanks(); - const RowBufferState &getRowBufferStates() - { - return *(state->rowBufferStates); - } - bool hasPendingRequests(); - bool hasPendingRequests(Bank bank); - bool bankIsBusy(Bank bank); - - ICommandChecker &getCommandChecker(Command command); - - Configuration config; - ControllerState *state; - IController &controller; - IPowerDownManager *powerDownManager; - IRefreshManager *refreshManager; - std::map &numberOfPayloads; - -private: - - ScheduledCommand schedule(Command command, sc_time start, - tlm::tlm_generic_payload &payload); - std::map commandChecker; - void printDebugMessage(string message); -}; - -#endif // CONTROLLERCORE_H - diff --git a/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.cpp b/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.cpp deleted file mode 100644 index a4d3f94f..00000000 --- a/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Lukas Steiner - */ - -#include "ConfigurationLoader.h" -#include "MemSpec.h" -#include "../timingCalculations.h" - -using namespace tinyxml2; -using namespace std; - -void ConfigurationLoader::loadSimConfig(Configuration &config, - string simconfigUri) -{ - tinyxml2::XMLDocument doc; - - loadXML(simconfigUri, doc); - XMLElement *simconfig = doc.FirstChildElement("simconfig"); - loadConfig(config, simconfig); -} - -void ConfigurationLoader::loadSimConfig(Configuration &config, - XMLElement *simconfig) -{ - if (simconfig->Attribute("src")) { - XMLDocument doc; - string src(simconfig->Attribute("src")); - loadXML(src, doc); - loadSimConfig(config, doc.FirstChildElement("simconfig")); - } - loadConfig(config, simconfig); -} - -void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config, - std::string thermalsimconfigUri) -{ - loadConfigFromUri(config, thermalsimconfigUri, "thermalsimconfig"); -} - -void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config, - XMLElement *thermalsimconfig) -{ - if (thermalsimconfig->Attribute("src")) { - // Configuration is inside another a file - std::string uri(thermalsimconfig->Attribute("src")); - loadConfigFromUri(config, uri, "thermalsimconfig"); - } else { - loadConfig(config, thermalsimconfig); - } -} - -void ConfigurationLoader::loadConfig(Configuration &config, - XMLElement *configNode) -{ - XMLElement *element; - for (element = configNode->FirstChildElement(); element != NULL; - element = element->NextSiblingElement()) { - config.setParameter(element->Name(), element->Attribute("value")); - - } -} - -void ConfigurationLoader::loadConfigFromUri(Configuration &config, - std::string uri, std::string first_element) -{ - tinyxml2::XMLDocument doc; - loadXML(uri, doc); - XMLElement *e = doc.FirstChildElement(first_element.c_str()); - loadConfig(config, e); -} - -void ConfigurationLoader::loadMCConfig(Configuration &config, - string mcconfigUri) -{ - tinyxml2::XMLDocument doc; - config.mcconfigUri = mcconfigUri; - loadXML(mcconfigUri, doc); - XMLElement *mcconfig = doc.FirstChildElement("mcconfig"); - loadConfig(config, mcconfig); -} - -void ConfigurationLoader::loadMCConfig(Configuration &config, - XMLElement *mcconfig) -{ - if (mcconfig->Attribute("src")) { - XMLDocument doc; - string src(mcconfig->Attribute("src")); - config.mcconfigUri = src; - loadXML(src, doc); - loadMCConfig(config, doc.FirstChildElement("mcconfig")); - } else { - loadConfig(config, mcconfig); - } - - -} - -void ConfigurationLoader::loadMemSpec(Configuration &config, string memspecUri) -{ - tinyxml2::XMLDocument doc; - config.memspecUri = memspecUri; - loadXML(memspecUri, doc); - XMLElement *memspec = doc.FirstChildElement("memspec"); - loadMemSpec(config, memspec); -} - -void ConfigurationLoader::loadMemSpec(Configuration &config, - XMLElement *memspec) -{ - string memoryType = queryStringParameter(memspec, "memoryType"); - - if (memoryType == "DDR4") { - Configuration::getInstance().memSpec = - new MemSpecDDR4; - loadDDR4(config, memspec); - } else if (memoryType == "DDR3") { - Configuration::getInstance().memSpec = - new MemSpecDDR3; - loadDDR3(config, memspec); - } else if (memoryType == "LPDDR4") { - Configuration::getInstance().memSpec = - new MemSpecLPDDR4; - loadLPDDR4(config, memspec); - } else if (memoryType == "WIDEIO_SDR") { - Configuration::getInstance().memSpec = - new MemSpecWideIO; - loadWideIO(config, memspec); - } else { - reportFatal("ConfigurationLoader", "Unsupported DRAM type"); - } - - loadCommons(config, memspec); -} - -void ConfigurationLoader::loadCommons(Configuration &config, XMLElement *memspec) -{ - config.memSpec->MemoryId = queryStringParameter(memspec, "memoryId"); - config.memSpec->MemoryType = queryStringParameter(memspec, "memoryType"); -} - -void ConfigurationLoader::loadDDR3(Configuration &config, XMLElement *memspec) -{ - //MemArchitecture - XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec"); - - config.memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks"); - config.memSpec->NumberOfBankGroups = 1; - config.memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); - config.memSpec->BurstLength = queryUIntParameter(architecture, "burstLength"); - config.memSpec->nActivate = 4; - config.memSpec->DataRate = queryUIntParameter(architecture, "dataRate"); - config.memSpec->NumberOfRows = queryUIntParameter(architecture, "nbrOfRows"); - config.memSpec->NumberOfColumns = queryUIntParameter(architecture, - "nbrOfColumns"); - config.memSpec->bitWidth = queryUIntParameter(architecture, "width"); - config.memSpec->DLL = true; - config.memSpec->termination = true; - - //MemTimings - XMLElement *timings = memspec->FirstChildElement("memtimingspec"); - config.memSpec->clkMHz = queryDoubleParameter(timings, "clkMhz"); - config.memSpec->clk = FrequencyToClk(config.memSpec->clkMHz); - sc_time clk = config.memSpec->clk; - config.memSpec->tRP = clk * queryUIntParameter(timings, "RP"); - config.memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); - config.memSpec->tRC = clk * queryUIntParameter(timings, "RC"); - config.memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); - config.memSpec->tRRD_S = clk * queryUIntParameter(timings, "RRD"); - config.memSpec->tRRD_L = clk * queryUIntParameter(timings, "RRD"); - config.memSpec->tCCD_S = clk * queryUIntParameter(timings, "CCD"); - config.memSpec->tCCD_L = clk * queryUIntParameter(timings, "CCD"); - config.memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); - config.memSpec->tNAW = clk * queryUIntParameter(timings, "FAW"); - config.memSpec->tRL = clk * queryUIntParameter(timings, "RL"); - config.memSpec->tWL = clk * queryUIntParameter(timings, "WL"); - config.memSpec->tWR = clk * queryUIntParameter(timings, "WR"); - config.memSpec->tWTR_S = clk * queryUIntParameter(timings, "WTR"); - config.memSpec->tWTR_L = clk * queryUIntParameter(timings, "WTR"); - config.memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); - config.memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); - config.memSpec->tXP = clk * queryUIntParameter(timings, "XP"); - config.memSpec->tXPDLL = clk * queryUIntParameter(timings, "XPDLL"); - config.memSpec->tXSR = clk * queryUIntParameter(timings, "XS"); - config.memSpec->tXSRDLL = clk * queryUIntParameter(timings, "XSDLL"); - config.memSpec->tAL = clk * queryUIntParameter(timings, "AL"); - config.memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); - config.memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); - config.memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); - - config.memSpec->refreshTimings.clear(); - for (unsigned int i = 0; i < config.memSpec->NumberOfBanks; ++i) { - config.memSpec->refreshTimings[Bank(i)] = RefreshTiming(config.memSpec->tRFC, - config.memSpec->tREFI); - } - - // Currents and Volatages: TODO Check if this is correct. - XMLElement *powers = memspec->FirstChildElement("mempowerspec"); - config.memSpec->iDD0 = queryDoubleParameter(powers, "idd0"); - config.memSpec->iDD02 = 0; - config.memSpec->iDD2P0 = queryDoubleParameter(powers, "idd2p0"); - config.memSpec->iDD2P1 = queryDoubleParameter(powers, "idd2p1"); - config.memSpec->iDD2N = queryDoubleParameter(powers, "idd2n"); - config.memSpec->iDD3P0 = queryDoubleParameter(powers, "idd3p0"); - config.memSpec->iDD3P1 = queryDoubleParameter(powers, "idd3p1"); - config.memSpec->iDD3N = queryDoubleParameter(powers, "idd3n"); - config.memSpec->iDD4R = queryDoubleParameter(powers, "idd4r"); - config.memSpec->iDD4W = queryDoubleParameter(powers, "idd4w"); - config.memSpec->iDD5 = queryDoubleParameter(powers, "idd5"); - config.memSpec->iDD6 = queryDoubleParameter(powers, "idd6"); - config.memSpec->iDD62 = 0; - config.memSpec->vDD = queryDoubleParameter(powers, "vdd"); - config.memSpec->vDD2 = 0; -} - -void ConfigurationLoader::loadDDR4(Configuration &config, XMLElement *memspec) -{ - //MemArchitecture - XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec"); - - config.memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks"); - config.memSpec->NumberOfBankGroups = queryUIntParameter(architecture, - "nbrOfBankGroups"); - config.memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); - config.memSpec->BurstLength = queryUIntParameter(architecture, "burstLength"); - config.memSpec->nActivate = 4; - config.memSpec->DataRate = queryUIntParameter(architecture, "dataRate"); - config.memSpec->NumberOfRows = queryUIntParameter(architecture, "nbrOfRows"); - config.memSpec->NumberOfColumns = queryUIntParameter(architecture, - "nbrOfColumns"); - config.memSpec->bitWidth = queryUIntParameter(architecture, "width"); - config.memSpec->DLL = true; - config.memSpec->termination = true; - - //MemTimings - XMLElement *timings = memspec->FirstChildElement("memtimingspec"); - config.memSpec->clkMHz = queryDoubleParameter(timings, "clkMhz"); - config.memSpec->clk = FrequencyToClk(config.memSpec->clkMHz); - sc_time clk = config.memSpec->clk; - config.memSpec->tRP = clk * queryUIntParameter(timings, "RP"); - config.memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); - config.memSpec->tRC = clk * queryUIntParameter(timings, "RC"); - config.memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); - config.memSpec->tRRD_S = clk * queryUIntParameter(timings, "RRD_S"); - config.memSpec->tRRD_L = clk * queryUIntParameter(timings, "RRD_L"); - config.memSpec->tCCD_S = clk * queryUIntParameter(timings, "CCD_S"); - config.memSpec->tCCD_L = clk * queryUIntParameter(timings, "CCD_L"); - config.memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); - config.memSpec->tNAW = clk * queryUIntParameter(timings, "FAW"); - config.memSpec->tRL = clk * queryUIntParameter(timings, "RL"); - config.memSpec->tWL = clk * queryUIntParameter(timings, "WL"); - config.memSpec->tWR = clk * queryUIntParameter(timings, "WR"); - config.memSpec->tWTR_S = clk * queryUIntParameter(timings, "WTR_S"); - config.memSpec->tWTR_L = clk * queryUIntParameter(timings, "WTR_L"); - config.memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); - config.memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); - config.memSpec->tXP = clk * queryUIntParameter(timings, "XP"); - config.memSpec->tXPDLL = clk * queryUIntParameter(timings, "XPDLL"); - config.memSpec->tXSR = clk * queryUIntParameter(timings, "XS"); - config.memSpec->tXSRDLL = clk * queryUIntParameter(timings, "XSDLL"); - config.memSpec->tAL = clk * queryUIntParameter(timings, "AL"); - config.memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); - config.memSpec->tRFC2 = clk * queryUIntParameter(timings, "RFC2"); - config.memSpec->tRFC4 = clk * queryUIntParameter(timings, "RFC4"); - config.memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); - config.memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); - - config.memSpec->refreshTimings.clear(); - for (unsigned int i = 0; i < config.memSpec->NumberOfBanks; ++i) { - config.memSpec->refreshTimings[Bank(i)] = RefreshTiming(config.memSpec->tRFC, - config.memSpec->tRFC2, - config.memSpec->tRFC4, - config.memSpec->tREFI); - } - - // Currents and Volatages: - XMLElement *powers = memspec->FirstChildElement("mempowerspec"); - config.memSpec->iDD0 = queryDoubleParameter(powers, "idd0"); - config.memSpec->iDD02 = queryDoubleParameter(powers, "idd02"); - config.memSpec->iDD2P0 = queryDoubleParameter(powers, "idd2p0"); - config.memSpec->iDD2P1 = queryDoubleParameter(powers, "idd2p1"); - config.memSpec->iDD2N = queryDoubleParameter(powers, "idd2n"); - config.memSpec->iDD3P0 = queryDoubleParameter(powers, "idd3p0"); - config.memSpec->iDD3P1 = queryDoubleParameter(powers, "idd3p1"); - config.memSpec->iDD3N = queryDoubleParameter(powers, "idd3n"); - config.memSpec->iDD4R = queryDoubleParameter(powers, "idd4r"); - config.memSpec->iDD4W = queryDoubleParameter(powers, "idd4w"); - config.memSpec->iDD5 = queryDoubleParameter(powers, "idd5"); - config.memSpec->iDD6 = queryDoubleParameter(powers, "idd6"); - config.memSpec->iDD62 = queryDoubleParameter(powers, "idd62"); - config.memSpec->vDD = queryDoubleParameter(powers, "vdd"); - config.memSpec->vDD2 = queryDoubleParameter(powers, "vdd2"); -} - -// TODO: change timings for LPDDR4 -void ConfigurationLoader::loadLPDDR4(Configuration &config, XMLElement *memspec) -{ - //MemArchitecture: - XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec"); - - config.memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks"); - config.memSpec->NumberOfBankGroups = 1; - config.memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); - config.memSpec->BurstLength = queryUIntParameter(architecture, "burstLength"); - config.memSpec->nActivate = 4; - config.memSpec->DataRate = queryUIntParameter(architecture, "dataRate"); - config.memSpec->NumberOfRows = queryUIntParameter(architecture, "nbrOfRows"); - config.memSpec->NumberOfColumns = queryUIntParameter(architecture, - "nbrOfColumns"); - config.memSpec->bitWidth = queryUIntParameter(architecture, "width"); - config.memSpec->DLL = false; // TODO: Correct? - config.memSpec->termination = true; // TODO: Correct? - - //MemTimings - XMLElement *timings = memspec->FirstChildElement("memtimingspec"); - config.memSpec->clkMHz = queryDoubleParameter(timings, "clkMhz"); - config.memSpec->clk = FrequencyToClk(config.memSpec->clkMHz); - sc_time clk = config.memSpec->clk; - config.memSpec->tRP = clk * queryUIntParameter(timings, "RPPB"); - config.memSpec->tRPAB = clk * queryUIntParameter(timings, "RPAB"); - config.memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); - config.memSpec->tRC = clk * queryUIntParameter(timings, "RC"); - config.memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); - config.memSpec->tRRD_S = clk * queryUIntParameter(timings, "RRD"); - config.memSpec->tRRD_L = clk * queryUIntParameter(timings, "RRD"); - config.memSpec->tCCD_S = clk * queryUIntParameter(timings, "CCD"); - config.memSpec->tCCD_L = clk * queryUIntParameter(timings, "CCD"); - config.memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); - config.memSpec->tNAW = clk * queryUIntParameter(timings, "FAW"); - config.memSpec->tRL = clk * queryUIntParameter(timings, "RL"); - config.memSpec->tWL = clk * queryUIntParameter(timings, "WL"); - config.memSpec->tWR = clk * queryUIntParameter(timings, "WR"); - config.memSpec->tWTR_S = clk * queryUIntParameter(timings, "WTR"); - config.memSpec->tWTR_L = clk * queryUIntParameter(timings, "WTR"); - config.memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); - config.memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); - config.memSpec->tXP = clk * queryUIntParameter(timings, "XP"); - config.memSpec->tXPDLL = clk * queryUIntParameter(timings, "XP"); - config.memSpec->tXSR = clk * queryUIntParameter(timings, "XS"); - config.memSpec->tXSRDLL = clk * queryUIntParameter(timings, "XS"); - config.memSpec->tAL = clk * queryUIntParameter(timings, "AL"); - config.memSpec->tRFC = clk * queryUIntParameter(timings, "RFCAB"); - // TODO: config.memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB"); - config.memSpec->tREFI = clk * queryUIntParameter(timings, "REFIAB"); - // TODO: config.memSpec->tREFIPB = clk * queryUIntParameter(timings, "RFCPB"); - config.memSpec->tDQSCK = clk * queryUIntParameter(timings, "DQSCK"); - - config.memSpec->refreshTimings.clear(); - for (unsigned int i = 0; i < config.memSpec->NumberOfBanks; ++i) { - config.memSpec->refreshTimings[Bank(i)] = RefreshTiming(config.memSpec->tRFC, - config.memSpec->tREFI); - } - - // Currents and Volatages: - XMLElement *powers = memspec->FirstChildElement("mempowerspec"); - config.memSpec->iDD0 = queryDoubleParameter(powers, "idd0"); - config.memSpec->iDD02 = queryDoubleParameter(powers, "idd02"); - config.memSpec->iDD2P0 = queryDoubleParameter(powers, "idd2p"); - config.memSpec->iDD2P1 = queryDoubleParameter(powers, "idd2p2"); - config.memSpec->iDD2N = queryDoubleParameter(powers, "idd2n"); - config.memSpec->iDD3P0 = queryDoubleParameter(powers, "idd3p"); - config.memSpec->iDD3P1 = queryDoubleParameter(powers, "idd3p2"); - config.memSpec->iDD3N = queryDoubleParameter(powers, "idd3n"); - config.memSpec->iDD4R = queryDoubleParameter(powers, "idd4r"); - config.memSpec->iDD4W = queryDoubleParameter(powers, "idd4w"); - config.memSpec->iDD5 = queryDoubleParameter(powers, "idd5"); - config.memSpec->iDD6 = queryDoubleParameter(powers, "idd6"); - config.memSpec->iDD62 = queryDoubleParameter(powers, "idd62"); - config.memSpec->vDD = queryDoubleParameter(powers, "vdd"); - config.memSpec->vDD2 = queryDoubleParameter(powers, "vdd2"); -} - -void ConfigurationLoader::loadWideIO(Configuration &config, XMLElement *memspec) -{ - //MemSpecification - XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec"); - - config.memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks"); - config.memSpec->NumberOfBankGroups = 1; - config.memSpec->NumberOfRanks = 1; - config.memSpec->BurstLength = queryUIntParameter(architecture, "burstLength"); - config.memSpec->nActivate = 2; - config.memSpec->DataRate = queryUIntParameter(architecture, "dataRate"); - config.memSpec->NumberOfRows = queryUIntParameter(architecture, "nbrOfRows"); - config.memSpec->NumberOfColumns = queryUIntParameter(architecture, - "nbrOfColumns"); - config.memSpec->bitWidth = queryUIntParameter(architecture, "width"); - config.memSpec->DLL = false; - config.memSpec->termination = false; - - //MemTimings - XMLElement *timings = memspec->FirstChildElement("memtimingspec"); - config.memSpec->clkMHz = queryDoubleParameter(timings, "clkMhz"); - config.memSpec->clk = FrequencyToClk(config.memSpec->clkMHz); - sc_time clk = config.memSpec->clk; - config.memSpec->tRP = clk * queryUIntParameter(timings, "RP"); - config.memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); - config.memSpec->tRC = clk * queryUIntParameter(timings, "RC"); - config.memSpec->tRRD_S = clk * queryUIntParameter(timings, "RRD"); - config.memSpec->tRRD_L = config.memSpec->tRRD_S; - config.memSpec->tCCD_S = clk * queryUIntParameter(timings, "CCD"); - config.memSpec->tCCD_L = config.memSpec->tCCD_S; - config.memSpec->tRCD = clk * queryUIntParameter(timings, "RCD"); - config.memSpec->tNAW = clk * queryUIntParameter(timings, "TAW"); - config.memSpec->tRL = clk * queryUIntParameter(timings, "RL"); - config.memSpec->tWL = clk * queryUIntParameter(timings, "WL"); - config.memSpec->tWR = clk * queryUIntParameter(timings, "WR"); - config.memSpec->tWTR_S = clk * queryUIntParameter(timings, "WTR"); - config.memSpec->tWTR_L = config.memSpec->tWTR_S; - config.memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); - config.memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); - config.memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); - config.memSpec->tXP = clk * queryUIntParameter(timings, "XP"); - config.memSpec->tXPDLL = config.memSpec->tXP; - config.memSpec->tXSR = clk * queryUIntParameter(timings, "XS"); - config.memSpec->tXSRDLL = config.memSpec->tXSR; - config.memSpec->tAL = clk * queryUIntParameter(timings, "AL"); - config.memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); - config.memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); - - config.memSpec->refreshTimings.clear(); - for (unsigned int i = 0; i < config.memSpec->NumberOfBanks; ++i) { - config.memSpec->refreshTimings[Bank(i)] = RefreshTiming(config.memSpec->tRFC, - config.memSpec->tREFI); - } - - // Currents and Volatages: - XMLElement *powers = memspec->FirstChildElement("mempowerspec"); - config.memSpec->iDD0 = queryDoubleParameter(powers, "idd0"); - config.memSpec->iDD02 = queryDoubleParameter(powers, "idd02"); - config.memSpec->iDD2P0 = queryDoubleParameter(powers, "idd2p0"); - config.memSpec->iDD2P02 = queryDoubleParameter(powers, "idd2p02"); - config.memSpec->iDD2P1 = queryDoubleParameter(powers, "idd2p1"); - config.memSpec->iDD2P12 = queryDoubleParameter(powers, "idd2p12"); - config.memSpec->iDD2N = queryDoubleParameter(powers, "idd2n"); - config.memSpec->iDD2N2 = queryDoubleParameter(powers, "idd2n2"); - config.memSpec->iDD3P0 = queryDoubleParameter(powers, "idd3p0"); - config.memSpec->iDD3P02 = queryDoubleParameter(powers, "idd3p02"); - config.memSpec->iDD3P1 = queryDoubleParameter(powers, "idd3p1"); - config.memSpec->iDD3P12 = queryDoubleParameter(powers, "idd3p12"); - config.memSpec->iDD3N = queryDoubleParameter(powers, "idd3n"); - config.memSpec->iDD3N2 = queryDoubleParameter(powers, "idd3n2"); - config.memSpec->iDD4R = queryDoubleParameter(powers, "idd4r"); - config.memSpec->iDD4R2 = queryDoubleParameter(powers, "idd4r2"); - config.memSpec->iDD4W = queryDoubleParameter(powers, "idd4w"); - config.memSpec->iDD4W2 = queryDoubleParameter(powers, "idd4w2"); - config.memSpec->iDD5 = queryDoubleParameter(powers, "idd5"); - config.memSpec->iDD52 = queryDoubleParameter(powers, "idd52"); - config.memSpec->iDD6 = queryDoubleParameter(powers, "idd6"); - config.memSpec->iDD62 = queryDoubleParameter(powers, "idd62"); - config.memSpec->vDD = queryDoubleParameter(powers, "vdd"); - config.memSpec->vDD2 = queryDoubleParameter(powers, "vdd2"); -} diff --git a/DRAMSys/library/src/controller/core/configuration/MemSpec.h b/DRAMSys/library/src/controller/core/configuration/MemSpec.h deleted file mode 100644 index d13f2701..00000000 --- a/DRAMSys/library/src/controller/core/configuration/MemSpec.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Lukas Steiner - */ - -#ifndef MEMSPEC_H -#define MEMSPEC_H - -#include -#include -#include "../../../common/dramExtensions.h" - -struct RefreshTiming -{ - RefreshTiming() {} - RefreshTiming(sc_time tRFC, sc_time tREFI) : tRFC(tRFC), tRFC2(SC_ZERO_TIME), - tRFC4(SC_ZERO_TIME), tREFI(tREFI) {} - RefreshTiming(sc_time tRFC, sc_time tRFC2, sc_time tRFC4, - sc_time tREFI) : tRFC(tRFC), tRFC2(tRFC2), tRFC4(tRFC4), tREFI(tREFI) {} - sc_time tRFC; - sc_time tRFC2; - sc_time tRFC4; - sc_time tREFI; -}; - -struct MemSpec -{ - const std::vector &getBanks() const - { - static std::vector banks; - if (banks.size() == 0) { - for (unsigned int i = 0; i < NumberOfBanks; i++) { - banks.push_back(Bank(i)); - } - } - - return banks; - } - - std::string MemoryId = "not defined."; - std::string MemoryType = "not defined."; - - unsigned int NumberOfBanks; - unsigned int NumberOfBankGroups; - unsigned int NumberOfRanks; - unsigned int BurstLength; - unsigned int nActivate; - unsigned int DataRate; - unsigned int NumberOfRows; - unsigned int NumberOfColumns; - unsigned int bitWidth; - bool DLL; - bool termination; - - // Memspec Variables: - double clkMHz; - sc_time clk; - sc_time tRP; //precharge-time (pre -> act same bank - sc_time tRTP; //Read to precharge - sc_time tRCD; //act -> read/write - sc_time tRL; //read latency (read command start to data strobe) - sc_time tWL; //write latency - sc_time tWR; //write recovery (write to precharge) - sc_time tCKESR; //min time in sref - sc_time tCKE; //min time in pdna or pdnp - - sc_time tRFC; //min ref->act delay 1X mode - sc_time tRFC2; //min ref->act delay 2X mode - sc_time tRFC4; //min ref->act delay 4X mode - sc_time tREFI; //auto refresh must be issued at an average periodic interval tREFI - - // TODO: move to specific memspecs - sc_time tRPAB; //precharge-all time only for LPDDR4 - sc_time tRAS; //active-time (act -> pre same bank) - sc_time tRC; //RAS-cycle-time (min time bw 2 succesive ACT to same bank) - sc_time tCCD_S; //max(bl, tCCD) is relevant for rd->rd - sc_time tCCD_L; - sc_time tRRD_S; //min time bw 2 succesive ACT to different banks (different bank group) - sc_time tRRD_L; //.. (same bank group) - sc_time tNAW; //n activate window - sc_time tWTR_S; //write to read (different bank group) - sc_time tWTR_L; //.. (same bank group) - sc_time tXP; //min delay to row access command after pdnpx pdnax - sc_time tXPDLL; //min delay to row access command after pdnpx pdnax for dll commands - sc_time tXSR; //min delay to row access command after srefx - sc_time tXSRDLL; //min delay to row access command after srefx for dll commands - sc_time tAL; //additive delay (delayed execution in dram) - sc_time tDQSCK; - - // Currents and Voltages: - double iDD0; - double iDD02; - double iDD2P0; - double iDD2P02; - double iDD2P1; - double iDD2P12; - double iDD2N; - double iDD2N2; - double iDD3P0; - double iDD3P02; - double iDD3P1; - double iDD3P12; - double iDD3N; - double iDD3N2; - double iDD4R; - double iDD4R2; - double iDD4W; - double iDD4W2; - double iDD5; - double iDD52; - double iDD6; - double iDD62; - double vDD; - double vDD2; - - - std::map - refreshTimings;//ensure that map is populated completely in memspecloader - - //act and read/write commands remain for this timespan in history - sc_time tActHistory() - { - return tNAW; - } - sc_time tActBHistory() - { - return tNAW; - } - sc_time tDataStrobeHistory() - { - return tWTR_L; - } -}; - -struct MemSpecDDR3 : public MemSpec -{ - -}; - -struct MemSpecDDR4 : public MemSpec -{ - -}; - -struct MemSpecWideIO : public MemSpec -{ - -}; - -struct MemSpecLPDDR4 : public MemSpec -{ - -}; - -#endif // MEMSPEC_H - diff --git a/DRAMSys/library/src/controller/core/powerdown/IPowerDownManager.h b/DRAMSys/library/src/controller/core/powerdown/IPowerDownManager.h deleted file mode 100644 index 9ff8bd39..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/IPowerDownManager.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef IPOWERDOWNMANAGER_H -#define IPOWERDOWNMANAGER_H - -#include -#include "../../../common/dramExtensions.h" -#include "../../Command.h" - - -enum class PowerDownState { - Awake, AwakeForRefresh, PDNActive, PDNPrecharge, PDNSelfRefresh -}; - -class IPowerDownManager -{ -public: - virtual ~IPowerDownManager() {} - - virtual void sleep(Bank bank, sc_time time) = 0; - virtual void triggerSleep(Bank bank, sc_time time) = 0; - - virtual void wakeUp(Bank bank, sc_time time) = 0; - virtual void wakeUpForRefresh(Bank bank, sc_time time) = 0; - - virtual bool isInSelfRefresh(Bank bank) = 0; - -protected: - Command getSleepCommand(PowerDownState state); - Command getWakeUpCommand(PowerDownState state); - -}; - -inline Command IPowerDownManager::getSleepCommand(PowerDownState state) -{ - Command cmd(Command::NOP); - switch (state) { - case PowerDownState::PDNActive: - cmd = Command::PDNA; - break; - case PowerDownState::PDNPrecharge: - cmd = Command::PDNP; - break; - case PowerDownState::PDNSelfRefresh: - cmd = Command::SREF; - break; - default: - SC_REPORT_FATAL("In PowerDownManager sendPowerdownBegin", - "invalid powerDownState"); - break; - } - return cmd; -} - -inline Command IPowerDownManager::getWakeUpCommand(PowerDownState state) - -{ - Command cmd(Command::NOP); - switch (state) { - case PowerDownState::PDNActive: - cmd = Command::PDNAX; - break; - case PowerDownState::PDNPrecharge: - cmd = Command::PDNPX; - break; - case PowerDownState::PDNSelfRefresh: - cmd = Command::SREFX; - break; - default: - SC_REPORT_FATAL("In PowerDownManager sendPowerdownEnd", - "invalid powerDownState"); - } - return cmd; -} - -inline std::string powerDownStateToString(PowerDownState powerDownState) -{ - switch (powerDownState) { - case PowerDownState::Awake: - return "Awake"; - case PowerDownState::AwakeForRefresh: - return "Awake for refresh"; - case PowerDownState::PDNActive: - return "PDN Active"; - case PowerDownState::PDNPrecharge: - return "PDN Precharged"; - case PowerDownState::PDNSelfRefresh: - return "PDN Self refresh"; - default: - return "unknown state"; - } -} - - -#endif // IPOWERDOWNMANAGER_H diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManager.cpp b/DRAMSys/library/src/controller/core/powerdown/PowerDownManager.cpp deleted file mode 100644 index d5281e05..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManager.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Felipe S. Prado - */ - -#include -#include -#include "PowerDownManager.h" -#include "../ControllerCore.h" -#include "../timingCalculations.h" -#include "../../../common/DebugManager.h" -#include -#include "../../../common/utils.h" - -using namespace tlm; -using namespace std; - - -PowerDownManager::PowerDownManager(sc_module_name /*name*/, - ControllerCore &controller) : - controllerCore(controller) -{ - powerDownState = PowerDownState::Awake; - for (Bank bank : controller.getBanks()) { - setUpDummy(powerDownPayloads[bank], bank); - } - //controllerCore.controller.send(PDNTrigger, sc_time_stamp(), powerDownPayloads[Bank(0)]); -} - -PowerDownManager::~PowerDownManager() -{ - -} - -void PowerDownManager::sleep(Bank /*bank*/, sc_time time) -{ - if (!canSleep() || isInPowerDown()) - return; - - PowerDownState state = powerDownState; - - if (state == PowerDownState::Awake) { //coming from active - state = controllerCore.state->rowBufferStates->allRowBuffersAreClosed() ? - PowerDownState::PDNPrecharge : PowerDownState::PDNActive; - } else if (state == - PowerDownState::AwakeForRefresh) { //coming from refresh interrupting power down - sc_assert(controllerCore.state->rowBufferStates->allRowBuffersAreClosed()); - - if (controllerCore.state->getLastCommand(Command::PDNA).getStart() - >= controllerCore.state->getLastCommand(Command::PDNP).getStart()) - state = PowerDownState::PDNPrecharge; - else { - state = PowerDownState::PDNSelfRefresh; - } - } - - Command cmd = IPowerDownManager::getSleepCommand(state); - ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd), - DramExtension::getExtension(powerDownPayloads[Bank(0)])); - - controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn); - - if (state != PowerDownState::PDNSelfRefresh - && controllerCore.refreshManager->hasCollision(pdn)) { - return; - } else { - setPowerDownState(state); - sendPowerDownPayload(pdn); - } -} - -void PowerDownManager::wakeUp(Bank bank, sc_time time) -{ - printDebugMessage("Waking up at " + time.to_string() + - " current power down state is " + powerDownStateToString(powerDownState)); - - if (isAwakeForRefresh()) { //Request enters system during Refresh - setPowerDownState(PowerDownState::Awake); - } else if (isInPowerDown()) { //Request wakes up power down - Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState); - ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, - powerDownPayloads[Bank(0)]), - DramExtension::getExtension(powerDownPayloads[Bank(0)])); - controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn); - - if (cmd == Command::SREFX) { - // Leaving Self Refresh. Plan the next refresh. - controllerCore.refreshManager->reInitialize(bank, pdn.getEnd()); - printDebugMessage("Waking up. Leaving Self Refresh at " + time.to_string() + - " next refresh planned to " + pdn.getEnd().to_string()); - } - - setPowerDownState(PowerDownState::Awake); - - printDebugMessage("Sending power down exit command " + commandToString( - cmd) + " on all banks"); - sendPowerDownPayload(pdn); - } - - printDebugMessage("Awaken at " + time.to_string() + - " current power down state is " + powerDownStateToString(powerDownState)); -} - -void PowerDownManager::wakeUpForRefresh(Bank /*bank*/, sc_time time) -{ - printDebugMessage("Waking up for refresh at " + time.to_string() + - " current power down state is " + powerDownStateToString(powerDownState)); - - if (isInPowerDown()) { - Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState); - ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, - powerDownPayloads[Bank(0)]), - DramExtension::getExtension(powerDownPayloads[Bank(0)])); - - setPowerDownState(PowerDownState::AwakeForRefresh); - - printDebugMessage("Sending power down exit command " + commandToString( - cmd) + " on all banks"); - sendPowerDownPayload(pdn); - } - - printDebugMessage("Awaken for refresh at " + time.to_string() + - " current power down state is " + powerDownStateToString(powerDownState)); -} - -void PowerDownManager::sendPowerDownPayload(ScheduledCommand &pdnToSend) -{ - controllerCore.state->bus.moveCommandToNextFreeSlot(pdnToSend); - for (size_t bank = 1; bank < controllerCore.getBanks().size(); bank++) { - tlm_generic_payload &payloadToSend = powerDownPayloads[bank]; - - ScheduledCommand pdn(pdnToSend.getCommand(), pdnToSend.getStart(), - pdnToSend.getExecutionTime(), DramExtension::getExtension(payloadToSend)); - controllerCore.state->change(pdn); - - } - controllerCore.state->change(pdnToSend); - controllerCore.controller.send(pdnToSend, powerDownPayloads[Bank(0)]); - printDebugMessage("Sending power down command " + commandToString( - pdnToSend.getCommand()) + " on bank " + to_string(pdnToSend.getBank().ID()) + - " start time " + pdnToSend.getStart().to_string() + " end time " + - pdnToSend.getEnd().to_string()); -} - -void PowerDownManager::setPowerDownState(PowerDownState state) -{ - powerDownState = state; - printDebugMessage("Is now in state " + powerDownStateToString( - powerDownState) + " on all banks"); -} - -bool PowerDownManager::isInPowerDown() -{ - return (powerDownState == PowerDownState::PDNActive - || powerDownState == PowerDownState::PDNPrecharge - || powerDownState == PowerDownState::PDNSelfRefresh); -} - -bool PowerDownManager::canSleep() -{ - for (Bank bank : controllerCore.getBanks()) { - if (!controllerCore.numberOfPayloads[bank] == 0) - return false; - } - return true; -} - -bool PowerDownManager::isInSelfRefresh(Bank /*bank*/) -{ - return powerDownState == PowerDownState::PDNSelfRefresh; -} - -bool PowerDownManager::isAwakeForRefresh() -{ - return powerDownState == PowerDownState::AwakeForRefresh; -} - -void PowerDownManager::triggerSleep(Bank bank, sc_time time) -{ - sleep(bank, time); -} - -void PowerDownManager::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); -} - diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManager.h b/DRAMSys/library/src/controller/core/powerdown/PowerDownManager.h deleted file mode 100644 index ee90629e..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManager.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef POWERDOWNMANAGER_H -#define POWERDOWNMANAGER_H - -#include "PowerDownManagerBankwise.h" - - -class ControllerCore; - -class PowerDownManager: public IPowerDownManager, public sc_module -{ -public: - PowerDownManager(sc_module_name /*name*/, ControllerCore &controllerCore); - virtual ~PowerDownManager(); - - virtual void triggerSleep(Bank bank, sc_time time) override; - virtual void sleep(Bank /*bank*/, sc_time time) override; - virtual void wakeUp(Bank bank, sc_time time) override; - virtual void wakeUpForRefresh(Bank bank, sc_time time) override; - virtual bool isInSelfRefresh(Bank bank) override; - -protected: - void sendPowerDownPayload(ScheduledCommand &pdnToSend); - bool isInPowerDown(); - void setPowerDownState(PowerDownState state); - bool canSleep(); - bool isAwakeForRefresh(); - - PowerDownState powerDownState; - std::map powerDownPayloads; - ControllerCore &controllerCore; - void printDebugMessage(std::string message); -}; - - -#endif // POWERDOWNMANAGER_H diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerBankwise.cpp b/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerBankwise.cpp deleted file mode 100644 index a73d7674..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerBankwise.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#include "PowerDownManager.h" -#include "../ControllerCore.h" -#include "../../../common/utils.h" -#include "../../../common/DebugManager.h" -#include "../timingCalculations.h" - -using namespace tlm; - -PowerDownManagerBankwise::PowerDownManagerBankwise(sc_module_name /*name*/, - ControllerCore &controllerCore) : controllerCore(controllerCore) -{ - for (Bank bank : controllerCore.getBanks()) { - setUpDummy(powerDownPayloads[bank], bank); - powerDownStates[bank] = PowerDownState::Awake; - //controllerCore.controller.send(PDNTrigger, sc_time_stamp(), powerDownPayloads[bank]); - } -} - -void PowerDownManagerBankwise::sleep(Bank bank, sc_time time) -{ - if (!canSleep(bank) || isInPowerDown(bank)) - return; - - tlm_generic_payload &payload = powerDownPayloads[bank]; - - PowerDownState state = powerDownStates[bank]; - if (state == PowerDownState::Awake) { //coming from active - state = controllerCore.state->rowBufferStates->rowBufferIsOpen( - bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge; - } else if (state == - PowerDownState::AwakeForRefresh) { //coming from refresh interrupting power down - sc_assert(!controllerCore.state->rowBufferStates->rowBufferIsOpen(bank)); - - if (controllerCore.state->getLastCommand(Command::PDNA, bank).getStart() - >= controllerCore.state->getLastCommand(Command::PDNP, bank).getStart()) - state = PowerDownState::PDNPrecharge; - else { - state = PowerDownState::PDNSelfRefresh; - } - } - - Command cmd = IPowerDownManager::getSleepCommand(state); - ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd), - DramExtension::getExtension(payload)); - controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn); - - if (state != PowerDownState::PDNSelfRefresh - && controllerCore.refreshManager->hasCollision(pdn)) { - return; - } else { - setPowerDownState(state, bank); - sendPowerDownPayload(pdn); - } -} - -void PowerDownManagerBankwise::wakeUp(Bank bank, sc_time time) -{ - printDebugMessage("Waking up on bank " + to_string(bank.ID()) + " at " + - time.to_string() + " current power down state is " + powerDownStateToString( - powerDownStates[bank])); - - if (isAwakeForRefresh(bank)) { - printDebugMessage("It was already awake for refresh on bank " + to_string( - bank.ID()) + " at " + time.to_string()); - setPowerDownState(PowerDownState::Awake, bank); - } else if (isInPowerDown(bank)) { - // Request wake up from power down. A Power Down Exit request will be generated (PDNAX, PDNPX, SREFX). - Command pdnExitCmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]); - // Mount the command to be scheduled - ScheduledCommand pdnExit(pdnExitCmd, time, getExecutionTime(pdnExitCmd, - powerDownPayloads[bank]), DramExtension::getExtension(powerDownPayloads[bank])); - // Ensure that time constraints are respected - controllerCore.getCommandChecker(pdnExitCmd).delayToSatisfyConstraints(pdnExit); - - if (pdnExitCmd == Command::SREFX) { - // Leaving Self Refresh. Plan the next refresh. - controllerCore.refreshManager->reInitialize(bank, pdnExit.getEnd()); - printDebugMessage("Waking up. Leaving Self Refresh on Bank " + to_string( - bank.ID()) + " at " + time.to_string() + " next refresh planned to " + - pdnExit.getEnd().to_string()); - } - - setPowerDownState(PowerDownState::Awake, bank); - - printDebugMessage("Sending power down exit command " + commandToString( - pdnExitCmd) + " on bank " + to_string(bank.ID()) + " at " + time.to_string() + - " start time " + pdnExit.getStart().to_string() + " end time " + - pdnExit.getEnd().to_string()); - sendPowerDownPayload(pdnExit); - } - - printDebugMessage("Awaken on bank " + to_string(bank.ID()) + " at " + - time.to_string() + " current power down state is " + powerDownStateToString( - powerDownStates[bank])); -} - -void PowerDownManagerBankwise::wakeUpForRefresh(Bank bank, sc_time time) -{ - printDebugMessage("Waking up for refresh on bank " + to_string( - bank.ID()) + " at " + time.to_string() + " current power down state is " + - powerDownStateToString(powerDownStates[bank])); - - if (isInPowerDown(bank)) { - // A Power Down Exit request will be generated (PDNAX, PDNPX, SREFX). - Command pdnExitCmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]); - // Get the execution time for this request - sc_time executionTime = getExecutionTime(pdnExitCmd, powerDownPayloads[bank]); - // Mount the command to be scheduled - ScheduledCommand pdnExit(pdnExitCmd, time, executionTime, - DramExtension::getExtension(powerDownPayloads[bank])); - - setPowerDownState(PowerDownState::AwakeForRefresh, bank); - - printDebugMessage("Sending power down exit command " + commandToString( - pdnExitCmd) + " on bank " + to_string(bank.ID()) + " at " + time.to_string() + - " start time " + pdnExit.getStart().to_string() + " end time " + - pdnExit.getEnd().to_string()); - sendPowerDownPayload(pdnExit); - } - - printDebugMessage("Awaken for refresh on bank " + to_string( - bank.ID()) + " at " + time.to_string() + " current power down state is " + - powerDownStateToString(powerDownStates[bank])); -} - -bool PowerDownManagerBankwise::isInPowerDown(Bank bank) -{ - return isIn(powerDownStates[bank], { PowerDownState::PDNActive, PowerDownState::PDNPrecharge, PowerDownState::PDNSelfRefresh }); -} - -bool PowerDownManagerBankwise::isInSelfRefresh(Bank bank) -{ - return powerDownStates[bank] == PowerDownState::PDNSelfRefresh; -} - -bool PowerDownManagerBankwise::isAwakeForRefresh(Bank bank) -{ - return powerDownStates[bank] == PowerDownState::AwakeForRefresh; -} - -bool PowerDownManagerBankwise::isAwake(Bank bank) -{ - return powerDownStates[bank] == PowerDownState::Awake; -} - -void PowerDownManagerBankwise::setPowerDownState(PowerDownState state, - Bank bank) -{ - PowerDownState &bankstate = powerDownStates[bank]; - bankstate = state; - printDebugMessage("Is now in state " + powerDownStateToString( - state) + " on Bank " + to_string(bank.ID())); -} - -void PowerDownManagerBankwise::sendPowerDownPayload(ScheduledCommand &pdn) -{ - controllerCore.state->bus.moveCommandToNextFreeSlot(pdn); - controllerCore.state->change(pdn); - printDebugMessage("Sending power down command " + commandToString( - pdn.getCommand()) + " on bank " + to_string(pdn.getBank().ID()) + " start time " - + pdn.getStart().to_string() + " end time " + pdn.getEnd().to_string()); - controllerCore.controller.send(pdn, powerDownPayloads[pdn.getBank()]); -} - -bool PowerDownManagerBankwise::canSleep(Bank bank) -{ - return controllerCore.numberOfPayloads[bank] == 0; -} - -void PowerDownManagerBankwise::triggerSleep(Bank bank, sc_time time) -{ - sleep(bank, time); -} - -void PowerDownManagerBankwise::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); -} - diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerBankwise.h b/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerBankwise.h deleted file mode 100644 index 69382538..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerBankwise.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef POWERDOWNMANAGERBANKWISE_H -#define POWERDOWNMANAGERBANKWISE_H - -#include -#include -#include -#include -#include "../../Command.h" -#include "../../../common/dramExtensions.h" -#include "../scheduling/ScheduledCommand.h" -#include "IPowerDownManager.h" - - -class ControllerCore; - -class PowerDownManagerBankwise : public sc_module, public IPowerDownManager -{ -public: - PowerDownManagerBankwise(sc_module_name /*name*/, - ControllerCore &controllerCore); - virtual ~PowerDownManagerBankwise() {} - virtual void triggerSleep(Bank bank, sc_time time) override; - virtual void sleep(Bank bank, sc_time time) override; - virtual void wakeUp(Bank bank, sc_time time) override; - virtual void wakeUpForRefresh(Bank bank, sc_time time) override; - virtual bool isInSelfRefresh(Bank bank) override; - -protected: - virtual bool isInPowerDown(Bank bank); - virtual bool isAwake(Bank bank); - virtual bool isAwakeForRefresh(Bank bank); - - ControllerCore &controllerCore; - std::map powerDownPayloads; - std::map powerDownStates; - - virtual bool canSleep(Bank bank); - - void setPowerDownState(PowerDownState state, Bank bank); - - Command getWakeUpCommand(PowerDownState state); - Command getSleepCommand(PowerDownState state); - - void sendPowerDownPayload(ScheduledCommand &pdn); - - void printDebugMessage(std::string message); -}; - -#endif // POWERDOWNMANAGERBANKWISE_H - diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeout.cpp b/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeout.cpp deleted file mode 100644 index 997e9c37..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeout.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Felipe S. Prado - */ - -#include "PowerDownManagerTimeout.h" -#include "../ControllerCore.h" -#include "../../../common/utils.h" -#include "../../../common/DebugManager.h" -#include "../timingCalculations.h" - -using namespace tlm; - -PowerDownManagerTimeout::PowerDownManagerTimeout(sc_module_name name, - ControllerCore &controllerCore): - PowerDownManager(name, controllerCore) -{ - //controllerCore.controller.send(PDNTrigger, Configuration::getInstance().getPowerDownTimeout(), powerDownPayloads[Bank(0)]); -} - -PowerDownManagerTimeout::~PowerDownManagerTimeout() -{ - // TODO Auto-generated destructor stub -} - -void PowerDownManagerTimeout::sleep(Bank /*bank*/, sc_time time) -{ - bool timeoutTest; - if (!isAwakeForRefresh()) { - sc_time lastReadScheduled; - sc_time lastWriteScheduled; - if (Configuration::getInstance().OpenPagePolicy) { - lastReadScheduled = controllerCore.state->getLastCommand( - Command::Read).getEnd(); - lastWriteScheduled = controllerCore.state->getLastCommand( - Command::Write).getEnd(); - } else { - lastReadScheduled = controllerCore.state->getLastCommand( - Command::ReadA).getEnd(); - lastWriteScheduled = controllerCore.state->getLastCommand( - Command::WriteA).getEnd(); - } - sc_time lastScheduledCommand = max(lastReadScheduled, lastWriteScheduled); - timeoutTest = (time - lastScheduledCommand) >= - Configuration::getInstance().getPowerDownTimeout(); - } else { - timeoutTest = true; - } - - //test_awakeForRefresh = false; - - if ( canSleep() && !isInPowerDown() && timeoutTest) { - - PowerDownState newState; - if (Configuration::getInstance().PowerDownMode == EPowerDownMode::TimeoutPDN) { - newState = controllerCore.state->rowBufferStates->allRowBuffersAreClosed() ? - PowerDownState::PDNPrecharge : PowerDownState::PDNActive; - } else { // PowerDownMode == TimeoutSREF - if (!controllerCore.state->rowBufferStates->allRowBuffersAreClosed()) { - ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time, - getExecutionTime(Command::PrechargeAll, powerDownPayloads[Bank(0)]), - DramExtension::getExtension(powerDownPayloads[Bank(0)])); - - controllerCore.getCommandChecker( - Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster); - - if (controllerCore.refreshManager->hasCollision(prechargeAllMaster)) { - return; - } else { - for (size_t i = 1; i < controllerCore.getBanks().size(); i++) { - ScheduledCommand prechargeAll(Command::PrechargeAll, - prechargeAllMaster.getStart(), prechargeAllMaster.getExecutionTime(), - powerDownPayloads[Bank(i)]); - controllerCore.state->change(prechargeAll); - } - controllerCore.state->change(prechargeAllMaster); - controllerCore.controller.send(prechargeAllMaster, powerDownPayloads[Bank(0)]); - } - - } - - newState = PowerDownState::PDNSelfRefresh; - } - - Command cmd = IPowerDownManager::getSleepCommand(newState); - ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd), - DramExtension::getExtension(powerDownPayloads[Bank(0)])); - - controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn); - - if (controllerCore.refreshManager->hasCollision(pdn)) { - return; - } else { - setPowerDownState(newState); - sendPowerDownPayload(pdn); - } - } -} - -void PowerDownManagerTimeout::triggerSleep(Bank /*bank*/, sc_time time) -{ - if (canSleep() && !isInPowerDown()) { - controllerCore.controller.send(PDNTrigger, - time + controllerCore.config.getPowerDownTimeout(), powerDownPayloads[Bank(0)]); - } -} - diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeout.h b/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeout.h deleted file mode 100644 index d56675f5..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeout.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Felipe S. Prado - */ - -#ifndef POWERDOWNMANAGERTIMEOUT_H -#define POWERDOWNMANAGERTIMEOUT_H - -#include "PowerDownManager.h" -#include -#include "../../../common/dramExtensions.h" -#include "../scheduling/ScheduledCommand.h" -#include - -class ControllerCore; - -class PowerDownManagerTimeout: public PowerDownManager -{ -public: - PowerDownManagerTimeout(sc_module_name /*name*/, - ControllerCore &controllerCore); - virtual ~PowerDownManagerTimeout(); - - virtual void triggerSleep(Bank /*bank*/, sc_time time); - virtual void sleep(Bank /*bank*/, sc_time time); -}; - - - -#endif // POWERDOWNMANAGERTIMEOUT_H diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp b/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp deleted file mode 100644 index cd743e02..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Felipe S. Prado - */ - -#include "PowerDownManagerTimeoutBankwise.h" -#include "../ControllerCore.h" -#include "../../../common/utils.h" -#include "../../../common/DebugManager.h" -#include "../timingCalculations.h" - -using namespace tlm; - -PowerDownManagerTimeoutBankwise::PowerDownManagerTimeoutBankwise( - sc_module_name name, ControllerCore &controllerCore): - PowerDownManagerBankwise(name, controllerCore) -{ - /*for (Bank bank : controllerCore.getBanks()) - { - controllerCore.controller.send(PDNTrigger, controllerCore.config.getPowerDownTimeout(), powerDownPayloads[bank]); - }*/ -} - -PowerDownManagerTimeoutBankwise::~PowerDownManagerTimeoutBankwise() -{ - // TODO Auto-generated destructor stub -} - -void PowerDownManagerTimeoutBankwise::sleep(Bank bank, sc_time time) -{ - bool timeoutTest; - if (!isAwakeForRefresh(bank)) { - sc_time lastReadScheduled; - sc_time lastWriteScheduled; - if (Configuration::getInstance().OpenPagePolicy) { - lastReadScheduled = controllerCore.state->getLastCommand(Command::Read, - bank).getEnd(); - lastWriteScheduled = controllerCore.state->getLastCommand(Command::Write, - bank).getEnd(); - } else { - lastReadScheduled = controllerCore.state->getLastCommand(Command::ReadA, - bank).getEnd(); - lastWriteScheduled = controllerCore.state->getLastCommand(Command::WriteA, - bank).getEnd(); - } - sc_time lastScheduledCommand = max(lastReadScheduled, lastWriteScheduled); - timeoutTest = (time - lastScheduledCommand) >= - Configuration::getInstance().getPowerDownTimeout(); - } else { - timeoutTest = true; - } - - if ( canSleep(bank) && !isInPowerDown(bank) && timeoutTest) { - PowerDownState newState; - if (Configuration::getInstance().PowerDownMode == EPowerDownMode::TimeoutPDN) { - newState = controllerCore.state->rowBufferStates->rowBufferIsOpen( - bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge; - } else { // PowerDownMode == TimeoutSREF - if (controllerCore.state->rowBufferStates->rowBufferIsOpen(bank)) { - ScheduledCommand precharge(Command::Precharge, time, - getExecutionTime(Command::Precharge, powerDownPayloads[bank]), - DramExtension::getExtension(powerDownPayloads[bank])); - - controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints( - precharge); - - if (controllerCore.refreshManager->hasCollision(precharge)) { - return; - } else { - controllerCore.state->change(precharge); - controllerCore.controller.send(precharge, powerDownPayloads[bank]); - } - - } - - newState = PowerDownState::PDNSelfRefresh; - } - - - Command cmd = IPowerDownManager::getSleepCommand(newState); - ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd), - DramExtension::getExtension(powerDownPayloads[bank])); - - controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn); - - if (controllerCore.refreshManager->hasCollision(pdn)) { - return; - } else { - setPowerDownState(newState, bank); - sendPowerDownPayload(pdn); - } - } -} - -void PowerDownManagerTimeoutBankwise::triggerSleep(Bank bank, sc_time time) -{ - if (canSleep(bank) && !isInPowerDown(bank)) { - controllerCore.controller.send(PDNTrigger, - time + controllerCore.config.getPowerDownTimeout(), powerDownPayloads[bank]); - } -} diff --git a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.h b/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.h deleted file mode 100644 index e4a43bed..00000000 --- a/DRAMSys/library/src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Felipe S. Prado - */ - -#ifndef POWERDOWNMANAGERTIMEOUTBANKWISE_H -#define POWERDOWNMANAGERTIMEOUTBANKWISE_H - -#include "PowerDownManager.h" -#include -#include "../../../common/dramExtensions.h" -#include "../scheduling/ScheduledCommand.h" -#include - -class ControllerCore; - -class PowerDownManagerTimeoutBankwise: public PowerDownManagerBankwise -{ -public: - PowerDownManagerTimeoutBankwise(sc_module_name /*name*/, - ControllerCore &controllerCore); - virtual ~PowerDownManagerTimeoutBankwise(); - - virtual void triggerSleep(Bank bank, sc_time time); - virtual void sleep(Bank bank, sc_time time); -}; - - - -#endif // POWERDOWNMANAGERTIMEOUTBANKWISE_H diff --git a/DRAMSys/library/src/controller/core/refresh/IRefreshManager.h b/DRAMSys/library/src/controller/core/refresh/IRefreshManager.h deleted file mode 100644 index 9b2f581b..00000000 --- a/DRAMSys/library/src/controller/core/refresh/IRefreshManager.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - */ - -#ifndef IREFRESHMANAGER_H -#define IREFRESHMANAGER_H - -#include -#include "../scheduling/ScheduledCommand.h" - -// Flex. refresh (pull-in, postpone) -typedef enum { - ST_REFRESH = 0, - ST_PULLIN, - ST_POSTPONE, - ST_SKIP, - ST_BURST, - ST_ALIGN -} ref_fsm_state_t; - -class IRefreshManager -{ -public: - virtual ~IRefreshManager() {}; - virtual bool hasCollision(const ScheduledCommand &command) = 0; - virtual void scheduleRefresh(tlm::tlm_generic_payload &payload, - sc_time time) = 0; - virtual void reInitialize(Bank bank, sc_time time) = 0; - virtual bool isInvalidated(tlm::tlm_generic_payload &payload, sc_time time) = 0; -}; - -#endif // IREFRESHMANAGER_H - diff --git a/DRAMSys/library/src/controller/core/refresh/RGR.cpp b/DRAMSys/library/src/controller/core/refresh/RGR.cpp deleted file mode 100644 index f5cea5d0..00000000 --- a/DRAMSys/library/src/controller/core/refresh/RGR.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Éder F. Zulian - */ - -#include - -#include "RGR.h" -#include "../ControllerCore.h" -#include "../timingCalculations.h" -#include "../../../common/utils.h" - -#define TRUE 1 -#define FALSE !(TRUE) -#define INITIAL_DISPLACEMENT FALSE - -using namespace std; - -RGR::RGR(sc_module_name, ControllerCore &ctrlcore) : ccore(ctrlcore), - timing(ctrlcore.config.memSpec->refreshTimings[ccore.getBanks()[0]]) -{ - fmb = ccore.config.ControllerCoreRefForceMaxPostponeBurst; - bwl = ccore.config.BankwiseLogic; - ri = ccore.config.getRowInc(); - auto nr = ccore.config.memSpec->NumberOfRows; - auto nar = ccore.config.getNumAR(); - auto m = ccore.config.getRefMode(); - rpr = (nr / m) / nar; - assert(rpr > 0); - tREFIx = timing.tREFI / m; - trp = ccore.config.getTrpb(); - trcd = ccore.config.memSpec->tRCD; - postponeEnabled = ccore.config.ControllerCoreRefEnablePostpone; - pullInEnabled = ccore.config.ControllerCoreRefEnablePullIn; - maxpostpone = ccore.config.ControllerCoreRefMaxPostponed * m; - maxpullin = ccore.config.ControllerCoreRefMaxPulledIn * m; - for (Bank b : ccore.getBanks()) { - pulledin[b] = 0; - postponed[b] = 0; - currentState[b] = ST_REFRESH; - previousState[b] = ST_REFRESH; - nextState[b] = ST_REFRESH; - setUpDummy(rps[b], b); - } -#if INITIAL_DISPLACEMENT == TRUE - if (bwl) { - auto nbs = ccore.config.memSpec->NumberOfBanks; - for (Bank b : ccore.getBanks()) { - nextPlannedRefreshs[b] = b.ID() * tREFIx / nbs; - } - } -#else - for (Bank b : ccore.getBanks()) { - nextPlannedRefreshs[b] = SC_ZERO_TIME; - } -#endif - if (bwl) { - for (Bank b : ccore.getBanks()) { - planNextRefresh(b, tREFIx, false); - } - } else { - planNextRefresh(ccore.getBanks()[0], tREFIx, false); - } -} - -RGR::~RGR() -{ -} - -bool RGR::hasCollision(const ScheduledCommand &cmd) -{ - Bank b = cmd.getBank(); - if (currentState[b] == ST_BURST) { - // A burst due to postponed refreshes shall not be interrupted. - return true; - } - return false; -} - -sc_time RGR::doRefresh(tlm::tlm_generic_payload &p, sc_time t) -{ - sc_assert(!isInvalidated(p, t)); - Bank b = DramExtension::getExtension(p).getBank(); - bool openBank = ccore.state->rowBufferStates->rowBufferIsOpen(b); - bool allClosed = ccore.state->rowBufferStates->allRowBuffersAreClosed(); - bool pre = bwl ? openBank : !allClosed; - sc_time trfcx = SC_ZERO_TIME; - - if (!bwl) { - for (Bank b : ccore.getBanks()) { - currentRefresh[b] = t; - } - } else { - currentRefresh[b] = t; - } - - if (pre) { - trfcx += trp; - if (bwl) { - if (ccore.config.getRGRBank(b.ID())) { - ccore.scheduleRequest(Command::PreB, rps[b]); - } - } else { - for (Bank b : ccore.getBanks()) { - auto rgrb = ccore.config.getRGRBank(b.ID()); - if (ccore.state->rowBufferStates->rowBufferIsOpen(b) && rgrb) { - ccore.scheduleRequest(Command::PreB, rps[Bank(b)]); - } - } - } - } - - for (unsigned r = 0; r < rpr; r += ri) { - trfcx += trcd + trp; - if (bwl) { - if (ccore.config.getRGRBank(b.ID())) { - ccore.scheduleRequest(Command::ActB, rps[b]); - ccore.scheduleRequest(Command::PreB, rps[b]); - } - DramExtension::getExtension(p).incrementRow(); - } else { - for (Bank b : ccore.getBanks()) { - if (ccore.config.getRGRBank(b.ID())) { - ccore.scheduleRequest(Command::ActB, rps[b]); - ccore.scheduleRequest(Command::PreB, rps[b]); - } - DramExtension::getExtension(rps[b]).incrementRow(); - } - } - } - - return trfcx; -} - -void RGR::scheduleRefresh(tlm::tlm_generic_payload &p, sc_time t) -{ - sc_time nrt; - sc_time trfcx; - Bank b = DramExtension::getExtension(p).getBank(); - bool preq = bwl ? ccore.hasPendingRequests(b) : ccore.hasPendingRequests(); - bool postpone = postponeEnabled && preq && (postponed[b] < maxpostpone); - bool pullIn = pullInEnabled && !preq && (pulledin[b] < maxpullin); - previousState[b] = currentState[b]; - currentState[b] = nextState[b]; - bool align = false; - - switch (currentState[b]) { - case ST_REFRESH: - assert(pulledin[b] == 0 && postponed[b] == 0); - if (postpone) { - nrt = SC_ZERO_TIME; - nextState[b] = ST_POSTPONE; - } else if (pullIn) { - trfcx = doRefresh(p, t); - nrt = trfcx; - nextState[b] = ST_PULLIN; - } else { - doRefresh(p, t); - nrt = tREFIx; - nextState[b] = ST_REFRESH; - } - break; - case ST_PULLIN: - if (pullIn) { - trfcx = doRefresh(p, t); - pulledin[b]++; - nrt = trfcx; - nextState[b] = ST_PULLIN; - } else { - nrt = SC_ZERO_TIME; - nextState[b] = ST_ALIGN; - } - break; - case ST_SKIP: - if (pulledin[b] == 0) { - nrt = SC_ZERO_TIME; - nextState[b] = ST_REFRESH; - } else { - pulledin[b]--; - nrt = tREFIx; - nextState[b] = ST_SKIP; - } - break; - case ST_POSTPONE: - postponed[b]++; - if ((postponed[b] > maxpostpone) || (!preq && !fmb)) { - // Burst triggered by inactivity or max postpone value reached. - nrt = SC_ZERO_TIME; - nextState[b] = ST_BURST; - } else { - nrt = tREFIx; - nextState[b] = ST_POSTPONE; - } - break; - case ST_BURST: - doRefresh(p, t); - postponed[b]--; - if (postponed[b] == 0) { - nrt = SC_ZERO_TIME; - nextState[b] = ST_ALIGN; - } else { - nrt = SC_ZERO_TIME; - nextState[b] = ST_BURST; - } - break; - case ST_ALIGN: - nrt = tREFIx; - align = true; - if (previousState[b] == ST_PULLIN) { - nextState[b] = ST_SKIP; - } else { - nextState[b] = ST_REFRESH; - } - break; - default: - SC_REPORT_FATAL(this->name(), "RGR flex FSM invalid state."); - break; - } - planNextRefresh(bwl ? b : ccore.getBanks()[0], nrt, align); -} - -void RGR::planNextRefresh(Bank b, sc_time t, bool align) -{ - if (align) { - nextPlannedRefreshs[b] = trunc(nextPlannedRefreshs[b].to_double() / - tREFIx.to_double()) * tREFIx; - } - nextPlannedRefreshs[b] += t; - ccore.controller.send(REFTrigger, nextPlannedRefreshs[b], rps[b]); -} - -void RGR::reInitialize(Bank b, sc_time t) -{ - nextPlannedRefreshs[b] = clkAlign(t, Alignment::DOWN); - planNextRefresh(b, tREFIx, true); -} - -bool RGR::isInvalidated(tlm::tlm_generic_payload &p, sc_time t) -{ - return nextPlannedRefreshs[DramExtension::getExtension(p).getBank()] > t; -} - -void RGR::printDebugMessage(std::string msg) -{ - DebugManager::getInstance().printDebugMessage(this->name(), msg); -} diff --git a/DRAMSys/library/src/controller/core/refresh/RGR.h b/DRAMSys/library/src/controller/core/refresh/RGR.h deleted file mode 100644 index bfe8e444..00000000 --- a/DRAMSys/library/src/controller/core/refresh/RGR.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Éder F. Zulian - */ - -#ifndef RGR_H -#define RGR_H - -#include "../../../common/dramExtensions.h" -#include "../configuration/MemSpec.h" -#include "IRefreshManager.h" - -class ControllerCore; - -class RGR : public IRefreshManager, public sc_module -{ -public: - RGR(sc_module_name, ControllerCore &ctrlcore); - virtual ~RGR(); - virtual bool hasCollision(const ScheduledCommand &cmd) override; - virtual void scheduleRefresh(tlm::tlm_generic_payload &p, sc_time t) override; - void reInitialize(Bank bank, sc_time time) override; - bool isInvalidated(tlm::tlm_generic_payload &payload, sc_time time) override; -private: - bool fmb; - bool bwl; - unsigned int ri; - unsigned int rpr; - sc_time trp; - sc_time trcd; - sc_time tREFIx; - ControllerCore &ccore; - RefreshTiming &timing; - std::map rps; - std::map nextPlannedRefreshs; - std::map currentRefresh; - bool postponeEnabled; - bool pullInEnabled; - unsigned int maxpostpone; - unsigned int maxpullin; - std::map pulledin; - std::map postponed; - std::map currentState; - std::map previousState; - std::map nextState; - sc_time doRefresh(tlm::tlm_generic_payload &p, sc_time t); - void planNextRefresh(Bank b, sc_time t, bool align); - void printDebugMessage(std::string message); -}; - -#endif // RGR_H - diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp deleted file mode 100644 index b088ca97..00000000 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Felipe S. Prado - * Ana Mativi - * Éder F. Zulian - */ - -#include "RefreshManager.h" -#include "../ControllerCore.h" -#include "../timingCalculations.h" -#include "../../../common/utils.h" - -using namespace tlm; - -RefreshManager::RefreshManager(sc_module_name, - ControllerCore &controller) : controllerCore(controller), - timing(controller.config.memSpec->refreshTimings[Bank(0)]) -{ - auto m = controllerCore.config.getRefMode(); - tREFIx = timing.tREFI / m; - tRFCx = m == 4 ? timing.tRFC4 : m == 2 ? timing.tRFC2 : timing.tRFC; - postponeEnabled = controllerCore.config.ControllerCoreRefEnablePostpone; - pullInEnabled = controllerCore.config.ControllerCoreRefEnablePullIn; - maxpostpone = controllerCore.config.ControllerCoreRefMaxPostponed * m; - maxpullin = controllerCore.config.ControllerCoreRefMaxPulledIn * m; - pulledin = 0; - postponed = 0; - currentState = ST_REFRESH; - previousState = ST_REFRESH; - nextState = ST_REFRESH; - nextPlannedRefresh = SC_ZERO_TIME; - for (Bank bank : controller.getBanks()) { - setUpDummy(refreshPayloads[bank], bank); - } - planNextRefresh(tREFIx, false); -} - -RefreshManager::~RefreshManager() -{ -} - -//Check if a command will be scheduled during the next refresh period -bool RefreshManager::hasCollision(const ScheduledCommand &command) -{ - bool collisionWithPreviousRefEnd = command.getStart() < - controllerCore.state->getLastCommand(Command::AutoRefresh).getEnd(); - bool collisionWithNextRefStart = command.getEnd() >= nextPlannedRefresh; - if (controllerCore.config.ControllerCoreRefEnablePostpone - && (postponed < maxpostpone)) { - // Flexible refresh is on and have "credits" to postpone. - // Then there will not be a collision with next refresh because - // nextPlannedRefresh will be updated. - collisionWithNextRefStart = false; - } - if (currentState == ST_BURST) { - // A burst due to postponed refreshes shall not be interrupted. - collisionWithNextRefStart = true; - } - return collisionWithPreviousRefEnd || collisionWithNextRefStart; -} - -bool RefreshManager::doRefresh(tlm::tlm_generic_payload &payload, sc_time time) -{ - sc_assert(!isInvalidated(payload, time)); - bool pre = false; - // If any row is open, precharge all. - if (!controllerCore.state->rowBufferStates->allRowBuffersAreClosed()) { - pre = true; - ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time, - getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]), - refreshPayloads[Bank(0)]); - controllerCore.getCommandChecker( - Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster); - - for (size_t i = 1; i < controllerCore.getBanks().size(); i++) { - ScheduledCommand prechargeAll(Command::PrechargeAll, - prechargeAllMaster.getStart(), prechargeAllMaster.getExecutionTime(), - refreshPayloads[Bank(i)]); - controllerCore.state->change(prechargeAll); - } - controllerCore.state->change(prechargeAllMaster); - controllerCore.controller.send(prechargeAllMaster, refreshPayloads[Bank(0)]); - } - - //Otherwise just the AutoRefresh command is scheduled. - ScheduledCommand refreshAllMaster(Command::AutoRefresh, time, - getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]), - DramExtension::getExtension(refreshPayloads[Bank(0)])); - controllerCore.getCommandChecker( - Command::AutoRefresh).delayToSatisfyConstraints(refreshAllMaster); - - for (size_t i = 1; i < controllerCore.getBanks().size(); i++) { - ScheduledCommand refresh(Command::AutoRefresh, refreshAllMaster.getStart(), - refreshAllMaster.getExecutionTime(), refreshPayloads[Bank(i)]); - controllerCore.state->change(refresh); - DramExtension::getExtension(refreshPayloads[Bank(i)]).incrementRow(); - } - controllerCore.state->change(refreshAllMaster); - DramExtension::getExtension(refreshPayloads[Bank(0)]).incrementRow(); - controllerCore.controller.send(refreshAllMaster, refreshPayloads[Bank(0)]); - return pre; -} - - -void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload &payload, - sc_time time) -{ - sc_time nextRefTiming; - bool pendingReq = controllerCore.hasPendingRequests(); - bool canPostpone = postponeEnabled && pendingReq && (postponed < maxpostpone); - bool canPullIn = pullInEnabled && !pendingReq && (pulledin < maxpullin); - previousState = currentState; - currentState = nextState; - bool align = false; - sc_time nrt; - bool pre; - - switch (currentState) { - case ST_REFRESH: - // Regular Refresh. It's possible to migrate from this to the flexible - // refresh states - assert(pulledin == 0 && postponed == 0); - if (canPostpone) { - nextRefTiming = SC_ZERO_TIME; - nextState = ST_POSTPONE; - } else if (canPullIn) { - pre = doRefresh(payload, time); - nrt = tRFCx; - if (pre) - nrt += controllerCore.config.memSpec->tRP; - nextRefTiming = nrt; - nextState = ST_PULLIN; - } else { - doRefresh(payload, time); - nextRefTiming = tREFIx; - nextState = ST_REFRESH; - } - break; - case ST_PULLIN: - // Pull-in a refresh. Try to pull-in refreshes as long it is possible. - if (canPullIn) { - pulledin++; - pre = doRefresh(payload, time); - nrt = tRFCx; - if (pre) - nrt += controllerCore.config.memSpec->tRP; - nextRefTiming = nrt; - nextState = ST_PULLIN; - } else { - nextRefTiming = SC_ZERO_TIME; - nextState = ST_ALIGN; - } - break; - case ST_SKIP: - // Skip the pulled-in refreshes. - if (pulledin == 0) { - nextRefTiming = SC_ZERO_TIME; - nextState = ST_REFRESH; - } else { - pulledin--; - nextRefTiming = tREFIx; - nextState = ST_SKIP; - } - break; - case ST_POSTPONE: - // Postpone Refresh. Delaying refreshes as long as there are pending - // requests and credits to postpone. Should be followed by a burst - // refresh. - postponed++; - if ((postponed > maxpostpone) || (!pendingReq - && !controllerCore.config.ControllerCoreRefForceMaxPostponeBurst)) { - // Burst triggered by inactivity or max postpone value reached. - nextRefTiming = SC_ZERO_TIME; - nextState = ST_BURST; - } else { - nextRefTiming = tREFIx; - nextState = ST_POSTPONE; - } - break; - case ST_BURST: - // Burst postponed refreshes. - pre = doRefresh(payload, time); - postponed--; - if (postponed == 0) { - // All refreshes issued, next state will align to tREFIx - nextRefTiming = SC_ZERO_TIME; - nextState = ST_ALIGN; - } else { - nrt = tRFCx; - if (pre) - nrt += controllerCore.config.memSpec->tRP; - nextRefTiming = nrt; - nextState = ST_BURST; - } - break; - case ST_ALIGN: - // Align Refresh. Adjusting the timing so the next REF timing will be - // a in a time multiple of tREFIx - nextRefTiming = tREFIx; - align = true; - if (previousState == ST_PULLIN) { - nextState = ST_SKIP; - } else { - nextState = ST_REFRESH; - } - break; - default: - SC_REPORT_FATAL(this->name(), "Invalid state in flexible refresh FSM."); - break; - } - planNextRefresh(nextRefTiming, align); -} - -void RefreshManager::planNextRefresh(sc_time nextRefTiming, bool align) -{ - if (align) { - nextPlannedRefresh = trunc(nextPlannedRefresh.to_double() / tREFIx.to_double()) - * tREFIx; - } - nextPlannedRefresh += nextRefTiming; - controllerCore.controller.send(REFTrigger, nextPlannedRefresh, - refreshPayloads[Bank(0)]); -} - -void RefreshManager::reInitialize(Bank, sc_time time) -{ - nextPlannedRefresh = clkAlign(time, Alignment::DOWN); - planNextRefresh(tREFIx, true); -} - -bool RefreshManager::isInvalidated(tlm::tlm_generic_payload &payload - __attribute__((unused)), sc_time time) -{ - return nextPlannedRefresh > time; -} - -void RefreshManager::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); -} - diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManager.h b/DRAMSys/library/src/controller/core/refresh/RefreshManager.h deleted file mode 100644 index c89fa12b..00000000 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManager.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Éder F. Zulian - */ - -#ifndef REFRESHMANAGER_H -#define REFRESHMANAGER_H - -#include "IRefreshManager.h" -#include "../configuration/MemSpec.h" - -class ControllerCore; - -class RefreshManager : public IRefreshManager, public sc_module -{ -public: - RefreshManager(sc_module_name /*name*/, ControllerCore &controllerCore); - virtual ~RefreshManager(); - - virtual bool hasCollision(const ScheduledCommand &command) override; - virtual void scheduleRefresh(tlm::tlm_generic_payload &payload, - sc_time time) override; - void reInitialize(Bank bank, sc_time time) override; - virtual bool isInvalidated(tlm::tlm_generic_payload &payload, - sc_time time) override; - -private: - ControllerCore &controllerCore; - RefreshTiming &timing; - sc_time nextPlannedRefresh; - sc_time tREFIx; - sc_time tRFCx; - std::map refreshPayloads; - bool postponeEnabled; - bool pullInEnabled; - unsigned int maxpostpone; - unsigned int maxpullin; - unsigned int pulledin; - unsigned int postponed; - ref_fsm_state_t currentState; - ref_fsm_state_t previousState; - ref_fsm_state_t nextState; - - bool doRefresh(tlm::tlm_generic_payload &payload, sc_time time); - void planNextRefresh(sc_time time, bool align); - void printDebugMessage(std::string message); -}; - -#endif // REFRESHMANAGER_H - diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.cpp deleted file mode 100644 index c53f779b..00000000 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Éder F. Zulian - */ - -#include "RefreshManagerBankwise.h" -#include "../ControllerCore.h" -#include "../timingCalculations.h" -#include "../../../common/utils.h" - -using namespace std; - -RefreshManagerBankwise::RefreshManagerBankwise(sc_module_name, - ControllerCore &controller) : controllerCore(controller), - timing(controller.config.memSpec->refreshTimings[Bank(0)]) -{ - auto m = controllerCore.config.getRefMode(); - tREFIx = timing.tREFI / m; - tRFCx = m == 4 ? timing.tRFC4 : m == 2 ? timing.tRFC2 : timing.tRFC; - postponeEnabled = controllerCore.config.ControllerCoreRefEnablePostpone; - pullInEnabled = controllerCore.config.ControllerCoreRefEnablePullIn; - maxpostpone = controllerCore.config.ControllerCoreRefMaxPostponed * m; - maxpullin = controllerCore.config.ControllerCoreRefMaxPulledIn * m; - for (Bank bank : controller.getBanks()) { - nextPlannedRefreshs[bank] = SC_ZERO_TIME; - pulledin[bank] = 0; - postponed[bank] = 0; - currentState[bank] = ST_REFRESH; - previousState[bank] = ST_REFRESH; - nextState[bank] = ST_REFRESH; - setUpDummy(refreshPayloads[bank], bank); - planNextRefresh(bank, tREFIx, false); - } -} - -RefreshManagerBankwise::~RefreshManagerBankwise() -{ -} - -bool RefreshManagerBankwise::hasCollision(const ScheduledCommand &command) -{ - Bank bank = command.getBank(); - bool collisionWithPreviousRefEnd = command.getStart() < - controllerCore.state->getLastCommand(Command::AutoRefresh, bank).getEnd(); - bool collisionWithNextRefStart = command.getEnd() >= nextPlannedRefreshs[bank]; - if (controllerCore.config.ControllerCoreRefEnablePostpone - && (postponed[bank] < maxpostpone)) { - // Flexible refresh is on and have "credits" to postpone. - // Then there will not be a collision with next refresh because - // nextPlannedRefresh will be updated. - collisionWithNextRefStart = false; - } - if (currentState[bank] == ST_BURST) { - // A burst due to postponed refreshes shall not be interrupted. - collisionWithNextRefStart = true; - } - return collisionWithPreviousRefEnd || collisionWithNextRefStart; -} - -bool RefreshManagerBankwise::doRefresh(tlm::tlm_generic_payload &payload, - sc_time time) -{ - sc_assert(!isInvalidated(payload, time)); - bool pre = false; - tlm::tlm_generic_payload &refreshPayload = - refreshPayloads[DramExtension::getExtension(payload).getBank()]; - DramExtension &extension = DramExtension::getExtension(refreshPayload); - - if (controllerCore.state->rowBufferStates->rowBufferIsOpen( - extension.getBank())) { - pre = true; - ScheduledCommand precharge(Command::Precharge, time, - getExecutionTime(Command::Precharge, refreshPayload), extension); - controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints( - precharge); - controllerCore.state->change(precharge); - controllerCore.controller.send(precharge, refreshPayload); - } - - ScheduledCommand refresh(Command::AutoRefresh, time, - getExecutionTime(Command::AutoRefresh, refreshPayload), extension); - controllerCore.getCommandChecker( - Command::AutoRefresh).delayToSatisfyConstraints(refresh); - controllerCore.state->change(refresh); - extension.incrementRow(); - controllerCore.controller.send(refresh, refreshPayload); - return pre; -} - -void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload &payload, - sc_time time) -{ - sc_time nextRefTiming; - Bank bank = DramExtension::getExtension(payload).getBank(); - bool pendingReq = controllerCore.hasPendingRequests(bank); - bool canPostpone = postponeEnabled && pendingReq - && (postponed[bank] < maxpostpone); - bool canPullIn = pullInEnabled && !pendingReq && (pulledin[bank] < maxpullin); - previousState[bank] = currentState[bank]; - currentState[bank] = nextState[bank]; - bool align = false; - sc_time nrt; - bool pre; - - switch (currentState[bank]) { - case ST_REFRESH: - // Regular Refresh. It's possible to migrate from this to the flexible - // refresh states - assert(pulledin[bank] == 0 && postponed[bank] == 0); - if (canPostpone) { - nextRefTiming = SC_ZERO_TIME; - nextState[bank] = ST_POSTPONE; - } else if (canPullIn) { - pre = doRefresh(payload, time); - nrt = tRFCx; - if (pre) - nrt += controllerCore.config.memSpec->tRP; - nextRefTiming = nrt; - nextState[bank] = ST_PULLIN; - } else { - doRefresh(payload, time); - nextRefTiming = tREFIx; - nextState[bank] = ST_REFRESH; - } - break; - case ST_PULLIN: - // Pull-in a refresh. Try to pull-in refreshes as long it is possible. - if (canPullIn) { - pulledin[bank]++; - pre = doRefresh(payload, time); - nrt = tRFCx; - if (pre) - nrt += controllerCore.config.memSpec->tRP; - nextRefTiming = nrt; - nextState[bank] = ST_PULLIN; - } else { - nextRefTiming = SC_ZERO_TIME; - nextState[bank] = ST_ALIGN; - } - break; - case ST_SKIP: - // Skip the pulled-in refreshes. - if (pulledin[bank] == 0) { - nextRefTiming = SC_ZERO_TIME; - nextState[bank] = ST_REFRESH; - } else { - pulledin[bank]--; - nextRefTiming = tREFIx; - nextState[bank] = ST_SKIP; - } - break; - case ST_POSTPONE: - // Postpone Refresh. Delaying refreshes as long as there are pending - // requests and credits to postpone. Should be followed by a burst - // refresh. - postponed[bank]++; - if ((postponed[bank] > maxpostpone) || (!pendingReq - && !controllerCore.config.ControllerCoreRefForceMaxPostponeBurst)) { - // Burst triggered by inactivity or max postpone value reached. - nextRefTiming = SC_ZERO_TIME; - nextState[bank] = ST_BURST; - } else { - nextRefTiming = tREFIx; - nextState[bank] = ST_POSTPONE; - } - break; - - case ST_BURST: - // Burst postponed refreshes. - pre = doRefresh(payload, time); - postponed[bank]--; - if (postponed[bank] == 0) { - // All refreshes issued, next state will align to tREFIx - nextRefTiming = SC_ZERO_TIME; - nextState[bank] = ST_ALIGN; - } else { - nrt = tRFCx; - if (pre) - nrt += controllerCore.config.memSpec->tRP; - nextRefTiming = nrt; - nextState[bank] = ST_BURST; - } - break; - case ST_ALIGN: - // Align Refresh. Adjusting the timing so the next REF timing will be - // a in a time multiple of tREFIx - nextRefTiming = tREFIx; - align = true; - if (previousState[bank] == ST_PULLIN) { - nextState[bank] = ST_SKIP; - } else { - nextState[bank] = ST_REFRESH; - } - break; - default: - SC_REPORT_FATAL(this->name(), "Invalid state in bw flex. ref. FSM."); - break; - } - planNextRefresh(bank, nextRefTiming, align); -} - -void RefreshManagerBankwise::planNextRefresh(Bank bank, sc_time nextRefTiming, - bool align) -{ - if (align) { - nextPlannedRefreshs[bank] = trunc(nextPlannedRefreshs[bank].to_double() / - tREFIx.to_double()) * tREFIx; - } - nextPlannedRefreshs[bank] += nextRefTiming; - controllerCore.controller.send(REFTrigger, nextPlannedRefreshs[bank], - refreshPayloads[bank]); -} - -void RefreshManagerBankwise::reInitialize(Bank bank, sc_time time) -{ - nextPlannedRefreshs[bank] = clkAlign(time, Alignment::DOWN); - planNextRefresh(bank, tREFIx, true); -} - -bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload &payload, - sc_time time) -{ - return nextPlannedRefreshs[DramExtension::getExtension(payload).getBank()] > - time; -} - -void RefreshManagerBankwise::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); -} - diff --git a/DRAMSys/library/src/controller/core/scheduling/ScheduledCommand.cpp b/DRAMSys/library/src/controller/core/scheduling/ScheduledCommand.cpp deleted file mode 100644 index 4207b9ff..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/ScheduledCommand.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - */ - -#include "ScheduledCommand.h" -#include "../timingCalculations.h" -#include "../../../common/utils.h" -#include "../configuration/Configuration.h" - -bool ScheduledCommand::isNoCommand() const -{ - return (command == Command::NOP && start == SC_ZERO_TIME - && executionTime == SC_ZERO_TIME && end == SC_ZERO_TIME); -} - -bool ScheduledCommand::isValidCommand() const -{ - return !isNoCommand(); -} - -const sc_time ScheduledCommand::getStart() const -{ - return start; -} - -void ScheduledCommand::setStart(sc_time newStart) -{ - start = newStart; - end = newStart + executionTime; -} - -void ScheduledCommand::delayStart(sc_time delay) -{ - setStart(start + delay); -} - -// Delays the command so that its start is at least value(constraint) from timepoint previous apart. -// If passed a constraint of 0ns, method will make sure that command starts no earlier than at timepoint previous -void ScheduledCommand::establishMinDistanceFromStart(sc_time previous, - sc_time constraint) -{ - delayStart(getDelayToMeetConstraint(previous, start, constraint)); -} - -sc_time ScheduledCommand::getEnd() const -{ - return end; -} - -Command ScheduledCommand::getCommand() const -{ - return command; -} - -sc_time ScheduledCommand::getExecutionTime() const -{ - return executionTime; -} - -Bank ScheduledCommand::getBank() const -{ - return extension.getBank(); -} - -BankGroup ScheduledCommand::getBankGroup() const -{ - return extension.getBankGroup(); -} - -Row ScheduledCommand::getRow() const -{ - return extension.getRow(); -} - -unsigned int ScheduledCommand::getBurstLength() const -{ - return extension.getBurstlength(); -} - -bool ScheduledCommand::operator ==(const ScheduledCommand &b) const -{ - return b.command == command && b.start == start - && b.executionTime == executionTime && b.end == end; -} - -bool ScheduledCommand::commandIsIn(const std::vector &commandSet) const -{ - return isIn(command, commandSet); -} - -TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const -{ - //only read and write commands have an assoicated time on the data strobe - sc_assert(getCommand() == Command::Read || getCommand() == Command::ReadA - || getCommand() == Command::Write - || getCommand() == Command::WriteA); - - MemSpec *timings = Configuration::getInstance().memSpec; - - if (getCommand() == Command::Read || getCommand() == Command::ReadA) { - return TimeInterval(getStart() + timings->tRL, - getStart() + timings->tRL + getReadAccessTime()); - } else { - return TimeInterval(getStart() + timings->tWL - timings->clk / 2, - getStart() + timings->tWL + getWriteAccessTime() - timings->clk / 2); - } -} diff --git a/DRAMSys/library/src/controller/core/scheduling/ScheduledCommand.h b/DRAMSys/library/src/controller/core/scheduling/ScheduledCommand.h deleted file mode 100644 index bc4721b7..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/ScheduledCommand.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef SCHEDULEDCOMMAND_H -#define SCHEDULEDCOMMAND_H - -#include -#include -#include "../../Command.h" -#include "../../../common/dramExtensions.h" -#include "../../../common/utils.h" - -class ScheduledCommand -{ -public: - - ScheduledCommand(Command command, sc_time start, sc_time executionTime, - const DramExtension &extension) : - command(command), start(start), executionTime(executionTime), - end(start + executionTime), - extension(extension) - { - } - - ScheduledCommand(Command command, sc_time start, sc_time executionTime, - const tlm::tlm_generic_payload &payload) : - ScheduledCommand(command, start, executionTime, - DramExtension::getExtension(payload)) - { - } - - ScheduledCommand() : - command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), - end(SC_ZERO_TIME), extension() - { - } - - bool isNoCommand() const; - bool isValidCommand() const; - - const sc_time getStart() const; - void setStart(sc_time newStart); - void delayStart(sc_time delay); - void establishMinDistanceFromStart(sc_time previous, sc_time constraint); - - sc_time getEnd() const; - Command getCommand() const; - sc_time getExecutionTime() const; - - Bank getBank() const; - BankGroup getBankGroup() const; - Row getRow() const; - - unsigned int getBurstLength() const; - bool operator ==(const ScheduledCommand &b) const; - bool commandIsIn(const std::vector &commandSet) const; - - TimeInterval getIntervalOnDataStrobe() const; - -private: - Command command; - sc_time start; - sc_time executionTime; - sc_time end; - DramExtension extension; -}; - -#endif // SCHEDULEDCOMMAND_H - diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/ActBChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/ActBChecker.cpp deleted file mode 100644 index 16557602..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/ActBChecker.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Éder F. Zulian - */ - -#include -#include -#include -#include "ActBChecker.h" -#include "../../timingCalculations.h" -#include "../../../../common/DebugManager.h" -#include "../../../Command.h" -#include "../../../../common/utils.h" - -using namespace std; - -void ActBChecker::delayToSatisfyConstraints(ScheduledCommand &cmd) const -{ - sc_assert(cmd.getCommand() == Command::ActB); - ScheduledCommand lcb = state.getLastScheduledCommand(cmd.getBank()); - if (lcb.isValidCommand()) { - if (lcb.getCommand() == Command::PreB) { - cmd.establishMinDistanceFromStart(lcb.getStart(), - Configuration::getInstance().getTrpb()); - } else if (lcb.getCommand() == Command::Precharge - || lcb.getCommand() == Command::PrechargeAll) { - cmd.establishMinDistanceFromStart(lcb.getStart(), config.memSpec->tRP); - } else if (lcb.getCommand() == Command::ReadA) { - cmd.establishMinDistanceFromStart(lcb.getStart(), - config.memSpec->tRTP + config.memSpec->tRP); - } else if (lcb.getCommand() == Command::WriteA) { - cmd.establishMinDistanceFromStart(lcb.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR + - config.memSpec->tRP); - } else if (lcb.getCommand() == Command::AutoRefresh) { - auto m = Configuration::getInstance().getRefMode(); - if (m == 4) - cmd.establishMinDistanceFromStart(lcb.getStart(), config.memSpec->tRFC4); - else if (m == 2) - cmd.establishMinDistanceFromStart(lcb.getStart(), config.memSpec->tRFC2); - else - cmd.establishMinDistanceFromStart(lcb.getStart(), config.memSpec->tRFC); - } else if (lcb.getCommand() == Command::PDNPX - || lcb.getCommand() == Command::PDNAX) { - cmd.establishMinDistanceFromStart(lcb.getStart(), config.memSpec->tXP); - } else if (lcb.getCommand() == Command::SREFX) { - cmd.establishMinDistanceFromStart(lcb.getStart(), config.memSpec->tXSR); - } else { - reportFatal("ActB Checker", - "ActB can not follow " + commandToString(lcb.getCommand())); - } - } - ScheduledCommand lc; - if ((lc = state.getLastCommand(Command::PrechargeAll)).isValidCommand()) { - cmd.establishMinDistanceFromStart(lc.getStart(), config.memSpec->tRP); - } - delay_to_satisfy_activateToActivate_sameBank(cmd); - while (!(state.bus.isFree(cmd.getStart()) - && satsfies_activateToActivate_differentBank(cmd) - && satisfies_nActivateWindow(cmd))) { - cmd.delayStart(config.memSpec->clk); - } -} - -void ActBChecker::delay_to_satisfy_activateToActivate_sameBank( - ScheduledCommand &cmd) const -{ - ScheduledCommand lastActOnBank = state.getLastCommand(Command::Activate, - cmd.getBank()); - if (lastActOnBank.isValidCommand()) { - cmd.establishMinDistanceFromStart(lastActOnBank.getStart(), config.memSpec->tRC); - } - ScheduledCommand lastActBOnBank = state.getLastCommand(Command::ActB, - cmd.getBank()); - if (lastActBOnBank.isValidCommand()) { - cmd.establishMinDistanceFromStart(lastActBOnBank.getStart(), - Configuration::getInstance().getTrcb()); - } -} - -bool ActBChecker::satsfies_activateToActivate_differentBank( - ScheduledCommand &cmd) const -{ - for (auto act : state.lastActivatesB) { - sc_time t = act.first, tRRD = (cmd.getBankGroup() == act.second.getBankGroup() ? - Configuration::getInstance().getTrrdb_L() : - Configuration::getInstance().getTrrdb_S()); - if ((t < cmd.getStart() && cmd.getStart() - t < tRRD) || (cmd.getStart() <= t - && t - cmd.getStart() < tRRD)) { - return false; - } - } - for (auto act : state.lastActivates) { - sc_time t = act.first, tRRD = (cmd.getBankGroup() == act.second.getBankGroup() ? - config.memSpec->tRRD_L : config.memSpec->tRRD_S); - if ((t < cmd.getStart() && cmd.getStart() - t < tRRD) || (cmd.getStart() <= t - && t - cmd.getStart() < tRRD)) { - return false; - } - } - return true; -} - -bool ActBChecker::satisfies_nActivateWindow(ScheduledCommand &cmd) const -{ - if (state.lastActivatesB.size() >= config.memSpec->nActivate) { - maplastActivates = state.lastActivatesB; - lastActivates.emplace(cmd.getStart(), cmd); - auto upper = lastActivates.begin(); - advance(upper, config.memSpec->nActivate); - auto lower = lastActivates.begin(); - while (upper != lastActivates.end()) { - if (upper->first - lower->first < Configuration::getInstance().getTfawb()) { - return false; - } - ++upper; - ++lower; - } - } - return true; -} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/ActBChecker.h b/DRAMSys/library/src/controller/core/scheduling/checker/ActBChecker.h deleted file mode 100644 index f1a04859..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/ActBChecker.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Éder F. Zulian - */ - -#ifndef ACTBCHECKER_H -#define ACTBCHECKER_H - -#include -#include "ICommandChecker.h" -#include "../../configuration/Configuration.h" -#include "../../../ControllerState.h" - -class ActBChecker : public ICommandChecker -{ -public: - ActBChecker(const Configuration &config, - ControllerState &state) : config(config), state(state) {} - virtual ~ActBChecker() {} - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; -private: - const Configuration &config; - ControllerState &state; - void delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand &command) - const; - bool satsfies_activateToActivate_differentBank(ScheduledCommand &command) const; - bool satisfies_nActivateWindow(ScheduledCommand &command) const; -}; - -#endif // ACTBCHECKER_H diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/ActivateChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/ActivateChecker.cpp deleted file mode 100644 index f2bb8033..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/ActivateChecker.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#include -#include -#include -#include "ActivateChecker.h" -#include "../../timingCalculations.h" -#include "../../../../common/DebugManager.h" -#include "../../../Command.h" -#include "../../../../common/utils.h" - -using namespace std; - -void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand &command) const -{ - sc_assert(command.getCommand() == Command::Activate); - - ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand( - command.getBank()); - if (lastCommandOnBank.isValidCommand()) { - if (lastCommandOnBank.getCommand() == Command::PreB - || lastCommandOnBank.getCommand() == Command::Precharge - || lastCommandOnBank.getCommand() == Command::PrechargeAll) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tRP); - } else if (lastCommandOnBank.getCommand() == Command::ReadA) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tRTP + config.memSpec->tRP); - } else if (lastCommandOnBank.getCommand() == Command::WriteA) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR + - config.memSpec->tRP); - } else if (lastCommandOnBank.getCommand() == Command::AutoRefresh) { - auto m = Configuration::getInstance().getRefMode(); - if (m == 4) - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tRFC4); - else if (m == 2) - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tRFC2); - else - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tRFC); - } else if (lastCommandOnBank.getCommand() == Command::PDNPX - || lastCommandOnBank.getCommand() == Command::PDNAX) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tXP); - } else if (lastCommandOnBank.getCommand() == Command::SREFX) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tXSR); - } else - reportFatal("Activate Checker", - "Activate can not follow " + commandToString(lastCommandOnBank.getCommand())); - } - - delay_to_satisfy_activateToActivate_sameBank(command); - - while (!(state.bus.isFree(command.getStart()) - && satsfies_activateToActivate_differentBank(command) - && satisfies_nActivateWindow(command))) { - command.delayStart(config.memSpec->clk); - } - -} - -void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank( - ScheduledCommand &command) const -{ - ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, - command.getBank()); - if (lastActivateOnBank.isValidCommand()) { - command.establishMinDistanceFromStart(lastActivateOnBank.getStart(), - config.memSpec->tRC); - } - - ScheduledCommand lastActBOnBank = state.getLastCommand(Command::ActB, - command.getBank()); - if (lastActBOnBank.isValidCommand()) { - command.establishMinDistanceFromStart(lastActivateOnBank.getStart(), - config.memSpec->tRC); - } -} - -bool ActivateChecker::satsfies_activateToActivate_differentBank( - ScheduledCommand &command) const -{ - for (auto act : state.lastActivates) { - sc_time time = act.first; - sc_time tRRD = (command.getBankGroup() == act.second.getBankGroup()) ? - config.memSpec->tRRD_L : config.memSpec->tRRD_S; - - if ((time < command.getStart() && command.getStart() - time < tRRD) - || (command.getStart() <= time && time - command.getStart() < tRRD)) - return false; - } - return true; -} - -bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand &command) const -{ - /* - * there may be activates scheduled in the future, so emplace - * command in a copied set (not necessarily the last in time), - * and check if the n-act constraint holds for the whole set. - */ - if (state.lastActivates.size() >= config.memSpec->nActivate) { - map lastActivates = state.lastActivates; - lastActivates.emplace(command.getStart(), command); - auto upper = lastActivates.begin(); - advance(upper, config.memSpec->nActivate); - auto lower = lastActivates.begin(); - - while (upper != lastActivates.end()) { - if (upper->first - lower->first < config.memSpec->tNAW) - return false; - ++upper; - ++lower; - } - } - - return true; -} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/ActivateChecker.h b/DRAMSys/library/src/controller/core/scheduling/checker/ActivateChecker.h deleted file mode 100644 index 1312505d..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/ActivateChecker.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef ACTIVATECHECKER_H -#define ACTIVATECHECKER_H - -#include -#include "ICommandChecker.h" -#include "../../configuration/Configuration.h" -#include "../../../ControllerState.h" - -class ActivateChecker: public ICommandChecker -{ -public: - ActivateChecker(const Configuration &config, - ControllerState &state) : config(config), state(state) {} - virtual ~ActivateChecker() {} - - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; -private: - const Configuration &config; - ControllerState &state;//TODO make const - - void delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand &command) - const; - bool satsfies_activateToActivate_differentBank(ScheduledCommand &command) const; - bool satisfies_nActivateWindow(ScheduledCommand &command) const; -}; - -#endif // ACTIVATECHECKER_H diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PowerDownChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/PowerDownChecker.cpp deleted file mode 100644 index 723c74ec..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PowerDownChecker.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Felipe S. Prado - */ - -#include "PowerDownChecker.h" -#include "../../timingCalculations.h" - -sc_time PowerDownChecker::getTimeConstraintToEnterPowerDown(Command lastCmd, - Command pdnCmd) const -{ - sc_assert(pdnCmd == Command::SREF || pdnCmd == Command::PDNA - || pdnCmd == Command::PDNP); - - sc_time constraint; - - if (lastCmd == Command::Read || lastCmd == Command::ReadA) { - constraint = config.memSpec->tRL + getReadAccessTime() + config.memSpec->clk; - } else if (lastCmd == Command::Write) { - constraint = config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR; - } else if (lastCmd == Command::WriteA) { - constraint = config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR + - config.memSpec->clk; - } else if (lastCmd == Command::AutoRefresh) { - auto m = Configuration::getInstance().getRefMode(); - if (m == 4) - constraint = config.memSpec->tRFC4; - else if (m == 2) - constraint = config.memSpec->tRFC2; - else - constraint = config.memSpec->tRFC; - } else if (lastCmd == Command::PDNPX || lastCmd == Command::PDNAX) { - constraint = config.memSpec->tXP; - } else if (lastCmd == Command::SREFX) { - constraint = config.memSpec->tXSR; - } else if (lastCmd == Command::Precharge || lastCmd == Command::PrechargeAll) { - constraint = config.memSpec->tRP; - } else { - reportFatal("Powerdown checker", - commandToString(pdnCmd) + " can not follow " + commandToString(lastCmd)); - } - - return constraint; -} - -void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand &command) -const -{ - sc_assert(command.commandIsIn({Command::PDNA, Command::PDNP, Command::SREF, Command::PDNAX, Command::PDNPX, Command::SREFX})); - - // Power Down commmand (one of the listed above) - Command pdnCmd = command.getCommand(); - Bank bank = command.getBank(); - - sc_time timeConstraint; - - if (pdnCmd == Command::PDNA || pdnCmd == Command::PDNP - || pdnCmd == Command::SREF) { - // Entering in one of the Power Down modes: - // PDNA - Active Power Down - // PDNP - Precharge Power Down - // SREF - Self Refresh - - // Get the last scheduled command - ScheduledCommand lastSchedCmd; - if(Configuration::getInstance().BankwiseLogic) - { - lastSchedCmd = state.getLastScheduledCommand(bank); - } - else - { - lastSchedCmd = state.getLastScheduledCommand(); - } - - if (lastSchedCmd.isValidCommand()) { - // Get the start time for the last scheduled command - sc_time lastSchedCmdStart = lastSchedCmd.getStart(); - // Get the last command - Command lastCmd = lastSchedCmd.getCommand(); - - timeConstraint = getTimeConstraintToEnterPowerDown(lastCmd, pdnCmd); - - command.establishMinDistanceFromStart(lastSchedCmdStart, timeConstraint); - } - - } else if (pdnCmd == Command::PDNAX) { - // Leaving Active Power Down - timeConstraint = config.memSpec->tCKE; - command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNA, - bank).getStart(), timeConstraint); - } else if (pdnCmd == Command::PDNPX) { - // Leaving Precharge Power Down - timeConstraint = config.memSpec->tCKE; - command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNP, - bank).getStart(), timeConstraint); - } else if (pdnCmd == Command::SREFX) { - // Leaving Self Refresh - timeConstraint = config.memSpec->tCKESR; - command.establishMinDistanceFromStart(state.getLastCommand(Command::SREF, - bank).getStart(), timeConstraint); - } - - state.bus.moveCommandToNextFreeSlot(command); -} - diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PreBChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/PreBChecker.cpp deleted file mode 100644 index 44e23882..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PreBChecker.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Éder F. Zulian - */ - -#include "PreBChecker.h" -#include "../../timingCalculations.h" -void PreBChecker::delayToSatisfyConstraints(ScheduledCommand &cmd) const -{ - sc_assert(cmd.getCommand() == Command::PreB); - ScheduledCommand lastCmd = state.getLastScheduledCommand(cmd.getBank()); - if (lastCmd.isValidCommand()) { - if (lastCmd.getCommand() == Command::PreB) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), - Configuration::getInstance().getTrpb()); - } else if (lastCmd.getCommand() == Command::Precharge) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), config.memSpec->tRP); - } else if (lastCmd.getCommand() == Command::PrechargeAll) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), config.memSpec->tRP); - } else if (lastCmd.getCommand() == Command::ActB) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), - config.memSpec->tRCD); // XXX: trcd is less than the NEW! trasb! ok! - } else if (lastCmd.getCommand() == Command::Activate) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), config.memSpec->tRCD); - } else if (lastCmd.getCommand() == Command::Read) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), config.memSpec->tRTP); - } else if (lastCmd.getCommand() == Command::Write) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR); - } else if (lastCmd.getCommand() == Command::PDNAX) { - cmd.establishMinDistanceFromStart(lastCmd.getStart(), config.memSpec->tXP); - } else { - reportFatal("PreB Checker", - "PreB can not follow " + commandToString(lastCmd.getCommand())); - } - } - ScheduledCommand lc; - if ((lc = state.getLastCommand(Command::PrechargeAll)).isValidCommand()) { - cmd.establishMinDistanceFromStart(lc.getStart(), config.memSpec->tRP); - } - if ((lc = state.getLastCommand(Command::Activate, - cmd.getBank())).isValidCommand()) { - cmd.establishMinDistanceFromStart(lc.getStart(), config.memSpec->tRAS); - } - if ((lc = state.getLastCommand(Command::ActB, - cmd.getBank())).isValidCommand()) { - cmd.establishMinDistanceFromStart(lc.getStart(), - Configuration::getInstance().getTrasb()); - } - state.bus.moveCommandToNextFreeSlot(cmd); -} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PreBChecker.h b/DRAMSys/library/src/controller/core/scheduling/checker/PreBChecker.h deleted file mode 100644 index 980901a3..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PreBChecker.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Éder F. Zulian - */ - -#ifndef PREBCHECKER_H -#define PREBCHECKER_H - -#include "ICommandChecker.h" -#include "../../configuration/Configuration.h" -#include "../../../ControllerState.h" - -class PreBChecker: public ICommandChecker -{ -public: - PreBChecker(const Configuration &config, - ControllerState &state): config(config), state(state) {} - virtual ~PreBChecker() {} - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; -private: - const Configuration &config; - ControllerState &state; -}; - -#endif // PREBCHECKER_H diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeAllChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeAllChecker.cpp deleted file mode 100644 index f6ee06d9..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeAllChecker.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Felipe S. Prado - */ - -#include "PrechargeAllChecker.h" -#include "../../timingCalculations.h" - - -void PrechargeAllChecker::delayToSatisfyConstraints(ScheduledCommand &command) -const -{ - sc_assert(command.getCommand() == Command::PrechargeAll); - - // Consider all banks for the constraints, since precharge all command is supposed to happen at the same time on all banks - for (unsigned int bank = 0; bank < config.memSpec->NumberOfBanks; ++bank) { - ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank)); - if (lastCommand.isValidCommand()) { - if (lastCommand.getCommand() == Command::Precharge - || lastCommand.getCommand() == Command::PreB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRP); - } else if (lastCommand.getCommand() == Command::Activate - || lastCommand.getCommand() == Command::ActB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRCD); - } else if (lastCommand.getCommand() == Command::Read) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRTP); - } else if (lastCommand.getCommand() == Command::ReadA) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRTP + config.memSpec->tRP); - } else if (lastCommand.getCommand() == Command::Write) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR); - } else if (lastCommand.getCommand() == Command::WriteA) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR + - config.memSpec->tRP); - } else if (lastCommand.getCommand() == Command::AutoRefresh) { - auto m = Configuration::getInstance().getRefMode(); - if (m == 4) - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRFC4); - else if (m == 2) - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRFC2); - else - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRFC); - } else if (lastCommand.getCommand() == Command::PDNAX - || lastCommand.getCommand() == Command::PDNPX) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tXP); - } else if (lastCommand.getCommand() == Command::SREFX) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tXSR); - } else - reportFatal("Precharge All Checker", - "Precharge All can not follow " + commandToString(lastCommand.getCommand())); - } - } - - ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, - command.getBank()); - if (lastActivate.isValidCommand()) { - command.establishMinDistanceFromStart(lastActivate.getStart(), - config.memSpec->tRAS); - } - - state.bus.moveCommandToNextFreeSlot(command); -} - diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeChecker.cpp deleted file mode 100644 index 75a8ebdc..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/PrechargeChecker.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#include "PrechargeChecker.h" -#include "../../timingCalculations.h" - - -void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand &command) -const -{ - //return; - sc_assert(command.getCommand() == Command::Precharge); - - ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank()); - - if (lastCommand.isValidCommand()) { - // the first two cases happen when a resfresh interrups the command sequence of a transaction - // (e.g. commands to process transaction are PRE-ACT-RD and refresh happens after the PRE or after the ACT) - if (lastCommand.getCommand() == Command::Precharge - || lastCommand.getCommand() == Command::PreB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRP); - } else if (lastCommand.getCommand() == Command::Activate - || lastCommand.getCommand() == Command::ActB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRCD); - } - - else if (lastCommand.getCommand() == Command::Read) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRTP); - } else if (lastCommand.getCommand() == Command::Write) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR); - - } else if (lastCommand.getCommand() == Command::PDNAX) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tXP); - } else - reportFatal("Precharge Checker", - "Precharge can not follow " + commandToString(lastCommand.getCommand())); - } - - ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, - command.getBank()); - if (lastActivate.isValidCommand()) { - command.establishMinDistanceFromStart(lastActivate.getStart(), - config.memSpec->tRAS); - } - - state.bus.moveCommandToNextFreeSlot(command); -} - diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/ReadChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/ReadChecker.cpp deleted file mode 100644 index 06a121a6..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/ReadChecker.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#include "ReadChecker.h" -#include "../../timingCalculations.h" -#include "../../../../common/utils.h" -#include "WriteChecker.h" - -using namespace std; - -void ReadChecker::delayToSatisfyConstraints(ScheduledCommand &command) const -{ - sc_assert(command.getCommand() == Command::Read - || command.getCommand() == Command::ReadA); - delayToSatisfyDLL(command); - ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank()); - - if (lastCommand.isValidCommand()) { - if (lastCommand.getCommand() == Command::Activate - || lastCommand.getCommand() == Command::ActB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRCD); - } else if (lastCommand.getCommand() == Command::Read) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - ReadChecker::readToRead(lastCommand, command)); - } else if (lastCommand.getCommand() == Command::Write) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - ReadChecker::writeToRead(lastCommand, command)); - } else if (lastCommand.getCommand() == Command::PDNPX - || lastCommand.getCommand() == Command::PDNAX) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tXP); - } else - reportFatal("Read Checker", - "Read can not follow " + commandToString(lastCommand.getCommand())); - } - - while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command)) { - command.delayStart(config.memSpec->clk); - } -} - -bool ReadChecker::collidesOnDataStrobe(ScheduledCommand &read) const -{ - for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) { - if (collidesWithStrobeCommand(read, strobeCommand)) - return true; - } - - return false; -} - -bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand &read, - ScheduledCommand &strobeCommand) const -{ - if (strobeCommand.getCommand() == Command::Read - || strobeCommand.getCommand() == Command::ReadA) { - return getDistance(read.getStart(), - strobeCommand.getStart()) < ReadChecker::readToRead(strobeCommand, read); - } else if (strobeCommand.getCommand() == Command::Write - || strobeCommand.getCommand() == Command::WriteA) { - if (strobeCommand.getStart() >= read.getStart()) - return getDistance(read.getStart(), - strobeCommand.getStart()) < WriteChecker::readToWrite(read, strobeCommand); - else - return getDistance(strobeCommand.getStart(), - read.getStart()) < ReadChecker::writeToRead(strobeCommand, read); - } else { - reportFatal("Read Checker", - "Invalid strobeCommand in data strobe commands " + commandToString( - strobeCommand.getCommand())); - return true; - } -} - -void ReadChecker::delayToSatisfyDLL(ScheduledCommand &read) const -{ - ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, - read.getBank()); - if (lastSREFX.isValidCommand()) - read.establishMinDistanceFromStart(lastSREFX.getStart(), - config.memSpec->tXSRDLL); -} - -sc_time ReadChecker::readToRead(ScheduledCommand &firstRead, - ScheduledCommand &secondRead) -{ - sc_assert(firstRead.getCommand() == Command::Read - || firstRead.getCommand() == Command::ReadA); - sc_assert(secondRead.getCommand() == Command::Read - || secondRead.getCommand() == Command::ReadA); - - MemSpec *config = Configuration::getInstance().memSpec; - sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ? - config->tCCD_L : config->tCCD_S; - return max(tCCD, getReadAccessTime()); -} - -sc_time ReadChecker::writeToRead(ScheduledCommand &write, - ScheduledCommand &read) -{ - sc_assert(read.getCommand() == Command::Read - || read.getCommand() == Command::ReadA); - sc_assert(write.getCommand() == Command::Write - || write.getCommand() == Command::WriteA); - - MemSpec *config = Configuration::getInstance().memSpec; - sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config->tWTR_L : - config->tWTR_S; - return config->tWL + getWriteAccessTime() + tWTR; -} - diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/ReadChecker.h b/DRAMSys/library/src/controller/core/scheduling/checker/ReadChecker.h deleted file mode 100644 index d9c9cce8..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/ReadChecker.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#ifndef READCHECKER_H -#define READCHECKER_H - -#include "ICommandChecker.h" -#include "../../configuration/Configuration.h" -#include "../../../ControllerState.h" - -class ReadChecker: public ICommandChecker -{ -public: - ReadChecker(Configuration &config, ControllerState &state) : config(config), - state(state) {} - virtual ~ReadChecker() {} - - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const - override; - - static sc_time readToRead(ScheduledCommand &firstRead, - ScheduledCommand &secondRead); - static sc_time writeToRead(ScheduledCommand &write, ScheduledCommand &read); - -private: - const Configuration &config; - ControllerState &state; - - void delayToSatisfyDLL(ScheduledCommand &read) const; - bool collidesOnDataStrobe(ScheduledCommand &read) const; - bool collidesWithStrobeCommand(ScheduledCommand &read, - ScheduledCommand &strobeCommand) const; -}; - -#endif // READCHECKER_H - diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/RefreshChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/RefreshChecker.cpp deleted file mode 100644 index eea8f763..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/RefreshChecker.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - * Felipe S. Prado - */ - -#include "RefreshChecker.h" -#include "../../timingCalculations.h" - -void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand &command) const -{ - sc_assert(command.getCommand() == Command::AutoRefresh); - - if (config.BankwiseLogic) { - ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand( - command.getBank()); - - if (lastCommandOnBank.isValidCommand()) { - if (lastCommandOnBank.getCommand() == Command::Precharge - || lastCommandOnBank.getCommand() == Command::PrechargeAll) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tRP); - } else if (lastCommandOnBank.getCommand() == Command::ReadA) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tRTP + config.memSpec->tRP); - } else if (lastCommandOnBank.getCommand() == Command::WriteA) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR + - config.memSpec->tRP); - } else if (lastCommandOnBank.getCommand() == Command::PDNPX - || lastCommandOnBank.getCommand() == Command::PDNAX) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tXP); - } else if (lastCommandOnBank.getCommand() == Command::SREFX) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec->tXSR); - } else if (lastCommandOnBank.getCommand() == Command::AutoRefresh) { - } else - reportFatal("Refresh Checker", - "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand())); - } - } else { - for (unsigned int bank = 0; bank < config.memSpec->NumberOfBanks; ++bank) { - ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank)); - if (lastCommand.isValidCommand()) { - if (lastCommand.getCommand() == Command::Precharge - || lastCommand.getCommand() == Command::PrechargeAll - || lastCommand.getCommand() == Command::PreB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRP); - } else if (lastCommand.getCommand() == Command::Activate - || lastCommand.getCommand() == Command::ActB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRCD); - } else if (lastCommand.getCommand() == Command::ReadA) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRTP + config.memSpec->tRP); - } else if (lastCommand.getCommand() == Command::WriteA) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR + - config.memSpec->tRP); - } else if (lastCommand.getCommand() == Command::PDNAX - || lastCommand.getCommand() == Command::PDNPX) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tXP); - } else if (lastCommand.getCommand() == Command::SREFX) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tXSR); - } else if (lastCommand.getCommand() == Command::AutoRefresh) { - } else - reportFatal("Refresh Checker", - "Refresh can not follow " + commandToString(lastCommand.getCommand())); - } - } - } - - state.bus.moveCommandToNextFreeSlot(command); - - -} - - diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/WriteChecker.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/WriteChecker.cpp deleted file mode 100644 index 38eafdaa..00000000 --- a/DRAMSys/library/src/controller/core/scheduling/checker/WriteChecker.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#include "WriteChecker.h" -#include "../../timingCalculations.h" -#include "../../../../common/utils.h" -#include "ReadChecker.h" - -using namespace std; - -void WriteChecker::delayToSatisfyConstraints(ScheduledCommand &command) const -{ - sc_assert(command.getCommand() == Command::Write - || command.getCommand() == Command::WriteA); - - ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank()); - - if (lastCommand.isValidCommand()) { - if (lastCommand.getCommand() == Command::Activate - || lastCommand.getCommand() == Command::ActB) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tRCD); - } else if (lastCommand.getCommand() == Command::Read) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - WriteChecker::readToWrite(lastCommand, command)); - } else if (lastCommand.getCommand() == Command::Write) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - WriteChecker::writeToWrite(lastCommand, command)); - } else if (lastCommand.getCommand() == Command::PDNPX - || lastCommand.getCommand() == Command::PDNAX) { - command.establishMinDistanceFromStart(lastCommand.getStart(), - config.memSpec->tXP); - } else - reportFatal("Write Checker", - "Write can not follow " + commandToString(lastCommand.getCommand())); - } - - while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command)) { - command.delayStart(config.memSpec->clk); - } -} - -bool WriteChecker::collidesOnDataStrobe(ScheduledCommand &write) const -{ - for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) { - if (collidesWithStrobeCommand(write, strobeCommand)) - return true; - } - - return false; -} - -bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand &write, - ScheduledCommand &strobeCommand) const -{ - if (strobeCommand.getCommand() == Command::Write - || strobeCommand.getCommand() == Command::WriteA) { - return getDistance(write.getStart(), - strobeCommand.getStart()) < WriteChecker::writeToWrite(strobeCommand, write); - } else if (strobeCommand.getCommand() == Command::Read - || strobeCommand.getCommand() == Command::ReadA) { - if (strobeCommand.getStart() >= write.getStart()) - return getDistance(write.getStart(), - strobeCommand.getStart()) < ReadChecker::writeToRead(write, strobeCommand); - else - return getDistance(strobeCommand.getStart(), - write.getStart()) < WriteChecker::readToWrite(strobeCommand, write); - } else { - reportFatal("Write Checker", - "Invalid strobeCommand in data strobe commands " + commandToString( - strobeCommand.getCommand())); - return true; - } -} - -sc_time WriteChecker::writeToWrite(ScheduledCommand &firstWrite, - ScheduledCommand &secondWrite) -{ - sc_assert(firstWrite.getCommand() == Command::Write - || firstWrite.getCommand() == Command::WriteA); - sc_assert(secondWrite.getCommand() == Command::Write - || secondWrite.getCommand() == Command::WriteA); - - MemSpec *config = Configuration::getInstance().memSpec; - sc_time tCCD = (firstWrite.getBankGroup() == secondWrite.getBankGroup()) ? - config->tCCD_L : config->tCCD_S; - return max(tCCD, getWriteAccessTime()); -} - -sc_time WriteChecker::readToWrite(ScheduledCommand &read __attribute__(( - unused)), ScheduledCommand &write __attribute__((unused))) -{ - sc_assert(read.getCommand() == Command::Read - || read.getCommand() == Command::ReadA); - sc_assert(write.getCommand() == Command::Write - || write.getCommand() == Command::WriteA); - - MemSpec *config = Configuration::getInstance().memSpec; - return config->tRL + getReadAccessTime() - config->tWL + config->clk * 2; -} - diff --git a/DRAMSys/library/src/controller/core/timingCalculations.cpp b/DRAMSys/library/src/controller/core/timingCalculations.cpp deleted file mode 100644 index 077e5d22..00000000 --- a/DRAMSys/library/src/controller/core/timingCalculations.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Matthias Jung - */ - -#include "timingCalculations.h" -#include "configuration/MemSpec.h" -#include "ControllerCore.h" -#include "../../common/DebugManager.h" -#include "configuration/Configuration.h" -#include "../../common/utils.h" - - - -sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, - sc_time constraint) -{ - if (previous + constraint > start) - return previous + constraint - start; - else - return SC_ZERO_TIME; -} - -const sc_time FrequencyToClk(double frequencyMhz) -{ - return sc_time(1 / frequencyMhz, SC_US); -} - -const sc_time clkAlign(sc_time time, Alignment alignment) -{ - sc_time clk = Configuration::getInstance().memSpec->clk; - if (alignment == UP) - return ceil(time / clk) * clk; - else - return floor(time / clk) * clk; -} - -// Returns the execution time for commands that have a fixed execution time -sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload) -{ - MemSpec *config = Configuration::getInstance().memSpec; - - if (command == Command::PreB) { - return Configuration::getInstance().getTrpb(); - } else if (command == Command::Precharge || command == Command::PrechargeAll) { - return config->tRP; - } else if (command == Command::ActB) { - return config->tRCD; - } else if (command == Command::Activate) { - return config->tRCD; - } else if (command == Command::Read) { - return config->tRL + getReadAccessTime(); - } else if (command == Command::ReadA) { - return config->tRTP + config->tRP; - } else if (command == Command::Write) { - return config->tWL + getWriteAccessTime(); - } else if (command == Command::WriteA) { - return config->tWL + getWriteAccessTime() + config->tWR + config->tRP; - } else if (command == Command::PrechargeAll) { - return config->tRP; - } else if (command == Command::AutoRefresh) { - if (Configuration::getInstance().getRefMode() == 4) - return getElementFromMap(config->refreshTimings, - DramExtension::getExtension(payload).getBank()).tRFC4; - else if (Configuration::getInstance().getRefMode() == 2) - return getElementFromMap(config->refreshTimings, - DramExtension::getExtension(payload).getBank()).tRFC2; - else - return getElementFromMap(config->refreshTimings, - DramExtension::getExtension(payload).getBank()).tRFC; - } else if (command == Command::PDNAX || command == Command::PDNPX - || command == Command::SREFX) { - return config->clk; - } else { - SC_REPORT_FATAL("getExecutionTime", - "command not known or command doesn't have a fixed execution time"); - return SC_ZERO_TIME; - } -} - -// Returns the minimum execution time for commands that have a variable execution time -sc_time getMinExecutionTimeForPowerDownCmd(Command command) -{ - MemSpec *config = Configuration::getInstance().memSpec; - if (command == Command::PDNA || command == Command::PDNP) { - return config->tCKE; - } else if (command == Command::SREF) { - return config->tCKESR; - } else { - SC_REPORT_FATAL("getMinimalExecutionTime", - "command is not know or command has a fixed execution time"); - return SC_ZERO_TIME; - } -} - -bool isClkAligned(sc_time time, sc_time clk) -{ - return !((time / clk) - ceil(time / clk)); -} - - -sc_time getReadAccessTime() -{ - Configuration &config = Configuration::getInstance(); - return (config.memSpec->BurstLength / config.memSpec->DataRate) * - config.memSpec->clk; -} - -sc_time getWriteAccessTime() -{ - Configuration &config = Configuration::getInstance(); - - if (config.memSpec->DataRate == 1) { - return config.memSpec->clk * (config.memSpec->BurstLength); - } else { - return config.memSpec->clk * (config.memSpec->BurstLength / - config.memSpec->DataRate); - } -} - - diff --git a/DRAMSys/library/src/controller/powerdown/PowerDownManagerDummy.cpp b/DRAMSys/library/src/controller/powerdown/PowerDownManagerDummy.cpp new file mode 100644 index 00000000..b24db7fb --- /dev/null +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManagerDummy.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "PowerDownManagerDummy.h" + +std::pair PowerDownManagerDummy::getNextCommand() +{ + return std::pair(Command::NOP, nullptr); +} + +sc_time PowerDownManagerDummy::start() +{ + return sc_max_time() - sc_time_stamp(); +} diff --git a/DRAMSys/library/src/controller/powerdown/PowerDownManagerDummy.h b/DRAMSys/library/src/controller/powerdown/PowerDownManagerDummy.h new file mode 100644 index 00000000..8aef3f54 --- /dev/null +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManagerDummy.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef POWERDOWNMANAGERDUMMY_H +#define POWERDOWNMANAGERDUMMY_H + +#include "PowerDownManagerIF.h" + +using namespace tlm; + +class PowerDownManagerDummy final : public PowerDownManagerIF +{ +public: + PowerDownManagerDummy() {} + + virtual void triggerEntry(TriggerSource) override {} + virtual void triggerExit(TriggerSource) override {} + + virtual std::pair getNextCommand() override; + virtual void updateState(Command) override {} + virtual sc_time start() override; +}; + +#endif // POWERDOWNMANAGERDUMMY_H diff --git a/DRAMSys/library/src/controller/scheduler/Fifo.h b/DRAMSys/library/src/controller/powerdown/PowerDownManagerIF.h similarity index 72% rename from DRAMSys/library/src/controller/scheduler/Fifo.h rename to DRAMSys/library/src/controller/powerdown/PowerDownManagerIF.h index 83f14124..d6a12ac4 100644 --- a/DRAMSys/library/src/controller/scheduler/Fifo.h +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManagerIF.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,35 +29,32 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Robert Gernhardt - * Matthias Jung + * Author: Lukas Steiner */ -#ifndef FIFO_H -#define FIFO_H +#ifndef POWERDOWNMANAGERIF_H +#define POWERDOWNMANAGERIF_H -#include -#include #include - -#include "../core/ControllerCore.h" +#include +#include #include "../Command.h" -#include "IScheduler.h" -class Fifo : public IScheduler +using namespace tlm; + +enum class TriggerSource {Controller, RefreshManager}; + +class PowerDownManagerIF { public: - Fifo(ControllerCore &controllerCore) : IScheduler(controllerCore) {} - virtual ~Fifo() {} + virtual ~PowerDownManagerIF() {} - void storeRequest(gp *payload) override; - std::pair - getNextRequest(Bank bank) override; - virtual gp *getPendingRequest(Bank bank) override; + virtual void triggerEntry(TriggerSource) = 0; + virtual void triggerExit(TriggerSource) = 0; -private: - std::map> buffer; + virtual std::pair getNextCommand() = 0; + virtual void updateState(Command) = 0; + virtual sc_time start() = 0; }; -#endif // FIFO_H +#endif // POWERDOWNMANAGERIF_H diff --git a/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.cpp b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.cpp new file mode 100644 index 00000000..cf3cc839 --- /dev/null +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "PowerDownManagerStaggered.h" +#include "../../common/utils.h" + +PowerDownManagerStaggered::PowerDownManagerStaggered(Rank rank, CheckerIF *checker) + : rank(rank), checker(checker) +{ + setUpDummy(powerDownPayload, rank); +} + +void PowerDownManagerStaggered::triggerEntry(TriggerSource source) +{ + if (source == TriggerSource::Controller) + controllerIdle = true; + + // TODO: check if state is always idle here + if (state == PdmState::Idle && controllerIdle) + triggered = true; +} + +void PowerDownManagerStaggered::triggerExit(TriggerSource source) +{ + if (source == TriggerSource::Controller) + { + controllerIdle = false; + enterSelfRefresh = false; + + if (state == PdmState::Idle) + triggered = false; + else + triggered = true; + } + else // if (source == TriggerSource::RefreshManager) + { + if (state == PdmState::Idle && !enterSelfRefresh) + triggered = false; + else if (state == PdmState::PrechargePd && !triggered) + { + triggered = true; + enterSelfRefresh = true; + } + else if (state == PdmState::ActivePd) // TODO: check if normal else is also ok here + triggered = true; + } +} + +std::pair PowerDownManagerStaggered::getNextCommand() +{ + if (sc_time_stamp() == timeToSchedule) + return std::pair(nextCommand, &powerDownPayload); + else + return std::pair(Command::NOP, nullptr); +} + +sc_time PowerDownManagerStaggered::start() +{ + timeToSchedule = sc_max_time(); + sc_time delay = sc_max_time() - sc_time_stamp(); + + if (triggered) + { + if (state == PdmState::Idle) + { + if (enterSelfRefresh) + nextCommand = Command::SREFEN; + else if (activatedBanks == 0) + nextCommand = Command::PDEP; + else + nextCommand = Command::PDEA; + } + else if (state == PdmState::ActivePd) + nextCommand = Command::PDXA; + else if (state == PdmState::PrechargePd) + nextCommand = Command::PDXP; + else if (state == PdmState::SelfRefresh) + nextCommand = Command::SREFEX; + else // if (state == PdmState::Refresh) + nextCommand = Command::REFA; + + delay = checker->delayToSatisfyConstraints(nextCommand, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + } + + return delay; +} + +void PowerDownManagerStaggered::updateState(Command command) +{ + if (command == Command::ACT) + activatedBanks++; + else if (command == Command::PRE) + activatedBanks--; + else if (command == Command::PREA) + activatedBanks = 0; + else if (command == Command::PDEA) + { + state = PdmState::ActivePd; + triggered = false; + } + else if (command == Command::PDEP) + { + state = PdmState::PrechargePd; + triggered = false; + } + else if (command == Command::SREFEN) + { + state = PdmState::SelfRefresh; + triggered = false; + enterSelfRefresh = false; + } + else if (command == Command::PDXA) + { + state = PdmState::Idle; + triggered = false; + } + else if (command == Command::PDXP) + { + state = PdmState::Idle; + if (!enterSelfRefresh) + triggered = false; + } + else if (command == Command::SREFEX) + state = PdmState::Refresh; + else if (command == Command::REFA && state == PdmState::Refresh) + { + state = PdmState::Idle; + triggered = false; + } +} diff --git a/DRAMSys/library/src/controller/scheduler/FifoStrict.h b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.h similarity index 59% rename from DRAMSys/library/src/controller/scheduler/FifoStrict.h rename to DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.h index 5404cb8c..350e38b5 100644 --- a/DRAMSys/library/src/controller/scheduler/FifoStrict.h +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,41 +29,43 @@ * 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 - * Robert Gernhardt - * Matthias Jung - * Éder F. Zulian + * Author: Lukas Steiner */ -#ifndef FIFOSTRICT_H -#define FIFOSTRICT_H +#ifndef POWERDOWNMANAGERSTAGGERED_H +#define POWERDOWNMANAGERSTAGGERED_H -#include -//#include -#include +#include "PowerDownManagerIF.h" +#include "../BankMachine.h" +#include "../checker/CheckerIF.h" -#include "../core/ControllerCore.h" -#include "../Command.h" -#include "IScheduler.h" +using namespace tlm; -class FifoStrict : public IScheduler +class PowerDownManagerStaggered final : public PowerDownManagerIF { public: - IController &controller; - FifoStrict(IController &controller, ControllerCore &controllerCore) - : IScheduler(controllerCore), controller(controller) {} + PowerDownManagerStaggered(Rank, CheckerIF *); - virtual ~FifoStrict() {} + virtual void triggerEntry(TriggerSource) override; + virtual void triggerExit(TriggerSource) override; - void storeRequest(gp *payload) override; - std::pair - getNextRequest(Bank bank) override; - virtual gp *getPendingRequest(Bank bank) override; + virtual std::pair getNextCommand() override; + virtual void updateState(Command) override; + virtual sc_time start() override; private: - std::deque> buffer; + enum class PdmState {Idle, ActivePd, PrechargePd, SelfRefresh, Refresh} state = PdmState::Idle; + tlm_generic_payload powerDownPayload; + Rank rank; + CheckerIF *checker; + + sc_time timeToSchedule; + Command nextCommand; + + bool triggered = false; + bool enterSelfRefresh = false; + bool controllerIdle = true; + unsigned activatedBanks = 0; }; -#endif // FIFOSTRICT_H - +#endif // POWERDOWNMANAGERSTAGGERED_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp new file mode 100644 index 00000000..148c8828 --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "RefreshManager.h" +#include "../../common/dramExtensions.h" +#include "../../configuration/Configuration.h" +#include "../../common/utils.h" + +RefreshManager::RefreshManager(std::vector &bankMachines, + PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) + : bankMachines(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) +{ + Configuration &config = Configuration::getInstance(); + memSpec = config.memSpec; + timeForNextTrigger = memSpec->getRefreshIntervalAB(); + setUpDummy(refreshPayload, rank); + + if (config.ControllerCoreRefEnablePostpone) + maxPostponed = config.ControllerCoreRefMaxPostponed; + if (config.ControllerCoreRefEnablePullIn) + maxPulledin = -config.ControllerCoreRefMaxPulledIn; +} + +void RefreshManager::notifyActive() +{ + controllerIdle = false; +} + +void RefreshManager::notifyIdle() +{ + controllerIdle = true; +} + +std::pair RefreshManager::getNextCommand() +{ + if (sc_time_stamp() == timeToSchedule) + return std::pair(nextCommand, &refreshPayload); + else + return std::pair(Command::NOP, nullptr); +} + +sc_time RefreshManager::start() +{ + timeToSchedule = sc_max_time(); + + if (sc_time_stamp() >= timeForNextTrigger) + { + powerDownManager->triggerExit(TriggerSource::RefreshManager); + if (sleeping) + return sc_max_time() - sc_time_stamp(); + + if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalAB()) + { + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + state = RmState::Regular; + } + + sc_time delay; + if (state == RmState::Regular) + { + bool forcedRefresh = (flexibilityCounter == maxPostponed); + if (!forcedRefresh && !controllerIdle) // no forced refresh & controller is busy -> postpone + { + flexibilityCounter++; + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + return timeForNextTrigger - sc_time_stamp(); + } + else + { + if (forcedRefresh) + { + for (auto it : bankMachines) + it->block(); + } + + if (activatedBanks > 0) + nextCommand = Command::PREA; + else + nextCommand = Command::REFA; + delay = checker->delayToSatisfyConstraints(nextCommand, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + } + else // if (state == RmState::Pulledin) + { + if (!controllerIdle) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + return timeForNextTrigger - sc_time_stamp(); + } + else + { + // nextCommand stays Command::REFA + delay = checker->delayToSatisfyConstraints(nextCommand, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + } + } + else + return timeForNextTrigger - sc_time_stamp(); +} + +void RefreshManager::updateState(Command command, tlm_generic_payload *) +{ + if (command == Command::ACT) + activatedBanks++; + else if (command == Command::PRE) + activatedBanks--; + else if (command == Command::PREA) + activatedBanks = 0; + else if (command == Command::REFA) + { + if (sleeping) + { + // Refresh command after SREFEX + state = RmState::Regular; // TODO: check if this assignment is necessary + timeForNextTrigger = sc_time_stamp() + memSpec->getRefreshIntervalAB(); + sleeping = false; + } + else + { + if (state == RmState::Pulledin) + flexibilityCounter--; + else + state = RmState::Pulledin; + + if (flexibilityCounter == maxPulledin) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + powerDownManager->triggerEntry(TriggerSource::RefreshManager); + } + } + } + else if (command == Command::PDEA || command == Command::PDEP) + sleeping = true; + else if (command == Command::SREFEN) + { + sleeping = true; + timeForNextTrigger = sc_max_time(); + } + else if (command == Command::PDXA || command == Command::PDXP) + sleeping = false; +} diff --git a/DRAMSys/library/src/simulation/RecordableDram.h b/DRAMSys/library/src/controller/refresh/RefreshManager.h similarity index 55% rename from DRAMSys/library/src/simulation/RecordableDram.h rename to DRAMSys/library/src/controller/refresh/RefreshManager.h index 0434177a..e6a2942a 100644 --- a/DRAMSys/library/src/simulation/RecordableDram.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,50 +29,52 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Felipe S. Prado - * Matthias Jung + * Author: Lukas Steiner */ -#ifndef RECORDABLEDRAM_H -#define RECORDABLEDRAM_H +#ifndef REFRESHMANAGER_H +#define REFRESHMANAGER_H -#include "Dram.h" -#include "../common/TlmRecorder.h" +#include "RefreshManagerIF.h" +#include "../../configuration/memspec/MemSpec.h" +#include "../BankMachine.h" +#include "../powerdown/PowerDownManagerIF.h" +#include "../checker/CheckerIF.h" using namespace tlm; -class RecordableDram : public Dram +class RefreshManager final : public RefreshManagerIF { public: - RecordableDram(sc_module_name, TlmRecorder *tlmRecorder); - SC_HAS_PROCESS(RecordableDram); + RefreshManager(std::vector &, PowerDownManagerIF *, Rank, CheckerIF *); - ~RecordableDram(); + virtual std::pair getNextCommand() override; + virtual sc_time start() override; + virtual void updateState(Command, tlm_generic_payload *) override; -protected: - virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &delay); + virtual void notifyActive() override; + virtual void notifyIdle() override; private: - TlmRecorder *tlmRecorder; - sc_time powerWindowSize = Configuration::getInstance().memSpec->clk * - Configuration::getInstance().WindowSize; + enum class RmState {Regular, Pulledin} state = RmState::Regular; + const MemSpec *memSpec; + std::vector &bankMachines; + PowerDownManagerIF *powerDownManager; + tlm_generic_payload refreshPayload; + sc_time timeForNextTrigger = sc_max_time(); + sc_time timeToSchedule = sc_max_time(); + Rank rank; + CheckerIF *checker; + Command nextCommand; - // When working with floats, we have to decide ourselves what is an - // acceptable definition for "equal". Here the number is compared with a - // suitable error margin (0.00001). - bool isEqual(double a, double b, const double epsilon = 1e-05) - { - return std::fabs(a - b) < epsilon; - } + bool controllerIdle = true; + unsigned activatedBanks = 0; - // This Thread is only triggered when Power Simulation is enabled. - // It estimates the current average power which will be stored in the trace database for visualization purposes. - void powerWindow(); + int flexibilityCounter = 0; + int maxPostponed = 0; + int maxPulledin = 0; - void recordPower(); + bool sleeping = false; }; -#endif // RECORDABLEDRAM_H - +#endif // REFRESHMANAGER_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp new file mode 100644 index 00000000..0475ec6b --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "RefreshManagerBankwise.h" +#include "../../configuration/Configuration.h" +#include "../../common/utils.h" +#include "../../common/dramExtensions.h" + +RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines, + PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) + : bankMachines(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) +{ + Configuration &config = Configuration::getInstance(); + memSpec = config.memSpec; + timeForNextTrigger = memSpec->getRefreshIntervalPB(); + + refreshPayloads = std::vector(memSpec->BanksPerRank); + for (unsigned bankID = 0; bankID < memSpec->BanksPerRank; bankID++) + { + setUpDummy(refreshPayloads[bankID], rank, bankMachines[bankID]->getBank()); + allBankMachines.push_back(bankMachines[bankID]); + } + remainingBankMachines = allBankMachines; + + if (config.ControllerCoreRefEnablePostpone) + maxPostponed = config.ControllerCoreRefMaxPostponed * memSpec->BanksPerRank; + if (config.ControllerCoreRefEnablePullIn) + maxPulledin = -(config.ControllerCoreRefMaxPulledIn * memSpec->BanksPerRank); +} + +std::pair RefreshManagerBankwise::getNextCommand() +{ + if (sc_time_stamp() == timeToSchedule) + return std::pair + (nextCommand, &refreshPayloads[currentBankMachine->getBank().ID() % memSpec->BanksPerRank]); + else + return std::pair(Command::NOP, nullptr); +} + +sc_time RefreshManagerBankwise::start() +{ + timeToSchedule = sc_max_time(); + + if (sc_time_stamp() >= timeForNextTrigger) + { + powerDownManager->triggerExit(TriggerSource::RefreshManager); + if (sleeping) + return sc_max_time() - sc_time_stamp(); + + if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalPB()) + { + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + state = RmState::Regular; + } + + sc_time delay; + if (state == RmState::Regular) + { + currentIterator = remainingBankMachines.begin(); + currentBankMachine = *remainingBankMachines.begin(); + bool forcedRefresh = (flexibilityCounter == maxPostponed); + bool allBanksBusy = true; + + for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++) + { + if ((*it)->isIdle()) + { + currentIterator = it; + currentBankMachine = *it; + allBanksBusy = false; + break; + } + } + + if (allBanksBusy && !forcedRefresh) + { + flexibilityCounter++; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + return timeForNextTrigger - sc_time_stamp(); + } + else + { + if (currentBankMachine->getState() == BmState::Activated) + nextCommand = Command::PRE; + else + nextCommand = Command::REFB; + delay = checker->delayToSatisfyConstraints(nextCommand, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + } + else // if (state == RmState::Pulledin) + { + bool allBanksBusy = true; + + for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++) + { + if ((*it)->isIdle()) + { + currentIterator = it; + currentBankMachine = *it; + allBanksBusy = false; + break; + } + } + + if (allBanksBusy) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + return timeForNextTrigger - sc_time_stamp(); + } + else + { + if (currentBankMachine->getState() == BmState::Activated) + nextCommand = Command::PRE; + else + nextCommand = Command::REFB; + delay = checker->delayToSatisfyConstraints(nextCommand, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + } + } + else + return timeForNextTrigger - sc_time_stamp(); +} + +void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *payload) +{ + if (command == Command::REFB) + { + remainingBankMachines.erase(currentIterator); + if (remainingBankMachines.empty()) + remainingBankMachines = allBankMachines; + + if (state == RmState::Pulledin) + flexibilityCounter--; + else + state = RmState::Pulledin; + + if (flexibilityCounter == maxPulledin) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + powerDownManager->triggerEntry(TriggerSource::RefreshManager); + } + } + else if (command == Command::REFA) + { + // Refresh command after SREFEX + state = RmState::Regular; // TODO: check if this assignment is necessary + timeForNextTrigger = sc_time_stamp() + memSpec->getRefreshIntervalPB(); + sleeping = false; + } + else if (command == Command::PDEA || command == Command::PDEP) + sleeping = true; + else if (command == Command::SREFEN) + { + sleeping = true; + timeForNextTrigger = sc_max_time(); + } + else if (command == Command::PDXA || command == Command::PDXP) + sleeping = false; +} diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h similarity index 52% rename from DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.h rename to DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h index a4728f4e..e92cc08f 100644 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,55 +29,56 @@ * 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 - * Éder F. Zulian + * Author: Lukas Steiner */ #ifndef REFRESHMANAGERBANKWISE_H #define REFRESHMANAGERBANKWISE_H -//#include "../../../common/dramExtension.h" -#include "IRefreshManager.h" -#include "../configuration/MemSpec.h" +#include "RefreshManagerIF.h" +#include "../../configuration/memspec/MemSpec.h" +#include "../BankMachine.h" +#include "../powerdown/PowerDownManagerIF.h" +#include +#include +#include +using namespace tlm; -class ControllerCore; - -class RefreshManagerBankwise : public IRefreshManager, public sc_module +class RefreshManagerBankwise final : public RefreshManagerIF { public: - RefreshManagerBankwise(sc_module_name /*name*/, ControllerCore &controllerCore); - virtual ~RefreshManagerBankwise(); + RefreshManagerBankwise(std::vector &, PowerDownManagerIF *, Rank, CheckerIF *); - virtual bool hasCollision(const ScheduledCommand &command) override; - virtual void scheduleRefresh(tlm::tlm_generic_payload &payload, - sc_time time) override; - void reInitialize(Bank bank, sc_time time) override; - bool isInvalidated(tlm::tlm_generic_payload &payload, sc_time time) override; + virtual std::pair getNextCommand() override; + virtual sc_time start() override; + virtual void updateState(Command, tlm_generic_payload *) override; + + virtual void notifyActive() override {} + virtual void notifyIdle() override {} private: - ControllerCore &controllerCore; - RefreshTiming &timing; - std::map nextPlannedRefreshs; - sc_time tREFIx; - sc_time tRFCx; - std::map refreshPayloads; - bool postponeEnabled; - bool pullInEnabled; - unsigned int maxpostpone; - unsigned int maxpullin; - std::map pulledin; - std::map postponed; - std::map currentState; - std::map previousState; - std::map nextState; + enum class RmState {Regular, Pulledin} state = RmState::Regular; + const MemSpec *memSpec; + std::vector &bankMachines; + PowerDownManagerIF *powerDownManager; + std::vector refreshPayloads; + sc_time timeForNextTrigger = sc_max_time(); + sc_time timeToSchedule = sc_max_time(); + Rank rank; + CheckerIF *checker; + Command nextCommand; - bool doRefresh(tlm::tlm_generic_payload &payload, sc_time time); - void planNextRefresh(Bank bank, sc_time time, bool align); - void printDebugMessage(std::string message); + std::list remainingBankMachines; + std::list allBankMachines; + std::list::iterator currentIterator; + BankMachine *currentBankMachine; + + int flexibilityCounter = 0; + int maxPostponed = 0; + int maxPulledin = 0; + + bool sleeping = false; }; #endif // REFRESHMANAGERBANKWISE_H - diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.cpp new file mode 100644 index 00000000..c6c1428c --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "RefreshManagerDummy.h" + +std::pair RefreshManagerDummy::getNextCommand() +{ + return std::pair(Command::NOP, nullptr); +} + +sc_time RefreshManagerDummy::start() +{ + return sc_max_time() - sc_time_stamp(); +} diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h new file mode 100644 index 00000000..e9c2cabe --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef REFRESHMANAGERDUMMY_H +#define REFRESHMANAGERDUMMY_H + +#include +#include +#include +#include "RefreshManagerIF.h" +#include "../Command.h" + +using namespace tlm; + +class RefreshManagerDummy final : public RefreshManagerIF +{ +public: + virtual std::pair getNextCommand() override; + virtual sc_time start() override; + virtual void updateState(Command, tlm_generic_payload *) override {} + + virtual void notifyActive() override {} + virtual void notifyIdle() override {} +}; + +#endif // REFRESHMANAGERDUMMY_H diff --git a/DRAMSys/library/src/controller/core/Slots.h b/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h similarity index 74% rename from DRAMSys/library/src/controller/core/Slots.h rename to DRAMSys/library/src/controller/refresh/RefreshManagerIF.h index 61663568..cedf94c9 100644 --- a/DRAMSys/library/src/controller/core/Slots.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,35 +29,30 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Robert Gernhardt - * Matthias Jung + * Author: Lukas Steiner */ -#ifndef SLOTS_H -#define SLOTS_H +#ifndef REFRESHMANAGERIF_H +#define REFRESHMANAGERIF_H #include -#include -#include "scheduling/ScheduledCommand.h" +#include +#include +#include "../Command.h" -class Slots +using namespace tlm; + +class RefreshManagerIF { public: - Slots(sc_time clk); - virtual ~Slots(); + virtual ~RefreshManagerIF() {} - void moveCommandToNextFreeSlot(ScheduledCommand &command); - void cleanUpSlots(sc_time time); - void blockSlot(sc_time time); - bool isFree(sc_time); - -private: - sc_time clk; - std::set slotSet; - void blockSlots(sc_time begin, sc_time end, bool excludeBorders); + virtual std::pair getNextCommand() = 0; + virtual sc_time start() = 0; + virtual void updateState(Command, tlm_generic_payload *) = 0; + virtual void notifyIdle() = 0; + virtual void notifyActive() = 0; }; - -#endif // SLOTS_H +#endif // REFRESHMANAGERIF_H diff --git a/DRAMSys/library/src/controller/scheduler/FifoStrict.cpp b/DRAMSys/library/src/controller/scheduler/FifoStrict.cpp deleted file mode 100644 index 4b890433..00000000 --- a/DRAMSys/library/src/controller/scheduler/FifoStrict.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Éder F. Zulian - */ - -#include "FifoStrict.h" - -void FifoStrict::storeRequest(tlm::tlm_generic_payload *payload) -{ - Bank bank = DramExtension::getExtension(payload).getBank(); - buffer.push_back(std::pair(bank, payload)); -} - -std::pair FifoStrict::getNextRequest( - Bank bank) -{ - if (!buffer.empty()) { - - if (buffer.front().first == bank) { - // The next request in the FIFO is for the bank passed as parameter - - tlm::tlm_generic_payload *payload = buffer.front().second; - - // For a given request (a given payload) one or more commands will - // be sent to the DRAM in order to process it. - // - // getNextRequest() may be called more than once for the same - // enqueued request until the appropriate sequence of commands is - // sent to the DRAM. - // - // Every time getNextRequest() is called it calls - // getNextCommand() that returns the suitable command to be sent - // to the DRAM. - // - // getNextCommand() returns the proper command based on the - // internal status of the DRAM. - // - // In the worst case getNextCommand() needs to be called three - // times for a given element in the requests queue: first for - // precharge, second for activate and finally for read or write - // (accordingly the nature of the request). In contrast, for the - // case of an already open row (due to a previous request) the - // command itself could be directly issued. - // - Command command = IScheduler::getNextCommand(payload); - - if (commandIsIn(command, {Command::Read, Command::Write, Command::ReadA, Command::WriteA})) { - buffer.pop_front(); - - // Check if the next transaction is a blocked read or write - - if (!buffer.empty()) { - tlm::tlm_generic_payload *p = buffer.front().second; - Command cmd = IScheduler::getNextCommand(p); - if (commandIsIn(cmd, {Command::Read, Command::Write, Command::ReadA, Command::WriteA})) { - Bank b = DramExtension::getBank(p); - controller.blockedRequests.push(b); - } - } - } - - return std::pair(command, payload); - - } else { - // The next request in the FIFO is NOT for the bank passed as parameter. - - // Search for the next request related to the bank passed as parameter. - for (auto req = buffer.begin(); req != buffer.end(); req++) { - if (req->first == bank) { - // Found a request to this bank in the queue - tlm::tlm_generic_payload *payload = req->second; - - // Get the appropriate command to be sent to the DRAM - // regarding this request. - // - // Commands other than read and write will be issued. - // Reads and writes will not be issued since this - // scheduler executes all read and writes in a strict - // order. - Command command = getNextCommand(payload); - if (commandIsIn(command, {Command::Read, Command::Write, Command::ReadA, Command::WriteA})) { - // Reads and writes must be executed in order. Then if - // the next command for this request is read or write - // NOP will be returned and no operation will be - // performed. - return std::pair(Command::NOP, NULL); - } - else { - // Commands other than read and write are issued normally. - return std::pair(command, payload); - } - } - } - } - } - - return std::pair(Command::NOP, NULL); -} - -gp *FifoStrict::getPendingRequest(Bank /*bank*/) -{ - return NULL; -} diff --git a/DRAMSys/library/src/controller/scheduler/FrFcfs.cpp b/DRAMSys/library/src/controller/scheduler/FrFcfs.cpp deleted file mode 100644 index c0d742af..00000000 --- a/DRAMSys/library/src/controller/scheduler/FrFcfs.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - */ - -#include "FrFcfs.h" -#include "../../common/dramExtensions.h" -#include "../core/configuration/Configuration.h" -#include - -using namespace std; - -// The FrFcfs (First Ready First Come First Served) is descibed in a 2000 paper from Rixner et al.: -// Memory Access Scheduling -// -// The FrFcfs scheduler features for each bank in the DRAM a specific -// scheduling buffer for example: -// -// Bank0: OOOOOOOO -// Bank1: OOXXXXXX -// ... ^ ^ -// ... | | -// ... back | -// ... front -// ... -// Bank6: OOOOO0XX -// Bank7: XXXXXXXX - -void FrFcfs::storeRequest(gp *payload) -{ - // FIXME: Question: what if the buffer is full? IMHO the schedule function - // should provide a true or false when the placement into the buffer worked - // out or not (?). - buffer[DramExtension::getExtension(payload).getBank()] - .emplace_back(payload); -} - -std::pair FrFcfs::getNextRequest(Bank bank) -{ - // If the bank is empty like Bank0 in the example we do nothing - if (buffer[bank].empty()) - return std::pair(Command::NOP, NULL); - - // In FrFcfs row hits have always the highest priority, therefore we search - // for row hits. If we find a row hit, we remove the transaction from the - // queue and send it to the DRAM. - std::deque::iterator it = findRowHit(bank); - if (it != buffer[bank].end()) - { - gp *payload = *it; - buffer[bank].erase(it); - return std::pair(getReadWriteCommand(payload), payload); - } - - // If there is no row hit, the FrFcfs takes always the oldest transaction - // in the buffer, i.e. the transaction in the front. - return std::pair(getNextCommand(buffer[bank].front()), - buffer[bank].front()); -} - -// This function searches for a row hit in the scheduling queue of the specific -// bank. If no row hit is found the end of the queue is returned. -// -// Note: end() Returns an iterator referring to the past-the-end element in the -// deque container. The past-the-end element is the theoretical element that -// would follow the last element in the deque container. It does not point to -// any element, and thus shall not be dereferenced. -std::deque::iterator FrFcfs::findRowHit(Bank bank) -{ - std::deque &queue = buffer[bank]; - Row activeRow = controllerCore.getRowBufferStates().getRowInRowBuffer(bank); - - if (!controllerCore.getRowBufferStates().rowBufferIsOpen(bank)) - return queue.end(); - - // Traverse the scheduling queue of the specific bank: - for (auto it = queue.begin(); it != queue.end(); it++) - { - //Found row-hit and return the according iterator - if (DramExtension::getRow(*it) == activeRow) - return it; - } - - return queue.end(); -} - -gp *FrFcfs::getPendingRequest(Bank /*bank*/) -{ - return NULL; -} diff --git a/DRAMSys/library/src/controller/scheduler/FrFcfsGrp.cpp b/DRAMSys/library/src/controller/scheduler/FrFcfsGrp.cpp deleted file mode 100644 index 3b41fd43..00000000 --- a/DRAMSys/library/src/controller/scheduler/FrFcfsGrp.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Matthias Jung - */ - -#include "FrFcfsGrp.h" - -// The FrFcfsGrp (First Ready First Come First Served Grouper) works exactly -// like the FrFcfsRp (First Ready First Come First Served Read Priority). -// However writes are grouped! For detailed documentation look into the FrFcfs. -// TODO: what is missed is a check if the buffers are full. This will only work -// if we have buffers with a fixed size (Prado's future patch). - -std::pair FrFcfsGrp::getNextRequest(Bank bank) -{ - // If the bank is empty we do nothing: - if (buffer[bank].empty()) { - return pair(Command::NOP, NULL); - } - - // If we are in write mode we should check if we should switch to read mode - // because there are no writes anymore in the buffer. - if (readMode == false) { - if (getNumberOfRequest(tlm::TLM_WRITE_COMMAND) == 0) { - readMode = true; - } - } else { // If we are in read mode but all reads are served we switch to write - if (getNumberOfRequest(tlm::TLM_READ_COMMAND) == 0) { - readMode = false; - } - } - - // Now lets search for read and write commands. However keep in mind that - // readMode is a shared variable for all the banks! - if (readMode == true) { - // 1. Seach for read hit: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *read = *it; - - if (read->get_command() == tlm::TLM_READ_COMMAND) { - // If there is a row hit: - if (DramExtension::getRow(read) - == controllerCore.getRowBufferStates() - .getRowInRowBuffer(bank)) { - if (hazardDetection(bank, it) == false) { - buffer[bank].erase(it); - printDebugMessage("Read Hit found"); - return pair(getReadWriteCommand(read), - read); - } else { - // If there was a hazard, switch the mode and try again: - readMode = false; - return getNextRequest(bank); - } - } - } - } - - // 2. Search for read miss: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *read = *it; - - if (read->get_command() == tlm::TLM_READ_COMMAND) { - if (hazardDetection(bank, it) == false) { - printDebugMessage("Read miss found"); - return pair(getNextCommand(read), read); - } else { - // If there was a hazard, switch the mode and try again: - readMode = false; - return getNextRequest(bank); - } - } - } - } else { // write mode: - // 3. Search for write hit: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *write = *it; - - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - // If there is a row hit: - if (DramExtension::getRow(write) - == controllerCore.getRowBufferStates() - .getRowInRowBuffer(bank)) { - buffer[bank].erase(it); - printDebugMessage("Write Hit found"); - return pair(getReadWriteCommand(write), - write); - } - } - } - - // 4. Search for write miss: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *write = *it; - - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - printDebugMessage("Write miss found"); - return pair(getNextCommand(write), write); - } - } - } - - // If nothing was found we check the other banks before we switch the mode: - pair other(Command::NOP, NULL); - unsigned int B = Configuration::getInstance().memSpec->NumberOfBanks; - - for (unsigned int i = 1; i < B; i++) { - Bank nextBank((bank.ID() + i) % B); - ctrl->scheduleNextFromScheduler(nextBank); - } - - // If nothing was found in the current mode, switch the mode and try again: - // FIXME: this is in my opinion not so clever yet, because we switch maybe - // even though there are still reads/writes request on other banks ... - readMode = !readMode; - return getNextRequest(bank); - - reportFatal("FrFcfsGrp", "Never should go here ..."); -} - -// There is a hazard if a read is found which will be scheduled before a write -// to the same column and the same row of the same bank: -bool FrFcfsGrp::hazardDetection(Bank bank, std::deque::iterator ext) -{ - gp *read = *ext; - - //for(unsigned long i=0; i < id; i++) - for (auto it = buffer[bank].begin(); it != ext; it++) { - gp *write = *it; - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - if ((DramExtension::getExtension(read).getColumn() - == DramExtension::getExtension(write).getColumn()) - && (DramExtension::getExtension(read).getRow() - == DramExtension::getExtension(write).getRow())) { - printDebugMessage("Hazard Detected"); - return true; - } - } - } - return false; -} - -// Estimate the number of writes/reads in all bank buffers: -unsigned int FrFcfsGrp::getNumberOfRequest(tlm::tlm_command cmd) -{ - unsigned int numberOfRequests = 0; - for (unsigned int i = 0; - i < Configuration::getInstance().memSpec->NumberOfBanks; - i++) { - for (auto it = buffer[i].begin(); it != buffer[i].end(); it++) { - gp *trans = *it; - if (trans->get_command() == cmd) { - numberOfRequests++; - } - } - } - - return numberOfRequests; -} - -void FrFcfsGrp::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage("FrFcfsGrp", message); -} diff --git a/DRAMSys/library/src/controller/scheduler/FrFcfsGrp.h b/DRAMSys/library/src/controller/scheduler/FrFcfsGrp.h deleted file mode 100644 index ffcf0b5a..00000000 --- a/DRAMSys/library/src/controller/scheduler/FrFcfsGrp.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Matthias Jung - */ - -#ifndef FRFCFSGRP_H -#define FRFCFSGRP_H - -#include "FrFcfs.h" -#include "../Controller.h" - -class Controller; - -class FrFcfsGrp : public FrFcfs -{ -public: - FrFcfsGrp(ControllerCore &controllerCore, Controller *c) - : FrFcfs(controllerCore), ctrl(c), readMode(true) {} - - std::pair - getNextRequest(Bank bank) override; - -private: - Controller *ctrl; - bool hazardDetection(Bank bank, std::deque::iterator ext); - unsigned int getNumberOfRequest(tlm::tlm_command cmd); - void printDebugMessage(std::string message); - bool readMode; -}; - -#endif // FRFCFSGRP_H diff --git a/DRAMSys/library/src/controller/scheduler/FrFcfsRp.cpp b/DRAMSys/library/src/controller/scheduler/FrFcfsRp.cpp deleted file mode 100644 index 250510c0..00000000 --- a/DRAMSys/library/src/controller/scheduler/FrFcfsRp.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2017, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Matthias Jung - */ - -#include "FrFcfsRp.h" - -// The FrFcfsRp (First Ready First Come First Served Read Priority) works -// exactly like the FrFcfs but reads are prioratized over writes. -// For detailed documentation look into the FrFcfs. - -std::pair FrFcfsRp::getNextRequest(Bank bank) -{ - // If the bank is empty like Bank0 in the example we do nothing: - if (buffer[bank].empty()) { - return pair(Command::NOP, NULL); - } - - // Order of Priority: - // 1. Read Hits (Hazard Check) - // 2. Write Hits - // 3. Read Miss (Hazard Check) - // 4. Write Miss - - // 1. Seach for read hit: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *read = *it; - - if (read->get_command() == tlm::TLM_READ_COMMAND) { - // If there is a row hit: - if (DramExtension::getRow(read) - == controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) { - if (hazardDetection(bank, it) == false) { - buffer[bank].erase(it); - printDebugMessage("Read Hit found"); - return pair(getReadWriteCommand(read), read); - } - } - } - } - - // 2. Search for write hit: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *write = *it; - - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - // If there is a row hit: - if (DramExtension::getRow(write) - == controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) { - buffer[bank].erase(it); - printDebugMessage("Write Hit found"); - return pair(getReadWriteCommand(write), write); - } - } - } - - // For now return the oldest request but prefere also reads before writes: - - // 3. Search for read miss: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *read = *it; - - if (read->get_command() == tlm::TLM_READ_COMMAND) { - if (hazardDetection(bank, it) == false) { - printDebugMessage("Read miss found"); - return pair(getNextCommand(read), read); - } - } - } - - // 3. Search for write miss: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *write = *it; - - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - printDebugMessage("Write miss found"); - return pair(getNextCommand(write), write); - } - } - - reportFatal("FrFcfsRp", "Never should go here ..."); - return pair(Command::NOP, NULL); -} - -// There is a hazard if a read is found which will be scheduled before a write -// to the same column and the same row of the same bank: -bool FrFcfsRp::hazardDetection(Bank bank, std::deque::iterator ext) -{ - gp *read = *ext; - - //for(unsigned long i=0; i < id; i++) - for (auto it = buffer[bank].begin(); it != ext; it++) { - gp *write = *it; - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - if ((DramExtension::getExtension(read).getColumn() - == DramExtension::getExtension(write).getColumn()) - && (DramExtension::getExtension(read).getRow() - == DramExtension::getExtension(write).getRow())) { - printDebugMessage("Hazard Detected"); - return true; - } - } - } - return false; -} - -void FrFcfsRp::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage("FrFcfsRp", message); -} diff --git a/DRAMSys/library/src/controller/scheduler/Grp.cpp b/DRAMSys/library/src/controller/scheduler/Grp.cpp deleted file mode 100644 index cf4dffe2..00000000 --- a/DRAMSys/library/src/controller/scheduler/Grp.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2018, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Matthias Jung - */ - -#include "Grp.h" - -// Grp (Grouper) just reorders w.r.t. read write grouping, however is not aware of the -// row buffer. For a row buffer aware grouper refer to FrFcfsGrp. -// TODO: what is missed is a check if the buffers are full. This will only work -// if we have buffers with a fixed size (Prado's future patch). - -std::pair Grp::getNextRequest(Bank bank) -{ - // If the bank is empty we do nothing: - if (buffer[bank].empty()) { - return pair(Command::NOP, NULL); - } - - // If we are in write mode we should check if we should switch to read mode - // because there are no writes anymore in the buffer. - if (readMode == false) { - if (getNumberOfRequest(tlm::TLM_WRITE_COMMAND) == 0) { - readMode = true; - } - } else { // If we are in read mode but all reads are served we switch to write - if (getNumberOfRequest(tlm::TLM_READ_COMMAND) == 0) { - readMode = false; - } - } - - // Now lets search for read and write commands. However keep in mind that - // readMode is a shared variable for all the banks! - if (readMode == true) { - // 1. Seach for read hit: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *read = *it; - - if (read->get_command() == tlm::TLM_READ_COMMAND) { - // If there is a row hit: - if (DramExtension::getRow(read) - == controllerCore.getRowBufferStates() - .getRowInRowBuffer(bank)) { - if (hazardDetection(bank, it) == false) { - buffer[bank].erase(it); - printDebugMessage("Read Hit found"); - return pair(getReadWriteCommand(read), - read); - } else { - // If there was a hazard, switch the mode and try again: - readMode = false; - return getNextRequest(bank); - } - } else { // if there is a row miss: - if (hazardDetection(bank, it) == false) { - printDebugMessage("Read miss found"); - return pair(getNextCommand(read), read); - } else { - // If there was a hazard, switch the mode and try again: - readMode = false; - return getNextRequest(bank); - } - } - } - } - - } else { // write mode: - // 3. Search for write hit: - for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { - gp *write = *it; - - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - // If there is a row hit: - if (DramExtension::getRow(write) - == controllerCore.getRowBufferStates() - .getRowInRowBuffer(bank)) { - buffer[bank].erase(it); - printDebugMessage("Write Hit found"); - return pair(getReadWriteCommand(write), - write); - } else { - printDebugMessage("Write miss found"); - return pair(getNextCommand(write), write); - } - } - } - } - - // If nothing was found we check the other banks before we switch the mode: - pair other(Command::NOP, NULL); - unsigned int B = Configuration::getInstance().memSpec->NumberOfBanks; - - for (unsigned int i = 1; i < B; i++) { - Bank nextBank((bank.ID() + i) % B); - ctrl->scheduleNextFromScheduler(nextBank); - } - - // If nothing was found in the current mode, switch the mode and try again: - // FIXME: this is in my opinion not so clever yet, because we switch maybe - // even though there are still reads/writes request on other banks ... - readMode = !readMode; - return getNextRequest(bank); - - reportFatal("Grp", "Never should go here ..."); -} - -// There is a hazard if a read is found which will be scheduled before a write -// to the same column and the same row of the same bank: -bool Grp::hazardDetection(Bank bank, std::deque::iterator ext) -{ - gp *read = *ext; - - //for(unsigned long i=0; i < id; i++) - for (auto it = buffer[bank].begin(); it != ext; it++) { - gp *write = *it; - if (write->get_command() == tlm::TLM_WRITE_COMMAND) { - if ((DramExtension::getExtension(read).getColumn() - == DramExtension::getExtension(write).getColumn()) - && (DramExtension::getExtension(read).getRow() - == DramExtension::getExtension(write).getRow())) { - printDebugMessage("Hazard Detected"); - return true; - } - } - } - return false; -} - -// Estimate the number of writes/reads in all bank buffers: -unsigned int Grp::getNumberOfRequest(tlm::tlm_command cmd) -{ - unsigned int numberOfRequests = 0; - for (unsigned int i = 0; - i < Configuration::getInstance().memSpec->NumberOfBanks; - i++) { - for (auto it = buffer[i].begin(); it != buffer[i].end(); it++) { - gp *trans = *it; - if (trans->get_command() == cmd) { - numberOfRequests++; - } - } - } - - return numberOfRequests; -} - -void Grp::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage("FrFcfsGrp", message); -} diff --git a/DRAMSys/library/src/controller/scheduler/Grp.h b/DRAMSys/library/src/controller/scheduler/Grp.h deleted file mode 100644 index 13ccea71..00000000 --- a/DRAMSys/library/src/controller/scheduler/Grp.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2018, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Matthias Jung - */ - -#ifndef GRP_H -#define GRP_H - -#include "FrFcfs.h" -#include "../Controller.h" - -class Controller; - -class Grp : public FrFcfs -{ -public: - Grp(ControllerCore &controllerCore, Controller *c) - : FrFcfs(controllerCore), ctrl(c), readMode(true) {} - - std::pair - getNextRequest(Bank bank) override; - -private: - Controller *ctrl; - bool hazardDetection(Bank bank, std::deque::iterator ext); - unsigned int getNumberOfRequest(tlm::tlm_command cmd); - void printDebugMessage(std::string message); - bool readMode; -}; - -#endif // GRP_H diff --git a/DRAMSys/library/src/controller/scheduler/SMS.cpp b/DRAMSys/library/src/controller/scheduler/SMS.cpp deleted file mode 100644 index f01267d7..00000000 --- a/DRAMSys/library/src/controller/scheduler/SMS.cpp +++ /dev/null @@ -1,358 +0,0 @@ -#include "SMS.h" -#include - -using namespace std; - -void SMS::storeRequest(gp *payload) -{ - Thread thread = DramExtension::getExtension(payload).getThread(); - bool wasEmpty = isRequestBuffersEmpty(); - - requestBuffers[thread].emplace_back(payload); - - if (inFlightMemRequestCounter.find(thread) == inFlightMemRequestCounter.end()) { - inFlightMemRequestCounter[thread] = 0; - cacheMisses[thread] = 0; - } - inFlightMemRequestCounter[thread]++; - cacheMisses[thread]++; - - if (wasEmpty) { - newRequest.notify(SC_ZERO_TIME); - } -} - -std::pair SMS::getNextRequest(Bank bank) -{ - if (bankBuffers[bank].empty()) { - debugManager.printDebugMessage(name(), - "Get next request on bank " + to_string(bank.ID()) + " : EMPTY buffer"); - return pair(Command::NOP, NULL); - } else { - gp *payload = bankBuffers[bank].front(); - Command command = IScheduler::getNextCommand(payload); - if (command == Command::Read || command == Command::ReadA - || command == Command::Write - || command == Command::WriteA) { - inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]--; - bankBuffers[bank].pop_front(); - } - - debugManager.printDebugMessage(name(), - "Get next request on bank " + to_string(bank.ID())); - return pair(command, payload); - } -} - -void SMS::batchScheduler() -{ - sc_time memClk = Configuration::getInstance().memSpec->clk; - std::default_random_engine generator; - std::bernoulli_distribution distribution((double) SJFprobability / 100.0); - - while (true) { - updateMPKCs(memClk); - if (isRequestBuffersEmpty()) { - wait(newRequest); - } else { - multiBatchFormation(memClk); - if (existReadyBatches()) { - if (!isSystemLightlyLoaded() && (existLowIntensityThread() - || distribution(generator))) { - pickSJF(); - } else { - pickRR(); - } - drainOnePayloadFromReadybatch(memClk); - } else { - wait(memClk); - } - } - } -} - -/** - * Pick a Thread according to Shortest-Job Policy - * Save the picked one into lastSelectedThread - * @return true if it can, otherwise false - */ -bool SMS::pickSJF() -{ - // find threads with ready batches - std::vector threadsWithReadyBatches; - for (const auto &each : readyBatchInclusiveEndLocs) { - if (!each.second.empty()) { - // marked as thread with non-empty request buffer - threadsWithReadyBatches.push_back(each.first); - } - } - - if (!threadsWithReadyBatches.empty()) { - // pick shortest-job thread among threads with non-empty request buffer - Thread &minThread = threadsWithReadyBatches.front(); - for (const auto &thread : threadsWithReadyBatches) { - if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread]) { - minThread = thread; - } - } - - // save selected thread - lastSelectedThread = readyBatchInclusiveEndLocs.find(minThread); - debugManager.printDebugMessage(name(), - "[SJF] Select ready batch of thread " + to_string(minThread.ID())); - return true; - } else { - return false; - } -} - -/** - * Drain the picked request buffer into bank buffers - * by move request one-by-one from start of the request buffer till last parameter - * @param memClk - * @param last - */ -void SMS::drainOnePayloadFromReadybatch(const sc_time &memClk) -{ - if (lastSelectedThread->second.empty()) { - return; - } - const Thread &selectedThread = lastSelectedThread->first; - - const size_t &inclusiveEndLoc = lastSelectedThread->second.front(); - assert(inclusiveEndLoc < requestBuffers.size()); - - for (size_t i = 0; i <= inclusiveEndLoc; ++i) { - wait(memClk); - Bank bank = DramExtension::getExtension( - requestBuffers[selectedThread].front()).getBank(); - bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front()); - requestBuffers[selectedThread].pop_front(); - - // decrement inclusive end locations of ready batches - // except this ready batch - for (size_t i = 1; i < readyBatchInclusiveEndLocs[selectedThread].size(); ++i) { - --readyBatchInclusiveEndLocs[selectedThread][i]; - } - - debugManager.printDebugMessage(name(), - "[SJF] Drain request in the ready batch of thread " - + to_string((*lastSelectedThread).first.ID()) + " to bankbuffer " - + to_string(bank.ID())); - } - lastSelectedThread->second.pop_front(); -} - -/** - * Pick a Thread according to Round-Robin Policy - * Save the picked one into lastSelectedThread - * @return true if it can pick one, otherwise false - */ -bool SMS::pickRR() -{ - if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { - lastSelectedThread = readyBatchInclusiveEndLocs.begin(); - if (!(*lastSelectedThread).second.empty()) { - return true; - } - } - - std::map>::iterator savedOriginalNextSelectedThread = - lastSelectedThread; - - do { - lastSelectedThread++; - if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { - lastSelectedThread = readyBatchInclusiveEndLocs.begin(); - } - if (lastSelectedThread == savedOriginalNextSelectedThread) { - return false; - } - } while ((*lastSelectedThread).second.empty()); - - debugManager.printDebugMessage(name(), - "[RR] Select ready batch of thread " + to_string(( - *lastSelectedThread).first.ID())); - return true; -} - -bool SMS::isSystemLightlyLoaded() const -{ - unsigned int totalRequest = 0; - for (const auto &bankBuffer : bankBuffers) { - totalRequest += bankBuffer.second.size(); - } - return (totalRequest <= LOW_SYSTEM_LOAD); -} - -bool SMS::existLowIntensityThread() const -{ - for (const auto &mpkcPerThread : MPKCs) { - if (mpkcPerThread.second < LOW_MPKC) { - return true; - } - } - return false; -} - -bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk, - size_t const &inclusiveBeginLoc, size_t const &exclusiveEndLoc) -{ - assert((exclusiveEndLoc - inclusiveBeginLoc) >= 1); - // find the oldest request in the thread's batch - sc_time oldestGenerationTime = sc_time_stamp(); - for (size_t i = inclusiveBeginLoc; i != exclusiveEndLoc; ++i) { - sc_time reqGenerationTime = GenerationExtension::getExtension( - requestBuffers[thread][i]).TimeOfGeneration(); - if (reqGenerationTime < oldestGenerationTime) { - oldestGenerationTime = reqGenerationTime; - } - } - - // check threshold age according to the thread's MPKC - sc_time oldestRequestAge = sc_time_stamp() - oldestGenerationTime; - if ((MPKCs[thread] <= MEDIUM_MPKC) - && (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) { - return true; - } else if ((MPKCs[thread] > MEDIUM_MPKC) - && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) { - return true; - } else { - return false; - } -} - -void SMS::updateMPKCs(sc_time const &memClk) -{ - if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) { - // reset for every 10k clk cycles - for (const auto &cacheMiss : cacheMisses) { - MPKCs[cacheMiss.first] = 0; - } - debugManager.printDebugMessage(name(), "Reset MKKCs"); - } else { - // update MPKC for every thread - for (const auto &cacheMiss : cacheMisses) { - MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / - (sc_time_stamp()); - } - debugManager.printDebugMessage(name(), "Update MPKCs"); - } -} - -bool SMS::isExceededReqBufferSize(size_t const &exclusiveEndLoc) -{ - return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize; -} - -bool SMS::isRequestBuffersEmpty() const -{ - for (const auto &requestBuffer : requestBuffers) { - if (!requestBuffer.second.empty()) { - return false; - } - } - return true; -} - -bool SMS::existReadyBatches() const -{ - for (const auto &each : readyBatchInclusiveEndLocs) { - if (!each.second.empty()) { - return true; - } - } - return false; -} - -/** - * Form batch from begin iterator parameter of a request buffer - * If this batch is deemed ready, save the iterator pointing to its last element - * @param memClk - * @param begin - * @return true if this batch is ready, otherwise false - */ -bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, - std::deque const &requestBuffer, size_t const &inclusiveBeginLoc) -{ - if (requestBuffer.empty()) { - return false; - } - - assert(inclusiveBeginLoc <= requestBuffer.size()); - if (requestBuffer.size() == inclusiveBeginLoc) { - return false; - } - - if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded()) { - // bypass requests by forming batch with only one request (threshold age is ZERO) - readyBatchInclusiveEndLocs[thread].push_back(inclusiveBeginLoc); - return true; - } else { - // forming batch with FIFO size & threshold age constraints - size_t firstDifferentRowAccessReqLoc = inclusiveBeginLoc; - Row firstRow = DramExtension::getRow(requestBuffer[inclusiveBeginLoc]); - bool isBatchReady = false; - size_t bufferSize = requestBuffer.size(); - while (firstDifferentRowAccessReqLoc != bufferSize - && DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) == - firstRow) { - ++firstDifferentRowAccessReqLoc; - if (firstDifferentRowAccessReqLoc < bufferSize) { - if (DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) != - firstRow - || isExceededReqBufferSize(firstDifferentRowAccessReqLoc) - || isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, - firstDifferentRowAccessReqLoc)) { - isBatchReady = true; - break; - } - } else { - if (isExceededReqBufferSize(firstDifferentRowAccessReqLoc) - || isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, - firstDifferentRowAccessReqLoc)) { - isBatchReady = true; - break; - } - } - } - - // store this ready batch location - if (isBatchReady) { - --firstDifferentRowAccessReqLoc; - readyBatchInclusiveEndLocs[thread].push_back(firstDifferentRowAccessReqLoc); - debugManager.printDebugMessage(name(), - "Deem batch ready - thread " + to_string(thread.ID())); - return true; - } else { - return false; - } - } -} - -void SMS::multiBatchFormation(sc_time const &memClk) -{ - for (auto &requestBuffer : requestBuffers) { - bool formed = false; - do { - if (readyBatchInclusiveEndLocs[requestBuffer.first].empty()) { - formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, 0); - } else { - formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, - readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1); - } - } while (!requestBuffer.second.empty() && formed); - } -} - -gp *SMS::getPendingRequest(Bank bank) -{ - for (const auto &requestBuffer : requestBuffers) { - for (const auto &request : requestBuffer.second) { - if (DramExtension::getBank(request) == bank) { - return request; - } - } - } - return NULL; -} diff --git a/DRAMSys/library/src/controller/scheduler/SMS.h b/DRAMSys/library/src/controller/scheduler/SMS.h deleted file mode 100644 index 4019836b..00000000 --- a/DRAMSys/library/src/controller/scheduler/SMS.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef SMS_H -#define SMS_H - -#include -#include -#include "sysc/utils/sc_report.h" -#include "IScheduler.h" -#include "../core/ControllerCore.h" -#include "../core/configuration/Configuration.h" -#include "../../common/dramExtensions.h" -#include "../../common/DebugManager.h" - -#define LOW_SYSTEM_LOAD 16 -#define LOW_MPKC 1 -#define MEDIUM_MPKC 10 -#define MEDIUM_THRESHOLD_AGE 50 -#define HIGH_THRESHOLD_AGE 200 -#define MPKC_RESET_CYCLE 10000 - -using namespace std; -typedef std::deque::iterator gp_deque_iterator; - -/** - * SMS - Staged Memory Scheduler involves 3 steps: - * 1. Arrage request in to each buffer of each thread - * 2. Forming ready batches for each thread, i.e all requests access the same row. The batch is deemed - * ready when the next request accesses different row OR When the buffer is full OR When this batch - * is too old - * 3. Send batches to bank buffers. The rules to send batches are Shortest-Job-First OR Round-Robin - * How we select the rule depends on the probability we setup earlier. - */ -class SMS: public sc_module, public IScheduler -{ -public: - SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, - unsigned int SJFprobability) : IScheduler(controllerCore), - SJFprobability(SJFprobability), debugManager(DebugManager::getInstance()) - { - // initialize selected thread iterator - lastSelectedThread = readyBatchInclusiveEndLocs.end(); - SC_THREAD(batchScheduler); - } - SC_HAS_PROCESS(SMS); - - virtual ~SMS() - { - } - - virtual void storeRequest(gp *payload) override; - virtual std::pair getNextRequest(Bank bank) override; - virtual gp *getPendingRequest(Bank bank) override; - - void batchScheduler(); - -private: - std::map> requestBuffers; - std::map> bankBuffers; - std::map> readyBatchInclusiveEndLocs; - - std::map inFlightMemRequestCounter; - std::map cacheMisses; - std::map MPKCs; - unsigned int SJFprobability; - - std::map>::iterator lastSelectedThread; - sc_event newRequest; - - DebugManager &debugManager; - - bool batchFormation(sc_time const &memClk, Thread const &thread, - const std::deque &requestBuffer, const size_t &inclusiveBeginLoc); - void multiBatchFormation(const sc_time &memClk); - bool pickSJF(); - bool pickRR(); - void drainOnePayloadFromReadybatch(const sc_time &memClk); - - bool existLowIntensityThread() const; - bool isSystemLightlyLoaded() const; - bool isThresholdAgeExceeded(const Thread &thread, const sc_time &memClk, - const size_t &inclusiveBeginLoc, const size_t &exclusiveEndLoc); - bool isExceededReqBufferSize(size_t const &exclusiveEndLoc); - void updateMPKCs(const sc_time &memClk); - - bool isRequestBuffersEmpty() const; - bool existReadyBatches() const; -}; - -#endif // SMS_H diff --git a/DRAMSys/library/src/controller/scheduler/Fifo.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp similarity index 54% rename from DRAMSys/library/src/controller/scheduler/Fifo.cpp rename to DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp index cc2ddb11..ce31bc50 100644 --- a/DRAMSys/library/src/controller/scheduler/Fifo.cpp +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,42 +29,59 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: - * Robert Gernhardt - * Matthias Jung + * Author: Lukas Steiner */ -#include "Fifo.h" +#include "SchedulerFifo.h" -void Fifo::storeRequest(gp *payload) +SchedulerFifo::SchedulerFifo() { - Bank bank = DramExtension::getExtension(payload).getBank(); - buffer[bank].emplace_back(payload); + buffer = std::vector> + (Configuration::getInstance().memSpec->NumberOfBanks); + maxNumberOfRequests = Configuration::getInstance().MaxNrOfTransactions; } -std::pair Fifo::getNextRequest(Bank bank) +bool SchedulerFifo::hasBufferSpace(tlm_generic_payload *payload) { - if (!buffer[bank].empty()) - { - gp *payload = buffer[bank].front(); - Command command = IScheduler::getNextCommand(payload); - if (command == Command::Read || command == Command::ReadA - || command == Command::Write || command == Command::WriteA) - { - buffer[bank].pop_front(); - } + if (buffer[DramExtension::getBank(payload).ID()].size() < maxNumberOfRequests) + return true; + else + return false; +} - return std::pair(command, payload); +void SchedulerFifo::storeRequest(tlm_generic_payload *payload) +{ + buffer[DramExtension::getBank(payload).ID()].push(payload); +} + +tlm_generic_payload *SchedulerFifo::getNextRequest(BankMachine *bankMachine) +{ + unsigned bankID = bankMachine->getBank().ID(); + if (!buffer[bankID].empty()) + { + tlm_generic_payload *front = buffer[bankID].front(); + buffer[bankID].pop(); + return front; } else - { - return std::pair(Command::NOP, NULL); - } + return nullptr; } -gp *Fifo::getPendingRequest(Bank /*bank*/) +bool SchedulerFifo::hasRowHit(Bank bank, Row row) { - return NULL; + if (!buffer[bank.ID()].empty()) + { + tlm_generic_payload *front = buffer[bank.ID()].front(); + if (DramExtension::getRow(front) == row) + return true; + } + return false; } - +bool SchedulerFifo::hasRequest(Bank bank) +{ + if (buffer[bank.ID()].empty()) + return false; + else + return true; +} diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h new file mode 100644 index 00000000..f2d9f8be --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef SCHEDULERFIFO_H +#define SCHEDULERFIFO_H + +#include +#include +#include +#include "SchedulerIF.h" +#include "../../common/dramExtensions.h" +#include "../BankMachine.h" + +using namespace tlm; + +class SchedulerFifo : public SchedulerIF +{ +public: + SchedulerFifo(); + virtual bool hasBufferSpace(tlm_generic_payload *) override; + virtual void storeRequest(tlm_generic_payload *) override; + virtual tlm_generic_payload *getNextRequest(BankMachine *) override; + virtual bool hasRowHit(Bank, Row) override; + virtual bool hasRequest(Bank) override; +private: + std::vector> buffer; + unsigned maxNumberOfRequests; +}; + +#endif // SCHEDULERFIFO_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp new file mode 100644 index 00000000..eb784508 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "SchedulerFrFcfs.h" + +#include + +SchedulerFrFcfs::SchedulerFrFcfs() +{ + buffer = std::vector> + (Configuration::getInstance().memSpec->NumberOfBanks); + maxNumberOfRequests = Configuration::getInstance().MaxNrOfTransactions; +} + +bool SchedulerFrFcfs::hasBufferSpace(tlm_generic_payload *payload) +{ + if (buffer[DramExtension::getBank(payload).ID()].size() < maxNumberOfRequests) + return true; + else + return false; +} + +void SchedulerFrFcfs::storeRequest(tlm_generic_payload *payload) +{ + buffer[DramExtension::getBank(payload).ID()].push_back(payload); +} + +tlm_generic_payload *SchedulerFrFcfs::getNextRequest(BankMachine *bankMachine) +{ + unsigned bankID = bankMachine->getBank().ID(); + if (!buffer[bankID].empty()) + { + BmState currentState = bankMachine->getState(); + if (currentState == BmState::Precharged) + { + tlm_generic_payload *result = buffer[bankID].front(); + buffer[bankID].pop_front(); + return result; + } + else if (currentState == BmState::Activated) + { + // Search for row hit + Row openRow = bankMachine->getOpenRow(); + for (auto it = buffer[bankID].begin(); it != buffer[bankID].end(); it++) + { + if (DramExtension::getRow(*it) == openRow) + { + tlm_generic_payload *result = *it; + buffer[bankID].erase(it); + return result; + } + } + // No row hit found + tlm_generic_payload *result = buffer[bankID].front(); + buffer[bankID].pop_front(); + return result; + } + else + SC_REPORT_FATAL("SchedulerFrFcfs", "Wrong BM state!"); + } + return nullptr; +} + +bool SchedulerFrFcfs::hasRowHit(Bank bank, Row row) +{ + for (auto it = buffer[bank.ID()].begin(); it != buffer[bank.ID()].end(); it++) + { + if (DramExtension::getRow(*it) == row) + return true; + } + return false; +} + +bool SchedulerFrFcfs::hasRequest(Bank bank) +{ + if (buffer[bank.ID()].empty()) + return false; + else + return true; +} diff --git a/DRAMSys/library/src/controller/scheduler/FrFcfs.h b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h similarity index 68% rename from DRAMSys/library/src/controller/scheduler/FrFcfs.h rename to DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h index b3fa643b..5bf4f264 100644 --- a/DRAMSys/library/src/controller/scheduler/FrFcfs.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,38 +29,33 @@ * 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 - * Robert Gernhardt - * Matthias Jung + * Author: Lukas Steiner */ -#ifndef FRFCFS_H -#define FRFCFS_H +#ifndef SCHEDULERFRFCFS_H +#define SCHEDULERFRFCFS_H -#include "IScheduler.h" -#include "../core/ControllerCore.h" -#include -#include +#include #include +#include +#include "SchedulerIF.h" +#include "../../common/dramExtensions.h" +#include "../BankMachine.h" -class FrFcfs : public IScheduler +using namespace tlm; + +class SchedulerFrFcfs : public SchedulerIF { public: - FrFcfs(ControllerCore &controllerCore) : IScheduler(controllerCore) {} - virtual ~FrFcfs() {} - - void storeRequest(gp *payload) override; - std::pair - getNextRequest(Bank bank) override; - virtual gp *getPendingRequest(Bank bank) override; - -protected: - std::map> buffer; - std::deque::iterator findRowHit(Bank bank); - + SchedulerFrFcfs(); + virtual bool hasBufferSpace(tlm_generic_payload *) override; + virtual void storeRequest(tlm_generic_payload *) override; + virtual tlm_generic_payload *getNextRequest(BankMachine *) override; + virtual bool hasRowHit(Bank, Row) override; + virtual bool hasRequest(Bank) override; private: - + std::vector> buffer; + unsigned maxNumberOfRequests; }; -#endif // FRFCFS_H +#endif // SCHEDULERFRFCFS_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerIF.h b/DRAMSys/library/src/controller/scheduler/SchedulerIF.h new file mode 100644 index 00000000..c882a3b0 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/SchedulerIF.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef SCHEDULERIF_H +#define SCHEDULERIF_H + +#include +#include "../../common/dramExtensions.h" +#include "../../common/DebugManager.h" +#include "../BankMachine.h" + +using namespace tlm; + +enum class BmState; +class BankMachine; + +class SchedulerIF +{ +public: + virtual ~SchedulerIF() {} + virtual bool hasBufferSpace(tlm_generic_payload *) = 0; + virtual void storeRequest(tlm_generic_payload *) = 0; + virtual tlm_generic_payload *getNextRequest(BankMachine *) = 0; + virtual bool hasRowHit(Bank, Row) = 0; + virtual bool hasRequest(Bank) = 0; +}; + +#endif // SCHEDULERIF_H diff --git a/DRAMSys/library/src/error/errormodel.cpp b/DRAMSys/library/src/error/errormodel.cpp index 861df60a..b23b8dff 100644 --- a/DRAMSys/library/src/error/errormodel.cpp +++ b/DRAMSys/library/src/error/errormodel.cpp @@ -48,7 +48,7 @@ void errorModel::init() // Get Configuration parameters: burstLenght = Configuration::getInstance().memSpec->BurstLength; numberOfColumns = Configuration::getInstance().memSpec->NumberOfColumns; - bytesPerColumn = AddressDecoder::getInstance().amount["bytes"]; + bytesPerColumn = AddressDecoder::getInstance().amount.bytes; // Adjust number of bytes per column dynamically to the selected ecc controller bytesPerColumn = Configuration::getInstance().adjustNumBytesAfterECC( @@ -112,13 +112,13 @@ void errorModel::init() markBitFlips(); } -errorModel::errorModel(sc_module_name /*name*/, libDRAMPower *dp) +errorModel::errorModel(sc_module_name name, libDRAMPower *dp) : sc_module(name) { this->DRAMPower = dp; init(); } -errorModel::errorModel(sc_module_name /*name*/) +errorModel::errorModel(sc_module_name name) : sc_module(name) { init(); } @@ -165,12 +165,12 @@ void errorModel::store(tlm::tlm_generic_payload &trans) msg << "bank: " << key.bank << " group: " << key.bankgroup << " bytes: " << key.bytes << " channel: " << key.channel << " column: " << key.column << " rank: " << key.rank << " row: " << key.row; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); // Check if the provided data length is correct: assert((bytesPerColumn * burstLenght) == trans.get_data_length()); - printDebugMessage(("Data length: " + std::to_string(trans.get_data_length()) + + PRINTDEBUGMESSAGE(name(), ("Data length: " + std::to_string(trans.get_data_length()) + " bytesPerColumn: " + std::to_string(bytesPerColumn)).c_str()); // Handle the DRAM burst, @@ -211,7 +211,7 @@ void errorModel::store(tlm::tlm_generic_payload &trans) std::stringstream msg; msg << "key.column is " << key.column << " numberOfColumns is " << numberOfColumns; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); assert(key.column <= numberOfColumns); } } @@ -269,7 +269,7 @@ void errorModel::markBitFlips() if (weakCells[i].flipped == false && weakCells[i].row == row) { std::stringstream msg; msg << "Maked weakCell[" << i << "] as flipped" << std::endl; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); weakCells[i].flipped = true; } @@ -334,7 +334,7 @@ void errorModel::activate(unsigned int row) << " row: " << key.row << " col: " << key.column << " bit: " << weakCells[i].bit; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); numberOfBitErrorEvents++; @@ -387,7 +387,7 @@ void errorModel::activate(unsigned int row) << grid[0] << grid[1] << grid[2] << std::endl << grid[3] << grid[4] << grid[5] << std::endl << grid[6] << grid[7] << grid[8]; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); } else { // Output on the Console: std::stringstream msg; @@ -399,7 +399,7 @@ void errorModel::activate(unsigned int row) << grid[0] << grid[1] << grid[2] << std::endl << grid[3] << grid[4] << grid[5] << std::endl << grid[6] << grid[7] << grid[8]; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); } } } @@ -431,7 +431,7 @@ unsigned int errorModel::getBit(DecodedAddress key, unsigned int byteInColumn, << " tempByte = " << (unsigned int)tempByte << " result = " << result; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); return result; } @@ -569,7 +569,7 @@ void errorModel::parseInputData() << " independent = " << errorMap[temp][retentionTime].independent << " dependent = " << errorMap[temp][retentionTime].dependent; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); } inputFile.close(); } else { @@ -670,7 +670,7 @@ void errorModel::prepareWeakCells() << " bit=" << weakCells[i].bit << " flip=" << weakCells[i].flipped << " dep=" << weakCells[i].dependent; - printDebugMessage(msg.str()); + PRINTDEBUGMESSAGE(name(), msg.str()); } } @@ -735,10 +735,3 @@ void errorModel::setContext(DecodedAddress addr) myBank) + " "; } } - -void errorModel::printDebugMessage(std::string message) -{ - std::stringstream msg; - msg << contextStr << message; - DebugManager::getInstance().printDebugMessage(this->name(), msg.str()); -} diff --git a/DRAMSys/library/src/error/errormodel.h b/DRAMSys/library/src/error/errormodel.h index e562401c..d027d9b3 100644 --- a/DRAMSys/library/src/error/errormodel.h +++ b/DRAMSys/library/src/error/errormodel.h @@ -39,15 +39,15 @@ #include #include #include -#include "../controller/core/configuration/Configuration.h" +#include "../configuration/Configuration.h" #include "../common/XmlAddressDecoder.h" #include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" class errorModel : public sc_module { public: - errorModel(sc_module_name /*name*/, libDRAMPower *dp); - errorModel(sc_module_name /*name*/); + errorModel(sc_module_name, libDRAMPower *); + errorModel(sc_module_name); ~errorModel(); // Access Methods: @@ -72,8 +72,6 @@ private: // context: std::string contextStr; - void printDebugMessage(std::string message); - // Online Parameters: unsigned int numberOfBitErrorEvents; @@ -119,8 +117,8 @@ private: bool operator()( const DecodedAddress &first , const DecodedAddress &second) const { - sc_dt::uint64 addrFirst = AddressDecoder::getInstance().encodeAddress(first); - sc_dt::uint64 addrSecond = AddressDecoder::getInstance().encodeAddress(second); + uint64_t addrFirst = AddressDecoder::getInstance().encodeAddress(first); + uint64_t addrSecond = AddressDecoder::getInstance().encodeAddress(second); return addrFirst < addrSecond; } }; diff --git a/DRAMSys/library/src/simulation/Arbiter.cpp b/DRAMSys/library/src/simulation/Arbiter.cpp index c68927f8..f275e057 100644 --- a/DRAMSys/library/src/simulation/Arbiter.cpp +++ b/DRAMSys/library/src/simulation/Arbiter.cpp @@ -40,7 +40,8 @@ using namespace std; using namespace tlm; -Arbiter::Arbiter(sc_module_name /*name*/) : payloadEventQueue(this, &Arbiter::peqCallback) +Arbiter::Arbiter(sc_module_name name) : + sc_module(name), payloadEventQueue(this, &Arbiter::peqCallback) { // The arbiter communicates with one or more memory unity through one or more sockets (one or more memory channels). // Each of the arbiter's initiator sockets is bound to a memory controller's target socket. @@ -51,6 +52,7 @@ Arbiter::Arbiter(sc_module_name /*name*/) : payloadEventQueue(this, &Arbiter::pe { channelIsFree.push_back(true); pendingRequests.push_back(queue()); + nextPayloadID.push_back(0); } // One or more devices can accesss all the memory units through the arbiter. @@ -85,7 +87,7 @@ tlm_sync_enum Arbiter::nb_transport_fw(int id, tlm_generic_payload &payload, payload.release(); } - printDebugMessage("[fw] " + phaseNameToString(phase) + " notification in " + + PRINTDEBUGMESSAGE(name(), "[fw] " + phaseNameToString(phase) + " notification in " + notDelay.to_string()); payloadEventQueue.notify(payload, phase, notDelay); return TLM_ACCEPTED; @@ -100,7 +102,7 @@ tlm_sync_enum Arbiter::nb_transport_bw(int channelId, tlm_generic_payload &paylo if ((unsigned int)channelId != DramExtension::getExtension(payload).getChannel().ID()) SC_REPORT_FATAL("Arbiter", "Payload extension was corrupted"); - printDebugMessage("[bw] " + phaseNameToString(phase) + " notification in " + + PRINTDEBUGMESSAGE(name(), "[bw] " + phaseNameToString(phase) + " notification in " + bwDelay.to_string()); payloadEventQueue.notify(payload, phase, bwDelay); return TLM_ACCEPTED; @@ -215,37 +217,29 @@ void Arbiter::appendDramExtension(int socketId, tlm_generic_payload &payload) // Check the valid range of decodedAddress if (addressIsValid(decodedAddress)) { DramExtension *extension = new DramExtension(Thread(socketId), - Channel(decodedAddress.channel), Bank(decodedAddress.bank), - BankGroup(decodedAddress.bankgroup), Row(decodedAddress.row), - Column(decodedAddress.column), burstlength); + Channel(decodedAddress.channel), Rank(decodedAddress.rank), + BankGroup(decodedAddress.bankgroup), Bank(decodedAddress.bank), + Row(decodedAddress.row), Column(decodedAddress.column), + burstlength, nextPayloadID[decodedAddress.channel]++); payload.set_auto_extension(extension); } else { SC_REPORT_FATAL("Arbiter", "Decoded Address is not inside the valid range"); } } -bool Arbiter::addressIsValid(DecodedAddress &decodedAddress) +bool Arbiter::addressIsValid(DecodedAddress &decodedAddress) { - if (decodedAddress.channel >= AddressDecoder::getInstance().amount["channel"]) { + if (decodedAddress.channel >= AddressDecoder::getInstance().amount.channel) return false; - } - if (decodedAddress.bank >= AddressDecoder::getInstance().amount["bank"]) { + if (decodedAddress.rank >= AddressDecoder::getInstance().amount.rank) return false; - } - if (decodedAddress.bankgroup > - AddressDecoder::getInstance().amount["bankgroup"]) { + if (decodedAddress.bankgroup >= AddressDecoder::getInstance().amount.bankgroup) return false; - } - if (decodedAddress.column >= AddressDecoder::getInstance().amount["column"]) { + if (decodedAddress.bank >= AddressDecoder::getInstance().amount.bank) return false; - } - if (decodedAddress.row >= AddressDecoder::getInstance().amount["row"]) { + if (decodedAddress.row >= AddressDecoder::getInstance().amount.row) + return false; + if (decodedAddress.column >= AddressDecoder::getInstance().amount.column) return false; - } return true; } - -void Arbiter::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); -} diff --git a/DRAMSys/library/src/simulation/Arbiter.h b/DRAMSys/library/src/simulation/Arbiter.h index 672862c8..b8576eda 100644 --- a/DRAMSys/library/src/simulation/Arbiter.h +++ b/DRAMSys/library/src/simulation/Arbiter.h @@ -48,8 +48,8 @@ #include #include "../common/XmlAddressDecoder.h" #include "../common/dramExtensions.h" -#include "../controller/core/timingCalculations.h" -#include "../controller/core/configuration/ConfigurationLoader.h" +#include "../common/timingCalculations.h" +#include "../configuration/ConfigurationLoader.h" using namespace std; using namespace tlm; @@ -96,10 +96,9 @@ private: const tlm_phase &phase, const sc_time &delay); void appendDramExtension(int socketId, tlm_generic_payload &payload); + std::vector nextPayloadID; bool addressIsValid(DecodedAddress &decodedAddress); - - void printDebugMessage(std::string message); }; #endif // ARBITER_H diff --git a/DRAMSys/library/src/simulation/DRAMSys.cpp b/DRAMSys/library/src/simulation/DRAMSys.cpp index 8ee7792f..f705a6fc 100644 --- a/DRAMSys/library/src/simulation/DRAMSys.cpp +++ b/DRAMSys/library/src/simulation/DRAMSys.cpp @@ -48,22 +48,28 @@ #include "../common/DebugManager.h" #include "../common/XmlAddressDecoder.h" #include "../common/CongenAddressDecoder.h" -#include "../controller/core/ControllerCore.h" -#include "../controller/core/configuration/ConfigurationLoader.h" +#include "../configuration/ConfigurationLoader.h" #include "../common/utils.h" #include "../simulation/TemperatureController.h" -#include "../controller/Controller.h" #include "../error/ecchamming.h" -#include "DramRecordable.h" -#include "DramDDR3.h" -#include "DramDDR4.h" -#include "DramWideIO.h" +#include "dram/DramRecordable.h" +#include "dram/DramDDR3.h" +#include "dram/DramDDR4.h" +#include "dram/DramWideIO.h" +#include "dram/DramLPDDR4.h" +#include "dram/DramWideIO2.h" +#include "dram/DramHBM2.h" +#include "dram/DramGDDR5.h" +#include "dram/DramGDDR5X.h" +#include "dram/DramGDDR6.h" +#include "../controller/Controller.h" +#include "../controller/ControllerRecordable.h" using namespace std; -DRAMSys::DRAMSys(sc_module_name __attribute__((unused)) name, +DRAMSys::DRAMSys(sc_module_name name, string simulationToRun, - string pathToResources) : tSocket("DRAMSys_tSocket") + string pathToResources) : sc_module(name), tSocket("DRAMSys_tSocket") { // Initialize ecc pointer ecc = nullptr; @@ -77,6 +83,7 @@ DRAMSys::DRAMSys(sc_module_name __attribute__((unused)) name, string simconfig; string thermalconfig; + // TODO: Setup never used? Setup setup(simulationToRun, memspec, mcconfig, @@ -86,10 +93,28 @@ DRAMSys::DRAMSys(sc_module_name __attribute__((unused)) name, Configuration::getInstance().setPathToResources(pathToResources); - // The xmlAddressDecoder MUST be initialized before calling the - // ConfigurationLoader because some information from the xmlAddressDecoder - // is needed to assure the coherence of the configuration. + // Load config and initialize modules + ConfigurationLoader::loadMemSpec(Configuration::getInstance(), + pathToResources + + "configs/memspecs/" + + memspec); + ConfigurationLoader::loadMCConfig(Configuration::getInstance(), + pathToResources + + "configs/mcconfigs/" + + mcconfig); + + ConfigurationLoader::loadSimConfig(Configuration::getInstance(), + pathToResources + + "configs/simulator/" + + simconfig); + + ConfigurationLoader::loadTemperatureSimConfig(Configuration::getInstance(), + pathToResources + + "configs/thermalsim/" + + thermalconfig); + + // Load addressmapping if (XmlAddressDecoder::testConfigFile(pathToResources + "configs/amconfigs/" + amconfig)) { AddressDecoder::createInstance(AddressDecoder::Type::XML); @@ -108,26 +133,8 @@ DRAMSys::DRAMSys(sc_module_name __attribute__((unused)) name, AddressDecoder::getInstance().print(); - ConfigurationLoader::loadMemSpec(Configuration::getInstance(), - pathToResources - + "configs/memspecs/" - + memspec); - - // Setup the memory controller with the propriate xml file - ConfigurationLoader::loadMCConfig(Configuration::getInstance(), - pathToResources - + "configs/mcconfigs/" - + mcconfig); - - ConfigurationLoader::loadSimConfig(Configuration::getInstance(), - pathToResources - + "configs/simulator/" - + simconfig); - - ConfigurationLoader::loadTemperatureSimConfig(Configuration::getInstance(), - pathToResources - + "configs/thermalsim/" - + thermalconfig); + // Setup the debug manager: + setupDebugManager(Configuration::getInstance().SimulationName); // If a simulation file is passed as argument to DRAMSys the simulation ID // is prepended to the simulation name if found. @@ -153,9 +160,6 @@ DRAMSys::DRAMSys(sc_module_name __attribute__((unused)) name, // Connect all internal DRAMSys modules: bindSockets(); - // Setup the debug manager: - setupDebugManager(Configuration::getInstance().SimulationName); - report(headline); } @@ -170,19 +174,21 @@ void DRAMSys::logo() cout << REDTXT("=| |= ") << BOLDBLUETXT("University of Kaiserslautern") << endl; cout << REDTXT(" +---+ ") << endl; - cout << REDTXT(" ||| ") << "DRAMSys v3.0" << endl; + cout << REDTXT(" ||| ") << "DRAMSys v4.0" << endl; cout << endl; #undef REDTXT #undef BOLDBLUETXT } -void DRAMSys::setupDebugManager(const string &traceName) +void DRAMSys::setupDebugManager(const string &traceName __attribute__((unused))) { +#ifdef DEBUGGING auto &dbg = DebugManager::getInstance(); dbg.writeToConsole = false; dbg.writeToFile = true; if (dbg.writeToFile) dbg.openDebugFile(traceName + ".txt"); +#endif } void DRAMSys::setupTlmRecorders(const string &traceName, @@ -203,9 +209,7 @@ void DRAMSys::setupTlmRecorders(const string &traceName, std::string recorderName = "tlmRecorder" + std::to_string(i); TlmRecorder *tlmRecorder = - new TlmRecorder(recorderName.c_str(), - sqlScriptURI.c_str(), - dbName.c_str()); + new TlmRecorder(recorderName, sqlScriptURI.c_str(), dbName.c_str()); tlmRecorder->recordMCconfig(Configuration::getInstance().mcconfigUri); tlmRecorder->recordMemspec(Configuration::getInstance().memspecUri); @@ -247,14 +251,13 @@ void DRAMSys::instantiateModules(const string &traceName, // Create DRAM std::string memoryType = Configuration::getInstance().memSpec->MemoryType; - for (size_t i = 0; - i < Configuration::getInstance().NumberOfMemChannels; - i++) { + for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; i++) + { std::string str = "controller" + std::to_string(i); - Controller *controller; + GenericController *controller; if (recordingEnabled) - controller = new RecordableController(str.c_str(), tlmRecorders[i]); + controller = new ControllerRecordable(str.c_str(), tlmRecorders[i]); else controller = new Controller(str.c_str()); controllers.push_back(controller); @@ -269,6 +272,13 @@ void DRAMSys::instantiateModules(const string &traceName, else dram = new DramDDR3(str.c_str()); } + else if (memoryType == "WIDEIO_SDR") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramWideIO(str.c_str()); + } else if (memoryType == "DDR4") { if (recordingEnabled) @@ -276,12 +286,47 @@ void DRAMSys::instantiateModules(const string &traceName, else dram = new DramDDR4(str.c_str()); } - else if (memoryType == "WIDEIO_SDR") + else if (memoryType == "LPDDR4") { if (recordingEnabled) - dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); else - dram = new DramWideIO(str.c_str()); + dram = new DramLPDDR4(str.c_str()); + } + else if (memoryType == "WIDEIO2") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramWideIO2(str.c_str()); + } + else if (memoryType == "HBM2") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramHBM2(str.c_str()); + } + else if (memoryType == "GDDR5") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramGDDR5(str.c_str()); + } + else if (memoryType == "GDDR5X") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramGDDR5X(str.c_str()); + } + else if (memoryType == "GDDR6") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramGDDR6(str.c_str()); } else { @@ -358,6 +403,6 @@ DRAMSys::~DRAMSys() void DRAMSys::report(string message) { - DebugManager::getInstance().printDebugMessage(this->name(), message); + PRINTDEBUGMESSAGE(name(), message); cout << message << endl; } diff --git a/DRAMSys/library/src/simulation/DRAMSys.h b/DRAMSys/library/src/simulation/DRAMSys.h index 288820e8..354241f0 100644 --- a/DRAMSys/library/src/simulation/DRAMSys.h +++ b/DRAMSys/library/src/simulation/DRAMSys.h @@ -42,16 +42,17 @@ #include #include -#include "RecordableDram.h" +#include "dram/Dram.h" #include "Arbiter.h" #include "TraceGenerator.h" #include "ReorderBuffer.h" #include #include -#include "../controller/RecordableController.h" #include "../common/third_party/tinyxml2/tinyxml2.h" #include "../common/tlm2_base_protocol_checker.h" #include "../error/eccbaseclass.h" +#include "../controller/GenericController.h" +#include "../common/TlmRecorder.h" class DRAMSys : public sc_module { @@ -72,7 +73,6 @@ public: void logo(); - private: std::string traceName; @@ -87,7 +87,8 @@ private: // All transactions pass through the same arbiter Arbiter *arbiter; // Each DRAM unit has a controller - std::vector controllers; + std::vector controllers; + //std::vector controllers; // TODO: Each DRAM has a reorder buffer (check this!) ReorderBuffer *reorder; diff --git a/DRAMSys/library/src/simulation/Dram.cpp b/DRAMSys/library/src/simulation/Dram.cpp deleted file mode 100644 index cc391efc..00000000 --- a/DRAMSys/library/src/simulation/Dram.cpp +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright (c) 2015, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Peter Ehses - * Eder F. Zulian - * Felipe S. Prado - */ - -#include "Dram.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../common/DebugManager.h" -#include "../common/dramExtensions.h" -#include "../controller/Controller.h" -#include "../controller/core/timingCalculations.h" -#include "../controller/core/configuration/Configuration.h" -#include "../common/protocol.h" -#include "../common/utils.h" -#include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" - -using namespace std; -using namespace tlm; -using namespace Data; - -Dram::Dram(sc_module_name) : tSocket("socket") -{ - // Adjust number of bytes per burst dynamically to the selected ecc controller - bytesPerBurst = Configuration::getInstance() - .adjustNumBytesAfterECC(bytesPerBurst); - - tSocket.register_nb_transport_fw(this, &Dram::nb_transport_fw); - tSocket.register_transport_dbg(this, &Dram::transport_dbg); - - // Parameters for DRAMPower - sc_time clk = Configuration::getInstance().memSpec->clk; - - MemArchitectureSpec memArchSpec; - memArchSpec.burstLength = - Configuration::getInstance().memSpec->BurstLength; - memArchSpec.dataRate = Configuration::getInstance().memSpec->DataRate; - memArchSpec.nbrOfRows = - Configuration::getInstance().memSpec->NumberOfRows; - memArchSpec.nbrOfBanks = - Configuration::getInstance().memSpec->NumberOfBanks; - memArchSpec.nbrOfColumns = - Configuration::getInstance().memSpec->NumberOfColumns; - memArchSpec.nbrOfRanks = - Configuration::getInstance().memSpec->NumberOfRanks; - memArchSpec.width = Configuration::getInstance().memSpec->bitWidth; - memArchSpec.nbrOfBankGroups = - Configuration::getInstance().memSpec->NumberOfBankGroups; - memArchSpec.twoVoltageDomains = (Configuration::getInstance().memSpec->vDD2 == 0 - ? false : true); - memArchSpec.dll = Configuration::getInstance().memSpec->DLL; - - MemTimingSpec memTimingSpec; - memTimingSpec.FAWB = Configuration::getInstance().tfawbclk; - memTimingSpec.RASB = Configuration::getInstance().trasbclk; - memTimingSpec.RCB = Configuration::getInstance().trcbclk; - memTimingSpec.RPB = Configuration::getInstance().trpbclk; - memTimingSpec.RRDB = Configuration::getInstance().trrdblclk; - memTimingSpec.RRDB_L = Configuration::getInstance().trrdblclk; - memTimingSpec.RRDB_S = Configuration::getInstance().trrdblclk; - memTimingSpec.AL = Configuration::getInstance().memSpec->tAL / clk; - memTimingSpec.CCD = Configuration::getInstance().memSpec->tCCD_S / clk; - memTimingSpec.CCD_L = Configuration::getInstance().memSpec->tCCD_L / clk; - memTimingSpec.CCD_S = Configuration::getInstance().memSpec->tCCD_S / clk; - memTimingSpec.CKE = Configuration::getInstance().memSpec->tCKE / clk; - memTimingSpec.CKESR = Configuration::getInstance().memSpec->tCKESR / clk; - memTimingSpec.clkMhz = Configuration::getInstance().memSpec->clkMHz; - // See also MemTimingSpec.cc in DRAMPower - memTimingSpec.clkPeriod = 1000.0 / Configuration::getInstance().memSpec->clkMHz; - memTimingSpec.DQSCK = Configuration::getInstance().memSpec->tDQSCK / clk; - memTimingSpec.FAW = Configuration::getInstance().memSpec->tNAW / clk; - memTimingSpec.RAS = Configuration::getInstance().memSpec->tRAS / clk; - memTimingSpec.RC = Configuration::getInstance().memSpec->tRC / clk; - memTimingSpec.RCD = Configuration::getInstance().memSpec->tRCD / clk; - memTimingSpec.REFI = Configuration::getInstance().memSpec->tREFI / clk; - auto m = Configuration::getInstance().getRefMode(); - if (m == 4) - memTimingSpec.RFC = Configuration::getInstance().memSpec->tRFC4 / clk; - else if (m == 2) - memTimingSpec.RFC = Configuration::getInstance().memSpec->tRFC2 / clk; - else - memTimingSpec.RFC = Configuration::getInstance().memSpec->tRFC / clk; - memTimingSpec.RL = Configuration::getInstance().memSpec->tRL / clk; - memTimingSpec.RP = Configuration::getInstance().memSpec->tRP / clk; - memTimingSpec.RRD = Configuration::getInstance().memSpec->tRRD_S / clk; - memTimingSpec.RRD_L = Configuration::getInstance().memSpec->tRRD_L / clk; - memTimingSpec.RRD_S = Configuration::getInstance().memSpec->tRRD_S / clk; - memTimingSpec.RTP = Configuration::getInstance().memSpec->tRTP / clk; - memTimingSpec.TAW = Configuration::getInstance().memSpec->tNAW / clk; - memTimingSpec.WL = Configuration::getInstance().memSpec->tWL / clk; - memTimingSpec.WR = Configuration::getInstance().memSpec->tWR / clk; - memTimingSpec.WTR = Configuration::getInstance().memSpec->tWTR_S / clk; - memTimingSpec.WTR_L = Configuration::getInstance().memSpec->tWTR_L / clk; - memTimingSpec.WTR_S = Configuration::getInstance().memSpec->tWTR_S / clk; - memTimingSpec.XP = Configuration::getInstance().memSpec->tXP / clk; - memTimingSpec.XPDLL = Configuration::getInstance().memSpec->tXPDLL / clk; - memTimingSpec.XS = Configuration::getInstance().memSpec->tXSR / clk; - memTimingSpec.XSDLL = Configuration::getInstance().memSpec->tXSRDLL / clk; - - MemPowerSpec memPowerSpec; - memPowerSpec.idd0 = Configuration::getInstance().memSpec->iDD0; - memPowerSpec.idd02 = Configuration::getInstance().memSpec->iDD02; - memPowerSpec.idd2p0 = Configuration::getInstance().memSpec->iDD2P0; - memPowerSpec.idd2p02 = Configuration::getInstance().memSpec->iDD2P02; - memPowerSpec.idd2p1 = Configuration::getInstance().memSpec->iDD2P1; - memPowerSpec.idd2p12 = Configuration::getInstance().memSpec->iDD2P12; - memPowerSpec.idd2n = Configuration::getInstance().memSpec->iDD2N; - memPowerSpec.idd2n2 = Configuration::getInstance().memSpec->iDD2N2; - memPowerSpec.idd3p0 = Configuration::getInstance().memSpec->iDD3P0; - memPowerSpec.idd3p02 = Configuration::getInstance().memSpec->iDD3P02; - memPowerSpec.idd3p1 = Configuration::getInstance().memSpec->iDD3P1; - memPowerSpec.idd3p12 = Configuration::getInstance().memSpec->iDD3P12; - memPowerSpec.idd3n = Configuration::getInstance().memSpec->iDD3N; - memPowerSpec.idd3n2 = Configuration::getInstance().memSpec->iDD3N2; - memPowerSpec.idd4r = Configuration::getInstance().memSpec->iDD4R; - memPowerSpec.idd4r2 = Configuration::getInstance().memSpec->iDD4R2; - memPowerSpec.idd4w = Configuration::getInstance().memSpec->iDD4W; - memPowerSpec.idd4w2 = Configuration::getInstance().memSpec->iDD4W2; - memPowerSpec.idd5 = Configuration::getInstance().memSpec->iDD5; - memPowerSpec.idd52 = Configuration::getInstance().memSpec->iDD52; - memPowerSpec.idd6 = Configuration::getInstance().memSpec->iDD6; - memPowerSpec.idd62 = Configuration::getInstance().memSpec->iDD62; - memPowerSpec.vdd = Configuration::getInstance().memSpec->vDD; - memPowerSpec.vdd2 = Configuration::getInstance().memSpec->vDD2; - - MemorySpecification memSpec; - memSpec.id = Configuration::getInstance().memSpec->MemoryId; - memSpec.memoryType = Configuration::getInstance().memSpec->MemoryType; - memSpec.memTimingSpec = memTimingSpec; - memSpec.memPowerSpec = memPowerSpec; - memSpec.memArchSpec = memArchSpec; - - DRAMPower = new libDRAMPower(memSpec, 0); -} - -Dram::~Dram() -{ - if (!Configuration::getInstance().DatabaseRecording) - DRAMPower->calcEnergy(); - - // Print the final total energy and the average power for - // the simulation: - cout << name() << string(" Total Energy: ") - << fixed << std::setprecision( 2 ) - << DRAMPower->getEnergy().total_energy - * Configuration::getInstance().NumberOfDevicesOnDIMM - << string(" pJ") - << endl; - - cout << name() << string(" Average Power: ") - << fixed << std::setprecision( 2 ) - << DRAMPower->getPower().average_power - * Configuration::getInstance().NumberOfDevicesOnDIMM - << string(" mW") << endl; - - if (Configuration::getInstance().UseMalloc) - free(memory); -} - -tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &delay) -{ - unsigned int bank = DramExtension::getExtension(payload).getBank().ID(); - - // This is only needed for power simulation: - unsigned long long cycle = sc_time_stamp().value() / - Configuration::getInstance().memSpec->clk.value(); - - if (phase == BEGIN_PREB) - { - DRAMPower->doCommand(MemCommand::PREB, bank, cycle); - sendToController(payload, END_PREB, delay + getExecutionTime(Command::PreB, - payload)); - } - else if (phase == BEGIN_PRE) - { - DRAMPower->doCommand(MemCommand::PRE, bank, cycle); - sendToController(payload, END_PRE, delay + getExecutionTime(Command::Precharge, - payload)); - } - else if (phase == BEGIN_PRE_ALL) - { - DRAMPower->doCommand(MemCommand::PREA, bank, cycle); - sendToController(payload, END_PRE_ALL, - delay + getExecutionTime(Command::PrechargeAll, payload)); - } - else if (phase == BEGIN_ACTB) - { - DRAMPower->doCommand(MemCommand::ACTB, bank, cycle); - sendToController(payload, END_ACTB, delay + getExecutionTime(Command::ActB, - payload)); - } - else if (phase == BEGIN_ACT) - { - DRAMPower->doCommand(MemCommand::ACT, bank, cycle); - sendToController(payload, END_ACT, delay + getExecutionTime(Command::Activate, - payload)); - } - else if (phase == BEGIN_WR) - { - DRAMPower->doCommand(MemCommand::WR, bank, cycle); - // save data: - if (StoreMode == StorageMode::Store) // Use Storage - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); - } - sendToController(payload, END_WR, delay + getExecutionTime(Command::Write, - payload)); - } - else if (phase == BEGIN_RD) - { - DRAMPower->doCommand(MemCommand::RD, bank, cycle); - // load data: - if (StoreMode == StorageMode::Store) // use StorageMode - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); - } - sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, - payload)); - } - else if (phase == BEGIN_WRA) - { - DRAMPower->doCommand(MemCommand::WRA, bank, cycle); - // save data: - if (StoreMode == StorageMode::Store) // Use Storage - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); - } - sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA, - payload)); - } - else if (phase == BEGIN_RDA) - { - DRAMPower->doCommand(MemCommand::RDA, bank, cycle); - // Load data: - if (StoreMode == StorageMode::Store) // use StorageMode - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); - } - sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA, - payload)); - } - else if (phase == BEGIN_REFA) - { - DRAMPower->doCommand(MemCommand::REF, bank, cycle); - sendToController(payload, END_REFA, - delay + getExecutionTime(Command::AutoRefresh, payload)); - } - else if (phase == BEGIN_REFB) - { - DRAMPower->doCommand(MemCommand::REFB, bank, cycle); - sendToController(payload, END_REFB, - delay + getExecutionTime(Command::AutoRefresh, payload)); - } - // Powerdown phases have to be started and ended by the controller, because they do not have a fixed length - else if (phase == BEGIN_PDNA) - { - DRAMPower->doCommand(MemCommand::PDN_S_ACT, bank, cycle); - } - else if (phase == END_PDNA) - { - DRAMPower->doCommand(MemCommand::PUP_ACT, bank, cycle); - } - else if (phase == BEGIN_PDNAB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == END_PDNAB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == BEGIN_PDNP) - { - DRAMPower->doCommand(MemCommand::PDN_S_PRE, bank, cycle); - } - else if (phase == END_PDNP) - { - DRAMPower->doCommand(MemCommand::PUP_PRE, bank, cycle); - } - else if (phase == BEGIN_PDNPB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == END_PDNPB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == BEGIN_SREF) - { - DRAMPower->doCommand(MemCommand::SREN, bank, cycle); - } - else if (phase == END_SREF) - { - DRAMPower->doCommand(MemCommand::SREX, bank, cycle); - } - else if (phase == BEGIN_SREFB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == END_SREFB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else - { - SC_REPORT_FATAL("DRAM", "DRAM PEQ was called with unknown phase"); - } - - return TLM_ACCEPTED; -} - -unsigned int Dram::transport_dbg(tlm_generic_payload &trans) -{ - printDebugMessage("transport_dgb"); - - // TODO: This part is not tested yet, neither with traceplayers nor with GEM5 coupling - if (StoreMode == StorageMode::NoStorage) - { - SC_REPORT_FATAL("DRAM", - "Debug Transport is used in combination with NoStorage"); - } - else - { - tlm_command cmd = trans.get_command(); - //sc_dt::uint64 adr = trans.get_address(); // TODO: - offset; - unsigned char *ptr = trans.get_data_ptr(); - unsigned int len = trans.get_data_length(); - //unsigned int bank = DramExtension::getExtension(trans).getBank().ID(); - - //cout << "cmd " << (cmd ? "write" : "read") << " adr " << hex << adr << " len " << len << endl; - - if (cmd == TLM_READ_COMMAND) - { - if (StoreMode == StorageMode::Store) - { // Use Storage - unsigned char *phyAddr = memory + trans.get_address(); - memcpy(ptr, phyAddr, trans.get_data_length()); - } - else - { - //ememory[bank]->load(trans); - SC_REPORT_FATAL("DRAM", "Debug transport not supported with error model yet."); - } - } - else if (cmd == TLM_WRITE_COMMAND) - { - if (StoreMode == StorageMode::Store) - { // Use Storage - unsigned char *phyAddr = memory + trans.get_address(); - memcpy(phyAddr, ptr, trans.get_data_length()); - } - else - { - //ememory[bank]->store(trans); - SC_REPORT_FATAL("DRAM", "Debug transport not supported with error model yet."); - } - } - return len; - } - return 0; -} - -void Dram::sendToController(tlm_generic_payload &payload, const tlm_phase &phase, - const sc_time &delay) -{ - tlm_phase TPhase = phase; - sc_time TDelay = delay; - tSocket->nb_transport_bw(payload, TPhase, TDelay); -} - -void Dram::printDebugMessage(string message) -{ - DebugManager::getInstance().printDebugMessage(name(), message); -} diff --git a/DRAMSys/library/src/simulation/DramWideIO.cpp b/DRAMSys/library/src/simulation/DramWideIO.cpp deleted file mode 100644 index 3f69ca7a..00000000 --- a/DRAMSys/library/src/simulation/DramWideIO.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2019, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Lukas Steiner - */ - -#include "DramWideIO.h" - -#include -#include -#include "Dram.h" -#include "../controller/core/configuration/Configuration.h" -#include "../error/errormodel.h" - -using namespace tlm; - -DramWideIO::DramWideIO(sc_module_name name) : Dram(name) -{ - // For each bank in a channel a error Model is created: - if (StoreMode == StorageMode::ErrorModel) - { - if (Configuration::getInstance().UseMalloc) - free(memory); - - for (unsigned i = 0; i < Configuration::getInstance().memSpec->NumberOfBanks; - i++) - { - errorModel *em; - std::string errorModelStr = "errorModel_bank" + std::to_string(i); - em = new errorModel(errorModelStr.c_str(), DRAMPower); - ememory.push_back(em); - } - } -} - -DramWideIO::~DramWideIO() -{ - // Clean up: - for (auto e : ememory) - delete e; -} - -tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &delay) -{ - unsigned int bank = DramExtension::getExtension(payload).getBank().ID(); - - // This is only needed for power simulation: - unsigned long long cycle = sc_time_stamp().value() / - Configuration::getInstance().memSpec->clk.value(); - - if (phase == BEGIN_PREB) - { - DRAMPower->doCommand(MemCommand::PREB, bank, cycle); - sendToController(payload, END_PREB, delay + getExecutionTime(Command::PreB, - payload)); - } - else if (phase == BEGIN_PRE) - { - DRAMPower->doCommand(MemCommand::PRE, bank, cycle); - sendToController(payload, END_PRE, delay + getExecutionTime(Command::Precharge, - payload)); - } - else if (phase == BEGIN_PRE_ALL) - { - DRAMPower->doCommand(MemCommand::PREA, bank, cycle); - sendToController(payload, END_PRE_ALL, - delay + getExecutionTime(Command::PrechargeAll, payload)); - } - else if (phase == BEGIN_ACTB) - { - DRAMPower->doCommand(MemCommand::ACTB, bank, cycle); - sendToController(payload, END_ACTB, delay + getExecutionTime(Command::ActB, - payload)); - unsigned int row = DramExtension::getExtension(payload).getRow().ID(); - if (StoreMode == StorageMode::ErrorModel) - ememory[bank]->activate(row); - } - else if (phase == BEGIN_ACT) - { - DRAMPower->doCommand(MemCommand::ACT, bank, cycle); - sendToController(payload, END_ACT, delay + getExecutionTime(Command::Activate, - payload)); - unsigned int row = DramExtension::getExtension(payload).getRow().ID(); - - if (StoreMode == StorageMode::ErrorModel) - ememory[bank]->activate(row); - } - else if (phase == BEGIN_WR) - { - DRAMPower->doCommand(MemCommand::WR, bank, cycle); - // save data: - if (StoreMode == StorageMode::Store) // Use Storage - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); - } - else if (StoreMode == StorageMode::ErrorModel) // Use Storage with Error Model - { - ememory[bank]->store(payload); - } - sendToController(payload, END_WR, delay + getExecutionTime(Command::Write, - payload)); - } - else if (phase == BEGIN_RD) - { - DRAMPower->doCommand(MemCommand::RD, bank, cycle); - // load data: - if (StoreMode == StorageMode::Store) // use StorageMode - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); - } - else if (StoreMode == StorageMode::ErrorModel) // use StorageMode with errormodel - { - ememory[bank]->load(payload); - } - sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, - payload)); - } - else if (phase == BEGIN_WRA) - { - DRAMPower->doCommand(MemCommand::WRA, bank, cycle); - // save data: - if (StoreMode == StorageMode::Store) // Use Storage - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); - } - else if (StoreMode == StorageMode::ErrorModel) // Use Storage with Error Model - { - ememory[bank]->store(payload); - } - sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA, - payload)); - } - else if (phase == BEGIN_RDA) - { - DRAMPower->doCommand(MemCommand::RDA, bank, cycle); - // Load data: - if (StoreMode == StorageMode::Store) // use StorageMode - { - unsigned char *phyAddr = memory + payload.get_address(); - memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); - } - else if (StoreMode == StorageMode::ErrorModel) // use StorageMode with errormodel - { - ememory[bank]->load(payload); - } - sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA, - payload)); - } - else if (phase == BEGIN_REFA) - { - DRAMPower->doCommand(MemCommand::REF, bank, cycle); - sendToController(payload, END_REFA, - delay + getExecutionTime(Command::AutoRefresh, payload)); - unsigned int row = DramExtension::getExtension(payload).getRow().ID(); - - if (StoreMode == StorageMode::ErrorModel) - ememory[bank]->refresh(row); - } - else if (phase == BEGIN_REFB) - { - DRAMPower->doCommand(MemCommand::REFB, bank, cycle); - sendToController(payload, END_REFB, - delay + getExecutionTime(Command::AutoRefresh, payload)); - } - // Powerdown phases have to be started and ended by the controller, because they do not have a fixed length - else if (phase == BEGIN_PDNA) - { - DRAMPower->doCommand(MemCommand::PDN_S_ACT, bank, cycle); - } - else if (phase == END_PDNA) - { - DRAMPower->doCommand(MemCommand::PUP_ACT, bank, cycle); - } - else if (phase == BEGIN_PDNAB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == END_PDNAB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == BEGIN_PDNP) - { - DRAMPower->doCommand(MemCommand::PDN_S_PRE, bank, cycle); - } - else if (phase == END_PDNP) - { - DRAMPower->doCommand(MemCommand::PUP_PRE, bank, cycle); - } - else if (phase == BEGIN_PDNPB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == END_PDNPB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == BEGIN_SREF) - { - DRAMPower->doCommand(MemCommand::SREN, bank, cycle); - } - else if (phase == END_SREF) - { - DRAMPower->doCommand(MemCommand::SREX, bank, cycle); - } - else if (phase == BEGIN_SREFB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else if (phase == END_SREFB) - { - SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"); - } - else - { - SC_REPORT_FATAL("DRAM", "DRAM PEQ was called with unknown phase"); - } - - return TLM_ACCEPTED; -} diff --git a/DRAMSys/library/src/simulation/ExampleInitiator.h b/DRAMSys/library/src/simulation/ExampleInitiator.h index 7b227709..45233838 100644 --- a/DRAMSys/library/src/simulation/ExampleInitiator.h +++ b/DRAMSys/library/src/simulation/ExampleInitiator.h @@ -185,7 +185,7 @@ struct ExampleInitiator : sc_module } tlm::tlm_command cmd = trans.get_command(); - sc_dt::uint64 adr = trans.get_address(); + uint64_t adr = trans.get_address(); int *ptr = reinterpret_cast( trans.get_data_ptr() ); cout << hex << adr << " check, cmd=" << (cmd ? "write" : "read") diff --git a/DRAMSys/library/src/simulation/IArbiter.h b/DRAMSys/library/src/simulation/IArbiter.h index 872fd929..1ad91a0e 100644 --- a/DRAMSys/library/src/simulation/IArbiter.h +++ b/DRAMSys/library/src/simulation/IArbiter.h @@ -44,7 +44,7 @@ #include #include #include -#include "../controller/core/configuration/ConfigurationLoader.h" +#include "../configuration/ConfigurationLoader.h" using namespace std; using namespace tlm; @@ -89,11 +89,6 @@ protected: virtual unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans) = 0; - void printDebugMessage(std::string message) - { - DebugManager::getInstance().printDebugMessage(this->name(), message); - } - void appendDramExtension(int socketId, tlm_generic_payload &payload) { // Append Generation Extension @@ -109,7 +104,7 @@ protected: DramExtension *extension = new DramExtension(Thread(socketId + 1), Channel(decodedAddress.channel), Bank(decodedAddress.bank), BankGroup(decodedAddress.bankgroup), Row(decodedAddress.row), - Column(decodedAddress.column), burstlength); + Column(decodedAddress.column), burstlength, 0); payload.set_auto_extension(extension); } else { SC_REPORT_FATAL("Arbiter", "Decoded Address are not inside the valid range"); @@ -119,21 +114,21 @@ protected: bool addressIsValid(DecodedAddress &decodedAddress) { if (decodedAddress.channel >= - XmlAddressDecoder::getInstance().amount["channel"]) { + XmlAddressDecoder::getInstance().amount.channel) { return false; } - if (decodedAddress.bank >= XmlAddressDecoder::getInstance().amount["bank"]) { - return false; - } - if (decodedAddress.bankgroup > - XmlAddressDecoder::getInstance().amount["bankgroup"]) { + if (decodedAddress.bank >= XmlAddressDecoder::getInstance().amount.bank) { return false; } +// if (decodedAddress.bankgroup > +// XmlAddressDecoder::getInstance().amount["bankgroup"]) { +// return false; +// } if (decodedAddress.column >= - XmlAddressDecoder::getInstance().amount["column"]) { + XmlAddressDecoder::getInstance().amount.column) { return false; } - if (decodedAddress.row >= XmlAddressDecoder::getInstance().amount["row"]) { + if (decodedAddress.row >= XmlAddressDecoder::getInstance().amount.row) { return false; } return true; diff --git a/DRAMSys/library/src/simulation/MemoryManager.cpp b/DRAMSys/library/src/simulation/MemoryManager.cpp index 0094a9b4..f5dee080 100644 --- a/DRAMSys/library/src/simulation/MemoryManager.cpp +++ b/DRAMSys/library/src/simulation/MemoryManager.cpp @@ -36,7 +36,7 @@ #include "MemoryManager.h" #include "../common/DebugManager.h" -#include "../controller/core/configuration/Configuration.h" +#include "../configuration/Configuration.h" #include using namespace std; @@ -54,10 +54,9 @@ MemoryManager::~MemoryManager() numberOfFrees++; } - DebugManager::getInstance().printDebugMessage("MemoryManager", - "Number of allocated payloads: " + to_string(numberOfAllocations)); - DebugManager::getInstance().printDebugMessage("MemoryManager", - "Number of freed payloads: " + to_string(numberOfFrees)); + // Comment in if you are suspecting a memory leak in the manager + //PRINTDEBUGMESSAGE("MemoryManager","Number of allocated payloads: " + to_string(numberOfAllocations)); + //PRINTDEBUGMESSAGE("MemoryManager","Number of freed payloads: " + to_string(numberOfFrees)); } gp *MemoryManager::allocate() @@ -82,7 +81,7 @@ gp *MemoryManager::allocate() void MemoryManager::free(gp *payload) { - payload->reset(); //clears all extensions + payload->reset(); // clears all extensions freePayloads.push_back(payload); } diff --git a/DRAMSys/library/src/simulation/RecordableDram.cpp b/DRAMSys/library/src/simulation/RecordableDram.cpp deleted file mode 100644 index 699f0a74..00000000 --- a/DRAMSys/library/src/simulation/RecordableDram.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2018, University of Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Felipe S. Prado - * Matthias Jung - */ - -#include "RecordableDram.h" - -using namespace tlm; - -RecordableDram::RecordableDram(sc_module_name name, TlmRecorder *tlmRecorder) - : Dram(name), tlmRecorder(tlmRecorder) -{ - // Create a thread that is triggered every $powerWindowSize - // to generate a Power over Time plot in the Trace analyzer: - if (Configuration::getInstance().PowerAnalysis - && Configuration::getInstance().EnableWindowing) - SC_THREAD(powerWindow); -} - -RecordableDram::~RecordableDram() -{ - if (Configuration::getInstance().PowerAnalysis) - { - // Obtain the residual energy which was not covered by - // previous windows - DRAMPower->calcEnergy(); - recordPower(); - } - tlmRecorder->closeConnection(); -} - - -tlm_sync_enum RecordableDram::nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &delay) -{ - // Recording time used by the traceAnalyzer - sc_time recTime = sc_time_stamp() + delay; - - // These are terminating phases recorded by the DRAM. The execution - // time of the related command must be taken into consideration. - if (phase == END_PDNA || phase == END_PDNAB) { - recTime += getExecutionTime(Command::PDNAX, payload); - } else if (phase == END_PDNP || phase == END_PDNPB) { - recTime += getExecutionTime(Command::PDNPX, payload); - } else if (phase == END_SREF || phase == END_SREFB) { - recTime += getExecutionTime(Command::SREFX, payload); - } - - unsigned int thr = DramExtension::getExtension(payload).getThread().ID(); - unsigned int ch = DramExtension::getExtension(payload).getChannel().ID(); - unsigned int bg = DramExtension::getExtension(payload).getBankGroup().ID(); - unsigned int bank = DramExtension::getExtension(payload).getBank().ID(); - unsigned int row = DramExtension::getExtension(payload).getRow().ID(); - unsigned int col = DramExtension::getExtension(payload).getColumn().ID(); - - printDebugMessage("Recording " + phaseNameToString(phase) + " thread " + - to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string( - bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " + - to_string(col) + " at " + recTime.to_string()); - - tlmRecorder->recordPhase(payload, phase, recTime); - - return Dram::nb_transport_fw(payload, phase, delay); -} - -// This Thread is only triggered when Power Simulation is enabled. -// It estimates the current average power which will be stored in the trace database for visualization purposes. -void RecordableDram::powerWindow() -{ - unsigned long long clkCycles = 0; - - do { - // At the very beginning (zero clock cycles) the energy is 0, so we wait first - wait(powerWindowSize); - - clkCycles = sc_time_stamp().value() / - Configuration::getInstance().memSpec->clk.value(); - - DRAMPower->calcWindowEnergy(clkCycles); - - // During operation the energy should never be zero since the device is always consuming - assert(!isEqual(DRAMPower->getEnergy().window_energy, 0.0)); - - // Store the time (in seconds) and the current average power (in mW) into the database - recordPower(); - - // Here considering that DRAMPower provides the energy in pJ and the power in mW - printDebugMessage(string("\tWindow Energy: \t") + to_string( - DRAMPower->getEnergy().window_energy * - Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[pJ]")); - printDebugMessage(string("\tWindow Average Power: \t") + to_string( - DRAMPower->getPower().window_average_power * - Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[mW]")); - - } while (true); -} - -void RecordableDram::recordPower() -{ - tlmRecorder->recordPower(sc_time_stamp().to_seconds(), - DRAMPower->getPower().window_average_power - * Configuration::getInstance().NumberOfDevicesOnDIMM); -} - diff --git a/DRAMSys/library/src/simulation/StlPlayer.h b/DRAMSys/library/src/simulation/StlPlayer.h index dae8e4ab..e45e1233 100644 --- a/DRAMSys/library/src/simulation/StlPlayer.h +++ b/DRAMSys/library/src/simulation/StlPlayer.h @@ -50,11 +50,11 @@ template class StlPlayer : public TracePlayer { public: - StlPlayer(sc_module_name /*name*/, + StlPlayer(sc_module_name name, string pathToTrace, sc_time playerClk, TracePlayerListener *listener) : - TracePlayer(listener), + TracePlayer(name, listener), file(pathToTrace) { if (!file.is_open()) @@ -89,6 +89,7 @@ public: } // Allocate a generic payload for this request. gp *payload = this->allocatePayload(); + payload->acquire(); unsigned char *data = payload->get_data_ptr(); // Trace files MUST provide timestamp, command and address for every @@ -165,14 +166,16 @@ public: payload->set_data_ptr(data); payload->set_command(cmd); - if (relative == false) { + if (relative == false) + { // Send the transaction directly or schedule it to be sent in the future. if (sendingTime <= sc_time_stamp()) this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME); else this->payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp()); - } else + } + else payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime); } diff --git a/DRAMSys/library/src/simulation/TemperatureController.cpp b/DRAMSys/library/src/simulation/TemperatureController.cpp index 2e183a77..04fb716d 100644 --- a/DRAMSys/library/src/simulation/TemperatureController.cpp +++ b/DRAMSys/library/src/simulation/TemperatureController.cpp @@ -37,7 +37,7 @@ #include #include "TemperatureController.h" -#include "../controller/core/configuration/Configuration.h" +#include "../configuration/Configuration.h" double TemperatureController::temperatureConvert(double tKelvin) { @@ -52,7 +52,7 @@ double TemperatureController::temperatureConvert(double tKelvin) double TemperatureController::getTemperature(int deviceId, float currentPower) { - printDebugMessage("Temperature requested by device " + std::to_string( + PRINTDEBUGMESSAGE(name(), "Temperature requested by device " + std::to_string( deviceId) + " current power is " + std::to_string(currentPower)); if (dynamicTempSimEnabled == true) { @@ -66,7 +66,7 @@ double TemperatureController::getTemperature(int deviceId, float currentPower) return temperatureConvert(temperatureValues.at(deviceId)); } else { - printDebugMessage("Temperature is " + std::to_string(staticTemperature)); + PRINTDEBUGMESSAGE(name(), "Temperature is " + std::to_string(staticTemperature)); return staticTemperature; } } @@ -139,7 +139,7 @@ double TemperatureController::adjustThermalSimPeriod() period = period / periodAdjustFactor; cyclesSinceLastPeriodAdjust = 0; decreaseSimPeriod = false; - printDebugMessage("Thermal Simulation period reduced to " + std::to_string( + PRINTDEBUGMESSAGE(name(), "Thermal Simulation period reduced to " + std::to_string( period) + ". Target is " + std::to_string(targetPeriod)); } else { if (period != targetPeriod) { @@ -149,8 +149,8 @@ double TemperatureController::adjustThermalSimPeriod() period = period * (periodAdjustFactor / 2); if (period > targetPeriod) period = targetPeriod; - printDebugMessage("Thermal Simulation period increased to " + std::to_string( - period) + ". Target is " + std::to_string(targetPeriod)); + PRINTDEBUGMESSAGE(name(), "Thermal Simulation period increased to " + + std::to_string(period) + ". Target is " + std::to_string(targetPeriod)); } } } @@ -164,19 +164,13 @@ void TemperatureController::temperatureThread() updateTemperatures(); double p = adjustThermalSimPeriod(); - int i = 0; - for (auto t : temperatureValues) { - printDebugMessage("Temperature[" + std::to_string(i++) + "] is " + - std::to_string(t)); + int i __attribute__((unused)) = 0; + for (auto t __attribute__((unused)) : temperatureValues) { + PRINTDEBUGMESSAGE(name(), "Temperature[" + std::to_string(i++) + + "] is " + std::to_string(t)); } - printDebugMessage("Thermal simulation period is " + std::to_string(p)); + PRINTDEBUGMESSAGE(name(), "Thermal simulation period is " + std::to_string(p)); wait(sc_time(p, t_unit)); } } - -void TemperatureController::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(name(), message); -} - diff --git a/DRAMSys/library/src/simulation/TemperatureController.h b/DRAMSys/library/src/simulation/TemperatureController.h index 8d91d56a..aeb02e00 100644 --- a/DRAMSys/library/src/simulation/TemperatureController.h +++ b/DRAMSys/library/src/simulation/TemperatureController.h @@ -44,7 +44,7 @@ #include "../common/DebugManager.h" #include "../common/utils.h" -#include "../controller/core/configuration/Configuration.h" +#include "../configuration/Configuration.h" #ifdef THERMALSIM #include "IceWrapper.h" @@ -72,8 +72,8 @@ public: std::string ip = Configuration::getInstance().temperatureSim.IceServerIp; unsigned int port = Configuration::getInstance().temperatureSim.IceServerPort; thermalSimulation = new IceWrapper(ip, port); - printDebugMessage("Dynamic temperature simulation. Server @ " + ip + ":" + - std::to_string(port)); + PRINTDEBUGMESSAGE(name(), "Dynamic temperature simulation. Server @ " + + ip + ":" + std::to_string(port)); #else SC_REPORT_FATAL(name(), "DRAMSys was build without support to dynamic temperature simulation. Check the README file for further details."); @@ -107,7 +107,7 @@ public: SC_THREAD(temperatureThread); } else { - printDebugMessage("Static temperature simulation. Temperature set to " + + PRINTDEBUGMESSAGE(name(), "Static temperature simulation. Temperature set to " + std::to_string(staticTemperature)); } } @@ -148,8 +148,6 @@ private: std::string temperatureMapFile; bool genPowerMap; std::string powerMapFile; - - void printDebugMessage(std::string message); }; #endif // TEMPERATURECONTROLLER_H diff --git a/DRAMSys/library/src/simulation/TraceGenerator.h b/DRAMSys/library/src/simulation/TraceGenerator.h index c6e5cd12..4631c5a9 100644 --- a/DRAMSys/library/src/simulation/TraceGenerator.h +++ b/DRAMSys/library/src/simulation/TraceGenerator.h @@ -46,8 +46,8 @@ using namespace tlm; struct TraceGenerator : public TracePlayer { public: - TraceGenerator(sc_module_name /*name*/, unsigned int clkMhz, - TracePlayerListener *listener) : TracePlayer(listener), transCounter(0) + TraceGenerator(sc_module_name name, unsigned int clkMhz, TracePlayerListener *listener) + : TracePlayer(name, listener), transCounter(0) { if (clkMhz == 0) clk = Configuration::getInstance().memSpec->clk; @@ -64,7 +64,7 @@ public: } gp *payload = this->allocatePayload(); - + payload->acquire(); unsigned char *dataElement = new unsigned char[16]; // TODO: column / burst breite diff --git a/DRAMSys/library/src/simulation/TracePlayer.cpp b/DRAMSys/library/src/simulation/TracePlayer.cpp index 793dd904..f9aa8fb6 100644 --- a/DRAMSys/library/src/simulation/TracePlayer.cpp +++ b/DRAMSys/library/src/simulation/TracePlayer.cpp @@ -38,7 +38,8 @@ #include "TracePlayer.h" -TracePlayer::TracePlayer(TracePlayerListener *listener) : +TracePlayer::TracePlayer(sc_module_name name, TracePlayerListener *listener) : + sc_module(name), payloadEventQueue(this, &TracePlayer::peqCallback), numberOfTransactions(0), transactionsSent(0), @@ -65,11 +66,6 @@ void TracePlayer::terminate() listener->tracePlayerTerminates(); } -void TracePlayer::printDebugMessage(std::string message) -{ - DebugManager::getInstance().printDebugMessage(this->name(), message); -} - tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay) { @@ -81,17 +77,14 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase) { if (phase == BEGIN_REQ) { - payload.acquire(); sendToTarget(payload, phase, SC_ZERO_TIME); - transactionsSent++; - DebugManager::getInstance().printDebugMessage(name(), - "Performing request #" + std::to_string(transactionsSent)); + PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent)); } else if (phase == END_REQ) { nextPayload(); } else if (phase == BEGIN_RESP) { - sendToTarget(payload, END_RESP, SC_ZERO_TIME); payload.release(); + sendToTarget(payload, END_RESP, SC_ZERO_TIME); if (Configuration::getInstance().SimulationProgressBar) listener->transactionFinished(); diff --git a/DRAMSys/library/src/simulation/TracePlayer.h b/DRAMSys/library/src/simulation/TracePlayer.h index fbc2e004..b866e5ce 100644 --- a/DRAMSys/library/src/simulation/TracePlayer.h +++ b/DRAMSys/library/src/simulation/TracePlayer.h @@ -47,10 +47,10 @@ #include #include #include "MemoryManager.h" -#include "../controller/core/configuration/Configuration.h" +#include "../configuration/Configuration.h" #include "../common/DebugManager.h" #include "../common/XmlAddressDecoder.h" -#include "../controller/core/timingCalculations.h" +#include "../common/timingCalculations.h" #include "TracePlayerListener.h" using namespace std; @@ -60,7 +60,7 @@ struct TracePlayer : public sc_module { public: tlm_utils::simple_initiator_socket iSocket; - TracePlayer(TracePlayerListener *listener); + TracePlayer(sc_module_name name, TracePlayerListener *listener); virtual void nextPayload() = 0; unsigned int getNumberOfLines(string pathToTrace); @@ -69,7 +69,6 @@ protected: tlm_utils::peq_with_cb_and_phase payloadEventQueue; void finish(); void terminate(); - void printDebugMessage(std::string message); void setNumberOfTransactions(unsigned int n); unsigned int numberOfTransactions; diff --git a/DRAMSys/library/src/simulation/dram/Dram.cpp b/DRAMSys/library/src/simulation/dram/Dram.cpp new file mode 100644 index 00000000..b23e9c58 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/Dram.cpp @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2015, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Robert Gernhardt + * Matthias Jung + * Peter Ehses + * Eder F. Zulian + * Felipe S. Prado + */ + +#include "Dram.h" + +#ifdef _WIN32 + #include +#else + #include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../common/DebugManager.h" +#include "../../common/dramExtensions.h" +#include "../../common/timingCalculations.h" +#include "../../configuration/Configuration.h" +#include "../../common/protocol.h" +#include "../../common/utils.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../common/third_party/DRAMPower/src/MemCommand.h" + +using namespace tlm; +using namespace DRAMPower; + +Dram::Dram(sc_module_name name) : sc_module(name), tSocket("socket") +{ + // Adjust number of bytes per burst dynamically to the selected ecc controller + // TODO: ECC only used for WideIO? + bytesPerBurst = Configuration::getInstance().adjustNumBytesAfterECC(bytesPerBurst); + + uint64_t memorySize = Configuration::getInstance().getSimMemSizeInBytes(); + if (StoreMode == StorageMode::Store) + { + if (Configuration::getInstance().UseMalloc) + { + memory = (unsigned char *)malloc(memorySize); + if (!memory) + SC_REPORT_FATAL(this->name(), "Memory allocation failed"); + } + else + { + // allocate and model storage of one DRAM channel using memory map + #ifdef _WIN32 + SC_REPORT_FATAL("Dram", "On Windows Storage is not yet supported"); + memory = 0; // FIXME + #else + memory = (unsigned char *)mmap(NULL, memorySize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); + #endif + } + } + + tSocket.register_nb_transport_fw(this, &Dram::nb_transport_fw); + tSocket.register_transport_dbg(this, &Dram::transport_dbg); +} + +Dram::~Dram() +{ + if (Configuration::getInstance().PowerAnalysis) + { + libDRAMPower *DRAMPower = dynamic_cast(this->DRAMPower); + if (DRAMPower == nullptr) + SC_REPORT_FATAL("Dram", "Power Analysis active but libDRAMPowerIF instantiated"); + + if (!Configuration::getInstance().DatabaseRecording) + DRAMPower->calcEnergy(); + + // Print the final total energy and the average power for + // the simulation: + std::cout << name() << std::string(" Total Energy: ") + << std::fixed << std::setprecision( 2 ) + << DRAMPower->getEnergy().total_energy + * Configuration::getInstance().NumberOfDevicesOnDIMM + << std::string(" pJ") + << std::endl; + + std::cout << name() << std::string(" Average Power: ") + << std::fixed << std::setprecision( 2 ) + << DRAMPower->getPower().average_power + * Configuration::getInstance().NumberOfDevicesOnDIMM + << std::string(" mW") << std::endl; + } + delete DRAMPower; + + if (Configuration::getInstance().UseMalloc) + free(memory); +} + +tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload, + tlm_phase &phase, sc_time &delay) +{ + unsigned int bank = DramExtension::getExtension(payload).getBank().ID(); + + // This is only needed for power simulation: + unsigned long long cycle = sc_time_stamp().value() / memSpec->clk.value(); + + if (phase == BEGIN_PRE) + { + DRAMPower->doCommand(MemCommand::PRE, bank, cycle); + sendToController(payload, END_PRE, delay + memSpec->getExecutionTime(Command::PRE, payload)); + } + else if (phase == BEGIN_PREA) + { + DRAMPower->doCommand(MemCommand::PREA, bank, cycle); + sendToController(payload, END_PREA, + delay + memSpec->getExecutionTime(Command::PREA, payload)); + } + else if (phase == BEGIN_ACT) + { + DRAMPower->doCommand(MemCommand::ACT, bank, cycle); + sendToController(payload, END_ACT, delay + memSpec->getExecutionTime(Command::ACT, payload)); + } + else if (phase == BEGIN_WR) + { + DRAMPower->doCommand(MemCommand::WR, bank, cycle); + // save data: + if (StoreMode == StorageMode::Store) // Use Storage + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); + } + sendToController(payload, END_WR, delay + memSpec->getExecutionTime(Command::WR, payload)); + } + else if (phase == BEGIN_RD) + { + DRAMPower->doCommand(MemCommand::RD, bank, cycle); + // load data: + if (StoreMode == StorageMode::Store) // use StorageMode + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); + } + sendToController(payload, END_RD, delay + memSpec->getExecutionTime(Command::RD, payload)); + } + else if (phase == BEGIN_WRA) + { + DRAMPower->doCommand(MemCommand::WRA, bank, cycle); + // save data: + if (StoreMode == StorageMode::Store) // Use Storage + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); + } + sendToController(payload, END_WRA, delay + memSpec->getExecutionTime(Command::WRA, payload)); + } + else if (phase == BEGIN_RDA) + { + DRAMPower->doCommand(MemCommand::RDA, bank, cycle); + // Load data: + if (StoreMode == StorageMode::Store) // use StorageMode + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); + } + sendToController(payload, END_RDA, delay + memSpec->getExecutionTime(Command::RDA, payload)); + } + else if (phase == BEGIN_REFA) + { + DRAMPower->doCommand(MemCommand::REF, bank, cycle); + sendToController(payload, END_REFA, + delay + memSpec->getExecutionTime(Command::REFA, payload)); + } + else if (phase == BEGIN_REFB) + { + DRAMPower->doCommand(MemCommand::REFB, bank, cycle); + sendToController(payload, END_REFB, + delay + memSpec->getExecutionTime(Command::REFB, payload)); + } + // Powerdown phases have to be started and ended by the controller, because they do not have a fixed length + else if (phase == BEGIN_PDNA) + { + DRAMPower->doCommand(MemCommand::PDN_S_ACT, bank, cycle); + } + else if (phase == END_PDNA) + { + DRAMPower->doCommand(MemCommand::PUP_ACT, bank, cycle); + } + else if (phase == BEGIN_PDNP) + { + DRAMPower->doCommand(MemCommand::PDN_S_PRE, bank, cycle); + } + else if (phase == END_PDNP) + { + DRAMPower->doCommand(MemCommand::PUP_PRE, bank, cycle); + } + else if (phase == BEGIN_SREF) + { + DRAMPower->doCommand(MemCommand::SREN, bank, cycle); + } + else if (phase == END_SREF) + { + DRAMPower->doCommand(MemCommand::SREX, bank, cycle); + } + else + { + SC_REPORT_FATAL("DRAM", "DRAM PEQ was called with unknown phase"); + } + + return TLM_ACCEPTED; +} + +unsigned int Dram::transport_dbg(tlm_generic_payload &trans) +{ + PRINTDEBUGMESSAGE(name(), "transport_dgb"); + + // TODO: This part is not tested yet, neither with traceplayers nor with GEM5 coupling + if (StoreMode == StorageMode::NoStorage) + { + SC_REPORT_FATAL("DRAM", + "Debug Transport is used in combination with NoStorage"); + } + else + { + tlm_command cmd = trans.get_command(); + //uint64_t adr = trans.get_address(); // TODO: - offset; + unsigned char *ptr = trans.get_data_ptr(); + unsigned int len = trans.get_data_length(); + //unsigned int bank = DramExtension::getExtension(trans).getBank().ID(); + + //cout << "cmd " << (cmd ? "write" : "read") << " adr " << hex << adr << " len " << len << endl; + + if (cmd == TLM_READ_COMMAND) + { + if (StoreMode == StorageMode::Store) + { // Use Storage + unsigned char *phyAddr = memory + trans.get_address(); + memcpy(ptr, phyAddr, trans.get_data_length()); + } + else + { + //ememory[bank]->load(trans); + SC_REPORT_FATAL("DRAM", "Debug transport not supported with error model yet."); + } + } + else if (cmd == TLM_WRITE_COMMAND) + { + if (StoreMode == StorageMode::Store) + { // Use Storage + unsigned char *phyAddr = memory + trans.get_address(); + memcpy(phyAddr, ptr, trans.get_data_length()); + } + else + { + //ememory[bank]->store(trans); + SC_REPORT_FATAL("DRAM", "Debug transport not supported with error model yet."); + } + } + return len; + } + return 0; +} + +void Dram::sendToController(tlm_generic_payload &payload, const tlm_phase &phase, + const sc_time &delay) +{ + tlm_phase TPhase = phase; + sc_time TDelay = delay; + tSocket->nb_transport_bw(payload, TPhase, TDelay); +} diff --git a/DRAMSys/library/src/simulation/Dram.h b/DRAMSys/library/src/simulation/dram/Dram.h similarity index 86% rename from DRAMSys/library/src/simulation/Dram.h rename to DRAMSys/library/src/simulation/dram/Dram.h index 372df02c..e317768c 100644 --- a/DRAMSys/library/src/simulation/Dram.h +++ b/DRAMSys/library/src/simulation/dram/Dram.h @@ -40,31 +40,34 @@ #ifndef DRAM_H #define DRAM_H -#include -#include +#include +#include #include -#include "../controller/Controller.h" -#include "../controller/core/configuration/Configuration.h" -#include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../common/protocol.h" +#include "../../configuration/Configuration.h" +#include "../../configuration/memspec/MemSpec.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" using namespace std; using namespace tlm; -using namespace Data; +using namespace DRAMPower; class Dram : public sc_module { private: unsigned int bytesPerBurst = Configuration::getInstance().getBytesPerBurst(); - // Power Model related - bool powerAnalysis = Configuration::getInstance().PowerAnalysis; - protected: + Dram(sc_module_name); + SC_HAS_PROCESS(Dram); + + MemSpec *memSpec = Configuration::getInstance().memSpec; + // Data Storage: StorageMode StoreMode = Configuration::getInstance().StoreMode; unsigned char *memory; - libDRAMPower *DRAMPower; + libDRAMPowerDummy *DRAMPower; virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &delay); @@ -74,14 +77,9 @@ protected: void sendToController(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay); - void printDebugMessage(string message); - public: tlm_utils::simple_target_socket tSocket; - Dram(sc_module_name); - SC_HAS_PROCESS(Dram); - virtual ~Dram(); }; diff --git a/DRAMSys/library/src/simulation/dram/DramDDR3.cpp b/DRAMSys/library/src/simulation/dram/DramDDR3.cpp new file mode 100644 index 00000000..bcdb03eb --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramDDR3.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramDDR3.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecDDR3.h" + +DramDDR3::DramDDR3(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramDDR3", "Error Model not supported for DDR3"); + + // Parameters for DRAMPower + MemSpecDDR3 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramDDR3", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + { + sc_time clk = memSpec->clk; + + MemArchitectureSpec memArchSpec; + memArchSpec.burstLength = memSpec->BurstLength; + memArchSpec.dataRate = memSpec->DataRate; + memArchSpec.nbrOfRows = memSpec->NumberOfRows; + memArchSpec.nbrOfBanks = memSpec->NumberOfBanks; + memArchSpec.nbrOfColumns = memSpec->NumberOfColumns; + memArchSpec.nbrOfRanks = memSpec->NumberOfRanks; + memArchSpec.width = memSpec->bitWidth; + memArchSpec.nbrOfBankGroups = memSpec->NumberOfBankGroups; + memArchSpec.twoVoltageDomains = false; + memArchSpec.dll = true; + + MemTimingSpec memTimingSpec; + //FIXME: memTimingSpec.FAWB = memSpec->tFAW / clk; + //FIXME: memTimingSpec.RASB = memSpec->tRAS / clk; + //FIXME: memTimingSpec.RCB = memSpec->tRC / clk; + //FIXME: memTimingSpec.RPB = memSpec->tRP / clk; + //FIXME: memTimingSpec.RRDB = memSpec->tRRD / clk; + //FIXME: memTimingSpec.RRDB_L = memSpec->tRRD / clk; + //FIXME: memTimingSpec.RRDB_S = memSpec->tRRD / clk; + memTimingSpec.AL = memSpec->tAL / clk; + memTimingSpec.CCD = memSpec->tCCD / clk; + memTimingSpec.CCD_L = memSpec->tCCD / clk; + memTimingSpec.CCD_S = memSpec->tCCD / clk; + memTimingSpec.CKE = memSpec->tCKE / clk; + memTimingSpec.CKESR = memSpec->tCKESR / clk; + memTimingSpec.clkMhz = memSpec->clkMHz; + // See also MemTimingSpec.cc in DRAMPower + memTimingSpec.clkPeriod = 1000.0 / memSpec->clkMHz; + memTimingSpec.DQSCK = memSpec->tDQSCK / clk; + memTimingSpec.FAW = memSpec->tFAW / clk; + memTimingSpec.RAS = memSpec->tRAS / clk; + memTimingSpec.RC = memSpec->tRC / clk; + memTimingSpec.RCD = memSpec->tRCD / clk; + memTimingSpec.REFI = memSpec->tREFI / clk; + memTimingSpec.RFC = memSpec->tRFC / clk; + memTimingSpec.RL = memSpec->tRL / clk; + memTimingSpec.RP = memSpec->tRP / clk; + memTimingSpec.RRD = memSpec->tRRD / clk; + memTimingSpec.RRD_L = memSpec->tRRD / clk; + memTimingSpec.RRD_S = memSpec->tRRD / clk; + memTimingSpec.RTP = memSpec->tRTP / clk; + memTimingSpec.TAW = memSpec->tFAW / clk; + memTimingSpec.WL = memSpec->tWL / clk; + memTimingSpec.WR = memSpec->tWR / clk; + memTimingSpec.WTR = memSpec->tWTR / clk; + memTimingSpec.WTR_L = memSpec->tWTR / clk; + memTimingSpec.WTR_S = memSpec->tWTR / clk; + memTimingSpec.XP = memSpec->tXP / clk; + memTimingSpec.XPDLL = memSpec->tXPDLL / clk; + memTimingSpec.XS = memSpec->tXS / clk; + memTimingSpec.XSDLL = memSpec->tXSDLL / clk; + + MemPowerSpec memPowerSpec; + memPowerSpec.idd0 = memSpec->iDD0; + memPowerSpec.idd02 = 0; + memPowerSpec.idd2p0 = memSpec->iDD2P0; + memPowerSpec.idd2p02 = 0; + memPowerSpec.idd2p1 = memSpec->iDD2P1; + memPowerSpec.idd2p12 = 0; + memPowerSpec.idd2n = memSpec->iDD2N; + memPowerSpec.idd2n2 = 0; + memPowerSpec.idd3p0 = memSpec->iDD3P0; + memPowerSpec.idd3p02 = 0; + memPowerSpec.idd3p1 = memSpec->iDD3P1; + memPowerSpec.idd3p12 = 0; + memPowerSpec.idd3n = memSpec->iDD3N; + memPowerSpec.idd3n2 = 0; + memPowerSpec.idd4r = memSpec->iDD4R; + memPowerSpec.idd4r2 = 0; + memPowerSpec.idd4w = memSpec->iDD4W; + memPowerSpec.idd4w2 = 0; + memPowerSpec.idd5 = memSpec->iDD5; + memPowerSpec.idd52 = 0; + memPowerSpec.idd6 = memSpec->iDD6; + memPowerSpec.idd62 = 0; + memPowerSpec.vdd = memSpec->vDD; + memPowerSpec.vdd2 = 0; + + MemorySpecification powerSpec; + powerSpec.id = memSpec->MemoryId; + powerSpec.memoryType = memSpec->MemoryType; + powerSpec.memTimingSpec = memTimingSpec; + powerSpec.memPowerSpec = memPowerSpec; + powerSpec.memArchSpec = memArchSpec; + + DRAMPower = new libDRAMPower(powerSpec, 0); + } + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/DramDDR3.h b/DRAMSys/library/src/simulation/dram/DramDDR3.h similarity index 97% rename from DRAMSys/library/src/simulation/DramDDR3.h rename to DRAMSys/library/src/simulation/dram/DramDDR3.h index 0886d25a..1c1a9ffe 100644 --- a/DRAMSys/library/src/simulation/DramDDR3.h +++ b/DRAMSys/library/src/simulation/dram/DramDDR3.h @@ -36,15 +36,15 @@ #ifndef DRAMDDR3_H #define DRAMDDR3_H +#include #include "Dram.h" -#include -#include class DramDDR3 : public Dram { public: DramDDR3(sc_module_name); SC_HAS_PROCESS(DramDDR3); + virtual ~DramDDR3() {} }; #endif // DRAMDDR3_H diff --git a/DRAMSys/library/src/simulation/dram/DramDDR4.cpp b/DRAMSys/library/src/simulation/dram/DramDDR4.cpp new file mode 100644 index 00000000..7fb03743 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramDDR4.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramDDR4.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecDDR4.h" + +DramDDR4::DramDDR4(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramDDR4", "Error Model not supported for DDR4"); + + // Parameters for DRAMPower + MemSpecDDR4 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramDDR4", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + { + sc_time clk = memSpec->clk; + + MemArchitectureSpec memArchSpec; + memArchSpec.burstLength = memSpec->BurstLength; + memArchSpec.dataRate = memSpec->DataRate; + memArchSpec.nbrOfRows = memSpec->NumberOfRows; + memArchSpec.nbrOfBanks = memSpec->NumberOfBanks; + memArchSpec.nbrOfColumns = memSpec->NumberOfColumns; + memArchSpec.nbrOfRanks = memSpec->NumberOfRanks; + memArchSpec.width = memSpec->bitWidth; + memArchSpec.nbrOfBankGroups = memSpec->NumberOfBankGroups; + memArchSpec.twoVoltageDomains = true; + memArchSpec.dll = true; + + MemTimingSpec memTimingSpec; + //FIXME: memTimingSpec.FAWB = memSpec->tFAW / clk; + //FIXME: memTimingSpec.RASB = memSpec->tRAS / clk; + //FIXME: memTimingSpec.RCB = memSpec->tRC / clk; + //FIXME: memTimingSpec.RPB = memSpec->tRP / clk; + //FIXME: memTimingSpec.RRDB = memSpec->tRRD_S / clk; + //FIXME: memTimingSpec.RRDB_L = memSpec->tRRD_L / clk; + //FIXME: memTimingSpec.RRDB_S = memSpec->tRRD_S / clk; + memTimingSpec.AL = memSpec->tAL / clk; + memTimingSpec.CCD = memSpec->tCCD_S / clk; + memTimingSpec.CCD_L = memSpec->tCCD_L / clk; + memTimingSpec.CCD_S = memSpec->tCCD_S / clk; + memTimingSpec.CKE = memSpec->tCKE / clk; + memTimingSpec.CKESR = memSpec->tCKESR / clk; + memTimingSpec.clkMhz = memSpec->clkMHz; + // See also MemTimingSpec.cc in DRAMPower + memTimingSpec.clkPeriod = 1000.0 / memSpec->clkMHz; + memTimingSpec.DQSCK = memSpec->tDQSCK / clk; + memTimingSpec.FAW = memSpec->tFAW / clk; + memTimingSpec.RAS = memSpec->tRAS / clk; + memTimingSpec.RC = memSpec->tRC / clk; + memTimingSpec.RCD = memSpec->tRCD / clk; + memTimingSpec.REFI = memSpec->tREFI / clk; + memTimingSpec.RFC = memSpec->tRFC / clk; + memTimingSpec.RL = memSpec->tRL / clk; + memTimingSpec.RP = memSpec->tRP / clk; + memTimingSpec.RRD = memSpec->tRRD_S / clk; + memTimingSpec.RRD_L = memSpec->tRRD_L / clk; + memTimingSpec.RRD_S = memSpec->tRRD_S / clk; + memTimingSpec.RTP = memSpec->tRTP / clk; + memTimingSpec.TAW = memSpec->tFAW / clk; + memTimingSpec.WL = memSpec->tWL / clk; + memTimingSpec.WR = memSpec->tWR / clk; + memTimingSpec.WTR = memSpec->tWTR_S / clk; + memTimingSpec.WTR_L = memSpec->tWTR_L / clk; + memTimingSpec.WTR_S = memSpec->tWTR_S / clk; + memTimingSpec.XP = memSpec->tXP / clk; + memTimingSpec.XPDLL = memSpec->tXPDLL / clk; + memTimingSpec.XS = memSpec->tXS / clk; + memTimingSpec.XSDLL = memSpec->tXSDLL / clk; + + MemPowerSpec memPowerSpec; + memPowerSpec.idd0 = memSpec->iDD0; + memPowerSpec.idd02 = memSpec->iDD02; + memPowerSpec.idd2p0 = memSpec->iDD2P0; + memPowerSpec.idd2p02 = 0; + memPowerSpec.idd2p1 = memSpec->iDD2P1; + memPowerSpec.idd2p12 = 0; + memPowerSpec.idd2n = memSpec->iDD2N; + memPowerSpec.idd2n2 = 0; + memPowerSpec.idd3p0 = memSpec->iDD3P0; + memPowerSpec.idd3p02 = 0; + memPowerSpec.idd3p1 = memSpec->iDD3P1; + memPowerSpec.idd3p12 = 0; + memPowerSpec.idd3n = memSpec->iDD3N; + memPowerSpec.idd3n2 = 0; + memPowerSpec.idd4r = memSpec->iDD4R; + memPowerSpec.idd4r2 = 0; + memPowerSpec.idd4w = memSpec->iDD4W; + memPowerSpec.idd4w2 = 0; + memPowerSpec.idd5 = memSpec->iDD5; + memPowerSpec.idd52 = 0; + memPowerSpec.idd6 = memSpec->iDD6; + memPowerSpec.idd62 = memSpec->iDD62; + memPowerSpec.vdd = memSpec->vDD; + memPowerSpec.vdd2 = memSpec->vDD2; + + MemorySpecification powerSpec; + powerSpec.id = memSpec->MemoryId; + powerSpec.memoryType = memSpec->MemoryType; + powerSpec.memTimingSpec = memTimingSpec; + powerSpec.memPowerSpec = memPowerSpec; + powerSpec.memArchSpec = memArchSpec; + + DRAMPower = new libDRAMPower(powerSpec, 0); + } + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/DramDDR4.h b/DRAMSys/library/src/simulation/dram/DramDDR4.h similarity index 97% rename from DRAMSys/library/src/simulation/DramDDR4.h rename to DRAMSys/library/src/simulation/dram/DramDDR4.h index 5cf92424..bb901591 100644 --- a/DRAMSys/library/src/simulation/DramDDR4.h +++ b/DRAMSys/library/src/simulation/dram/DramDDR4.h @@ -36,15 +36,15 @@ #ifndef DRAMDDR4_H #define DRAMDDR4_H +#include #include "Dram.h" -#include -#include class DramDDR4 : public Dram { public: DramDDR4(sc_module_name); SC_HAS_PROCESS(DramDDR4); + virtual ~DramDDR4() {} }; #endif // DRAMDDR4_H diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp new file mode 100644 index 00000000..3e580346 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramGDDR5.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecGDDR5.h" + +DramGDDR5::DramGDDR5(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramGDDR5", "Error Model not supported for GDDR5"); + + // Parameters for DRAMPower + MemSpecGDDR5 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramGDDR5", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramGDDR5", "DRAMPower not supported for GDDR5"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/DramDDR3.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5.h similarity index 86% rename from DRAMSys/library/src/simulation/DramDDR3.cpp rename to DRAMSys/library/src/simulation/dram/DramGDDR5.h index ebe78c90..e35bc380 100644 --- a/DRAMSys/library/src/simulation/DramDDR3.cpp +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5.h @@ -33,13 +33,18 @@ * Lukas Steiner */ -#include "DramDDR3.h" +#ifndef DRAMGDDR5_H +#define DRAMGDDR5_H +#include #include "Dram.h" -#include "../controller/core/configuration/Configuration.h" -DramDDR3::DramDDR3(sc_module_name name) : Dram(name) +class DramGDDR5 : public Dram { - if (StoreMode == StorageMode::ErrorModel) - SC_REPORT_FATAL("DramDDR3", "Error Model for DDR3 not supported"); -} +public: + DramGDDR5(sc_module_name); + SC_HAS_PROCESS(DramGDDR5); + virtual ~DramGDDR5() {} +}; + +#endif // DRAMGDDR5_H diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp new file mode 100644 index 00000000..a3f492e7 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramGDDR5X.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecGDDR5X.h" + +DramGDDR5X::DramGDDR5X(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramGDDR5X", "Error Model not supported for GDDR5X"); + + // Parameters for DRAMPower + MemSpecGDDR5X *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramGDDR5X", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramGDDR5X", "DRAMPower not supported for GDDR5X"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/DramDDR4.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5X.h similarity index 86% rename from DRAMSys/library/src/simulation/DramDDR4.cpp rename to DRAMSys/library/src/simulation/dram/DramGDDR5X.h index 8feeb259..dedf1f8d 100644 --- a/DRAMSys/library/src/simulation/DramDDR4.cpp +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5X.h @@ -33,13 +33,18 @@ * Lukas Steiner */ -#include "DramDDR4.h" +#ifndef DRAMGDDR5X_H +#define DRAMGDDR5X_H +#include #include "Dram.h" -#include "../controller/core/configuration/Configuration.h" -DramDDR4::DramDDR4(sc_module_name name) : Dram(name) +class DramGDDR5X : public Dram { - if (StoreMode == StorageMode::ErrorModel) - SC_REPORT_FATAL("DramDDR4", "Error Model for DDR4 not supported"); -} +public: + DramGDDR5X(sc_module_name); + SC_HAS_PROCESS(DramGDDR5X); + virtual ~DramGDDR5X() {} +}; + +#endif // DRAMGDDR5X_H diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp new file mode 100644 index 00000000..8260db52 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramGDDR6.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecGDDR6.h" + +DramGDDR6::DramGDDR6(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramGDDR6", "Error Model not supported for GDDR6"); + + // Parameters for DRAMPower + MemSpecGDDR6 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramGDDR6", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramGDDR6", "DRAMPower not supported for GDDR6"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/ICommandChecker.h b/DRAMSys/library/src/simulation/dram/DramGDDR6.h similarity index 82% rename from DRAMSys/library/src/controller/core/scheduling/checker/ICommandChecker.h rename to DRAMSys/library/src/simulation/dram/DramGDDR6.h index 3f38f93b..07f586c2 100644 --- a/DRAMSys/library/src/controller/core/scheduling/checker/ICommandChecker.h +++ b/DRAMSys/library/src/simulation/dram/DramGDDR6.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,24 +30,22 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: - * Janik Schlemminger - * Matthias Jung + * Lukas Steiner */ -#ifndef ICOMMANDCHECKER_H -#define ICOMMANDCHECKER_H +#ifndef DRAMGDDR6_H +#define DRAMGDDR6_H #include -#include "../ScheduledCommand.h" +#include "Dram.h" - -class ICommandChecker +class DramGDDR6 : public Dram { public: - virtual ~ICommandChecker() {} - virtual void delayToSatisfyConstraints(ScheduledCommand &command) const = 0; + DramGDDR6(sc_module_name); + SC_HAS_PROCESS(DramGDDR6); + virtual ~DramGDDR6() {} }; - -#endif // ICOMMANDCHECKER_H +#endif // DRAMGDDR6_H diff --git a/DRAMSys/library/src/simulation/dram/DramHBM2.cpp b/DRAMSys/library/src/simulation/dram/DramHBM2.cpp new file mode 100644 index 00000000..3ee73ea0 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramHBM2.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramHBM2.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecHBM2.h" + +DramHBM2::DramHBM2(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramHBM2", "Error Model not supported for HBM2"); + + // Parameters for DRAMPower + MemSpecHBM2 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramHBM2", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramHBM2", "DRAMPower not supported for HBM2"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/controller/scheduler/FrFcfsRp.h b/DRAMSys/library/src/simulation/dram/DramHBM2.h similarity index 76% rename from DRAMSys/library/src/controller/scheduler/FrFcfsRp.h rename to DRAMSys/library/src/simulation/dram/DramHBM2.h index c1c10ca4..0b2861fa 100644 --- a/DRAMSys/library/src/controller/scheduler/FrFcfsRp.h +++ b/DRAMSys/library/src/simulation/dram/DramHBM2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,24 +30,21 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: - * Matthias Jung + * Lukas Steiner */ -#ifndef FRFCFSRP_H -#define FRFCFSRP_H +#ifndef DRAMHBM2_H +#define DRAMHBM2_H -#include "FrFcfs.h" +#include +#include "Dram.h" -class FrFcfsRp : public FrFcfs +class DramHBM2 : public Dram { public: - FrFcfsRp(ControllerCore &controllerCore) : FrFcfs(controllerCore) {} - std::pair - getNextRequest(Bank bank) override; - -private: - bool hazardDetection(Bank bank, std::deque::iterator ext); - void printDebugMessage(std::string message); + DramHBM2(sc_module_name); + SC_HAS_PROCESS(DramHBM2); + virtual ~DramHBM2() {} }; -#endif // FRFCFSRP_H +#endif // DRAMHBM2_H diff --git a/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp b/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp new file mode 100644 index 00000000..38df1da5 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramLPDDR4.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecLPDDR4.h" + +DramLPDDR4::DramLPDDR4(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramLPDDR4", "Error Model not supported for LPDDR4"); + + // Parameters for DRAMPower + MemSpecLPDDR4 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramLPDDR4", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramLPDDR4", "DRAMPower not supported for LPDDR4"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/dram/DramLPDDR4.h b/DRAMSys/library/src/simulation/dram/DramLPDDR4.h new file mode 100644 index 00000000..31271928 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramLPDDR4.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef DRAMLPDDR4_H +#define DRAMLPDDR4_H + +#include +#include "Dram.h" + +class DramLPDDR4 : public Dram +{ +public: + DramLPDDR4(sc_module_name); + SC_HAS_PROCESS(DramLPDDR4); + virtual ~DramLPDDR4() {} +}; + +#endif // DRAMLPDDR4_H diff --git a/DRAMSys/library/src/simulation/DramRecordable.cpp b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp similarity index 61% rename from DRAMSys/library/src/simulation/DramRecordable.cpp rename to DRAMSys/library/src/simulation/dram/DramRecordable.cpp index cc24e5a2..97c03e38 100644 --- a/DRAMSys/library/src/simulation/DramRecordable.cpp +++ b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp @@ -34,13 +34,20 @@ */ #include "DramRecordable.h" -#include -#include -#include "../common/TlmRecorder.h" + +#include +#include +#include "../../common/TlmRecorder.h" +#include "../../common/utils.h" #include "DramDDR3.h" #include "DramDDR4.h" #include "DramWideIO.h" -#include "../common/utils.h" +#include "DramLPDDR4.h" +#include "DramWideIO2.h" +#include "DramHBM2.h" +#include "DramGDDR5.h" +#include "DramGDDR5X.h" +#include "DramGDDR6.h" using namespace tlm; @@ -50,14 +57,25 @@ DramRecordable::DramRecordable(sc_module_name name, TlmRecorder *tlmRe { // Create a thread that is triggered every $powerWindowSize // to generate a Power over Time plot in the Trace analyzer: - SC_THREAD(powerWindow); + if (Configuration::getInstance().PowerAnalysis) + { + DRAMPower = dynamic_cast(Dram::DRAMPower); + if (DRAMPower == nullptr) + SC_REPORT_FATAL("DramRecordable", "Power Analysis active but libDRAMPowerIF instantiated"); + SC_THREAD(powerWindow); + } } template DramRecordable::~DramRecordable() { - BaseDram::DRAMPower->calcEnergy(); - recordPower(); + if (Configuration::getInstance().PowerAnalysis) + { + DRAMPower->calcEnergy(); + tlmRecorder->recordPower(sc_time_stamp().to_seconds(), + DRAMPower->getPower().window_average_power + * Configuration::getInstance().NumberOfDevicesOnDIMM); + } tlmRecorder->closeConnection(); } @@ -71,21 +89,20 @@ tlm_sync_enum DramRecordable::nb_transport_fw(tlm_generic_payload &pay // These are terminating phases recorded by the DRAM. The execution // time of the related command must be taken into consideration. if (phase == END_PDNA || phase == END_PDNAB) - recTime += getExecutionTime(Command::PDNAX, payload); + recTime += this->memSpec->getExecutionTime(Command::PDXA, payload); else if (phase == END_PDNP || phase == END_PDNPB) - recTime += getExecutionTime(Command::PDNPX, payload); + recTime += this->memSpec->getExecutionTime(Command::PDXP, payload); else if (phase == END_SREF || phase == END_SREFB) - recTime += getExecutionTime(Command::SREFX, payload); + recTime += this->memSpec->getExecutionTime(Command::SREFEX, payload); - unsigned int thr = DramExtension::getExtension(payload).getThread().ID(); - unsigned int ch = DramExtension::getExtension(payload).getChannel().ID(); - unsigned int bg = DramExtension::getExtension(payload).getBankGroup().ID(); - unsigned int bank = DramExtension::getExtension(payload).getBank().ID(); - unsigned int row = DramExtension::getExtension(payload).getRow().ID(); - unsigned int col = DramExtension::getExtension(payload).getColumn().ID(); + unsigned int thr __attribute__((unused)) = DramExtension::getExtension(payload).getThread().ID(); + unsigned int ch __attribute__((unused)) = DramExtension::getExtension(payload).getChannel().ID(); + unsigned int bg __attribute__((unused)) = DramExtension::getExtension(payload).getBankGroup().ID(); + unsigned int bank __attribute__((unused)) = DramExtension::getExtension(payload).getBank().ID(); + unsigned int row __attribute__((unused)) = DramExtension::getExtension(payload).getRow().ID(); + unsigned int col __attribute__((unused)) = DramExtension::getExtension(payload).getColumn().ID(); - // TODO: printDebugMessage not inherited - this->printDebugMessage("Recording " + phaseNameToString(phase) + " thread " + + PRINTDEBUGMESSAGE(this->name(), "Recording " + phaseNameToString(phase) + " thread " + to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string( bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " + to_string(col) + " at " + recTime.to_string()); @@ -106,38 +123,36 @@ void DramRecordable::powerWindow() // At the very beginning (zero clock cycles) the energy is 0, so we wait first wait(powerWindowSize); - clkCycles = sc_time_stamp().value() / - Configuration::getInstance().memSpec->clk.value(); + clkCycles = sc_time_stamp().value() / this->memSpec->clk.value(); - this->DRAMPower->calcWindowEnergy(clkCycles); + DRAMPower->calcWindowEnergy(clkCycles); // During operation the energy should never be zero since the device is always consuming - assert(!isEqual(this->DRAMPower->getEnergy().window_energy, 0.0)); + assert(!isEqual(DRAMPower->getEnergy().window_energy, 0.0)); // Store the time (in seconds) and the current average power (in mW) into the database - recordPower(); + tlmRecorder->recordPower(sc_time_stamp().to_seconds(), + DRAMPower->getPower().window_average_power + * Configuration::getInstance().NumberOfDevicesOnDIMM); // Here considering that DRAMPower provides the energy in pJ and the power in mW - this->printDebugMessage(string("\tWindow Energy: \t") + to_string( - this->DRAMPower->getEnergy().window_energy * + PRINTDEBUGMESSAGE(this->name(), string("\tWindow Energy: \t") + to_string( + DRAMPower->getEnergy().window_energy * Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[pJ]")); - this->printDebugMessage(string("\tWindow Average Power: \t") + to_string( - this->DRAMPower->getPower().window_average_power * + PRINTDEBUGMESSAGE(this->name(), string("\tWindow Average Power: \t") + to_string( + DRAMPower->getPower().window_average_power * Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[mW]")); } while (true); } -template -void DramRecordable::recordPower() -{ - tlmRecorder->recordPower(sc_time_stamp().to_seconds(), - this->DRAMPower->getPower().window_average_power - * Configuration::getInstance().NumberOfDevicesOnDIMM); -} - - template class DramRecordable; template class DramRecordable; template class DramRecordable; +template class DramRecordable; +template class DramRecordable; +template class DramRecordable; +template class DramRecordable; +template class DramRecordable; +template class DramRecordable; diff --git a/DRAMSys/library/src/simulation/DramRecordable.h b/DRAMSys/library/src/simulation/dram/DramRecordable.h similarity index 87% rename from DRAMSys/library/src/simulation/DramRecordable.h rename to DRAMSys/library/src/simulation/dram/DramRecordable.h index 59d6873a..c11f9a81 100644 --- a/DRAMSys/library/src/simulation/DramRecordable.h +++ b/DRAMSys/library/src/simulation/dram/DramRecordable.h @@ -36,30 +36,28 @@ #ifndef DRAMRECORDABLE_H #define DRAMRECORDABLE_H -#include -#include -#include "DramDDR3.h" -#include "DramDDR4.h" -#include "RecordableDram.h" -#include "../common/TlmRecorder.h" +#include +#include +#include "../../common/TlmRecorder.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" using namespace tlm; template -class DramRecordable : public BaseDram +class DramRecordable final : public BaseDram { public: - DramRecordable(sc_module_name name, TlmRecorder *tlmRecorder); + DramRecordable(sc_module_name, TlmRecorder *); SC_HAS_PROCESS(DramRecordable); - - virtual ~DramRecordable(); - -protected: - virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &delay); + ~DramRecordable(); private: + virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, + tlm_phase &phase, sc_time &delay) override; TlmRecorder *tlmRecorder; + + libDRAMPower *DRAMPower; sc_time powerWindowSize = Configuration::getInstance().memSpec->clk * Configuration::getInstance().WindowSize; @@ -74,8 +72,6 @@ private: // This Thread is only triggered when Power Simulation is enabled. // It estimates the current average power which will be stored in the trace database for visualization purposes. void powerWindow(); - - void recordPower(); }; #endif // DRAMRECORDABLE_H diff --git a/DRAMSys/library/src/simulation/dram/DramWideIO.cpp b/DRAMSys/library/src/simulation/dram/DramWideIO.cpp new file mode 100644 index 00000000..1ee85597 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramWideIO.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramWideIO.h" + +#include +#include +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../error/errormodel.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecWideIO.h" + +using namespace tlm; + +DramWideIO::DramWideIO(sc_module_name name) : Dram(name) +{ + // Parameters for DRAMPower + MemSpecWideIO *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramWideIO", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + { + sc_time clk = memSpec->clk; + + MemArchitectureSpec memArchSpec; + memArchSpec.burstLength = memSpec->BurstLength; + memArchSpec.dataRate = memSpec->DataRate; + memArchSpec.nbrOfRows = memSpec->NumberOfRows; + memArchSpec.nbrOfBanks = memSpec->NumberOfBanks; + memArchSpec.nbrOfColumns = memSpec->NumberOfColumns; + memArchSpec.nbrOfRanks = memSpec->NumberOfRanks; + memArchSpec.width = memSpec->bitWidth; + memArchSpec.nbrOfBankGroups = memSpec->NumberOfBankGroups; + memArchSpec.twoVoltageDomains = true; + memArchSpec.dll = false; + + MemTimingSpec memTimingSpec; + //FIXME: memTimingSpec.FAWB = memSpec->tTAW / clk; + //FIXME: memTimingSpec.RASB = memSpec->tRAS / clk; + //FIXME: memTimingSpec.RCB = memSpec->tRC / clk; + //FIXME: memTimingSpec.RPB = memSpec->tRP / clk; + //FIXME: memTimingSpec.RRDB = memSpec->tRRD / clk; + //FIXME: memTimingSpec.RRDB_L = memSpec->tRRD / clk; + //FIXME: memTimingSpec.RRDB_S = memSpec->tRRD / clk; + memTimingSpec.AL = 0; + memTimingSpec.CCD = memSpec->BurstLength; + memTimingSpec.CCD_L = memSpec->BurstLength; + memTimingSpec.CCD_S = memSpec->BurstLength; + memTimingSpec.CKE = memSpec->tCKE / clk; + memTimingSpec.CKESR = memSpec->tCKESR / clk; + memTimingSpec.clkMhz = memSpec->clkMHz; + // See also MemTimingSpec.cc in DRAMPower + memTimingSpec.clkPeriod = 1000.0 / memSpec->clkMHz; + memTimingSpec.DQSCK = memSpec->tDQSCK / clk; + memTimingSpec.FAW = memSpec->tTAW / clk; + memTimingSpec.RAS = memSpec->tRAS / clk; + memTimingSpec.RC = memSpec->tRC / clk; + memTimingSpec.RCD = memSpec->tRCD / clk; + memTimingSpec.REFI = memSpec->tREFI / clk; + memTimingSpec.RFC = memSpec->tRFC / clk; + memTimingSpec.RL = memSpec->tRL / clk; + memTimingSpec.RP = memSpec->tRP / clk; + memTimingSpec.RRD = memSpec->tRRD / clk; + memTimingSpec.RRD_L = memSpec->tRRD / clk; + memTimingSpec.RRD_S = memSpec->tRRD / clk; + memTimingSpec.RTP = memSpec->BurstLength; + memTimingSpec.TAW = memSpec->tTAW / clk; + memTimingSpec.WL = memSpec->tWL / clk; + memTimingSpec.WR = memSpec->tWR / clk; + memTimingSpec.WTR = memSpec->tWTR / clk; + memTimingSpec.WTR_L = memSpec->tWTR / clk; + memTimingSpec.WTR_S = memSpec->tWTR / clk; + memTimingSpec.XP = memSpec->tXP / clk; + memTimingSpec.XPDLL = memSpec->tXP / clk; + memTimingSpec.XS = memSpec->tXS / clk; + memTimingSpec.XSDLL = memSpec->tXS / clk; + + MemPowerSpec memPowerSpec; + memPowerSpec.idd0 = memSpec->iDD0; + memPowerSpec.idd02 = memSpec->iDD02; + memPowerSpec.idd2p0 = memSpec->iDD2P0; + memPowerSpec.idd2p02 = memSpec->iDD2P02; + memPowerSpec.idd2p1 = memSpec->iDD2P1; + memPowerSpec.idd2p12 = memSpec->iDD2P12; + memPowerSpec.idd2n = memSpec->iDD2N; + memPowerSpec.idd2n2 = memSpec->iDD2N2; + memPowerSpec.idd3p0 = memSpec->iDD3P0; + memPowerSpec.idd3p02 = memSpec->iDD3P02; + memPowerSpec.idd3p1 = memSpec->iDD3P1; + memPowerSpec.idd3p12 = memSpec->iDD3P12; + memPowerSpec.idd3n = memSpec->iDD3N; + memPowerSpec.idd3n2 = memSpec->iDD3N2; + memPowerSpec.idd4r = memSpec->iDD4R; + memPowerSpec.idd4r2 = memSpec->iDD4R2; + memPowerSpec.idd4w = memSpec->iDD4W; + memPowerSpec.idd4w2 = memSpec->iDD4W2; + memPowerSpec.idd5 = memSpec->iDD5; + memPowerSpec.idd52 = memSpec->iDD52; + memPowerSpec.idd6 = memSpec->iDD6; + memPowerSpec.idd62 = memSpec->iDD62; + memPowerSpec.vdd = memSpec->vDD; + memPowerSpec.vdd2 = memSpec->vDD2; + + MemorySpecification powerSpec; + powerSpec.id = memSpec->MemoryId; + powerSpec.memoryType = memSpec->MemoryType; + powerSpec.memTimingSpec = memTimingSpec; + powerSpec.memPowerSpec = memPowerSpec; + powerSpec.memArchSpec = memArchSpec; + + libDRAMPower *DRAMPower = new libDRAMPower(powerSpec, 0); + + // For each bank in a channel a error Model is created: + if (StoreMode == StorageMode::ErrorModel) + { + for (unsigned i = 0; i < memSpec->NumberOfBanks; i++) + { + errorModel *em; + std::string errorModelStr = "errorModel_bank" + std::to_string(i); + em = new errorModel(errorModelStr.c_str(), DRAMPower); + ememory.push_back(em); + } + } + this->DRAMPower = DRAMPower; + } + else + { + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramWideIO", "Error modeling without power analysis is not supported"); + DRAMPower = new libDRAMPowerDummy(); + } +} + +DramWideIO::~DramWideIO() +{ + // Clean up: + for (auto e : ememory) + delete e; +} + +tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload, + tlm_phase &phase, sc_time &delay) +{ + unsigned int bank = DramExtension::getExtension(payload).getBank().ID(); + + // This is only needed for power simulation: + unsigned long long cycle = sc_time_stamp().value() / memSpec->clk.value(); + + if (phase == BEGIN_PRE) + { + DRAMPower->doCommand(MemCommand::PRE, bank, cycle); + sendToController(payload, END_PRE, delay + memSpec->getExecutionTime(Command::PRE, payload)); + } + else if (phase == BEGIN_PREA) + { + DRAMPower->doCommand(MemCommand::PREA, bank, cycle); + sendToController(payload, END_PREA, + delay + memSpec->getExecutionTime(Command::PREA, payload)); + } + else if (phase == BEGIN_ACT) + { + DRAMPower->doCommand(MemCommand::ACT, bank, cycle); + sendToController(payload, END_ACT, delay + memSpec->getExecutionTime(Command::ACT, payload)); + unsigned int row = DramExtension::getExtension(payload).getRow().ID(); + + if (StoreMode == StorageMode::ErrorModel) + ememory[bank]->activate(row); + } + else if (phase == BEGIN_WR) + { + DRAMPower->doCommand(MemCommand::WR, bank, cycle); + // save data: + if (StoreMode == StorageMode::Store) // Use Storage + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); + } + else if (StoreMode == StorageMode::ErrorModel) // Use Storage with Error Model + { + ememory[bank]->store(payload); + } + sendToController(payload, END_WR, delay + memSpec->getExecutionTime(Command::WR, payload)); + } + else if (phase == BEGIN_RD) + { + DRAMPower->doCommand(MemCommand::RD, bank, cycle); + // load data: + if (StoreMode == StorageMode::Store) // use StorageMode + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); + } + else if (StoreMode == StorageMode::ErrorModel) // use StorageMode with errormodel + { + ememory[bank]->load(payload); + } + sendToController(payload, END_RD, delay + memSpec->getExecutionTime(Command::RD, payload)); + } + else if (phase == BEGIN_WRA) + { + DRAMPower->doCommand(MemCommand::WRA, bank, cycle); + // save data: + if (StoreMode == StorageMode::Store) // Use Storage + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); + } + else if (StoreMode == StorageMode::ErrorModel) // Use Storage with Error Model + { + ememory[bank]->store(payload); + } + sendToController(payload, END_WRA, delay + memSpec->getExecutionTime(Command::WRA, payload)); + } + else if (phase == BEGIN_RDA) + { + DRAMPower->doCommand(MemCommand::RDA, bank, cycle); + // Load data: + if (StoreMode == StorageMode::Store) // use StorageMode + { + unsigned char *phyAddr = memory + payload.get_address(); + memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length()); + } + else if (StoreMode == StorageMode::ErrorModel) // use StorageMode with errormodel + { + ememory[bank]->load(payload); + } + sendToController(payload, END_RDA, delay + memSpec->getExecutionTime(Command::RDA, payload)); + } + else if (phase == BEGIN_REFA) + { + DRAMPower->doCommand(MemCommand::REF, bank, cycle); + sendToController(payload, END_REFA, + delay + memSpec->getExecutionTime(Command::REFA, payload)); + unsigned int row = DramExtension::getExtension(payload).getRow().ID(); + + if (StoreMode == StorageMode::ErrorModel) + ememory[bank]->refresh(row); + } + else if (phase == BEGIN_REFB) + { + DRAMPower->doCommand(MemCommand::REFB, bank, cycle); + sendToController(payload, END_REFB, + delay + memSpec->getExecutionTime(Command::REFA, payload)); + } + // Powerdown phases have to be started and ended by the controller, because they do not have a fixed length + else if (phase == BEGIN_PDNA) + { + DRAMPower->doCommand(MemCommand::PDN_S_ACT, bank, cycle); + } + else if (phase == END_PDNA) + { + DRAMPower->doCommand(MemCommand::PUP_ACT, bank, cycle); + } + else if (phase == BEGIN_PDNP) + { + DRAMPower->doCommand(MemCommand::PDN_S_PRE, bank, cycle); + } + else if (phase == END_PDNP) + { + DRAMPower->doCommand(MemCommand::PUP_PRE, bank, cycle); + } + else if (phase == BEGIN_SREF) + { + DRAMPower->doCommand(MemCommand::SREN, bank, cycle); + } + else if (phase == END_SREF) + { + DRAMPower->doCommand(MemCommand::SREX, bank, cycle); + } + else + { + SC_REPORT_FATAL("DRAM", "DRAM PEQ was called with unknown phase"); + } + + return TLM_ACCEPTED; +} diff --git a/DRAMSys/library/src/simulation/DramWideIO.h b/DRAMSys/library/src/simulation/dram/DramWideIO.h similarity index 95% rename from DRAMSys/library/src/simulation/DramWideIO.h rename to DRAMSys/library/src/simulation/dram/DramWideIO.h index 56e0b39a..10aeb629 100644 --- a/DRAMSys/library/src/simulation/DramWideIO.h +++ b/DRAMSys/library/src/simulation/dram/DramWideIO.h @@ -36,10 +36,10 @@ #ifndef DRAMWIDEIO_H #define DRAMWIDEIO_H -#include -#include +#include +#include #include "Dram.h" -#include "../error/errormodel.h" +#include "../../error/errormodel.h" using namespace tlm; @@ -48,12 +48,11 @@ class DramWideIO : public Dram public: DramWideIO(sc_module_name); SC_HAS_PROCESS(DramWideIO); - virtual ~DramWideIO(); protected: virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &delay); + tlm_phase &phase, sc_time &delay) override; private: std::vector ememory; diff --git a/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp b/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp new file mode 100644 index 00000000..dde791fa --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramWideIO2.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecWideIO2.h" + +DramWideIO2::DramWideIO2(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramWideIO2", "Error Model not supported for WideIO2"); + + // Parameters for DRAMPower + MemSpecWideIO2 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramWideIO2", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramWideIO2", "DRAMPower not supported for WideIO2"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/dram/DramWideIO2.h b/DRAMSys/library/src/simulation/dram/DramWideIO2.h new file mode 100644 index 00000000..d51f7e4f --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramWideIO2.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef DRAMWIDEIO2_H +#define DRAMWIDEIO2_H + +#include +#include "Dram.h" + +class DramWideIO2 : public Dram +{ +public: + DramWideIO2(sc_module_name); + SC_HAS_PROCESS(DramWideIO2); + virtual ~DramWideIO2() {} +}; + +#endif // DRAMWIDEIO2_H diff --git a/DRAMSys/simulator/main.cpp b/DRAMSys/simulator/main.cpp index 956f373e..0cd387ac 100644 --- a/DRAMSys/simulator/main.cpp +++ b/DRAMSys/simulator/main.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "DRAMSys.h" #include "TraceSetup.h" @@ -68,14 +68,14 @@ int sc_main(int argc, char **argv) if (argc == 1) { // Get path of resources: resources = pathOfFile(argv[0]) - + string("/../../DRAMSys/library/resources/"); + + string("/../DRAMSys/library/resources/"); SimulationXML = resources + "simulations/ddr3-example.xml"; } // Run with specific config but default resource folders: else if (argc == 2) { // Get path of resources: resources = pathOfFile(argv[0]) - + string("/../../DRAMSys/library/resources/"); + + string("/../DRAMSys/library/resources/"); SimulationXML = argv[1]; } // Run with spefific config and specific resource folder: @@ -110,7 +110,7 @@ int sc_main(int argc, char **argv) } // Store the starting of the simulation in wallclock time: - clock_t simStartTime = clock(); + auto start = std::chrono::high_resolution_clock::now(); // Kickstart the players: for (auto &p : players) { @@ -121,8 +121,9 @@ int sc_main(int argc, char **argv) sc_set_stop_mode(SC_STOP_FINISH_DELTA); sc_start(); - double elapsed_secs = double(clock() - simStartTime) / CLOCKS_PER_SEC; - cout << "Simulation took " + to_string(elapsed_secs) + " seconds" << endl; + auto finish = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = finish - start; + std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl; delete dramSys; delete ts; diff --git a/DRAMSys/simulator/simulator.pro b/DRAMSys/simulator/simulator.pro deleted file mode 100644 index a0b27493..00000000 --- a/DRAMSys/simulator/simulator.pro +++ /dev/null @@ -1,71 +0,0 @@ -TARGET = DRAMSys - -TEMPLATE = app -CONFIG += console -CONFIG -= app_bundle -CONFIG -= qt - -systemc_home = $$(SYSTEMC_HOME) -isEmpty(systemc_home) { - systemc_home = /opt/systemc -} -message(SystemC home is $${systemc_home}) - -systemc_target_arch = $$(SYSTEMC_TARGET_ARCH) -isEmpty(systemc_target_arch) { - systemc_target_arch = linux64 -} - -message(SystemC target architecture is $${systemc_target_arch}) - -dramsys_disable_coverage_check = $$(DRAMSYS_DISABLE_COVERAGE_CHECK) -isEmpty(dramsys_disable_coverage_check) { - coverage_check = true - message(Coverage check ENABLED) -} else { - coverage_check = false - message(Coverage check DISABLED) -} - -unix:!macx { - message(Building on a GNU/Linux) - QMAKE_RPATHDIR += $${systemc_home}/lib-$${systemc_target_arch} - message(Linker options QMAKE_RPATHDIR is $${QMAKE_RPATHDIR}) -} - -DEFINES += TIXML_USE_STL -DEFINES += SC_INCLUDE_DYNAMIC_PROCESSES - -unix:!macx { - QMAKE_CXXFLAGS += -std=c++11 -O0 -g - $$eval(coverage_check) { - QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -fPIC -O0 - QMAKE_LFLAGS += -lgcov --coverage - } -} - -macx: { - CONFIG += c++11 - QMAKE_CXXFLAGS += -std=c++0x -stdlib=libc++ -O0 -g - QMAKE_MACOSX_DEPLOYMENT_TARGET=10.14 - $$eval(coverage_check) { - QMAKE_CXXFLAGS += --coverage - QMAKE_LFLAGS += --coverage - } -} - -INCLUDEPATH += ../library/src/simulation/ -INCLUDEPATH += $${systemc_home}/include -INCLUDEPATH += ../library/src/common/third_party/DRAMPower/src -INCLUDEPATH += ../library/src/common/third_party/DRAMPower/src/libdrampower - -LIBS += -L$${systemc_home}/lib-$${systemc_target_arch} -lsystemc -LIBS += ../library/libDRAMSys.a -LIBS += ../../DRAMSys/library/src/common/third_party/DRAMPower/src/libdrampower.a -LIBS += -lsqlite3 - -PRE_TARGETDEPS += ../library/libDRAMSys.a - -SOURCES += main.cpp - -DISTFILES += ../DRAMSys.astylerc diff --git a/DRAMSys/traceAnalyzer/CMakeLists.txt b/DRAMSys/traceAnalyzer/CMakeLists.txt new file mode 100644 index 00000000..3db02a3b --- /dev/null +++ b/DRAMSys/traceAnalyzer/CMakeLists.txt @@ -0,0 +1,121 @@ +# Copyright (c) 2020, 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: Matthias Jung + +cmake_minimum_required(VERSION 3.10) + +# Project Name: +project(TraceAnalyzer) + +# Add Python Dependency: +find_library(PYTHON3_LIBRARY NAMES Python3) + +# Add sqlite3 Dependency: +find_package(PythonLibs REQUIRED) + +# Add QWT Dependency: +find_library(QWT_LIBRARY NAMES "qwt-qt5" "qwt") +find_path (QWT_INCLUDE_DIRS NAMES "qwt_plot.h" PATHS + "/usr/include/qwt-qt5" + "/usr/include/qwt" + "C:\\Qwt\\" + "C:\\Qwt-6.1.4\\" + "C:\\Users\\jung\\Zeugs\\qwt\\qwt-614-install\\include" +) + +# Add QT Library: +find_package(Qt5 COMPONENTS Core Gui Widgets Sql REQUIRED) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Configure: +set (CMAKE_CXX_STANDARD 11) +set(DCMAKE_SH="CMAKE_SH-NOTFOUND") + +include_directories( + ${QWT_INCLUDE_DIRS} + ${PYTHON_INCLUDE_DIRS} + ./ + businessObjects/ + businessObjects/phases/ + data/ + presentation/ + presentation/util/ +) + + +add_executable(TraceAnalyzer + main.cpp + businessObjects/transaction.cpp + businessObjects/timespan.cpp + data/tracedb.cpp + presentation/tracenavigator.cpp + presentation/util/colorgenerator.cpp + presentation/tracedrawing.cpp + presentation/traceplotitem.cpp + gototimedialog.cpp + presentation/traceplot.cpp + tracefiletab.cpp + presentation/pornotracescroller.cpp + traceanalyzer.cpp + presentation/transactiontreewidget.cpp + presentation/commenttreewidget.cpp + presentation/util/clkgrid.cpp + queryeditor.cpp + presentation/selectedtransactiontreewidget.cpp + businessObjects/phases/phasefactory.cpp + presentation/debugmessagetreewidget.cpp + presentation/tracePlotMouseLabel.cpp + evaluationtool.cpp + selectmetrics.cpp + presentation/util/testlight.cpp + presentation/tracetesttreewidget.cpp + businessObjects/pythoncaller.cpp + businessObjects/tracetestresults.cpp + presentation/tracemetrictreewidget.cpp + businessObjects/phases/phase.cpp + selectmetrics.ui + preferences.ui + evaluationtool.ui + gototimedialog.ui + tracefiletab.ui + queryeditor.ui + traceanalyzer.ui +) + +# Build: +target_link_libraries(TraceAnalyzer + ${PYTHON_LIBRARIES} + ${QWT_LIBRARY} +) +qt5_use_modules(TraceAnalyzer Widgets Sql) diff --git a/DRAMSys/library/src/controller/core/powerdown/NoPowerDown.h b/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h similarity index 61% rename from DRAMSys/library/src/controller/core/powerdown/NoPowerDown.h rename to DRAMSys/traceAnalyzer/businessObjects/commandlengths.h index 19a53403..63c9ed75 100644 --- a/DRAMSys/library/src/controller/core/powerdown/NoPowerDown.h +++ b/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,36 +30,39 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung + * Lukas Steiner */ -#ifndef NOPOWERDOWN_H -#define NOPOWERDOWN_H +#ifndef COMMANDLENGTHS_H +#define COMMANDLENGTHS_H -#include "PowerDownManager.h" -#include -#include "../../../common/dramExtensions.h" -#include "../scheduling/ScheduledCommand.h" - - - -class NoPowerDown : public IPowerDownManager +struct CommandLengths { -public: - NoPowerDown() {} - virtual ~NoPowerDown() {} + unsigned ACT; + unsigned PRE; + unsigned PREA; + unsigned RD; + unsigned RDA; + unsigned WR; + unsigned WRA; + unsigned REFA; + unsigned REFB; + unsigned PDEA; + unsigned PDXA; + unsigned PDEP; + unsigned PDXP; + unsigned SREFEN; + unsigned SREFEX; - virtual void triggerSleep(Bank bank, sc_time time) override; - virtual void sleep(Bank bank, sc_time time) override; + CommandLengths(unsigned ACT, unsigned PRE, unsigned PREA, + unsigned RD, unsigned RDA, unsigned WR, unsigned WRA, + unsigned REFA, unsigned REFB, unsigned PDEA, unsigned PDXA, + unsigned PDEP, unsigned PDXP, unsigned SREFEN, unsigned SREFEX) : + ACT(ACT), PRE(PRE), PREA(PREA), RD(RD), RDA(RDA), WR(WR), WRA(WRA), + REFA(REFA), REFB(REFB), PDEA(PDEA), PDXA(PDXA), + PDEP(PDEP), PDXP(PDXP), SREFEN(SREFEN), SREFEX(SREFEX) {} - virtual void wakeUp(Bank bank, sc_time time) override; - virtual void wakeUpForRefresh(Bank bank, sc_time time) override; - - virtual bool isInSelfRefresh(Bank bank) override; + CommandLengths() {} }; - - -#endif // NOPOWERDOWN_H +#endif // COMMANDLENGTHS_H diff --git a/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h b/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h index 883ad0a1..a2858cdb 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h +++ b/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h @@ -44,6 +44,7 @@ struct GeneralInfo { unsigned int numberOfTransactions; unsigned int numberOfPhases; Timespan span; + unsigned int numberOfRanks; unsigned int numberOfBanks; QString description; QString unitOfTime; @@ -53,15 +54,13 @@ struct GeneralInfo { public: GeneralInfo(unsigned int numberOfTransactions, unsigned int numberOfPhases, - Timespan span, unsigned int numberOfBanks, const QString &description, - QString unitOfTime, unsigned int clkPeriod, unsigned int windowSize, - unsigned int controllerThread) : + Timespan span, unsigned int numberOfRanks, unsigned int numberOfBanks, + const QString &description, QString unitOfTime, unsigned int clkPeriod, + unsigned int windowSize, unsigned int controllerThread) : numberOfTransactions(numberOfTransactions) , numberOfPhases(numberOfPhases), - span(span), numberOfBanks(numberOfBanks), description(description), - unitOfTime(unitOfTime), clkPeriod(clkPeriod), windowSize(windowSize), - controllerThread(controllerThread) - { - } + span(span), numberOfRanks(numberOfRanks), numberOfBanks(numberOfBanks), + description(description), unitOfTime(unitOfTime), clkPeriod(clkPeriod), + windowSize(windowSize), controllerThread(controllerThread) {} GeneralInfo() {} }; diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp index b72bf9ed..45163619 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp @@ -64,7 +64,7 @@ void Phase::draw(QPainter *painter, const QwtScaleMap &xMap, } if (!isBankwise()) { - for (unsigned int i = 0; i < drawingProperties.numberOfBanks; i++) + for (int i = getYVal(drawingProperties); i < (int)(getYVal(drawingProperties) + drawingProperties.banksPerRank); i++) drawPhaseSymbol(span.Begin(), span.End(), i, drawingProperties.drawText, getPhaseSymbol(), painter, xMap, yMap); } else @@ -123,8 +123,10 @@ QColor Phase::getColor(const TraceDrawingProperties &drawingProperties) const int Phase::getYVal(const TraceDrawingProperties &drawingProperties) const { - Q_UNUSED(drawingProperties) - return transaction->Bank(); + if (isBankwise()) + return transaction->Bank(); + else + return transaction->Rank() * drawingProperties.banksPerRank; } Qt::BrushStyle Phase::getBrushStyle() const diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp b/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp index 3f7dc143..e505deb7 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp @@ -48,71 +48,64 @@ shared_ptr PhaseFactory::CreatePhase(ID id, const QString &dbPhaseName, const Timespan &span, const shared_ptr &trans, TraceDB &database) { traceTime clk = database.getGeneralInfo().clkPeriod; + const CommandLengths &cl = database.getCommandLengths(); if (dbPhaseName == "REQ") - return shared_ptr(new REQ(id, span, trans, {}, - std::shared_ptr())); + return shared_ptr(new REQ(id, span, trans, {}, std::shared_ptr())); else if (dbPhaseName == "RESP") - return shared_ptr(new RESP(id, span, trans, {}, - std::shared_ptr())); + return shared_ptr(new RESP(id, span, trans, {}, std::shared_ptr())); - else if (dbPhaseName == "PREB") return shared_ptr(new PREB(id, span, - trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr())); + else if (dbPhaseName == "PREB") + return shared_ptr(new PREB(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk)}, std::shared_ptr())); else if (dbPhaseName == "PRE") - return shared_ptr(new PRE(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr())); - else if (dbPhaseName == "ACTB") return shared_ptr(new ACTB(id, span, - trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr())); + return shared_ptr(new PRE(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk * cl.PRE)}, std::shared_ptr())); + else if (dbPhaseName == "ACTB") + return shared_ptr(new ACTB(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk)}, std::shared_ptr())); else if (dbPhaseName == "ACT") - return shared_ptr(new ACT(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr())); - else if (dbPhaseName == "PRE_ALL") - return shared_ptr(new PRECHARGE_ALL(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr())); + return shared_ptr(new ACT(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk * cl.ACT)}, std::shared_ptr())); + else if (dbPhaseName == "PREA") + return shared_ptr(new PRECHARGE_ALL(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk * cl.PREA)}, std::shared_ptr())); else if (dbPhaseName == "REFA") - return shared_ptr(new REFA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr())); + return shared_ptr(new REFA(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk * cl.REFA)}, std::shared_ptr())); else if (dbPhaseName == "REFB") - return shared_ptr(new REFB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr())); - + return shared_ptr(new REFB(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk * cl.REFB)}, std::shared_ptr())); else if (dbPhaseName == "RD") - return shared_ptr(new RD(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr - (new Timespan(trans->SpanOnDataStrobe())))); + return shared_ptr(new RD(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.RD)}, + std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); else if (dbPhaseName == "RDA") - return shared_ptr(new RDA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr - (new Timespan(trans->SpanOnDataStrobe())))); + return shared_ptr(new RDA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.RDA)}, + std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); else if (dbPhaseName == "WR") - return shared_ptr(new WR(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr - (new Timespan(trans->SpanOnDataStrobe())))); + return shared_ptr(new WR(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.WR)}, + std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); else if (dbPhaseName == "WRA") - return shared_ptr(new WRA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk)}, - std::shared_ptr - (new Timespan(trans->SpanOnDataStrobe())))); + return shared_ptr(new WRA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.WRA)}, + std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); else if (dbPhaseName == "PDNA") - return shared_ptr(new PDNA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), Timespan(span.End() - clk, span.End())}, - std::shared_ptr())); + return shared_ptr(new PDNA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.PDEA), + Timespan(span.End() - clk * cl.PDXA, span.End())}, std::shared_ptr())); else if (dbPhaseName == "PDNAB") - return shared_ptr(new PDNAB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), Timespan(span.End() - clk, span.End())}, - std::shared_ptr())); + return shared_ptr(new PDNAB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), + Timespan(span.End() - clk, span.End())}, std::shared_ptr())); else if (dbPhaseName == "PDNP") - return shared_ptr(new PDNP(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), Timespan(span.End() - clk, span.End())}, - std::shared_ptr())); + return shared_ptr(new PDNP(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.PDEP), + Timespan(span.End() - clk * cl.PDXP, span.End())}, std::shared_ptr())); else if (dbPhaseName == "PDNPB") - return shared_ptr(new PDNPB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), Timespan(span.End() - clk, span.End())}, - std::shared_ptr())); + return shared_ptr(new PDNPB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), + Timespan(span.End() - clk, span.End())}, std::shared_ptr())); else if (dbPhaseName == "SREF") - return shared_ptr(new SREF(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), Timespan(span.End() - clk, span.End())}, - std::shared_ptr())); + return shared_ptr(new SREF(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.SREFEN), + Timespan(span.End() - clk * cl.SREFEX, span.End())}, std::shared_ptr())); else if (dbPhaseName == "SREFB") - return shared_ptr(new SREFB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), Timespan(span.End() - clk, span.End())}, - std::shared_ptr())); + return shared_ptr(new SREFB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk), + Timespan(span.End() - clk, span.End())}, std::shared_ptr())); else - throw std::runtime_error("DB phasename " + dbPhaseName.toStdString() + - " unkown to phasefactory"); + throw std::runtime_error("DB phasename " + dbPhaseName.toStdString() + " unkown to phasefactory"); } diff --git a/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h b/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h index 17ff8819..9eceec38 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h +++ b/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h @@ -38,6 +38,12 @@ #ifndef PYTHONCALLER_H #define PYTHONCALLER_H + +// Workaround for CMAKE and Python +#ifdef slots +#undef slots +#endif + #include #include #include diff --git a/DRAMSys/traceAnalyzer/businessObjects/transaction.cpp b/DRAMSys/traceAnalyzer/businessObjects/transaction.cpp index 9bdec5f5..306141fd 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/transaction.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/transaction.cpp @@ -39,11 +39,11 @@ using namespace std; Transaction::Transaction(ID id, unsigned int address, unsigned int burstlength, - unsigned int thread, unsigned int channel, unsigned int bank, - unsigned int bankgroup, unsigned int row, unsigned int column, Timespan span, - Timespan spanOnDataStrobe) - : address(address), burstlength(burstlength), thread(thread), channel(channel), - bank(bank), bankgroup(bankgroup), row(row), column(column), span(span), + unsigned int thread, unsigned int channel, unsigned int rank, + unsigned int bankgroup, unsigned int bank, unsigned int row, unsigned int column, + Timespan span, Timespan spanOnDataStrobe) + : address(address), burstlength(burstlength), thread(thread), channel(channel), rank(rank), + bankgroup(bankgroup), bank(bank), row(row), column(column), span(span), spanOnDataStrobe(spanOnDataStrobe), id(id) {} void Transaction::addPhase(shared_ptr phase) diff --git a/DRAMSys/traceAnalyzer/businessObjects/transaction.h b/DRAMSys/traceAnalyzer/businessObjects/transaction.h index 767c4f48..d58a7c56 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/transaction.h +++ b/DRAMSys/traceAnalyzer/businessObjects/transaction.h @@ -48,8 +48,8 @@ typedef unsigned int ID; class Transaction { private: - unsigned int address, burstlength, thread, channel, bank, bankgroup, row, - column; + unsigned int address, burstlength, thread, channel, rank, + bankgroup, bank, row, column; Timespan span; Timespan spanOnDataStrobe; ID id; @@ -57,9 +57,9 @@ private: public: Transaction(ID id, unsigned int address, unsigned int burstlength, - unsigned int thread, unsigned int channel, unsigned int bank, - unsigned int bankgroup, unsigned int row, unsigned int column, Timespan span, - Timespan spanOnDataStrobe); + unsigned int thread, unsigned int channel, unsigned int rank, + unsigned int bankgroup, unsigned int bank, unsigned int row, unsigned int column, + Timespan span, Timespan spanOnDataStrobe); void draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, bool highlight, @@ -85,14 +85,18 @@ public: { return channel; } - unsigned int Bank() const + unsigned int Rank() const { - return bank; + return rank; } unsigned int BankGroup() const { return bankgroup; } + unsigned int Bank() const + { + return bank; + } unsigned int Row() const { return row; diff --git a/DRAMSys/traceAnalyzer/data/QueryTexts.h b/DRAMSys/traceAnalyzer/data/QueryTexts.h index aeccca6d..96aab29e 100644 --- a/DRAMSys/traceAnalyzer/data/QueryTexts.h +++ b/DRAMSys/traceAnalyzer/data/QueryTexts.h @@ -46,7 +46,7 @@ struct TransactionQueryTexts { TransactionQueryTexts() { queryHead = - "SELECT Transactions.ID AS TransactionID, Ranges.begin, Ranges.end,DataStrobeBegin,DataStrobeEnd, Address,Burstlength, TThread, TChannel, TBank,TBankgroup, TRow, TColumn,Phases.ID AS PhaseID, PhaseName, PhaseBegin, PhaseEnd " + "SELECT Transactions.ID AS TransactionID, Ranges.begin, Ranges.end,DataStrobeBegin,DataStrobeEnd, Address,Burstlength, TThread, TChannel, TRank, TBankgroup, TBank, TRow, TColumn,Phases.ID AS PhaseID, PhaseName, PhaseBegin, PhaseEnd " " FROM Transactions INNER JOIN Phases ON Phases.Transact = Transactions.ID INNER JOIN Ranges ON Transactions.Range = Ranges.ID "; selectTransactionsByTimespan = queryHead + diff --git a/DRAMSys/traceAnalyzer/data/tracedb.cpp b/DRAMSys/traceAnalyzer/data/tracedb.cpp index 305ebcb5..c3ec15dd 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.cpp +++ b/DRAMSys/traceAnalyzer/data/tracedb.cpp @@ -70,6 +70,7 @@ TraceDB::TraceDB(QString path, bool openExisting) dropAndCreateTables(); prepareQueries(); generalInfo = getGeneralInfoFromDB(); + commandLengths = getCommandLengthsFromDB(); } void TraceDB::prepareQueries() @@ -164,7 +165,7 @@ shared_ptr TraceDB::getNextPrecharge(ID currentTransactionId) { QSqlQuery query(database); QString queryText = queryTexts.queryHead + - "WHERE TransactionID > :currentID AND PhaseName IN ('PRE','PRE_ALL') LIMIT 1"; + "WHERE TransactionID > :currentID AND PhaseName IN ('PRE','PREA') LIMIT 1"; query.prepare(queryText); query.bindValue(":currentID", currentTransactionId); @@ -237,22 +238,24 @@ ID TraceDB::getTransactionIDFromPhaseID(ID phaseID) GeneralInfo TraceDB::getGeneralInfoFromDB() { QSqlQuery query(database); - query.prepare("SELECT NumberOfTransactions,TraceEnd,NumberOfBanks,Clk,UnitOfTime,Traces,Memspec,MCconfig, WindowSize, ControllerThread FROM GeneralInfo"); + query.prepare("SELECT NumberOfTransactions, TraceEnd, NumberOfRanks, NumberOfBanks, Clk, " + "UnitOfTime, Traces, Memspec, MCconfig, WindowSize, ControllerThread FROM GeneralInfo"); executeQuery(query); if (query.next()) { unsigned int numberOfTransactions = query.value(0).toInt(); traceTime traceEnd = query.value(1).toLongLong(); - unsigned int numberOfBanks = query.value(2).toInt(); - unsigned int clkPeriod = query.value(3).toInt(); - QString unitOfTime = query.value(4).toString(); + unsigned int numberOfRanks = query.value(2).toInt(); + unsigned int numberOfBanks = query.value(3).toInt(); + unsigned int clkPeriod = query.value(4).toInt(); + QString unitOfTime = query.value(5).toString(); unsigned int numberOfPhases = getNumberOfPhases(); - QString traces = "Traces: " + query.value(5).toString(); - QString memspec = "Memspec: " + query.value(6).toString(); - QString mcconfig = "MCconfig: " + query.value(7).toString(); - unsigned int windowSize = query.value(8).toInt(); - unsigned int controllerThread = query.value(9).toUInt(); + QString traces = "Traces: " + query.value(6).toString(); + QString memspec = "Memspec: " + query.value(7).toString(); + QString mcconfig = "MCconfig: " + query.value(8).toString(); + unsigned int windowSize = query.value(9).toInt(); + unsigned int controllerThread = query.value(10).toUInt(); QString description = (traces + "\n"); description += mcconfig + "\n"; @@ -265,14 +268,48 @@ GeneralInfo TraceDB::getGeneralInfoFromDB() description += "Window size:" + QString::number(windowSize) + "\n"; return GeneralInfo(numberOfTransactions, numberOfPhases, Timespan(0, traceEnd), - numberOfBanks, description, unitOfTime, clkPeriod, windowSize, - controllerThread); + numberOfRanks, numberOfBanks, description, unitOfTime, + clkPeriod, windowSize, controllerThread); } else { throw sqlException("Tracefile corrupted. No general info table", this->pathToDB.toStdString()); } } +CommandLengths TraceDB::getCommandLengthsFromDB() +{ + QSqlQuery query(database); + query.prepare("SELECT * FROM CommandLengths"); + executeQuery(query); + + if (query.next()) + { + unsigned ACT = query.value(0).toInt(); + unsigned PRE = query.value(1).toInt(); + unsigned PREA = query.value(2).toInt(); + unsigned RD = query.value(3).toInt(); + unsigned RDA = query.value(4).toInt(); + unsigned WR = query.value(5).toInt(); + unsigned WRA = query.value(6).toInt(); + unsigned REFA = query.value(7).toInt(); + unsigned REFB = query.value(8).toInt(); + unsigned PDEA = query.value(9).toInt(); + unsigned PDXA = query.value(10).toInt(); + unsigned PDEP = query.value(11).toInt(); + unsigned PDXP = query.value(12).toInt(); + unsigned SREFEN = query.value(13).toInt(); + unsigned SREFEX = query.value(14).toInt(); + + return CommandLengths(ACT, PRE, PREA, RD, RDA, WR, WRA, REFA, REFB, + PDEA, PDXA, PDEP, PDXP, SREFEN, SREFEX); + } + else + { + throw sqlException("Tracefile corrupted. No command lengths table", + this->pathToDB.toStdString()); + } +} + unsigned int TraceDB::getNumberOfPhases() { QSqlQuery query(database); @@ -346,22 +383,23 @@ vector> TraceDB::parseTransactionsFromQuery( currentID = id; Timespan span(query.value(1).toLongLong(), query.value(2).toLongLong()); Timespan spanOnStrobe(query.value(3).toLongLong(), query.value(4).toLongLong()); - unsigned int address = query.value(5).toInt(); + unsigned int address = query.value(5).toInt(); unsigned int burstlength = query.value(6).toInt(); unsigned int thread = query.value(7).toInt(); unsigned int channel = query.value(8).toInt(); - unsigned int bank = query.value(9).toInt(); - unsigned int bankgroup = query.value(10).toInt(); - unsigned int row = query.value(11).toInt(); - unsigned int column = query.value(12).toInt(); - result.push_back(shared_ptr(new Transaction(id, address, - burstlength, thread, channel, bank, bankgroup, row, column, span, - spanOnStrobe))); + unsigned int rank = query.value(9).toInt(); + unsigned int bankgroup = query.value(10).toInt(); + unsigned int bank = query.value(11).toInt(); + unsigned int row = query.value(12).toInt(); + unsigned int column = query.value(13).toInt(); + result.push_back(shared_ptr(new Transaction(id, address, burstlength, + thread, channel, rank, bankgroup, bank, row, column, + span, spanOnStrobe))); } - unsigned int phaseID = query.value(13).toInt(); - QString phaseName = query.value(14).toString(); - Timespan span(query.value(15).toLongLong(), query.value(16).toLongLong()); + unsigned int phaseID = query.value(14).toInt(); + QString phaseName = query.value(15).toString(); + Timespan span(query.value(16).toLongLong(), query.value(17).toLongLong()); result.at(result.size() - 1)->addPhase(PhaseFactory::CreatePhase(phaseID, phaseName, span, result.at(result.size() - 1), *this)); } diff --git a/DRAMSys/traceAnalyzer/data/tracedb.h b/DRAMSys/traceAnalyzer/data/tracedb.h index 7ab07040..60afb9b8 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.h +++ b/DRAMSys/traceAnalyzer/data/tracedb.h @@ -48,6 +48,7 @@ #include #include "businessObjects/transaction.h" #include "businessObjects/generalinfo.h" +#include "businessObjects/commandlengths.h" #include "businessObjects/phases/phasefactory.h" #include "businessObjects/comment.h" #include "QueryTexts.h" @@ -76,6 +77,11 @@ public: return generalInfo; } + const CommandLengths &getCommandLengths() + { + return commandLengths; + } + std::vector> getTransactionsWithCustomQuery( QString queryText); std::vector> getTransactionsInTimespan( @@ -100,6 +106,7 @@ private: QString pathToDB; QSqlDatabase database; GeneralInfo generalInfo; + CommandLengths commandLengths; QSqlQuery insertPhaseQuery; QSqlQuery insertTransactionQuery; @@ -122,6 +129,7 @@ private: unsigned int getNumberOfPhases(); GeneralInfo getGeneralInfoFromDB(); + CommandLengths getCommandLengthsFromDB(); }; diff --git a/DRAMSys/traceAnalyzer/evaluationtool.h b/DRAMSys/traceAnalyzer/evaluationtool.h index 32977f5b..81364e07 100644 --- a/DRAMSys/traceAnalyzer/evaluationtool.h +++ b/DRAMSys/traceAnalyzer/evaluationtool.h @@ -41,7 +41,13 @@ #define EVALUATIONTOOL_H #include "selectmetrics.h" + +// Workaround for CMAKE and Python +#ifdef slots +#undef slots +#endif #include + #include #include #include diff --git a/DRAMSys/traceAnalyzer/mainwindow.cpp b/DRAMSys/traceAnalyzer/mainwindow.cpp index 7155466f..9bdc2565 100644 --- a/DRAMSys/traceAnalyzer/mainwindow.cpp +++ b/DRAMSys/traceAnalyzer/mainwindow.cpp @@ -61,7 +61,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->qwtPlot->setAxisScale(QwtPlot::xBottom, traceNavigator->GeneralTraceInfo().TraceSpan().Begin(), traceNavigator->GeneralTraceInfo().TraceSpan().End()); - unsigned int banksize = traceNavigator -> GeneralTraceInfo().NumberOfBanks(); + unsigned int banksize = traceNavigator->GeneralTraceInfo().NumberOfBanks(); ui->qwtPlot->setAxisScale(QwtPlot::yLeft, 0.0, banksize + 3, 1.0); PhaseCollectionDrawingProperties *drawingProperties = new diff --git a/DRAMSys/traceAnalyzer/presentation/pornotracescroller.cpp b/DRAMSys/traceAnalyzer/presentation/pornotracescroller.cpp index 45b46ec9..8b66efd2 100644 --- a/DRAMSys/traceAnalyzer/presentation/pornotracescroller.cpp +++ b/DRAMSys/traceAnalyzer/presentation/pornotracescroller.cpp @@ -44,7 +44,7 @@ PornoTraceScroller::PornoTraceScroller(QWidget *parent): QwtPlot(parent), isInitialized(false), drawingProperties(false, false, - ColorGrouping::Transaction) + ColorGrouping::PhaseType) { setAxisScaleDraw(xBottom, new EngineeringScaleDraw); canvas()->setCursor(Qt::ArrowCursor); @@ -86,10 +86,11 @@ void PornoTraceScroller::setUpTracePlotItem() void PornoTraceScroller::setUpDrawingProperties() { - unsigned int numberOfBanks = navigator -> GeneralTraceInfo().numberOfBanks; - drawingProperties.numberOfBanks = numberOfBanks; - drawingProperties.yValResponse = numberOfBanks; - drawingProperties.yValRequest = numberOfBanks + 1; + drawingProperties.numberOfRanks = navigator->GeneralTraceInfo().numberOfRanks; + drawingProperties.numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks; + drawingProperties.banksPerRank = drawingProperties.numberOfBanks / drawingProperties.numberOfRanks; + drawingProperties.yValResponse = drawingProperties.numberOfBanks; + drawingProperties.yValRequest = drawingProperties.numberOfBanks + 1; drawingProperties.yValCommandBus = -3; drawingProperties.yValDataBus = -4; } @@ -97,7 +98,7 @@ void PornoTraceScroller::setUpDrawingProperties() void PornoTraceScroller::setUpAxis() { - setAxisScale(yLeft, -1, navigator -> GeneralTraceInfo().numberOfBanks + 2, 1.0); + setAxisScale(yLeft, -1, navigator->GeneralTraceInfo().numberOfBanks + 2, 1.0); axisScaleDraw(yLeft)->enableComponent(QwtAbstractScaleDraw::Labels, false ); axisScaleDraw(yLeft)->enableComponent(QwtAbstractScaleDraw::Ticks, false ); } diff --git a/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h b/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h index 21351fc3..64496973 100644 --- a/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h +++ b/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h @@ -53,20 +53,23 @@ struct TraceDrawingProperties { int yValRequest; int yValCommandBus; int yValDataBus; + unsigned int numberOfRanks; unsigned int numberOfBanks; + unsigned int banksPerRank; TraceDrawingProperties() : drawText(true), drawBorder(true), - colorGrouping(ColorGrouping::Transaction) {} + colorGrouping(ColorGrouping::PhaseType) {} TraceDrawingProperties(bool drawText, bool drawBorder, ColorGrouping colorGrouping) : drawText(drawText), drawBorder(drawBorder), colorGrouping(colorGrouping) {} - TraceDrawingProperties(bool drawText, bool drawBorder, - ColorGrouping colorGrouping, int yValResponse, int yValRequest, - int yValCommandBus, int yValDataBus, unsigned int numberOfBanks) : + TraceDrawingProperties(bool drawText, bool drawBorder, ColorGrouping colorGrouping, + int yValResponse, int yValRequest, int yValCommandBus, int yValDataBus, + unsigned int numberOfRanks, unsigned int numberOfBanks) : drawText(drawText), drawBorder(drawBorder), colorGrouping(colorGrouping), yValResponse(yValResponse), yValRequest(yValRequest), yValCommandBus(yValCommandBus), yValDataBus(yValDataBus), - numberOfBanks(numberOfBanks) {} + numberOfRanks(numberOfRanks), numberOfBanks(numberOfBanks), + banksPerRank(numberOfBanks / numberOfRanks) {} QHash getLabels() const { diff --git a/DRAMSys/traceAnalyzer/presentation/traceplot.cpp b/DRAMSys/traceAnalyzer/presentation/traceplot.cpp index 65434781..27620d4a 100644 --- a/DRAMSys/traceAnalyzer/presentation/traceplot.cpp +++ b/DRAMSys/traceAnalyzer/presentation/traceplot.cpp @@ -158,7 +158,7 @@ void TracePlot::setUpContextMenu() contextMenu->addActions({deselectAll}); QMenu *colorGroupingSubMenu = new QMenu("Group by", contextMenu); - colorGroupingSubMenu->addActions({setColorGroupingTransaction, setColorGroupingPhase, setColorGroupingThread}); + colorGroupingSubMenu->addActions({setColorGroupingPhase, setColorGroupingTransaction, setColorGroupingThread}); contextMenu->addMenu(colorGroupingSubMenu); QMenu *goToSubMenu = new QMenu("Go to", contextMenu); @@ -205,10 +205,11 @@ void TracePlot::connectNavigatorQ_SIGNALS() void TracePlot::setUpDrawingProperties() { - unsigned int numberOfBanks = navigator -> GeneralTraceInfo().numberOfBanks; - drawingProperties.numberOfBanks = numberOfBanks; - drawingProperties.yValResponse = numberOfBanks; - drawingProperties.yValRequest = numberOfBanks + 1; + drawingProperties.numberOfRanks = navigator->GeneralTraceInfo().numberOfRanks; + drawingProperties.numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks; + drawingProperties.banksPerRank = drawingProperties.numberOfBanks / drawingProperties.numberOfRanks; + drawingProperties.yValResponse = drawingProperties.numberOfBanks; + drawingProperties.yValRequest = drawingProperties.numberOfBanks + 1; drawingProperties.yValCommandBus = -3; drawingProperties.yValDataBus = -4; } @@ -252,7 +253,7 @@ void TracePlot::setUpZoom() void TracePlot::setUpAxis() { - int numberOfBanks = navigator -> GeneralTraceInfo().numberOfBanks; + int numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks; setAxisScale(yLeft, -5, numberOfBanks + 2, 1.0); setAxisScaleDraw(yLeft, new CustomLabelScaleDraw( diff --git a/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp b/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp index 49211af4..1809d53b 100644 --- a/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp +++ b/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp @@ -101,8 +101,9 @@ TransactionTreeWidget::TransactionTreeItem::TransactionTreeItem( this->addChild(new QTreeWidgetItem( {"Lenght", prettyFormatTime(transaction->Span().timeCovered())})); this->addChild(new QTreeWidgetItem( {"Channel", QString::number(transaction->Channel())})); - this->addChild(new QTreeWidgetItem( {"Bank", QString::number(transaction->Bank())} )); + this->addChild(new QTreeWidgetItem( {"Rank", QString::number(transaction->Rank())} )); this->addChild(new QTreeWidgetItem( {"Bankgroup", QString::number(transaction->BankGroup())} )); + this->addChild(new QTreeWidgetItem( {"Bank", QString::number(transaction->Bank())} )); this->addChild(new QTreeWidgetItem( {"Row", QString::number(transaction->Row())} )); this->addChild(new QTreeWidgetItem( {"Column", QString::number(transaction->Column())} )); this->addChild(new QTreeWidgetItem( {"Address", QString("0x") + QString::number(transaction->Address(), 16)} )); diff --git a/DRAMSys/traceAnalyzer/scripts/metrics.py b/DRAMSys/traceAnalyzer/scripts/metrics.py index feebd957..d3fc044d 100644 --- a/DRAMSys/traceAnalyzer/scripts/metrics.py +++ b/DRAMSys/traceAnalyzer/scripts/metrics.py @@ -239,8 +239,8 @@ def ACT_count(connection): @metric -def PRE_ALL_count(connection): - return get_phase_occurrences(connection, 'PRE_ALL') +def PREA_count(connection): + return get_phase_occurrences(connection, 'PREA') @metric @@ -327,17 +327,17 @@ def bank_overlap_ratio(connection): cursor.execute(""" select p1.PhaseBegin, p1.PhaseName from Phases p1 where - (p1.PhaseName = "ACT" or p1.PhaseName = "PRE_ALL" or p1.PhaseName = "PRE" or p1.PhaseName = "RDA" or p1.PhaseName = "WRA" or p1.PhaseName = "PREB" or p1.PhaseName = "ACTB") + (p1.PhaseName = "ACT" or p1.PhaseName = "PREA" or p1.PhaseName = "PRE" or p1.PhaseName = "RDA" or p1.PhaseName = "WRA" or p1.PhaseName = "PREB" or p1.PhaseName = "ACTB") order by PhaseBegin """) - prevPhase = "PRE_ALL" + prevPhase = "PREA" prevTime = 0 for c in cursor: trace.append([(int(c[0]/clk)), c[1]]) # Insert a pseudo precharge all to mark the end of the trace - trace.append([traceEnd, "PRE_ALL"]) + trace.append([traceEnd, "PREA"]) bankCounter = 0 bankTime = [] @@ -362,7 +362,7 @@ def bank_overlap_ratio(connection): print("Unexpected ACT. bankCounter was {0} valid range is python range {1}".format(bankCounter, validBankRange)) elif t[1] == "ACTB": actbCnt += 1 - elif(t[1] == "PRE_ALL"): + elif(t[1] == "PREA"): bankCounter = 0 elif(t[1] == "PRE"): if (bankCounter > 0): @@ -403,7 +403,7 @@ def bank_overlap_ratio(connection): # @metric # def number_of_precharges(connection): # cursor = connection.cursor() -# cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('PRE','PRE_ALL','RDA','WRA')") +# cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('PRE','PREA','RDA','WRA')") # result = cursor.fetchone() # return result[0] diff --git a/DRAMSys/traceAnalyzer/scripts/tests.py b/DRAMSys/traceAnalyzer/scripts/tests.py index 2d3becd9..dd5c022f 100755 --- a/DRAMSys/traceAnalyzer/scripts/tests.py +++ b/DRAMSys/traceAnalyzer/scripts/tests.py @@ -36,12 +36,10 @@ class DramConfig(object): tCKE = 0 # min time in pdna or pdnp tXP = 0 # min delay to row access command after pdnpx pdnax tXPDLL = 0 # min delay to row access command after pdnpx pdnax for dll commands - tXSR = 0 # min delay to row access command after srefx - tXSRDLL = 0 # min delay to row access command after srefx for dll commands + tXS = 0 # min delay to row access command after srefx + tXSDLL = 0 # min delay to row access command after srefx for dll commands tAL = 0 # additive delay (delayed execution in dram) - tRFC = 0 # min ref->act delay 1X - tRFC2 = 0 # min ref->act delay 2X - tRFC4 = 0 # min ref->act delay 4X + tRFC = 0 # min ref->act delay tREFI = 0 # time between REF commands def readConfigFromFiles(self, connection): @@ -84,8 +82,8 @@ class DramConfig(object): self.tCKE = self.clk * memspec.getIntValue("CKE") self.tXP = self.clk * memspec.getIntValue("XP") self.tXPDLL = self.tXP - self.tXSR = self.clk * memspec.getIntValue("XS") - self.tXSRDLL = self.tXSR + self.tXS = self.clk * memspec.getIntValue("XS") + self.tXSDLL = self.tXS self.tAL = self.clk * memspec.getIntValue("AL") self.tRFC = self.clk * memspec.getIntValue("RFC") self.tREFI = self.clk * memspec.getIntValue("REFI") @@ -111,13 +109,18 @@ class DramConfig(object): self.tCKE = self.clk * memspec.getIntValue("CKE") self.tXP = self.clk * memspec.getIntValue("XP") self.tXPDLL = self.clk * memspec.getIntValue("XPDLL") - self.tXSR = self.clk * memspec.getIntValue("XS") - self.tXSRDLL = self.clk * memspec.getIntValue("XSDLL") + self.tXS = self.clk * memspec.getIntValue("XS") + self.tXSDLL = self.clk * memspec.getIntValue("XSDLL") self.tAL = self.clk * memspec.getIntValue("AL") - self.tRFC = self.clk * memspec.getIntValue("RFC") - self.tRFC2 = self.clk * memspec.getIntValue("RFC2") - self.tRFC4 = self.clk * memspec.getIntValue("RFC4") - self.tREFI = self.clk * memspec.getIntValue("REFI") + if (self.refMode == "4"): + self.tRFC = self.clk * memspec.getIntValue("RFC4") + self.tREFI = self.clk * (memspec.getIntValue("REFI") / 4) + elif (self.refMode == "2"): + self.tRFC = self.clk * memspec.getIntValue("RFC2") + self.tREFI = self.clk * (memspec.getIntValue("REFI") / 2) + else: + self.tRFC = self.clk * memspec.getIntValue("RFC") + self.tREFI = self.clk * memspec.getIntValue("REFI") elif (self. memoryType == "DDR3"): self.nActivateWindow = 4 @@ -140,8 +143,8 @@ class DramConfig(object): self.tCKE = self.clk * memspec.getIntValue("CKE") self.tXP = self.clk * memspec.getIntValue("XP") self.tXPDLL = self.clk * memspec.getIntValue("XPDLL") - self.tXSR = self.clk * memspec.getIntValue("XS") - self.tXSRDLL = self.clk * memspec.getIntValue("XSDLL") + self.tXS = self.clk * memspec.getIntValue("XS") + self.tXSDLL = self.clk * memspec.getIntValue("XSDLL") self.tAL = self.clk * memspec.getIntValue("AL") self.tRFC = self.clk * memspec.getIntValue("RFC") self.tREFI = self.clk * memspec.getIntValue("REFI") @@ -233,9 +236,9 @@ def commandbus_slots_are_used_once(connection): cursor = connection.cursor() if (dramconfig.bankwiseLogic == "1"): - excludedPhases = "('REQ','RESP','PRE_ALL')" + excludedPhases = "('REQ','RESP','PREA')" else: - excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF','REFA')" + excludedPhases = "('REQ','RESP','PREA','PDNA','PDNP','SREF','REFA')" query = """SELECT PhaseBegin,count FROM (SELECT phaseBegin,count(phasebegin) AS count FROM Phases WHERE PhaseName NOT IN """ + excludedPhases + """ AND phasebegin>0 GROUP BY phaseBegin) WHERE count>1""" @@ -258,7 +261,7 @@ def phase_transitions_are_valid(connection): if (dramconfig.bankwiseLogic == "1"): validTransitions['PRE'] = set(['ACT', 'REFB', 'SREFB']) - validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PRE', 'PRE_ALL']) + validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PRE', 'PREA']) validTransitions['RD'] = set(['PRE', 'RD', 'RDA', 'WR', 'WRA', 'PDNAB']) validTransitions['WR'] = set(['PRE', 'RD', 'RDA', 'WR', 'WRA', 'PDNAB']) @@ -271,20 +274,20 @@ def phase_transitions_are_valid(connection): validTransitions['PDNPB'] = set(['ACT', 'REFB', 'SREFB']) validTransitions['SREFB'] = set(['ACT', 'REFB']) else: - validTransitions['PRE'] = set(['ACT', 'PRE_ALL', 'REFA']) - validTransitions['PRE_ALL'] = set(['REFA', 'SREF']) - validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PRE_ALL']) + validTransitions['PRE'] = set(['ACT', 'PREA', 'REFA']) + validTransitions['PREA'] = set(['REFA', 'SREF']) + validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PREA']) - validTransitions['RD'] = set(['PRE', 'PRE_ALL', 'RD', 'RDA', 'WR', 'WRA', 'PDNA']) - validTransitions['WR'] = set(['PRE', 'PRE_ALL', 'RD', 'RDA', 'WR', 'WRA', 'PDNA']) - validTransitions['RDA'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP']) - validTransitions['WRA'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP']) + validTransitions['RD'] = set(['PRE', 'PREA', 'RD', 'RDA', 'WR', 'WRA', 'PDNA']) + validTransitions['WR'] = set(['PRE', 'PREA', 'RD', 'RDA', 'WR', 'WRA', 'PDNA']) + validTransitions['RDA'] = set(['PREA', 'ACT', 'REFA', 'PDNA', 'PDNP']) + validTransitions['WRA'] = set(['PREA', 'ACT', 'REFA', 'PDNA', 'PDNP']) - validTransitions['REFA'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP', 'SREF']) + validTransitions['REFA'] = set(['PREA', 'ACT', 'REFA', 'PDNA', 'PDNP', 'SREF']) - validTransitions['PDNA'] = set(['PRE', 'PRE_ALL', 'ACT', 'RD', 'RDA', 'WR', 'WRA', 'REFA', 'PDNA', 'PDNP']) - validTransitions['PDNP'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP', 'SREF']) - validTransitions['SREF'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP']) + validTransitions['PDNA'] = set(['PRE', 'PREA', 'ACT', 'RD', 'RDA', 'WR', 'WRA', 'REFA', 'PDNA', 'PDNP']) + validTransitions['PDNP'] = set(['PREA', 'ACT', 'REFA', 'PDNA', 'PDNP', 'SREF']) + validTransitions['SREF'] = set(['PREA', 'ACT', 'REFA', 'PDNA', 'PDNP']) if (dramconfig.bankwiseLogic == "1"): query = """SELECT @@ -294,13 +297,13 @@ def phase_transitions_are_valid(connection): WHERE (TBank=:bank) AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin""" else: - # REFA, PRE_ALL, PDNA, PDNP and SREF are attributed to Bank 0 therefore this must be added to the order evaluation: + # REFA, PREA, PDNA, PDNP and SREF are attributed to Bank 0 therefore this must be added to the order evaluation: query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE - ((TBank=:bank) OR PhaseName IN ('PRE_ALL', 'SREF', 'PDNP', 'PDNA', 'REFA')) + ((TBank=:bank) OR PhaseName IN ('PREA', 'SREF', 'PDNP', 'PDNA', 'REFA')) AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin""" for bankNumber in range(dramconfig.numberOfBanks): @@ -321,24 +324,24 @@ def timing_constraint(FirstPhase, SecondPhase): FirstPhaseName = FirstPhase[0] SecondPhaseName = SecondPhase[0] - if (FirstPhaseName == "PRE" or FirstPhaseName == "PRE_ALL"): + if ((FirstPhaseName == "PRE" or FirstPhaseName == "PREA") and SecondPhaseName != "PREA"): return dramconfig.tRP elif (FirstPhaseName == "ACT"): return dramconfig.tRCD elif (FirstPhaseName == "RD"): - if (SecondPhaseName in ["PRE, PRE_ALL"]): + if (SecondPhaseName in ["PRE, PREA"]): return dramconfig.tRTP elif (SecondPhaseName in ["RD, RDA"]): - return max(dramconfig.tCCD_L, getReadAccessTime()) + return max(dramconfig.tCCD_L, dramconfig.getReadAccessTime()) elif (SecondPhase in ["WR", "WRA"]): - return dramconfig.tRL + getReadAccessTime() - dramconfig.tWL + 2 * dramconfig.clk + return dramconfig.tRL + dramconfig.getReadAccessTime() - dramconfig.tWL + 2 * dramconfig.clk elif (SecondPhase == "PDNA"): - return dramconfig.tRL + getReadAccessTime() + dramconfig.clk + return dramconfig.tRL + dramconfig.getReadAccessTime() + dramconfig.clk elif (FirstPhaseName == "WR"): - if (SecondPhaseName in ["PRE, PRE_ALL", "PDNA"]): + if (SecondPhaseName in ["PRE, PREA", "PDNA"]): return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR elif (SecondPhaseName in ["RD, RDA"]): return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWTR_L @@ -346,24 +349,23 @@ def timing_constraint(FirstPhase, SecondPhase): return max(dramconfig.tCCD_L, burstlength/dramconfig.dataRate) elif (FirstPhaseName == "RDA"): - if (SecondPhaseName in ["ACT", "PRE_ALL", "REFA"]): + if (SecondPhaseName in ["ACT", "REFA"]): return dramconfig.tRTP + dramconfig.tRP + elif (SecondPhaseName == "PREA"): + return dramconfig.tRTP elif (SecondPhaseName in ["PDNA", "PDNP"]): - return dramconfig.tRL + getReadAccessTime() + dramconfig.clk + return dramconfig.tRL + dramconfig.getReadAccessTime() + dramconfig.clk elif (FirstPhaseName == "WRA"): - if (SecondPhaseName in ["ACT", "PRE_ALL", "REFA"]): - return dramconfig.tWL + getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP + if (SecondPhaseName in ["ACT", "REFA"]): + return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP + elif (SecondPhaseName == "PREA"): + return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR elif (SecondPhaseName in ["PDNA", "PDNP"]): return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.clk elif (FirstPhaseName == "REFA"): - if dramconfig.refMode == "4": - return dramconfig.tRFC4 - elif dramconfig.refMode == "2": - return dramconfig.tRFC2 - else: - return dramconfig.tRFC + return dramconfig.tRFC elif (FirstPhaseName in ["PDNA", "PDNP"]): # print("{0}".format(FirstPhaseName)) @@ -374,7 +376,7 @@ def timing_constraint(FirstPhase, SecondPhase): return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXP - dramconfig.clk elif (FirstPhaseName == "SREF"): - return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXSR - dramconfig.clk + return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXS - dramconfig.clk return 0 @@ -390,7 +392,7 @@ def timing_constraits_on_the_same_bank_hold(connection): AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin""" else: query = """SELECT PhaseName, phases.ID, PhaseBegin, PhaseEnd FROM phases INNER JOIN transactions ON phases.transact=transactions.ID - WHERE ((TBank=:bank) OR PhaseName IN ('PRE_ALL', 'SREF', 'PDNP', 'PDNA', 'REFA')) AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin""" + WHERE ((TBank=:bank) OR PhaseName IN ('PREA', 'SREF', 'PDNP', 'PDNA', 'REFA')) AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin""" for bankNumber in range(dramconfig.numberOfBanks): cursor.execute(query, {"bank": bankNumber}) lastRow = cursor.fetchone() @@ -416,21 +418,21 @@ def row_buffer_is_used_correctly(connection): FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE - ((TBank=:bank) OR (PhaseNAME = "REFA" AND TBank=0) OR (PhaseNAME = "PRE_ALL" AND TBank=0)) + ((TBank=:bank) OR (PhaseNAME = "REFA" AND TBank=0) OR (PhaseNAME = "PREA" AND TBank=0)) AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin""" else: - # REFA, PRE_ALL, PDNA, PDNP and SREF are stored to bank0 for all the other banks we have also to grep this command: - # PhaseName IN ('PRE_ALL', 'SREF', 'PDNP', 'PDNA', 'REFA') + # REFA, PREA, PDNA, PDNP and SREF are stored to bank0 for all the other banks we have also to grep this command: + # PhaseName IN ('PREA', 'SREF', 'PDNP', 'PDNA', 'REFA') query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE - ((TBank=:bank) OR PhaseName IN ('PRE_ALL', 'SREF', 'PDNP', 'PDNA', 'REFA')) + ((TBank=:bank) OR PhaseName IN ('PREA', 'SREF', 'PDNP', 'PDNA', 'REFA')) AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin""" # phases that precharge the bank and close the rowbuffer - prechargingPhases = set(['PRE', 'PRE_ALL', 'RDA', 'WRA']) + prechargingPhases = set(['PRE', 'PREA', 'RDA', 'WRA']) # phases that require the bank to be in active state and the rowbuffer to be opened accessingPhases = set(['RD', 'RDA', 'WR', 'WRA', 'PRE']) @@ -694,8 +696,8 @@ def read_holds_dll_constraint_after_sref(connection): for currentRow in cursor: if (currentRow[2] in ["RD", "RDA"] and lastRow[2] == 'SREF'): srefEndToRead = currentRow[1] - (lastRow[1] - dramconfig.clk) - if (srefEndToRead < dramconfig.tXSRDLL): - return TestFailed("Read {0} starts {1} after end of sref {2}. Minimum time is {3}".format(currentRow[0], formatTime(srefEndToRead), lastRow[0], formatTime(dramconfig.tXSRDLL))) + if (srefEndToRead < dramconfig.tXSDLL): + return TestFailed("Read {0} starts {1} after end of sref {2}. Minimum time is {3}".format(currentRow[0], formatTime(srefEndToRead), lastRow[0], formatTime(dramconfig.tXSDLL))) lastRow = currentRow return TestSuceeded() diff --git a/DRAMSys/traceAnalyzer/traceAnalyzer.pro b/DRAMSys/traceAnalyzer/traceAnalyzer.pro deleted file mode 100644 index e30300c5..00000000 --- a/DRAMSys/traceAnalyzer/traceAnalyzer.pro +++ /dev/null @@ -1,174 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2013-11-26T20:21:15 -# -#------------------------------------------------- - -QT += core gui -QT += sql -CONFIG += no_keywords - - -CONFIG += python - - -unix:!macx { - # Python library and header files - python_home = $$(PYTHON_HOME) - isEmpty(python_home) { - python_home = /opt/python/lib - } - message(Python home is $${python_home}) - - python_headers = $$(PYTHON_HEADERS) - isEmpty(python_headers) { - python_headers = /opt/python/include/python3.5m - } - message(Getting python headers from $${python_headers}) - - QMAKE_CXXFLAGS += -std=c++11 - CONFIG += qwt - QMAKE_CXXFLAGS += -Xlinker -export-dynamic - QMAKE_RPATHDIR += $${libqwt_home} - message(Linker options QMAKE_RPATHDIR is $${QMAKE_RPATHDIR}) - - CONFIG(python){ - libpython_vers = $$(LIBPYTHON_VERSION) - isEmpty(libpython_vers) { - libpython_vers = 3.5m - } - message(Lib Python version is $${libpython_vers}) - LIBS += -L$${python_home} -lpython$${libpython_vers} - INCLUDEPATH += $${python_headers} - } -} - -macx: { - message(Building on a MAC) - - CONFIG += c++11 - QMAKE_CXXFLAGS += -std=c++0x -stdlib=libc++ - - QMAKE_LFLAGS += -F$$(LIBQWT_HOME) - LIBS += -F$$(LIBQWT_HOME) -framework qwt - INCLUDEPATH += $$(LIBQWT_HEADERS) - DEPENDPATH += $$replace(LIBQWT_HOME, lib, ) - - INCLUDEPATH += /usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/Headers/ - LIBS += -L/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/ -lpython3.6 - - CONFIG-=app_bundle -} - -# QWT library and header files -libqwt_home = $$(LIBQWT_HOME) -isEmpty(libqwt_home) { - libqwt_home = /opt/qwt/lib -} -message(LIBQWT path is $${libqwt_home}) - - -libqwt_headers = $$(LIBQWT_HEADERS) -isEmpty(libqwt_headers) { - libqwt_headers = /opt/qwt/include -} -message(Getting LIBQWT headers from $${libqwt_headers}) - -CONFIG(qwt){ - LIBS += -L$${libqwt_home}/ -lqwt -lutil - INCLUDEPATH += $${libqwt_headers} -} - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = traceAnalyzer -TEMPLATE = app - -#copy python scripts -config.path = $${OUT_PWD}/scripts -config.files = scripts/* -INSTALLS += config - -SOURCES += main.cpp\ - businessObjects/transaction.cpp \ - businessObjects/timespan.cpp \ - data/tracedb.cpp \ - presentation/tracenavigator.cpp \ - presentation/util/colorgenerator.cpp \ - presentation/tracedrawing.cpp \ - presentation/traceplotitem.cpp \ - gototimedialog.cpp \ - presentation/traceplot.cpp \ - tracefiletab.cpp \ - presentation/pornotracescroller.cpp \ - traceanalyzer.cpp \ - presentation/transactiontreewidget.cpp \ - presentation/commenttreewidget.cpp \ - presentation/util/clkgrid.cpp \ - queryeditor.cpp \ - presentation/selectedtransactiontreewidget.cpp \ - businessObjects/phases/phasefactory.cpp \ - presentation/debugmessagetreewidget.cpp \ - presentation/tracePlotMouseLabel.cpp \ - evaluationtool.cpp \ - selectmetrics.cpp \ - presentation/util/testlight.cpp \ - presentation/tracetesttreewidget.cpp \ - businessObjects/pythoncaller.cpp \ - businessObjects/tracetestresults.cpp \ - presentation/tracemetrictreewidget.cpp \ - businessObjects/phases/phase.cpp - -HEADERS += businessObjects/transaction.h \ - businessObjects/timespan.h \ - businessObjects/generalinfo.h \ - data/tracedb.h \ - presentation/tracenavigator.h \ - presentation/util/colorgenerator.h \ - presentation/util/engineeringScaleDraw.h \ - presentation/tracedrawingproperties.h \ - presentation/tracedrawing.h \ - presentation/traceplotitem.h \ - gototimedialog.h \ - presentation/traceplot.h \ - tracefiletab.h \ - presentation/pornotracescroller.h \ - traceanalyzer.h \ - presentation/transactiontreewidget.h \ - businessObjects/comment.h \ - presentation/commenttreewidget.h \ - businessObjects/tracetime.h \ - presentation/util/clkgrid.h \ - presentation/util/customlabelscaledraw.h \ - data/QueryTexts.h \ - queryeditor.h \ - presentation/selectedtransactiontreewidget.h \ - businessObjects/phases/phasefactory.h \ - presentation/debugmessagetreewidget.h \ - presentation/tracePlotMouseLabel.h \ - evaluationtool.h \ - selectmetrics.h \ - presentation/util/testlight.h \ - presentation/tracetesttreewidget.h \ - businessObjects/pythoncaller.h \ - businessObjects/testresult.h \ - businessObjects/tracetestresults.h \ - presentation/tracemetrictreewidget.h \ - businessObjects/calculatedMetric.h \ - businessObjects/tracecalculatedmetrics.h \ - businessObjects/phases/phase.h - - -FORMS += \ - gototimedialog.ui \ - tracefiletab.ui \ - traceanalyzer.ui \ - queryeditor.ui \ - preferences.ui \ - selectmetrics.ui \ - evaluationtool.ui - -# Additional Files: -include(scripts/scripts.pri) - -DISTFILES += ../DRAMSys.astylerc diff --git a/DRAMSys/unitTests/CommandMuxTests.cpp b/DRAMSys/unitTests/CommandMuxTests.cpp new file mode 100644 index 00000000..6fc2736c --- /dev/null +++ b/DRAMSys/unitTests/CommandMuxTests.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include "../library/src/controller/CommandMux.h" +#include "../library/src/controller/Command.h" + +class CommandMuxState +{ +public: + Command firstCommand; + Command secondCommand; + Command resultCommand; +}; + +class CommandMuxTestBase : public testing::Test +{ +public: + CommandMux *commandMux; + + tlm_generic_payload *firstPayload; + tlm_generic_payload *secondPayload; + + std::pair firstPair; + std::pair secondPair; + + std::vector> readyCommands; + + std::pair result; + + CommandMuxTestBase() + { + commandMux = new CommandMux(); + firstPayload = new tlm_generic_payload(); + secondPayload = new tlm_generic_payload(); + } + + ~CommandMuxTestBase() + { + delete commandMux; + delete firstPayload; + delete secondPayload; + } +}; + +class CommandMuxTestParam : public CommandMuxTestBase, public testing::WithParamInterface +{ +public: + CommandMuxTestParam() + { + commandMux->insertPayload(firstPayload); + commandMux->insertPayload(secondPayload); + + firstPair.first = GetParam().firstCommand; + firstPair.second = firstPayload; + secondPair.first = GetParam().secondCommand; + secondPair.second = secondPayload; + + readyCommands.push_back(secondPair); + readyCommands.push_back(firstPair); + result = commandMux->selectCommand(readyCommands); + } +}; + +TEST_P(CommandMuxTestParam, satisfiesCommandOrder) +{ + EXPECT_EQ(result.first, GetParam().resultCommand); +} + +INSTANTIATE_TEST_CASE_P(Default, CommandMuxTestParam, testing::Values( + CommandMuxState{Command::RD, Command::WR, Command::RD}, + CommandMuxState{Command::RD, Command::ACT, Command::ACT})); diff --git a/DRAMSys/unitTests/Testfile.h b/DRAMSys/unitTests/Testfile.h index 50726e5c..da025ef2 100644 --- a/DRAMSys/unitTests/Testfile.h +++ b/DRAMSys/unitTests/Testfile.h @@ -3,5 +3,5 @@ TEST(testsuite, test) { - EXPECT_EQ(commandToString(Command::Activate), "ACT"); + EXPECT_EQ(commandToString(Command::ACT), "ACT"); } diff --git a/DRAMSys/unitTests/unitTests.pro b/DRAMSys/unitTests/unitTests.pro index 375411e7..a39ed9a7 100644 --- a/DRAMSys/unitTests/unitTests.pro +++ b/DRAMSys/unitTests/unitTests.pro @@ -64,11 +64,15 @@ SOURCEHOME = ../library/src/ SOURCES += \ main.cpp \ + CommandMuxTests.cpp \ + $${SOURCEHOME}/controller/CommandMux.cpp \ $${SOURCEHOME}/controller/Command.cpp + HEADERS += \ Testfile.h \ + $${SOURCEHOME}/controller/CommandMux.h \ $${SOURCEHOME}/controller/Command.h DISTFILES += ../DRAMSys.astylerc diff --git a/README.md b/README.md index 42b094de..bc1c6595 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -DRAMSys 3.0 +DRAMSys 4.0 =========== **DRAMSys** [1] is a flexible DRAM subsystem design space exploration @@ -9,40 +9,21 @@ Pipeline Status: [![pipeline status](https://git.eit.uni-kl.de/ems/astdm/dram.sy [![Coverage report](https://git.eit.uni-kl.de/ems/astdm/dram.sys/badges/master/coverage.svg?job=coverage)](https://git.eit.uni-kl.de/ems/astdm/dram.sys/commits/master) ## Basic Setup -Open a terminal window, go to your home directory, create a directory for your -projects and change to it. - -```bash -$ cd -$ mkdir projects -$ cd projects -``` - -Configure git on your machine. Some basic configurations follow. - -```bash -$ git config --global user.name "FirstName OtherNames LastName" -$ git config --global user.email user@email -$ git config --global credential.helper 'cache --timeout=3600' -$ git config --global color.ui auto -``` - -Now clone the repository into a local folder on your computer. +Start using DRAMSys by cloning the current stable master branch: ```bash $ git clone --recursive https://git.eit.uni-kl.de/ems/astdm/dram.sys.git ``` The *--recursive* flag tells git to initialize all submodules within the -repository. **DRAMPower** [2] and **tinyxml** are examples third party -repositories that were embedded within the source tree as submodules. +repository, namely **DRAMPower** [2], **SystemC** and **tinyxml**. Now you can implement, test, commit and push features into a **branch**. When you consider your work stable enough to be merged into the master branch it is time to open a **merge request** using the web interface. -Your changes will be reviewed and finally integrated into the master branch. +Your changes will be reviewed and might be integrated into the master branch. After cloning go to the project directory. @@ -66,87 +47,12 @@ $ ls ``` You can use [utils/install_deb.sh](./utils/install_deb.sh) in order to install -dependencies. First read and understand the script, then execute it. Type your -password if required. +dependencies. Type your password if required. ```bash $ ./install_deb.sh ``` -- **SystemC 2.3.1a and TLM-2.0** - -You can use [utils/getsysc.sh](./utils/getsysc.sh) to download and install SystemC 2.3.1a -and TLM-2.0. First read and understand the script then execute it. - -```bash -$ ./getsysc.sh -``` - -Alternatively, the sources can be downloaded from -[here](http://accellera.org/downloads/standards/systemc). For installation -instructions see the installation notes file contained in the release package. - -- **qwt-6.1** - -You can use [utils/getqwt.sh](./utils/getqwt.sh) in order to install qwt-6.1. First read -and understand the script then execute it. - -```bash -$ ./getqwt.sh -$ cd ~/qwt-6.1 -``` - -After that add environment variables to your ~/.bashrc. Open the file with a -text editor (e.g., nano, gedit, kate, notepad++, subl, atom, ultraedit, emacs, -vim, etc.). - -```bash -$ nano ~/.bashrc -``` - - -```bash -export LIBQWT_HOME=${HOME}/qwt-6.1/lib -export LIBQWT_HEADERS=${HOME}/qwt-6.1/src -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${LIBQWT_HOME} -``` - -Remember to verify that the library was created and the header files are -located in the paths you specify. You can use the **ls** command to accomplish -that. - -```bash -$ ls ${HOME}/qwt-6.1/lib -$ ls ${HOME}/qwt-6.1/src -``` - -Further information about Qwt can be found [here](http://qwt.sourceforge.net/). - -To grant flexibility to the user the paths where to find some essential -libraries and headers can be specified with environment variables. Make sure -you have the environment variables below defined in your ~/.bashrc file. - -**Note that some of the variables are automatically generated by the scripts. If -you install the libraries in custom paths in your system you have to adapt the -environment variables accordingly**. - -```bash -# SystemC home and target architecture -export SYSTEMC_HOME=$HOME/systemc-2.3.1a -export SYSTEMC_TARGET_ARCH=linux64 -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${SYSTEMC_HOME}/lib-$SYSTEMC_TARGET_ARCH - -# DRAMSys libraries and headers -export LIBPYTHON_VERSION="3.5m" -export PYTHON_HOME=/usr/lib/python3.5 -export PYTHON_HEADERS=/usr/include/python3.5m - -export LIBQWT_HOME=${HOME}/qwt-6.1/lib -export LIBQWT_HEADERS=${HOME}/qwt-6.1/src -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${LIBQWT_HOME} - -``` - ### Coding Style Please read the [coding-style document](coding-style.md) before starting to @@ -167,15 +73,15 @@ $ qtcreator & Use the menu bar and open the DRAMSys project. -**File -> Open Project -> dram.sys/DRAMSys/DRAMSys.pro** +**File -> Open Project -> dram.sys/DRAMSys/CMakeLists.txt** When you open the project for the first time a configuration window pops-up. Then click in **Configure Project** and after that **Build** the project. To speedup the building process one can use the additional **make** option -**-j[jobs]**. The command line below returns a good number to be passed to -make as the number of jobs that can run simultaneously to improve the building -time. +**-j[jobs]**. The command line below returns the number of CPUs on a Debian +Linux to be passed to make as the number of jobs that can run simultaneously to +improve the building time. ```bash $ cat /proc/cpuinfo | grep processor | wc -l @@ -193,17 +99,18 @@ version** configuration shown in the image below. ### Building without QTCreator In case you prefer a command line interface to the QTCreator GUI you can also -use **qmake** to generate a Makefile and then compile the project. +use **cmake** to generate a Makefile and then compile the project. ```bash +$ cd dram.sys $ mkdir build $ cd build -$ qmake ../DRAMSys/DRAMSys.pro +$ cmake ../DRAMSys/ $ make -j4 ``` The compilation generates executable binary files **DRAMSys** and -**traceAnalyzer** that can be found inside sub-directories. +**TraceAnalyzer** that can be found inside sub-directories. From the build directory use the commands below to execute DRAMSys. @@ -231,50 +138,13 @@ $ ./traceAnalyzer ``` ### Building on MacOS (Formerly OSX) -- Install XCode - -- Install SystemC manually in /opt: - -```bash -$ ./configure --prefix=/opt/systemc -$ make -$ sudo make install -``` - -Or you can install via homebrew: - -```bash -$ brew install systemc -``` - -in this case, systemc will be installed, e.g. in: -``` -/usr/local/Cellar/systemc/2.3.1 -``` -and make a simlink of the lib directory: -``` -ln -s lib/ lib-macosx64 -``` - - -- Install the required python 3 over homebrew: +- Install XCode as a Compiler (or any other via Homebrew) +- Install the required python3 over homebrew: ```bash $ brew install python3 ``` -Python3 (via homebrew) will be installed in -``` -/usr/local/Cellar/python3/3.5.2_2/Frameworks/Python.framework -``` - -or you can install manually using official package provided in [link](https://www.python.org/downloads/) - -**Note:** Official Python Package will be installed in -``` -/Library/Frameworks/Python.framework -``` - - Install the QtCreator using offical setup file from [link](https://www.qt.io/download-open-source/#section-2) **Note:** You have later setup PATH for Qt5 and its tool if you install QtCreator manually, e.g: @@ -291,61 +161,17 @@ export PATH $ cd /Library/Frameworks $ sudo ln -s /opt/qwt-6.1.2/lib/qwt.framework/ . ``` -- Export correct Environment Variables in your terminal's profile, e.g: -```bash -# Setting for DRAMSys -# SystemC via official source -export SYSTEMC_HOME=/opt/systemc -export SYSTEMC_TARGET_ARCH=macosx64 -# SystemC via Homebrew -#export SYSTEMC_HOME=/usr/local/Cellar/systemc/2.3.1 -#export SYSTEMC_TARGET_ARCH=macosx64 - -# Python via official pkg -export PYTHON_HOME=/Library/Frameworks/Python.framework/Versions/3.5/lib -export PYTHON_HEADERS=/Library/Frameworks/Python.framework/Versions/3.5/Headers - -# Python3 via Homebrew -#export PYTHON_HOME=/usr/local/Cellar/python3/3.5.2_2/Frameworks/Python.framework/Versions/3.5/lib -#export PYTHON_HEADERS=/usr/local/Cellar/python3/3.5.2_2/Frameworks/Python.framework/Versions/3.5/Headers - -export LIBQWT_HOME=/opt/qwt-6.1.4/lib -export LIBQWT_HEADERS=/opt/qwt-6.1.4/lib/qwt.framework/Headers -``` - -- For the trace analyzer the file: -``` -/opt/local/Library/Frameworks/Python.framework/Versions/3.5/include/python3.4m/pyport.h -``` -has to be changed like [this](https://trac.macports.org/attachment/ticket/44288/issue10910-workaround.txt) - -- Install package [xerces](http://xerces.apache.org/mirrors.cgi) if your system does not have. - -- Type following command inside your dram.sys folder: - -```bash -$ mkdir build -$ qmake ../DRAMSys/DRAMSys.pro -$ make -j -``` - -Now you can try to run DRAMSys and traceAnalyzer App inside folder simulator and traceAnalyzer, respectively +You compile DRAMSys also with QtCreator or CMAKE as described in the Linux +section. ### Building on Windows 10 -DRAMSys can also run on Windows 10 with the *Windows Subsystem for Linux* (WSL) feature. You can install a linux distribution like Debian over the windows app store. -We refer to the following example [website](https://docs.microsoft.com/en-us/windows/wsl/install-win10). +- DRAMSys can also run on Windows 10 with the *Windows Subsystem for Linux* (WSL) feature. You can install a linux distribution like Debian over the windows app store. + We refer to the following example [website](https://docs.microsoft.com/en-us/windows/wsl/install-win10). + Then DRAMSys can be installed as described above for Linux. -Then DRAMSys can be installed as described above for Linux. However it might be advisable to install Qt, SystemC and qwt by hand. Qt should be downloaded from the Qt website. -The install systemc.sh script can be used to install SystemC and for QWT the version 6.1.3 should be used. - -Also the build configuration for SystemC should be configured as static with pthreads in the ```simulator.pro``` file: - -```qmake - #LIBS += -L$${systemc_home}/lib-$${systemc_target_arch} -lsystemc - LIBS += -L$${systemc_home}/lib-$${systemc_target_arch} -Wl,-Bstatic -lsystemc -Wl,-Bdynamic -pthread -``` +- Native Windows 10 Implementation is currently under investigation ### DRAMSys Configuration diff --git a/utils/getsysc.sh b/utils/getsysc.sh deleted file mode 100755 index 0dc300cb..00000000 --- a/utils/getsysc.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) 2017, University of Kaiserslautern -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER -# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Author: Éder F. Zulian - -dest=$HOME -sysc=systemc-2.3.1a -sysctarball=$sysc.tar.gz -builddir=objdir - -function getnumprocs { - local __retvar=$1; - local __nprocs=$(cat /proc/cpuinfo | grep processor | wc -l) - if [[ "$__retvar" ]]; then - eval $__retvar="'$__nprocs'" - else - echo "$__nprocs" - fi -} - -# Get the code -cd $dest -wget -nc http://accellera.org/images/downloads/standards/systemc/$sysctarball -tar -xaf $sysctarball -rm $sysctarball - -# Create a git repo to keep track of local changes -cd $sysc -git init -git add . -git commit -m "Adding files to repository" - -# Build the library -mkdir $builddir -cd $builddir - -# Patch needed for building systemc-2.3.1a -if [[ $sysc == 'systemc-2.3.1a' ]]; then - printf "Patching $sysc\n" - sedfile="../src/systemc.h" - sed -i "s@using\ std::gets;@//using\ std::gets;@g" $sedfile -fi - -export SYSTEMC_HOME=$dest/$sysc -../configure $cfgopts -getnumprocs np -nj=`expr $np - 1` -make -j$nj -make check -j$nj -make install - -# Add env. variables to ~/.bashrc -arch=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/') -echo "# SystemC home" >> ~/.bashrc -echo "export SYSTEMC_HOME=$dest/$sysc" >> ~/.bashrc -echo "# SystemC target architecture" >> ~/.bashrc -echo "export SYSTEMC_TARGET_ARCH=linux$arch" >> ~/.bashrc -echo "export LD_LIBRARY_PATH=\${LD_LIBRARY_PATH}:\${SYSTEMC_HOME}/lib-linux$arch" >> ~/.bashrc -echo "Done." diff --git a/utils/install_deb.sh b/utils/install_deb.sh index 31afe9e7..c7db3eac 100755 --- a/utils/install_deb.sh +++ b/utils/install_deb.sh @@ -53,8 +53,8 @@ subversion astyle uncrustify clang-format -python3.5 -python3.5-dev +python3 +python3-dev python3-matplotlib sqlite3 sqlitebrowser @@ -72,6 +72,8 @@ libqt5sql5 libqt5widgets5 libqt5core5a lsb-core +libqwt-qt5-dev +cmake gedit sublime-text vim-gtk @@ -81,6 +83,8 @@ gtkwave openssh-server nautilus telnet +dpkg-dev +pkg-config " for d in $deplist; do sudo apt-get -y install $d