diff --git a/DRAMSys/library/CMakeLists.txt b/DRAMSys/library/CMakeLists.txt index 5634ba6d..ba08335f 100644 --- a/DRAMSys/library/CMakeLists.txt +++ b/DRAMSys/library/CMakeLists.txt @@ -78,7 +78,6 @@ if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/src/common/third_party/sqlite-amalgamation) endif() add_library(DRAMSysLibrary - src/common/AddressDecoder.cpp src/common/DebugManager.cpp src/common/dramExtensions.cpp src/common/tlm2_base_protocol_checker.h @@ -90,6 +89,7 @@ add_library(DRAMSysLibrary src/configuration/memspec/MemSpec.cpp src/configuration/memspec/MemSpecDDR3.cpp src/configuration/memspec/MemSpecDDR4.cpp + src/configuration/memspec/MemSpecDDR5.cpp src/configuration/memspec/MemSpecLPDDR4.cpp src/configuration/memspec/MemSpecWideIO.cpp src/configuration/memspec/MemSpecWideIO2.cpp @@ -106,6 +106,7 @@ add_library(DRAMSysLibrary src/controller/checker/CheckerIF.h src/controller/checker/CheckerDDR3.cpp src/controller/checker/CheckerDDR4.cpp + src/controller/checker/CheckerDDR5.cpp src/controller/checker/CheckerLPDDR4.cpp src/controller/checker/CheckerWideIO.cpp src/controller/checker/CheckerWideIO2.cpp @@ -126,6 +127,7 @@ add_library(DRAMSysLibrary src/controller/refresh/RefreshManagerDummy.cpp src/controller/refresh/RefreshManagerRankwise.cpp src/controller/refresh/RefreshManagerBankwise.cpp + src/controller/refresh/RefreshManagerGroupwise.cpp src/controller/respqueue/RespQueueIF.h src/controller/respqueue/RespQueueFifo.cpp @@ -135,6 +137,11 @@ add_library(DRAMSysLibrary src/controller/scheduler/SchedulerFifo.cpp src/controller/scheduler/SchedulerFrFcfs.cpp src/controller/scheduler/SchedulerFrFcfsGrp.cpp + + src/controller/scheduler/BufferCounterIF.h + src/controller/scheduler/BufferCounterBankwise.cpp + src/controller/scheduler/BufferCounterReadWrite.cpp + src/controller/scheduler/BufferCounterShared.cpp src/error/eccbaseclass.cpp src/error/ecchamming.cpp @@ -145,6 +152,7 @@ add_library(DRAMSysLibrary src/error/ECC/Word.cpp src/simulation/Arbiter.cpp + src/simulation/AddressDecoder.cpp src/simulation/DRAMSys.cpp src/simulation/ReorderBuffer.h src/simulation/TemperatureController.cpp @@ -152,6 +160,7 @@ add_library(DRAMSysLibrary src/simulation/dram/Dram.cpp src/simulation/dram/DramDDR3.cpp src/simulation/dram/DramDDR4.cpp + src/simulation/dram/DramDDR5.cpp src/simulation/dram/DramLPDDR4.cpp src/simulation/dram/DramWideIO.cpp src/simulation/dram/DramWideIO2.cpp diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x4x1Gbx8_dimm_p1KB_rbc.json b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x4x1Gbx8_dimm_p1KB_rbc.json new file mode 100644 index 00000000..7e02f877 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x4x1Gbx8_dimm_p1KB_rbc.json @@ -0,0 +1,49 @@ +{ + "CONGEN": { + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11 + ], + "BANKGROUP_BIT": [ + 12, + 13, + 14 + ], + "BANK_BIT": [ + 15 + ], + "ROW_BIT": [ + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "CHANNEL_BIT": [ + 32 + ] + } +} \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json new file mode 100644 index 00000000..bce5038e --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json @@ -0,0 +1,50 @@ +{ + "CONGEN": { + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "BANKGROUP_BIT": [ + 13, + 14, + 15 + ], + "BANK_BIT": [ + 16 + ], + "ROW_BIT": [ + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ], + "CHANNEL_BIT": [ + 33 + ] + } +} \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x8x8x2Gbx4_dimm_p1KB_rbc.json b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x8x8x2Gbx4_dimm_p1KB_rbc.json new file mode 100644 index 00000000..48f1301d --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x8x8x2Gbx4_dimm_p1KB_rbc.json @@ -0,0 +1,55 @@ +{ + "CONGEN": { + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "BANKGROUP_BIT": [ + 13, + 14, + 15 + ], + "BANK_BIT": [ + 16 + ], + "ROW_BIT": [ + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ], + "RANK_BIT": [ + 33, + 34, + 35 + ], + "CHANNEL_BIT": [ + 36 + ] + } +} \ No newline at end of file diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3200A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3200A.json new file mode 100644 index 00000000..8bc5a428 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3200A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-3200A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 22, + "PPD": 2, + "RP": 22, + "RAS": 52, + "RL": 22, + "RTP": 12, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 20, + "WPRE": 2, + "WPST": 0, + "WR": 48, + "CCD_L_slr": 8, + "CCD_L_WR_slr": 16, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 8, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 16, + "WTR_S": 4, + "RFC1_slr": 312, + "RFC2_slr": 208, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 184, + "RFCsb_dlr": 0, + "REFI1": 6240, + "REFI2": 3120, + "REFISB": 1560, + "REFSBRD_slr": 48, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 8, + "PD": 12, + "XP": 12, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..639c16a9 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-3600A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-3600A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 26, + "PPD": 2, + "RP": 26, + "RAS": 58, + "RL": 26, + "RTP": 14, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 24, + "WPRE": 2, + "WPST": 0, + "WR": 54, + "CCD_L_slr": 9, + "CCD_L_WR_slr": 18, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 9, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 18, + "WTR_S": 5, + "RFC1_slr": 351, + "RFC2_slr": 234, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 207, + "RFCsb_dlr": 0, + "REFI1": 7020, + "REFI2": 3510, + "REFISB": 1755, + "REFSBRD_slr": 54, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 9, + "PD": 14, + "XP": 14, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..98d6a123 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4000A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-4000A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 28, + "PPD": 2, + "RP": 28, + "RAS": 64, + "RL": 28, + "RTP": 15, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 26, + "WPRE": 2, + "WPST": 0, + "WR": 60, + "CCD_L_slr": 10, + "CCD_L_WR_slr": 20, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 10, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 20, + "WTR_S": 5, + "RFC1_slr": 390, + "RFC2_slr": 260, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 230, + "RFCsb_dlr": 0, + "REFI1": 7800, + "REFI2": 3900, + "REFISB": 1950, + "REFSBRD_slr": 60, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 10, + "PD": 15, + "XP": 15, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..1455cecb --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4400A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-4400A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 32, + "PPD": 2, + "RP": 32, + "RAS": 71, + "RL": 32, + "RTP": 17, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 30, + "WPRE": 2, + "WPST": 0, + "WR": 66, + "CCD_L_slr": 11, + "CCD_L_WR_slr": 22, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 11, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 22, + "WTR_S": 6, + "RFC_slr": 429, + "RFC_slr": 286, + "RFC_dlr": 0, + "RFC_dlr": 0, + "RFC_dpr": 0, + "RFC_dpr": 0, + "RFCsb_slr": 253, + "RFCsb_dlr": 0, + "REFI1": 8580, + "REFI2": 4290, + "REFISB": 2145, + "REFSBRD_slr": 66, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 11, + "PD": 17, + "XP": 17, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..5fef3321 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-4800A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-4800A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 34, + "PPD": 2, + "RP": 34, + "RAS": 77, + "RL": 34, + "RTP": 18, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 32, + "WPRE": 2, + "WPST": 0, + "WR": 72, + "CCD_L_slr": 12, + "CCD_L_WR_slr": 24, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 12, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 24, + "WTR_S": 6, + "RFC1_slr": 468, + "RFC2_slr": 312, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 276, + "RFCsb_dlr": 0, + "REFI1": 9360, + "REFI2": 4680, + "REFISB": 2340, + "REFSBRD_slr": 72, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 12, + "PD": 18, + "XP": 18, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..358643b8 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5200A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-5200A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 38, + "PPD": 2, + "RP": 38, + "RAS": 84, + "RL": 38, + "RTP": 20, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 36, + "WPRE": 2, + "WPST": 0, + "WR": 78, + "CCD_L_slr": 13, + "CCD_L_WR_slr": 26, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 13, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 26, + "WTR_S": 7, + "RFC1_slr": 507, + "RFC2_slr": 338, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 299, + "RFCsb_dlr": 0, + "REFI1": 10140, + "REFI2": 5070, + "REFISB": 2535, + "REFSBRD_slr": 78, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 13, + "PD": 20, + "XP": 20, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..766c837c --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-5600A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-5600A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 40, + "PPD": 2, + "RP": 40, + "RAS": 90, + "RL": 40, + "RTP": 21, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 38, + "WPRE": 2, + "WPST": 0, + "WR": 84, + "CCD_L_slr": 14, + "CCD_L_WR_slr": 28, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 14, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 28, + "WTR_S": 7, + "RFC1_slr": 546, + "RFC2_slr": 364, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 322, + "RFCsb_dlr": 0, + "REFI1": 10920, + "REFI2": 5460, + "REFISB": 2730, + "REFSBRD_slr": 84, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 14, + "PD": 21, + "XP": 21, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..9e387dc4 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6000A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-6000A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 42, + "PPD": 2, + "RP": 42, + "RAS": 96, + "RL": 42, + "RTP": 23, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 40, + "WPRE": 2, + "WPST": 0, + "WR": 90, + "CCD_L_slr": 15, + "CCD_L_WR_slr": 30, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 15, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 30, + "WTR_S": 8, + "RFC1_slr": 585, + "RFC2_slr": 390, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 345, + "RFCsb_dlr": 0, + "REFI1": 11700, + "REFI2": 5850, + "REFISB": 2925, + "REFSBRD_slr": 90, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 15, + "PD": 23, + "XP": 23, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..18caa618 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x4x1Gbx8_DDR5-6400A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x4x1Gbx8_DDR5-6400A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 46, + "PPD": 2, + "RP": 46, + "RAS": 103, + "RL": 46, + "RTP": 24, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 44, + "WPRE": 2, + "WPST": 0, + "WR": 96, + "CCD_L_slr": 16, + "CCD_L_WR_slr": 32, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 16, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 32, + "WTR_S": 8, + "RFC1_slr": 624, + "RFC2_slr": 416, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 368, + "RFCsb_dlr": 0, + "REFI1": 12480, + "REFI2": 6240, + "REFISB": 3120, + "REFSBRD_slr": 96, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 16, + "PD": 24, + "XP": 24, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..aa6e82b0 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3200A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-3200A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 22, + "PPD": 2, + "RP": 22, + "RAS": 52, + "RL": 22, + "RTP": 12, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 20, + "WPRE": 2, + "WPST": 0, + "WR": 48, + "CCD_L_slr": 8, + "CCD_L_WR_slr": 32, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 8, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 16, + "WTR_S": 4, + "RFC1_slr": 312, + "RFC2_slr": 208, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 184, + "RFCsb_dlr": 0, + "REFI1": 6240, + "REFI2": 3120, + "REFISB": 1560, + "REFSBRD_slr": 48, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 8, + "PD": 12, + "XP": 12, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..96359874 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-3600A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-3600A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 26, + "PPD": 2, + "RP": 26, + "RAS": 58, + "RL": 26, + "RTP": 14, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 24, + "WPRE": 2, + "WPST": 0, + "WR": 54, + "CCD_L_slr": 9, + "CCD_L_WR_slr": 36, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 9, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 18, + "WTR_S": 5, + "RFC1_slr": 351, + "RFC2_slr": 234, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 207, + "RFCsb_dlr": 0, + "REFI1": 7020, + "REFI2": 3510, + "REFISB": 1755, + "REFSBRD_slr": 54, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 9, + "PD": 14, + "XP": 14, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..bf632566 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4000A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-4000A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 28, + "PPD": 2, + "RP": 28, + "RAS": 64, + "RL": 28, + "RTP": 15, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 26, + "WPRE": 2, + "WPST": 0, + "WR": 60, + "CCD_L_slr": 10, + "CCD_L_WR_slr": 40, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 10, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 20, + "WTR_S": 5, + "RFC1_slr": 390, + "RFC2_slr": 260, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 230, + "RFCsb_dlr": 0, + "REFI1": 7800, + "REFI2": 3900, + "REFISB": 1950, + "REFSBRD_slr": 60, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 10, + "PD": 15, + "XP": 15, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..a343598b --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4400A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-4400A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 32, + "PPD": 2, + "RP": 32, + "RAS": 71, + "RL": 32, + "RTP": 17, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 30, + "WPRE": 2, + "WPST": 0, + "WR": 66, + "CCD_L_slr": 11, + "CCD_L_WR_slr": 44, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 11, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 22, + "WTR_S": 6, + "RFC_slr": 429, + "RFC_slr": 286, + "RFC_dlr": 0, + "RFC_dlr": 0, + "RFC_dpr": 0, + "RFC_dpr": 0, + "RFCsb_slr": 253, + "RFCsb_dlr": 0, + "REFI1": 8580, + "REFI2": 4290, + "REFISB": 2145, + "REFSBRD_slr": 66, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 11, + "PD": 17, + "XP": 17, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..46998d40 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-4800A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-4800A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 34, + "PPD": 2, + "RP": 34, + "RAS": 77, + "RL": 34, + "RTP": 18, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 32, + "WPRE": 2, + "WPST": 0, + "WR": 72, + "CCD_L_slr": 12, + "CCD_L_WR_slr": 48, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 12, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 24, + "WTR_S": 6, + "RFC1_slr": 468, + "RFC2_slr": 312, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 276, + "RFCsb_dlr": 0, + "REFI1": 9360, + "REFI2": 4680, + "REFISB": 2340, + "REFSBRD_slr": 72, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 12, + "PD": 18, + "XP": 18, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..18e6c093 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5200A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-5200A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 38, + "PPD": 2, + "RP": 38, + "RAS": 84, + "RL": 38, + "RTP": 20, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 36, + "WPRE": 2, + "WPST": 0, + "WR": 78, + "CCD_L_slr": 13, + "CCD_L_WR_slr": 52, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 13, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 26, + "WTR_S": 7, + "RFC1_slr": 507, + "RFC2_slr": 338, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 299, + "RFCsb_dlr": 0, + "REFI1": 10140, + "REFI2": 5070, + "REFISB": 2535, + "REFSBRD_slr": 78, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 13, + "PD": 20, + "XP": 20, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..4891bb1b --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-5600A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-5600A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 40, + "PPD": 2, + "RP": 40, + "RAS": 90, + "RL": 40, + "RTP": 21, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 38, + "WPRE": 2, + "WPST": 0, + "WR": 84, + "CCD_L_slr": 14, + "CCD_L_WR_slr": 56, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 14, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 28, + "WTR_S": 7, + "RFC1_slr": 546, + "RFC2_slr": 364, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 322, + "RFCsb_dlr": 0, + "REFI1": 10920, + "REFI2": 5460, + "REFISB": 2730, + "REFSBRD_slr": 84, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 14, + "PD": 21, + "XP": 21, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..3e26408e --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6000A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-6000A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 42, + "PPD": 2, + "RP": 42, + "RAS": 96, + "RL": 42, + "RTP": 23, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 40, + "WPRE": 2, + "WPST": 0, + "WR": 90, + "CCD_L_slr": 15, + "CCD_L_WR_slr": 60, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 15, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 30, + "WTR_S": 8, + "RFC1_slr": 585, + "RFC2_slr": 390, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 345, + "RFCsb_dlr": 0, + "REFI1": 11700, + "REFI2": 5850, + "REFISB": 2925, + "REFSBRD_slr": 90, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 15, + "PD": 23, + "XP": 23, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..ca9eac9b --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x2Gbx4_DDR5-6400A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-6400A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 46, + "PPD": 2, + "RP": 46, + "RAS": 103, + "RL": 46, + "RTP": 24, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 44, + "WPRE": 2, + "WPST": 0, + "WR": 96, + "CCD_L_slr": 16, + "CCD_L_WR_slr": 64, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 16, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 32, + "WTR_S": 8, + "RFC1_slr": 624, + "RFC2_slr": 416, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 368, + "RFCsb_dlr": 0, + "REFI1": 12480, + "REFI2": 6240, + "REFISB": 3120, + "REFSBRD_slr": 96, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 16, + "PD": 24, + "XP": 24, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "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 new file mode 100644 index 00000000..315fb976 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json @@ -0,0 +1,73 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 8, + "nbrOfDIMMRanks": 2, + "nbrOfPhysicalRanks": 2, + "nbrOfLogicalRanks": 2, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevicesOnDIMM": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1 + }, + "memoryId": "JEDEC_2x8x8x8Gbx4_DDR5-3200A_4bit", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 22, + "PPD": 2, + "RP": 22, + "RAS": 52, + "RL": 22, + "RTP": 12, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 20, + "WPRE": 2, + "WPST": 0, + "WR": 48, + "CCD_L_slr": 8, + "CCD_L_WR_slr": 32, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 8, + "CCD_WR_dlr": 8, + "CCD_WR_dpr": 8, + "RRD_L_slr": 8, + "RRD_S_slr": 8, + "RRD_dlr": 4, + "FAW_slr": 32, + "FAW_dlr": 16, + "WTR_L": 16, + "WTR_S": 4, + "RFC1_slr": 312, + "RFC2_slr": 208, + "RFC1_dlr": 104, + "RFC2_dlr": 70, + "RFC1_dpr": 104, + "RFC2_dpr": 70, + "RFCsb_slr": 184, + "RFCsb_dlr": 62, + "REFI1": 6240, + "REFI2": 3120, + "REFISB": 1560, + "REFSBRD_slr": 48, + "REFSBRD_dlr": 24, + "RTRS": 2, + "CPDED": 8, + "PD": 12, + "XP": 12, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "clkMhz": 1600 + } + } +} diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.json index f993ede8..229ef834 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.json @@ -49,11 +49,13 @@ "RFC2": 150, "RFC4": 103, "RL": 13, + "RPRE": 1, "RP": 13, "RRD_L": 5, "RRD_S": 4, "RTP": 8, "WL": 12, + "WPRE": 1, "WR": 14, "WTR_L": 7, "WTR_S": 3, diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-2400_8bit_A.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-2400_8bit_A.json index 4eec52f5..f6ad7862 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-2400_8bit_A.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_4Gb_DDR4-2400_8bit_A.json @@ -49,11 +49,13 @@ "RFC2": 192, "RFC4": 132, "RL": 16, + "RPRE": 1, "RP": 16, "RRD_L": 6, "RRD_S": 4, "RTP": 12, "WL": 16, + "WPRE": 1, "WR": 18, "WTR_L": 9, "WTR_S": 3, diff --git a/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json b/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json index cb4e5e7c..159b0b73 100644 --- a/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json +++ b/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json @@ -47,11 +47,13 @@ "REFI": 3644, "RFC": 243, "RL": 13, + "RPRE": 1, "RP": 13, "RRD_L": 5, "RRD_S": 4, "RTP": 8, "WL": 12, + "WPRE": 1, "WR": 14, "WTR_L": 7, "WTR_S": 3, diff --git a/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-2400_8bit_A.json b/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-2400_8bit_A.json index 865c7b5b..4973bd10 100644 --- a/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-2400_8bit_A.json +++ b/DRAMSys/library/resources/configs/memspecs/MICRON_4Gb_DDR4-2400_8bit_A.json @@ -47,11 +47,13 @@ "REFI": 4680, "RFC": 313, "RL": 16, + "RPRE": 1, "RP": 16, "RRD_L": 6, "RRD_S": 4, "RTP": 12, "WL": 16, + "WPRE": 1, "WR": 18, "WTR_L": 9, "WTR_S": 3, diff --git a/DRAMSys/library/resources/configs/simulator/ddr5.json b/DRAMSys/library/resources/configs/simulator/ddr5.json new file mode 100644 index 00000000..d3987d37 --- /dev/null +++ b/DRAMSys/library/resources/configs/simulator/ddr5.json @@ -0,0 +1,19 @@ +{ + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "ECCControllerMode": "Disabled", + "EnableWindowing": false, + "ErrorCSVFile": "", + "ErrorChipSeed": 42, + "PowerAnalysis": false, + "SimulationName": "ddr5", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + } +} diff --git a/DRAMSys/library/resources/scripts/createTraceDB.sql b/DRAMSys/library/resources/scripts/createTraceDB.sql deleted file mode 100644 index 7a127fac..00000000 --- a/DRAMSys/library/resources/scripts/createTraceDB.sql +++ /dev/null @@ -1,94 +0,0 @@ -DROP TABLE IF EXISTS Phases; -DROP TABLE IF EXISTS GeneralInfo; -DROP TABLE IF EXISTS CommandLengths; -DROP TABLE IF EXISTS Comments; -DROP TABLE IF EXISTS ranges; -DROP TABLE IF EXISTS Transactions; -DROP TABLE IF EXISTS DebugMessages; -DROP TABLE IF EXISTS Power; - -CREATE TABLE Phases( - ID INTEGER PRIMARY KEY, - PhaseName TEXT, - PhaseBegin INTEGER, - PhaseEnd INTEGER, - Transact INTEGER -); - -CREATE TABLE GeneralInfo( - NumberOfTransactions INTEGER, - TraceEnd INTEGER, - NumberOfRanks INTEGER, - NumberOfBanks INTEGER, - clk INTEGER, - UnitOfTime TEXT, - MCconfig TEXT, - Memspec TEXT, - Traces TEXT, - WindowSize INTEGER, - FlexibleRefresh INTEGER, - MaxRefBurst INTEGER, - ControllerThread INTEGER -); - -CREATE TABLE CommandLengths( - ACT INTEGER, - PRE INTEGER, - PREA INTEGER, - RD INTEGER, - RDA INTEGER, - WR INTEGER, - WRA INTEGER, - REFA INTEGER, - REFB INTEGER, - PDEA INTEGER, - PDXA INTEGER, - PDEP INTEGER, - PDXP INTEGER, - SREFEN INTEGER, - SREFEX INTEGER -); - -CREATE TABLE Power( - time DOUBLE, - AveragePower DOUBLE -); - - -CREATE TABLE Comments( - Time INTEGER, - Text TEXT -); - -CREATE TABLE DebugMessages( - Time INTEGER, - Message TEXT -); - --- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html) -CREATE VIRTUAL TABLE ranges USING rtree( - id, - begin, end -); - -CREATE TABLE Transactions( - ID INTEGER, - Range INTEGER, - Address INTEGER, - Burstlength INTEGER, - TThread INTEGER, - TChannel INTEGER, - TRank INTEGER, - TBankgroup INTEGER, - TBank INTEGER, - TRow INTEGER, - TColumn INTEGER, - DataStrobeBegin INTEGER, - DataStrobeEnd INTEGER, - TimeOfGeneration INTEGER, - Command TEXT - ); - -CREATE INDEX ranges_index ON Transactions(Range); -CREATE INDEX "phasesTransactions" ON "Phases" ("Transact" ASC); -CREATE INDEX "messageTimes" ON "DebugMessages" ("Time" ASC); diff --git a/DRAMSys/library/resources/simulations/ddr5-example.json b/DRAMSys/library/resources/simulations/ddr5-example.json new file mode 100644 index 00000000..e85d1b92 --- /dev/null +++ b/DRAMSys/library/resources/simulations/ddr5-example.json @@ -0,0 +1,16 @@ +{ + "simulation": { + "addressmapping": "am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json", + "mcconfig": "fr_fcfs.json", + "memspec": "JEDEC_2x8x2Gbx4_DDR5-3200A.json", + "simconfig": "ddr5.json", + "simulationid": "ddr5-example", + "thermalconfig": "config.json", + "tracesetup": [ + { + "clkMhz": 2000, + "name": "ddr3_example.stl" + } + ] + } +} diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index 660fd461..51e941de 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -46,8 +46,8 @@ using namespace tlm; -TlmRecorder::TlmRecorder(std::string name, std::string uri, std::string dbname) : - name(name), sqlScriptURI(uri), dbName(dbname), +TlmRecorder::TlmRecorder(std::string name, std::string dbname) : + dbName(dbname), name(name), totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME) { recordedData.reserve(transactionCommitRate); @@ -60,7 +60,7 @@ TlmRecorder::TlmRecorder(std::string name, std::string uri, std::string dbname) sqlite3_exec(db, "PRAGMA main.synchronous=OFF", NULL, NULL, &sErrMsg); sqlite3_exec(db, "PRAGMA journal_mode = OFF", NULL, NULL, &sErrMsg); - createTables(TlmRecorder::sqlScriptURI); + executeInitialSqlCommand(); prepareSqlStatements(); PRINTDEBUGMESSAGE(name, "Starting new database transaction"); @@ -80,6 +80,8 @@ TlmRecorder::~TlmRecorder() sqlite3_finalize(insertDebugMessageStatement); sqlite3_finalize(updateDataStrobeStatement); sqlite3_finalize(insertPowerStatement); + sqlite3_finalize(insertBufferDepthStatement); + sqlite3_finalize(insertBandwidthStatement); } void TlmRecorder::recordPower(double timeInSeconds, double averagePower) @@ -89,6 +91,24 @@ void TlmRecorder::recordPower(double timeInSeconds, double averagePower) executeSqlStatement(insertPowerStatement); } +void TlmRecorder::recordBufferDepth(double timeInSeconds, const std::vector &averageBufferDepth) +{ + for (size_t index = 0; index < averageBufferDepth.size(); index++) + { + sqlite3_bind_double(insertBufferDepthStatement, 1, timeInSeconds); + sqlite3_bind_int(insertBufferDepthStatement, 2, index); + sqlite3_bind_double(insertBufferDepthStatement, 3, averageBufferDepth[index]); + executeSqlStatement(insertBufferDepthStatement); + } +} + +void TlmRecorder::recordBandwidth(double timeInSeconds, double averageBandwidth) +{ + sqlite3_bind_double(insertBandwidthStatement, 1, timeInSeconds); + sqlite3_bind_double(insertBandwidthStatement, 2, averageBandwidth); + executeSqlStatement(insertBandwidthStatement); +} + void TlmRecorder::recordPhase(tlm_generic_payload &trans, tlm_phase phase, sc_time time) { @@ -186,7 +206,11 @@ void TlmRecorder::commitRecordedDataToDB() } sc_time rangeBegin = recordingData.recordedPhases.front().interval.start; - sc_time rangeEnd = recordingData.recordedPhases.back().interval.end; + sc_time rangeEnd = rangeBegin; + for (auto &it : recordingData.recordedPhases) + { + rangeEnd = std::max(rangeEnd, it.interval.end); + } insertRangeInDB(recordingData.id, rangeBegin, rangeEnd); } @@ -232,23 +256,6 @@ void TlmRecorder::openDB(std::string name) } } -void TlmRecorder::createTables(std::string pathToURI) -{ - std::string initial; - ifstream in(pathToURI.c_str(), ios::in | ios::binary); - - if (!in) - SC_REPORT_FATAL("Error loading file", ("Could not load textfile from " + pathToURI).c_str()); - - in.seekg(0, ios::end); - initial.resize(in.tellg()); - in.seekg(0, ios::beg); - in.read(&initial[0], initial.size()); - in.close(); - - executeSqlCommand(initial); -} - void TlmRecorder::setUpTransactionTerminatingPhases() { transactionTerminatingPhases.push_back(END_RESP); @@ -261,6 +268,10 @@ void TlmRecorder::setUpTransactionTerminatingPhases() transactionTerminatingPhases.push_back(static_cast (END_REFB)); + // Refresh Same Bank + transactionTerminatingPhases.push_back(static_cast + (END_REFSB)); + // Phases for Power Down transactionTerminatingPhases.push_back(static_cast (END_PDNA)); @@ -275,86 +286,91 @@ void TlmRecorder::prepareSqlStatements() insertTransactionString = "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:rank," ":bankgroup,:bank,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)"; + insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)"; + updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id"; + updateDataStrobeString = "UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id"; insertPhaseString = "INSERT INTO Phases (PhaseName,PhaseBegin,PhaseEnd,Transact) VALUES (:name,:begin,:end,:transaction)"; + updatePhaseString = "UPDATE Phases SET PhaseEnd = :end WHERE Transact = :trans AND PhaseName = :name"; + insertGeneralInfoString = "INSERT INTO GeneralInfo VALUES" - "(:numberOfTransactions,:end,:numberOfRanks,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec," - ":traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread)"; + "(:numberOfTransactions,:end,:numberOfRanks,:numberOfBankgroups,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec," + ":traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread, :maxBufferDepth)"; + insertCommandLengthsString = "INSERT INTO CommandLengths VALUES" - "(:ACT, :PRE, :PREA, :RD, :RDA, :WR, :WRA, :REFA, :REFB, :PDEA, :PDXA, :PDEP, :PDXP, :SREFEN, :SREFEX)"; + "(:NOP, :RD, :WR, :RDA, :WRA, :ACT, :PRE, :REFB, :PRESB, :REFSB, :PREA, :REFA, :PDEA, :PDXA, :PDEP, :PDXP, :SREFEN, :SREFEX)"; + insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)"; - insertPowerString = "INSERT INTO Power VALUES (:time,:averagePower)"; - sqlite3_prepare_v2(db, insertTransactionString.c_str(), -1, - &insertTransactionStatement, 0); + insertPowerString = "INSERT INTO Power VALUES (:time,:averagePower)"; + insertBufferDepthString = "INSERT INTO BufferDepth VALUES (:time,:bufferNumber,:averageBufferDepth)"; + insertBandwidthString = "INSERT INTO Bandwidth VALUES (:time,:averageBandwidth)"; + + sqlite3_prepare_v2(db, insertTransactionString.c_str(), -1, &insertTransactionStatement, 0); sqlite3_prepare_v2(db, insertRangeString.c_str(), -1, &insertRangeStatement, 0); sqlite3_prepare_v2(db, updateRangeString.c_str(), -1, &updateRangeStatement, 0); sqlite3_prepare_v2(db, insertPhaseString.c_str(), -1, &insertPhaseStatement, 0); sqlite3_prepare_v2(db, updatePhaseString.c_str(), -1, &updatePhaseStatement, 0); - sqlite3_prepare_v2(db, updateDataStrobeString.c_str(), -1, - &updateDataStrobeStatement, 0); - sqlite3_prepare_v2(db, insertGeneralInfoString.c_str(), -1, - &insertGeneralInfoStatement, 0); - sqlite3_prepare_v2(db, insertCommandLengthsString.c_str(), -1, - &insertCommandLengthsStatement, 0); - sqlite3_prepare_v2(db, insertDebugMessageString.c_str(), -1, - &insertDebugMessageStatement, 0); + sqlite3_prepare_v2(db, updateDataStrobeString.c_str(), -1, &updateDataStrobeStatement, 0); + sqlite3_prepare_v2(db, insertGeneralInfoString.c_str(), -1, &insertGeneralInfoStatement, 0); + sqlite3_prepare_v2(db, insertCommandLengthsString.c_str(), -1, &insertCommandLengthsStatement, 0); + sqlite3_prepare_v2(db, insertDebugMessageString.c_str(), -1, &insertDebugMessageStatement, 0); sqlite3_prepare_v2(db, insertPowerString.c_str(), -1, &insertPowerStatement, 0); + sqlite3_prepare_v2(db, insertBufferDepthString.c_str(), -1, &insertBufferDepthStatement, 0); + sqlite3_prepare_v2(db, insertBandwidthString.c_str(), -1, &insertBandwidthStatement, 0); } void TlmRecorder::insertDebugMessageInDB(std::string message, const sc_time &time) { sqlite3_bind_int64(insertDebugMessageStatement, 1, time.value()); - sqlite3_bind_text(insertDebugMessageStatement, 2, message.c_str(), - message.length(), 0); + sqlite3_bind_text(insertDebugMessageStatement, 2, message.c_str(), message.length(), 0); executeSqlStatement(insertDebugMessageStatement); } void TlmRecorder::insertGeneralInfo() { sqlite3_bind_int64(insertGeneralInfoStatement, 1, totalNumTransactions - 1); - sqlite3_bind_int64(insertGeneralInfoStatement, 2, - simulationTimeCoveredByRecording.value()); - sqlite3_bind_int(insertGeneralInfoStatement, 3, - Configuration::getInstance().memSpec->numberOfRanks); - sqlite3_bind_int(insertGeneralInfoStatement, 4, - Configuration::getInstance().memSpec->numberOfBanks); - sqlite3_bind_int(insertGeneralInfoStatement, 5, - Configuration::getInstance().memSpec->tCK.value()); - sqlite3_bind_text(insertGeneralInfoStatement, 6, "PS", 2, NULL); - sqlite3_bind_text(insertGeneralInfoStatement, 7, mcconfig.c_str(), - mcconfig.length(), NULL); - sqlite3_bind_text(insertGeneralInfoStatement, 8, memspec.c_str(), - memspec.length(), NULL); - sqlite3_bind_text(insertGeneralInfoStatement, 9, traces.c_str(), - traces.length(), NULL); + sqlite3_bind_int64(insertGeneralInfoStatement, 2, simulationTimeCoveredByRecording.value()); + sqlite3_bind_int(insertGeneralInfoStatement, 3, Configuration::getInstance().memSpec->numberOfRanks); + sqlite3_bind_int(insertGeneralInfoStatement, 4, Configuration::getInstance().memSpec->numberOfBankGroups); + sqlite3_bind_int(insertGeneralInfoStatement, 5, Configuration::getInstance().memSpec->numberOfBanks); + sqlite3_bind_int(insertGeneralInfoStatement, 6, Configuration::getInstance().memSpec->tCK.value()); + sqlite3_bind_text(insertGeneralInfoStatement, 7, "PS", 2, NULL); + sqlite3_bind_text(insertGeneralInfoStatement, 8, mcconfig.c_str(), mcconfig.length(), NULL); + sqlite3_bind_text(insertGeneralInfoStatement, 9, memspec.c_str(), memspec.length(), NULL); + sqlite3_bind_text(insertGeneralInfoStatement, 10, traces.c_str(), traces.length(), NULL); if (!Configuration::getInstance().enableWindowing) - sqlite3_bind_int64(insertGeneralInfoStatement, 10, 0); + sqlite3_bind_int64(insertGeneralInfoStatement, 11, 0); else - sqlite3_bind_int64(insertGeneralInfoStatement, 10, - (Configuration::getInstance().memSpec->tCK * - Configuration::getInstance().windowSize).value()); + sqlite3_bind_int64(insertGeneralInfoStatement, 11, + (Configuration::getInstance().memSpec->tCK * + Configuration::getInstance().windowSize).value()); + if ((Configuration::getInstance().refreshMaxPostponed > 0) - || (Configuration::getInstance().refreshMaxPulledin > 0)) { - sqlite3_bind_int(insertGeneralInfoStatement, 11, 1); - sqlite3_bind_int(insertGeneralInfoStatement, 12, - std::max(Configuration::getInstance().refreshMaxPostponed, - Configuration::getInstance().refreshMaxPulledin)); - } else { - sqlite3_bind_int(insertGeneralInfoStatement, 11, 0); + || (Configuration::getInstance().refreshMaxPulledin > 0)) + { + sqlite3_bind_int(insertGeneralInfoStatement, 12, 1); + sqlite3_bind_int(insertGeneralInfoStatement, 13, + std::max(Configuration::getInstance().refreshMaxPostponed, + Configuration::getInstance().refreshMaxPulledin)); + } + else + { sqlite3_bind_int(insertGeneralInfoStatement, 12, 0); + sqlite3_bind_int(insertGeneralInfoStatement, 13, 0); } - sqlite3_bind_int(insertGeneralInfoStatement, 13, UINT_MAX); + sqlite3_bind_int(insertGeneralInfoStatement, 14, UINT_MAX); + sqlite3_bind_int(insertGeneralInfoStatement, 15, Configuration::getInstance().requestBufferSize); executeSqlStatement(insertGeneralInfoStatement); } @@ -362,21 +378,24 @@ void TlmRecorder::insertCommandLengths() { MemSpec *memSpec = Configuration::getInstance().memSpec; - sqlite3_bind_int(insertCommandLengthsStatement, 1, memSpec->getCommandLength(Command::ACT) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 2, memSpec->getCommandLength(Command::PRE) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 3, memSpec->getCommandLength(Command::PREA) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 4, memSpec->getCommandLength(Command::RD) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 5, memSpec->getCommandLength(Command::RDA) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 6, memSpec->getCommandLength(Command::WR) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 7, memSpec->getCommandLength(Command::WRA) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 8, memSpec->getCommandLength(Command::REFA) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 9, memSpec->getCommandLength(Command::REFB) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 10, memSpec->getCommandLength(Command::PDEA) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 11, memSpec->getCommandLength(Command::PDXA) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 12, memSpec->getCommandLength(Command::PDEP) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 13, memSpec->getCommandLength(Command::PDXP) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 14, memSpec->getCommandLength(Command::SREFEN) / memSpec->tCK); - sqlite3_bind_int(insertCommandLengthsStatement, 15, memSpec->getCommandLength(Command::SREFEX) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 1, memSpec->getCommandLength(Command::NOP) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 2, memSpec->getCommandLength(Command::RD) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 3, memSpec->getCommandLength(Command::WR) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 4, memSpec->getCommandLength(Command::RDA) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 5, memSpec->getCommandLength(Command::WRA) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 6, memSpec->getCommandLength(Command::ACT) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 7, memSpec->getCommandLength(Command::PRE) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 8, memSpec->getCommandLength(Command::REFB) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 9, memSpec->getCommandLength(Command::PRESB) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 10, memSpec->getCommandLength(Command::REFSB) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 11, memSpec->getCommandLength(Command::PREA) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 12, memSpec->getCommandLength(Command::REFA) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 13, memSpec->getCommandLength(Command::PDEA) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 14, memSpec->getCommandLength(Command::PDXA) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 15, memSpec->getCommandLength(Command::PDEP) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 16, memSpec->getCommandLength(Command::PDXP) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 17, memSpec->getCommandLength(Command::SREFEN) / memSpec->tCK); + sqlite3_bind_int(insertCommandLengthsStatement, 18, memSpec->getCommandLength(Command::SREFEX) / memSpec->tCK); executeSqlStatement(insertCommandLengthsStatement); } @@ -411,7 +430,6 @@ void TlmRecorder::insertTransactionInDB(Transaction &recordingData) recordingData.cmd.c_str(), recordingData.cmd.length(), NULL); executeSqlStatement(insertTransactionStatement); - } void TlmRecorder::insertRangeInDB(unsigned int id, const sc_time &begin, @@ -445,12 +463,12 @@ void TlmRecorder::executeSqlStatement(sqlite3_stmt *statement) sqlite3_reset(statement); } -void TlmRecorder::executeSqlCommand(std::string command) +void TlmRecorder::executeInitialSqlCommand() { PRINTDEBUGMESSAGE(name, "Creating database by running provided sql script"); char *errMsg = 0; - int rc = sqlite3_exec(db, command.c_str(), NULL, 0, &errMsg); + int rc = sqlite3_exec(db, initialCommand.c_str(), NULL, 0, &errMsg); if (rc != SQLITE_OK) { SC_REPORT_FATAL("SQLITE Error", errMsg); sqlite3_free(errMsg); diff --git a/DRAMSys/library/src/common/TlmRecorder.h b/DRAMSys/library/src/common/TlmRecorder.h index 67d7986b..8480b966 100644 --- a/DRAMSys/library/src/common/TlmRecorder.h +++ b/DRAMSys/library/src/common/TlmRecorder.h @@ -58,7 +58,7 @@ public: std::string sqlScriptURI; std::string dbName; - TlmRecorder(std::string name, std::string uri, std::string dbname); + TlmRecorder(std::string name, std::string dbname); ~TlmRecorder(); void recordMCconfig(std::string mcconfig) @@ -77,13 +77,16 @@ public: void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time); void recordPower(double timeInSeconds, double averagePower); + void recordBufferDepth(double timeInSeconds, const std::vector &averageBufferDepth); + void recordBandwidth(double timeInSeconds, double averageBandwidth); void recordDebugMessage(std::string message, sc_time time); void updateDataStrobe(const sc_time &begin, const sc_time &end, tlm::tlm_generic_payload &trans); void closeConnection(); private: - struct Transaction { + struct Transaction + { Transaction() {} Transaction(unsigned int id): id(id) {} @@ -95,7 +98,8 @@ private: sc_time timeOfGeneration; TimeInterval timeOnDataStrobe; - struct Phase { + struct Phase + { Phase(std::string name, sc_time begin): name(name), interval(begin, SC_ZERO_TIME) {} std::string name; TimeInterval interval; @@ -111,11 +115,10 @@ private: std::string mcconfig, memspec, traces; void prepareSqlStatements(); - void executeSqlCommand(std::string command); + void executeInitialSqlCommand(); void executeSqlStatement(sqlite3_stmt *statement); void openDB(std::string name); - void createTables(std::string pathToURI); void setUpTransactionTerminatingPhases(); void introduceTransactionSystem(tlm::tlm_generic_payload &trans); @@ -142,10 +145,125 @@ private: sqlite3_stmt *insertTransactionStatement, *insertRangeStatement, *updateRangeStatement, *insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertCommandLengthsStatement, - *insertDebugMessageStatement, *updateDataStrobeStatement, *insertPowerStatement; + *insertDebugMessageStatement, *updateDataStrobeStatement, + *insertPowerStatement, *insertBufferDepthStatement, *insertBandwidthStatement; std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, updatePhaseString, insertGeneralInfoString, insertCommandLengthsString, - insertDebugMessageString, updateDataStrobeString, insertPowerString; + insertDebugMessageString, updateDataStrobeString, insertPowerString, + insertBufferDepthString, insertBandwidthString; + + std::string initialCommand = + "DROP TABLE IF EXISTS Phases; \n" + "DROP TABLE IF EXISTS GeneralInfo; \n" + "DROP TABLE IF EXISTS CommandLengths; \n" + "DROP TABLE IF EXISTS Comments; \n" + "DROP TABLE IF EXISTS ranges; \n" + "DROP TABLE IF EXISTS Transactions; \n" + "DROP TABLE IF EXISTS DebugMessages; \n" + "DROP TABLE IF EXISTS Power; \n" + "DROP TABLE IF EXISTS BufferDepth; \n" + "DROP TABLE IF EXISTS Bandwidth; \n" + " \n" + "CREATE TABLE Phases( \n" + " ID INTEGER PRIMARY KEY, \n" + " PhaseName TEXT, \n" + " PhaseBegin INTEGER, \n" + " PhaseEnd INTEGER, \n" + " Transact INTEGER \n" + "); \n" + " \n" + "CREATE TABLE GeneralInfo( \n" + " NumberOfTransactions INTEGER, \n" + " TraceEnd INTEGER, \n" + " NumberOfRanks INTEGER, \n" + " NumberOfBankgroups INTEGER, \n" + " NumberOfBanks INTEGER, \n" + " clk INTEGER, \n" + " UnitOfTime TEXT, \n" + " MCconfig TEXT, \n" + " Memspec TEXT, \n" + " Traces TEXT, \n" + " WindowSize INTEGER, \n" + " FlexibleRefresh INTEGER, \n" + " MaxRefBurst INTEGER, \n" + " ControllerThread INTEGER, \n" + " MaxBufferDepth INTEGER \n" + "); \n" + " \n" + "CREATE TABLE CommandLengths( \n" + " NOP INTEGER, \n" + " RD INTEGER, \n" + " WR INTEGER, \n" + " RDA INTEGER, \n" + " WRA INTEGER, \n" + " ACT INTEGER, \n" + " PRE INTEGER, \n" + " REFB INTEGER, \n" + " PRESB INTEGER, \n" + " REFSB INTEGER, \n" + " PREA INTEGER, \n" + " REFA INTEGER, \n" + " PDEA INTEGER, \n" + " PDXA INTEGER, \n" + " PDEP INTEGER, \n" + " PDXP INTEGER, \n" + " SREFEN INTEGER, \n" + " SREFEX INTEGER \n" + "); \n" + " \n" + "CREATE TABLE Power( \n" + " time DOUBLE, \n" + " AveragePower DOUBLE \n" + "); \n" + " \n" + "CREATE TABLE BufferDepth( \n" + " Time DOUBLE, \n" + " BufferNumber INTEGER, \n" + " AverageBufferDepth DOUBLE \n" + "); \n" + " \n" + "CREATE TABLE Bandwidth( \n" + " Time DOUBLE, \n" + " AverageBandwidth DOUBLE \n" + "); \n" + " \n" + "CREATE TABLE Comments( \n" + " Time INTEGER, \n" + " Text TEXT \n" + "); \n" + " \n" + "CREATE TABLE DebugMessages( \n" + " Time INTEGER, \n" + " Message TEXT \n" + "); \n" + " \n" + "-- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html)\n" + "CREATE VIRTUAL TABLE ranges USING rtree( \n" + " id, \n" + " begin, end \n" + "); \n" + " \n" + "CREATE TABLE Transactions( \n" + " ID INTEGER, \n" + " Range INTEGER, \n" + " Address INTEGER, \n" + " Burstlength INTEGER, \n" + " TThread INTEGER, \n" + " TChannel INTEGER, \n" + " TRank INTEGER, \n" + " TBankgroup INTEGER, \n" + " TBank INTEGER, \n" + " TRow INTEGER, \n" + " TColumn INTEGER, \n" + " DataStrobeBegin INTEGER, \n" + " DataStrobeEnd INTEGER, \n" + " TimeOfGeneration INTEGER, \n" + " Command TEXT \n" + "); \n" + " \n" + "CREATE INDEX ranges_index ON Transactions(Range); \n" + "CREATE INDEX \"phasesTransactions\" ON \"Phases\" (\"Transact\" ASC); \n" + "CREATE INDEX \"messageTimes\" ON \"DebugMessages\" (\"Time\" ASC); \n"; }; #endif // TLMRECORDER_H diff --git a/DRAMSys/library/src/common/dramExtensions.cpp b/DRAMSys/library/src/common/dramExtensions.cpp index 93a9bbad..09a49be9 100644 --- a/DRAMSys/library/src/common/dramExtensions.cpp +++ b/DRAMSys/library/src/common/dramExtensions.cpp @@ -44,24 +44,22 @@ using namespace tlm; DramExtension::DramExtension() : thread(0), channel(0), rank(0), bankgroup(0), bank(0), - row(0), column(0), burstlength(0), payloadID(0) {} - -DramExtension::DramExtension(Thread thread, Rank rank, BankGroup bankgroup, - Bank bank, Row row, Column column, - unsigned int burstlength, uint64_t payloadID) : - thread(thread), channel(0), rank(rank), bankgroup(bankgroup), bank(bank), - row(row), column(column), burstlength(burstlength), payloadID(payloadID) {} + 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, uint64_t payloadID) : + 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), payloadID(payloadID) {} + 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, uint64_t payloadID) + Column column, unsigned int burstlength, + uint64_t threadPayloadID, uint64_t channelPayloadID) { DramExtension *extension = nullptr; payload->get_extension(extension); @@ -76,12 +74,14 @@ void DramExtension::setExtension(tlm::tlm_generic_payload *payload, extension->row = row; extension->column = column; extension->burstlength = burstlength; - extension->payloadID = payloadID; + extension->threadPayloadID = threadPayloadID; + extension->channelPayloadID = channelPayloadID; } else { extension = new DramExtension(thread, channel, rank, bankgroup, - bank, row, column, burstlength, payloadID); + bank, row, column, burstlength, + threadPayloadID, channelPayloadID); payload->set_auto_extension(extension); } } @@ -89,10 +89,25 @@ 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, uint64_t payloadID) + Column column, unsigned int burstlength, + uint64_t threadPayloadID, uint64_t channelPayloadID) { setExtension(&payload, thread, channel, rank, bankgroup, - bank, row, column, burstlength, payloadID); + bank, row, column, burstlength, + threadPayloadID, channelPayloadID); +} + +void DramExtension::setPayloadIDs(tlm::tlm_generic_payload *payload, uint64_t threadPayloadID, uint64_t channelPayloadID) +{ + DramExtension *extension; + payload->get_extension(extension); + extension->threadPayloadID = threadPayloadID; + extension->channelPayloadID = channelPayloadID; +} + +void DramExtension::setPayloadIDs(tlm::tlm_generic_payload &payload, uint64_t threadPayloadID, uint64_t channelPayloadID) +{ + DramExtension::setPayloadIDs(&payload, threadPayloadID, channelPayloadID); } DramExtension &DramExtension::getExtension(const tlm_generic_payload *payload) @@ -179,19 +194,30 @@ Column DramExtension::getColumn(const tlm_generic_payload &payload) return DramExtension::getColumn(&payload); } -uint64_t DramExtension::getPayloadID(const tlm_generic_payload *payload) +uint64_t DramExtension::getThreadPayloadID(const tlm_generic_payload *payload) { - return DramExtension::getExtension(payload).getPayloadID(); + return DramExtension::getExtension(payload).getThreadPayloadID(); } -uint64_t DramExtension::getPayloadID(const tlm_generic_payload &payload) +uint64_t DramExtension::getThreadPayloadID(const tlm_generic_payload &payload) { - return DramExtension::getPayloadID(&payload); + return DramExtension::getThreadPayloadID(&payload); +} + +uint64_t DramExtension::getChannelPayloadID(const tlm_generic_payload *payload) +{ + return DramExtension::getExtension(payload).getChannelPayloadID(); +} + +uint64_t DramExtension::getChannelPayloadID(const tlm_generic_payload &payload) +{ + return DramExtension::getChannelPayloadID(&payload); } tlm_extension_base *DramExtension::clone() const { - return new DramExtension(thread, channel, rank, bankgroup, bank, row, column, burstlength, payloadID); + return new DramExtension(thread, channel, rank, bankgroup, bank, row, column, + burstlength, threadPayloadID, channelPayloadID); } void DramExtension::copy_from(const tlm_extension_base &ext) @@ -247,9 +273,14 @@ unsigned int DramExtension::getBurstlength() const return burstlength; } -uint64_t DramExtension::getPayloadID() const +uint64_t DramExtension::getThreadPayloadID() const { - return payloadID; + return threadPayloadID; +} + +uint64_t DramExtension::getChannelPayloadID() const +{ + return channelPayloadID; } void DramExtension::incrementRow() diff --git a/DRAMSys/library/src/common/dramExtensions.h b/DRAMSys/library/src/common/dramExtensions.h index 1c33454d..989bb079 100644 --- a/DRAMSys/library/src/common/dramExtensions.h +++ b/DRAMSys/library/src/common/dramExtensions.h @@ -163,12 +163,10 @@ class DramExtension : public tlm::tlm_extension { public: DramExtension(); - DramExtension(Thread thread, Rank rank, BankGroup bankgroup, - Bank bank, Row row, Column column, - unsigned int burstlength, uint64_t payloadID); DramExtension(Thread thread, Channel channel, Rank rank, BankGroup bankgroup, Bank bank, Row row, - Column column, unsigned int burstlength, uint64_t payloadID); + Column column, unsigned int burstlength, + uint64_t threadPayloadID, uint64_t channelPayloadID); virtual tlm::tlm_extension_base *clone() const; virtual void copy_from(const tlm::tlm_extension_base &ext); @@ -176,15 +174,22 @@ 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, uint64_t payloadID); + 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, uint64_t payloadID); + Column column, unsigned int burstlength, + uint64_t threadPayloadID, uint64_t channelPayloadID); static DramExtension &getExtension(const tlm::tlm_generic_payload *payload); static DramExtension &getExtension(const tlm::tlm_generic_payload &payload); + static void setPayloadIDs(tlm::tlm_generic_payload *payload, + uint64_t threadPayloadID, uint64_t channelPayloadID); + static void setPayloadIDs(tlm::tlm_generic_payload &payload, + uint64_t threadPayloadID, uint64_t channelPayloadID); + // Used for convience, caller could also use getExtension(..) to access these field static Thread getThread(const tlm::tlm_generic_payload *payload); static Thread getThread(const tlm::tlm_generic_payload &payload); @@ -200,8 +205,10 @@ 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 uint64_t getPayloadID(const tlm::tlm_generic_payload *payload); - static uint64_t getPayloadID(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); + static uint64_t getChannelPayloadID(const tlm::tlm_generic_payload &payload); Thread getThread() const; Channel getChannel() const; @@ -212,7 +219,8 @@ public: Column getColumn() const; unsigned int getBurstlength() const; - uint64_t getPayloadID() const; + uint64_t getThreadPayloadID() const; + uint64_t getChannelPayloadID() const; void incrementRow(); private: @@ -224,7 +232,8 @@ private: Row row; Column column; unsigned int burstlength; - uint64_t payloadID; + uint64_t threadPayloadID; + uint64_t channelPayloadID; }; diff --git a/DRAMSys/library/src/common/utils.cpp b/DRAMSys/library/src/common/utils.cpp index 76237841..75ceda79 100644 --- a/DRAMSys/library/src/common/utils.cpp +++ b/DRAMSys/library/src/common/utils.cpp @@ -74,18 +74,17 @@ std::string getPhaseName(tlm_phase phase) json parseJSON(std::string path) { - try + std::ifstream file(path); + if (file.is_open()) { - // parsing input with a syntax error - json j = json::parse(std::ifstream(path)); - return j; - } - catch (json::parse_error& e) - { - // output exception information - std::cout << "Error while trying to parse file: " << path << '\n' - << "message: " << e.what() << std::endl; + json j = json::parse(file, nullptr, false); + if (!j.is_discarded()) + return j; + else + throw std::invalid_argument("JSON parse error in file '" + path + "'."); } + else + throw std::invalid_argument("Failed to open file '" + path + "'."); } bool parseBool(json &obj, std::string name) @@ -95,10 +94,10 @@ bool parseBool(json &obj, std::string name) if (obj.is_boolean()) return obj; else - throw std::invalid_argument("Expected type for '" + name + "': bool"); + throw std::invalid_argument("Expected type for parameter '" + name + "': bool"); } else - SC_REPORT_FATAL("Query json", ("Parameter '" + name + "' does not exist.").c_str()); + throw std::invalid_argument("Parameter '" + name + "' does not exist."); } unsigned int parseUint(json &obj, std::string name) @@ -108,10 +107,10 @@ unsigned int parseUint(json &obj, std::string name) if (obj.is_number_unsigned()) return obj; else - throw std::invalid_argument("Expected type for '" + name + "': unsigned int"); + throw std::invalid_argument("Expected type for parameter '" + name + "': unsigned int"); } else - SC_REPORT_FATAL("Query json", ("Parameter '" + name + "' does not exist.").c_str()); + throw std::invalid_argument("Parameter '" + name + "' does not exist."); } double parseUdouble(json &obj, std::string name) @@ -121,10 +120,10 @@ double parseUdouble(json &obj, std::string name) if (obj.is_number() && (obj > 0)) return obj; else - throw std::invalid_argument("Expected type for '" + name + "': positive double"); + throw std::invalid_argument("Expected type for parameter '" + name + "': positive double"); } else - SC_REPORT_FATAL("Query json", ("Parameter '" + name + "' does not exist.").c_str()); + throw std::invalid_argument("Parameter '" + name + "' does not exist."); } std::string parseString(json &obj, std::string name) @@ -134,13 +133,13 @@ std::string parseString(json &obj, std::string name) if (obj.is_string()) return obj; else - throw std::invalid_argument("Expected type for '" + name + "': string"); + throw std::invalid_argument("Expected type for parameter '" + name + "': string"); } else - SC_REPORT_FATAL("Query json", ("Parameter '" + name + "' does not exist.").c_str()); + throw std::invalid_argument("Parameter '" + name + "' does not exist."); } -void setUpDummy(tlm_generic_payload &payload, uint64_t payloadID, Rank rank, BankGroup bankgroup, Bank bank) +void setUpDummy(tlm_generic_payload &payload, uint64_t channelPayloadID, Rank rank, BankGroup bankgroup, Bank bank) { payload.set_address(bank.getStartAddress()); payload.set_command(TLM_READ_COMMAND); @@ -149,6 +148,6 @@ void setUpDummy(tlm_generic_payload &payload, uint64_t payloadID, Rank rank, Ban payload.set_dmi_allowed(false); payload.set_byte_enable_length(0); payload.set_streaming_width(0); - payload.set_extension(new DramExtension(Thread(UINT_MAX), rank, bankgroup, - bank, Row(0), Column(0), 0, payloadID)); + payload.set_extension(new DramExtension(Thread(UINT_MAX), Channel(0), rank, bankgroup, + bank, Row(0), Column(0), 0, 0, channelPayloadID)); } diff --git a/DRAMSys/library/src/common/utils.h b/DRAMSys/library/src/common/utils.h index 6a073c81..e29a430d 100644 --- a/DRAMSys/library/src/common/utils.h +++ b/DRAMSys/library/src/common/utils.h @@ -65,43 +65,6 @@ public: constexpr const char headline[] = "==========================================================================="; -static inline void loadbar(unsigned int x, - unsigned int n, - unsigned int w = 50, - unsigned int granularity = 1) -{ - if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0))) - return; - - float ratio = x / (float) n; - unsigned int c = (ratio * w); - float rest = (ratio * w) - c; - std::cout << std::setw(3) << round(ratio * 100) << "% |"; - for (unsigned int x = 0; x < c; x++) - std::cout << "█"; - - if (rest >= 0 && rest < 0.125 && c != w) - std::cout << " "; - if (rest >= 0.125 && rest < 2 * 0.125) - std::cout << "▏"; - if (rest >= 2 * 0.125 && rest < 3 * 0.125) - std::cout << "▎"; - if (rest >= 3 * 0.125 && rest < 4 * 0.125) - std::cout << "▍"; - if (rest >= 4 * 0.125 && rest < 5 * 0.125) - std::cout << "▌"; - if (rest >= 5 * 0.125 && rest < 6 * 0.125) - std::cout << "▋"; - if (rest >= 6 * 0.125 && rest < 7 * 0.125) - std::cout << "▊"; - if (rest >= 7 * 0.125 && rest < 8 * 0.125) - std::cout << "▉"; - - for (unsigned int x = c; x < (w - 1); x++) - std::cout << " "; - std::cout << "|\r" << std::flush; -} - std::string getPhaseName(tlm::tlm_phase phase); nlohmann::json parseJSON(std::string path); @@ -110,7 +73,8 @@ unsigned int parseUint(nlohmann::json &obj, std::string name); double parseUdouble(nlohmann::json &obj, std::string name); std::string parseString(nlohmann::json &obj, std::string name); -void setUpDummy(tlm::tlm_generic_payload &payload, uint64_t payloadID, Rank rank = Rank(0), BankGroup bankgroup = BankGroup(0), Bank bank = Bank(0)); +void setUpDummy(tlm::tlm_generic_payload &payload, uint64_t channelPayloadID, + Rank rank = Rank(0), BankGroup bankgroup = BankGroup(0), Bank bank = Bank(0)); #endif // UTILS_H diff --git a/DRAMSys/library/src/configuration/Configuration.cpp b/DRAMSys/library/src/configuration/Configuration.cpp index 4a0b9645..04c03378 100644 --- a/DRAMSys/library/src/configuration/Configuration.cpp +++ b/DRAMSys/library/src/configuration/Configuration.cpp @@ -43,6 +43,7 @@ #include "Configuration.h" #include "memspec/MemSpecDDR3.h" #include "memspec/MemSpecDDR4.h" +#include "memspec/MemSpecDDR5.h" #include "memspec/MemSpecWideIO.h" #include "memspec/MemSpecLPDDR4.h" #include "memspec/MemSpecWideIO2.h" @@ -81,25 +82,105 @@ void Configuration::setParameter(std::string name, nlohmann::json value) { // MCConfig if (name == "PagePolicy") - pagePolicy = value; + { + if (value == "Open") + pagePolicy = PagePolicy::Open; + else if (value == "Closed") + pagePolicy = PagePolicy::Closed; + else if (value == "OpenAdaptive") + pagePolicy = PagePolicy::OpenAdaptive; + else if (value == "ClosedAdaptive") + pagePolicy = PagePolicy::ClosedAdaptive; + else + SC_REPORT_FATAL("Configuration", "Unsupported page policy!"); + } else if (name == "Scheduler") - scheduler = value; + { + if (value == "Fifo") + scheduler = Scheduler::Fifo; + else if (value == "FrFcfs") + scheduler = Scheduler::FrFcfs; + else if (value == "FrFcfsGrp") + scheduler = Scheduler::FrFcfsGrp; + else + SC_REPORT_FATAL("Configuration", "Unsupported scheduler!"); + } + else if (name == "SchedulerBuffer") + { + if (value == "Bankwise") + schedulerBuffer = SchedulerBuffer::Bankwise; + else if (value == "ReadWrite") + schedulerBuffer = SchedulerBuffer::ReadWrite; + else if (value == "Shared") + schedulerBuffer = SchedulerBuffer::Shared; + else + SC_REPORT_FATAL("Configuration", "Unsupported scheduler buffer!"); + } else if (name == "RequestBufferSize") + { requestBufferSize = value; + if (requestBufferSize == 0) + SC_REPORT_FATAL("Configuration", "Minimum request buffer size is 1!"); + } else if (name == "CmdMux") - cmdMux = value; + { + if (value == "Oldest") + cmdMux = CmdMux::Oldest; + else if (value == "Strict") + cmdMux = CmdMux::Strict; + else + SC_REPORT_FATAL("Configuration", "Unsupported cmd mux!"); + } else if (name == "RespQueue") - respQueue = value; + { + if (value == "Fifo") + respQueue = RespQueue::Fifo; + else if (value == "Reorder") + respQueue = RespQueue::Reorder; + else + SC_REPORT_FATAL("Configuration", "Unsupported response queue!"); + } + else if (name == "Arbiter") + { + if (value == "Simple") + arbiter = Arbiter::Simple; + else if (value == "Fifo") + arbiter = Arbiter::Fifo; + else if (value == "Reorder") + arbiter = Arbiter::Reorder; + else + SC_REPORT_FATAL("Configuration", "Unsupported arbiter!"); + } else if (name == "RefreshPolicy") - refreshPolicy = value; + { + if (value == "NoRefresh") + refreshPolicy = RefreshPolicy::NoRefresh; + else if (value == "Rankwise") + refreshPolicy = RefreshPolicy::Rankwise; + else if (value == "Bankwise") + refreshPolicy = RefreshPolicy::Bankwise; + else if (value == "Groupwise") + refreshPolicy = RefreshPolicy::Groupwise; + else + SC_REPORT_FATAL("Configuration", "Unsupported refresh policy!"); + } else if (name == "RefreshMaxPostponed") refreshMaxPostponed = value; else if (name == "RefreshMaxPulledin") refreshMaxPulledin = value; else if (name == "PowerDownPolicy") - powerDownPolicy = value; + { + if (value == "NoPowerDown") + powerDownPolicy = PowerDownPolicy::NoPowerDown; + else if (value == "Staggered") + powerDownPolicy = PowerDownPolicy::Staggered; + else + SC_REPORT_FATAL("Configuration", "Unsupported power down policy!"); + } else if (name == "PowerDownTimeout") powerDownTimeout = value; + else if (name == "MaxActiveTransactions") + maxActiveTransactions = value; //SimConfig------------------------------------------------ else if (name == "SimulationName") simulationName = value; @@ -113,9 +194,7 @@ void Configuration::setParameter(std::string name, nlohmann::json value) { windowSize = value; if (windowSize == 0) - SC_REPORT_FATAL("Configuration", - ("Invalid value for parameter " + name + - ". This parameter must be at least one.").c_str()); + SC_REPORT_FATAL("Configuration", "Minimum window size is 1"); } else if (name == "Debug") debug = value; @@ -124,26 +203,37 @@ void Configuration::setParameter(std::string name, nlohmann::json value) else if (name == "SimulationProgressBar") simulationProgressBar = value; else if (name == "AddressOffset") - { -#ifdef DRAMSYS_GEM5 addressOffset = value; -#else - addressOffset = 0; -#endif - } else if (name == "UseMalloc") useMalloc = value; else if (name == "CheckTLM2Protocol") checkTLM2Protocol = value; else if (name == "ECCControllerMode") - ECCMode = value; + { + if (value == "Disabled") + eccMode = ECCMode::Disabled; + else if (value == "Hamming") + eccMode = ECCMode::Hamming; + else + SC_REPORT_FATAL("Configuration", "Unsupported ECC mode!"); + } // Specification for ErrorChipSeed, ErrorCSVFile path and StoreMode else if (name == "ErrorChipSeed") errorChipSeed = value; else if (name == "ErrorCSVFile") errorCSVFile = value; else if (name == "StoreMode") - storeMode = value; + { + if (value == "NoStorage") + storeMode = StoreMode::NoStorage; + else if (value == "Store") + storeMode = StoreMode::Store; + else if (value == "ErrorModel") + storeMode = StoreMode::ErrorModel; + else + SC_REPORT_FATAL("Configuration", "Unsupported store mode!"); + } + // Temperature Simulation related else if (name == "TemperatureScale") { @@ -186,80 +276,24 @@ void Configuration::setPathToResources(std::string path) temperatureSim.setPathToResources(path); } -// Returns the total memory size in bytes -std::uint64_t Configuration::getSimMemSizeInBytes() -{ - // 1. Get number of banks, rows, columns and data width in bits for one die (or chip) - std::string type = memSpec->memoryType; - std::uint64_t ranks = memSpec->numberOfRanks; - std::uint64_t bankgroups = memSpec->numberOfBankGroups; - std::uint64_t banks = memSpec->numberOfBanks; - std::uint64_t rows = memSpec->numberOfRows; - std::uint64_t columns = memSpec->numberOfColumns; - std::uint64_t bitWidth = memSpec->bitWidth; - std::uint64_t devicesOnDIMM = memSpec->numberOfDevicesOnDIMM; - // 2. Calculate size of one DRAM chip in bits - std::uint64_t chipBitSize = banks * rows * columns * bitWidth; - // 3. Calculate size of one DRAM chip in bytes - std::uint64_t chipSize = chipBitSize / 8; - // 4. Total memory size in Bytes of one DIMM (with only support of 1 rank on a DIMM) - std::uint64_t memorySize = chipSize * memSpec->numberOfDevicesOnDIMM; - - std::cout << headline << std::endl; - std::cout << "Per Channel Configuration:" << std::endl << std::endl; - std::cout << " Memory type: " << type << std::endl; - std::cout << " Memory size in bytes: " << memorySize << std::endl; - std::cout << " Number of ranks: " << ranks << std::endl; - std::cout << " Number of bankgroups: " << bankgroups << std::endl; - std::cout << " Number of banks: " << banks << std::endl; - std::cout << " Number of rows: " << rows << std::endl; - std::cout << " Number of columns: " << columns << std::endl; - std::cout << " Chip data bus width: " << bitWidth << std::endl; - std::cout << " Chip size in bits: " << chipBitSize << std::endl; - std::cout << " Chip Size in bytes: " << chipSize << std::endl; - std::cout << " Devices/Chips on DIMM: " << devicesOnDIMM << std::endl; - std::cout << std::endl; - - assert(memorySize > 0); - return memorySize; -} - -// Returns the width of the data bus. -// All DRAM chips on a DIMM operate in lockstep, -// which constituing aggregate data bus width = chip's bus width * # locksteep-operated chips -// The bus width is given in bits, e.g., 64-bit data bus, 128-bit data bus, etc. -unsigned int Configuration::getDataBusWidth() -{ - return memSpec->bitWidth * memSpec->numberOfDevicesOnDIMM; -} - -// Returns the number of bytes transfered in a burst -unsigned int Configuration::getBytesPerBurst() -{ - return (memSpec->burstLength * getDataBusWidth()) / 8; -} - // Changes the number of bytes depeding on the ECC Controller. This function is needed for modules which get data directly or indirectly from the ECC Controller unsigned int Configuration::adjustNumBytesAfterECC(unsigned nBytes) { // Manipulate the number of bytes only if there is an ECC Controller selected - if (ECCMode == "Disabled") + if (eccMode == ECCMode::Disabled) return nBytes; - else if (ECCMode == "Hamming") + else // if (eccMode == ECCMode::Hamming) { assert(pECC != nullptr); return pECC->AllocationSize(nBytes); } - else - { - SC_REPORT_FATAL("Configuration", ("ECC mode " + ECCMode + " unsupported").c_str()); - return 0; - } } void Configuration::loadSimConfig(Configuration &config, std::string simconfigUri) { json doc = parseJSON(simconfigUri); + if (doc["simconfig"].empty()) + SC_REPORT_FATAL("Configuration", "simconfig is empty."); for (auto& x : doc["simconfig"].items()) config.setParameter(x.key(), x.value()); } @@ -267,6 +301,8 @@ void Configuration::loadSimConfig(Configuration &config, std::string simconfigUr void Configuration::loadTemperatureSimConfig(Configuration &config, std::string thermalsimconfigUri) { json doc = parseJSON(thermalsimconfigUri); + if (doc["thermalsimconfig"].empty()) + SC_REPORT_FATAL("Configuration", "thermalsimconfig is empty."); for (auto& x : doc["thermalsimconfig"].items()) config.setParameter(x.key(), x.value()); } @@ -275,6 +311,8 @@ void Configuration::loadMCConfig(Configuration &config, std::string mcconfigUri) { config.mcconfigUri = mcconfigUri; json doc = parseJSON(mcconfigUri); + if (doc["mcconfig"].empty()) + SC_REPORT_FATAL("Configuration", "mcconfig is empty."); for (auto& x : doc["mcconfig"].items()) config.setParameter(x.key(), x.value()); } @@ -291,6 +329,8 @@ void Configuration::loadMemSpec(Configuration &config, std::string memspecUri) memSpec = new MemSpecDDR3(jMemSpec); else if (memoryType == "DDR4") memSpec = new MemSpecDDR4(jMemSpec); + else if (memoryType == "DDR5") + memSpec = new MemSpecDDR5(jMemSpec); else if (memoryType == "LPDDR4") memSpec = new MemSpecLPDDR4(jMemSpec); else if (memoryType == "WIDEIO_SDR") diff --git a/DRAMSys/library/src/configuration/Configuration.h b/DRAMSys/library/src/configuration/Configuration.h index 75176ae5..71c578f0 100644 --- a/DRAMSys/library/src/configuration/Configuration.h +++ b/DRAMSys/library/src/configuration/Configuration.h @@ -69,16 +69,19 @@ public: std::string pathToResources; // MCConfig: - std::string pagePolicy = "Open"; - std::string scheduler = "Fifo"; - std::string cmdMux = "Oldest"; - std::string respQueue = "Fifo"; + enum class PagePolicy {Open, Closed, OpenAdaptive, ClosedAdaptive} pagePolicy; + enum class Scheduler {Fifo, FrFcfs, FrFcfsGrp} scheduler; + enum class SchedulerBuffer {Bankwise, ReadWrite, Shared} schedulerBuffer; + enum class CmdMux {Oldest, Strict} cmdMux; + enum class RespQueue {Fifo, Reorder} respQueue; + enum class Arbiter {Simple, Fifo, Reorder} arbiter; unsigned int requestBufferSize = 8; - std::string refreshPolicy = "Rankwise"; + enum class RefreshPolicy {NoRefresh, Rankwise, Bankwise, Groupwise} refreshPolicy; unsigned int refreshMaxPostponed = 0; unsigned int refreshMaxPulledin = 0; - std::string powerDownPolicy = "NoPowerDown"; + enum class PowerDownPolicy {NoPowerDown, Staggered} powerDownPolicy; unsigned int powerDownTimeout = 3; + unsigned int maxActiveTransactions = 64; // SimConfig std::string simulationName = "default"; @@ -90,7 +93,7 @@ public: bool thermalSimulation = false; bool simulationProgressBar = false; bool checkTLM2Protocol = false; - std::string ECCMode = "Disabled"; + enum class ECCMode {Disabled, Hamming} eccMode; ECCBaseClass *pECC = nullptr; bool gem5 = false; bool useMalloc = false; @@ -104,14 +107,11 @@ public: //Configs for Seed, csv file and StorageMode unsigned int errorChipSeed; std::string errorCSVFile = "not defined."; - std::string storeMode; + enum class StoreMode {NoStorage, Store, ErrorModel} storeMode; // Temperature Simulation related TemperatureSimConfig temperatureSim; - std::uint64_t getSimMemSizeInBytes(); - unsigned int getDataBusWidth(); - unsigned int getBytesPerBurst(); unsigned int adjustNumBytesAfterECC(unsigned bytes); void setPathToResources(std::string path); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.cpp b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp index 39fd1211..c3a73127 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp @@ -43,7 +43,8 @@ using namespace tlm; using json = nlohmann::json; -MemSpec::MemSpec(json &memspec, unsigned numberOfChannels, +MemSpec::MemSpec(json &memspec, MemoryType memoryType, + unsigned numberOfChannels, unsigned numberOfRanks, unsigned banksPerRank, unsigned groupsPerRank, unsigned banksPerGroup, unsigned numberOfBanks, unsigned numberOfBankGroups, @@ -61,10 +62,12 @@ MemSpec::MemSpec(json &memspec, unsigned numberOfChannels, burstLength(parseUint(memspec["memarchitecturespec"]["burstLength"],"burstLength")), dataRate(parseUint(memspec["memarchitecturespec"]["dataRate"],"dataRate")), bitWidth(parseUint(memspec["memarchitecturespec"]["width"],"width")), + dataBusWidth(bitWidth * numberOfDevicesOnDIMM), + bytesPerBurst((burstLength * dataBusWidth) / 8), fCKMHz(parseUdouble(memspec["memtimingspec"]["clkMhz"], "clkMhz")), tCK(sc_time(1.0 / fCKMHz, SC_US)), memoryId(parseString(memspec["memoryId"], "memoryId")), - memoryType(parseString(memspec["memoryType"], "memoryType")), + memoryType(memoryType), burstDuration(tCK * (burstLength / dataRate)) { commandLengthInCycles = std::vector(numberOfCommands(), 1); @@ -74,3 +77,21 @@ sc_time MemSpec::getCommandLength(Command command) const { return tCK * commandLengthInCycles[command]; } + +sc_time MemSpec::getRefreshIntervalAB() const +{ + SC_REPORT_FATAL("MemSpec", "All bank refresh not supported"); + return SC_ZERO_TIME; +} + +sc_time MemSpec::getRefreshIntervalPB() const +{ + SC_REPORT_FATAL("MemSpec", "Per bank refresh not supported"); + return SC_ZERO_TIME; +} + +sc_time MemSpec::getRefreshIntervalSB() const +{ + SC_REPORT_FATAL("MemSpec", "Same bank refresh not supported"); + return SC_ZERO_TIME; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.h b/DRAMSys/library/src/configuration/memspec/MemSpec.h index 6f0fa875..5aa935f9 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.h @@ -48,39 +48,44 @@ class MemSpec { public: - unsigned numberOfChannels; - unsigned numberOfRanks; - unsigned banksPerRank; - unsigned groupsPerRank; - unsigned banksPerGroup; - unsigned numberOfBanks; - unsigned numberOfBankGroups; - unsigned numberOfDevicesOnDIMM; - unsigned numberOfRows; - unsigned numberOfColumns; - unsigned burstLength; - unsigned dataRate; - unsigned bitWidth; + const unsigned numberOfChannels; + const unsigned numberOfRanks; + const unsigned banksPerRank; + const unsigned groupsPerRank; + const unsigned banksPerGroup; + const unsigned numberOfBanks; + const unsigned numberOfBankGroups; + const unsigned numberOfDevicesOnDIMM; + const unsigned numberOfRows; + const unsigned numberOfColumns; + const unsigned burstLength; + const unsigned dataRate; + const unsigned bitWidth; + const unsigned dataBusWidth; + const unsigned bytesPerBurst; // Clock - double fCKMHz; - sc_time tCK; + const double fCKMHz; + const sc_time tCK; - std::string memoryId; - std::string memoryType; + const std::string memoryId; + const enum class MemoryType {DDR3, DDR4, DDR5, LPDDR4, WideIO, WideIO2, GDDR5, GDDR5X, GDDR6, HBM2} memoryType; virtual ~MemSpec() {} - virtual sc_time getRefreshIntervalAB() const = 0; - virtual sc_time getRefreshIntervalPB() const = 0; + virtual sc_time getRefreshIntervalAB() const; + virtual sc_time getRefreshIntervalPB() const; + virtual sc_time getRefreshIntervalSB() const; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const = 0; virtual TimeInterval getIntervalOnDataStrobe(Command) const = 0; sc_time getCommandLength(Command) const; + virtual uint64_t getSimMemSizeInBytes() const = 0; protected: - MemSpec(nlohmann::json &memspec, unsigned numberOfChannels, + MemSpec(nlohmann::json &memspec, MemoryType memoryType, + unsigned numberOfChannels, unsigned numberOfRanks, unsigned banksPerRank, unsigned groupsPerRank, unsigned banksPerGroup, unsigned numberOfBanks, unsigned numberOfBankGroups, diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp index 427c3f85..7cc92848 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecDDR3::MemSpecDDR3(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::DDR3, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -95,12 +95,6 @@ sc_time MemSpecDDR3::getRefreshIntervalAB() const return tREFI; } -sc_time MemSpecDDR3::getRefreshIntervalPB() const -{ - SC_REPORT_FATAL("MemSpecDDR3", "Per bank refresh not supported"); - return SC_ZERO_TIME; -} - // Returns the execution time for commands that have a fixed execution time sc_time MemSpecDDR3::getExecutionTime(Command command, const tlm_generic_payload &) const { @@ -138,3 +132,27 @@ TimeInterval MemSpecDDR3::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecDDR3::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: " << "DDR3" << 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/MemSpecDDR3.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h index f8a1d6de..6c9174de 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h @@ -88,10 +88,11 @@ public: const double iDD3P1; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECDDR3_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp index d3bd513c..23f6773e 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp @@ -40,7 +40,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecDDR4::MemSpecDDR4(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::DDR4, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -55,19 +55,17 @@ MemSpecDDR4::MemSpecDDR4(json &memspec) 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")), + tRPRE (tCK * parseUint(memspec["memtimingspec"]["RPRE"], "RPRE")), tRTP (tCK * parseUint(memspec["memtimingspec"]["RTP"], "RTP")), tWL (tCK * parseUint(memspec["memtimingspec"]["WL"], "WL")), + tWPRE (tCK * parseUint(memspec["memtimingspec"]["WPRE"], "WPRE")), tWR (tCK * parseUint(memspec["memtimingspec"]["WR"], "WR")), tXP (tCK * parseUint(memspec["memtimingspec"]["XP"], "XP")), tXS (tCK * parseUint(memspec["memtimingspec"]["XS"], "XS")), - tCCD_S (tCK * parseUint(memspec["memtimingspec"]["CCD_S"], "CCD_S")), - tCCD_L (tCK * parseUint(memspec["memtimingspec"]["CCD_L"], "CCD_L")), - tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")), tREFI ((parseUint(memspec["memtimingspec"]["REFM"], "REFM") == 4) ? (tCK * (parseUint(memspec["memtimingspec"]["REFI"], "REFI") / 4)) : ((parseUint(memspec["memtimingspec"]["REFM"], "REFM") == 2) ? @@ -79,6 +77,10 @@ MemSpecDDR4::MemSpecDDR4(json &memspec) (tCK * parseUint(memspec["memtimingspec"]["RFC2"], "RFC2")) : (tCK * parseUint(memspec["memtimingspec"]["RFC"], "RFC")))), tRP (tCK * parseUint(memspec["memtimingspec"]["RP"], "RP")), + tDQSCK (tCK * parseUint(memspec["memtimingspec"]["DQSCK"], "DQSCK")), + tCCD_S (tCK * parseUint(memspec["memtimingspec"]["CCD_S"], "CCD_S")), + tCCD_L (tCK * parseUint(memspec["memtimingspec"]["CCD_L"], "CCD_L")), + tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")), tRRD_S (tCK * parseUint(memspec["memtimingspec"]["RRD_S"], "RRD_S")), tRRD_L (tCK * parseUint(memspec["memtimingspec"]["RRD_L"], "RRD_L")), tWTR_S (tCK * parseUint(memspec["memtimingspec"]["WTR_S"], "WTR_S")), @@ -112,12 +114,6 @@ sc_time MemSpecDDR4::getRefreshIntervalAB() const return tREFI; } -sc_time MemSpecDDR4::getRefreshIntervalPB() const -{ - SC_REPORT_FATAL("MemSpecDDR4", "Per bank refresh not supported"); - return SC_ZERO_TIME; -} - // Returns the execution time for commands that have a fixed execution time sc_time MemSpecDDR4::getExecutionTime(Command command, const tlm_generic_payload &) const { @@ -155,3 +151,28 @@ TimeInterval MemSpecDDR4::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecDDR4::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: " << "DDR4" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " Ranks: " << numberOfRanks << std::endl; + std::cout << " Bank groups per rank: " << groupsPerRank << 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/MemSpecDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h index 9395626c..c63fb36f 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h @@ -52,8 +52,10 @@ public: const sc_time tRC; const sc_time tRCD; const sc_time tRL; + const sc_time tRPRE; const sc_time tRTP; const sc_time tWL; + const sc_time tWPRE; const sc_time tWR; const sc_time tXP; const sc_time tXS; @@ -93,11 +95,12 @@ public: const double iDD62; const double vDD2; - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECDDR4_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp new file mode 100644 index 00000000..bd5e92ef --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2020, 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 "MemSpecDDR5.h" +#include "../Configuration.h" + +using namespace tlm; +using json = nlohmann::json; + +MemSpecDDR5::MemSpecDDR5(json &memspec) + : MemSpec(memspec, MemoryType::DDR5, + parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), + parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfBankGroups"], "nbrOfBankGroups"), + parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks") + / parseUint(memspec["memarchitecturespec"]["nbrOfBankGroups"], "nbrOfBankGroups"), + parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks") + * parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfBankGroups"], "nbrOfBankGroups") + * parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), + parseUint(memspec["memarchitecturespec"]["nbrOfDevicesOnDIMM"],"nbrOfDevicesOnDIMM")), + numberOfDIMMRanks(parseUint(memspec["memarchitecturespec"]["nbrOfDIMMRanks"], "nbrOfDIMMRanks")), + physicalRanksPerDIMMRank(parseUint(memspec["memarchitecturespec"]["nbrOfPhysicalRanks"], "nbrOfPhysicalRanks")), + numberOfPhysicalRanks(physicalRanksPerDIMMRank * numberOfDIMMRanks), + logicalRanksPerPhysicalRank(parseUint(memspec["memarchitecturespec"]["nbrOfLogicalRanks"], "nbrOfLogicalRanks")), + 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) +{ + if (cmdMode == 1) + { + commandLengthInCycles[Command::ACT] = 2; + commandLengthInCycles[Command::RD] = 2; + commandLengthInCycles[Command::RDA] = 2; + commandLengthInCycles[Command::WR] = 2; + commandLengthInCycles[Command::WRA] = 2; + } + else if (cmdMode == 2) + { + commandLengthInCycles[Command::ACT] = 4; + commandLengthInCycles[Command::PRE] = 2; + commandLengthInCycles[Command::PREA] = 2; + commandLengthInCycles[Command::PRESB] = 2; + commandLengthInCycles[Command::RD] = 4; + commandLengthInCycles[Command::RDA] = 4; + commandLengthInCycles[Command::WR] = 4; + commandLengthInCycles[Command::WRA] = 4; + commandLengthInCycles[Command::REFA] = 2; + commandLengthInCycles[Command::REFSB] = 2; + commandLengthInCycles[Command::PDEA] = 2; + commandLengthInCycles[Command::PDXA] = 2; + commandLengthInCycles[Command::PDEP] = 2; + commandLengthInCycles[Command::PDXP] = 2; + commandLengthInCycles[Command::SREFEN] = 2; + commandLengthInCycles[Command::SREFEX] = 2; + } + else + SC_REPORT_FATAL("MemSpecDDR5", "Invalid command mode!"); + + if (!(refMode == 1 || refMode == 2)) + SC_REPORT_FATAL("MemSpecDDR5", "Invalid refresh mode! " + "Set 1 for normal or 2 for fine granularity refresh mode."); +} + +sc_time MemSpecDDR5::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecDDR5::getRefreshIntervalSB() const +{ + return tREFIsb; +} + +// Returns the execution time for commands that have a fixed execution time +sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload &) const +{ + if (command == Command::PRE || command == Command::PREA || command == Command::PRESB) + return tRP + cmdOffset_S; + else if (command == Command::ACT) + return tRCD + cmdOffset_L; + else if (command == Command::RD) + return tRL + burstDuration + cmdOffset_L; + else if (command == Command::RDA) + return tRTP + tRP + cmdOffset_L; + else if (command == Command::WR) + return tWL + burstDuration + cmdOffset_L; + else if (command == Command::WRA) + return tWL + burstDuration + tWR + tRP + cmdOffset_L; + else if (command == Command::REFA) + return tRFC_slr + cmdOffset_S; + else if (command == Command::REFSB) + return tRFCsb_slr + cmdOffset_S; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecDDR5::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + cmdOffset_L, sc_time_stamp() + tRL + burstDuration + cmdOffset_L); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + cmdOffset_L, sc_time_stamp() + tWL + burstDuration + cmdOffset_L); + else + { + SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); + return TimeInterval(); + } +} + +uint64_t MemSpecDDR5::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: " << "DDR5" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " DIMMs: " << numberOfDIMMRanks << std::endl; + std::cout << " Physical Ranks per DIMM: " << physicalRanksPerDIMMRank << std::endl; + std::cout << " Logical Ranks per device: " << logicalRanksPerPhysicalRank << std::endl; + std::cout << " Ranks: " << numberOfRanks << std::endl; + std::cout << " Bank groups per rank: " << groupsPerRank << 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/MemSpecDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h new file mode 100644 index 00000000..13883326 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2020, 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 MEMSPECDDR5_H +#define MEMSPECDDR5_H + +#include "MemSpec.h" +#include "../../common/third_party/nlohmann/single_include/nlohmann/json.hpp" + +class MemSpecDDR5 final : public MemSpec +{ +public: + MemSpecDDR5(nlohmann::json &memspec); + + const unsigned numberOfDIMMRanks; + const unsigned physicalRanksPerDIMMRank; + const unsigned numberOfPhysicalRanks; + const unsigned logicalRanksPerPhysicalRank; + const unsigned numberOfLogicalRanks; + const unsigned cmdMode; + const unsigned refMode; + + // Memspec Variables: + const sc_time tRCD; + const sc_time tPPD; + const sc_time tRP; + const sc_time tRAS; + const sc_time tRC; + const sc_time tRL; + const sc_time tRTP; + const sc_time tRPRE; + const sc_time tRPST; + const sc_time tRDDQS; + const sc_time tWL; + const sc_time tWPRE; + const sc_time tWPST; + const sc_time tWR; + const sc_time tCCD_L_slr; + const sc_time tCCD_L_WR_slr; + const sc_time tCCD_S_slr; + const sc_time tCCD_S_WR_slr; + const sc_time tCCD_dlr; + const sc_time tCCD_WR_dlr; + const sc_time tCCD_WR_dpr; + const sc_time tRRD_L_slr; + const sc_time tRRD_S_slr; + const sc_time tRRD_dlr; + const sc_time tFAW_slr; + const sc_time tFAW_dlr; + const sc_time tWTR_L; + const sc_time tWTR_S; + const sc_time tRFC_slr; + const sc_time tRFC_dlr; + const sc_time tRFC_dpr; + const sc_time tRFCsb_slr; + const sc_time tRFCsb_dlr; + const sc_time tREFI; + const sc_time tREFIsb; + const sc_time tREFSBRD_slr; + const sc_time tREFSBRD_dlr; + const sc_time tRTRS; + + const sc_time tCPDED; + const sc_time tPD; + const sc_time tXP; + const sc_time tACTPDEN; + const sc_time tPRPDEN; + const sc_time tREFPDEN; + + const sc_time cmdOffset_S; + const sc_time cmdOffset_L; + + // Currents and Voltages: + // TODO: to be completed + + 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 uint64_t getSimMemSizeInBytes() const override; +}; + +#endif // MEMSPECDDR5_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp index 3ca42b65..f99ce411 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecGDDR5::MemSpecGDDR5(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::GDDR5, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -142,3 +142,27 @@ TimeInterval MemSpecGDDR5::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecGDDR5::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "GDDR5" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " Ranks: " << numberOfRanks << std::endl; + std::cout << " Bank groups per rank: " << groupsPerRank << 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 << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h index 84e7113e..3abeb869 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h @@ -85,11 +85,13 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECGDDR5_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp index e2fd9855..84f581fa 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecGDDR5X::MemSpecGDDR5X(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::GDDR5X, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -142,3 +142,27 @@ TimeInterval MemSpecGDDR5X::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecGDDR5X::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "GDDR5X" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " Ranks: " << numberOfRanks << std::endl; + std::cout << " Bank groups per rank: " << groupsPerRank << 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 << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h index f5d22239..10fcd5b5 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h @@ -85,11 +85,13 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECGDDR5X_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp index a1b6e4e3..4cde4e10 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecGDDR6::MemSpecGDDR6(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::GDDR6, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -144,3 +144,27 @@ TimeInterval MemSpecGDDR6::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecGDDR6::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "GDDR6" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " Ranks: " << numberOfRanks << std::endl; + std::cout << " Bank groups per rank: " << groupsPerRank << 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 << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h index a4d2318d..c0f9f7d1 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h @@ -87,11 +87,13 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECGDDR6_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp index 784b4f99..3f61973b 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecHBM2::MemSpecHBM2(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::HBM2, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -139,3 +139,27 @@ TimeInterval MemSpecHBM2::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecHBM2::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "HBM2" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " Ranks: " << numberOfRanks << std::endl; + std::cout << " Bank groups per rank: " << groupsPerRank << 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 << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h index a6885b49..618f40db 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h @@ -80,11 +80,13 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECHBM2_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp index 915c14c4..ca0a2fc1 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecLPDDR4::MemSpecLPDDR4(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::LPDDR4, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -147,3 +147,26 @@ TimeInterval MemSpecLPDDR4::getIntervalOnDataStrobe(Command command) const } } +uint64_t MemSpecLPDDR4::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "GDDR5" << 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 << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} + diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h index 26da297c..4c7d0d52 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h @@ -80,11 +80,13 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECLPDDR4_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp index 0d8b9be6..f0df06df 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecWideIO::MemSpecWideIO(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::WideIO, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -101,12 +101,6 @@ sc_time MemSpecWideIO::getRefreshIntervalAB() const return tREFI; } -sc_time MemSpecWideIO::getRefreshIntervalPB() const -{ - SC_REPORT_FATAL("MemSpecWideIO", "Per bank refresh not supported"); - return SC_ZERO_TIME; -} - // Returns the execution time for commands that have a fixed execution time sc_time MemSpecWideIO::getExecutionTime(Command command, const tlm_generic_payload &) const { @@ -146,3 +140,26 @@ TimeInterval MemSpecWideIO::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecWideIO::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "GDDR5" << 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 << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h index 2ce092ff..eb1ad7d7 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h @@ -93,11 +93,12 @@ public: const double iDD62; const double vDD2; - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECWIDEIO_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp index b74129ba..97006423 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.cpp @@ -39,7 +39,7 @@ using namespace tlm; using json = nlohmann::json; MemSpecWideIO2::MemSpecWideIO2(json &memspec) - : MemSpec(memspec, + : MemSpec(memspec, MemoryType::WideIO2, parseUint(memspec["memarchitecturespec"]["nbrOfChannels"],"nbrOfChannels"), parseUint(memspec["memarchitecturespec"]["nbrOfRanks"],"nbrOfRanks"), parseUint(memspec["memarchitecturespec"]["nbrOfBanks"],"nbrOfBanks"), @@ -69,9 +69,9 @@ MemSpecWideIO2::MemSpecWideIO2(json &memspec) tWTR (tCK * parseUint(memspec["memtimingspec"]["WTR"], "WTR")), tRRD (tCK * parseUint(memspec["memtimingspec"]["RRD"], "RRD")), tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")), - tREFI (tCK * (unsigned)(parseUint(memspec["memtimingspec"]["REFI"], "REFI") + tREFI (tCK * static_cast(parseUint(memspec["memtimingspec"]["REFI"], "REFI") * parseUdouble(memspec["memtimingspec"]["REFM"], "REFM"))), - tREFIpb (tCK * (unsigned)(parseUint(memspec["memtimingspec"]["REFIPB"], "REFIPB") + tREFIpb (tCK * static_cast(parseUint(memspec["memtimingspec"]["REFIPB"], "REFIPB") * parseUdouble(memspec["memtimingspec"]["REFM"], "REFM"))), tRFCab (tCK * parseUint(memspec["memtimingspec"]["RFCAB"], "RFCAB")), tRFCpb (tCK * parseUint(memspec["memtimingspec"]["RFCPB"], "RFCPB")), @@ -131,3 +131,26 @@ TimeInterval MemSpecWideIO2::getIntervalOnDataStrobe(Command command) const return TimeInterval(); } } + +uint64_t MemSpecWideIO2::getSimMemSizeInBytes() const +{ + uint64_t deviceSizeBits = static_cast(banksPerRank) * numberOfRows * numberOfColumns * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + uint64_t memorySizeBytes = deviceSizeBytes * numberOfRanks; + + std::cout << headline << std::endl; + std::cout << "Per Channel Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "GDDR5" << 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 << std::endl; + + assert(memorySizeBytes > 0); + return memorySizeBytes; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h index d56f9d30..35503a61 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h @@ -74,11 +74,13 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; 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 uint64_t getSimMemSizeInBytes() const override; }; #endif // MEMSPECWIDEIO2_H diff --git a/DRAMSys/library/src/controller/BankMachine.cpp b/DRAMSys/library/src/controller/BankMachine.cpp index fb7e3e8c..0c4f5770 100644 --- a/DRAMSys/library/src/controller/BankMachine.cpp +++ b/DRAMSys/library/src/controller/BankMachine.cpp @@ -55,23 +55,23 @@ void BankMachine::updateState(Command command) switch (command) { case Command::ACT: - currentState = BmState::Activated; - currentRow = DramExtension::getRow(currentPayload); + state = State::Activated; + openRow = DramExtension::getRow(currentPayload); break; - case Command::PRE: case Command::PREA: - currentState = BmState::Precharged; + case Command::PRE: case Command::PREA: case Command::PRESB: + state = State::Precharged; break; case Command::RD: case Command::WR: currentPayload = nullptr; break; case Command::RDA: case Command::WRA: - currentState = BmState::Precharged; + state = State::Precharged; currentPayload = nullptr; break; case Command::PDEA: case Command::PDEP: case Command::SREFEN: sleeping = true; break; - case Command::REFA: case Command::REFB: + case Command::REFA: case Command::REFB: case Command::REFSB: sleeping = false; blocked = false; break; @@ -105,12 +105,12 @@ Bank BankMachine::getBank() Row BankMachine::getOpenRow() { - return currentRow; + return openRow; } -BmState BankMachine::getState() +BankMachine::State BankMachine::getState() { - return currentState; + return state; } bool BankMachine::isIdle() @@ -133,14 +133,14 @@ sc_time BankMachineOpen::start() if (currentPayload == nullptr) return timeToSchedule; - if (currentState == BmState::Precharged && !blocked) // row miss + if (state == State::Precharged && !blocked) // row miss { nextCommand = Command::ACT; timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); } - else if (currentState == BmState::Activated) + else if (state == State::Activated) { - if (DramExtension::getRow(currentPayload) == currentRow) // row hit + if (DramExtension::getRow(currentPayload) == openRow) // row hit { if (currentPayload->get_command() == TLM_READ_COMMAND) nextCommand = Command::RD; @@ -175,12 +175,12 @@ sc_time BankMachineClosed::start() if (currentPayload == nullptr) return timeToSchedule; - if (currentState == BmState::Precharged && !blocked) // row miss + if (state == State::Precharged && !blocked) // row miss { nextCommand = Command::ACT; timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); } - else if (currentState == BmState::Activated) + else if (state == State::Activated) { if (currentPayload->get_command() == TLM_READ_COMMAND) nextCommand = Command::RDA; @@ -209,16 +209,16 @@ sc_time BankMachineOpenAdaptive::start() if (currentPayload == nullptr) return timeToSchedule; - if (currentState == BmState::Precharged && !blocked) // row miss + if (state == State::Precharged && !blocked) // row miss { nextCommand = Command::ACT; timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); } - else if (currentState == BmState::Activated) + else if (state == State::Activated) { - if (DramExtension::getRow(currentPayload) == currentRow) // row hit + if (DramExtension::getRow(currentPayload) == openRow) // row hit { - if (scheduler->hasFurtherRequest(bank) && !scheduler->hasFurtherRowHit(bank, currentRow)) + if (scheduler->hasFurtherRequest(bank) && !scheduler->hasFurtherRowHit(bank, openRow)) { if (currentPayload->get_command() == TLM_READ_COMMAND) nextCommand = Command::RDA; @@ -262,16 +262,16 @@ sc_time BankMachineClosedAdaptive::start() if (currentPayload == nullptr) return timeToSchedule; - if (currentState == BmState::Precharged && !blocked) // row miss + if (state == State::Precharged && !blocked) // row miss { nextCommand = Command::ACT; timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank); } - else if (currentState == BmState::Activated) + else if (state == State::Activated) { - if (DramExtension::getRow(currentPayload) == currentRow) // row hit + if (DramExtension::getRow(currentPayload) == openRow) // row hit { - if (scheduler->hasFurtherRowHit(bank, currentRow)) + if (scheduler->hasFurtherRowHit(bank, openRow)) { if (currentPayload->get_command() == TLM_READ_COMMAND) nextCommand = Command::RD; diff --git a/DRAMSys/library/src/controller/BankMachine.h b/DRAMSys/library/src/controller/BankMachine.h index 9fec70a2..508ed46d 100644 --- a/DRAMSys/library/src/controller/BankMachine.h +++ b/DRAMSys/library/src/controller/BankMachine.h @@ -43,12 +43,6 @@ #include "scheduler/SchedulerIF.h" #include "checker/CheckerIF.h" -enum class BmState -{ - Precharged, - Activated -}; - class BankMachine { public: @@ -58,11 +52,13 @@ public: void updateState(Command); void block(); + enum class State {Precharged, Activated}; + Rank getRank(); BankGroup getBankGroup(); Bank getBank(); Row getOpenRow(); - BmState getState(); + State getState(); bool isIdle(); protected: @@ -71,8 +67,8 @@ protected: SchedulerIF *scheduler; CheckerIF *checker; Command nextCommand = Command::NOP; - BmState currentState = BmState::Precharged; - Row currentRow; + State state = State::Precharged; + Row openRow; sc_time timeToSchedule = sc_max_time(); Rank rank = Rank(0); BankGroup bankgroup = BankGroup(0); diff --git a/DRAMSys/library/src/controller/Command.cpp b/DRAMSys/library/src/controller/Command.cpp index d1e9f0d4..a5f50101 100644 --- a/DRAMSys/library/src/controller/Command.cpp +++ b/DRAMSys/library/src/controller/Command.cpp @@ -44,95 +44,104 @@ using namespace DRAMPower; std::string commandToString(Command command) { assert(command >= Command::NOP && command <= Command::SREFEX); - static std::array stringOfCommand = + static std::array stringOfCommand = {"NOP", - "RD", - "WR", - "RDA", - "WRA", - "PRE", - "ACT", - "REFB", - "PREA", - "REFA", - "PDEA", - "PDXA", - "PDEP", - "PDXP", - "SREFEN", - "SREFEX"}; + "RD", + "WR", + "RDA", + "WRA", + "ACT", + "PRE", + "REFB", + "PRESB", + "REFSB", + "PREA", + "REFA", + "PDEA", + "PDXA", + "PDEP", + "PDXP", + "SREFEN", + "SREFEX"}; return stringOfCommand[command]; } unsigned numberOfCommands() { - return 16; + return 18; } tlm_phase commandToPhase(Command command) { assert(command >= Command::NOP && command <= Command::SREFEX); - static std::array phaseOfCommand = + static std::array phaseOfCommand = {UNINITIALIZED_PHASE, - BEGIN_RD, - BEGIN_WR, - BEGIN_RDA, - BEGIN_WRA, - BEGIN_PRE, - BEGIN_ACT, - BEGIN_REFB, - BEGIN_PREA, - BEGIN_REFA, - BEGIN_PDNA, - END_PDNA, - BEGIN_PDNP, - END_PDNP, - BEGIN_SREF, - END_SREF}; + BEGIN_RD, + BEGIN_WR, + BEGIN_RDA, + BEGIN_WRA, + BEGIN_ACT, + BEGIN_PRE, + BEGIN_REFB, + BEGIN_PRESB, + BEGIN_REFSB, + BEGIN_PREA, + BEGIN_REFA, + BEGIN_PDNA, + END_PDNA, + BEGIN_PDNP, + END_PDNP, + BEGIN_SREF, + END_SREF}; return phaseOfCommand[command]; } Command phaseToCommand(tlm_phase phase) { assert(phase >= BEGIN_RD && phase <= END_SREF); - static std::array commandOfPhase = + static std::array commandOfPhase = {Command::RD, - Command::WR, - Command::RDA, - Command::WRA, - Command::PRE, - Command::ACT, - Command::REFB, - Command::PREA, - Command::REFA, - Command::PDEA, - Command::PDXA, - Command::PDEP, - Command::PDXP, - Command::SREFEN, - Command::SREFEX}; + Command::WR, + Command::RDA, + Command::WRA, + Command::ACT, + Command::PRE, + Command::REFB, + Command::PRESB, + Command::REFSB, + Command::PREA, + Command::REFA, + Command::PDEA, + Command::PDXA, + Command::PDEP, + Command::PDXP, + Command::SREFEN, + Command::SREFEX}; return commandOfPhase[phase - BEGIN_RD]; } MemCommand::cmds phaseToDRAMPowerCommand(tlm_phase phase) { + // TODO: add correct phases when DRAMPower supports DDR5 same bank refresh assert(phase >= BEGIN_RD && phase <= END_SREF); - static std::array phaseOfCommand = + static std::array phaseOfCommand = {MemCommand::RD, - MemCommand::WR, - MemCommand::RDA, - MemCommand::WRA, - MemCommand::PRE, - MemCommand::ACT, - MemCommand::REFB, - MemCommand::PREA, - MemCommand::REF, - MemCommand::PDN_S_ACT, - MemCommand::PUP_ACT, - MemCommand::PDN_S_PRE, - MemCommand::PUP_PRE, - MemCommand::SREN, - MemCommand::SREX}; + MemCommand::WR, + MemCommand::RDA, + MemCommand::WRA, + MemCommand::ACT, + MemCommand::PRE, + MemCommand::REFB, + MemCommand::NOP, + MemCommand::NOP, + MemCommand::PREA, + MemCommand::REF, + MemCommand::PDN_S_ACT, + MemCommand::PUP_ACT, + MemCommand::PDN_S_PRE, + MemCommand::PUP_PRE, + MemCommand::SREN, + MemCommand::SREX}; return phaseOfCommand[phase - BEGIN_RD]; } @@ -144,7 +153,7 @@ bool phaseNeedsEnd(tlm_phase phase) tlm_phase getEndPhase(tlm_phase phase) { assert(phase >= BEGIN_RD && phase <= BEGIN_REFA); - return (phase + 15); + return (phase + 17); } bool isBankCommand(Command command) @@ -153,6 +162,12 @@ bool isBankCommand(Command command) return (command <= Command::REFB); } +bool isGroupCommand(Command command) +{ + assert(command >= Command::NOP && command <= Command::SREFEX); + return (command >= Command::PRESB && command <= Command::REFSB); +} + bool isRankCommand(Command command) { assert(command >= Command::NOP && command <= Command::SREFEX); @@ -168,5 +183,5 @@ bool isCasCommand(Command command) bool isRasCommand(Command command) { assert(command >= Command::NOP && command <= Command::SREFEX); - return (command >= Command::PRE); + return (command >= Command::ACT); } diff --git a/DRAMSys/library/src/controller/Command.h b/DRAMSys/library/src/controller/Command.h index d058ab63..5e9c92f8 100644 --- a/DRAMSys/library/src/controller/Command.h +++ b/DRAMSys/library/src/controller/Command.h @@ -46,31 +46,35 @@ #include "../common/third_party/DRAMPower/src/MemCommand.h" // DO NOT CHANGE THE ORDER! -DECLARE_EXTENDED_PHASE(BEGIN_RD); // 5 -DECLARE_EXTENDED_PHASE(BEGIN_WR); // 6 -DECLARE_EXTENDED_PHASE(BEGIN_RDA); // 7 -DECLARE_EXTENDED_PHASE(BEGIN_WRA); // 8 -DECLARE_EXTENDED_PHASE(BEGIN_PRE); // 9 -DECLARE_EXTENDED_PHASE(BEGIN_ACT); // 10 -DECLARE_EXTENDED_PHASE(BEGIN_REFB); // 11 -DECLARE_EXTENDED_PHASE(BEGIN_PREA); // 12 -DECLARE_EXTENDED_PHASE(BEGIN_REFA); // 13 -DECLARE_EXTENDED_PHASE(BEGIN_PDNA); // 14 -DECLARE_EXTENDED_PHASE(END_PDNA); // 15 -DECLARE_EXTENDED_PHASE(BEGIN_PDNP); // 16 -DECLARE_EXTENDED_PHASE(END_PDNP); // 17 -DECLARE_EXTENDED_PHASE(BEGIN_SREF); // 18 -DECLARE_EXTENDED_PHASE(END_SREF); // 19 +DECLARE_EXTENDED_PHASE(BEGIN_RD); // 5 +DECLARE_EXTENDED_PHASE(BEGIN_WR); // 6 +DECLARE_EXTENDED_PHASE(BEGIN_RDA); // 7 +DECLARE_EXTENDED_PHASE(BEGIN_WRA); // 8 +DECLARE_EXTENDED_PHASE(BEGIN_ACT); // 9 +DECLARE_EXTENDED_PHASE(BEGIN_PRE); // 10 +DECLARE_EXTENDED_PHASE(BEGIN_REFB); // 11 +DECLARE_EXTENDED_PHASE(BEGIN_PRESB); // 12 +DECLARE_EXTENDED_PHASE(BEGIN_REFSB); // 13 +DECLARE_EXTENDED_PHASE(BEGIN_PREA); // 14 +DECLARE_EXTENDED_PHASE(BEGIN_REFA); // 15 +DECLARE_EXTENDED_PHASE(BEGIN_PDNA); // 16 +DECLARE_EXTENDED_PHASE(END_PDNA); // 17 +DECLARE_EXTENDED_PHASE(BEGIN_PDNP); // 18 +DECLARE_EXTENDED_PHASE(END_PDNP); // 19 +DECLARE_EXTENDED_PHASE(BEGIN_SREF); // 20 +DECLARE_EXTENDED_PHASE(END_SREF); // 21 -DECLARE_EXTENDED_PHASE(END_RD); // 20 -DECLARE_EXTENDED_PHASE(END_WR); // 21 -DECLARE_EXTENDED_PHASE(END_RDA); // 22 -DECLARE_EXTENDED_PHASE(END_WRA); // 23 -DECLARE_EXTENDED_PHASE(END_PRE); // 24 -DECLARE_EXTENDED_PHASE(END_ACT); // 25 -DECLARE_EXTENDED_PHASE(END_REFB); // 26 -DECLARE_EXTENDED_PHASE(END_PREA); // 27 -DECLARE_EXTENDED_PHASE(END_REFA); // 28 +DECLARE_EXTENDED_PHASE(END_RD); // 22 +DECLARE_EXTENDED_PHASE(END_WR); // 23 +DECLARE_EXTENDED_PHASE(END_RDA); // 24 +DECLARE_EXTENDED_PHASE(END_WRA); // 25 +DECLARE_EXTENDED_PHASE(END_ACT); // 26 +DECLARE_EXTENDED_PHASE(END_PRE); // 27 +DECLARE_EXTENDED_PHASE(END_REFB); // 28 +DECLARE_EXTENDED_PHASE(END_PRESB); // 29 +DECLARE_EXTENDED_PHASE(END_REFSB); // 30 +DECLARE_EXTENDED_PHASE(END_PREA); // 31 +DECLARE_EXTENDED_PHASE(END_REFA); // 32 enum Command { @@ -79,9 +83,11 @@ enum Command WR, RDA, WRA, - PRE, ACT, + PRE, REFB, + PRESB, + REFSB, PREA, REFA, PDEA, @@ -100,6 +106,7 @@ bool phaseNeedsEnd(tlm::tlm_phase); tlm::tlm_phase getEndPhase(tlm::tlm_phase); unsigned numberOfCommands(); bool isBankCommand(Command); +bool isGroupCommand(Command); bool isRankCommand(Command); bool isCasCommand(Command); bool isRasCommand(Command); diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 4176929e..7e870207 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -39,6 +39,7 @@ #include "Command.h" #include "checker/CheckerDDR3.h" #include "checker/CheckerDDR4.h" +#include "checker/CheckerDDR5.h" #include "checker/CheckerWideIO.h" #include "checker/CheckerLPDDR4.h" #include "checker/CheckerWideIO2.h" @@ -53,9 +54,10 @@ #include "cmdmux/CmdMuxOldest.h" #include "respqueue/RespQueueFifo.h" #include "respqueue/RespQueueReorder.h" -#include "refresh/RefreshManagerRankwise.h" #include "refresh/RefreshManagerDummy.h" +#include "refresh/RefreshManagerRankwise.h" #include "refresh/RefreshManagerBankwise.h" +#include "refresh/RefreshManagerGroupwise.h" #include "powerdown/PowerDownManagerStaggered.h" #include "powerdown/PowerDownManagerDummy.h" @@ -75,74 +77,66 @@ Controller::Controller(sc_module_name name) : readyCommands.reserve(memSpec->numberOfBanks); // instantiate timing checker - if (memSpec->memoryType == "DDR3") + if (memSpec->memoryType == MemSpec::MemoryType::DDR3) checker = new CheckerDDR3(); - else if (memSpec->memoryType == "DDR4") + else if (memSpec->memoryType == MemSpec::MemoryType::DDR4) checker = new CheckerDDR4(); - else if (memSpec->memoryType == "WIDEIO_SDR") + else if (memSpec->memoryType == MemSpec::MemoryType::DDR5) + checker = new CheckerDDR5(); + else if (memSpec->memoryType == MemSpec::MemoryType::WideIO) checker = new CheckerWideIO(); - else if (memSpec->memoryType == "LPDDR4") + else if (memSpec->memoryType == MemSpec::MemoryType::LPDDR4) checker = new CheckerLPDDR4(); - else if (memSpec->memoryType == "WIDEIO2") + else if (memSpec->memoryType == MemSpec::MemoryType::WideIO2) checker = new CheckerWideIO2(); - else if (memSpec->memoryType == "HBM2") + else if (memSpec->memoryType == MemSpec::MemoryType::HBM2) checker = new CheckerHBM2(); - else if (memSpec->memoryType == "GDDR5") + else if (memSpec->memoryType == MemSpec::MemoryType::GDDR5) checker = new CheckerGDDR5(); - else if (memSpec->memoryType == "GDDR5X") + else if (memSpec->memoryType == MemSpec::MemoryType::GDDR5X) checker = new CheckerGDDR5X(); - else if (memSpec->memoryType == "GDDR6") + else if (memSpec->memoryType == MemSpec::MemoryType::GDDR6) checker = new CheckerGDDR6(); - else - SC_REPORT_FATAL("Controller", "Unsupported DRAM type!"); // instantiate scheduler and command mux - if (config.scheduler == "Fifo") + if (config.scheduler == Configuration::Scheduler::Fifo) scheduler = new SchedulerFifo(); - else if (config.scheduler == "FrFcfs") + else if (config.scheduler == Configuration::Scheduler::FrFcfs) scheduler = new SchedulerFrFcfs(); - else if (config.scheduler == "FrFcfsGrp") + else if (config.scheduler == Configuration::Scheduler::FrFcfsGrp) scheduler = new SchedulerFrFcfsGrp(); - else - SC_REPORT_FATAL("Controller", "Selected scheduler not supported!"); - if (config.cmdMux == "Oldest") + if (config.cmdMux == Configuration::CmdMux::Oldest) cmdMux = new CmdMuxOldest(); - else if (config.cmdMux == "Strict") + else if (config.cmdMux == Configuration::CmdMux::Strict) cmdMux = new CmdMuxStrict(); - else - SC_REPORT_FATAL("Controller", "Selected cmdmux not supported!"); - if (config.respQueue == "Fifo") + if (config.respQueue == Configuration::RespQueue::Fifo) respQueue = new RespQueueFifo(); - else if (config.respQueue == "Reorder") + else if (config.respQueue == Configuration::RespQueue::Reorder) respQueue = new RespQueueReorder(); - else - SC_REPORT_FATAL("Controller", "Selected respqueue not supported!"); // instantiate bank machines (one per bank) - if (config.pagePolicy == "Open") + if (config.pagePolicy == Configuration::PagePolicy::Open) { for (unsigned bankID = 0; bankID < memSpec->numberOfBanks; bankID++) bankMachines.push_back(new BankMachineOpen(scheduler, checker, Bank(bankID))); } - else if (config.pagePolicy == "OpenAdaptive") + else if (config.pagePolicy == Configuration::PagePolicy::OpenAdaptive) { for (unsigned bankID = 0; bankID < memSpec->numberOfBanks; bankID++) bankMachines.push_back(new BankMachineOpenAdaptive(scheduler, checker, Bank(bankID))); } - else if (config.pagePolicy == "Closed") + else if (config.pagePolicy == Configuration::PagePolicy::Closed) { for (unsigned bankID = 0; bankID < memSpec->numberOfBanks; bankID++) bankMachines.push_back(new BankMachineClosed(scheduler, checker, Bank(bankID))); } - else if (config.pagePolicy == "ClosedAdaptive") + else if (config.pagePolicy == Configuration::PagePolicy::ClosedAdaptive) { for (unsigned bankID = 0; bankID < memSpec->numberOfBanks; bankID++) bankMachines.push_back(new BankMachineClosedAdaptive(scheduler, checker, Bank(bankID))); } - else - SC_REPORT_FATAL("Controller", "Selected page policy not supported!"); for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) { @@ -151,7 +145,7 @@ Controller::Controller(sc_module_name name) : } // instantiate power-down managers (one per rank) - if (config.powerDownPolicy == "NoPowerDown") + if (config.powerDownPolicy == Configuration::PowerDownPolicy::NoPowerDown) { for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) { @@ -159,7 +153,7 @@ Controller::Controller(sc_module_name name) : powerDownManagers.push_back(manager); } } - else if (config.powerDownPolicy == "Staggered") + else if (config.powerDownPolicy == Configuration::PowerDownPolicy::Staggered) { for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) { @@ -167,16 +161,14 @@ Controller::Controller(sc_module_name name) : powerDownManagers.push_back(manager); } } - else - SC_REPORT_FATAL("Controller", "Selected power-down mode not supported!"); // instantiate refresh managers (one per rank) - if (config.refreshPolicy == "NoRefresh") + if (config.refreshPolicy == Configuration::RefreshPolicy::NoRefresh) { for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) refreshManagers.push_back(new RefreshManagerDummy()); } - else if (config.refreshPolicy == "Rankwise") + else if (config.refreshPolicy == Configuration::RefreshPolicy::Rankwise) { for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) { @@ -185,7 +177,16 @@ Controller::Controller(sc_module_name name) : refreshManagers.push_back(manager); } } - else if (config.refreshPolicy == "Bankwise") + else if (config.refreshPolicy == Configuration::RefreshPolicy::Groupwise) + { + for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) + { + RefreshManagerIF *manager = new RefreshManagerGroupwise + (bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker); + refreshManagers.push_back(manager); + } + } + else if (config.refreshPolicy == Configuration::RefreshPolicy::Bankwise) { for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) { @@ -280,6 +281,12 @@ void Controller::controllerMethod() for (auto it : bankMachinesOnRank[rank.ID()]) it->updateState(command); } + else if (isGroupCommand(command)) + { + for (unsigned bankID = (bank.ID() % memSpec->banksPerGroup); + bankID < memSpec->banksPerRank; bankID += memSpec->banksPerGroup) + bankMachinesOnRank[rank.ID()][bankID]->updateState(command); + } else bankMachines[bank.ID()]->updateState(command); @@ -347,7 +354,7 @@ tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans, SC_REPORT_FATAL("Controller", "nb_transport_fw in controller was triggered with unknown phase"); PRINTDEBUGMESSAGE(name(), "[fw] " + getPhaseName(phase) + " notification in " + - notificationDelay.to_string()); + delay.to_string()); return TLM_ACCEPTED; } @@ -368,7 +375,7 @@ void Controller::finishBeginReq() { if (transToAcquire.payload != nullptr && transToAcquire.time <= sc_time_stamp()) { - NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(transToAcquire.payload); + NDEBUG_UNUSED(uint64_t id) = DramExtension::getChannelPayloadID(transToAcquire.payload); PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system."); if (totalNumberOfPayloads == 0) @@ -415,6 +422,7 @@ void Controller::startBeginResp() { transToRelease.time = sc_max_time(); sendToFrontend(transToRelease.payload, BEGIN_RESP); + numberOfTransactionsServed++; } else { @@ -429,12 +437,11 @@ void Controller::finishEndResp() { if (transToRelease.payload != nullptr && transToRelease.time <= sc_time_stamp()) { - NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(transToRelease.payload); + NDEBUG_UNUSED(uint64_t id) = DramExtension::getChannelPayloadID(transToRelease.payload); PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system."); transToRelease.payload->release(); transToRelease.payload = nullptr; - numberOfTransactionsServed++; totalNumberOfPayloads--; if (totalNumberOfPayloads == 0) diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index 4fef0c65..20e6b3ad 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -62,7 +62,7 @@ class Controller : public ControllerIF public: Controller(sc_module_name); SC_HAS_PROCESS(Controller); - virtual ~Controller(); + virtual ~Controller() override; protected: virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &, tlm::tlm_phase &, sc_time &) override; @@ -72,17 +72,19 @@ protected: virtual void sendToFrontend(tlm::tlm_generic_payload *, tlm::tlm_phase); virtual void sendToDram(Command, tlm::tlm_generic_payload *); + virtual void controllerMethod(); + + SchedulerIF *scheduler; + MemSpec *memSpec; + private: unsigned totalNumberOfPayloads = 0; std::vector ranksNumberOfPayloads; ReadyCommands readyCommands; - MemSpec *memSpec; - std::vector bankMachines; std::vector> bankMachinesOnRank; CmdMuxIF *cmdMux; - SchedulerIF *scheduler; CheckerIF *checker; RespQueueIF *respQueue; std::vector refreshManagers; @@ -99,7 +101,6 @@ private: void startBeginResp(); void finishEndResp(); - void controllerMethod(); sc_event beginReqEvent, endRespEvent, controllerEvent, dataResponseEvent; }; diff --git a/DRAMSys/library/src/controller/ControllerRecordable.cpp b/DRAMSys/library/src/controller/ControllerRecordable.cpp index 8ca3f8c2..c8ab5efd 100644 --- a/DRAMSys/library/src/controller/ControllerRecordable.cpp +++ b/DRAMSys/library/src/controller/ControllerRecordable.cpp @@ -37,6 +37,20 @@ using namespace tlm; +ControllerRecordable::ControllerRecordable(sc_module_name name, TlmRecorder *tlmRecorder) + : Controller(name), tlmRecorder(tlmRecorder) +{ + if (Configuration::getInstance().enableWindowing) + { + sensitive << windowEvent; + windowSizeTime = Configuration::getInstance().windowSize * memSpec->tCK; + slidingAverageBufferDepth = std::vector(scheduler->getBufferDepth().size()); + windowAverageBufferDepth = std::vector(scheduler->getBufferDepth().size()); + windowEvent.notify(windowSizeTime); + nextWindowEventTime = windowSizeTime; + } +} + tlm_sync_enum ControllerRecordable::nb_transport_fw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay) { @@ -65,7 +79,10 @@ void ControllerRecordable::sendToDram(Command command, tlm_generic_payload *payl TimeInterval dataStrobe = Configuration::getInstance().memSpec->getIntervalOnDataStrobe(command); tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, *payload); } - Controller::sendToDram(command, payload); + sc_time delay = SC_ZERO_TIME; + tlm_phase phase = commandToPhase(command); + + iSocket->nb_transport_fw(*payload, phase, delay); } void ControllerRecordable::recordPhase(tlm_generic_payload &trans, tlm_phase phase, sc_time delay) @@ -78,7 +95,7 @@ void ControllerRecordable::recordPhase(tlm_generic_payload &trans, tlm_phase pha NDEBUG_UNUSED(unsigned bank) = DramExtension::getExtension(trans).getBank().ID(); NDEBUG_UNUSED(unsigned row) = DramExtension::getExtension(trans).getRow().ID(); NDEBUG_UNUSED(unsigned col) = DramExtension::getExtension(trans).getColumn().ID(); - NDEBUG_UNUSED(uint64_t id) = DramExtension::getExtension(trans).getPayloadID(); + NDEBUG_UNUSED(uint64_t id) = DramExtension::getExtension(trans).getChannelPayloadID(); PRINTDEBUGMESSAGE(name(), "Recording " + getPhaseName(phase) + " thread " + std::to_string(thr) + " channel " + std::to_string(ch) + " bank group " + std::to_string( @@ -87,3 +104,46 @@ void ControllerRecordable::recordPhase(tlm_generic_payload &trans, tlm_phase pha tlmRecorder->recordPhase(trans, phase, recTime); } + +void ControllerRecordable::controllerMethod() +{ + if (Configuration::getInstance().enableWindowing) + { + sc_time timeDiff = sc_time_stamp() - lastTimeCalled; + lastTimeCalled = sc_time_stamp(); + const std::vector &bufferDepth = scheduler->getBufferDepth(); + + for (size_t index = 0; index < slidingAverageBufferDepth.size(); index++) + slidingAverageBufferDepth[index] += bufferDepth[index] * timeDiff; + + if (sc_time_stamp() == nextWindowEventTime) + { + windowEvent.notify(windowSizeTime); + nextWindowEventTime += windowSizeTime; + + for (size_t index = 0; index < slidingAverageBufferDepth.size(); index++) + { + windowAverageBufferDepth[index] = slidingAverageBufferDepth[index] / windowSizeTime; + slidingAverageBufferDepth[index] = SC_ZERO_TIME; + } + + tlmRecorder->recordBufferDepth(sc_time_stamp().to_seconds(), windowAverageBufferDepth); + + Controller::controllerMethod(); + + uint64_t windowNumberOfTransactionsServed = numberOfTransactionsServed - lastNumberOfTransactionsServed; + lastNumberOfTransactionsServed = numberOfTransactionsServed; + sc_time windowActiveTime = windowNumberOfTransactionsServed * activeTimeMultiplier; + double windowAverageBandwidth = windowActiveTime / windowSizeTime; + tlmRecorder->recordBandwidth(sc_time_stamp().to_seconds(), windowAverageBandwidth); + } + else + { + Controller::controllerMethod(); + } + } + else + { + Controller::controllerMethod(); + } +} diff --git a/DRAMSys/library/src/controller/ControllerRecordable.h b/DRAMSys/library/src/controller/ControllerRecordable.h index e39555f0..acb910f4 100644 --- a/DRAMSys/library/src/controller/ControllerRecordable.h +++ b/DRAMSys/library/src/controller/ControllerRecordable.h @@ -41,8 +41,8 @@ class ControllerRecordable final : public Controller { public: - ControllerRecordable(sc_module_name name, TlmRecorder *tlmRecorder) : - Controller(name), tlmRecorder(tlmRecorder) {} + ControllerRecordable(sc_module_name name, TlmRecorder *tlmRecorder); + virtual ~ControllerRecordable() override {} protected: virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans, @@ -53,9 +53,23 @@ protected: virtual void sendToFrontend(tlm::tlm_generic_payload *, tlm::tlm_phase) override; virtual void sendToDram(Command, tlm::tlm_generic_payload *) override; + virtual void controllerMethod() override; + private: void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time delay); TlmRecorder *tlmRecorder; + + sc_event windowEvent; + sc_time windowSizeTime; + sc_time nextWindowEventTime; + std::vector slidingAverageBufferDepth; + 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; }; #endif // CONTROLLERRECORDABLE_H diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp index a8439903..e2529753 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp @@ -52,11 +52,11 @@ CheckerDDR4::CheckerDDR4() last4Activates = std::vector>(memSpec->numberOfRanks); tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; - tRDWR = memSpec->tRL + tBURST - memSpec->tWL + 2 * memSpec->tCK; - tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL; + 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_R = memSpec->tWL + tBURST + memSpec->tRTRS - memSpec->tRL; + tWRRD_R = memSpec->tWL + tBURST + memSpec->tRTRS - memSpec->tRL + memSpec->tRPRE; tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; tRDPDEN = memSpec->tRL + tBURST + memSpec->tCK; tWRPDEN = memSpec->tWL + tBURST + memSpec->tWR; diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp new file mode 100644 index 00000000..0f57b9a9 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2020, 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 "CheckerDDR5.h" + +CheckerDDR5::CheckerDDR5() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerDDR5", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndDIMMRank = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfDIMMRanks)); + lastScheduledByCommandAndPhysicalRank = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfPhysicalRanks)); + lastScheduledByCommandAndLogicalRank = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfLogicalRanks)); + lastScheduledByCommandAndBankGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfBankGroups)); + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfBanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + // Required for Same Bank Refresh + lastScheduledByCommandAndBankInGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfRanks * memSpec->banksPerGroup)); + + last4ActivatesLogical = std::vector>(memSpec->numberOfLogicalRanks); + last4ActivatesPhysical = std::vector>(memSpec->numberOfPhysicalRanks); + + cmdOffset = memSpec->cmdMode * memSpec->tCK; + + tRD_BURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; + tWR_BURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; + tWTRA = memSpec->tWR - memSpec->tRTP; + tWRRDA = memSpec->tWL + tWR_BURST + tWTRA; + tWRPRE = memSpec->tWL + tWR_BURST + 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) +} + +sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + 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); + + if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RD][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_dlr); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RD][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RDA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_dlr); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RDA][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDRD_ddr); + } + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDA); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WR][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WR][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_WTR_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_WTR_dlr); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WRA][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_ddr); + } + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RD][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RD][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RD][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_RTW_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RDA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_S_RTW_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_RTW_dlr); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::RDA][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_ddr); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WR][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S_WR_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_WR_dlr); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WR][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WR][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S_WR_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_WR_dlr); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != lastScheduledByCommandAndPhysicalRank[Command::WRA][physicalrank.ID()]) + { + if (lastCommandStart == lastScheduledByCommandAndDIMMRank[Command::WRA][dimmrank.ID()]) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_dpr); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRWR_ddr); + } + } + else if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L_slr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_S_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::ACT][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_dlr); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdOffset); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::PREA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdOffset); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRESB][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - cmdOffset); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr - cmdOffset); + + // TODO: No tRFC_dlr and tRFC_dpr between REFA and ACT? + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::REFSB][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr - cmdOffset); + + // TODO: No tRFCsb_dlr between REFSB and ACT? + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFSB][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_slr - cmdOffset); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFSB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_dlr - cmdOffset); + + if (last4ActivatesLogical[logicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesLogical[logicalrank.ID()].front() + + memSpec->tFAW_slr - memSpec->cmdOffset_L); + + if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesPhysical[physicalrank.ID()].front() + + memSpec->tFAW_dlr - memSpec->cmdOffset_L); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PREA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRESB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RD][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RDA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WR][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PREA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + // PRESB tPPD + } + else if (command == Command::PRESB) + { + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RD][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WR][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WRA][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + // PREA tRP + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRESB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::RDA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::PRE][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::PREA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dlr); + + lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr); + + // REFSB tRFCsb_slr/dlr + // PRESB tRP + } + else if (command == Command::REFSB) + { + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L_slr + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WRA][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRE][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + // PREA tRP + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRESB][bankInGroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr); + + // TODO: check this + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dlr); + + // TODO: check this + lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFSB][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFSB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_dlr); + + if (last4ActivatesLogical[logicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesLogical[logicalrank.ID()].front() + + memSpec->tFAW_slr - memSpec->cmdOffset_S); + + if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesPhysical[physicalrank.ID()].front() + + memSpec->tFAW_dlr - memSpec->cmdOffset_S); + } + else + SC_REPORT_FATAL("CheckerDDR5", "Unknown command!"); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->tCK); + + return earliestTimeToStart; +} + +void CheckerDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + 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); + + 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(); + + 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 (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 new file mode 100644 index 00000000..caf04154 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020, 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 CHECKERDDR5_H +#define CHECKERDDR5_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecDDR5.h" +#include "../../configuration/Configuration.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; + +private: + const MemSpecDDR5 *memSpec; + + std::vector> lastScheduledByCommandAndDIMMRank; + std::vector> lastScheduledByCommandAndPhysicalRank; + std::vector> lastScheduledByCommandAndLogicalRank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndBank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + std::vector> lastScheduledByCommandAndBankInGroup; + + std::vector> last4ActivatesPhysical; + std::vector> last4ActivatesLogical; + + sc_time cmdOffset; + + sc_time tRD_BURST; + sc_time tWR_BURST; + sc_time tWTRA; + sc_time tWRRDA; + sc_time tWRPRE; + sc_time tRDAACT; + sc_time tWRAACT; + sc_time tCCD_L_RTW_slr; + sc_time tCCD_S_RTW_slr; + sc_time tCCD_RTW_dlr; + sc_time tRDRD_dpr; + sc_time tRDRD_ddr; + sc_time tRDWR_dpr; + sc_time tRDWR_ddr; + sc_time tCCD_L_WTR_slr; + sc_time tCCD_S_WTR_slr; + sc_time tCCD_WTR_dlr; + sc_time tWRWR_dpr; + sc_time tWRWR_ddr; + sc_time tWRRD_dpr; + sc_time tWRRD_ddr; + sc_time tRDPDEN; + sc_time tWRPDEN; + sc_time tWRAPDEN; +}; + +#endif // CHECKERDDR5_H diff --git a/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.cpp b/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.cpp index 769427d6..819db5c4 100644 --- a/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.cpp +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxOldest.cpp @@ -49,7 +49,7 @@ CommandTuple::Type CmdMuxOldest::selectCommand(ReadyCommands &readyCommands) { if (std::get(*it) == sc_time_stamp()) { - newPayloadID = DramExtension::getPayloadID(std::get(*it)); + newPayloadID = DramExtension::getChannelPayloadID(std::get(*it)); if (newPayloadID < lastPayloadID) { lastPayloadID = newPayloadID; diff --git a/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp index f00f072a..e88b6dd2 100644 --- a/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp @@ -49,7 +49,7 @@ CommandTuple::Type CmdMuxStrict::selectCommand(ReadyCommands &readyCommands) { if (std::get(*it) == sc_time_stamp()) { - newPayloadID = DramExtension::getPayloadID(std::get(*it)); + newPayloadID = DramExtension::getChannelPayloadID(std::get(*it)); if (isCasCommand(std::get(*it))) { if ((newPayloadID < lastPayloadID) && (newPayloadID == nextPayloadID)) diff --git a/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.cpp b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.cpp index f299beef..77615452 100644 --- a/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.cpp +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.cpp @@ -47,7 +47,7 @@ void PowerDownManagerStaggered::triggerEntry() { controllerIdle = true; - if (state == PdmState::Idle) + if (state == State::Idle) entryTriggered = true; } @@ -57,7 +57,7 @@ void PowerDownManagerStaggered::triggerExit() enterSelfRefresh = false; entryTriggered = false; - if (state != PdmState::Idle) + if (state != State::Idle) exitTriggered = true; } @@ -65,7 +65,7 @@ void PowerDownManagerStaggered::triggerInterruption() { entryTriggered = false; - if (state != PdmState::Idle) + if (state != State::Idle) exitTriggered = true; } @@ -81,13 +81,13 @@ sc_time PowerDownManagerStaggered::start() if (exitTriggered) { - if (state == PdmState::ActivePdn) + if (state == State::ActivePdn) nextCommand = Command::PDXA; - else if (state == PdmState::PrechargePdn) + else if (state == State::PrechargePdn) nextCommand = Command::PDXP; - else if (state == PdmState::SelfRefresh) + else if (state == State::SelfRefresh) nextCommand = Command::SREFEX; - else if (state == PdmState::ExtraRefresh) + else if (state == State::ExtraRefresh) nextCommand = Command::REFA; timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, BankGroup(0), Bank(0)); @@ -124,35 +124,35 @@ void PowerDownManagerStaggered::updateState(Command command) activatedBanks = 0; break; case Command::PDEA: - state = PdmState::ActivePdn; + state = State::ActivePdn; entryTriggered = false; break; case Command::PDEP: - state = PdmState::PrechargePdn; + state = State::PrechargePdn; entryTriggered = false; break; case Command::SREFEN: - state = PdmState::SelfRefresh; + state = State::SelfRefresh; entryTriggered = false; enterSelfRefresh = false; break; case Command::PDXA: - state = PdmState::Idle; + state = State::Idle; exitTriggered = false; break; case Command::PDXP: - state = PdmState::Idle; + state = State::Idle; exitTriggered = false; if (controllerIdle) enterSelfRefresh = true; break; case Command::SREFEX: - state = PdmState::ExtraRefresh; + state = State::ExtraRefresh; break; case Command::REFA: - if (state == PdmState::ExtraRefresh) + if (state == State::ExtraRefresh) { - state = PdmState::Idle; + state = State::Idle; exitTriggered = false; } else if (controllerIdle) diff --git a/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.h b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.h index fb5795da..eaa6cf77 100644 --- a/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.h +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManagerStaggered.h @@ -53,7 +53,7 @@ public: virtual sc_time start() override; private: - enum class PdmState {Idle, ActivePdn, PrechargePdn, SelfRefresh, ExtraRefresh} state = PdmState::Idle; + enum class State {Idle, ActivePdn, PrechargePdn, SelfRefresh, ExtraRefresh} state = State::Idle; tlm::tlm_generic_payload powerDownPayload; Rank rank; CheckerIF *checker; diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp index c31a73c7..fc95da43 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp @@ -39,9 +39,9 @@ using namespace tlm; -RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines, +RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachinesOnRank, PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) - : bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) + : bankMachinesOnRank(bankMachinesOnRank), powerDownManager(powerDownManager), rank(rank), checker(checker) { Configuration &config = Configuration::getInstance(); memSpec = config.memSpec; @@ -50,8 +50,9 @@ RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankM refreshPayloads = std::vector(memSpec->banksPerRank); for (unsigned bankID = 0; bankID < memSpec->banksPerRank; bankID++) { - setUpDummy(refreshPayloads[bankID], 0, rank, bankMachines[bankID]->getBankGroup(), bankMachines[bankID]->getBank()); - allBankMachines.push_back(bankMachines[bankID]); + setUpDummy(refreshPayloads[bankID], 0, rank, bankMachinesOnRank[bankID]->getBankGroup(), + bankMachinesOnRank[bankID]->getBank()); + allBankMachines.push_back(bankMachinesOnRank[bankID]); } remainingBankMachines = allBankMachines; currentBankMachine = *remainingBankMachines.begin(); @@ -80,10 +81,10 @@ sc_time RefreshManagerBankwise::start() if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalPB()) { timeForNextTrigger += memSpec->getRefreshIntervalPB(); - state = RmState::Regular; + state = State::Regular; } - if (state == RmState::Regular) + if (state == State::Regular) { bool forcedRefresh = (flexibilityCounter == maxPostponed); bool allBanksBusy = true; @@ -113,7 +114,7 @@ sc_time RefreshManagerBankwise::start() } else { - if (currentBankMachine->getState() == BmState::Activated) + if (currentBankMachine->getState() == BankMachine::State::Activated) nextCommand = Command::PRE; else { @@ -148,13 +149,13 @@ sc_time RefreshManagerBankwise::start() if (allBanksBusy) { - state = RmState::Regular; + state = State::Regular; timeForNextTrigger += memSpec->getRefreshIntervalPB(); return timeForNextTrigger; } else { - if (currentBankMachine->getState() == BmState::Activated) + if (currentBankMachine->getState() == BankMachine::State::Activated) nextCommand = Command::PRE; else nextCommand = Command::REFB; @@ -178,20 +179,20 @@ void RefreshManagerBankwise::updateState(Command command) if (remainingBankMachines.empty()) remainingBankMachines = allBankMachines; - if (state == RmState::Pulledin) + if (state == State::Pulledin) flexibilityCounter--; else - state = RmState::Pulledin; + state = State::Pulledin; if (flexibilityCounter == maxPulledin) { - state = RmState::Regular; + state = State::Regular; timeForNextTrigger += memSpec->getRefreshIntervalPB(); } break; case Command::REFA: // Refresh command after SREFEX - state = RmState::Regular; // TODO: check if this assignment is necessary + state = State::Regular; // TODO: check if this assignment is necessary timeForNextTrigger = sc_time_stamp() + memSpec->getRefreshIntervalPB(); sleeping = false; break; diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h index ba976fc3..ea96c86d 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h @@ -53,7 +53,7 @@ public: virtual void updateState(Command) override; private: - enum class RmState {Regular, Pulledin} state = RmState::Regular; + enum class State {Regular, Pulledin} state = State::Regular; const MemSpec *memSpec; std::vector &bankMachinesOnRank; PowerDownManagerIF *powerDownManager; diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.cpp new file mode 100644 index 00000000..11a59521 --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2020, 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 "RefreshManagerGroupwise.h" +#include "../../configuration/Configuration.h" +#include "../../common/utils.h" +#include "../../common/dramExtensions.h" + +using namespace tlm; + +RefreshManagerGroupwise::RefreshManagerGroupwise(std::vector &bankMachinesOnRank, + PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) + : bankMachinesOnRank(bankMachinesOnRank), powerDownManager(powerDownManager), rank(rank), checker(checker) +{ + Configuration &config = Configuration::getInstance(); + memSpec = config.memSpec; + timeForNextTrigger = memSpec->getRefreshIntervalSB(); + + refreshPayloads = std::vector(memSpec->banksPerGroup); + for (unsigned bankID = 0; bankID < memSpec->banksPerGroup; bankID++) + { + setUpDummy(refreshPayloads[bankID], 0, rank, bankMachinesOnRank[bankID]->getBankGroup(), + bankMachinesOnRank[bankID]->getBank()); + allBankMachines.push_back(std::vector(memSpec->groupsPerRank)); + } + + std::list>::iterator it = allBankMachines.begin(); + for (unsigned bankID = 0; bankID < memSpec->banksPerGroup; bankID++) + { + for (unsigned groupID = 0; groupID < memSpec->groupsPerRank; groupID++) + (*it)[groupID] = bankMachinesOnRank[groupID * memSpec->banksPerGroup + bankID]; + it++; + } + + remainingBankMachines = allBankMachines; + currentIterator = remainingBankMachines.begin(); + + maxPostponed = static_cast(config.refreshMaxPostponed * memSpec->banksPerGroup); + maxPulledin = -static_cast(config.refreshMaxPulledin * memSpec->banksPerGroup); +} + +CommandTuple::Type RefreshManagerGroupwise::getNextCommand() +{ + return CommandTuple::Type + (nextCommand, &refreshPayloads[currentIterator->front()->getBank().ID() + % memSpec->banksPerGroup], timeToSchedule); +} + +sc_time RefreshManagerGroupwise::start() +{ + timeToSchedule = sc_max_time(); + nextCommand = Command::NOP; + + if (sc_time_stamp() >= timeForNextTrigger) + { + powerDownManager->triggerInterruption(); + if (sleeping) + return timeToSchedule; + + if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalSB()) + { + timeForNextTrigger += memSpec->getRefreshIntervalSB(); + state = State::Regular; + } + + if (state == State::Regular) + { + bool forcedRefresh = (flexibilityCounter == maxPostponed); + bool allBanksBusy = true; + + if (!skipSelection) + { + currentIterator = remainingBankMachines.begin(); + for (auto bankIt = remainingBankMachines.begin(); bankIt != remainingBankMachines.end(); bankIt++) + { + bool groupIsBusy = false; + for (auto groupIt : *bankIt) + { + if (!groupIt->isIdle()) + { + groupIsBusy = true; + break; + } + } + if (!groupIsBusy) + { + allBanksBusy = false; + currentIterator = bankIt; + break; + } + } + } + + if (allBanksBusy && !forcedRefresh) + { + flexibilityCounter++; + timeForNextTrigger += memSpec->getRefreshIntervalSB(); + return timeForNextTrigger; + } + else + { + nextCommand = Command::REFSB; + for (auto it : *currentIterator) + { + if (it->getState() == BankMachine::State::Activated) + { + nextCommand = Command::PRESB; + break; + } + } + + if (nextCommand == Command::REFSB && forcedRefresh) + { + for (auto it : *currentIterator) + it->block(); + skipSelection = true; + } + + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + currentIterator->front()->getBankGroup(), currentIterator->front()->getBank()); + return timeToSchedule; + } + } + else // if (state == RmState::Pulledin) + { + bool allBanksBusy = true; + + currentIterator = remainingBankMachines.begin(); + for (auto bankIt = remainingBankMachines.begin(); bankIt != remainingBankMachines.end(); bankIt++) + { + bool groupIsBusy = false; + for (auto groupIt : *bankIt) + { + if (!groupIt->isIdle()) + { + groupIsBusy = true; + break; + } + } + if (!groupIsBusy) + { + allBanksBusy = false; + currentIterator = bankIt; + break; + } + } + + if (allBanksBusy) + { + state = State::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalSB(); + return timeForNextTrigger; + } + else + { + nextCommand = Command::REFSB; + for (auto it : *currentIterator) + { + if (it->getState() == BankMachine::State::Activated) + { + nextCommand = Command::PRESB; + break; + } + } + + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + currentIterator->front()->getBankGroup(), currentIterator->front()->getBank()); + return timeToSchedule; + } + } + } + else + return timeForNextTrigger; +} + +void RefreshManagerGroupwise::updateState(Command command) +{ + switch (command) + { + case Command::REFSB: + skipSelection = false; + remainingBankMachines.erase(currentIterator); + if (remainingBankMachines.empty()) + remainingBankMachines = allBankMachines; + currentIterator = remainingBankMachines.begin(); + + if (state == State::Pulledin) + flexibilityCounter--; + else + state = State::Pulledin; + + if (flexibilityCounter == maxPulledin) + { + state = State::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalSB(); + } + break; + case Command::REFA: + // Refresh command after SREFEX + state = State::Regular; // TODO: check if this assignment is necessary + timeForNextTrigger = sc_time_stamp() + memSpec->getRefreshIntervalSB(); + sleeping = false; + break; + case Command::PDEA: case Command::PDEP: + sleeping = true; + break; + case Command::SREFEN: + sleeping = true; + timeForNextTrigger = sc_max_time(); + break; + case Command::PDXA: case Command::PDXP: + sleeping = false; + break; + default: + break; + } +} diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.h new file mode 100644 index 00000000..e583c81d --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, 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 REFRESHMANAGERGROUPWISE_H +#define REFRESHMANAGERGROUPWISE_H + +#include "RefreshManagerIF.h" +#include "../../configuration/memspec/MemSpec.h" +#include "../BankMachine.h" +#include "../powerdown/PowerDownManagerIF.h" +#include +#include +#include + +class RefreshManagerGroupwise final : public RefreshManagerIF +{ +public: + RefreshManagerGroupwise(std::vector &, PowerDownManagerIF *, Rank, CheckerIF *); + + virtual CommandTuple::Type getNextCommand() override; + virtual sc_time start() override; + virtual void updateState(Command) override; + +private: + enum class State {Regular, Pulledin} state = State::Regular; + const MemSpec *memSpec; + std::vector &bankMachinesOnRank; + PowerDownManagerIF *powerDownManager; + std::vector refreshPayloads; + sc_time timeForNextTrigger = sc_max_time(); + sc_time timeToSchedule = sc_max_time(); + Rank rank; + CheckerIF *checker; + Command nextCommand = Command::NOP; + + std::list> remainingBankMachines; + std::list> allBankMachines; + std::list>::iterator currentIterator; + + int flexibilityCounter = 0; + int maxPostponed = 0; + int maxPulledin = 0; + + bool sleeping = false; + bool skipSelection = false; +}; + +#endif // REFRESHMANAGERGROUPWISE_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp index dd68bb2b..5aaf2d64 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp @@ -39,9 +39,9 @@ using namespace tlm; -RefreshManagerRankwise::RefreshManagerRankwise(std::vector &bankMachines, +RefreshManagerRankwise::RefreshManagerRankwise(std::vector &bankMachinesOnRank, PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) - : bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) + : bankMachinesOnRank(bankMachinesOnRank), powerDownManager(powerDownManager), rank(rank), checker(checker) { Configuration &config = Configuration::getInstance(); memSpec = config.memSpec; @@ -71,10 +71,10 @@ sc_time RefreshManagerRankwise::start() if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalAB()) { timeForNextTrigger += memSpec->getRefreshIntervalAB(); - state = RmState::Regular; + state = State::Regular; } - if (state == RmState::Regular) + if (state == State::Regular) { if (flexibilityCounter == maxPostponed) // forced refresh { @@ -122,7 +122,7 @@ sc_time RefreshManagerRankwise::start() if (controllerBusy) { - state = RmState::Regular; + state = State::Regular; timeForNextTrigger += memSpec->getRefreshIntervalAB(); return timeForNextTrigger; } @@ -155,20 +155,20 @@ void RefreshManagerRankwise::updateState(Command command) if (sleeping) { // Refresh command after SREFEX - state = RmState::Regular; // TODO: check if this assignment is necessary + state = State::Regular; // TODO: check if this assignment is necessary timeForNextTrigger = sc_time_stamp() + memSpec->getRefreshIntervalAB(); sleeping = false; } else { - if (state == RmState::Pulledin) + if (state == State::Pulledin) flexibilityCounter--; else - state = RmState::Pulledin; + state = State::Pulledin; if (flexibilityCounter == maxPulledin) { - state = RmState::Regular; + state = State::Regular; timeForNextTrigger += memSpec->getRefreshIntervalAB(); } } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.h index d1dec3fc..f7e7b859 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.h @@ -51,7 +51,7 @@ public: virtual void updateState(Command) override; private: - enum class RmState {Regular, Pulledin} state = RmState::Regular; + enum class State {Regular, Pulledin} state = State::Regular; const MemSpec *memSpec; std::vector &bankMachinesOnRank; PowerDownManagerIF *powerDownManager; diff --git a/DRAMSys/library/src/controller/respqueue/RespQueueReorder.cpp b/DRAMSys/library/src/controller/respqueue/RespQueueReorder.cpp index d2bf06d2..77118c2f 100644 --- a/DRAMSys/library/src/controller/respqueue/RespQueueReorder.cpp +++ b/DRAMSys/library/src/controller/respqueue/RespQueueReorder.cpp @@ -39,7 +39,7 @@ using namespace tlm; void RespQueueReorder::insertPayload(tlm_generic_payload *payload, sc_time strobeEnd) { - buffer[DramExtension::getPayloadID(payload)] = {payload, strobeEnd}; + buffer[DramExtension::getChannelPayloadID(payload)] = {payload, strobeEnd}; } tlm_generic_payload *RespQueueReorder::nextPayload() diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.cpp b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.cpp new file mode 100644 index 00000000..f1c4f5f0 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, 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 "BufferCounterBankwise.h" +#include "../../common/dramExtensions.h" + +BufferCounterBankwise::BufferCounterBankwise(unsigned requestBufferSize, unsigned numberOfBanks) + : requestBufferSize(requestBufferSize) +{ + numRequestsOnBank = std::vector(numberOfBanks, 0); +} + +bool BufferCounterBankwise::hasBufferSpace() const +{ + return (numRequestsOnBank[lastBankID] < requestBufferSize); +} + +void BufferCounterBankwise::storeRequest(tlm::tlm_generic_payload *payload) +{ + lastBankID = DramExtension::getBank(payload).ID(); + numRequestsOnBank[lastBankID]++; +} + +void BufferCounterBankwise::removeRequest(tlm::tlm_generic_payload *payload) +{ + numRequestsOnBank[DramExtension::getBank(payload).ID()]--; +} + +const std::vector &BufferCounterBankwise::getBufferDepth() const +{ + return numRequestsOnBank; +} diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.h b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.h new file mode 100644 index 00000000..19d3ab43 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020, 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 BUFFERCOUNTERBANKWISE_H +#define BUFFERCOUNTERBANKWISE_H + +#include + +#include "BufferCounterIF.h" + +class BufferCounterBankwise final : public BufferCounterIF +{ +public: + BufferCounterBankwise(unsigned requestBufferSize, unsigned numberOfBanks); + virtual bool hasBufferSpace() const override; + virtual void storeRequest(tlm::tlm_generic_payload *payload) override; + virtual void removeRequest(tlm::tlm_generic_payload *payload) override; + virtual const std::vector &getBufferDepth() const override; + +private: + const unsigned requestBufferSize; + std::vector numRequestsOnBank; + unsigned lastBankID; +}; + +#endif // BUFFERCOUNTERBANKWISE_H diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterIF.h b/DRAMSys/library/src/controller/scheduler/BufferCounterIF.h new file mode 100644 index 00000000..5deab172 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterIF.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020, 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 BUFFERCOUNTERIF_H +#define BUFFERCOUNTERIF_H + +#include + +class BufferCounterIF +{ +public: + virtual ~BufferCounterIF() = default; + virtual bool hasBufferSpace() const = 0; + virtual void storeRequest(tlm::tlm_generic_payload *payload) = 0; + virtual void removeRequest(tlm::tlm_generic_payload *payload) = 0; + virtual const std::vector &getBufferDepth() const = 0; +}; + +#endif // BUFFERCOUNTERIF_H diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.cpp b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.cpp new file mode 100644 index 00000000..a43b1241 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020, 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 "BufferCounterReadWrite.h" + +BufferCounterReadWrite::BufferCounterReadWrite(unsigned requestBufferSize) + : requestBufferSize(requestBufferSize) +{ + numReadWriteRequests = std::vector(2); +} + +bool BufferCounterReadWrite::hasBufferSpace() const +{ + return (numReadWriteRequests[0] < requestBufferSize && numReadWriteRequests[1] < requestBufferSize); +} + +void BufferCounterReadWrite::storeRequest(tlm::tlm_generic_payload *payload) +{ + if (payload->is_read()) + numReadWriteRequests[0]++; + else + numReadWriteRequests[1]++; +} + +void BufferCounterReadWrite::removeRequest(tlm::tlm_generic_payload *payload) +{ + if (payload->is_read()) + numReadWriteRequests[0]--; + else + numReadWriteRequests[1]--; +} + +const std::vector &BufferCounterReadWrite::getBufferDepth() const +{ + return numReadWriteRequests; +} diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.h b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.h new file mode 100644 index 00000000..a99716b9 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, 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 BUFFERCOUNTERREADWRITE_H +#define BUFFERCOUNTERREADWRITE_H + +#include "BufferCounterIF.h" + +class BufferCounterReadWrite final : public BufferCounterIF +{ +public: + BufferCounterReadWrite(unsigned requestBufferSize); + virtual bool hasBufferSpace() const override; + virtual void storeRequest(tlm::tlm_generic_payload *payload) override; + virtual void removeRequest(tlm::tlm_generic_payload *payload) override; + virtual const std::vector &getBufferDepth() const override; + +private: + const unsigned requestBufferSize; + std::vector numReadWriteRequests; +}; + +#endif // BUFFERCOUNTERREADWRITE_H diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterShared.cpp b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.cpp new file mode 100644 index 00000000..459a0078 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, 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 "BufferCounterShared.h" + +BufferCounterShared::BufferCounterShared(unsigned requestBufferSize) + : requestBufferSize(requestBufferSize) +{ + numRequests = std::vector(1); +} + +bool BufferCounterShared::hasBufferSpace() const +{ + return (numRequests[0] < requestBufferSize); +} + +void BufferCounterShared::storeRequest(tlm::tlm_generic_payload *) +{ + numRequests[0]++; +} + +void BufferCounterShared::removeRequest(tlm::tlm_generic_payload *) +{ + numRequests[0]--; +} + +const std::vector &BufferCounterShared::getBufferDepth() const +{ + return numRequests; +} diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterShared.h b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.h new file mode 100644 index 00000000..aefd20ad --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, 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 BUFFERCOUNTERSHARED_H +#define BUFFERCOUNTERSHARED_H + +#include "BufferCounterIF.h" + +class BufferCounterShared final : public BufferCounterIF +{ +public: + BufferCounterShared(unsigned requestBufferSize); + virtual bool hasBufferSpace() const override; + virtual void storeRequest(tlm::tlm_generic_payload *payload) override; + virtual void removeRequest(tlm::tlm_generic_payload *payload) override; + virtual const std::vector &getBufferDepth() const override; + +private: + const unsigned requestBufferSize; + std::vector numRequests; +}; + +#endif // BUFFERCOUNTERSHARED_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp index f90c1c95..90d38301 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp @@ -34,36 +34,48 @@ #include "SchedulerFifo.h" #include "../../configuration/Configuration.h" +#include "BufferCounterBankwise.h" +#include "BufferCounterReadWrite.h" +#include "BufferCounterShared.h" using namespace tlm; SchedulerFifo::SchedulerFifo() { - buffer = std::vector> - (Configuration::getInstance().memSpec->numberOfBanks); - requestBufferSize = Configuration::getInstance().requestBufferSize; + Configuration &config = Configuration::getInstance(); + buffer = std::vector>(config.memSpec->numberOfBanks); + + if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise) + bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->numberOfBanks); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite) + bufferCounter = new BufferCounterReadWrite(config.requestBufferSize); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared) + bufferCounter = new BufferCounterShared(config.requestBufferSize); } -bool SchedulerFifo::hasBufferSpace() +SchedulerFifo::~SchedulerFifo() { - if (buffer[lastBankID].size() < requestBufferSize) - return true; - else - return false; + delete bufferCounter; +} + +bool SchedulerFifo::hasBufferSpace() const +{ + return bufferCounter->hasBufferSpace(); } void SchedulerFifo::storeRequest(tlm_generic_payload *payload) { - lastBankID = DramExtension::getBank(payload).ID(); - buffer[lastBankID].push_back(payload); + buffer[DramExtension::getBank(payload).ID()].push_back(payload); + bufferCounter->storeRequest(payload); } void SchedulerFifo::removeRequest(tlm_generic_payload *payload) { buffer[DramExtension::getBank(payload).ID()].pop_front(); + bufferCounter->removeRequest(payload); } -tlm_generic_payload *SchedulerFifo::getNextRequest(BankMachine *bankMachine) +tlm_generic_payload *SchedulerFifo::getNextRequest(BankMachine *bankMachine) const { unsigned bankID = bankMachine->getBank().ID(); if (!buffer[bankID].empty()) @@ -72,7 +84,7 @@ tlm_generic_payload *SchedulerFifo::getNextRequest(BankMachine *bankMachine) return nullptr; } -bool SchedulerFifo::hasFurtherRowHit(Bank bank, Row row) +bool SchedulerFifo::hasFurtherRowHit(Bank bank, Row row) const { if (buffer[bank.ID()].size() >= 2) { @@ -83,10 +95,15 @@ bool SchedulerFifo::hasFurtherRowHit(Bank bank, Row row) return false; } -bool SchedulerFifo::hasFurtherRequest(Bank bank) +bool SchedulerFifo::hasFurtherRequest(Bank bank) const { if (buffer[bank.ID()].size() >= 2) return true; else return false; } + +const std::vector &SchedulerFifo::getBufferDepth() const +{ + return bufferCounter->getBufferDepth(); +} diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h index aacbb1e8..ae06ac48 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h @@ -38,24 +38,28 @@ #include #include #include + #include "SchedulerIF.h" #include "../../common/dramExtensions.h" #include "../BankMachine.h" +#include "BufferCounterIF.h" -class SchedulerFifo : public SchedulerIF +class SchedulerFifo final : public SchedulerIF { public: SchedulerFifo(); - virtual bool hasBufferSpace() override; + virtual ~SchedulerFifo() override; + virtual bool hasBufferSpace() const override; virtual void storeRequest(tlm::tlm_generic_payload *) override; virtual void removeRequest(tlm::tlm_generic_payload *) override; - virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) override; - virtual bool hasFurtherRowHit(Bank, Row) override; - virtual bool hasFurtherRequest(Bank) override; + virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) const override; + virtual bool hasFurtherRowHit(Bank, Row) const override; + virtual bool hasFurtherRequest(Bank) const override; + virtual const std::vector &getBufferDepth() const override; + private: std::vector> buffer; - unsigned requestBufferSize; - unsigned lastBankID; + BufferCounterIF *bufferCounter; }; #endif // SCHEDULERFIFO_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp index de91e8b4..a15dc6f2 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp @@ -33,53 +33,62 @@ */ #include "SchedulerFrFcfs.h" - #include "../../configuration/Configuration.h" -#include +#include "BufferCounterBankwise.h" +#include "BufferCounterReadWrite.h" +#include "BufferCounterShared.h" using namespace tlm; SchedulerFrFcfs::SchedulerFrFcfs() { - buffer = std::vector> - (Configuration::getInstance().memSpec->numberOfBanks); - requestBufferSize = Configuration::getInstance().requestBufferSize; + Configuration &config = Configuration::getInstance(); + buffer = std::vector>(config.memSpec->numberOfBanks); + + if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise) + bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->numberOfBanks); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite) + bufferCounter = new BufferCounterReadWrite(config.requestBufferSize); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared) + bufferCounter = new BufferCounterShared(config.requestBufferSize); } -bool SchedulerFrFcfs::hasBufferSpace() +SchedulerFrFcfs::~SchedulerFrFcfs() { - if (buffer[lastBankID].size() < requestBufferSize) - return true; - else - return false; + delete bufferCounter; +} + +bool SchedulerFrFcfs::hasBufferSpace() const +{ + return bufferCounter->hasBufferSpace(); } void SchedulerFrFcfs::storeRequest(tlm_generic_payload *payload) { - lastBankID = DramExtension::getBank(payload).ID(); - buffer[lastBankID].push_back(payload); + buffer[DramExtension::getBank(payload).ID()].push_back(payload); + bufferCounter->storeRequest(payload); } void SchedulerFrFcfs::removeRequest(tlm_generic_payload *payload) { + bufferCounter->removeRequest(payload); unsigned bankID = DramExtension::getBank(payload).ID(); for (auto it = buffer[bankID].begin(); it != buffer[bankID].end(); it++) { if (*it == payload) { buffer[bankID].erase(it); - return; + break; } } - SC_REPORT_FATAL("SchedulerFrFcfs", "removeRequest failed!"); } -tlm_generic_payload *SchedulerFrFcfs::getNextRequest(BankMachine *bankMachine) +tlm_generic_payload *SchedulerFrFcfs::getNextRequest(BankMachine *bankMachine) const { unsigned bankID = bankMachine->getBank().ID(); if (!buffer[bankID].empty()) { - if (bankMachine->getState() == BmState::Activated) + if (bankMachine->getState() == BankMachine::State::Activated) { // Search for row hit Row openRow = bankMachine->getOpenRow(); @@ -95,7 +104,7 @@ tlm_generic_payload *SchedulerFrFcfs::getNextRequest(BankMachine *bankMachine) return nullptr; } -bool SchedulerFrFcfs::hasFurtherRowHit(Bank bank, Row row) +bool SchedulerFrFcfs::hasFurtherRowHit(Bank bank, Row row) const { unsigned rowHitCounter = 0; for (auto it = buffer[bank.ID()].begin(); it != buffer[bank.ID()].end(); it++) @@ -110,7 +119,12 @@ bool SchedulerFrFcfs::hasFurtherRowHit(Bank bank, Row row) return false; } -bool SchedulerFrFcfs::hasFurtherRequest(Bank bank) +bool SchedulerFrFcfs::hasFurtherRequest(Bank bank) const { return (buffer[bank.ID()].size() >= 2); } + +const std::vector &SchedulerFrFcfs::getBufferDepth() const +{ + return bufferCounter->getBufferDepth(); +} diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h index 5d5347a4..15633b51 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h @@ -38,24 +38,28 @@ #include #include #include + #include "SchedulerIF.h" #include "../../common/dramExtensions.h" #include "../BankMachine.h" +#include "BufferCounterIF.h" -class SchedulerFrFcfs : public SchedulerIF +class SchedulerFrFcfs final : public SchedulerIF { public: SchedulerFrFcfs(); - virtual bool hasBufferSpace() override; + virtual ~SchedulerFrFcfs() override; + virtual bool hasBufferSpace() const override; virtual void storeRequest(tlm::tlm_generic_payload *) override; virtual void removeRequest(tlm::tlm_generic_payload *) override; - virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) override; - virtual bool hasFurtherRowHit(Bank, Row) override; - virtual bool hasFurtherRequest(Bank) override; + virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) const override; + virtual bool hasFurtherRowHit(Bank, Row) const override; + virtual bool hasFurtherRequest(Bank) const override; + virtual const std::vector &getBufferDepth() const override; + private: std::vector> buffer; - unsigned requestBufferSize; - unsigned lastBankID; + BufferCounterIF *bufferCounter; }; #endif // SCHEDULERFRFCFS_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp index 8af96e96..a1510123 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp @@ -34,32 +34,44 @@ #include "SchedulerFrFcfsGrp.h" #include "../../configuration/Configuration.h" +#include "BufferCounterBankwise.h" +#include "BufferCounterReadWrite.h" +#include "BufferCounterShared.h" using namespace tlm; SchedulerFrFcfsGrp::SchedulerFrFcfsGrp() { - buffer = std::vector> - (Configuration::getInstance().memSpec->numberOfBanks); - requestBufferSize = Configuration::getInstance().requestBufferSize; + Configuration &config = Configuration::getInstance(); + buffer = std::vector>(config.memSpec->numberOfBanks); + + if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise) + bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->numberOfBanks); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite) + bufferCounter = new BufferCounterReadWrite(config.requestBufferSize); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared) + bufferCounter = new BufferCounterShared(config.requestBufferSize); } -bool SchedulerFrFcfsGrp::hasBufferSpace() +SchedulerFrFcfsGrp::~SchedulerFrFcfsGrp() { - if (buffer[lastBankID].size() < requestBufferSize) - return true; - else - return false; + delete bufferCounter; +} + +bool SchedulerFrFcfsGrp::hasBufferSpace() const +{ + return bufferCounter->hasBufferSpace(); } void SchedulerFrFcfsGrp::storeRequest(tlm_generic_payload *payload) { - lastBankID = DramExtension::getBank(payload).ID(); - buffer[lastBankID].push_back(payload); + buffer[DramExtension::getBank(payload).ID()].push_back(payload); + bufferCounter->storeRequest(payload); } void SchedulerFrFcfsGrp::removeRequest(tlm_generic_payload *payload) { + bufferCounter->removeRequest(payload); lastCommand = payload->get_command(); unsigned bankID = DramExtension::getBank(payload).ID(); for (auto it = buffer[bankID].begin(); it != buffer[bankID].end(); it++) @@ -67,18 +79,17 @@ void SchedulerFrFcfsGrp::removeRequest(tlm_generic_payload *payload) if (*it == payload) { buffer[bankID].erase(it); - return; + break; } } - SC_REPORT_FATAL("SchedulerFrFcfs", "removeRequest failed!"); } -tlm_generic_payload *SchedulerFrFcfsGrp::getNextRequest(BankMachine *bankMachine) +tlm_generic_payload *SchedulerFrFcfsGrp::getNextRequest(BankMachine *bankMachine) const { unsigned bankID = bankMachine->getBank().ID(); if (!buffer[bankID].empty()) { - if (bankMachine->getState() == BmState::Activated) + if (bankMachine->getState() == BankMachine::State::Activated) { // Filter all row hits Row openRow = bankMachine->getOpenRow(); @@ -118,7 +129,7 @@ tlm_generic_payload *SchedulerFrFcfsGrp::getNextRequest(BankMachine *bankMachine return nullptr; } -bool SchedulerFrFcfsGrp::hasFurtherRowHit(Bank bank, Row row) +bool SchedulerFrFcfsGrp::hasFurtherRowHit(Bank bank, Row row) const { unsigned rowHitCounter = 0; for (auto it = buffer[bank.ID()].begin(); it != buffer[bank.ID()].end(); it++) @@ -133,10 +144,15 @@ bool SchedulerFrFcfsGrp::hasFurtherRowHit(Bank bank, Row row) return false; } -bool SchedulerFrFcfsGrp::hasFurtherRequest(Bank bank) +bool SchedulerFrFcfsGrp::hasFurtherRequest(Bank bank) const { if (buffer[bank.ID()].size() >= 2) return true; else return false; } + +const std::vector &SchedulerFrFcfsGrp::getBufferDepth() const +{ + return bufferCounter->getBufferDepth(); +} diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h index 34ca4472..b6f67e1c 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h @@ -42,22 +42,25 @@ #include "SchedulerIF.h" #include "../../common/dramExtensions.h" #include "../BankMachine.h" +#include "BufferCounterIF.h" -class SchedulerFrFcfsGrp : public SchedulerIF +class SchedulerFrFcfsGrp final : public SchedulerIF { public: SchedulerFrFcfsGrp(); - virtual bool hasBufferSpace() override; + virtual ~SchedulerFrFcfsGrp() override; + virtual bool hasBufferSpace() const override; virtual void storeRequest(tlm::tlm_generic_payload *) override; virtual void removeRequest(tlm::tlm_generic_payload *) override; - virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) override; - virtual bool hasFurtherRowHit(Bank, Row) override; - virtual bool hasFurtherRequest(Bank) override; + virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) const override; + virtual bool hasFurtherRowHit(Bank, Row) const override; + virtual bool hasFurtherRequest(Bank) const override; + virtual const std::vector &getBufferDepth() const override; + private: std::vector> buffer; - unsigned requestBufferSize; tlm::tlm_command lastCommand = tlm::TLM_READ_COMMAND; - unsigned lastBankID; + BufferCounterIF *bufferCounter; }; #endif // SCHEDULERFRFCFSGRP_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerIF.h b/DRAMSys/library/src/controller/scheduler/SchedulerIF.h index c069a5cb..fbde3fdb 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerIF.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerIF.h @@ -36,22 +36,23 @@ #define SCHEDULERIF_H #include + #include "../../common/dramExtensions.h" #include "../../common/DebugManager.h" -enum class BmState; class BankMachine; class SchedulerIF { public: - virtual ~SchedulerIF() {} - virtual bool hasBufferSpace() = 0; + virtual ~SchedulerIF() = default; + virtual bool hasBufferSpace() const = 0; virtual void storeRequest(tlm::tlm_generic_payload *) = 0; virtual void removeRequest(tlm::tlm_generic_payload *) = 0; - virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) = 0; - virtual bool hasFurtherRowHit(Bank, Row) = 0; - virtual bool hasFurtherRequest(Bank) = 0; + virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) const = 0; + virtual bool hasFurtherRowHit(Bank, Row) const = 0; + virtual bool hasFurtherRequest(Bank) const = 0; + virtual const std::vector &getBufferDepth() const = 0; }; #endif // SCHEDULERIF_H diff --git a/DRAMSys/library/src/error/errormodel.cpp b/DRAMSys/library/src/error/errormodel.cpp index 42e1d0d1..0195f194 100644 --- a/DRAMSys/library/src/error/errormodel.cpp +++ b/DRAMSys/library/src/error/errormodel.cpp @@ -36,7 +36,7 @@ #include "errormodel.h" #include "../common/DebugManager.h" #include "../simulation/TemperatureController.h" -#include "../common/AddressDecoder.h" +#include "../simulation/AddressDecoder.h" #include "../common/dramExtensions.h" #include @@ -51,7 +51,7 @@ void errorModel::init() // Get Configuration parameters: burstLenght = Configuration::getInstance().memSpec->burstLength; numberOfColumns = Configuration::getInstance().memSpec->numberOfColumns; - bytesPerColumn = std::log2(Configuration::getInstance().getDataBusWidth()); + bytesPerColumn = std::log2(Configuration::getInstance().memSpec->dataBusWidth); // Adjust number of bytes per column dynamically to the selected ecc controller bytesPerColumn = Configuration::getInstance().adjustNumBytesAfterECC( diff --git a/DRAMSys/library/src/error/errormodel.h b/DRAMSys/library/src/error/errormodel.h index 99598d9c..99fdd034 100644 --- a/DRAMSys/library/src/error/errormodel.h +++ b/DRAMSys/library/src/error/errormodel.h @@ -40,7 +40,7 @@ #include #include #include "../configuration/Configuration.h" -#include "../common/AddressDecoder.h" +#include "../simulation/AddressDecoder.h" #include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" class errorModel : public sc_module diff --git a/DRAMSys/library/src/common/AddressDecoder.cpp b/DRAMSys/library/src/simulation/AddressDecoder.cpp similarity index 99% rename from DRAMSys/library/src/common/AddressDecoder.cpp rename to DRAMSys/library/src/simulation/AddressDecoder.cpp index b6c9cdd4..f4bf0400 100644 --- a/DRAMSys/library/src/common/AddressDecoder.cpp +++ b/DRAMSys/library/src/simulation/AddressDecoder.cpp @@ -39,7 +39,7 @@ #include #include "AddressDecoder.h" -#include "utils.h" +#include "../common/utils.h" #include "../configuration/Configuration.h" using json = nlohmann::json; diff --git a/DRAMSys/library/src/common/AddressDecoder.h b/DRAMSys/library/src/simulation/AddressDecoder.h similarity index 100% rename from DRAMSys/library/src/common/AddressDecoder.h rename to DRAMSys/library/src/simulation/AddressDecoder.h diff --git a/DRAMSys/library/src/simulation/Arbiter.cpp b/DRAMSys/library/src/simulation/Arbiter.cpp index 8ed91d8e..3b87fa98 100644 --- a/DRAMSys/library/src/simulation/Arbiter.cpp +++ b/DRAMSys/library/src/simulation/Arbiter.cpp @@ -33,65 +33,110 @@ * Robert Gernhardt * Matthias Jung * Eder F. Zulian + * Lukas Steiner */ #include "Arbiter.h" -#include "../common/AddressDecoder.h" +#include "AddressDecoder.h" #include "../configuration/Configuration.h" using namespace tlm; Arbiter::Arbiter(sc_module_name name, std::string pathToAddressMapping) : - sc_module(name), payloadEventQueue(this, &Arbiter::peqCallback) + sc_module(name), payloadEventQueue(this, &Arbiter::peqCallback), + maxActiveTransactions(Configuration::getInstance().maxActiveTransactions), + tCK(Configuration::getInstance().memSpec->tCK) { - // The arbiter communicates with one or more memory unity through one or more sockets (one or more memory channels). - // Each of the arbiter's initiator sockets is bound to a memory controller's target socket. - // Anytime an transaction comes from a memory unity to the arbiter the "bw" callback is called. iSocket.register_nb_transport_bw(this, &Arbiter::nb_transport_bw); - - for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; ++i) - { - channelIsFree.push_back(true); - pendingRequests.push_back(std::queue()); - nextPayloadID.push_back(0); - } - - // One or more devices can accesss all the memory units through the arbiter. - // Devices' initiator sockets are bound to arbiter's target sockets. - // As soon the arbiter receives a request in any of its target sockets it should treat and forward it to the proper memory channel. tSocket.register_nb_transport_fw(this, &Arbiter::nb_transport_fw); - tSocket.register_transport_dbg(this, &Arbiter::transport_dbg); addressDecoder = new AddressDecoder(pathToAddressMapping); addressDecoder->print(); } -// Initiated by initiator side -// This function is called when an arbiter's target socket receives a transaction from a device +ArbiterSimple::ArbiterSimple(sc_module_name name, std::string pathToAddressMapping) : + Arbiter(name, pathToAddressMapping) {} + +ArbiterFifo::ArbiterFifo(sc_module_name name, std::string pathToAddressMapping) : + Arbiter(name, pathToAddressMapping) {} + +ArbiterReorder::ArbiterReorder(sc_module_name name, std::string pathToAddressMapping) : + Arbiter(name, pathToAddressMapping) {} + +Arbiter::~Arbiter() +{ + delete addressDecoder; +} + +void Arbiter::end_of_elaboration() +{ + for (unsigned i = 0; i < tSocket.size(); i++) // initiator side + { + threadIsBusy.push_back(false); + nextThreadPayloadIDToAppend.push_back(0); + activeTransactions.push_back(0); + outstandingEndReq.push_back(nullptr); + } + + for (unsigned i = 0; i < iSocket.size(); i++) // channel side + { + channelIsBusy.push_back(false); + pendingRequests.push_back(std::queue()); + nextChannelPayloadIDToAppend.push_back(0); + } +} + +void ArbiterSimple::end_of_elaboration() +{ + Arbiter::end_of_elaboration(); + + for (unsigned i = 0; i < tSocket.size(); i++) // initiator side + pendingResponses.push_back(std::queue()); +} + +void ArbiterFifo::end_of_elaboration() +{ + Arbiter::end_of_elaboration(); + + for (unsigned i = 0; i < tSocket.size(); i++) // initiator side + pendingResponses.push_back(std::queue()); +} + +void ArbiterReorder::end_of_elaboration() +{ + Arbiter::end_of_elaboration(); + + for (unsigned i = 0; i < tSocket.size(); i++) // initiator side + { + pendingResponses.push_back(std::set()); + nextThreadPayloadIDToReturn.push_back(0); + } +} + 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) / Configuration::getInstance().memSpec->tCK) - * Configuration::getInstance().memSpec->tCK - sc_time_stamp(); + sc_time notDelay = std::ceil((sc_time_stamp() + fwDelay) / tCK) + * tCK - sc_time_stamp(); if (phase == BEGIN_REQ) { // TODO: do not adjust address permanently // adjust address offset: - payload.set_address(payload.get_address() - - Configuration::getInstance().addressOffset); + uint64_t adjustedAddress = payload.get_address() - Configuration::getInstance().addressOffset; + payload.set_address(adjustedAddress); - // In the begin request phase the socket ID is appended to the payload. - // It will extracted from the payload and used later. - appendDramExtension(id, payload, fwDelay); + DecodedAddress decodedAddress = addressDecoder->decodeAddress(adjustedAddress); + DramExtension::setExtension(payload, Thread(static_cast(id)), + 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.acquire(); } else if (phase == END_RESP) - { - // TODO: why one additional cycle??? - notDelay += Configuration::getInstance().memSpec->tCK; - } + notDelay += tCK; PRINTDEBUGMESSAGE(name(), "[fw] " + getPhaseName(phase) + " notification in " + notDelay.to_string()); @@ -99,14 +144,9 @@ tlm_sync_enum Arbiter::nb_transport_fw(int id, tlm_generic_payload &payload, return TLM_ACCEPTED; } -// Initiated by dram side -// This function is called when an arbiter's initiator socket receives a transaction from a memory controller -tlm_sync_enum Arbiter::nb_transport_bw(int channelId, tlm_generic_payload &payload, +tlm_sync_enum Arbiter::nb_transport_bw(int, tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay) { - // Check channel ID - assert(static_cast(channelId) == DramExtension::getExtension(payload).getChannel().ID()); - PRINTDEBUGMESSAGE(name(), "[bw] " + getPhaseName(phase) + " notification in " + bwDelay.to_string()); payloadEventQueue.notify(payload, phase, bwDelay); @@ -115,7 +155,6 @@ tlm_sync_enum Arbiter::nb_transport_bw(int channelId, tlm_generic_payload &paylo unsigned int Arbiter::transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans) { - // adjust address offset: trans.set_address(trans.get_address() - Configuration::getInstance().addressOffset); @@ -123,121 +162,331 @@ unsigned int Arbiter::transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans) return iSocket[static_cast(decodedAddress.channel)]->transport_dbg(trans); } -void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase) +void ArbiterSimple::peqCallback(tlm_generic_payload &cbPayload, const tlm_phase &cbPhase) { - unsigned int threadId = DramExtension::getExtension(payload).getThread().ID(); - unsigned int channelId = DramExtension::getExtension(payload).getChannel().ID(); + unsigned int threadId = DramExtension::getExtension(cbPayload).getThread().ID(); + unsigned int channelId = DramExtension::getExtension(cbPayload).getChannel().ID(); - // Check the valid range of thread ID and channel Id - // TODO: thread ID not checked - assert(channelId < Configuration::getInstance().memSpec->numberOfChannels); - - // Phases initiated by the intiator side from arbiter's point of view (devices performing memory requests to the arbiter) - if (phase == BEGIN_REQ) + if (cbPhase == BEGIN_REQ) // from initiator { - if (channelIsFree[channelId]) + GenerationExtension::setExtension(cbPayload, sc_time_stamp()); + DramExtension::setPayloadIDs(cbPayload, + nextThreadPayloadIDToAppend[threadId]++, nextChannelPayloadIDToAppend[channelId]++); + + if (!channelIsBusy[channelId]) { - // This channel was available. Forward the new transaction to the memory controller. - channelIsFree[channelId] = false; + channelIsBusy[channelId] = true; + tlm_phase tPhase = BEGIN_REQ; sc_time tDelay = SC_ZERO_TIME; - iSocket[static_cast(channelId)]->nb_transport_fw(payload, tPhase, tDelay); - // TODO: early completion of channel controller!!! + iSocket[static_cast(channelId)]->nb_transport_fw(cbPayload, tPhase, tDelay); } else - { - // This channel is busy. Enqueue the new transaction which phase is BEGIN_REQ. - pendingRequests[channelId].push(&payload); - } + pendingRequests[channelId].push(&cbPayload); } - // Phases initiated by the target side from arbiter's point of view (memory side) - else if (phase == END_REQ) + else if (cbPhase == END_REQ) // from target { - channelIsFree[channelId] = true; + { + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + tSocket[static_cast(threadId)]->nb_transport_bw(cbPayload, tPhase, tDelay); + } - // The arbiter receives a transaction which phase is END_REQ from memory controller and forwards it to the requester device. - tlm_phase tPhase = END_REQ; - sc_time tDelay = SC_ZERO_TIME; - tlm_sync_enum response = tSocket[static_cast(threadId)]->nb_transport_bw(payload, tPhase, tDelay); - - // This channel is now free! Dispatch a new transaction (phase is BEGIN_REQ) from the queue, if any. Send it to the memory controller. if (!pendingRequests[channelId].empty()) { - // Send ONE of the enqueued new transactions (phase is BEGIN_REQ) through this channel. - tlm_generic_payload &payloadToSend = *pendingRequests[channelId].front(); + tlm_generic_payload &tPayload = *pendingRequests[channelId].front(); pendingRequests[channelId].pop(); tlm_phase tPhase = BEGIN_REQ; sc_time tDelay = SC_ZERO_TIME; - iSocket[static_cast(channelId)]->nb_transport_fw(payloadToSend, tPhase, tDelay); - // TODO: early completion of channel controller - // Mark the channel as busy again. - channelIsFree[channelId] = false; + iSocket[static_cast(channelId)]->nb_transport_fw(tPayload, tPhase, tDelay); } + else + channelIsBusy[channelId] = false; } - else if (phase == BEGIN_RESP) + else if (cbPhase == BEGIN_RESP) // from memory controller { - // The arbiter receives a transaction in BEGIN_RESP phase - // (that came from the memory side) and forwards it to the requester - // device - if (pendingResponses[threadId].empty()) + if (!threadIsBusy[threadId]) { tlm_phase tPhase = BEGIN_RESP; sc_time tDelay = SC_ZERO_TIME; - tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(payload, tPhase, tDelay); - if (returnValue != TLM_ACCEPTED) - { - tPhase = END_RESP; - payloadEventQueue.notify(payload, tPhase, tDelay); - } + tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(cbPayload, tPhase, tDelay); + if (returnValue == TLM_UPDATED) + payloadEventQueue.notify(cbPayload, tPhase, tDelay); + threadIsBusy[threadId] = true; } - - // Enqueue the transaction in BEGIN_RESP phase until the initiator - // device acknowledges it (phase changes to END_RESP). - pendingResponses[threadId].push(&payload); + else + pendingResponses[threadId].push(&cbPayload); } - else if (phase == END_RESP) + else if (cbPhase == END_RESP) // from initiator { - // Send the END_RESP message to the memory { tlm_phase tPhase = END_RESP; sc_time tDelay = SC_ZERO_TIME; - iSocket[static_cast(channelId)]->nb_transport_fw(payload, tPhase, tDelay); + iSocket[static_cast(channelId)]->nb_transport_fw(cbPayload, tPhase, tDelay); } - // Drop one element of the queue of BEGIN_RESP from memory to this device - pendingResponses[threadId].pop(); - payload.release(); + cbPayload.release(); - // Check if there are queued transactoins with phase BEGIN_RESP from memory to this device if (!pendingResponses[threadId].empty()) { - // The queue is not empty. - tlm_generic_payload &payloadToSend = *pendingResponses[threadId].front(); - // Send ONE extra BEGIN_RESP to the device + tlm_generic_payload &tPayload = *pendingResponses[threadId].front(); + pendingResponses[threadId].pop(); tlm_phase tPhase = BEGIN_RESP; sc_time tDelay = SC_ZERO_TIME; - tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(payloadToSend, tPhase, tDelay); - if (returnValue != TLM_ACCEPTED) + tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(tPayload, tPhase, tDelay); + if (returnValue == TLM_UPDATED) + payloadEventQueue.notify(tPayload, tPhase, tDelay); + } + else + threadIsBusy[threadId] = false; + } + else + SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase"); +} + +void ArbiterFifo::peqCallback(tlm_generic_payload &cbPayload, const tlm_phase &cbPhase) +{ + unsigned int threadId = DramExtension::getExtension(cbPayload).getThread().ID(); + unsigned int channelId = DramExtension::getExtension(cbPayload).getChannel().ID(); + + if (cbPhase == BEGIN_REQ) // from initiator + { + GenerationExtension::setExtension(cbPayload, sc_time_stamp()); + DramExtension::setPayloadIDs(cbPayload, + nextThreadPayloadIDToAppend[threadId]++, nextChannelPayloadIDToAppend[channelId]++); + activeTransactions[threadId]++; + + if (activeTransactions[threadId] < maxActiveTransactions) + { + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + tSocket[static_cast(threadId)]->nb_transport_bw(cbPayload, tPhase, tDelay); + } + else + { + outstandingEndReq[threadId] = &cbPayload; + } + + pendingRequests[channelId].push(&cbPayload); + + if (!channelIsBusy[channelId]) + { + channelIsBusy[channelId] = true; + + tlm_generic_payload *tPayload = pendingRequests[channelId].front(); + pendingRequests[channelId].pop(); + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = tCK; + + iSocket[static_cast(channelId)]->nb_transport_fw(*tPayload, tPhase, tDelay); + } + } + else if (cbPhase == END_REQ) // from memory controller + { + if (!pendingRequests[channelId].empty()) + { + tlm_generic_payload &tPayload = *pendingRequests[channelId].front(); + pendingRequests[channelId].pop(); + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = tCK; + iSocket[static_cast(channelId)]->nb_transport_fw(tPayload, tPhase, tDelay); + } + else + { + channelIsBusy[channelId] = false; + } + } + else if (cbPhase == BEGIN_RESP) // from memory controller + { + // TODO: use early completion + { + tlm_phase tPhase = END_RESP; + sc_time tDelay = SC_ZERO_TIME; + iSocket[static_cast(channelId)]->nb_transport_fw(cbPayload, tPhase, tDelay); + } + + pendingResponses[threadId].push(&cbPayload); + + if (!threadIsBusy[threadId]) + { + threadIsBusy[threadId] = true; + + tlm_generic_payload *tPayload = pendingResponses[threadId].front(); + pendingResponses[threadId].pop(); + tlm_phase tPhase = BEGIN_RESP; + sc_time tDelay = tCK; + + tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); + if (returnValue == TLM_UPDATED) + payloadEventQueue.notify(*tPayload, tPhase, tDelay); + + if (activeTransactions[threadId] == maxActiveTransactions) { - tPhase = END_RESP; - payloadEventQueue.notify(payloadToSend, tPhase, tDelay); + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + tPayload = outstandingEndReq[threadId]; + tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); } + + activeTransactions[threadId]--; + } + } + else if (cbPhase == END_RESP) // from initiator + { + cbPayload.release(); + + if (!pendingResponses[threadId].empty()) + { + tlm_generic_payload *tPayload = pendingResponses[threadId].front(); + pendingResponses[threadId].pop(); + tlm_phase tPhase = BEGIN_RESP; + sc_time tDelay = tCK; + tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); + if (returnValue == TLM_UPDATED) + payloadEventQueue.notify(*tPayload, tPhase, tDelay); + + if (activeTransactions[threadId] == maxActiveTransactions) + { + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + tPayload = outstandingEndReq[threadId]; + tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); + } + + activeTransactions[threadId]--; + } + else + { + threadIsBusy[threadId] = false; } } else - SC_REPORT_FATAL(0, - "Payload event queue in arbiter was triggered with unknown phase"); + SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase"); } -void Arbiter::appendDramExtension(int socketId, tlm_generic_payload &payload, sc_time delay) +void ArbiterReorder::peqCallback(tlm_generic_payload &cbPayload, const tlm_phase &cbPhase) { - // Set Generation Extension and DRAM Extension - GenerationExtension::setExtension(&payload, sc_time_stamp() + delay); + unsigned int threadId = DramExtension::getExtension(cbPayload).getThread().ID(); + unsigned int channelId = DramExtension::getExtension(cbPayload).getChannel().ID(); - unsigned int burstlength = payload.get_streaming_width(); - DecodedAddress decodedAddress = addressDecoder->decodeAddress(payload.get_address()); - DramExtension::setExtension(payload, Thread(static_cast(socketId)), - Channel(decodedAddress.channel), Rank(decodedAddress.rank), - BankGroup(decodedAddress.bankgroup), Bank(decodedAddress.bank), - Row(decodedAddress.row), Column(decodedAddress.column), - burstlength, nextPayloadID[decodedAddress.channel]++); + if (cbPhase == BEGIN_REQ) // from initiator + { + GenerationExtension::setExtension(cbPayload, sc_time_stamp()); + DramExtension::setPayloadIDs(cbPayload, + nextThreadPayloadIDToAppend[threadId]++, nextChannelPayloadIDToAppend[channelId]++); + activeTransactions[threadId]++; + + if (activeTransactions[threadId] < maxActiveTransactions) + { + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + tSocket[static_cast(threadId)]->nb_transport_bw(cbPayload, tPhase, tDelay); + } + else + { + outstandingEndReq[threadId] = &cbPayload; + } + + pendingRequests[channelId].push(&cbPayload); + + if (!channelIsBusy[channelId]) + { + channelIsBusy[channelId] = true; + + tlm_generic_payload *tPayload = pendingRequests[channelId].front(); + pendingRequests[channelId].pop(); + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = tCK; + + iSocket[static_cast(channelId)]->nb_transport_fw(*tPayload, tPhase, tDelay); + } + } + else if (cbPhase == END_REQ) // from memory controller + { + if (!pendingRequests[channelId].empty()) + { + tlm_generic_payload &tPayload = *pendingRequests[channelId].front(); + pendingRequests[channelId].pop(); + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = tCK; + iSocket[static_cast(channelId)]->nb_transport_fw(tPayload, tPhase, tDelay); + } + else + { + channelIsBusy[channelId] = false; + } + } + else if (cbPhase == BEGIN_RESP) // from memory controller + { + // TODO: use early completion + { + tlm_phase tPhase = END_RESP; + sc_time tDelay = SC_ZERO_TIME; + iSocket[static_cast(channelId)]->nb_transport_fw(cbPayload, tPhase, tDelay); + } + + pendingResponses[threadId].insert(&cbPayload); + + if (!threadIsBusy[threadId]) + { + tlm_generic_payload *tPayload = *pendingResponses[threadId].begin(); + + if (DramExtension::getThreadPayloadID(tPayload) == nextThreadPayloadIDToReturn[threadId]) + { + nextThreadPayloadIDToReturn[threadId]++; + pendingResponses[threadId].erase(pendingResponses[threadId].begin()); + threadIsBusy[threadId] = true; + + tlm_phase tPhase = BEGIN_RESP; + sc_time tDelay = tCK; + tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); + if (returnValue == TLM_UPDATED) + payloadEventQueue.notify(*tPayload, tPhase, tDelay); + + if (activeTransactions[threadId] == maxActiveTransactions) + { + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + tPayload = outstandingEndReq[threadId]; + tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); + } + + activeTransactions[threadId]--; + } + } + } + else if (cbPhase == END_RESP) // from initiator + { + cbPayload.release(); + + tlm_generic_payload *tPayload = *pendingResponses[threadId].begin(); + + if (!pendingResponses[threadId].empty() && + DramExtension::getThreadPayloadID(tPayload) == nextThreadPayloadIDToReturn[threadId]) + { + nextThreadPayloadIDToReturn[threadId]++; + pendingResponses[threadId].erase(pendingResponses[threadId].begin()); + + tlm_phase tPhase = BEGIN_RESP; + sc_time tDelay = tCK; + tlm_sync_enum returnValue = tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); + if (returnValue == TLM_UPDATED) + payloadEventQueue.notify(*tPayload, tPhase, tDelay); + + if (activeTransactions[threadId] == maxActiveTransactions) + { + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + tPayload = outstandingEndReq[threadId]; + tSocket[static_cast(threadId)]->nb_transport_bw(*tPayload, tPhase, tDelay); + } + + activeTransactions[threadId]--; + } + else + { + threadIsBusy[threadId] = false; + } + } + else + SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase"); } diff --git a/DRAMSys/library/src/simulation/Arbiter.h b/DRAMSys/library/src/simulation/Arbiter.h index c2c83222..c3185e2b 100644 --- a/DRAMSys/library/src/simulation/Arbiter.h +++ b/DRAMSys/library/src/simulation/Arbiter.h @@ -33,6 +33,7 @@ * Robert Gernhardt * Matthias Jung * Eder F. Zulian + * Lukas Steiner */ #ifndef ARBITER_H @@ -43,11 +44,11 @@ #include #include #include -#include +#include #include #include #include -#include "../common/AddressDecoder.h" +#include "AddressDecoder.h" #include "../common/dramExtensions.h" class Arbiter : public sc_module @@ -56,39 +57,85 @@ public: tlm_utils::multi_passthrough_initiator_socket iSocket; tlm_utils::multi_passthrough_target_socket tSocket; + virtual ~Arbiter() override; + +protected: Arbiter(sc_module_name, std::string); SC_HAS_PROCESS(Arbiter); -private: + virtual void end_of_elaboration() override; + AddressDecoder *addressDecoder; tlm_utils::peq_with_cb_and_phase payloadEventQueue; + virtual void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase) = 0; - std::vector channelIsFree; + std::vector threadIsBusy; + std::vector channelIsBusy; - // used to account for the request_accept_delay in the dram controllers - // This is a queue of new transactions. The phase of a new request is BEGIN_REQ. std::vector> pendingRequests; - // used to account for the response_accept_delay in the initiators (traceplayer, core etc.) - // This is a queue of responses comming from the memory side. The phase of these transactions is BEGIN_RESP. - std::unordered_map> pendingResponses; - // Initiated by initiator side - // This function is called when an arbiter's target socket receives a transaction from a device + std::vector nextThreadPayloadIDToAppend; + std::vector nextChannelPayloadIDToAppend; + + std::vector activeTransactions; + const unsigned maxActiveTransactions; + + std::vector outstandingEndReq; + tlm::tlm_sync_enum nb_transport_fw(int id, tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_time &fwDelay); - - // Initiated by dram side - // This function is called when an arbiter's initiator socket receives a transaction from a memory controller - tlm::tlm_sync_enum nb_transport_bw(int channelId, tlm::tlm_generic_payload &payload, + tlm::tlm_sync_enum nb_transport_bw(int, tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_time &bwDelay); - unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans); - void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); + sc_time tCK; +}; - void appendDramExtension(int socketId, tlm::tlm_generic_payload &payload, sc_time delay); - std::vector nextPayloadID; +class ArbiterSimple final : public Arbiter +{ +public: + ArbiterSimple(sc_module_name, std::string); + SC_HAS_PROCESS(ArbiterSimple); + +private: + virtual void end_of_elaboration() override; + virtual void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase) override; + std::vector> pendingResponses; +}; + +class ArbiterFifo final : public Arbiter +{ +public: + ArbiterFifo(sc_module_name, std::string); + SC_HAS_PROCESS(ArbiterFifo); + +private: + virtual void end_of_elaboration() override; + virtual void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase) override; + std::vector> pendingResponses; +}; + +class ArbiterReorder final : public Arbiter +{ +public: + ArbiterReorder(sc_module_name, std::string); + SC_HAS_PROCESS(ArbiterReorder); + +private: + virtual void end_of_elaboration() override; + virtual void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase) override; + + struct ThreadPayloadIDCompare + { + bool operator() (const tlm::tlm_generic_payload *lhs, const tlm::tlm_generic_payload *rhs) const + { + return DramExtension::getThreadPayloadID(lhs) < DramExtension::getThreadPayloadID(rhs); + } + }; + std::vector> pendingResponses; + + std::vector nextThreadPayloadIDToReturn; }; #endif // ARBITER_H diff --git a/DRAMSys/library/src/simulation/DRAMSys.cpp b/DRAMSys/library/src/simulation/DRAMSys.cpp index f890734f..c0d2c123 100644 --- a/DRAMSys/library/src/simulation/DRAMSys.cpp +++ b/DRAMSys/library/src/simulation/DRAMSys.cpp @@ -51,6 +51,7 @@ #include "../error/ecchamming.h" #include "dram/DramDDR3.h" #include "dram/DramDDR4.h" +#include "dram/DramDDR5.h" #include "dram/DramWideIO.h" #include "dram/DramLPDDR4.h" #include "dram/DramWideIO2.h" @@ -80,10 +81,6 @@ DRAMSys::DRAMSys(sc_module_name name, // Read Configuration Setup: nlohmann::json simulationdoc = parseJSON(simulationToRun); - if (simulationdoc["simulation"].empty()) - SC_REPORT_FATAL("SimulationManager", - "Cannot load simulation: simulation node expected"); - Configuration::getInstance().setPathToResources(pathToResources); // Load config and initialize modules @@ -183,24 +180,28 @@ void DRAMSys::instantiateModules(const std::string &pathToResources, // The first call to getInstance() creates the Temperature Controller. // The same instance will be accessed by all other modules. TemperatureController::getInstance(); + Configuration &config = Configuration::getInstance(); // Create new ECC Controller - if (Configuration::getInstance().ECCMode == "Hamming") + if (config.eccMode == Configuration::ECCMode::Hamming) ecc = new ECCHamming("ECCHamming"); - else if (Configuration::getInstance().ECCMode == "Disabled") + else if (config.eccMode == Configuration::ECCMode::Disabled) ecc = nullptr; - else - SC_REPORT_FATAL("DRAMSys", "Unsupported ECC mode"); // Save ECC Controller into the configuration struct to adjust it dynamically - Configuration::getInstance().pECC = ecc; + config.pECC = ecc; // Create arbiter - arbiter = new Arbiter("arbiter", pathToResources + "configs/amconfigs/" + amconfig); + if (config.arbiter == Configuration::Arbiter::Simple) + arbiter = new ArbiterSimple("arbiter", pathToResources + "configs/amconfigs/" + amconfig); + else if (config.arbiter == Configuration::Arbiter::Fifo) + arbiter = new ArbiterFifo("arbiter", pathToResources + "configs/amconfigs/" + amconfig); + else if (config.arbiter == Configuration::Arbiter::Reorder) + arbiter = new ArbiterReorder("arbiter", pathToResources + "configs/amconfigs/" + amconfig); // Create controllers and DRAMs - std::string memoryType = Configuration::getInstance().memSpec->memoryType; - for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++) + MemSpec::MemoryType memoryType = config.memSpec->memoryType; + for (size_t i = 0; i < config.memSpec->numberOfChannels; i++) { std::string str = "controller" + std::to_string(i); @@ -210,26 +211,26 @@ void DRAMSys::instantiateModules(const std::string &pathToResources, str = "dram" + std::to_string(i); Dram *dram; - if (memoryType == "DDR3") + if (memoryType == MemSpec::MemoryType::DDR3) dram = new DramDDR3(str.c_str()); - else if (memoryType == "WIDEIO_SDR") - dram = new DramWideIO(str.c_str()); - else if (memoryType == "DDR4") + else if (memoryType == MemSpec::MemoryType::DDR4) dram = new DramDDR4(str.c_str()); - else if (memoryType == "LPDDR4") + else if (memoryType == MemSpec::MemoryType::DDR5) + dram = new DramDDR5(str.c_str()); + else if (memoryType == MemSpec::MemoryType::WideIO) + dram = new DramWideIO(str.c_str()); + else if (memoryType == MemSpec::MemoryType::LPDDR4) dram = new DramLPDDR4(str.c_str()); - else if (memoryType == "WIDEIO2") + else if (memoryType == MemSpec::MemoryType::WideIO2) dram = new DramWideIO2(str.c_str()); - else if (memoryType == "HBM2") + else if (memoryType == MemSpec::MemoryType::HBM2) dram = new DramHBM2(str.c_str()); - else if (memoryType == "GDDR5") + else if (memoryType == MemSpec::MemoryType::GDDR5) dram = new DramGDDR5(str.c_str()); - else if (memoryType == "GDDR5X") + else if (memoryType == MemSpec::MemoryType::GDDR5X) dram = new DramGDDR5X(str.c_str()); - else if (memoryType == "GDDR6") + else if (memoryType == MemSpec::MemoryType::GDDR6) dram = new DramGDDR6(str.c_str()); - else - SC_REPORT_FATAL("DRAMSys", "Unsupported DRAM type"); drams.push_back(dram); @@ -245,21 +246,21 @@ void DRAMSys::instantiateModules(const std::string &pathToResources, void DRAMSys::bindSockets() { + Configuration &config = Configuration::getInstance(); + // If ECC Controller enabled, put it between Trace and arbiter - if (Configuration::getInstance().ECCMode == "Hamming") + if (config.eccMode == Configuration::ECCMode::Hamming) { assert(ecc != nullptr); tSocket.bind(ecc->t_socket); ecc->i_socket.bind(arbiter->tSocket); } - else if (Configuration::getInstance().ECCMode == "Disabled") + else if (config.eccMode == Configuration::ECCMode::Disabled) tSocket.bind(arbiter->tSocket); - else - SC_REPORT_FATAL("DRAMSys", "Unsupported ECC mode"); - if (Configuration::getInstance().checkTLM2Protocol) + if (config.checkTLM2Protocol) { - for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++) + for (size_t i = 0; i < config.memSpec->numberOfChannels; i++) { arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket); controllersTlmCheckers[i]->initiator_socket.bind(controllers[i]->tSocket); @@ -268,7 +269,7 @@ void DRAMSys::bindSockets() } else { - for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++) + for (size_t i = 0; i < config.memSpec->numberOfChannels; i++) { arbiter->iSocket.bind(controllers[i]->tSocket); controllers[i]->iSocket.bind(drams[i]->tSocket); diff --git a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp index 93b92a33..cdc0caf5 100644 --- a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp +++ b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp @@ -38,6 +38,7 @@ #include "dram/DramRecordable.h" #include "dram/DramDDR3.h" #include "dram/DramDDR4.h" +#include "dram/DramDDR5.h" #include "dram/DramWideIO.h" #include "dram/DramLPDDR4.h" #include "dram/DramWideIO2.h" @@ -87,21 +88,17 @@ DRAMSysRecordable::~DRAMSysRecordable() delete rec; } -void DRAMSysRecordable::setupTlmRecorders(const std::string &traceName, - const std::string &pathToResources) +void DRAMSysRecordable::setupTlmRecorders(const std::string &traceName) { // Create TLM Recorders, one per channel. for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++) { - std::string sqlScriptURI = pathToResources - + std::string("scripts/createTraceDB.sql"); - std::string dbName = traceName + std::string("_ch") + std::to_string(i) + ".tdb"; std::string recorderName = "tlmRecorder" + std::to_string(i); TlmRecorder *tlmRecorder = - new TlmRecorder(recorderName, sqlScriptURI.c_str(), dbName.c_str()); + new TlmRecorder(recorderName, dbName.c_str()); tlmRecorder->recordMCconfig(Configuration::getInstance().mcconfigUri); tlmRecorder->recordMemspec(Configuration::getInstance().memspecUri); @@ -120,27 +117,32 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName, // The same instance will be accessed by all other modules. TemperatureController::getInstance(); + Configuration &config = Configuration::getInstance(); + // Create and properly initialize TLM recorders. // They need to be ready before creating some modules. - setupTlmRecorders(traceName, pathToResources); + setupTlmRecorders(traceName); // Create new ECC Controller - if (Configuration::getInstance().ECCMode == "Hamming") + if (config.eccMode == Configuration::ECCMode::Hamming) ecc = new ECCHamming("ECCHamming"); - else if (Configuration::getInstance().ECCMode == "Disabled") + else if (config.eccMode == Configuration::ECCMode::Disabled) ecc = nullptr; - else - SC_REPORT_FATAL("DRAMSys", "Unsupported ECC mode"); // Save ECC Controller into the configuration struct to adjust it dynamically - Configuration::getInstance().pECC = ecc; + config.pECC = ecc; // Create arbiter - arbiter = new Arbiter("arbiter", pathToResources + "configs/amconfigs/" + amconfig); + if (config.arbiter == Configuration::Arbiter::Simple) + arbiter = new ArbiterSimple("arbiter", pathToResources + "configs/amconfigs/" + amconfig); + else if (config.arbiter == Configuration::Arbiter::Fifo) + arbiter = new ArbiterFifo("arbiter", pathToResources + "configs/amconfigs/" + amconfig); + else if (config.arbiter == Configuration::Arbiter::Reorder) + arbiter = new ArbiterReorder("arbiter", pathToResources + "configs/amconfigs/" + amconfig); // Create controllers and DRAMs - std::string memoryType = Configuration::getInstance().memSpec->memoryType; - for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++) + MemSpec::MemoryType memoryType = config.memSpec->memoryType; + for (size_t i = 0; i < config.memSpec->numberOfChannels; i++) { std::string str = "controller" + std::to_string(i); @@ -150,30 +152,30 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName, str = "dram" + std::to_string(i); Dram *dram; - if (memoryType == "DDR3") + if (memoryType == MemSpec::MemoryType::DDR3) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "WIDEIO_SDR") - dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "DDR4") + else if (memoryType == MemSpec::MemoryType::DDR4) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "LPDDR4") + else if (memoryType == MemSpec::MemoryType::DDR5) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else if (memoryType == MemSpec::MemoryType::WideIO) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else if (memoryType == MemSpec::MemoryType::LPDDR4) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "WIDEIO2") + else if (memoryType == MemSpec::MemoryType::WideIO2) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "HBM2") + else if (memoryType == MemSpec::MemoryType::HBM2) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "GDDR5") + else if (memoryType == MemSpec::MemoryType::GDDR5) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "GDDR5X") + else if (memoryType == MemSpec::MemoryType::GDDR5X) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "GDDR6") + else if (memoryType == MemSpec::MemoryType::GDDR6) dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else - SC_REPORT_FATAL("DRAMSys", "Unsupported DRAM type"); drams.push_back(dram); - if (Configuration::getInstance().checkTLM2Protocol) + if (config.checkTLM2Protocol) { str = "TLMCheckerController" + std::to_string(i); tlm_utils::tlm2_base_protocol_checker<> *controllerTlmChecker = @@ -185,21 +187,21 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName, void DRAMSysRecordable::bindSockets() { + Configuration &config = Configuration::getInstance(); + // If ECC Controller enabled, put it between Trace and arbiter - if (Configuration::getInstance().ECCMode == "Hamming") + if (config.eccMode == Configuration::ECCMode::Hamming) { assert(ecc != nullptr); tSocket.bind(ecc->t_socket); ecc->i_socket.bind(arbiter->tSocket); } - else if (Configuration::getInstance().ECCMode == "Disabled") + else if (config.eccMode == Configuration::ECCMode::Disabled) tSocket.bind(arbiter->tSocket); - else - SC_REPORT_FATAL("DRAMSys", "Unsupported ECC mode"); - if (Configuration::getInstance().checkTLM2Protocol) + if (config.checkTLM2Protocol) { - for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++) + for (size_t i = 0; i < config.memSpec->numberOfChannels; i++) { arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket); controllersTlmCheckers[i]->initiator_socket.bind(controllers[i]->tSocket); @@ -208,7 +210,7 @@ void DRAMSysRecordable::bindSockets() } else { - for (size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++) + for (size_t i = 0; i < config.memSpec->numberOfChannels; i++) { arbiter->iSocket.bind(controllers[i]->tSocket); controllers[i]->iSocket.bind(drams[i]->tSocket); diff --git a/DRAMSys/library/src/simulation/DRAMSysRecordable.h b/DRAMSys/library/src/simulation/DRAMSysRecordable.h index b2f10c8f..6640d40d 100644 --- a/DRAMSys/library/src/simulation/DRAMSysRecordable.h +++ b/DRAMSys/library/src/simulation/DRAMSysRecordable.h @@ -53,8 +53,7 @@ private: // They generate the output databases. std::vector tlmRecorders; - void setupTlmRecorders(const std::string &traceName, - const std::string &pathToResources); + void setupTlmRecorders(const std::string &traceName); void instantiateModules(const std::string &traceName, const std::string &pathToResources, diff --git a/DRAMSys/library/src/simulation/dram/Dram.cpp b/DRAMSys/library/src/simulation/dram/Dram.cpp index 8238195c..b19d34b1 100644 --- a/DRAMSys/library/src/simulation/dram/Dram.cpp +++ b/DRAMSys/library/src/simulation/dram/Dram.cpp @@ -69,19 +69,12 @@ Dram::Dram(sc_module_name name) : sc_module(name), tSocket("socket") // Adjust number of bytes per burst dynamically to the selected ecc controller bytesPerBurst = config.adjustNumBytesAfterECC(bytesPerBurst); - if (config.storeMode == "NoStorage") - storeMode = StorageMode::NoStorage; - else if (config.storeMode == "Store") - storeMode = StorageMode::Store; - else if (config.storeMode == "ErrorModel") - storeMode = StorageMode::ErrorModel; - else - SC_REPORT_FATAL(this->name(), "Unsupported storage mode"); + storeMode = config.storeMode; - uint64_t memorySize = Configuration::getInstance().getSimMemSizeInBytes(); - if (storeMode == StorageMode::Store) + uint64_t memorySize = config.memSpec->getSimMemSizeInBytes(); + if (storeMode == Configuration::StoreMode::Store) { - if (Configuration::getInstance().useMalloc) + if (config.useMalloc) { memory = (unsigned char *)malloc(memorySize); if (!memory) @@ -142,7 +135,7 @@ void Dram::reportPower() tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &) { - assert(phase >= 5 && phase <= 19); + assert(phase >= 5 && phase <= 21); if (Configuration::getInstance().powerAnalysis) { @@ -151,7 +144,7 @@ tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload, DRAMPower->doCommand(phaseToDRAMPowerCommand(phase), bank, cycle); } - if (storeMode == StorageMode::Store) + if (storeMode == Configuration::StoreMode::Store) { if (phase == BEGIN_RD || phase == BEGIN_RDA) { @@ -173,7 +166,7 @@ unsigned int Dram::transport_dbg(tlm_generic_payload &trans) PRINTDEBUGMESSAGE(name(), "transport_dgb"); // TODO: This part is not tested yet, neither with traceplayers nor with GEM5 coupling - if (storeMode == StorageMode::NoStorage) + if (storeMode == Configuration::StoreMode::NoStorage) { SC_REPORT_FATAL("DRAM", "Debug Transport is used in combination with NoStorage"); @@ -190,7 +183,7 @@ unsigned int Dram::transport_dbg(tlm_generic_payload &trans) if (cmd == TLM_READ_COMMAND) { - if (storeMode == StorageMode::Store) + if (storeMode == Configuration::StoreMode::Store) { // Use Storage unsigned char *phyAddr = memory + trans.get_address(); memcpy(ptr, phyAddr, trans.get_data_length()); @@ -203,7 +196,7 @@ unsigned int Dram::transport_dbg(tlm_generic_payload &trans) } else if (cmd == TLM_WRITE_COMMAND) { - if (storeMode == StorageMode::Store) + if (storeMode == Configuration::StoreMode::Store) { // Use Storage unsigned char *phyAddr = memory + trans.get_address(); memcpy(phyAddr, ptr, trans.get_data_length()); diff --git a/DRAMSys/library/src/simulation/dram/Dram.h b/DRAMSys/library/src/simulation/dram/Dram.h index d39d07b6..1d346e7a 100644 --- a/DRAMSys/library/src/simulation/dram/Dram.h +++ b/DRAMSys/library/src/simulation/dram/Dram.h @@ -50,7 +50,7 @@ class Dram : public sc_module { private: - unsigned int bytesPerBurst = Configuration::getInstance().getBytesPerBurst(); + unsigned int bytesPerBurst = Configuration::getInstance().memSpec->bytesPerBurst; bool powerReported = false; protected: @@ -60,7 +60,7 @@ protected: MemSpec *memSpec = Configuration::getInstance().memSpec; // Data Storage: - enum class StorageMode {NoStorage, Store, ErrorModel} storeMode; + Configuration::StoreMode storeMode; unsigned char *memory; diff --git a/DRAMSys/library/src/simulation/dram/DramDDR3.cpp b/DRAMSys/library/src/simulation/dram/DramDDR3.cpp index da039524..66e491df 100644 --- a/DRAMSys/library/src/simulation/dram/DramDDR3.cpp +++ b/DRAMSys/library/src/simulation/dram/DramDDR3.cpp @@ -44,7 +44,7 @@ using namespace DRAMPower; DramDDR3::DramDDR3(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramDDR3", "Error Model not supported for DDR3"); if (Configuration::getInstance().powerAnalysis) @@ -134,7 +134,7 @@ DramDDR3::DramDDR3(sc_module_name name) : Dram(name) MemorySpecification powerSpec; powerSpec.id = memSpec->memoryId; - powerSpec.memoryType = memSpec->memoryType; + powerSpec.memoryType = MemoryType::DDR3; powerSpec.memTimingSpec = memTimingSpec; powerSpec.memPowerSpec = memPowerSpec; powerSpec.memArchSpec = memArchSpec; diff --git a/DRAMSys/library/src/simulation/dram/DramDDR4.cpp b/DRAMSys/library/src/simulation/dram/DramDDR4.cpp index 751f4e30..82255616 100644 --- a/DRAMSys/library/src/simulation/dram/DramDDR4.cpp +++ b/DRAMSys/library/src/simulation/dram/DramDDR4.cpp @@ -44,7 +44,7 @@ using namespace DRAMPower; DramDDR4::DramDDR4(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramDDR4", "Error Model not supported for DDR4"); if (Configuration::getInstance().powerAnalysis) @@ -134,7 +134,7 @@ DramDDR4::DramDDR4(sc_module_name name) : Dram(name) MemorySpecification powerSpec; powerSpec.id = memSpec->memoryId; - powerSpec.memoryType = memSpec->memoryType; + powerSpec.memoryType = MemoryType::DDR4; powerSpec.memTimingSpec = memTimingSpec; powerSpec.memPowerSpec = memPowerSpec; powerSpec.memArchSpec = memArchSpec; diff --git a/DRAMSys/library/src/simulation/dram/DramDDR5.cpp b/DRAMSys/library/src/simulation/dram/DramDDR5.cpp new file mode 100644 index 00000000..8b10e911 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramDDR5.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, 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 "DramDDR5.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecDDR5.h" + +using namespace DRAMPower; + +DramDDR5::DramDDR5(sc_module_name name) : Dram(name) +{ + if (storeMode == Configuration::StoreMode::ErrorModel) + SC_REPORT_FATAL("DramDDR5", "Error Model not supported for DDR5"); + + if (Configuration::getInstance().powerAnalysis) + SC_REPORT_FATAL("DramDDR5", "DRAMPower does not support DDR5"); +} diff --git a/DRAMSys/library/src/simulation/dram/DramDDR5.h b/DRAMSys/library/src/simulation/dram/DramDDR5.h new file mode 100644 index 00000000..14898af1 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramDDR5.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020, 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 DRAMDDR5_H +#define DRAMDDR5_H + +#include +#include "Dram.h" + +class DramDDR5 : public Dram +{ +public: + DramDDR5(sc_module_name); + SC_HAS_PROCESS(DramDDR5); + virtual ~DramDDR5() {} +}; + +#endif // DRAMDDR5_H diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp index 552ff81d..e3fe6014 100644 --- a/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp @@ -42,7 +42,7 @@ DramGDDR5::DramGDDR5(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramGDDR5", "Error Model not supported for GDDR5"); if (Configuration::getInstance().powerAnalysis) diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp index 7db5f265..3c767638 100644 --- a/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp @@ -42,7 +42,7 @@ DramGDDR5X::DramGDDR5X(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramGDDR5X", "Error Model not supported for GDDR5X"); if (Configuration::getInstance().powerAnalysis) diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp index a144c211..24fbed6f 100644 --- a/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp +++ b/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp @@ -42,7 +42,7 @@ DramGDDR6::DramGDDR6(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramGDDR6", "Error Model not supported for GDDR6"); if (Configuration::getInstance().powerAnalysis) diff --git a/DRAMSys/library/src/simulation/dram/DramHBM2.cpp b/DRAMSys/library/src/simulation/dram/DramHBM2.cpp index a803d1a6..1dec6977 100644 --- a/DRAMSys/library/src/simulation/dram/DramHBM2.cpp +++ b/DRAMSys/library/src/simulation/dram/DramHBM2.cpp @@ -42,7 +42,7 @@ DramHBM2::DramHBM2(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramHBM2", "Error Model not supported for HBM2"); if (Configuration::getInstance().powerAnalysis) diff --git a/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp b/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp index de60b0da..503d2774 100644 --- a/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp +++ b/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp @@ -42,7 +42,7 @@ DramLPDDR4::DramLPDDR4(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramLPDDR4", "Error Model not supported for LPDDR4"); if (Configuration::getInstance().powerAnalysis) diff --git a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp index 46bd709f..c8dd5b6a 100644 --- a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp +++ b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp @@ -41,6 +41,7 @@ #include "../../common/utils.h" #include "DramDDR3.h" #include "DramDDR4.h" +#include "DramDDR5.h" #include "DramWideIO.h" #include "DramLPDDR4.h" #include "DramWideIO2.h" @@ -147,6 +148,7 @@ void DramRecordable::powerWindow() template class DramRecordable; template class DramRecordable; +template class DramRecordable; template class DramRecordable; template class DramRecordable; template class DramRecordable; diff --git a/DRAMSys/library/src/simulation/dram/DramWideIO.cpp b/DRAMSys/library/src/simulation/dram/DramWideIO.cpp index eeb78d01..1f9b7a79 100644 --- a/DRAMSys/library/src/simulation/dram/DramWideIO.cpp +++ b/DRAMSys/library/src/simulation/dram/DramWideIO.cpp @@ -135,7 +135,7 @@ DramWideIO::DramWideIO(sc_module_name name) : Dram(name) MemorySpecification powerSpec; powerSpec.id = memSpec->memoryId; - powerSpec.memoryType = memSpec->memoryType; + powerSpec.memoryType = MemoryType::WIDEIO_SDR; powerSpec.memTimingSpec = memTimingSpec; powerSpec.memPowerSpec = memPowerSpec; powerSpec.memArchSpec = memArchSpec; @@ -143,7 +143,7 @@ DramWideIO::DramWideIO(sc_module_name name) : Dram(name) DRAMPower = new libDRAMPower(powerSpec, 0); // For each bank in a channel a error Model is created: - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) { for (unsigned i = 0; i < memSpec->numberOfBanks; i++) { @@ -156,7 +156,7 @@ DramWideIO::DramWideIO(sc_module_name name) : Dram(name) } else { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) { for (unsigned i = 0; i < memSpec->numberOfBanks; i++) { @@ -188,7 +188,7 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload, DRAMPower->doCommand(phaseToDRAMPowerCommand(phase), bank, cycle); } - if (storeMode == StorageMode::Store) + if (storeMode == Configuration::StoreMode::Store) { if (phase == BEGIN_RD || phase == BEGIN_RDA) { @@ -201,7 +201,7 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload, memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); } } - else if (storeMode == StorageMode::ErrorModel) + else if (storeMode == Configuration::StoreMode::ErrorModel) { unsigned bank = DramExtension::getExtension(payload).getBank().ID(); diff --git a/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp b/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp index aba04086..2dbce0cc 100644 --- a/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp +++ b/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp @@ -42,7 +42,7 @@ DramWideIO2::DramWideIO2(sc_module_name name) : Dram(name) { - if (storeMode == StorageMode::ErrorModel) + if (storeMode == Configuration::StoreMode::ErrorModel) SC_REPORT_FATAL("DramWideIO2", "Error Model not supported for WideIO2"); if (Configuration::getInstance().powerAnalysis) diff --git a/DRAMSys/simulator/MemoryManager.cpp b/DRAMSys/simulator/MemoryManager.cpp index 361b3f68..bfb64e82 100644 --- a/DRAMSys/simulator/MemoryManager.cpp +++ b/DRAMSys/simulator/MemoryManager.cpp @@ -44,7 +44,7 @@ using namespace tlm; MemoryManager::MemoryManager() : numberOfAllocations(0), numberOfFrees(0) { - if (Configuration::getInstance().storeMode == "NoStorage") + if (Configuration::getInstance().storeMode == Configuration::StoreMode::NoStorage) storageEnabled = false; else storageEnabled = true; @@ -80,7 +80,7 @@ tlm_generic_payload *MemoryManager::allocate() if (storageEnabled) { // Allocate a data buffer and initialize it with zeroes: - unsigned int dataLength = Configuration::getInstance().getBytesPerBurst(); + unsigned int dataLength = Configuration::getInstance().memSpec->bytesPerBurst; unsigned char *data = new unsigned char[dataLength]; std::fill(data, data + dataLength, 0); payload->set_data_ptr(data); diff --git a/DRAMSys/simulator/StlPlayer.cpp b/DRAMSys/simulator/StlPlayer.cpp index 4aa918ec..6c2ea4fb 100644 --- a/DRAMSys/simulator/StlPlayer.cpp +++ b/DRAMSys/simulator/StlPlayer.cpp @@ -52,11 +52,11 @@ StlPlayer::StlPlayer(sc_module_name name, relative(relative) { if (!file.is_open()) - SC_REPORT_FATAL(0, (std::string("Could not open trace ") + pathToTrace).c_str()); + SC_REPORT_FATAL("StlPlayer", (std::string("Could not open trace ") + pathToTrace).c_str()); this->playerClk = playerClk; burstlength = Configuration::getInstance().memSpec->burstLength; - dataLength = Configuration::getInstance().getBytesPerBurst(); + dataLength = Configuration::getInstance().memSpec->bytesPerBurst; lineCnt = 0; currentBuffer->reserve(lineBufferSize); @@ -80,7 +80,7 @@ void StlPlayer::nextPayload() if (lineIterator == currentBuffer->cend()) { // The file is empty. Nothing more to do. - this->finish(); + finished = true; return; } } @@ -125,8 +125,9 @@ void StlPlayer::parseTraceFile() // Get a new line from the input file. std::getline(file, line); lineCnt++; - // If the line starts with '#' (commented lines) the transaction is ignored. - if (line.empty() || line.at(0) == '#') + + // If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is ignored. + if (line.size() <= 1 || line.at(0) == '#') continue; parsedLines++; @@ -160,9 +161,9 @@ void StlPlayer::parseTraceFile() lineCnt) + ").").c_str()); if (command == "read") - content.cmd = tlm::TLM_READ_COMMAND; + content.cmd = TLM_READ_COMMAND; else if (command == "write") - content.cmd = tlm::TLM_WRITE_COMMAND; + content.cmd = TLM_WRITE_COMMAND; else SC_REPORT_FATAL("StlPlayer", (std::string("Corrupted tracefile, command ") + command + @@ -177,7 +178,7 @@ void StlPlayer::parseTraceFile() content.addr = std::stoull(address.c_str(), nullptr, 16); // Get the data if necessary. - if (storageEnabled && content.cmd == tlm::TLM_WRITE_COMMAND) + if (storageEnabled && content.cmd == TLM_WRITE_COMMAND) { // The input trace file must provide the data to be stored into the memory. iss >> dataStr; diff --git a/DRAMSys/simulator/StlPlayer.h b/DRAMSys/simulator/StlPlayer.h index 74e4f713..27081d41 100644 --- a/DRAMSys/simulator/StlPlayer.h +++ b/DRAMSys/simulator/StlPlayer.h @@ -73,7 +73,7 @@ private: std::vector::const_iterator swapBuffers(); std::ifstream file; - unsigned int lineCnt; + uint64_t lineCnt; unsigned int burstlength; unsigned int dataLength; diff --git a/DRAMSys/simulator/TracePlayer.cpp b/DRAMSys/simulator/TracePlayer.cpp index 69e8b16a..7514be7e 100644 --- a/DRAMSys/simulator/TracePlayer.cpp +++ b/DRAMSys/simulator/TracePlayer.cpp @@ -49,20 +49,15 @@ TracePlayer::TracePlayer(sc_module_name name, TraceSetup *setup) : SC_METHOD(nextPayload); iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw); - if (Configuration::getInstance().storeMode == "NoStorage") + if (Configuration::getInstance().storeMode == Configuration::StoreMode::NoStorage) storageEnabled = false; else storageEnabled = true; } -void TracePlayer::finish() -{ - finished = true; -} - void TracePlayer::terminate() { - cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl; + std::cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl; setup->tracePlayerTerminates(); } @@ -91,11 +86,11 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload, // If all answers were received: if (finished == true && numberOfTransactions == transactionsReceived) - this->terminate(); + terminate(); } else { - SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase"); + SC_REPORT_FATAL("TracePlayer", "PEQ was triggered with unknown phase"); } } @@ -106,17 +101,29 @@ void TracePlayer::sendToTarget(tlm_generic_payload &payload, const tlm_phase &ph iSocket->nb_transport_fw(payload, TPhase, TDelay); } -unsigned int TracePlayer::getNumberOfLines(std::string pathToTrace) +uint64_t TracePlayer::getNumberOfLines(std::string pathToTrace) { - // Reference: http://stackoverflow.com/questions/3482064/counting-the-number-of-lines-in-a-text-file - ifstream newFile; - newFile.open(pathToTrace); - // new lines will be skipped unless we stop it from happening: - newFile.unsetf(std::ios_base::skipws); - // count the lines with an algorithm specialized for counting: - unsigned int lineCount = std::count(std::istream_iterator(newFile), - std::istream_iterator(), ':'); + std::ifstream file; + file.open(pathToTrace); - newFile.close(); - return lineCount; + if (file.is_open()) + { + uint64_t lineCount = 0; + std::string line; + while (std::getline(file, line)) + { + if (line.size() > 1 && line[0] != '#') + lineCount++; + } + file.close(); + + if (lineCount == 0) + SC_REPORT_FATAL("TracePlayer", "Trace file is empty"); + return lineCount; + } + else + { + SC_REPORT_FATAL("TracePlayer", "Unable to open trace file"); + return 0; + } } diff --git a/DRAMSys/simulator/TracePlayer.h b/DRAMSys/simulator/TracePlayer.h index 998929c9..7fc4df35 100644 --- a/DRAMSys/simulator/TracePlayer.h +++ b/DRAMSys/simulator/TracePlayer.h @@ -57,25 +57,24 @@ public: TracePlayer(sc_module_name name, TraceSetup *setup); SC_HAS_PROCESS(TracePlayer); virtual void nextPayload() = 0; - unsigned int getNumberOfLines(std::string pathToTrace); + uint64_t getNumberOfLines(std::string pathToTrace); protected: tlm_utils::peq_with_cb_and_phase payloadEventQueue; - void finish(); void terminate(); bool storageEnabled = false; TraceSetup *setup; void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase, const sc_time &delay); - unsigned int numberOfTransactions = 0; - unsigned int transactionsSent = 0; + uint64_t numberOfTransactions = 0; + uint64_t transactionsSent = 0; + bool finished = false; private: tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_time &bwDelay); void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); - unsigned int transactionsReceived = 0; - bool finished = false; + uint64_t transactionsReceived = 0; }; #endif // TRACEPLAYER_H diff --git a/DRAMSys/simulator/TraceSetup.cpp b/DRAMSys/simulator/TraceSetup.cpp index decd5423..871be829 100644 --- a/DRAMSys/simulator/TraceSetup.cpp +++ b/DRAMSys/simulator/TraceSetup.cpp @@ -47,10 +47,12 @@ TraceSetup::TraceSetup(std::string uri, nlohmann::json simulationdoc = parseJSON(uri); if (simulationdoc["simulation"].empty()) - SC_REPORT_FATAL("traceSetup", + SC_REPORT_FATAL("TraceSetup", "Cannot load simulation: simulation node expected"); // Load TracePlayers: + if (simulationdoc["simulation"]["tracesetup"].empty()) + SC_REPORT_FATAL("TraceSetup", "tracesetup is empty"); for (auto it : simulationdoc["simulation"]["tracesetup"].items()) { auto value = it.value(); @@ -60,7 +62,7 @@ TraceSetup::TraceSetup(std::string uri, unsigned int frequencyMHz = value["clkMhz"]; if (frequencyMHz == 0) - SC_REPORT_FATAL("traceSetup", "No Frequency Defined"); + SC_REPORT_FATAL("TraceSetup", "No frequency defined"); else playerClk = sc_time(1.0 / frequencyMHz, SC_US); @@ -121,3 +123,37 @@ tlm_generic_payload *TraceSetup::allocatePayload() { return memoryManager.allocate(); } + +void TraceSetup::loadbar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity) +{ + if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0))) + return; + + float ratio = x / (float) n; + unsigned int c = (ratio * w); + float rest = (ratio * w) - c; + std::cout << std::setw(3) << round(ratio * 100) << "% |"; + for (unsigned int x = 0; x < c; x++) + std::cout << "█"; + + if (rest >= 0 && rest < 0.125f && c != w) + std::cout << " "; + if (rest >= 0.125f && rest < 2 * 0.125f) + std::cout << "▏"; + if (rest >= 2 * 0.125f && rest < 3 * 0.125f) + std::cout << "▎"; + if (rest >= 3 * 0.125f && rest < 4 * 0.125f) + std::cout << "▍"; + if (rest >= 4 * 0.125f && rest < 5 * 0.125f) + std::cout << "▌"; + if (rest >= 5 * 0.125f && rest < 6 * 0.125f) + std::cout << "▋"; + if (rest >= 6 * 0.125f && rest < 7 * 0.125f) + std::cout << "▊"; + if (rest >= 7 * 0.125f && rest < 8 * 0.125f) + std::cout << "▉"; + + for (unsigned int x = c; x < (w - 1); x++) + std::cout << " "; + std::cout << "|\r" << std::flush; +} diff --git a/DRAMSys/simulator/TraceSetup.h b/DRAMSys/simulator/TraceSetup.h index 165c8747..5194c29a 100644 --- a/DRAMSys/simulator/TraceSetup.h +++ b/DRAMSys/simulator/TraceSetup.h @@ -56,10 +56,12 @@ public: private: unsigned int numberOfTracePlayers; - unsigned int totalTransactions = 0; - unsigned int remainingTransactions; + uint64_t totalTransactions = 0; + uint64_t remainingTransactions; unsigned int finishedTracePlayers = 0; MemoryManager memoryManager; + + void loadbar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1); }; #endif // TRACESETUP_H diff --git a/DRAMSys/simulator/main.cpp b/DRAMSys/simulator/main.cpp index 8d26d245..87ef8d35 100644 --- a/DRAMSys/simulator/main.cpp +++ b/DRAMSys/simulator/main.cpp @@ -76,7 +76,7 @@ int sc_main(int argc, char **argv) // Get path of resources: resources = pathOfFile(argv[0]) + std::string("/../../DRAMSys/library/resources/"); - simulationJson = resources + "simulations/ddr3-example.json"; + simulationJson = resources + "simulations/ddr5-example.json"; } // Run with specific config but default resource folders: else if (argc == 2) diff --git a/DRAMSys/tests/DDR4/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json b/DRAMSys/tests/DDR4/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json index 35a1dd8c..960db938 100644 --- a/DRAMSys/tests/DDR4/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json +++ b/DRAMSys/tests/DDR4/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.json @@ -47,11 +47,13 @@ "REFI": 3644, "RFC": 243, "RL": 13, + "RPRE": 1, "RP": 13, "RRD_L": 5, "RRD_S": 4, "RTP": 8, "WL": 12, + "WPRE": 1, "WR": 14, "WTR_L": 7, "WTR_S": 3, diff --git a/DRAMSys/tests/DDR4/scripts/createTraceDB.sql b/DRAMSys/tests/DDR4/scripts/createTraceDB.sql deleted file mode 100644 index 7a127fac..00000000 --- a/DRAMSys/tests/DDR4/scripts/createTraceDB.sql +++ /dev/null @@ -1,94 +0,0 @@ -DROP TABLE IF EXISTS Phases; -DROP TABLE IF EXISTS GeneralInfo; -DROP TABLE IF EXISTS CommandLengths; -DROP TABLE IF EXISTS Comments; -DROP TABLE IF EXISTS ranges; -DROP TABLE IF EXISTS Transactions; -DROP TABLE IF EXISTS DebugMessages; -DROP TABLE IF EXISTS Power; - -CREATE TABLE Phases( - ID INTEGER PRIMARY KEY, - PhaseName TEXT, - PhaseBegin INTEGER, - PhaseEnd INTEGER, - Transact INTEGER -); - -CREATE TABLE GeneralInfo( - NumberOfTransactions INTEGER, - TraceEnd INTEGER, - NumberOfRanks INTEGER, - NumberOfBanks INTEGER, - clk INTEGER, - UnitOfTime TEXT, - MCconfig TEXT, - Memspec TEXT, - Traces TEXT, - WindowSize INTEGER, - FlexibleRefresh INTEGER, - MaxRefBurst INTEGER, - ControllerThread INTEGER -); - -CREATE TABLE CommandLengths( - ACT INTEGER, - PRE INTEGER, - PREA INTEGER, - RD INTEGER, - RDA INTEGER, - WR INTEGER, - WRA INTEGER, - REFA INTEGER, - REFB INTEGER, - PDEA INTEGER, - PDXA INTEGER, - PDEP INTEGER, - PDXP INTEGER, - SREFEN INTEGER, - SREFEX INTEGER -); - -CREATE TABLE Power( - time DOUBLE, - AveragePower DOUBLE -); - - -CREATE TABLE Comments( - Time INTEGER, - Text TEXT -); - -CREATE TABLE DebugMessages( - Time INTEGER, - Message TEXT -); - --- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html) -CREATE VIRTUAL TABLE ranges USING rtree( - id, - begin, end -); - -CREATE TABLE Transactions( - ID INTEGER, - Range INTEGER, - Address INTEGER, - Burstlength INTEGER, - TThread INTEGER, - TChannel INTEGER, - TRank INTEGER, - TBankgroup INTEGER, - TBank INTEGER, - TRow INTEGER, - TColumn INTEGER, - DataStrobeBegin INTEGER, - DataStrobeEnd INTEGER, - TimeOfGeneration INTEGER, - Command TEXT - ); - -CREATE INDEX ranges_index ON Transactions(Range); -CREATE INDEX "phasesTransactions" ON "Phases" ("Transact" ASC); -CREATE INDEX "messageTimes" ON "DebugMessages" ("Time" ASC); diff --git a/DRAMSys/tests/HBM2/scripts/createTraceDB.sql b/DRAMSys/tests/HBM2/scripts/createTraceDB.sql deleted file mode 100644 index 7a127fac..00000000 --- a/DRAMSys/tests/HBM2/scripts/createTraceDB.sql +++ /dev/null @@ -1,94 +0,0 @@ -DROP TABLE IF EXISTS Phases; -DROP TABLE IF EXISTS GeneralInfo; -DROP TABLE IF EXISTS CommandLengths; -DROP TABLE IF EXISTS Comments; -DROP TABLE IF EXISTS ranges; -DROP TABLE IF EXISTS Transactions; -DROP TABLE IF EXISTS DebugMessages; -DROP TABLE IF EXISTS Power; - -CREATE TABLE Phases( - ID INTEGER PRIMARY KEY, - PhaseName TEXT, - PhaseBegin INTEGER, - PhaseEnd INTEGER, - Transact INTEGER -); - -CREATE TABLE GeneralInfo( - NumberOfTransactions INTEGER, - TraceEnd INTEGER, - NumberOfRanks INTEGER, - NumberOfBanks INTEGER, - clk INTEGER, - UnitOfTime TEXT, - MCconfig TEXT, - Memspec TEXT, - Traces TEXT, - WindowSize INTEGER, - FlexibleRefresh INTEGER, - MaxRefBurst INTEGER, - ControllerThread INTEGER -); - -CREATE TABLE CommandLengths( - ACT INTEGER, - PRE INTEGER, - PREA INTEGER, - RD INTEGER, - RDA INTEGER, - WR INTEGER, - WRA INTEGER, - REFA INTEGER, - REFB INTEGER, - PDEA INTEGER, - PDXA INTEGER, - PDEP INTEGER, - PDXP INTEGER, - SREFEN INTEGER, - SREFEX INTEGER -); - -CREATE TABLE Power( - time DOUBLE, - AveragePower DOUBLE -); - - -CREATE TABLE Comments( - Time INTEGER, - Text TEXT -); - -CREATE TABLE DebugMessages( - Time INTEGER, - Message TEXT -); - --- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html) -CREATE VIRTUAL TABLE ranges USING rtree( - id, - begin, end -); - -CREATE TABLE Transactions( - ID INTEGER, - Range INTEGER, - Address INTEGER, - Burstlength INTEGER, - TThread INTEGER, - TChannel INTEGER, - TRank INTEGER, - TBankgroup INTEGER, - TBank INTEGER, - TRow INTEGER, - TColumn INTEGER, - DataStrobeBegin INTEGER, - DataStrobeEnd INTEGER, - TimeOfGeneration INTEGER, - Command TEXT - ); - -CREATE INDEX ranges_index ON Transactions(Range); -CREATE INDEX "phasesTransactions" ON "Phases" ("Transact" ASC); -CREATE INDEX "messageTimes" ON "DebugMessages" ("Time" ASC); diff --git a/DRAMSys/tests/ddr3_multirank/scripts/createTraceDB.sql b/DRAMSys/tests/ddr3_multirank/scripts/createTraceDB.sql deleted file mode 100644 index 7a127fac..00000000 --- a/DRAMSys/tests/ddr3_multirank/scripts/createTraceDB.sql +++ /dev/null @@ -1,94 +0,0 @@ -DROP TABLE IF EXISTS Phases; -DROP TABLE IF EXISTS GeneralInfo; -DROP TABLE IF EXISTS CommandLengths; -DROP TABLE IF EXISTS Comments; -DROP TABLE IF EXISTS ranges; -DROP TABLE IF EXISTS Transactions; -DROP TABLE IF EXISTS DebugMessages; -DROP TABLE IF EXISTS Power; - -CREATE TABLE Phases( - ID INTEGER PRIMARY KEY, - PhaseName TEXT, - PhaseBegin INTEGER, - PhaseEnd INTEGER, - Transact INTEGER -); - -CREATE TABLE GeneralInfo( - NumberOfTransactions INTEGER, - TraceEnd INTEGER, - NumberOfRanks INTEGER, - NumberOfBanks INTEGER, - clk INTEGER, - UnitOfTime TEXT, - MCconfig TEXT, - Memspec TEXT, - Traces TEXT, - WindowSize INTEGER, - FlexibleRefresh INTEGER, - MaxRefBurst INTEGER, - ControllerThread INTEGER -); - -CREATE TABLE CommandLengths( - ACT INTEGER, - PRE INTEGER, - PREA INTEGER, - RD INTEGER, - RDA INTEGER, - WR INTEGER, - WRA INTEGER, - REFA INTEGER, - REFB INTEGER, - PDEA INTEGER, - PDXA INTEGER, - PDEP INTEGER, - PDXP INTEGER, - SREFEN INTEGER, - SREFEX INTEGER -); - -CREATE TABLE Power( - time DOUBLE, - AveragePower DOUBLE -); - - -CREATE TABLE Comments( - Time INTEGER, - Text TEXT -); - -CREATE TABLE DebugMessages( - Time INTEGER, - Message TEXT -); - --- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html) -CREATE VIRTUAL TABLE ranges USING rtree( - id, - begin, end -); - -CREATE TABLE Transactions( - ID INTEGER, - Range INTEGER, - Address INTEGER, - Burstlength INTEGER, - TThread INTEGER, - TChannel INTEGER, - TRank INTEGER, - TBankgroup INTEGER, - TBank INTEGER, - TRow INTEGER, - TColumn INTEGER, - DataStrobeBegin INTEGER, - DataStrobeEnd INTEGER, - TimeOfGeneration INTEGER, - Command TEXT - ); - -CREATE INDEX ranges_index ON Transactions(Range); -CREATE INDEX "phasesTransactions" ON "Phases" ("Transact" ASC); -CREATE INDEX "messageTimes" ON "DebugMessages" ("Time" ASC); diff --git a/DRAMSys/tests/lpddr4/scripts/createTraceDB.sql b/DRAMSys/tests/lpddr4/scripts/createTraceDB.sql deleted file mode 100644 index 7a127fac..00000000 --- a/DRAMSys/tests/lpddr4/scripts/createTraceDB.sql +++ /dev/null @@ -1,94 +0,0 @@ -DROP TABLE IF EXISTS Phases; -DROP TABLE IF EXISTS GeneralInfo; -DROP TABLE IF EXISTS CommandLengths; -DROP TABLE IF EXISTS Comments; -DROP TABLE IF EXISTS ranges; -DROP TABLE IF EXISTS Transactions; -DROP TABLE IF EXISTS DebugMessages; -DROP TABLE IF EXISTS Power; - -CREATE TABLE Phases( - ID INTEGER PRIMARY KEY, - PhaseName TEXT, - PhaseBegin INTEGER, - PhaseEnd INTEGER, - Transact INTEGER -); - -CREATE TABLE GeneralInfo( - NumberOfTransactions INTEGER, - TraceEnd INTEGER, - NumberOfRanks INTEGER, - NumberOfBanks INTEGER, - clk INTEGER, - UnitOfTime TEXT, - MCconfig TEXT, - Memspec TEXT, - Traces TEXT, - WindowSize INTEGER, - FlexibleRefresh INTEGER, - MaxRefBurst INTEGER, - ControllerThread INTEGER -); - -CREATE TABLE CommandLengths( - ACT INTEGER, - PRE INTEGER, - PREA INTEGER, - RD INTEGER, - RDA INTEGER, - WR INTEGER, - WRA INTEGER, - REFA INTEGER, - REFB INTEGER, - PDEA INTEGER, - PDXA INTEGER, - PDEP INTEGER, - PDXP INTEGER, - SREFEN INTEGER, - SREFEX INTEGER -); - -CREATE TABLE Power( - time DOUBLE, - AveragePower DOUBLE -); - - -CREATE TABLE Comments( - Time INTEGER, - Text TEXT -); - -CREATE TABLE DebugMessages( - Time INTEGER, - Message TEXT -); - --- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html) -CREATE VIRTUAL TABLE ranges USING rtree( - id, - begin, end -); - -CREATE TABLE Transactions( - ID INTEGER, - Range INTEGER, - Address INTEGER, - Burstlength INTEGER, - TThread INTEGER, - TChannel INTEGER, - TRank INTEGER, - TBankgroup INTEGER, - TBank INTEGER, - TRow INTEGER, - TColumn INTEGER, - DataStrobeBegin INTEGER, - DataStrobeEnd INTEGER, - TimeOfGeneration INTEGER, - Command TEXT - ); - -CREATE INDEX ranges_index ON Transactions(Range); -CREATE INDEX "phasesTransactions" ON "Phases" ("Transact" ASC); -CREATE INDEX "messageTimes" ON "DebugMessages" ("Time" ASC); diff --git a/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h b/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h index fad3eff2..5db48e37 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h +++ b/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h @@ -38,15 +38,18 @@ struct CommandLengths { + unsigned NOP; + unsigned RD; + unsigned WR; + unsigned RDA; + unsigned WRA; unsigned ACT; unsigned PRE; - unsigned PREA; - unsigned RD; - unsigned RDA; - unsigned WR; - unsigned WRA; - unsigned REFA; unsigned REFB; + unsigned PRESB; + unsigned REFSB; + unsigned PREA; + unsigned REFA; unsigned PDEA; unsigned PDXA; unsigned PDEP; @@ -54,13 +57,16 @@ struct CommandLengths unsigned SREFEN; unsigned SREFEX; - CommandLengths(unsigned ACT, unsigned PRE, unsigned PREA, - unsigned RD, unsigned RDA, unsigned WR, unsigned WRA, - unsigned REFA, unsigned REFB, unsigned PDEA, unsigned PDXA, - unsigned PDEP, unsigned PDXP, unsigned SREFEN, unsigned SREFEX) : - ACT(ACT), PRE(PRE), PREA(PREA), RD(RD), RDA(RDA), WR(WR), WRA(WRA), - REFA(REFA), REFB(REFB), PDEA(PDEA), PDXA(PDXA), - PDEP(PDEP), PDXP(PDXP), SREFEN(SREFEN), SREFEX(SREFEX) {} + CommandLengths(unsigned NOP, unsigned RD, unsigned WR, + unsigned RDA, unsigned WRA, unsigned ACT, + unsigned PRE, unsigned REFB, unsigned PRESB, + unsigned REFSB, unsigned PREA, unsigned REFA, + unsigned PDEA, unsigned PDXA, unsigned PDEP, + unsigned PDXP, unsigned SREFEN, unsigned SREFEX) : + NOP(NOP), RD(RD), WR(WR), RDA(RDA), WRA(WRA), ACT(ACT), PRE(PRE), + REFB(REFB), PRESB(PRESB), REFSB(REFSB), PREA(PREA), REFA(REFA), + PDEA(PDEA), PDXA(PDXA), PDEP(PDEP), PDXP(PDXP), + SREFEN(SREFEN), SREFEX(SREFEX) {} CommandLengths() {} }; diff --git a/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h b/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h index a86b8d62..d201f80d 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h +++ b/DRAMSys/traceAnalyzer/businessObjects/generalinfo.h @@ -40,27 +40,33 @@ #include "timespan.h" #include -struct GeneralInfo { +struct GeneralInfo +{ +public: unsigned int numberOfTransactions; unsigned int numberOfPhases; Timespan span; unsigned int numberOfRanks; + unsigned int numberOfBankgroups; unsigned int numberOfBanks; + unsigned int banksPerRank; + unsigned int groupsPerRank; + unsigned int banksPerGroup; QString description; QString unitOfTime; unsigned int clkPeriod; unsigned int windowSize; unsigned int controllerThread; -public: - GeneralInfo(unsigned int numberOfTransactions, unsigned int numberOfPhases, - Timespan span, unsigned int numberOfRanks, unsigned int numberOfBanks, + GeneralInfo(unsigned int numberOfTransactions, unsigned int numberOfPhases, Timespan span, + unsigned int numberOfRanks, unsigned int numberOfBankgroups, unsigned int numberOfBanks, const QString &description, QString unitOfTime, unsigned int clkPeriod, unsigned int windowSize, unsigned int controllerThread) : - numberOfTransactions(numberOfTransactions) , numberOfPhases(numberOfPhases), - span(span), numberOfRanks(numberOfRanks), numberOfBanks(numberOfBanks), - description(description), unitOfTime(unitOfTime), clkPeriod(clkPeriod), - windowSize(windowSize), controllerThread(controllerThread) {} + numberOfTransactions(numberOfTransactions) , numberOfPhases(numberOfPhases), span(span), + numberOfRanks(numberOfRanks), numberOfBankgroups(numberOfBankgroups), numberOfBanks(numberOfBanks), + banksPerRank(numberOfBanks / numberOfRanks), groupsPerRank(numberOfBankgroups / numberOfRanks), + banksPerGroup(numberOfBanks / numberOfBankgroups), description(description), unitOfTime(unitOfTime), + clkPeriod(clkPeriod), windowSize(windowSize), controllerThread(controllerThread) {} GeneralInfo() {} }; diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp index 1f88cc24..a7d7ef5a 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp @@ -63,23 +63,32 @@ void Phase::draw(QPainter *painter, const QwtScaleMap &xMap, painter->setPen(pen); } - if (!isBankwise()) { + if (getGranularity() == Granularity::Rankwise) + { for (int i = getYVal(drawingProperties); i < (int)(getYVal(drawingProperties) + drawingProperties.banksPerRank); i++) drawPhaseSymbol(span.Begin(), span.End(), i, drawingProperties.drawText, getPhaseSymbol(), painter, xMap, yMap); - } else + } + else if (getGranularity() == Granularity::Groupwise) + { + for (int i = getYVal(drawingProperties); i < (int)(getYVal(drawingProperties) + drawingProperties.banksPerRank); i += drawingProperties.banksPerGroup) + drawPhaseSymbol(span.Begin(), span.End(), i, drawingProperties.drawText, + getPhaseSymbol(), painter, xMap, yMap); + } + else // if (getGranularity() == Granularity::Bankwise) drawPhaseSymbol(span.Begin(), span.End(), getYVal(drawingProperties), drawingProperties.drawText, getPhaseSymbol(), painter, xMap, yMap); - for (Timespan span : spansOnCommandBus) { + for (Timespan span : spansOnCommandBus) + { drawPhaseSymbol(span.Begin(), span.End(), drawingProperties.yValCommandBus, false, PhaseSymbol::Hexagon, painter, xMap, yMap); } - if (spanOnDataBus) { - drawPhaseSymbol(spanOnDataBus->Begin(), spanOnDataBus->End(), - drawingProperties.yValDataBus, false, PhaseSymbol::Hexagon, painter, xMap, - yMap); + if (spanOnDataBus) + { + drawPhaseSymbol(spanOnDataBus->Begin(), spanOnDataBus->End(), drawingProperties.yValDataBus, + false, PhaseSymbol::Hexagon, painter, xMap, yMap); } } @@ -88,7 +97,7 @@ void Phase::drawPhaseSymbol(traceTime begin, traceTime end, double y, const QwtScaleMap &yMap) const { double yVal = yMap.transform(y); - double symbolHeight = yMap.transform(0) - yMap.transform(hexagonHeigth); + double symbolHeight = yMap.transform(0) - yMap.transform(hexagonHeight); if (symbol == PhaseSymbol::Hexagon) { QPoint hexFrom(xMap.transform(begin), yVal); @@ -113,20 +122,23 @@ QColor Phase::getColor(const TraceDrawingProperties &drawingProperties) const break; case ColorGrouping::Thread: return ColorGenerator::getColor(static_cast - (transaction->Thread())); + (transaction->thread)); break; case ColorGrouping::Transaction: default: - return ColorGenerator::getColor(transaction->Id()); + return ColorGenerator::getColor(transaction->id); } } int Phase::getYVal(const TraceDrawingProperties &drawingProperties) const { - if (isBankwise()) - return transaction->Bank(); - else - return transaction->Rank() * drawingProperties.banksPerRank; + if (getGranularity() == Granularity::Bankwise) + return transaction->bank; + else if (getGranularity() == Granularity::Groupwise) + return transaction->rank * drawingProperties.banksPerRank + + transaction->bank % drawingProperties.banksPerGroup; + else // if (getGranularity() == Granularity::Rankwise) + return transaction->rank * drawingProperties.banksPerRank; } Qt::BrushStyle Phase::getBrushStyle() const @@ -135,18 +147,39 @@ Qt::BrushStyle Phase::getBrushStyle() const } bool Phase::isSelected(traceTime time, double yVal, - const TraceDrawingProperties &drawingproperties) const + const TraceDrawingProperties &drawingProperties) const { - if (span.contains(time) && (!this->isBankwise() - || fabs(yVal - getYVal(drawingproperties)) <= hexagonHeigth)) - return true; - if (spanOnDataBus && spanOnDataBus->contains(time) - && fabs(yVal - drawingproperties.yValDataBus) <= hexagonHeigth) + if (span.contains(time)) + { + if (getGranularity() == Granularity::Bankwise) + { + if (fabs(yVal - getYVal(drawingProperties)) <= hexagonHeight) + return true; + } + else if (getGranularity() == Granularity::Groupwise) + { + for (int offset = 0; offset < drawingProperties.banksPerRank; offset += drawingProperties.banksPerGroup) + { + if (fabs(yVal - (getYVal(drawingProperties) + offset)) <= hexagonHeight) + return true; + } + } + else // if (getGranularity() == Granularity::Rankwise) + { + for (int offset = 0; offset < drawingProperties.banksPerRank; offset++) + { + if (fabs(yVal - (getYVal(drawingProperties) + offset)) <= hexagonHeight) + return true; + } + } + } + + if (spanOnDataBus && spanOnDataBus->contains(time) && fabs(yVal - drawingProperties.yValDataBus) <= hexagonHeight) return true; for (Timespan span : spansOnCommandBus) { if (span.contains(time) - && fabs(yVal - drawingproperties.yValCommandBus) <= hexagonHeigth) + && fabs(yVal - drawingProperties.yValCommandBus) <= hexagonHeight) return true; } diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h index ae5cbc3c..3192aed1 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h @@ -58,7 +58,7 @@ public: std::shared_ptr spanOnDataBus): id(id), span(span), transaction(transaction), spansOnCommandBus(spansOnCommandBus), spanOnDataBus(spanOnDataBus), - hexagonHeigth(0.6), captionPosition(TextPositioning::bottomRight) {} + hexagonHeight(0.6), captionPosition(TextPositioning::bottomRight) {} void draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, bool highlight, @@ -74,10 +74,6 @@ public: return id; } virtual QString Name() const = 0; - virtual bool isBankwise() const - { - return true; - } protected: ID id; @@ -85,7 +81,7 @@ protected: std::shared_ptr transaction; std::vector spansOnCommandBus; std::shared_ptr spanOnDataBus; - double hexagonHeigth; + double hexagonHeight; TextPositioning captionPosition; enum PhaseSymbol {Hexagon, Rect}; @@ -98,6 +94,12 @@ protected: bool drawtext, PhaseSymbol symbol, QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap) const; + enum class Granularity {Bankwise, Groupwise, Rankwise}; + + virtual Granularity getGranularity() const + { + return Granularity::Bankwise; + } }; class REQ : public Phase @@ -172,6 +174,62 @@ protected: } }; +class PRESB : public Phase +{ +public: + using Phase::Phase; +protected: + virtual QString Name() const override + { + return "PRESB"; + } + virtual std::vector getTimesOnCommandBus() const + { + return {span.Begin()}; + } + virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const + override + { + Q_UNUSED(drawingProperties) return getPhaseColor(); + } + virtual QColor getPhaseColor() const override + { + return ColorGenerator::getColor(1); + } + virtual Granularity getGranularity() const override + { + return Granularity::Groupwise; + } +}; + +class PREA : public Phase +{ +public: + using Phase::Phase; +protected: + virtual QString Name() const override + { + return "PREA"; + } + virtual std::vector getTimesOnCommandBus() const + { + return {span.Begin()}; + } + virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const + override + { + Q_UNUSED(drawingProperties) return getPhaseColor(); + } + virtual QColor getPhaseColor() const override + { + return ColorGenerator::getColor(10); + } + virtual Granularity getGranularity() const override + { + return Granularity::Rankwise; + } +}; + class ACTB : public Phase { public: @@ -297,9 +355,9 @@ protected: { return "REFA"; } - virtual bool isBankwise() const override + virtual Granularity getGranularity() const override { - return false; + return Granularity::Rankwise; } }; @@ -314,32 +372,18 @@ protected: } }; - -class PRECHARGE_ALL : public Phase +class REFSB : public AUTO_REFRESH { public: - using Phase::Phase; + using AUTO_REFRESH::AUTO_REFRESH; protected: virtual QString Name() const override { - return "PREA"; + return "REFSB"; } - virtual std::vector getTimesOnCommandBus() const + virtual Granularity getGranularity() const override { - return {span.Begin()}; - } - virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const - override - { - Q_UNUSED(drawingProperties) return getPhaseColor(); - } - virtual QColor getPhaseColor() const override - { - return ColorGenerator::getColor(10); - } - virtual bool isBankwise() const override - { - return false; + return Granularity::Groupwise; } }; @@ -380,9 +424,9 @@ protected: { return "PDNA"; } - virtual bool isBankwise() const override + virtual Granularity getGranularity() const override { - return false; + return Granularity::Rankwise; } }; @@ -423,9 +467,9 @@ protected: { return "PDNP"; } - virtual bool isBankwise() const override + virtual Granularity getGranularity() const override { - return false; + return Granularity::Rankwise; } }; @@ -466,9 +510,9 @@ protected: { return "SREF"; } - virtual bool isBankwise() const override + virtual Granularity getGranularity() const override { - return false; + return Granularity::Rankwise; } }; diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp b/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp index 9156a5d8..8ea561e5 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phasefactory.cpp @@ -68,7 +68,7 @@ shared_ptr PhaseFactory::CreatePhase(ID id, const QString &dbPhaseName, return shared_ptr(new ACT(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.ACT)}, std::shared_ptr())); else if (dbPhaseName == "PREA") - return shared_ptr(new PRECHARGE_ALL(id, span, trans, + return shared_ptr(new PREA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.PREA)}, std::shared_ptr())); else if (dbPhaseName == "REFA") return shared_ptr(new REFA(id, span, trans, @@ -76,18 +76,24 @@ shared_ptr PhaseFactory::CreatePhase(ID id, const QString &dbPhaseName, else if (dbPhaseName == "REFB") return shared_ptr(new REFB(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.REFB)}, std::shared_ptr())); + else if (dbPhaseName == "PRESB") + return shared_ptr(new PRESB(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk * cl.PRESB)}, std::shared_ptr())); + else if (dbPhaseName == "REFSB") + return shared_ptr(new REFSB(id, span, trans, + {Timespan(span.Begin(), span.Begin() + clk * cl.REFSB)}, std::shared_ptr())); else if (dbPhaseName == "RD") return shared_ptr(new RD(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.RD)}, - std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + std::shared_ptr(new Timespan(trans->spanOnDataStrobe)))); else if (dbPhaseName == "RDA") return shared_ptr(new RDA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.RDA)}, - std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + std::shared_ptr(new Timespan(trans->spanOnDataStrobe)))); else if (dbPhaseName == "WR") return shared_ptr(new WR(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.WR)}, - std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + std::shared_ptr(new Timespan(trans->spanOnDataStrobe)))); else if (dbPhaseName == "WRA") return shared_ptr(new WRA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.WRA)}, - std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + std::shared_ptr(new Timespan(trans->spanOnDataStrobe)))); else if (dbPhaseName == "PDNA") return shared_ptr(new PDNA(id, span, trans, {Timespan(span.Begin(), span.Begin() + clk * cl.PDEA), Timespan(span.End() - clk * cl.PDXA, span.End())}, std::shared_ptr())); diff --git a/DRAMSys/traceAnalyzer/businessObjects/transaction.h b/DRAMSys/traceAnalyzer/businessObjects/transaction.h index 723cfc8f..57854bea 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/transaction.h +++ b/DRAMSys/traceAnalyzer/businessObjects/transaction.h @@ -48,14 +48,15 @@ typedef unsigned int ID; class Transaction { private: - unsigned int address, burstlength, thread, channel, rank, - bankgroup, bank, row, column; - Timespan span; - Timespan spanOnDataStrobe; - ID id; std::vector> phases; public: + const unsigned int address, burstlength, thread, channel, rank, + bankgroup, bank, row, column; + const Timespan span; + const Timespan spanOnDataStrobe; + const ID id; + Transaction(ID id, unsigned int address, unsigned int burstlength, unsigned int thread, unsigned int channel, unsigned int rank, unsigned int bankgroup, unsigned int bank, unsigned int row, unsigned int column, @@ -69,54 +70,6 @@ public: bool isSelected(traceTime time, double yVal, const TraceDrawingProperties &drawingproperties) const; - unsigned int Address() const - { - return address; - } - unsigned int Burstlength() const - { - return burstlength; - } - unsigned int Thread() - { - return thread; - } - unsigned int Channel() const - { - return channel; - } - unsigned int Rank() const - { - return rank; - } - unsigned int BankGroup() const - { - return bankgroup; - } - unsigned int Bank() const - { - return bank; - } - unsigned int Row() const - { - return row; - } - unsigned int Column() const - { - return column; - } - ID Id() const - { - return id; - } - const Timespan &Span() const - { - return span; - } - const Timespan &SpanOnDataStrobe() - { - return spanOnDataStrobe; - } const std::vector> &Phases() const { return phases; diff --git a/DRAMSys/traceAnalyzer/data/tracedb.cpp b/DRAMSys/traceAnalyzer/data/tracedb.cpp index d8f177ca..4ef9142b 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.cpp +++ b/DRAMSys/traceAnalyzer/data/tracedb.cpp @@ -238,7 +238,7 @@ ID TraceDB::getTransactionIDFromPhaseID(ID phaseID) GeneralInfo TraceDB::getGeneralInfoFromDB() { QSqlQuery query(database); - query.prepare("SELECT NumberOfTransactions, TraceEnd, NumberOfRanks, NumberOfBanks, Clk, " + query.prepare("SELECT NumberOfTransactions, TraceEnd, NumberOfRanks, NumberOfBankgroups, NumberOfBanks, Clk, " "UnitOfTime, Traces, Memspec, MCconfig, WindowSize, ControllerThread FROM GeneralInfo"); executeQuery(query); @@ -246,16 +246,17 @@ GeneralInfo TraceDB::getGeneralInfoFromDB() unsigned int numberOfTransactions = query.value(0).toInt(); traceTime traceEnd = query.value(1).toLongLong(); unsigned int numberOfRanks = query.value(2).toInt(); - unsigned int numberOfBanks = query.value(3).toInt(); - unsigned int clkPeriod = query.value(4).toInt(); - QString unitOfTime = query.value(5).toString(); + unsigned int numberOfBankgroups = query.value(3).toInt(); + unsigned int numberOfBanks = query.value(4).toInt(); + unsigned int clkPeriod = query.value(5).toInt(); + QString unitOfTime = query.value(6).toString(); unsigned int numberOfPhases = getNumberOfPhases(); - QString traces = "Traces: " + query.value(6).toString(); - QString memspec = "Memspec: " + query.value(7).toString(); - QString mcconfig = "MCconfig: " + query.value(8).toString(); - unsigned int windowSize = query.value(9).toInt(); - unsigned int controllerThread = query.value(10).toUInt(); + QString traces = "Traces: " + query.value(7).toString(); + QString memspec = "Memspec: " + query.value(8).toString(); + QString mcconfig = "MCconfig: " + query.value(9).toString(); + unsigned int windowSize = query.value(10).toInt(); + unsigned int controllerThread = query.value(11).toUInt(); QString description = (traces + "\n"); description += mcconfig + "\n"; @@ -268,8 +269,8 @@ GeneralInfo TraceDB::getGeneralInfoFromDB() description += "Window size:" + QString::number(windowSize) + "\n"; return GeneralInfo(numberOfTransactions, numberOfPhases, Timespan(0, traceEnd), - numberOfRanks, numberOfBanks, description, unitOfTime, - clkPeriod, windowSize, controllerThread); + numberOfRanks, numberOfBankgroups, numberOfBanks, + description, unitOfTime, clkPeriod, windowSize, controllerThread); } else { throw sqlException("Tracefile corrupted. No general info table", this->pathToDB.toStdString()); @@ -284,24 +285,28 @@ CommandLengths TraceDB::getCommandLengthsFromDB() if (query.next()) { - unsigned ACT = query.value(0).toInt(); - unsigned PRE = query.value(1).toInt(); - unsigned PREA = query.value(2).toInt(); - unsigned RD = query.value(3).toInt(); - unsigned RDA = query.value(4).toInt(); - unsigned WR = query.value(5).toInt(); - unsigned WRA = query.value(6).toInt(); - unsigned REFA = query.value(7).toInt(); - unsigned REFB = query.value(8).toInt(); - unsigned PDEA = query.value(9).toInt(); - unsigned PDXA = query.value(10).toInt(); - unsigned PDEP = query.value(11).toInt(); - unsigned PDXP = query.value(12).toInt(); - unsigned SREFEN = query.value(13).toInt(); - unsigned SREFEX = query.value(14).toInt(); + unsigned NOP = query.value(0).toInt(); + unsigned RD = query.value(1).toInt(); + unsigned WR = query.value(2).toInt(); + unsigned RDA = query.value(3).toInt(); + unsigned WRA = query.value(4).toInt(); + unsigned ACT = query.value(5).toInt(); + unsigned PRE = query.value(6).toInt(); + unsigned REFB = query.value(7).toInt(); + unsigned PRESB = query.value(8).toInt(); + unsigned REFSB = query.value(9).toInt(); + unsigned PREA = query.value(10).toInt(); + unsigned REFA = query.value(11).toInt(); + unsigned PDEA = query.value(12).toInt(); + unsigned PDXA = query.value(13).toInt(); + unsigned PDEP = query.value(14).toInt(); + unsigned PDXP = query.value(15).toInt(); + unsigned SREFEN = query.value(16).toInt(); + unsigned SREFEX = query.value(17).toInt(); - return CommandLengths(ACT, PRE, PREA, RD, RDA, WR, WRA, REFA, REFB, - PDEA, PDXA, PDEP, PDXP, SREFEN, SREFEX); + return CommandLengths(NOP, RD, WR, RDA, WRA, ACT, PRE, REFB, + PRESB, REFSB, PREA, REFA, PDEA, PDXA, + PDEP, PDXP, SREFEN, SREFEX); } else { @@ -348,6 +353,11 @@ vector TraceDB::getDebugMessagesInTimespan(const Timespan &span, return parseCommentsFromQuery(selectDebugMessagesByTimespanWithLimit); } +QSqlDatabase TraceDB::getDatabase() const +{ + return database; +} + /* Helpers * * diff --git a/DRAMSys/traceAnalyzer/data/tracedb.h b/DRAMSys/traceAnalyzer/data/tracedb.h index 57a87055..d4c185a0 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.h +++ b/DRAMSys/traceAnalyzer/data/tracedb.h @@ -102,6 +102,8 @@ public: std::vector getDebugMessagesInTimespan(const Timespan &span, unsigned int limit); + QSqlDatabase getDatabase() const; + private: QString pathToDB; QSqlDatabase database; diff --git a/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h b/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h index 7f5f7abc..6fa65695 100644 --- a/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h +++ b/DRAMSys/traceAnalyzer/presentation/tracedrawingproperties.h @@ -37,6 +37,7 @@ #ifndef TRACECOLLECTIONDRAWINGPROPERTIES_H #define TRACECOLLECTIONDRAWINGPROPERTIES_H + #include #include #include @@ -54,31 +55,37 @@ struct TraceDrawingProperties { int yValCommandBus; int yValDataBus; unsigned int numberOfRanks; + unsigned int numberOfBankgroups; unsigned int numberOfBanks; unsigned int banksPerRank; + unsigned int groupsPerRank; + unsigned int banksPerGroup; TraceDrawingProperties() : drawText(true), drawBorder(true), colorGrouping(ColorGrouping::PhaseType) {} TraceDrawingProperties(bool drawText, bool drawBorder, ColorGrouping colorGrouping) : drawText(drawText), drawBorder(drawBorder), colorGrouping(colorGrouping) {} - TraceDrawingProperties(bool drawText, bool drawBorder, ColorGrouping colorGrouping, - int yValResponse, int yValRequest, int yValCommandBus, int yValDataBus, - unsigned int numberOfRanks, unsigned int numberOfBanks) : - drawText(drawText), drawBorder(drawBorder), colorGrouping(colorGrouping), - yValResponse(yValResponse), yValRequest(yValRequest), - yValCommandBus(yValCommandBus), yValDataBus(yValDataBus), - numberOfRanks(numberOfRanks), numberOfBanks(numberOfBanks), - banksPerRank(numberOfBanks / numberOfRanks) {} QHash getLabels() const { QHash result; - for (unsigned int i = 0; i < numberOfBanks; i++) { - result[i] = QString("Bank ") + QString::number(i); + + unsigned i = 0; + for (unsigned rank = 0; rank < numberOfRanks; rank++) + { + for (unsigned group = 0; group < groupsPerRank; group++) + { + for (unsigned bank = 0; bank < banksPerGroup; bank++) + { + result[i++] = QString("RA") + QString::number(rank) + + QString(" BG") + QString::number(group) + + QString(" BA") + QString::number(bank); + } + } } - result[yValCommandBus] = "Cmd Bus"; + result[yValCommandBus] = "Command Bus"; result[yValResponse] = "RESP"; result[yValRequest] = "REQ"; result[yValDataBus] = "Data Bus"; diff --git a/DRAMSys/traceAnalyzer/presentation/tracenavigator.cpp b/DRAMSys/traceAnalyzer/presentation/tracenavigator.cpp index afd59c73..7ff82f87 100644 --- a/DRAMSys/traceAnalyzer/presentation/tracenavigator.cpp +++ b/DRAMSys/traceAnalyzer/presentation/tracenavigator.cpp @@ -69,7 +69,7 @@ void TraceNavigator::navigateToTime(traceTime time) void TraceNavigator::navigateToTransaction(ID id) { - navigateToTime(traceFile.getTransactionByID(id)->Span().Begin()); + navigateToTime(traceFile.getTransactionByID(id)->span.Begin()); } @@ -162,25 +162,25 @@ void TraceNavigator::selectTransaction(ID id) void TraceNavigator::selectTransaction(const shared_ptr &transaction) { - selectTransaction(transaction->Id()); + selectTransaction(transaction->id); } void TraceNavigator::selectNextTransaction() { if (selectedTransactions.empty() - || selectedTransactions.front()->Id() == + || selectedTransactions.front()->id == traceFile.getGeneralInfo().numberOfTransactions) selectFirstTransaction(); else - selectTransaction(selectedTransactions.front()->Id() + 1); + selectTransaction(selectedTransactions.front()->id + 1); } void TraceNavigator::selectPreviousTransaction() { - if (selectedTransactions.empty() || selectedTransactions.front()->Id() == 1) + if (selectedTransactions.empty() || selectedTransactions.front()->id == 1) selectLastTransaction(); else - selectTransaction(selectedTransactions.front()->Id() - 1); + selectTransaction(selectedTransactions.front()->id - 1); } void TraceNavigator::selectFirstTransaction() @@ -199,7 +199,7 @@ void TraceNavigator::selectNextRefresh() shared_ptr nextRefresh; if (!SelectedTransactions().empty()) - nextRefresh = traceFile.getNextRefresh(SelectedTransactions().front()->Id()); + nextRefresh = traceFile.getNextRefresh(SelectedTransactions().front()->id); else nextRefresh = traceFile.getNextRefresh(0); @@ -212,7 +212,7 @@ void TraceNavigator::selectNextActivate() shared_ptr nextActivate; if (!SelectedTransactions().empty()) - nextActivate = traceFile.getNextActivate(SelectedTransactions().front()->Id()); + nextActivate = traceFile.getNextActivate(SelectedTransactions().front()->id); else nextActivate = traceFile.getNextActivate(0); @@ -226,7 +226,7 @@ void TraceNavigator::selectNextPrecharge() if (!SelectedTransactions().empty()) nextPrecharge = traceFile.getNextPrecharge( - SelectedTransactions().front()->Id()); + SelectedTransactions().front()->id); else nextPrecharge = traceFile.getNextPrecharge(0); @@ -239,7 +239,7 @@ void TraceNavigator::selectNextActb() shared_ptr nextActb; if (!SelectedTransactions().empty()) - nextActb = traceFile.getNextActb(SelectedTransactions().front()->Id()); + nextActb = traceFile.getNextActb(SelectedTransactions().front()->id); else nextActb = traceFile.getNextActb(0); @@ -253,7 +253,7 @@ void TraceNavigator::selectNextPreb() if (!SelectedTransactions().empty()) nextPreb = traceFile.getNextPreb( - SelectedTransactions().front()->Id()); + SelectedTransactions().front()->id); else nextPreb = traceFile.getNextPreb(0); @@ -266,7 +266,7 @@ void TraceNavigator::selectNextRefb() shared_ptr n; if (!SelectedTransactions().empty()) - n = traceFile.getNextRefb(SelectedTransactions().front()->Id()); + n = traceFile.getNextRefb(SelectedTransactions().front()->id); else n = traceFile.getNextRefb(0); @@ -277,13 +277,13 @@ void TraceNavigator::selectNextRefb() bool TraceNavigator::transactionIsSelected(const shared_ptr &transaction) const { - return transactionIsSelected(transaction->Id()); + return transactionIsSelected(transaction->id); } bool TraceNavigator::transactionIsSelected(ID id) const { for (const auto &transaction : selectedTransactions) { - if (transaction->Id() == id) + if (transaction->id == id) return true; } return false; @@ -307,12 +307,12 @@ Timespan TraceNavigator::getSpanCoveredBySelectedTransaction() if (!hasSelectedTransactions()) return Timespan(0, 0); - traceTime begin = SelectedTransactions().at(0)->Span().Begin(); - traceTime end = SelectedTransactions().at(0)->Span().End(); + traceTime begin = SelectedTransactions().at(0)->span.Begin(); + traceTime end = SelectedTransactions().at(0)->span.End(); for (const auto &transaction : selectedTransactions) { - if (transaction->Span().End() > end) - end = transaction->Span().End(); + if (transaction->span.End() > end) + end = transaction->span.End(); } return Timespan(begin, end); diff --git a/DRAMSys/traceAnalyzer/presentation/traceplot.cpp b/DRAMSys/traceAnalyzer/presentation/traceplot.cpp index 351477ee..e54ab395 100644 --- a/DRAMSys/traceAnalyzer/presentation/traceplot.cpp +++ b/DRAMSys/traceAnalyzer/presentation/traceplot.cpp @@ -206,8 +206,11 @@ void TracePlot::connectNavigatorQ_SIGNALS() void TracePlot::setUpDrawingProperties() { drawingProperties.numberOfRanks = navigator->GeneralTraceInfo().numberOfRanks; + drawingProperties.numberOfBankgroups = navigator->GeneralTraceInfo().numberOfBankgroups; drawingProperties.numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks; drawingProperties.banksPerRank = drawingProperties.numberOfBanks / drawingProperties.numberOfRanks; + drawingProperties.groupsPerRank = drawingProperties.numberOfBankgroups / drawingProperties.numberOfRanks; + drawingProperties.banksPerGroup = drawingProperties.numberOfBanks / drawingProperties.numberOfBankgroups; drawingProperties.yValResponse = drawingProperties.numberOfBanks; drawingProperties.yValRequest = drawingProperties.numberOfBanks + 1; drawingProperties.yValCommandBus = -3; diff --git a/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp b/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp index ddccf75a..1090bd45 100644 --- a/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp +++ b/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp @@ -87,8 +87,11 @@ void TraceScroller::setUpTracePlotItem() void TraceScroller::setUpDrawingProperties() { drawingProperties.numberOfRanks = navigator->GeneralTraceInfo().numberOfRanks; + drawingProperties.numberOfBankgroups = navigator->GeneralTraceInfo().numberOfBankgroups; drawingProperties.numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks; drawingProperties.banksPerRank = drawingProperties.numberOfBanks / drawingProperties.numberOfRanks; + drawingProperties.groupsPerRank = drawingProperties.numberOfBankgroups / drawingProperties.numberOfRanks; + drawingProperties.banksPerGroup = drawingProperties.numberOfBanks / drawingProperties.numberOfBankgroups; drawingProperties.yValResponse = drawingProperties.numberOfBanks; drawingProperties.yValRequest = drawingProperties.numberOfBanks + 1; drawingProperties.yValCommandBus = -3; diff --git a/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp b/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp index 0d37dcfc..759bbdde 100644 --- a/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp +++ b/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.cpp @@ -66,7 +66,7 @@ void TransactionTreeWidget::AppendTransaction(const shared_ptr &transaction) { QTreeWidgetItem *node = new TransactionTreeItem(this, transaction, - navigator->GeneralTraceInfo().controllerThread); + navigator->GeneralTraceInfo()); addTopLevelItem(node); } @@ -89,33 +89,33 @@ void TransactionTreeWidget::ContextMenuRequested(QPoint point) TransactionTreeWidget::TransactionTreeItem::TransactionTreeItem( QTreeWidget *parent, const shared_ptr &transaction, - unsigned int controllerThread) : QTreeWidgetItem(parent, - transactionTreeItemType) + const GeneralInfo &generalInfo) + : QTreeWidgetItem(parent, transactionTreeItemType) { - this->setText(0, QString::number(transaction->Id())); - this->id = transaction->Id(); + this->setText(0, QString::number(transaction->id)); + this->id = transaction->id; QTreeWidgetItem *time = new QTreeWidgetItem({"Timespan"}); - AppendTimespan(time, transaction->Span()); + AppendTimespan(time, transaction->span); this->addChild(time); - this->addChild(new QTreeWidgetItem( {"Length", prettyFormatTime(transaction->Span().timeCovered())})); + this->addChild(new QTreeWidgetItem({"Length", prettyFormatTime(transaction->span.timeCovered())})); + this->addChild(new QTreeWidgetItem({"Channel", QString::number(transaction->channel)})); + this->addChild(new QTreeWidgetItem({"Rank", QString::number(transaction->rank)})); + this->addChild(new QTreeWidgetItem({"Bankgroup", QString::number(transaction->bankgroup % generalInfo.groupsPerRank)})); + this->addChild(new QTreeWidgetItem({"Bank", QString::number(transaction->bank % generalInfo.banksPerGroup)})); + this->addChild(new QTreeWidgetItem({"Row", QString::number(transaction->row)})); + this->addChild(new QTreeWidgetItem({"Column", QString::number(transaction->column)})); + this->addChild(new QTreeWidgetItem({"Address", QString("0x") + QString::number(transaction->address, 16)})); - this->addChild(new QTreeWidgetItem( {"Channel", QString::number(transaction->Channel())})); - this->addChild(new QTreeWidgetItem( {"Rank", QString::number(transaction->Rank())} )); - this->addChild(new QTreeWidgetItem( {"Bankgroup", QString::number(transaction->BankGroup())} )); - this->addChild(new QTreeWidgetItem( {"Bank", QString::number(transaction->Bank())} )); - this->addChild(new QTreeWidgetItem( {"Row", QString::number(transaction->Row())} )); - this->addChild(new QTreeWidgetItem( {"Column", QString::number(transaction->Column())} )); - this->addChild(new QTreeWidgetItem( {"Address", QString("0x") + QString::number(transaction->Address(), 16)} )); - - if (transaction->Thread() != controllerThread) { - this->addChild(new QTreeWidgetItem( {"Burstlength", QString::number(transaction->Burstlength())})); - this->addChild(new QTreeWidgetItem( {"Thread", QString::number(transaction->Thread())})); + if (transaction->thread != generalInfo.controllerThread) + { + this->addChild(new QTreeWidgetItem({"Burstlength", QString::number(transaction->burstlength)})); + this->addChild(new QTreeWidgetItem({"Thread", QString::number(transaction->thread)})); } QTreeWidgetItem *phasesNode = new QTreeWidgetItem(this); phasesNode->setText(0, "Phases"); - phasesNode->addChild(new QTreeWidgetItem( {"", "Begin", "End"} )); + phasesNode->addChild(new QTreeWidgetItem({"", "Begin", "End"})); for (std::shared_ptr phase : transaction->Phases()) { AppendPhase(phasesNode, *phase); diff --git a/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.h b/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.h index a08547ab..5cda6399 100644 --- a/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.h +++ b/DRAMSys/traceAnalyzer/presentation/transactiontreewidget.h @@ -71,7 +71,7 @@ private: public: static constexpr int transactionTreeItemType = 1001; TransactionTreeItem(QTreeWidget *parent, - const std::shared_ptr &trans, unsigned int controllerThread); + const std::shared_ptr &trans, const GeneralInfo &generalInfo); ID Id() { return id; diff --git a/DRAMSys/traceAnalyzer/scripts/plots.py b/DRAMSys/traceAnalyzer/scripts/plots.py index aefb1235..dc6def9f 100755 --- a/DRAMSys/traceAnalyzer/scripts/plots.py +++ b/DRAMSys/traceAnalyzer/scripts/plots.py @@ -196,6 +196,55 @@ def memory_utilisation_window(connection, tracePath, steps): return outputFiles +@plot +def queue_window(connection, tracePath, steps): + + import matplotlib.pyplot as plt + from matplotlib.backends.backend_pdf import PdfPages + + cursor = connection.cursor() + cursor.execute("select max(BufferNumber) from BufferDepth;") + bufferNumber = int(cursor.fetchone()[0]) + 1 + + cursor = connection.cursor() + cursor.execute("select MaxBufferDepth from GeneralInfo;") + maxBufferDepth = int(cursor.fetchone()[0]) + + outputFile = "" + outputFileName, basename = createOutputFilename(tracePath, 'queue', '', 'pdf') + outputFile = "{0}\n\t".format(outputFileName) + + QueueFigure = plt.figure(figsize=(10, 5), dpi=300) + QueueFigurePlot = QueueFigure.add_subplot(111) + QueueFigurePlot.set_xlabel('Time [s]') + QueueFigurePlot.set_ylabel('Queue Utilization') + QueueFigurePlot.set_title('Average Queue Utilization: ' + str(basename)) + QueueFigurePlot.grid(True) + + + for b in range(bufferNumber): + cursor.execute("select Time, AverageBufferDepth from BufferDepth where BufferNumber = {};".format(b)) + time = [None] * steps + queue = [None] * steps + for i in range(steps-1): + result = cursor.fetchone() + time[i] = result[0] + queue[i] = result[1] + + QueueFigurePlot.plot(time, queue, linewidth=0.5, label="Queue {}".format(b)) + + QueueFigurePlot.legend(loc="upper left") + + x1,x2,y1,y2 = QueueFigurePlot.axis() + QueueFigurePlot.axis((x1,x2,0,maxBufferDepth)) + + pdf = PdfPages(outputFileName) + pdf.savefig(QueueFigure) + pdf.close() + QueueFigurePlot.clear() + plt.close() + + return outputFile @plot def power_window(connection, tracePath, steps): @@ -252,6 +301,44 @@ def power_window(connection, tracePath, steps): return outputFile +def latency_analysis(connection, tracePath, steps): + from collections import Counter + query = """ SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000), t.id + FROM Transactions t, Phases p1, Phases p2 + WHERE t.id = p1.Transact + AND t.id = p2.Transact + AND p1.PhaseName = "REQ" + AND p2.PhaseName = "RESP" """ + cursor = connection.cursor() + cursor.execute(query) + results = [] + while True: + result = cursor.fetchone() + if (result is not None): + results.append([result[0], result[1]]) + else: + break + + # Create histogram for analysis: + hist = {} + transactions = {} + for i in results: + hist[i[0]] = hist.get(i[0], 0) + 1 + if i[0] in transactions: + transactions[i[0]].append(i[1]) + else: + transactions[i[0]] = [] + + # Find N highest bins + N = 3 + k = Counter(hist) + high = k.most_common(3) + + for i in high: + print(i[0]," :",i[1]," ") + print(transactions[i[0]]) + + return "none\n" @plot def latency_histogram(connection, tracePath, steps): diff --git a/DRAMSys/traceAnalyzer/tracefiletab.cpp b/DRAMSys/traceAnalyzer/tracefiletab.cpp index ca88744c..b67004b7 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.cpp +++ b/DRAMSys/traceAnalyzer/tracefiletab.cpp @@ -41,6 +41,11 @@ #include "QFileInfo" #include "qmessagebox.h" #include +#include +#include +#include +#include "qwt_plot_histogram.h" +#include TraceFileTab::TraceFileTab(QWidget *parent, const QString &path) : QWidget(parent), ui(new Ui::TraceFileTab), savingChangesToDB(false) @@ -82,7 +87,6 @@ void TraceFileTab::initNavigatorAndItsDependentWidgets(QString path) ui->selectedTransactionTree->init(navigator); //ui->debugMessages->init(navigator,ui->traceplot); ui->commentTree->init(navigator); - } void TraceFileTab::setUpFileWatcher(QString path) @@ -110,3 +114,112 @@ void TraceFileTab::tracefileChanged() navigator->refreshData(); } +class ItemDelegate: public QItemDelegate +{ +public: + ItemDelegate(QObject* parent = nullptr): QItemDelegate(parent) + { + } + + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const + { + if (index.column() == 1) { + double progress = index.data().toDouble(); + QStyleOptionProgressBar opt; + opt.rect = option.rect; + opt.minimum = 0; + opt.maximum = 100; + opt.progress = static_cast(floor(progress)); + opt.text = QString::number(progress, 'f', 2)+" %"; + opt.textVisible = true; + QApplication::style()->drawControl(QStyle::CE_ProgressBar, &opt, painter, nullptr); + } else { + QItemDelegate::paint(painter, option, index); + } + } +}; + +void TraceFileTab::on_tabWidget_currentChanged(int index) +{ +} + +void TraceFileTab::on_latencyTreeView_doubleClicked(const QModelIndex &index) +{ + // Get onlye the leaf: + if(index.column() == 0 && index.model()->hasChildren(index) == false) { + unsigned int id = index.data().toUInt(); + if(id!=0) { + navigator->selectTransaction(id); + } + } +} + +void TraceFileTab::on_startLatencyAnalysis_clicked() +{ + // Setup Database: + QSqlDatabase db = navigator->TraceFile().getDatabase(); + QSqlQuery query(db); + + // Check the count of transactions: + QString sql = "SELECT COUNT(*) FROM Transactions;"; + query.exec(sql); + query.next(); + int maxTransactions = query.value(0).toInt(); + + // Create Database Setup and Query: + sql = "SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000) as latency, t.id " + "FROM Transactions t, Phases p1, Phases p2 " + "WHERE t.id = p1.Transact " + "AND t.id = p2.Transact " + "AND p1.PhaseName = \"REQ\" " + "AND p2.PhaseName = \"RESP\" ORDER BY latency;"; + + query.exec(sql); + + // Creatoe model and fill it from Database: + QStandardItemModel* model = new QStandardItemModel(); + + int currentLatency = 0; + QStandardItem* currentLatencyItem = nullptr; + int counter = 0; + while (query.next()) { + if(query.value(0) != currentLatency) { + currentLatencyItem = new QStandardItem(QString::number(query.value(0).toInt())+" ns"); + currentLatency = query.value(0).toInt(); + QList row; + row.append(currentLatencyItem); + row.append(new QStandardItem()); + model->appendRow(row); + } + QStandardItem * id = new QStandardItem(query.value(1).toString()); + currentLatencyItem->appendRow(id); + counter++; + + int percentage = int(ceil((double(counter))/(double(maxTransactions))*100.0)); + ui->latencyAnalysisProgressBar->setValue(percentage); + } + QStringList header = {"Latency","Occurences"}; + model->setHorizontalHeaderLabels(header); + + // Generate Histrogram and Tree: + QwtPlotHistogram *hist = new QwtPlotHistogram; + QVector *intervals = new QVector; + for(int i = 0; i < model->rowCount(); i++) { + double latency = model->item(i,0)->text().replace(" ns","").toDouble(); + int numberOfChilds = model->item(i)->rowCount(); + double percentage = 100*((double(numberOfChilds))/(double(counter))); + model->item(i,1)->setText(QString::number(percentage)); + intervals->append(QwtIntervalSample(percentage, latency, latency+1)); + } + ui->latencyTreeView->setItemDelegate(new ItemDelegate(ui->latencyTreeView)); + ui->latencyTreeView->setModel(model); + hist->setSamples(*intervals); + hist->attach(ui->latencyPlot); + hist->setPen(QPen(QColor(255,0,0,100))); + hist->setBrush(QBrush(QColor(255,0,0,255))); + ui->latencyPlot->setAxisTitle(0,"Occurences [%]"); + QwtText axisTitle( "Latency [ns]" ); + axisTitle.setFont( ui->latencyPlot->axisTitle( QwtPlot::xBottom ).font() ); + ui->latencyPlot->setAxisTitle( QwtPlot::xBottom, axisTitle ); + ui->latencyPlot->replot(); +} diff --git a/DRAMSys/traceAnalyzer/tracefiletab.h b/DRAMSys/traceAnalyzer/tracefiletab.h index ddc912cc..6ec1cec5 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.h +++ b/DRAMSys/traceAnalyzer/tracefiletab.h @@ -79,6 +79,10 @@ public Q_SLOTS: Q_SIGNALS: void statusChanged(QString message, bool saveChangesEnable = false); void colorGroupingChanged(ColorGrouping colorgrouping); +private Q_SLOTS: + void on_tabWidget_currentChanged(int index); + void on_latencyTreeView_doubleClicked(const QModelIndex &index); + void on_startLatencyAnalysis_clicked(); }; #endif // TRACEFILETAB_H diff --git a/DRAMSys/traceAnalyzer/tracefiletab.ui b/DRAMSys/traceAnalyzer/tracefiletab.ui index d6951f1b..726f36c8 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.ui +++ b/DRAMSys/traceAnalyzer/tracefiletab.ui @@ -56,97 +56,163 @@ - + - - - - 3 - 3 - - + - 300 - 0 + 0 + 500 - - - 16777215 - 16777215 - - - - true - - - false - - - false - - + 0 - - true - - - - - - - - 2 - 1 - - - - - 300 - 0 - - - - - 16777215 - 16777215 - - - - - 1 - - - - - - - - true - - - - 2 - 1 - - - - - 300 - 0 - - - - - 16777215 - 16777215 - - - - true - + + + Selected Transaction + + + + + + + + + 3 + 3 + + + + + 300 + 0 + + + + + 16777215 + 16777215 + + + + true + + + false + + + false + + + 0 + + + true + + + + + + + + 2 + 1 + + + + + 300 + 200 + + + + + 16777215 + 16777215 + + + + + 1 + + + + + + + + true + + + + 2 + 1 + + + + + 300 + 0 + + + + + 16777215 + 16777215 + + + + true + + + + + + + + + + Latency Analysis + + + + + + + + Start Analysis + + + + + + + 0 + + + + + + + + 16777215 + 200 + + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + @@ -156,6 +222,11 @@ + + QwtPlot + QFrame +
qwt_plot.h
+
TracePlot QListView