diff --git a/.gitignore b/.gitignore index da990e0b..97b2ac1b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ DRAMSys/analyzer/scripts/__pycache__/ DRAMSys/gem5/boot_linux/linux-aarch32-ael.img DRAMSys/docs/doxygen /.vscode +/cmake-build* +/.idea diff --git a/DRAMSys/library/CMakeLists.txt b/DRAMSys/library/CMakeLists.txt index bf784fb5..165a3e54 100644 --- a/DRAMSys/library/CMakeLists.txt +++ b/DRAMSys/library/CMakeLists.txt @@ -97,6 +97,7 @@ add_library(DRAMSysLibrary src/configuration/memspec/MemSpecGDDR5X.cpp src/configuration/memspec/MemSpecGDDR6.cpp src/configuration/memspec/MemSpecHBM2.cpp + src/configuration/memspec/MemSpecSTTMRAM.cpp src/controller/BankMachine.cpp src/controller/Command.cpp @@ -114,6 +115,7 @@ add_library(DRAMSysLibrary src/controller/checker/CheckerGDDR5X.cpp src/controller/checker/CheckerGDDR6.cpp src/controller/checker/CheckerHBM2.cpp + src/controller/checker/CheckerSTTMRAM.cpp src/controller/cmdmux/CmdMuxIF.h src/controller/cmdmux/CmdMuxOldest.cpp @@ -168,6 +170,7 @@ add_library(DRAMSysLibrary src/simulation/dram/DramGDDR5X.cpp src/simulation/dram/DramGDDR6.cpp src/simulation/dram/DramHBM2.cpp + src/simulation/dram/DramSTTMRAM.cpp ${RECORDING_SOURCES} diff --git a/DRAMSys/library/resources/configs/amconfigs/am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json b/DRAMSys/library/resources/configs/amconfigs/am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json new file mode 100644 index 00000000..d1bcfe70 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json @@ -0,0 +1,43 @@ +{ + "CONGEN": { + "BANK_BIT": [ + 13, + 14, + 15 + ], + "BYTE_BIT": [ + 0, + 1, + 2 + ], + "COLUMN_BIT": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "ROW_BIT": [ + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30 + ] + } +} \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_noref.json b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_noref.json new file mode 100644 index 00000000..b0d0a554 --- /dev/null +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs_noref.json @@ -0,0 +1,16 @@ +{ + "mcconfig": { + "PagePolicy": "Open", + "Scheduler": "FrFcfs", + "SchedulerBuffer": "Bankwise", + "RequestBufferSize": 8, + "CmdMux": "Oldest", + "RespQueue": "Fifo", + "RefreshPolicy": "NoRefresh", + "RefreshMaxPostponed": 0, + "RefreshMaxPulledin": 0, + "PowerDownPolicy": "NoPowerDown", + "Arbiter": "Simple", + "MaxActiveTransactions": 128 + } +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3200A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3200A.json index 8bc5a428..75172a46 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3200A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3200A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 48, "CCD_L_slr": 8, - "CCD_L_WR_slr": 16, + "CCD_L_WR_slr": 32, + "CCD_L_WR2_slr": 16, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 1600 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3600A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3600A.json index 639c16a9..e35d934f 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3600A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3600A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 54, "CCD_L_slr": 9, - "CCD_L_WR_slr": 18, + "CCD_L_WR_slr": 36, + "CCD_L_WR2_slr": 18, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 1800 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4000A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4000A.json index 98d6a123..484ba99f 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4000A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4000A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 60, "CCD_L_slr": 10, - "CCD_L_WR_slr": 20, + "CCD_L_WR_slr": 40, + "CCD_L_WR2_slr": 20, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2000 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4400A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4400A.json index e27d625d..43b961e5 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4400A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4400A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 66, "CCD_L_slr": 11, - "CCD_L_WR_slr": 22, + "CCD_L_WR_slr": 44, + "CCD_L_WR2_slr": 22, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2200 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4800A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4800A.json index 5fef3321..eb4a3b8c 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4800A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4800A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 72, "CCD_L_slr": 12, - "CCD_L_WR_slr": 24, + "CCD_L_WR_slr": 48, + "CCD_L_WR2_slr": 24, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2400 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5200A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5200A.json index 358643b8..030f4e43 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5200A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5200A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 78, "CCD_L_slr": 13, - "CCD_L_WR_slr": 26, + "CCD_L_WR_slr": 52, + "CCD_L_WR2_slr": 26, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2600 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5600A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5600A.json index 766c837c..8de5c0f9 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5600A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5600A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 84, "CCD_L_slr": 14, - "CCD_L_WR_slr": 28, + "CCD_L_WR_slr": 56, + "CCD_L_WR2_slr": 28, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2800 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6000A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6000A.json index 9e387dc4..0bf780ec 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6000A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6000A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 90, "CCD_L_slr": 15, - "CCD_L_WR_slr": 30, + "CCD_L_WR_slr": 60, + "CCD_L_WR2_slr": 30, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 3000 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6400A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6400A.json index 18caa618..70d03828 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6400A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6400A.json @@ -34,7 +34,8 @@ "WPST": 0, "WR": 96, "CCD_L_slr": 16, - "CCD_L_WR_slr": 32, + "CCD_L_WR_slr": 64, + "CCD_L_WR2_slr": 32, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 3200 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3200A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3200A.json index aa6e82b0..635cc6cf 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3200A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3200A.json @@ -35,6 +35,7 @@ "WR": 48, "CCD_L_slr": 8, "CCD_L_WR_slr": 32, + "CCD_L_WR2_slr": 16, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 1600 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3600A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3600A.json index 96359874..ac39be46 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3600A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3600A.json @@ -35,6 +35,7 @@ "WR": 54, "CCD_L_slr": 9, "CCD_L_WR_slr": 36, + "CCD_L_WR2_slr": 18, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 1800 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4000A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4000A.json index bf632566..9887512d 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4000A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4000A.json @@ -35,6 +35,7 @@ "WR": 60, "CCD_L_slr": 10, "CCD_L_WR_slr": 40, + "CCD_L_WR2_slr": 20, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2000 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4400A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4400A.json index a343598b..cd9bdced 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4400A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4400A.json @@ -35,6 +35,7 @@ "WR": 66, "CCD_L_slr": 11, "CCD_L_WR_slr": 44, + "CCD_L_WR2_slr": 22, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2200 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4800A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4800A.json index 46998d40..6215400d 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4800A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4800A.json @@ -35,6 +35,7 @@ "WR": 72, "CCD_L_slr": 12, "CCD_L_WR_slr": 48, + "CCD_L_WR2_slr": 24, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2400 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5200A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5200A.json index 18e6c093..48d99a38 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5200A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5200A.json @@ -35,6 +35,7 @@ "WR": 78, "CCD_L_slr": 13, "CCD_L_WR_slr": 52, + "CCD_L_WR2_slr": 26, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2600 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5600A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5600A.json index 4891bb1b..0a46d8ed 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5600A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5600A.json @@ -35,6 +35,7 @@ "WR": 84, "CCD_L_slr": 14, "CCD_L_WR_slr": 56, + "CCD_L_WR2_slr": 28, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 2800 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6000A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6000A.json index 3e26408e..ba5c81eb 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6000A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6000A.json @@ -35,6 +35,7 @@ "WR": 90, "CCD_L_slr": 15, "CCD_L_WR_slr": 60, + "CCD_L_WR2_slr": 30, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 3000 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6400A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6400A.json index ca9eac9b..ea3ec632 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6400A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6400A.json @@ -35,6 +35,7 @@ "WR": 96, "CCD_L_slr": 16, "CCD_L_WR_slr": 64, + "CCD_L_WR2_slr": 32, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -70,4 +71,4 @@ "clkMhz": 3200 } } -} \ No newline at end of file +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json index 315fb976..fbbe90fe 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json @@ -35,6 +35,7 @@ "WR": 48, "CCD_L_slr": 8, "CCD_L_WR_slr": 32, + "CCD_L_WR2_slr": 16, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 8, diff --git a/DRAMSys/library/resources/configs/memspecs/README.md b/DRAMSys/library/resources/configs/memspecs/README.md new file mode 100644 index 00000000..5ff0d2d2 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/README.md @@ -0,0 +1,16 @@ +*The following copyright notice only applies to the files "STT-MRAM-1.2x.json", "STT-MRAM-1.5x.json" and "STT-MRAM-2.0x.json".* + + + (C) Copyright 2006-2018 Barcelona Supercomputing Center (BSC) + +The copyright holder is BSC-CNS, and the authorship correspond to Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. The complete explanation of the derivation of the data can be found in the following study: Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. 2017. Enabling a reliable STT-MRAM main memory simulation. In Proceedings of the International Symposium on Memory Systems (MEMSYS '17). Washington DC, USA, 283-292. DOI: https://doi.org/10.1145/3132402.3132416 + +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. + +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.” + +The configuration files list detailed timing parameters for STT-MRAM main memory, specifying a 1.2x/1.5x/2.0x deviation from respective DRAM timing parameters. diff --git a/DRAMSys/library/resources/configs/memspecs/STT-MRAM-1.2x.json b/DRAMSys/library/resources/configs/memspecs/STT-MRAM-1.2x.json new file mode 100644 index 00000000..88511099 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/STT-MRAM-1.2x.json @@ -0,0 +1,44 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 8, + "dataRate": 2, + "nbrOfBanks": 8, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfRows": 32768, + "width": 8, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 1 + }, + "memoryId": "STT-MRAM-1.2x", + "memoryType": "STT-MRAM", + "memtimingspec": { + "AL": 0, + "CCD": 4, + "CKE": 4, + "CKESR": 7, + "CL": 11, + "DQSCK": 0, + "FAW": 29, + "RAS": 20, + "RC": 34, + "RCD": 14, + "RL": 11, + "RP": 14, + "RRD": 6, + "RTP": 6, + "WL": 11, + "WR": 12, + "WTR": 2, + "XP": 5, + "XPDLL": 325, + "XS": 324, + "XSDLL": 512, + "ACTPDEN": 2, + "PRPDEN": 2, + "RTRS": 1, + "clkMhz": 800 + } + } +} \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/memspecs/STT-MRAM-1.5x.json b/DRAMSys/library/resources/configs/memspecs/STT-MRAM-1.5x.json new file mode 100644 index 00000000..57440f78 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/STT-MRAM-1.5x.json @@ -0,0 +1,44 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 8, + "dataRate": 2, + "nbrOfBanks": 8, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfRows": 32768, + "width": 8, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 1 + }, + "memoryId": "STT-MRAM-1.5x", + "memoryType": "STT-MRAM", + "memtimingspec": { + "AL": 0, + "CCD": 4, + "CKE": 4, + "CKESR": 7, + "CL": 11, + "DQSCK": 0, + "FAW": 36, + "RAS": 23, + "RC": 40, + "RCD": 14, + "RL": 11, + "RP": 17, + "RRD": 8, + "RTP": 6, + "WL": 11, + "WR": 12, + "WTR": 6, + "XP": 5, + "XPDLL": 325, + "XS": 324, + "XSDLL": 512, + "ACTPDEN": 2, + "PRPDEN": 2, + "RTRS": 1, + "clkMhz": 800 + } + } +} \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/memspecs/STT-MRAM-2.0x.json b/DRAMSys/library/resources/configs/memspecs/STT-MRAM-2.0x.json new file mode 100644 index 00000000..08d0ba9b --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/STT-MRAM-2.0x.json @@ -0,0 +1,44 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 8, + "dataRate": 2, + "nbrOfBanks": 8, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfRows": 32768, + "width": 8, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 1 + }, + "memoryId": "STT-MRAM-2.0x", + "memoryType": "STT-MRAM", + "memtimingspec": { + "AL": 0, + "CCD": 4, + "CKE": 4, + "CKESR": 7, + "CL": 11, + "DQSCK": 0, + "FAW": 36, + "RAS": 28, + "RC": 50, + "RCD": 14, + "RL": 11, + "RP": 22, + "RRD": 10, + "RTP": 6, + "WL": 11, + "WR": 48, + "WTR": 6, + "XP": 5, + "XPDLL": 325, + "XS": 324, + "XSDLL": 512, + "ACTPDEN": 2, + "PRPDEN": 2, + "RTRS": 1, + "clkMhz": 800 + } + } +} \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/simulator/stt-mram.json b/DRAMSys/library/resources/configs/simulator/stt-mram.json new file mode 100644 index 00000000..3248e9f0 --- /dev/null +++ b/DRAMSys/library/resources/configs/simulator/stt-mram.json @@ -0,0 +1,19 @@ +{ + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "ECCControllerMode": "Disabled", + "EnableWindowing": false, + "ErrorCSVFile": "", + "ErrorChipSeed": 42, + "PowerAnalysis": false, + "SimulationName": "stt-mram", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + } +} diff --git a/DRAMSys/library/resources/simulations/stt-mram-example.json b/DRAMSys/library/resources/simulations/stt-mram-example.json new file mode 100644 index 00000000..fd9e3fce --- /dev/null +++ b/DRAMSys/library/resources/simulations/stt-mram-example.json @@ -0,0 +1,16 @@ +{ + "simulation": { + "addressmapping": "am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json", + "mcconfig": "fr_fcfs_noref.json", + "memspec": "STT-MRAM-1.2x.json", + "simconfig": "stt-mram.json", + "simulationid": "stt-mram-example", + "thermalconfig": "config.json", + "tracesetup": [ + { + "clkMhz": 800, + "name": "ddr3_example.stl" + } + ] + } +} diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index 17b20a34..ca347381 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -162,7 +162,7 @@ void TlmRecorder::introduceTransactionSystem(tlm_generic_payload &trans) currentTransactionsInSystem[&trans].cmd = trans.get_command() == tlm::TLM_READ_COMMAND ? "R" : "W"; currentTransactionsInSystem[&trans].address = trans.get_address(); - currentTransactionsInSystem[&trans].burstlength = trans.get_streaming_width(); + currentTransactionsInSystem[&trans].burstLength = DramExtension::getBurstLength(trans); currentTransactionsInSystem[&trans].dramExtension = DramExtension::getExtension(trans); currentTransactionsInSystem[&trans].timeOfGeneration = GenerationExtension::getTimeOfGeneration(trans); @@ -406,7 +406,7 @@ void TlmRecorder::insertTransactionInDB(Transaction &recordingData) sqlite3_bind_int(insertTransactionStatement, 1, static_cast(recordingData.id)); sqlite3_bind_int(insertTransactionStatement, 2, static_cast(recordingData.id)); sqlite3_bind_int64(insertTransactionStatement, 3, static_cast(recordingData.address)); - sqlite3_bind_int(insertTransactionStatement, 4, static_cast(recordingData.burstlength)); + sqlite3_bind_int(insertTransactionStatement, 4, static_cast(recordingData.burstLength)); sqlite3_bind_int(insertTransactionStatement, 5, static_cast(recordingData.dramExtension.getThread().ID())); sqlite3_bind_int(insertTransactionStatement, 6, diff --git a/DRAMSys/library/src/common/TlmRecorder.h b/DRAMSys/library/src/common/TlmRecorder.h index d3974f1b..fd422987 100644 --- a/DRAMSys/library/src/common/TlmRecorder.h +++ b/DRAMSys/library/src/common/TlmRecorder.h @@ -92,7 +92,7 @@ private: uint64_t id; uint64_t address; - unsigned int burstlength; + unsigned int burstLength; std::string cmd; DramExtension dramExtension; sc_time timeOfGeneration; diff --git a/DRAMSys/library/src/common/dramExtensions.cpp b/DRAMSys/library/src/common/dramExtensions.cpp index 09a49be9..44910e22 100644 --- a/DRAMSys/library/src/common/dramExtensions.cpp +++ b/DRAMSys/library/src/common/dramExtensions.cpp @@ -44,21 +44,21 @@ using namespace tlm; DramExtension::DramExtension() : thread(0), channel(0), rank(0), bankgroup(0), bank(0), - row(0), column(0), burstlength(0), + row(0), column(0), burstLength(0), threadPayloadID(0), channelPayloadID(0) {} DramExtension::DramExtension(Thread thread, Channel channel, Rank rank, BankGroup bankgroup, Bank bank, Row row, - Column column, unsigned int burstlength, + Column column, unsigned int burstLength, uint64_t threadPayloadID, uint64_t channelPayloadID) : thread(thread), channel(channel), rank(rank), bankgroup(bankgroup), bank(bank), - row(row), column(column), burstlength(burstlength), + row(row), column(column), burstLength(burstLength), threadPayloadID(threadPayloadID), channelPayloadID(channelPayloadID) {} void DramExtension::setExtension(tlm::tlm_generic_payload *payload, Thread thread, Channel channel, Rank rank, BankGroup bankgroup, Bank bank, Row row, - Column column, unsigned int burstlength, + Column column, unsigned int burstLength, uint64_t threadPayloadID, uint64_t channelPayloadID) { DramExtension *extension = nullptr; @@ -73,14 +73,14 @@ void DramExtension::setExtension(tlm::tlm_generic_payload *payload, extension->bank = bank; extension->row = row; extension->column = column; - extension->burstlength = burstlength; + extension->burstLength = burstLength; extension->threadPayloadID = threadPayloadID; extension->channelPayloadID = channelPayloadID; } else { extension = new DramExtension(thread, channel, rank, bankgroup, - bank, row, column, burstlength, + bank, row, column, burstLength, threadPayloadID, channelPayloadID); payload->set_auto_extension(extension); } @@ -89,11 +89,11 @@ void DramExtension::setExtension(tlm::tlm_generic_payload *payload, void DramExtension::setExtension(tlm::tlm_generic_payload &payload, Thread thread, Channel channel, Rank rank, BankGroup bankgroup, Bank bank, Row row, - Column column, unsigned int burstlength, + Column column, unsigned int burstLength, uint64_t threadPayloadID, uint64_t channelPayloadID) { setExtension(&payload, thread, channel, rank, bankgroup, - bank, row, column, burstlength, + bank, row, column, burstLength, threadPayloadID, channelPayloadID); } @@ -194,6 +194,16 @@ Column DramExtension::getColumn(const tlm_generic_payload &payload) return DramExtension::getColumn(&payload); } +unsigned DramExtension::getBurstLength(const tlm_generic_payload *payload) +{ + return DramExtension::getExtension(payload).getBurstLength(); +} + +unsigned DramExtension::getBurstLength(const tlm_generic_payload &payload) +{ + return DramExtension::getBurstLength(&payload); +} + uint64_t DramExtension::getThreadPayloadID(const tlm_generic_payload *payload) { return DramExtension::getExtension(payload).getThreadPayloadID(); @@ -217,7 +227,7 @@ uint64_t DramExtension::getChannelPayloadID(const tlm_generic_payload &payload) tlm_extension_base *DramExtension::clone() const { return new DramExtension(thread, channel, rank, bankgroup, bank, row, column, - burstlength, threadPayloadID, channelPayloadID); + burstLength, threadPayloadID, channelPayloadID); } void DramExtension::copy_from(const tlm_extension_base &ext) @@ -230,7 +240,7 @@ void DramExtension::copy_from(const tlm_extension_base &ext) bank = cpyFrom.bank; row = cpyFrom.row; column = cpyFrom.column; - burstlength = cpyFrom.burstlength; + burstLength = cpyFrom.burstLength; } Thread DramExtension::getThread() const @@ -268,9 +278,9 @@ Column DramExtension::getColumn() const return column; } -unsigned int DramExtension::getBurstlength() const +unsigned int DramExtension::getBurstLength() const { - return burstlength; + return burstLength; } uint64_t DramExtension::getThreadPayloadID() const diff --git a/DRAMSys/library/src/common/dramExtensions.h b/DRAMSys/library/src/common/dramExtensions.h index 989bb079..462a61a8 100644 --- a/DRAMSys/library/src/common/dramExtensions.h +++ b/DRAMSys/library/src/common/dramExtensions.h @@ -165,7 +165,7 @@ public: DramExtension(); DramExtension(Thread thread, Channel channel, Rank rank, BankGroup bankgroup, Bank bank, Row row, - Column column, unsigned int burstlength, + Column column, unsigned int burstLength, uint64_t threadPayloadID, uint64_t channelPayloadID); virtual tlm::tlm_extension_base *clone() const; @@ -174,12 +174,12 @@ public: static void setExtension(tlm::tlm_generic_payload *payload, Thread thread, Channel channel, Rank rank, BankGroup bankgroup, Bank bank, Row row, - Column column, unsigned int burstlength, + Column column, unsigned int burstLength, uint64_t threadPayloadID, uint64_t channelPayloadID); static void setExtension(tlm::tlm_generic_payload &payload, Thread thread, Channel channel, Rank rank, BankGroup bankgroup, Bank bank, Row row, - Column column, unsigned int burstlength, + Column column, unsigned int burstLength, uint64_t threadPayloadID, uint64_t channelPayloadID); static DramExtension &getExtension(const tlm::tlm_generic_payload *payload); @@ -205,6 +205,8 @@ public: static Row getRow(const tlm::tlm_generic_payload &payload); static Column getColumn(const tlm::tlm_generic_payload *payload); static Column getColumn(const tlm::tlm_generic_payload &payload); + static unsigned getBurstLength(const tlm::tlm_generic_payload *payload); + static unsigned getBurstLength(const tlm::tlm_generic_payload &payload); static uint64_t getThreadPayloadID(const tlm::tlm_generic_payload *payload); static uint64_t getThreadPayloadID(const tlm::tlm_generic_payload &payload); static uint64_t getChannelPayloadID(const tlm::tlm_generic_payload *payload); @@ -218,7 +220,7 @@ public: Row getRow() const; Column getColumn() const; - unsigned int getBurstlength() const; + unsigned int getBurstLength() const; uint64_t getThreadPayloadID() const; uint64_t getChannelPayloadID() const; void incrementRow(); @@ -231,7 +233,7 @@ private: Bank bank; Row row; Column column; - unsigned int burstlength; + unsigned int burstLength; uint64_t threadPayloadID; uint64_t channelPayloadID; }; diff --git a/DRAMSys/library/src/configuration/Configuration.cpp b/DRAMSys/library/src/configuration/Configuration.cpp index cdcee1af..065aee78 100644 --- a/DRAMSys/library/src/configuration/Configuration.cpp +++ b/DRAMSys/library/src/configuration/Configuration.cpp @@ -51,6 +51,7 @@ #include "memspec/MemSpecGDDR5.h" #include "memspec/MemSpecGDDR5X.h" #include "memspec/MemSpecGDDR6.h" +#include "memspec/MemSpecSTTMRAM.h" using json = nlohmann::json; @@ -357,6 +358,8 @@ void Configuration::loadMemSpec(Configuration &config, std::string memspecUri) memSpec = new MemSpecGDDR5X(jMemSpec); else if (memoryType == "GDDR6") memSpec = new MemSpecGDDR6(jMemSpec); + else if (memoryType == "STT-MRAM") + memSpec = new MemSpecSTTMRAM(jMemSpec); else SC_REPORT_FATAL("Configuration", "Unsupported DRAM type"); } diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.h b/DRAMSys/library/src/configuration/memspec/MemSpec.h index 4020a8ed..3e5c0c1f 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.h @@ -69,7 +69,8 @@ public: const sc_time tCK; const std::string memoryId; - const enum class MemoryType {DDR3, DDR4, DDR5, LPDDR4, WideIO, WideIO2, GDDR5, GDDR5X, GDDR6, HBM2} memoryType; + const enum class MemoryType {DDR3, DDR4, DDR5, LPDDR4, WideIO, + WideIO2, GDDR5, GDDR5X, GDDR6, HBM2, STTMRAM} memoryType; virtual ~MemSpec() {} @@ -79,8 +80,8 @@ public: virtual bool hasRasAndCasBus() const; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const = 0; - virtual TimeInterval getIntervalOnDataStrobe(Command) const = 0; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const = 0; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const = 0; sc_time getCommandLength(Command) const; virtual uint64_t getSimMemSizeInBytes() const = 0; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp index 2da79c88..5c566b46 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp @@ -120,7 +120,7 @@ sc_time MemSpecDDR3::getExecutionTime(Command command, const tlm_generic_payload } } -TimeInterval MemSpecDDR3::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecDDR3::getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL, tRL + burstDuration); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h index 6c9174de..370273b0 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h @@ -89,8 +89,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp index cd6daac4..2b6e3bfb 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp @@ -139,7 +139,7 @@ sc_time MemSpecDDR4::getExecutionTime(Command command, const tlm_generic_payload } } -TimeInterval MemSpecDDR4::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecDDR4::getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL, tRL + burstDuration); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h index c63fb36f..e3a5ed9b 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h @@ -97,8 +97,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp index 5d0353c8..662464d2 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp @@ -59,56 +59,59 @@ MemSpecDDR5::MemSpecDDR5(json &memspec) numberOfLogicalRanks(logicalRanksPerPhysicalRank * numberOfPhysicalRanks), cmdMode(parseUint(memspec["memarchitecturespec"]["cmdMode"], "cmdMode")), refMode(parseUint(memspec["memarchitecturespec"]["refMode"], "refMode")), - tRCD (tCK * parseUint(memspec["memtimingspec"]["RCD"], "RCD")), - tPPD (tCK * parseUint(memspec["memtimingspec"]["PPD"], "PPD")), - tRP (tCK * parseUint(memspec["memtimingspec"]["RP"], "RP")), - tRAS (tCK * parseUint(memspec["memtimingspec"]["RAS"], "RAS")), - tRC (tRAS + tRP), - tRL (tCK * parseUint(memspec["memtimingspec"]["RL"], "RL")), - tRTP (tCK * parseUint(memspec["memtimingspec"]["RTP"], "RTP")), - tRPRE (tCK * parseUint(memspec["memtimingspec"]["RPRE"], "RPRE")), - tRPST (tCK * parseUint(memspec["memtimingspec"]["RPST"], "RPST")), - tRDDQS (tCK * parseUint(memspec["memtimingspec"]["RDDQS"], "RDDQS")), - tWL (tCK * parseUint(memspec["memtimingspec"]["WL"], "WL")), - tWPRE (tCK * parseUint(memspec["memtimingspec"]["WPRE"], "WPRE")), - tWPST (tCK * parseUint(memspec["memtimingspec"]["WPST"], "WPST")), - tWR (tCK * parseUint(memspec["memtimingspec"]["WR"], "WR")), - tCCD_L_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_L_slr"], "CCD_L_slr")), - tCCD_L_WR_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_L_WR_slr"], "CCD_L_WR_slr")), - tCCD_S_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_S_slr"], "CCD_S_slr")), - tCCD_S_WR_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_S_WR_slr"], "CCD_S_WR_slr")), - tCCD_dlr (tCK * parseUint(memspec["memtimingspec"]["CCD_dlr"], "CCD_dlr")), - tCCD_WR_dlr (tCK * parseUint(memspec["memtimingspec"]["CCD_WR_dlr"], "CCD_WR_dlr")), - tCCD_WR_dpr (tCK * parseUint(memspec["memtimingspec"]["CCD_WR_dpr"], "CCD_WR_dpr")), - tRRD_L_slr (tCK * parseUint(memspec["memtimingspec"]["RRD_L_slr"], "RRD_L_slr")), - tRRD_S_slr (tCK * parseUint(memspec["memtimingspec"]["RRD_S_slr"], "RRD_S_slr")), - tRRD_dlr (tCK * parseUint(memspec["memtimingspec"]["RRD_dlr"], "RRD_dlr")), - tFAW_slr (tCK * parseUint(memspec["memtimingspec"]["FAW_slr"], "FAW_slr")), - tFAW_dlr (tCK * parseUint(memspec["memtimingspec"]["FAW_dlr"], "FAW_dlr")), - tWTR_L (tCK * parseUint(memspec["memtimingspec"]["WTR_L"], "WTR_L")), - tWTR_S (tCK * parseUint(memspec["memtimingspec"]["WTR_S"], "WTR_S")), - tRFC_slr ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["RFC1_slr"], "RFC1_slr") - : tCK * parseUint(memspec["memtimingspec"]["RFC2_slr"], "RFC2_slr")), - tRFC_dlr ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["RFC1_dlr"], "RFC1_dlr") - : tCK * parseUint(memspec["memtimingspec"]["RFC2_dlr"], "RFC2_dlr")), - tRFC_dpr ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["RFC1_dpr"], "RFC1_dpr") - : tCK * parseUint(memspec["memtimingspec"]["RFC2_dpr"], "RFC2_dpr")), - tRFCsb_slr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_slr"], "RFCsb_slr")), - tRFCsb_dlr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_dlr"], "RFCsb_dlr")), - tREFI ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["REFI1"], "REFI1") - : tCK * parseUint(memspec["memtimingspec"]["REFI2"], "REFI2")), - tREFIsb (tCK * parseUint(memspec["memtimingspec"]["REFISB"], "REFISB")), - tREFSBRD_slr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_slr"], "REFSBRD_slr")), - tREFSBRD_dlr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_dlr"], "REFSBRD_dlr")), - tRTRS (tCK * parseUint(memspec["memtimingspec"]["RTRS"], "RTRS")), - tCPDED (tCK * parseUint(memspec["memtimingspec"]["CPDED"], "CPDED")), - tPD (tCK * parseUint(memspec["memtimingspec"]["PD"], "PD")), - tXP (tCK * parseUint(memspec["memtimingspec"]["XP"], "XP")), - tACTPDEN (tCK * parseUint(memspec["memtimingspec"]["ACTPDEN"], "ACTPDEN")), - tPRPDEN (tCK * parseUint(memspec["memtimingspec"]["PRPDEN"], "PRPDEN")), - tREFPDEN (tCK * parseUint(memspec["memtimingspec"]["REFPDEN"], "REFPDEN")), - cmdOffset_S (cmdMode == 2 ? 1 * tCK : 0 * tCK), - cmdOffset_L (cmdMode == 2 ? 3 * tCK : 1 * tCK) + tRCD (tCK * parseUint(memspec["memtimingspec"]["RCD"], "RCD")), + tPPD (tCK * parseUint(memspec["memtimingspec"]["PPD"], "PPD")), + tRP (tCK * parseUint(memspec["memtimingspec"]["RP"], "RP")), + tRAS (tCK * parseUint(memspec["memtimingspec"]["RAS"], "RAS")), + tRC (tRAS + tRP), + tRL (tCK * parseUint(memspec["memtimingspec"]["RL"], "RL")), + tRTP (tCK * parseUint(memspec["memtimingspec"]["RTP"], "RTP")), + tRPRE (tCK * parseUint(memspec["memtimingspec"]["RPRE"], "RPRE")), + tRPST (tCK * parseUint(memspec["memtimingspec"]["RPST"], "RPST")), + tRDDQS (tCK * parseUint(memspec["memtimingspec"]["RDDQS"], "RDDQS")), + tWL (tCK * parseUint(memspec["memtimingspec"]["WL"], "WL")), + tWPRE (tCK * parseUint(memspec["memtimingspec"]["WPRE"], "WPRE")), + tWPST (tCK * parseUint(memspec["memtimingspec"]["WPST"], "WPST")), + tWR (tCK * parseUint(memspec["memtimingspec"]["WR"], "WR")), + tCCD_L_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_L_slr"], "CCD_L_slr")), + tCCD_L_WR_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_L_WR_slr"], "CCD_L_WR_slr")), + tCCD_L_WR2_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_L_WR2_slr"], "CCD_L_WR2_slr")), + tCCD_S_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_S_slr"], "CCD_S_slr")), + tCCD_S_WR_slr (tCK * parseUint(memspec["memtimingspec"]["CCD_S_WR_slr"], "CCD_S_WR_slr")), + tCCD_dlr (tCK * parseUint(memspec["memtimingspec"]["CCD_dlr"], "CCD_dlr")), + tCCD_WR_dlr (tCK * parseUint(memspec["memtimingspec"]["CCD_WR_dlr"], "CCD_WR_dlr")), + tCCD_WR_dpr (tCK * parseUint(memspec["memtimingspec"]["CCD_WR_dpr"], "CCD_WR_dpr")), + tRRD_L_slr (tCK * parseUint(memspec["memtimingspec"]["RRD_L_slr"], "RRD_L_slr")), + tRRD_S_slr (tCK * parseUint(memspec["memtimingspec"]["RRD_S_slr"], "RRD_S_slr")), + tRRD_dlr (tCK * parseUint(memspec["memtimingspec"]["RRD_dlr"], "RRD_dlr")), + tFAW_slr (tCK * parseUint(memspec["memtimingspec"]["FAW_slr"], "FAW_slr")), + tFAW_dlr (tCK * parseUint(memspec["memtimingspec"]["FAW_dlr"], "FAW_dlr")), + tWTR_L (tCK * parseUint(memspec["memtimingspec"]["WTR_L"], "WTR_L")), + tWTR_S (tCK * parseUint(memspec["memtimingspec"]["WTR_S"], "WTR_S")), + tRFC_slr ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["RFC1_slr"], "RFC1_slr") + : tCK * parseUint(memspec["memtimingspec"]["RFC2_slr"], "RFC2_slr")), + tRFC_dlr ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["RFC1_dlr"], "RFC1_dlr") + : tCK * parseUint(memspec["memtimingspec"]["RFC2_dlr"], "RFC2_dlr")), + tRFC_dpr ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["RFC1_dpr"], "RFC1_dpr") + : tCK * parseUint(memspec["memtimingspec"]["RFC2_dpr"], "RFC2_dpr")), + tRFCsb_slr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_slr"], "RFCsb_slr")), + tRFCsb_dlr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_dlr"], "RFCsb_dlr")), + tREFI ((refMode == 1) ? tCK * parseUint(memspec["memtimingspec"]["REFI1"], "REFI1") + : tCK * parseUint(memspec["memtimingspec"]["REFI2"], "REFI2")), + tREFIsb (tCK * parseUint(memspec["memtimingspec"]["REFISB"], "REFISB")), + tREFSBRD_slr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_slr"], "REFSBRD_slr")), + tREFSBRD_dlr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_dlr"], "REFSBRD_dlr")), + tRTRS (tCK * parseUint(memspec["memtimingspec"]["RTRS"], "RTRS")), + tCPDED (tCK * parseUint(memspec["memtimingspec"]["CPDED"], "CPDED")), + tPD (tCK * parseUint(memspec["memtimingspec"]["PD"], "PD")), + tXP (tCK * parseUint(memspec["memtimingspec"]["XP"], "XP")), + tACTPDEN (tCK * parseUint(memspec["memtimingspec"]["ACTPDEN"], "ACTPDEN")), + tPRPDEN (tCK * parseUint(memspec["memtimingspec"]["PRPDEN"], "PRPDEN")), + tREFPDEN (tCK * parseUint(memspec["memtimingspec"]["REFPDEN"], "REFPDEN")), + shortCmdOffset (cmdMode == 2 ? 1 * tCK : 0 * tCK), + longCmdOffset (cmdMode == 2 ? 3 * tCK : 1 * tCK), + tBURST16(tCK * 8), + tBURST32(tCK * 16) { if (cmdMode == 1) { @@ -156,24 +159,39 @@ sc_time MemSpecDDR5::getRefreshIntervalSB() const } // Returns the execution time for commands that have a fixed execution time -sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload &) const +sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload &payload) const { if (command == Command::PRE || command == Command::PREA || command == Command::PRESB) - return tRP + cmdOffset_S; + return tRP + shortCmdOffset; else if (command == Command::ACT) - return tRCD + cmdOffset_L; + return tRCD + longCmdOffset; else if (command == Command::RD) - return tRL + burstDuration + cmdOffset_L; + { + if (DramExtension::getBurstLength(payload) == 32) + return tRL + tBURST32 + longCmdOffset; + else + return tRL + tBURST16 + longCmdOffset; + } else if (command == Command::RDA) - return tRTP + tRP + cmdOffset_L; + return tRTP + tRP + longCmdOffset; else if (command == Command::WR) - return tWL + burstDuration + cmdOffset_L; + { + if (DramExtension::getBurstLength(payload) == 32) + return tWL + tBURST32 + longCmdOffset; + else + return tWL + tBURST16 + longCmdOffset; + } else if (command == Command::WRA) - return tWL + burstDuration + tWR + tRP + cmdOffset_L; + { + if (DramExtension::getBurstLength(payload) == 32) + return tWL + tBURST32 + tWR + tRP + longCmdOffset; + else + return tWL + tBURST16 + tWR + tRP + longCmdOffset; + } else if (command == Command::REFA) - return tRFC_slr + cmdOffset_S; + return tRFC_slr + shortCmdOffset; else if (command == Command::REFSB) - return tRFCsb_slr + cmdOffset_S; + return tRFCsb_slr + shortCmdOffset; else { SC_REPORT_FATAL("getExecutionTime", @@ -182,12 +200,22 @@ sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload } } -TimeInterval MemSpecDDR5::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecDDR5::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &payload) const { if (command == Command::RD || command == Command::RDA) - return TimeInterval(tRL + cmdOffset_L, tRL + burstDuration + cmdOffset_L); + { + if (DramExtension::getBurstLength(payload) == 32) + return TimeInterval(tRL + longCmdOffset, tRL + tBURST32 + longCmdOffset); + else + return TimeInterval(tRL + longCmdOffset, tRL + tBURST16 + longCmdOffset); + } else if (command == Command::WR || command == Command::WRA) - return TimeInterval(tWL + cmdOffset_L, tWL + burstDuration + cmdOffset_L); + { + if (DramExtension::getBurstLength(payload) == 32) + return TimeInterval(tWL + longCmdOffset, tWL + tBURST32 + longCmdOffset); + else + return TimeInterval(tWL + longCmdOffset, tWL + tBURST16 + longCmdOffset); + } else { SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h index 13883326..40de44f1 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h @@ -69,6 +69,7 @@ public: const sc_time tWR; const sc_time tCCD_L_slr; const sc_time tCCD_L_WR_slr; + const sc_time tCCD_L_WR2_slr; const sc_time tCCD_S_slr; const sc_time tCCD_S_WR_slr; const sc_time tCCD_dlr; @@ -99,8 +100,11 @@ public: const sc_time tPRPDEN; const sc_time tREFPDEN; - const sc_time cmdOffset_S; - const sc_time cmdOffset_L; + const sc_time shortCmdOffset; + const sc_time longCmdOffset; + + const sc_time tBURST16; + const sc_time tBURST32; // Currents and Voltages: // TODO: to be completed @@ -108,8 +112,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getRefreshIntervalSB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp index 2c27dbc3..4ae7bb17 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp @@ -128,7 +128,7 @@ sc_time MemSpecGDDR5::getExecutionTime(Command command, const tlm_generic_payloa } } -TimeInterval MemSpecGDDR5::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecGDDR5::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h index 3abeb869..cf584c98 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h @@ -88,8 +88,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getRefreshIntervalPB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp index ea1dc46e..1c97fada 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp @@ -128,7 +128,7 @@ sc_time MemSpecGDDR5X::getExecutionTime(Command command, const tlm_generic_paylo } } -TimeInterval MemSpecGDDR5X::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecGDDR5X::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h index 10fcd5b5..f507232d 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h @@ -88,8 +88,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getRefreshIntervalPB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp index d296f887..c0dfd854 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp @@ -130,7 +130,7 @@ sc_time MemSpecGDDR6::getExecutionTime(Command command, const tlm_generic_payloa } } -TimeInterval MemSpecGDDR6::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecGDDR6::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h index c0f9f7d1..b6d86f8e 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h @@ -90,8 +90,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getRefreshIntervalPB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp index c299f9d9..25f77ef9 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp @@ -130,7 +130,7 @@ sc_time MemSpecHBM2::getExecutionTime(Command command, const tlm_generic_payload } } -TimeInterval MemSpecHBM2::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecHBM2::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL + tDQSCK, tRL + tDQSCK + burstDuration); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h index a56f18fb..f5c0fbb0 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h @@ -85,8 +85,8 @@ public: virtual bool hasRasAndCasBus() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp index a046a7d7..9e181a0d 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp @@ -132,7 +132,7 @@ sc_time MemSpecLPDDR4::getExecutionTime(Command command, const tlm_generic_paylo } } -TimeInterval MemSpecLPDDR4::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecLPDDR4::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL + tDQSCK + 3 * tCK, diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h index 4c7d0d52..8005422e 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h @@ -83,8 +83,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getRefreshIntervalPB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecSTTMRAM.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecSTTMRAM.cpp new file mode 100644 index 00000000..1d4d52c6 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecSTTMRAM.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021, Technische Universität 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 "MemSpecSTTMRAM.h" + +using namespace tlm; +using json = nlohmann::json; + +MemSpecSTTMRAM::MemSpecSTTMRAM(json &memspec) + : MemSpec(memspec, MemoryType::STTMRAM, + parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), + parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), + 1, + parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks") + * parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfDevicesOnDIMM"],"nbrOfDevicesOnDIMM")), + tCKE (tCK * parseUint(memspec["memtimingspec"]["CKE"], "CKE")), + tPD (tCKE), + tCKESR (tCK * parseUint(memspec["memtimingspec"]["CKESR"], "CKESR")), + tDQSCK (tCK * parseUint(memspec["memtimingspec"]["DQSCK"], "DQSCK")), + tRAS (tCK * parseUint(memspec["memtimingspec"]["RAS"], "RAS")), + tRC (tCK * parseUint(memspec["memtimingspec"]["RC"], "RC")), + tRCD (tCK * parseUint(memspec["memtimingspec"]["RCD"], "RCD")), + tRL (tCK * parseUint(memspec["memtimingspec"]["RL"], "RL")), + tRTP (tCK * parseUint(memspec["memtimingspec"]["RTP"], "RTP")), + tWL (tCK * parseUint(memspec["memtimingspec"]["WL"], "WL")), + tWR (tCK * parseUint(memspec["memtimingspec"]["WR"], "WR")), + tXP (tCK * parseUint(memspec["memtimingspec"]["XP"], "XP")), + tXS (tCK * parseUint(memspec["memtimingspec"]["XS"], "XS")), + tCCD (tCK * parseUint(memspec["memtimingspec"]["CCD"], "CCD")), + tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")), + tRP (tCK * parseUint(memspec["memtimingspec"]["RP"], "RP")), + tRRD (tCK * parseUint(memspec["memtimingspec"]["RRD"], "RRD")), + tWTR (tCK * parseUint(memspec["memtimingspec"]["WTR"], "WTR")), + tAL (tCK * parseUint(memspec["memtimingspec"]["AL"], "AL")), + tXPDLL (tCK * parseUint(memspec["memtimingspec"]["XPDLL"], "XPDLL")), + tXSDLL (tCK * parseUint(memspec["memtimingspec"]["XSDLL"], "XSDLL")), + tACTPDEN (tCK * parseUint(memspec["memtimingspec"]["ACTPDEN"], "ACTPDEN")), + tPRPDEN (tCK * parseUint(memspec["memtimingspec"]["PRPDEN"], "PRPDEN")), + tRTRS (tCK * parseUint(memspec["memtimingspec"]["RTRS"], "RTRS")) +{} + +// Returns the execution time for commands that have a fixed execution time +sc_time MemSpecSTTMRAM::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) + return tRL + burstDuration; + else if (command == Command::RDA) + return tRTP + tRP; + else if (command == Command::WR) + return tWL + burstDuration; + else if (command == Command::WRA) + return tWL + burstDuration + tWR + tRP; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecSTTMRAM::getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(tRL, tRL + burstDuration); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(tWL, tWL + burstDuration); + else + { + SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); + return TimeInterval(); + } +} + +uint64_t MemSpecSTTMRAM::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfDevicesOnDIMM * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "STT-MRAM" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " Ranks: " << numberOfRanks << std::endl; + std::cout << " Banks per rank: " << banksPerRank << std::endl; + std::cout << " Rows per bank: " << numberOfRows << std::endl; + std::cout << " Columns per row: " << numberOfColumns << std::endl; + std::cout << " Device width in bits: " << bitWidth << std::endl; + std::cout << " Device size in bits: " << deviceSizeBits << std::endl; + std::cout << " Device size in bytes: " << deviceSizeBytes << std::endl; + std::cout << " Devices on DIMM: " << numberOfDevicesOnDIMM << std::endl; + std::cout << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecSTTMRAM.h b/DRAMSys/library/src/configuration/memspec/MemSpecSTTMRAM.h new file mode 100644 index 00000000..0f29a5c1 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecSTTMRAM.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021, Technische Universität 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 MEMSPECSTTMRAM_H +#define MEMSPECSTTMRAM_H + +#include "MemSpec.h" +#include "../../common/third_party/nlohmann/single_include/nlohmann/json.hpp" + +class MemSpecSTTMRAM final : public MemSpec +{ +public: + MemSpecSTTMRAM(nlohmann::json &memspec); + + // Memspec Variables: + const sc_time tCKE; + const sc_time tPD; + const sc_time tCKESR; + const sc_time tRAS; + const sc_time tRC; + const sc_time tRCD; + const sc_time tRL; + const sc_time tRTP; + const sc_time tWL; + const sc_time tWR; + const sc_time tXP; + const sc_time tXS; + const sc_time tRP; + const sc_time tDQSCK; + const sc_time tCCD; + const sc_time tFAW; + const sc_time tRRD; + const sc_time tWTR; + const sc_time tXPDLL; + const sc_time tXSDLL; + const sc_time tAL; + const sc_time tACTPDEN; + const sc_time tPRPDEN; + const sc_time tRTRS; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; + + virtual uint64_t getSimMemSizeInBytes() const override; +}; + +#endif // MEMSPECSTTMRAM_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp index 91f9f1c8..dcbd1ae7 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp @@ -126,7 +126,7 @@ sc_time MemSpecWideIO::getExecutionTime(Command command, const tlm_generic_paylo } } -TimeInterval MemSpecWideIO::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecWideIO::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL + tAC, tRL + tAC + burstDuration); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h index eb1ad7d7..79b2818c 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h @@ -95,8 +95,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp index 2b93a0cc..eb0efe10 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp @@ -117,7 +117,7 @@ sc_time MemSpecWideIO2::getExecutionTime(Command command, const tlm_generic_payl } } -TimeInterval MemSpecWideIO2::getIntervalOnDataStrobe(Command command) const +TimeInterval MemSpecWideIO2::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const { if (command == Command::RD || command == Command::RDA) return TimeInterval(tRL + tDQSCK, tRL + tDQSCK + burstDuration); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h index 35503a61..31b01a7d 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h @@ -77,8 +77,8 @@ public: virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getRefreshIntervalPB() const override; - virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; - virtual TimeInterval getIntervalOnDataStrobe(Command) const override; + virtual sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; virtual uint64_t getSimMemSizeInBytes() const override; }; diff --git a/DRAMSys/library/src/controller/BankMachine.cpp b/DRAMSys/library/src/controller/BankMachine.cpp index 0fab68d9..4fdecbb1 100644 --- a/DRAMSys/library/src/controller/BankMachine.cpp +++ b/DRAMSys/library/src/controller/BankMachine.cpp @@ -148,7 +148,8 @@ sc_time BankMachineOpen::start() else // row miss nextCommand = Command::PRE; } - timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + bankgroup, bank, DramExtension::getBurstLength(currentPayload)); } } return timeToSchedule; @@ -178,7 +179,8 @@ sc_time BankMachineClosed::start() else SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); } - timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + bankgroup, bank, DramExtension::getBurstLength(currentPayload)); } } return timeToSchedule; @@ -225,7 +227,8 @@ sc_time BankMachineOpenAdaptive::start() else // row miss nextCommand = Command::PRE; } - timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + bankgroup, bank, DramExtension::getBurstLength(currentPayload)); } } return timeToSchedule; @@ -272,7 +275,8 @@ sc_time BankMachineClosedAdaptive::start() else // row miss, should never happen SC_REPORT_FATAL("BankMachine", "Should never be reached for this policy"); } - timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + bankgroup, bank, DramExtension::getBurstLength(currentPayload)); } } return timeToSchedule; diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 21355bb1..c9c93f05 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -47,6 +47,7 @@ #include "checker/CheckerGDDR5.h" #include "checker/CheckerGDDR5X.h" #include "checker/CheckerGDDR6.h" +#include "checker/CheckerSTTMRAM.h" #include "scheduler/SchedulerFifo.h" #include "scheduler/SchedulerFrFcfs.h" #include "scheduler/SchedulerFrFcfsGrp.h" @@ -102,6 +103,8 @@ Controller::Controller(sc_module_name name) : checker = new CheckerGDDR5X(); else if (memSpec->memoryType == MemSpec::MemoryType::GDDR6) checker = new CheckerGDDR6(); + else if (memSpec->memoryType == MemSpec::MemoryType::STTMRAM) + checker = new CheckerSTTMRAM(); // instantiate scheduler and command mux if (config.scheduler == Configuration::Scheduler::Fifo) @@ -287,6 +290,7 @@ void Controller::controllerMethod() Rank rank = DramExtension::getRank(payload); BankGroup bankgroup = DramExtension::getBankGroup(payload); Bank bank = DramExtension::getBank(payload); + unsigned burstLength = DramExtension::getBurstLength(payload); if (isRankCommand(command)) { @@ -304,7 +308,7 @@ void Controller::controllerMethod() refreshManagers[rank.ID()]->updateState(command); powerDownManagers[rank.ID()]->updateState(command); - checker->insert(command, rank, bankgroup, bank); + checker->insert(command, rank, bankgroup, bank, burstLength); if (isCasCommand(command)) { @@ -312,7 +316,7 @@ void Controller::controllerMethod() manageRequests(thinkDelayFw); respQueue->insertPayload(payload, sc_time_stamp() + thinkDelayFw + phyDelayFw - + memSpec->getIntervalOnDataStrobe(command).end + + memSpec->getIntervalOnDataStrobe(command, *payload).end + phyDelayBw + thinkDelayBw); sc_time triggerTime = respQueue->getTriggerTime(); @@ -437,9 +441,9 @@ void Controller::manageResponses() NDEBUG_UNUSED(uint64_t id) = DramExtension::getChannelPayloadID(transToRelease.payload); PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system."); + numberOfBeatsServed += DramExtension::getBurstLength(transToRelease.payload); transToRelease.payload->release(); transToRelease.payload = nullptr; - numberOfTransactionsServed++; totalNumberOfPayloads--; if (totalNumberOfPayloads == 0) diff --git a/DRAMSys/library/src/controller/ControllerIF.h b/DRAMSys/library/src/controller/ControllerIF.h index b23c3a2e..aebae208 100644 --- a/DRAMSys/library/src/controller/ControllerIF.h +++ b/DRAMSys/library/src/controller/ControllerIF.h @@ -55,8 +55,7 @@ public: // Destructor virtual ~ControllerIF() { - sc_time activeTime = numberOfTransactionsServed - * Configuration::getInstance().memSpec->burstLength + sc_time activeTime = numberOfBeatsServed / Configuration::getInstance().memSpec->dataRate * Configuration::getInstance().memSpec->tCK; @@ -143,7 +142,7 @@ protected: sc_time idleStart; } idleTimeCollector; - uint64_t numberOfTransactionsServed = 0; + uint64_t numberOfBeatsServed = 0; }; diff --git a/DRAMSys/library/src/controller/ControllerRecordable.cpp b/DRAMSys/library/src/controller/ControllerRecordable.cpp index bd548d50..34350af4 100644 --- a/DRAMSys/library/src/controller/ControllerRecordable.cpp +++ b/DRAMSys/library/src/controller/ControllerRecordable.cpp @@ -75,7 +75,7 @@ void ControllerRecordable::sendToDram(Command command, tlm_generic_payload *payl { if (isCasCommand(command)) { - TimeInterval dataStrobe = Configuration::getInstance().memSpec->getIntervalOnDataStrobe(command); + TimeInterval dataStrobe = Configuration::getInstance().memSpec->getIntervalOnDataStrobe(command, *payload); tlmRecorder->updateDataStrobe(sc_time_stamp() + delay + dataStrobe.start, sc_time_stamp() + delay + dataStrobe.end, *payload); } @@ -130,9 +130,9 @@ void ControllerRecordable::controllerMethod() Controller::controllerMethod(); - uint64_t windowNumberOfTransactionsServed = numberOfTransactionsServed - lastNumberOfTransactionsServed; - lastNumberOfTransactionsServed = numberOfTransactionsServed; - sc_time windowActiveTime = windowNumberOfTransactionsServed * activeTimeMultiplier; + uint64_t windowNumberOfBeatsServed = numberOfBeatsServed - lastNumberOfBeatsServed; + lastNumberOfBeatsServed = numberOfBeatsServed; + sc_time windowActiveTime = windowNumberOfBeatsServed * activeTimeMultiplier; double windowAverageBandwidth = windowActiveTime / windowSizeTime; tlmRecorder->recordBandwidth(sc_time_stamp().to_seconds(), windowAverageBandwidth); } diff --git a/DRAMSys/library/src/controller/ControllerRecordable.h b/DRAMSys/library/src/controller/ControllerRecordable.h index c2efa334..9459cd12 100644 --- a/DRAMSys/library/src/controller/ControllerRecordable.h +++ b/DRAMSys/library/src/controller/ControllerRecordable.h @@ -66,10 +66,9 @@ private: std::vector windowAverageBufferDepth; sc_time lastTimeCalled = SC_ZERO_TIME; - uint64_t lastNumberOfTransactionsServed = 0; - sc_time activeTimeMultiplier = Configuration::getInstance().memSpec->burstLength - / Configuration::getInstance().memSpec->dataRate - * Configuration::getInstance().memSpec->tCK; + uint64_t lastNumberOfBeatsServed = 0; + sc_time activeTimeMultiplier = Configuration::getInstance().memSpec->tCK + / Configuration::getInstance().memSpec->dataRate; }; #endif // CONTROLLERRECORDABLE_H diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp index 1e48ea04..089a753b 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp @@ -52,7 +52,7 @@ CheckerDDR3::CheckerDDR3() tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; tRDWR = memSpec->tRL + tBURST + 2 * memSpec->tCK - memSpec->tWL; tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL; - tWRRD = memSpec->tWL + tBURST + memSpec->tWTR; + tWRRD = memSpec->tWL + tBURST + memSpec->tWTR - memSpec->tAL; tWRRD_R = memSpec->tWL + tBURST + memSpec->tRTRS - memSpec->tRL; tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; tRDPDEN = memSpec->tRL + tBURST + memSpec->tCK; @@ -60,7 +60,7 @@ CheckerDDR3::CheckerDDR3() tWRAPDEN = memSpec->tWL + tBURST + memSpec->tWR + memSpec->tCK; } -sc_time CheckerDDR3::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +sc_time CheckerDDR3::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -91,7 +91,7 @@ sc_time CheckerDDR3::timeToSatisfyConstraints(Command command, Rank rank, BankGr { lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP - memSpec->tAL); } lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; @@ -412,7 +412,7 @@ sc_time CheckerDDR3::timeToSatisfyConstraints(Command command, Rank rank, BankGr return earliestTimeToStart; } -void CheckerDDR3::insert(Command command, Rank rank, BankGroup, Bank bank) +void CheckerDDR3::insert(Command command, Rank rank, BankGroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerDDR3", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.h b/DRAMSys/library/src/controller/checker/CheckerDDR3.h index efce001a..1eed6b48 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.h @@ -45,8 +45,9 @@ class CheckerDDR3 final : public CheckerIF { public: CheckerDDR3(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecDDR3 *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp index 1dad1943..3dda147b 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp @@ -54,8 +54,8 @@ CheckerDDR4::CheckerDDR4() tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; tRDWR = memSpec->tRL + tBURST + memSpec->tCK - memSpec->tWL + memSpec->tWPRE; tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL + memSpec->tWPRE; - tWRRD_S = memSpec->tWL + tBURST + memSpec->tWTR_S; - tWRRD_L = memSpec->tWL + tBURST + memSpec->tWTR_L; + tWRRD_S = memSpec->tWL + tBURST + memSpec->tWTR_S - memSpec->tAL; + tWRRD_L = memSpec->tWL + tBURST + memSpec->tWTR_L - memSpec->tAL; tWRRD_R = memSpec->tWL + tBURST + memSpec->tRTRS - memSpec->tRL + memSpec->tRPRE; tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; tRDPDEN = memSpec->tRL + tBURST + memSpec->tCK; @@ -63,7 +63,7 @@ CheckerDDR4::CheckerDDR4() tWRAPDEN = memSpec->tWL + tBURST + memSpec->tCK + memSpec->tWR; } -sc_time CheckerDDR4::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +sc_time CheckerDDR4::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -102,7 +102,7 @@ sc_time CheckerDDR4::timeToSatisfyConstraints(Command command, Rank rank, BankGr { lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP - memSpec->tAL); } lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; @@ -443,7 +443,7 @@ sc_time CheckerDDR4::timeToSatisfyConstraints(Command command, Rank rank, BankGr return earliestTimeToStart; } -void CheckerDDR4::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +void CheckerDDR4::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerDDR4", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.h b/DRAMSys/library/src/controller/checker/CheckerDDR4.h index 694eecd4..d2befee3 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR4.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.h @@ -45,8 +45,9 @@ class CheckerDDR4 final : public CheckerIF { public: CheckerDDR4(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecDDR4 *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp index a5458a3d..775008aa 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp @@ -41,7 +41,7 @@ CheckerDDR5::CheckerDDR5() if (memSpec == nullptr) SC_REPORT_FATAL("CheckerDDR5", "Wrong MemSpec chosen"); - lastScheduledByCommandAndDIMMRank = std::vector> + lastScheduledByCommandAndDimmRank = std::vector> (numberOfCommands(), std::vector(memSpec->numberOfDIMMRanks, sc_max_time())); lastScheduledByCommandAndPhysicalRank = std::vector> (numberOfCommands(), std::vector(memSpec->numberOfPhysicalRanks, sc_max_time())); @@ -56,40 +56,63 @@ CheckerDDR5::CheckerDDR5() lastScheduledByCommandAndBankInGroup = std::vector>(numberOfCommands(), std::vector(memSpec->numberOfRanks * memSpec->banksPerGroup, sc_max_time())); lastCommandOnBus = sc_max_time(); + dummyCommandOnBus.start = sc_max_time(); + dummyCommandOnBus.end = sc_max_time(); + last4ActivatesLogical = std::vector>(memSpec->numberOfLogicalRanks); last4ActivatesPhysical = std::vector>(memSpec->numberOfPhysicalRanks); - cmdOffset = memSpec->cmdMode * memSpec->tCK; + lastBurstLengthByCommandAndDimmRank = std::vector> + (4, std::vector(memSpec->numberOfDIMMRanks)); + lastBurstLengthByCommandAndPhysicalRank = std::vector> + (4, std::vector(memSpec->numberOfPhysicalRanks)); + lastBurstLengthByCommandAndLogicalRank = std::vector> + (4, std::vector(memSpec->numberOfLogicalRanks)); + lastBurstLengthByCommandAndBankGroup = std::vector> + (4, std::vector(memSpec->numberOfBankGroups)); + lastBurstLengthByCommandAndBank = std::vector> + (4, std::vector(memSpec->numberOfBanks)); + lastBurstLengthByCommand = std::vector(4); + lastBurstLengthByCommandAndBankInGroup = std::vector> + (4, std::vector(memSpec->numberOfRanks * memSpec->banksPerGroup)); - tRD_BURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; - tWR_BURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; + cmdLengthDiff = memSpec->cmdMode * memSpec->tCK; + + tBURST16 = 8 * memSpec->tCK; + tBURST32 = 16 * memSpec->tCK; tWTRA = memSpec->tWR - memSpec->tRTP; - tWRRDA = memSpec->tWL + tWR_BURST + tWTRA; - tWRPRE = memSpec->tWL + tWR_BURST + memSpec->tWR; + tWRRDA = memSpec->tWL + tBURST16 + tWTRA; // tWTRA = tWR - tRTP + tWRPRE = memSpec->tWL + tBURST16 + memSpec->tWR; tRDAACT = memSpec->tRTP + memSpec->tRP; tWRAACT = tWRPRE + memSpec->tRP; - tCCD_L_RTW_slr = memSpec->tRL - memSpec->tWL + tRD_BURST + 2 * memSpec->tCK - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; - tCCD_S_RTW_slr = memSpec->tRL - memSpec->tWL + tRD_BURST + 2 * memSpec->tCK - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; - tCCD_RTW_dlr = memSpec->tRL - memSpec->tWL + tRD_BURST + 2 * memSpec->tCK - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; - tRDRD_dpr = tRD_BURST + memSpec->tRTRS; - tRDRD_ddr = tRD_BURST + memSpec->tRTRS; - tRDWR_dpr = memSpec->tRL - memSpec->tWL + tRD_BURST + memSpec->tRTRS - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; - tRDWR_ddr = memSpec->tRL - memSpec->tWL + tRD_BURST + memSpec->tRTRS - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; - tCCD_L_WTR_slr = memSpec->tWL + tWR_BURST + memSpec->tWTR_L; - tCCD_S_WTR_slr = memSpec->tWL + tWR_BURST + memSpec->tWTR_S; - tCCD_WTR_dlr = memSpec->tWL + tWR_BURST + memSpec->tWTR_S; - tWRWR_dpr = std::max(memSpec->tCCD_WR_dpr, tWR_BURST + memSpec->tRTRS); - tWRWR_ddr = tWR_BURST + memSpec->tRTRS; - tWRRD_dpr = memSpec->tWL - memSpec->tRL + tWR_BURST + memSpec->tRTRS + memSpec->tRDDQS + memSpec->tWPST + memSpec->tRPRE; - tWRRD_ddr = memSpec->tWL - memSpec->tRL + tWR_BURST + memSpec->tRTRS + memSpec->tRDDQS + memSpec->tWPST + memSpec->tRPRE; - tRDPDEN = memSpec->tRL + tRD_BURST + cmdOffset; - tWRPDEN = memSpec->tWL + tWR_BURST + memSpec->tWR + cmdOffset; - tWRAPDEN = memSpec->tWL + tWR_BURST + memSpec->tWR + cmdOffset; - - // TODO: tRTP BL 32 (similar to LPDDR4) + tCCD_L_RTW_slr = memSpec->tRL - memSpec->tWL + tBURST16 + 2 * memSpec->tCK + - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; + tCCD_S_RTW_slr = memSpec->tRL - memSpec->tWL + tBURST16 + 2 * memSpec->tCK + - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; + tCCD_RTW_dlr = memSpec->tRL - memSpec->tWL + tBURST16 + 2 * memSpec->tCK + - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; + tRDRD_dpr = tBURST16 + memSpec->tRTRS; + tRDRD_ddr = tBURST16 + memSpec->tRTRS; + tRDWR_dpr = memSpec->tRL - memSpec->tWL + tBURST16 + memSpec->tRTRS + - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; + tRDWR_ddr = memSpec->tRL - memSpec->tWL + tBURST16 + memSpec->tRTRS + - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; + tCCD_L_WTR_slr = memSpec->tWL + tBURST16 + memSpec->tWTR_L; + tCCD_S_WTR_slr = memSpec->tWL + tBURST16 + memSpec->tWTR_S; + tCCD_WTR_dlr = memSpec->tWL + tBURST16 + memSpec->tWTR_S; + tWRWR_dpr = std::max(memSpec->tCCD_WR_dpr, tBURST16 + memSpec->tRTRS); + tWRWR_ddr = tBURST16 + memSpec->tRTRS; + tWRRD_dpr = memSpec->tWL - memSpec->tRL + tBURST16 + memSpec->tRTRS + + memSpec->tRDDQS + memSpec->tWPST + memSpec->tRPRE; + tWRRD_ddr = memSpec->tWL - memSpec->tRL + tBURST16 + memSpec->tRTRS + + memSpec->tRDDQS + memSpec->tWPST + memSpec->tRPRE; + tRDPDEN = memSpec->tRL + tBURST16 + cmdLengthDiff; + tWRPDEN = memSpec->tWL + tBURST16 + memSpec->tWR + cmdLengthDiff; + tWRAPDEN = memSpec->tWL + tBURST16 + memSpec->tWR + cmdLengthDiff; } -sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank, + unsigned burstLength) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -116,15 +139,30 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::RD][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST32); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_dlr); + } lastCommandStart = lastScheduledByCommand[Command::RD]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RD][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::RD][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::RD][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::RD] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr); + } } lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; @@ -137,64 +175,134 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST32); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_dlr); + } lastCommandStart = lastScheduledByCommand[Command::RDA]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RDA][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::RDA][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::RDA][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::RDA] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr); + } } if (command == Command::RDA) { lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDA); + { + if (lastBurstLengthByCommandAndBank[Command::WR][bank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDA + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDA); + } } lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + { + if (lastBurstLengthByCommandAndBankGroup[Command::WR][bankgroup.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WR][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr); + { + if (lastBurstLengthByCommandAndLogicalRank[Command::WR][logicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr); + } lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr); + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::WR][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr); + } lastCommandStart = lastScheduledByCommand[Command::WR]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WR][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::WR][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::WR][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::WR] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr); + } } lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + { + if (lastBurstLengthByCommandAndBankGroup[Command::WRA][bankgroup.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr); + { + if (lastBurstLengthByCommandAndLogicalRank[Command::WRA][logicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr); + } lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr); + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr); + } lastCommandStart = lastScheduledByCommand[Command::WRA]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WRA][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::WRA][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::WRA][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::WRA] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr); + } } } else if (command == Command::WR || command == Command::WRA) @@ -205,49 +313,114 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr); + { + if (lastBurstLengthByCommandAndBankGroup[Command::RD][bankgroup.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr); + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RD][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr); + { + if (lastBurstLengthByCommandAndLogicalRank[Command::RD][logicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr); + } lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr); + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::RD][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr); + } lastCommandStart = lastScheduledByCommand[Command::RD]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RD][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::RD][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::RD][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::RD] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr); + } } lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr); + { + if (lastBurstLengthByCommandAndBankGroup[Command::RDA][bankgroup.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr); + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RDA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr); + { + if (lastBurstLengthByCommandAndLogicalRank[Command::RDA][logicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr); + } lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr); + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr); + } lastCommandStart = lastScheduledByCommand[Command::RDA]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RDA][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::RDA][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::RDA][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::RDA] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr); + } } lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + { + if (lastBurstLengthByCommandAndBankGroup[Command::WR][bankgroup.ID()] == 32) + { + if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR_slr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR2_slr); + } + else + { + if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR2_slr); + } + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WR][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) @@ -255,20 +428,50 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::WR][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST32); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_WR_dlr); + } lastCommandStart = lastScheduledByCommand[Command::WR]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WR][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::WR][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::WR][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::WR] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr); + } } lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + { + if (lastBurstLengthByCommandAndBankGroup[Command::WRA][bankgroup.ID()] == 32) + { + if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR_slr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR2_slr); + } + else + { + if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR2_slr); + } + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) @@ -276,15 +479,30 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) + { + if (lastBurstLengthByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST32); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_WR_dlr); + } lastCommandStart = lastScheduledByCommand[Command::WRA]; - if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]) + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]) // different physical rank { - if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WRA][dimmrank.ID()]) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr); - else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr); + if (lastCommandStart == lastScheduledByCommandAndDimmRank[Command::WRA][dimmrank.ID()]) // same DIMM + { + if (lastBurstLengthByCommandAndDimmRank[Command::WRA][dimmrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr); + } + else // different DIMM + { + if (lastBurstLengthByCommand[Command::WRA] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr); + } } } else if (command == Command::ACT) @@ -311,61 +529,71 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT); + { + if (lastBurstLengthByCommandAndBank[Command::WRA][bank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT); + } lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdOffset); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::PREA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdOffset); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRESB][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdOffset); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr - cmdOffset); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr - cmdLengthDiff); // TODO: No tRFC_dlr and tRFC_dpr between REFA and ACT? lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::REFSB][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr - cmdOffset); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr - cmdLengthDiff); // TODO: No tRFCsb_dlr between REFSB and ACT? lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFSB][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_slr - cmdOffset); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_slr - cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFSB][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_dlr - cmdOffset); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_dlr - cmdLengthDiff); if (last4ActivatesLogical[logicalrank.ID()].size() >= 4) earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesLogical[logicalrank.ID()].front() - + memSpec->tFAW_slr - memSpec->cmdOffset_L); + + memSpec->tFAW_slr - memSpec->longCmdOffset); if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4) earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesPhysical[physicalrank.ID()].front() - + memSpec->tFAW_dlr - memSpec->cmdOffset_L); + + memSpec->tFAW_dlr - memSpec->longCmdOffset); } else if (command == Command::PRE) { lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + { + if (lastBurstLengthByCommandAndBank[Command::WR][bank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + tBURST16 + cmdLengthDiff); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + cmdLengthDiff); + } lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) @@ -383,23 +611,33 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr { lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RD][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RDA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WR][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + { + if (lastBurstLengthByCommandAndLogicalRank[Command::WR][logicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + tBURST16 + cmdLengthDiff); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + cmdLengthDiff); + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + { + if (lastBurstLengthByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + tBURST16 + cmdLengthDiff); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + cmdLengthDiff); + } lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) @@ -415,23 +653,33 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr { lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RD][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WR][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + { + if (lastBurstLengthByCommandAndBankInGroup[Command::WR][bankInGroup.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + tBURST16 + cmdLengthDiff); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + cmdLengthDiff); + } lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WRA][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + { + if (lastBurstLengthByCommandAndBankInGroup[Command::WRA][bankInGroup.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + tBURST16 + cmdLengthDiff); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + cmdLengthDiff); + } lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) @@ -447,15 +695,20 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr { lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP + memSpec->tCK); + { + if (lastBurstLengthByCommandAndLogicalRank[Command::WRA][logicalrank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + tBURST16 + memSpec->tRP + cmdLengthDiff); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP + cmdLengthDiff); + } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::PRE][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) @@ -473,7 +726,7 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr if (lastCommandStart != sc_max_time()) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dlr); - lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()]; + lastCommandStart = lastScheduledByCommandAndDimmRank[Command::REFA][dimmrank.ID()]; if (lastCommandStart != sc_max_time()) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr); @@ -484,19 +737,24 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr { lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L_slr + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L_slr + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + memSpec->tCK); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + cmdLengthDiff); lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WRA][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT + memSpec->tCK); + { + if (lastBurstLengthByCommandAndBankInGroup[Command::WRA][bankInGroup.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT + tBURST16 + cmdLengthDiff); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT + cmdLengthDiff); + } lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRE][bankInGroup.ID()]; if (lastCommandStart != sc_max_time()) @@ -518,7 +776,7 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dlr); // TODO: check this - lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()]; + lastCommandStart = lastScheduledByCommandAndDimmRank[Command::REFA][dimmrank.ID()]; if (lastCommandStart != sc_max_time()) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr); @@ -532,11 +790,11 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr if (last4ActivatesLogical[logicalrank.ID()].size() >= 4) earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesLogical[logicalrank.ID()].front() - + memSpec->tFAW_slr - memSpec->cmdOffset_S); + + memSpec->tFAW_slr - memSpec->shortCmdOffset); if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4) earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesPhysical[physicalrank.ID()].front() - + memSpec->tFAW_dlr - memSpec->cmdOffset_S); + + memSpec->tFAW_dlr - memSpec->shortCmdOffset); } else SC_REPORT_FATAL("CheckerDDR5", "Unknown command!"); @@ -544,38 +802,62 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr if (lastCommandOnBus != sc_max_time()) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->tCK); + if (dummyCommandOnBus.start != sc_max_time()) + { + TimeInterval currentCommandOnBus(earliestTimeToStart, + earliestTimeToStart + memSpec->getCommandLength(command)); + if (currentCommandOnBus.intersects(dummyCommandOnBus)) + earliestTimeToStart = dummyCommandOnBus.end; + } + return earliestTimeToStart; } -void CheckerDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +void CheckerDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned burstLength) { PRINTDEBUGMESSAGE("CheckerDDR5", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); - Rank logicalrank = rank; - Rank physicalrank = Rank(logicalrank.ID() / memSpec->logicalRanksPerPhysicalRank); - Rank dimmrank = Rank(physicalrank.ID() / memSpec->physicalRanksPerDIMMRank); + Rank logicalRank = rank; + Rank physicalRank = Rank(logicalRank.ID() / memSpec->logicalRanksPerPhysicalRank); + Rank dimmRank = Rank(physicalRank.ID() / memSpec->physicalRanksPerDIMMRank); + Bank bankInGroup = Bank(rank.ID() * memSpec->banksPerGroup + bank.ID() % memSpec->banksPerGroup); - lastScheduledByCommandAndDIMMRank[command][dimmrank.ID()] = sc_time_stamp(); - lastScheduledByCommandAndPhysicalRank[command][physicalrank.ID()] = sc_time_stamp(); - lastScheduledByCommandAndLogicalRank[command][logicalrank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndDimmRank[command][dimmRank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndPhysicalRank[command][physicalRank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndLogicalRank[command][logicalRank.ID()] = sc_time_stamp(); lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp(); lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); lastScheduledByCommand[command] = sc_time_stamp(); + lastScheduledByCommandAndBankInGroup[command][bankInGroup.ID()] = sc_time_stamp(); + + if (isCasCommand(command)) + { + lastBurstLengthByCommandAndDimmRank[command][dimmRank.ID()] = burstLength; + lastBurstLengthByCommandAndPhysicalRank[command][physicalRank.ID()] = burstLength; + lastBurstLengthByCommandAndLogicalRank[command][logicalRank.ID()] = burstLength; + lastBurstLengthByCommandAndBankGroup[command][bankgroup.ID()] = burstLength; + lastBurstLengthByCommandAndBank[command][bank.ID()] = burstLength; + lastBurstLengthByCommand[command] = burstLength; + lastBurstLengthByCommandAndBankInGroup[command][bankInGroup.ID()] = burstLength; + + if (burstLength == 32) + { + dummyCommandOnBus.start = sc_time_stamp() + tBURST16; + dummyCommandOnBus.end = sc_time_stamp() + tBURST16 + memSpec->getCommandLength(command); + } + } lastCommandOnBus = sc_time_stamp() + memSpec->getCommandLength(command) - memSpec->tCK; - lastScheduledByCommandAndBankInGroup[command][rank.ID() * memSpec->banksPerGroup - + bank.ID() % memSpec->banksPerGroup] = sc_time_stamp(); - if (command == Command::ACT || command == Command::REFSB) { - if (last4ActivatesLogical[logicalrank.ID()].size() == 4) - last4ActivatesLogical[logicalrank.ID()].pop(); - last4ActivatesLogical[logicalrank.ID()].push(lastCommandOnBus); + if (last4ActivatesLogical[logicalRank.ID()].size() == 4) + last4ActivatesLogical[logicalRank.ID()].pop(); + last4ActivatesLogical[logicalRank.ID()].push(lastCommandOnBus); - if (last4ActivatesPhysical[physicalrank.ID()].size() == 4) - last4ActivatesPhysical[physicalrank.ID()].pop(); - last4ActivatesPhysical[physicalrank.ID()].push(lastCommandOnBus); + if (last4ActivatesPhysical[physicalRank.ID()].size() == 4) + last4ActivatesPhysical[physicalRank.ID()].pop(); + last4ActivatesPhysical[physicalRank.ID()].push(lastCommandOnBus); } } diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR5.h b/DRAMSys/library/src/controller/checker/CheckerDDR5.h index caf04154..7717b052 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR5.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.h @@ -40,34 +40,48 @@ #include #include "../../configuration/memspec/MemSpecDDR5.h" #include "../../configuration/Configuration.h" +#include "../../common/utils.h" class CheckerDDR5 final : public CheckerIF { public: CheckerDDR5(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecDDR5 *memSpec; - std::vector> lastScheduledByCommandAndDIMMRank; + std::vector> lastScheduledByCommandAndDimmRank; std::vector> lastScheduledByCommandAndPhysicalRank; std::vector> lastScheduledByCommandAndLogicalRank; std::vector> lastScheduledByCommandAndBankGroup; std::vector> lastScheduledByCommandAndBank; std::vector lastScheduledByCommand; sc_time lastCommandOnBus; + TimeInterval dummyCommandOnBus; std::vector> lastScheduledByCommandAndBankInGroup; std::vector> last4ActivatesPhysical; std::vector> last4ActivatesLogical; - sc_time cmdOffset; + std::vector> lastBurstLengthByCommandAndDimmRank; + std::vector> lastBurstLengthByCommandAndPhysicalRank; + std::vector> lastBurstLengthByCommandAndLogicalRank; + std::vector> lastBurstLengthByCommandAndBankGroup; + std::vector> lastBurstLengthByCommandAndBank; + std::vector lastBurstLengthByCommand; - sc_time tRD_BURST; - sc_time tWR_BURST; + std::vector> lastBurstLengthByCommandAndBankInGroup; + + // TODO: store BL of last RD and WR globally or for each hierarchy? + + sc_time cmdLengthDiff; + + sc_time tBURST16; + sc_time tBURST32; sc_time tWTRA; sc_time tWRRDA; sc_time tWRPRE; diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp index fe5fc00d..a32251f1 100644 --- a/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp @@ -64,7 +64,7 @@ CheckerGDDR5::CheckerGDDR5() tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; } -sc_time CheckerGDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +sc_time CheckerGDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -525,7 +525,7 @@ sc_time CheckerGDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankG return earliestTimeToStart; } -void CheckerGDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +void CheckerGDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerGDDR5", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5.h b/DRAMSys/library/src/controller/checker/CheckerGDDR5.h index 326dae75..30ab9287 100644 --- a/DRAMSys/library/src/controller/checker/CheckerGDDR5.h +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5.h @@ -45,8 +45,9 @@ class CheckerGDDR5 final : public CheckerIF { public: CheckerGDDR5(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecGDDR5 *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp index bb5679a9..487184a0 100644 --- a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp @@ -64,7 +64,7 @@ CheckerGDDR5X::CheckerGDDR5X() tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; } -sc_time CheckerGDDR5X::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +sc_time CheckerGDDR5X::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -525,7 +525,7 @@ sc_time CheckerGDDR5X::timeToSatisfyConstraints(Command command, Rank rank, Bank return earliestTimeToStart; } -void CheckerGDDR5X::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +void CheckerGDDR5X::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerGDDR5X", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h index 39138be3..652de82b 100644 --- a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h @@ -45,8 +45,9 @@ class CheckerGDDR5X final : public CheckerIF { public: CheckerGDDR5X(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecGDDR5X *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp index f0f6fa54..f50504e6 100644 --- a/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp @@ -63,7 +63,7 @@ CheckerGDDR6::CheckerGDDR6() tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; } -sc_time CheckerGDDR6::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +sc_time CheckerGDDR6::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -546,7 +546,7 @@ sc_time CheckerGDDR6::timeToSatisfyConstraints(Command command, Rank rank, BankG return earliestTimeToStart; } -void CheckerGDDR6::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +void CheckerGDDR6::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerGDDR6", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR6.h b/DRAMSys/library/src/controller/checker/CheckerGDDR6.h index 202bd8d3..edd78a7c 100644 --- a/DRAMSys/library/src/controller/checker/CheckerGDDR6.h +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR6.h @@ -45,8 +45,9 @@ class CheckerGDDR6 final : public CheckerIF { public: CheckerGDDR6(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecGDDR6 *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM2.cpp b/DRAMSys/library/src/controller/checker/CheckerHBM2.cpp index 4ed20f3f..7472d0ad 100644 --- a/DRAMSys/library/src/controller/checker/CheckerHBM2.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerHBM2.cpp @@ -64,7 +64,7 @@ CheckerHBM2::CheckerHBM2() tWRRDL = memSpec->tWL + tBURST + memSpec->tWTRL; } -sc_time CheckerHBM2::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +sc_time CheckerHBM2::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -500,7 +500,7 @@ sc_time CheckerHBM2::timeToSatisfyConstraints(Command command, Rank rank, BankGr return earliestTimeToStart; } -void CheckerHBM2::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +void CheckerHBM2::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerHBM2", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM2.h b/DRAMSys/library/src/controller/checker/CheckerHBM2.h index 3578ee9b..a68a5f86 100644 --- a/DRAMSys/library/src/controller/checker/CheckerHBM2.h +++ b/DRAMSys/library/src/controller/checker/CheckerHBM2.h @@ -45,8 +45,9 @@ class CheckerHBM2 final : public CheckerIF { public: CheckerHBM2(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecHBM2 *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerIF.h b/DRAMSys/library/src/controller/checker/CheckerIF.h index b5c4d9bb..a930d797 100644 --- a/DRAMSys/library/src/controller/checker/CheckerIF.h +++ b/DRAMSys/library/src/controller/checker/CheckerIF.h @@ -46,8 +46,9 @@ class CheckerIF public: virtual ~CheckerIF() {} - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const = 0; - virtual void insert(Command, Rank, BankGroup, Bank) = 0; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const = 0; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) = 0; }; #endif // CHECKERIF_H diff --git a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp index 366f9b1f..2dfc9456 100644 --- a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp @@ -66,7 +66,7 @@ CheckerLPDDR4::CheckerLPDDR4() tREFPDEN = memSpec->tCK + memSpec->tCMDCKE; } -sc_time CheckerLPDDR4::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +sc_time CheckerLPDDR4::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -496,7 +496,7 @@ sc_time CheckerLPDDR4::timeToSatisfyConstraints(Command command, Rank rank, Bank return earliestTimeToStart; } -void CheckerLPDDR4::insert(Command command, Rank rank, BankGroup, Bank bank) +void CheckerLPDDR4::insert(Command command, Rank rank, BankGroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerLPDDR4", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h index 5a73154a..3fe5e506 100644 --- a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h +++ b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h @@ -45,8 +45,9 @@ class CheckerLPDDR4 final : public CheckerIF { public: CheckerLPDDR4(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecLPDDR4 *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerSTTMRAM.cpp b/DRAMSys/library/src/controller/checker/CheckerSTTMRAM.cpp new file mode 100644 index 00000000..bb157ee7 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerSTTMRAM.cpp @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2021, Technische Universität 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 "CheckerSTTMRAM.h" + +CheckerSTTMRAM::CheckerSTTMRAM() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerSTTMRAM", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfBanks, sc_max_time())); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfRanks, sc_max_time())); + lastScheduledByCommand = std::vector(numberOfCommands(), sc_max_time()); + lastCommandOnBus = sc_max_time(); + last4Activates = std::vector>(memSpec->numberOfRanks); + + tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; + tRDWR = memSpec->tRL + tBURST + 2 * memSpec->tCK - memSpec->tWL; + tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL; + tWRRD = memSpec->tWL + tBURST + memSpec->tWTR - memSpec->tAL; + tWRRD_R = memSpec->tWL + tBURST + memSpec->tRTRS - memSpec->tRL; + tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; + tRDPDEN = memSpec->tRL + tBURST + memSpec->tCK; + tWRPDEN = memSpec->tWL + tBURST + memSpec->tWR; + tWRAPDEN = memSpec->tWL + tBURST + memSpec->tWR + memSpec->tCK; +} + +sc_time CheckerSTTMRAM::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank, unsigned) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::RD] != lastScheduledByCommandAndRank[Command::RD][rank.ID()] ? + lastScheduledByCommand[Command::RD] : sc_max_time(); + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::RDA] != lastScheduledByCommandAndRank[Command::RDA][rank.ID()] ? + lastScheduledByCommand[Command::RDA] : sc_max_time(); + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP - memSpec->tAL); + } + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_R); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_R); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD] != lastScheduledByCommandAndRank[Command::RD][rank.ID()] ? lastScheduledByCommand[Command::RD] : sc_max_time(); + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_R); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR); + + lastCommandStart = lastScheduledByCommand[Command::RDA] != lastScheduledByCommandAndRank[Command::RDA][rank.ID()] ? lastScheduledByCommand[Command::RDA] : sc_max_time(); + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_R); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WR] != lastScheduledByCommandAndRank[Command::WR][rank.ID()] ? lastScheduledByCommand[Command::WR] : sc_max_time(); + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD); + + lastCommandStart = lastScheduledByCommand[Command::WRA] != lastScheduledByCommandAndRank[Command::WRA][rank.ID()] ? lastScheduledByCommand[Command::WRA] : sc_max_time(); + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL); + } + else if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + if (last4Activates[rank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + } + else if (command == Command::PDEA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tACTPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + } + else if (command == Command::PDXA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::PDEA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD); + } + else if (command == Command::PDEP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::PDXP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::PDEP][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD); + } + else if (command == Command::SREFEN) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + std::max(tRDPDEN, memSpec->tAL + memSpec->tRTP + memSpec->tRP)); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + std::max(tWRAPDEN, tWRPRE + memSpec->tRP)); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::SREFEX) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEN][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKESR); + } + else + SC_REPORT_FATAL("CheckerSTTMRAM", "Unknown command!"); + + if (lastCommandOnBus != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->tCK); + + return earliestTimeToStart; +} + +void CheckerSTTMRAM::insert(Command command, Rank rank, BankGroup, Bank bank, unsigned) +{ + PRINTDEBUGMESSAGE("CheckerSTTMRAM", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + commandToString(command)); + + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT) + { + if (last4Activates[rank.ID()].size() == 4) + last4Activates[rank.ID()].pop(); + last4Activates[rank.ID()].push(sc_time_stamp()); + } +} diff --git a/DRAMSys/library/src/controller/checker/CheckerSTTMRAM.h b/DRAMSys/library/src/controller/checker/CheckerSTTMRAM.h new file mode 100644 index 00000000..50d48d53 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerSTTMRAM.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Technische Universität 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 CHECKERSTTMRAM_H +#define CHECKERSTTMRAM_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecSTTMRAM.h" +#include "../../configuration/Configuration.h" + +class CheckerSTTMRAM final : public CheckerIF +{ +public: + CheckerSTTMRAM(); + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; + +private: + const MemSpecSTTMRAM *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // Four activate window + std::vector> last4Activates; + + sc_time tBURST; + sc_time tRDWR; + sc_time tRDWR_R; + sc_time tWRRD; + sc_time tWRPRE; + sc_time tWRRD_R; + sc_time tRDPDEN; + sc_time tWRPDEN; + sc_time tWRAPDEN; +}; + +#endif // CHECKERSTTMRAM_H diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp index 6f588494..16985f5d 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp @@ -60,7 +60,7 @@ CheckerWideIO::CheckerWideIO() tWRAPDEN = memSpec->tWL + tBURST + memSpec->tWR; // + memSpec->tCK; ?? } -sc_time CheckerWideIO::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +sc_time CheckerWideIO::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -385,7 +385,7 @@ sc_time CheckerWideIO::timeToSatisfyConstraints(Command command, Rank rank, Bank return earliestTimeToStart; } -void CheckerWideIO::insert(Command command, Rank rank, BankGroup, Bank bank) +void CheckerWideIO::insert(Command command, Rank rank, BankGroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerWideIO", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.h b/DRAMSys/library/src/controller/checker/CheckerWideIO.h index e5cdb430..c8b145a6 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO.h +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.h @@ -45,8 +45,9 @@ class CheckerWideIO final : public CheckerIF { public: CheckerWideIO(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecWideIO *memSpec; diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO2.cpp b/DRAMSys/library/src/controller/checker/CheckerWideIO2.cpp index 14818bed..10e75682 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO2.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO2.cpp @@ -61,7 +61,7 @@ CheckerWideIO2::CheckerWideIO2() tWRRD_R = memSpec->tWL + memSpec->tCK + tBURST + memSpec->tRTRS - memSpec->tRL; } -sc_time CheckerWideIO2::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const +sc_time CheckerWideIO2::timeToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank, unsigned) const { sc_time lastCommandStart; sc_time earliestTimeToStart = sc_time_stamp(); @@ -463,7 +463,7 @@ sc_time CheckerWideIO2::timeToSatisfyConstraints(Command command, Rank rank, Ban return earliestTimeToStart; } -void CheckerWideIO2::insert(Command command, Rank rank, BankGroup, Bank bank) +void CheckerWideIO2::insert(Command command, Rank rank, BankGroup, Bank bank, unsigned) { PRINTDEBUGMESSAGE("CheckerWideIO2", "Changing state on bank " + std::to_string(bank.ID()) + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO2.h b/DRAMSys/library/src/controller/checker/CheckerWideIO2.h index 08d328b9..a1e32636 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO2.h +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO2.h @@ -45,8 +45,9 @@ class CheckerWideIO2 final : public CheckerIF { public: CheckerWideIO2(); - virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; - virtual void insert(Command, Rank, BankGroup, Bank) override; + virtual sc_time timeToSatisfyConstraints(Command, Rank = Rank(0), + BankGroup = BankGroup(0), Bank = Bank(0), unsigned burstLength = 0) const override; + virtual void insert(Command, Rank, BankGroup, Bank, unsigned) override; private: const MemSpecWideIO2 *memSpec; diff --git a/DRAMSys/library/src/simulation/Arbiter.cpp b/DRAMSys/library/src/simulation/Arbiter.cpp index 500f098b..a0de4bb6 100644 --- a/DRAMSys/library/src/simulation/Arbiter.cpp +++ b/DRAMSys/library/src/simulation/Arbiter.cpp @@ -54,6 +54,8 @@ Arbiter::Arbiter(sc_module_name name, std::string pathToAddressMapping) : addressDecoder = new AddressDecoder(pathToAddressMapping); addressDecoder->print(); + + bytesPerBeat = Configuration::getInstance().memSpec->dataBusWidth / 8; } ArbiterSimple::ArbiterSimple(sc_module_name name, std::string pathToAddressMapping) : @@ -126,7 +128,8 @@ void ArbiterReorder::end_of_elaboration() tlm_sync_enum Arbiter::nb_transport_fw(int id, tlm_generic_payload &payload, tlm_phase &phase, sc_time &fwDelay) { - sc_time notDelay = std::ceil((sc_time_stamp() + fwDelay) / tCK) * tCK - sc_time_stamp(); + sc_time clockOffset = (sc_time_stamp() + fwDelay) % tCK; + sc_time notDelay = (clockOffset == SC_ZERO_TIME) ? fwDelay : (fwDelay + tCK - clockOffset); if (phase == BEGIN_REQ) { @@ -140,7 +143,7 @@ tlm_sync_enum Arbiter::nb_transport_fw(int id, tlm_generic_payload &payload, Channel(decodedAddress.channel), Rank(decodedAddress.rank), BankGroup(decodedAddress.bankgroup), Bank(decodedAddress.bank), Row(decodedAddress.row), Column(decodedAddress.column), - payload.get_streaming_width(), 0, 0); + payload.get_data_length() / bytesPerBeat, 0, 0); payload.acquire(); } diff --git a/DRAMSys/library/src/simulation/Arbiter.h b/DRAMSys/library/src/simulation/Arbiter.h index d124c466..8b3f9b44 100644 --- a/DRAMSys/library/src/simulation/Arbiter.h +++ b/DRAMSys/library/src/simulation/Arbiter.h @@ -87,6 +87,8 @@ protected: sc_time tCK; sc_time arbitrationDelayFw; sc_time arbitrationDelayBw; + + unsigned bytesPerBeat; }; class ArbiterSimple final : public Arbiter diff --git a/DRAMSys/library/src/simulation/DRAMSys.cpp b/DRAMSys/library/src/simulation/DRAMSys.cpp index 1e76d1d9..395f4742 100644 --- a/DRAMSys/library/src/simulation/DRAMSys.cpp +++ b/DRAMSys/library/src/simulation/DRAMSys.cpp @@ -59,6 +59,7 @@ #include "dram/DramGDDR5.h" #include "dram/DramGDDR5X.h" #include "dram/DramGDDR6.h" +#include "dram/DramSTTMRAM.h" #include "../controller/Controller.h" DRAMSys::DRAMSys(sc_module_name name, @@ -231,6 +232,8 @@ void DRAMSys::instantiateModules(const std::string &pathToResources, dram = new DramGDDR5X(str.c_str()); else if (memoryType == MemSpec::MemoryType::GDDR6) dram = new DramGDDR6(str.c_str()); + else if (memoryType == MemSpec::MemoryType::STTMRAM) + dram = new DramSTTMRAM(str.c_str()); drams.push_back(dram); diff --git a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp index cdc0caf5..25a89d5c 100644 --- a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp +++ b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp @@ -46,6 +46,7 @@ #include "dram/DramGDDR5.h" #include "dram/DramGDDR5X.h" #include "dram/DramGDDR6.h" +#include "dram/DramSTTMRAM.h" #include "../common/TlmRecorder.h" #include "../simulation/TemperatureController.h" #include "../error/ecchamming.h" @@ -172,6 +173,8 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName, dram = new DramRecordable(str.c_str(), tlmRecorders[i]); else if (memoryType == MemSpec::MemoryType::GDDR6) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else if (memoryType == MemSpec::MemoryType::STTMRAM) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); drams.push_back(dram); diff --git a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp index 4c6701ce..5167bccf 100644 --- a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp +++ b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp @@ -49,6 +49,7 @@ #include "DramGDDR5.h" #include "DramGDDR5X.h" #include "DramGDDR6.h" +#include "DramSTTMRAM.h" using namespace tlm; @@ -156,3 +157,4 @@ template class DramRecordable; template class DramRecordable; template class DramRecordable; template class DramRecordable; +template class DramRecordable; diff --git a/DRAMSys/library/src/simulation/dram/DramSTTMRAM.cpp b/DRAMSys/library/src/simulation/dram/DramSTTMRAM.cpp new file mode 100644 index 00000000..3680ce05 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramSTTMRAM.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021, Technische Universität 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 "DramSTTMRAM.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecSTTMRAM.h" + +using namespace DRAMPower; + +DramSTTMRAM::DramSTTMRAM(sc_module_name name) : Dram(name) +{ + if (storeMode == Configuration::StoreMode::ErrorModel) + SC_REPORT_FATAL("DramSTTMRAM", "Error Model not supported for STT-MRAM"); + + if (Configuration::getInstance().powerAnalysis) + SC_REPORT_FATAL("DramSTTMRAM", "DRAMPower does not support STT-MRAM"); +} diff --git a/DRAMSys/library/src/simulation/dram/DramSTTMRAM.h b/DRAMSys/library/src/simulation/dram/DramSTTMRAM.h new file mode 100644 index 00000000..3d481be1 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramSTTMRAM.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021, Technische Universität 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 DRAMSTTMRAM_H +#define DRAMSTTMRAM_H + +#include +#include "Dram.h" + +class DramSTTMRAM : public Dram +{ +public: + DramSTTMRAM(sc_module_name); + SC_HAS_PROCESS(DramSTTMRAM); + virtual ~DramSTTMRAM() {} +}; + +#endif // DRAMSTTMRAM_H diff --git a/DRAMSys/simulator/CMakeLists.txt b/DRAMSys/simulator/CMakeLists.txt index dac282fe..a938367c 100644 --- a/DRAMSys/simulator/CMakeLists.txt +++ b/DRAMSys/simulator/CMakeLists.txt @@ -42,6 +42,8 @@ project(DRAMSysSimulator) set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ Version") set(DCMAKE_SH="CMAKE_SH-NOTFOUND") +find_package(Threads REQUIRED) + add_executable(DRAMSys main.cpp ExampleInitiator.h @@ -62,4 +64,5 @@ target_include_directories(DRAMSys target_link_libraries(DRAMSys PRIVATE DRAMSysLibrary + PRIVATE Threads::Threads ) diff --git a/DRAMSys/simulator/StlPlayer.cpp b/DRAMSys/simulator/StlPlayer.cpp index 24e4a5d6..59c917eb 100644 --- a/DRAMSys/simulator/StlPlayer.cpp +++ b/DRAMSys/simulator/StlPlayer.cpp @@ -61,7 +61,7 @@ StlPlayer::StlPlayer(const sc_module_name &name, this->maxPendingWriteRequests = maxPendingWriteRequests; this->playerClk = playerClk; - burstlength = Configuration::getInstance().memSpec->burstLength; + burstLength = Configuration::getInstance().memSpec->burstLength; dataLength = Configuration::getInstance().memSpec->bytesPerBurst; lineCnt = 0; @@ -100,23 +100,23 @@ void StlPlayer::nextPayload() payload->set_response_status(TLM_INCOMPLETE_RESPONSE); payload->set_dmi_allowed(false); payload->set_byte_enable_length(0); - payload->set_streaming_width(burstlength); + payload->set_streaming_width(burstLength); payload->set_data_length(dataLength); payload->set_command(lineIterator->cmd); std::copy(lineIterator->data.begin(), lineIterator->data.end(), payload->get_data_ptr()); - sc_time sendingOffset; sc_time sendingTime; + sc_time sendingOffset; - if (lastEndReq == sc_time_stamp()) - sendingOffset = playerClk; - else + if (transactionsSent == 0) sendingOffset = SC_ZERO_TIME; + else + sendingOffset = playerClk - (sc_time_stamp() % playerClk); if (!relative) sendingTime = std::max(sc_time_stamp() + sendingOffset, lineIterator->sendingTime); else - sendingTime = sc_time_stamp() + std::max(sendingOffset, lineIterator->sendingTime); + sendingTime = sc_time_stamp() + sendingOffset + lineIterator->sendingTime; sendToTarget(*payload, BEGIN_REQ, sendingTime - sc_time_stamp()); diff --git a/DRAMSys/simulator/StlPlayer.h b/DRAMSys/simulator/StlPlayer.h index ba48619d..31b2f4e9 100644 --- a/DRAMSys/simulator/StlPlayer.h +++ b/DRAMSys/simulator/StlPlayer.h @@ -80,7 +80,7 @@ private: std::ifstream file; uint64_t lineCnt; - unsigned int burstlength; + unsigned int burstLength; unsigned int dataLength; sc_time playerClk; // May be different from the memory clock! diff --git a/DRAMSys/simulator/TrafficGenerator.cpp b/DRAMSys/simulator/TrafficGenerator.cpp index 51c7751f..8b373f2d 100644 --- a/DRAMSys/simulator/TrafficGenerator.cpp +++ b/DRAMSys/simulator/TrafficGenerator.cpp @@ -92,10 +92,10 @@ void TrafficGenerator::nextPayload() payload->set_command(command); sc_time sendingOffset; - if (lastEndReq == sc_time_stamp()) - sendingOffset = tCK; - else + if (transactionsSent == 0) sendingOffset = SC_ZERO_TIME; + else + sendingOffset = tCK; // TODO: do not send two requests in the same cycle sendToTarget(*payload, tlm::BEGIN_REQ, sendingOffset); diff --git a/DRAMSys/simulator/TrafficInitiator.cpp b/DRAMSys/simulator/TrafficInitiator.cpp index 9b54943f..df779f72 100644 --- a/DRAMSys/simulator/TrafficInitiator.cpp +++ b/DRAMSys/simulator/TrafficInitiator.cpp @@ -74,8 +74,6 @@ void TrafficInitiator::peqCallback(tlm_generic_payload &payload, { if (phase == END_REQ) { - lastEndReq = sc_time_stamp(); - if (nextPayloadSendable()) nextPayload(); else diff --git a/DRAMSys/simulator/TrafficInitiator.h b/DRAMSys/simulator/TrafficInitiator.h index c0408385..84978da2 100644 --- a/DRAMSys/simulator/TrafficInitiator.h +++ b/DRAMSys/simulator/TrafficInitiator.h @@ -75,7 +75,7 @@ protected: unsigned int maxPendingWriteRequests = 0; bool payloadPostponed = false; bool finished = false; - sc_time lastEndReq = sc_max_time(); + sc_event transactionFinished; private: