Files
DRAMSys/tests/tests_configuration/test_configuration.cpp

790 lines
24 KiB
C++

/*
* Copyright (c) 2021, RPTU Kaiserslautern-Landau
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
* Marco Mörz
*/
#include <DRAMSys/config/DRAMSysConfiguration.h>
#include <DRAMSys/config/MemSpec.h>
#include <DRAMUtils/util/json.h>
#include <DRAMUtils/memspec/MemSpec.h>
#include <DRAMUtils/memspec/standards/MemSpecDDR5.h>
#include <fstream>
#include <gtest/gtest.h>
#include <iostream>
#include <optional>
using namespace DRAMSys::Config;
class ConfigurationTest : public ::testing::Test
{
protected:
ConfigurationTest() :
memSpec(createMemSpec()),
tracePlayer(createTracePlayer()),
traceGeneratorOneState(createTraceGeneratorOneState()),
traceGeneratorMultipleStates(createTraceGeneratorMultipleStates()),
traceHammer(createTraceHammer())
{
}
static DRAMUtils::MemSpec::MemSpecVariant createMemSpec();
static DRAMSys::Config::TracePlayer createTracePlayer();
static DRAMSys::Config::TrafficGenerator createTraceGeneratorOneState();
static DRAMSys::Config::TrafficGeneratorStateMachine createTraceGeneratorMultipleStates();
static DRAMSys::Config::RowHammer createTraceHammer();
static std::vector<DRAMSys::Config::AddressMapping::BitEntry>
addressMapBitVector(std::initializer_list<std::vector<unsigned int>> bits)
{
auto result = std::vector<DRAMSys::Config::AddressMapping::BitEntry>();
for (const auto& bit : bits)
{
result.push_back(DRAMSys::Config::AddressMapping::BitEntry({bit.begin(), bit.end()}));
}
return result;
};
static std::vector<DRAMSys::Config::AddressMapping::BitEntry>
addressMapBitVector(std::vector<unsigned int> bits)
{
return {bits.begin(), bits.end()};
};
DRAMSys::Config::AddressMapping addressMapping{
addressMapBitVector({0, 1}),
addressMapBitVector({2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}),
addressMapBitVector({16}),
addressMapBitVector({13, 14, 15}),
addressMapBitVector({17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}),
addressMapBitVector({33}),
std::nullopt,
std::nullopt,
std::nullopt};
DRAMSys::Config::McConfig mcConfig{PagePolicyType::Open,
SchedulerType::FrFcfs,
0,
0,
SchedulerBufferType::Bankwise,
8,
std::nullopt,
std::nullopt,
CmdMuxType::Oldest,
RespQueueType::Fifo,
RefreshPolicyType::AllBank,
0,
0,
PowerDownPolicyType::NoPowerDown,
ArbiterType::Simple,
128,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt};
DRAMSys::Config::SimConfig simConfig{0,
false,
true,
false,
false,
false,
{"ddr5"},
true,
DRAMSys::Config::StoreModeType::NoStorage,
false,
false,
1000,
1e-3,
std::nullopt};
DRAMUtils::MemSpec::MemSpecVariant memSpec;
DRAMSys::Config::TracePlayer tracePlayer;
DRAMSys::Config::TrafficGenerator traceGeneratorOneState;
DRAMSys::Config::TrafficGeneratorStateMachine traceGeneratorMultipleStates;
DRAMSys::Config::RowHammer traceHammer;
std::vector<DRAMSys::Config::Initiator> traceSetup{
{
DRAMSys::Config::Initiator{tracePlayer},
DRAMSys::Config::Initiator{traceGeneratorOneState},
DRAMSys::Config::Initiator{traceGeneratorMultipleStates},
DRAMSys::Config::Initiator{traceHammer}
}
};
DRAMSys::Config::Configuration configuration{
addressMapping, mcConfig, memSpec, simConfig, "std::string_simulationId", traceSetup};
};
DRAMUtils::MemSpec::MemSpecVariant ConfigurationTest::createMemSpec()
{
DRAMUtils::MemSpec::MemArchitectureSpecTypeDDR5 memArchitectureSpec
{
2, // nbrOfChannels
8, // nbrOfDevices
1, // nbrOfRanks
1, // nbrOfDIMMRanks
1, // nbrOfPhysicalRanks
1, // nbrOfLogicalRanks
16, // nbrOfBanks
8, // nbrOfBankGroups
65536, // nbrOfRows
2048, // nbrOfColumns
16, // burstLength
2, // dataRate
4, // width
DRAMUtils::MemSpec::RefModeTypeDDR5::REF_MODE_1, // RefMode
16, // maxBurstLength
1, // cmdMode
32, // RAAIMT
96, // RAAMMT
1 // RAADEC
};
DRAMUtils::MemSpec::MemTimingSpecTypeDDR5 memTimingSpec
{
625, // tCK
52, // RAS
22, // RCD
12, // RTP
20, // WL
48, // WR
22, // RP
2, // PPD
22, // RL
1, // RPRE
0, // RPST
0, // RDDQS
2, // WPRE
0, // WPST
8, // CCD_L_slr
32, // CCD_L_WR_slr
16, // CCD_L_WR2_slr
8, // CCD_M_slr
32, // CCD_M_WR_slr
8, // CCD_S_slr
8, // CCD_S_WR_slr
0, // CCD_dlr
0, // CCD_WR_dlr
0, // CCD_WR_dpr
8, // RRD_L_slr
8, // RRD_S_slr
0, // RRD_dlr
32, // FAW_slr
0, // FAW_dlr
16, // WTR_L
16, // WTR_M
4, // WTR_S
312, // RFC1_slr
208, // RFC2_slr
0, // RFC1_dlr
0, // RFC2_dlr
0, // RFC1_dpr
0, // RFC2_dpr
184, // RFCsb_slr
0, // RFCsb_dlr
6240, // REFI1
3120, // REFI2
1560, // REFISB
48, // REFSBRD_slr
0, // REFSBRD_dlr
2, // RTRS
8, // CPDED
12, // PD
12, // XP
2, // ACTPDEN
2, // PRPDEN
2 // REFPDEN
};
DRAMUtils::MemSpec::MemImpedanceSpecTypeDDR5 memImpedanceSpec {
true, // ck_termination
1e6, // ck_R_eq
1e-12, // ck_dyn_E
true, // ca_termination
1e6, // ca_R_eq
1e-12, // ca_dyn_E
true, // rdq_termination
1e6, // rdq_R_eq
1e-12, // rdq_dyn_E
true, // wdq_termination
1e6, // wdq_R_eq
1e-12, // wdq_dyn_E
true, // rdqs_termination
1e6, // rdqs_R_eq
1e-12, // rdqs_dyn_E
true, // wdqs_termination
1e6, // wdqs_R_eq
1e-12 // wdqs_dyn_E
};
DRAMUtils::MemSpec::MemPowerSpecTypeDDR5 memPowerSpec {
0, // vdd
0, // idd0
0, // idd2n
0, // idd3n
0, // idd4r
0, // idd4w
0, // idd5c
0, // idd6n
0, // idd2p
0, // idd3p
0, // vpp
0, // ipp0
0, // ipp2n
0, // ipp3n
0, // ipp4r
0, // ipp4w
0, // ipp5c
0, // ipp6n
0, // ipp2p
0, // ipp3p
0, // idd5b // RefModeTypeDDR5::REF_MODE_1
0, // idd5f // RefModeTypeDDR5::REF_MODE_2
0, // ipp5b // RefModeTypeDDR5::REF_MODE_1
0, // ipp5f // RefModeTypeDDR5::REF_MODE_2
0, // vddq
0, // iBeta_vdd
0 // iBeta_vpp
};
DRAMUtils::MemSpec::MemSpecVariant variant;
DRAMUtils::MemSpec::MemSpecDDR5 memspec
{
DRAMUtils::MemSpec::BaseMemSpec{}, // base
"JEDEC_2x8x2Gbx4_DDR5-3200A", // memoryId
memArchitectureSpec, // memarchitecturespec
memPowerSpec, // mempowerspec
memTimingSpec, // memtimingspec
std::nullopt, // bankwisespec
memImpedanceSpec, // memimpedancespec
std::nullopt // dataratespec
};
variant.setVariant(memspec);
return variant;
}
DRAMSys::Config::TracePlayer ConfigurationTest::createTracePlayer()
{
DRAMSys::Config::TracePlayer player;
player.clkMhz = 100;
player.dataLength = 64;
player.name = "mytrace.stl";
return player;
}
DRAMSys::Config::TrafficGenerator ConfigurationTest::createTraceGeneratorOneState()
{
DRAMSys::Config::TrafficGenerator gen;
gen.clkMhz = 100;
gen.dataLength = 64;
gen.name = "MyTestGen";
gen.numRequests = 1000;
gen.rwRatio = 0.5;
gen.addressDistribution = DRAMSys::Config::AddressDistribution::Random;
gen.addressIncrement = {};
gen.minAddress = {};
gen.maxAddress = {};
return gen;
}
DRAMSys::Config::TrafficGeneratorStateMachine
ConfigurationTest::createTraceGeneratorMultipleStates()
{
DRAMSys::Config::TrafficGeneratorStateMachine gen;
gen.clkMhz = 100;
gen.dataLength = 64;
gen.name = "MyTestGen";
gen.maxPendingReadRequests = 8;
DRAMSys::Config::TrafficGeneratorActiveState state0;
state0.numRequests = 1000;
state0.rwRatio = 0.5;
state0.addressDistribution = DRAMSys::Config::AddressDistribution::Sequential;
state0.addressIncrement = 256;
state0.minAddress = {};
state0.maxAddress = 1024;
state0.id = 0;
DRAMSys::Config::TrafficGeneratorActiveState state1;
state1.numRequests = 100;
state1.rwRatio = 0.75;
state1.addressDistribution = DRAMSys::Config::AddressDistribution::Sequential;
state1.addressIncrement = 512;
state1.minAddress = 1024;
state1.maxAddress = 2048;
state1.id = 1;
gen.states.push_back(state0);
gen.states.push_back(state1);
DRAMSys::Config::TrafficGeneratorStateTransition transistion0{0, 1, 1.0};
gen.transitions.push_back(transistion0);
return gen;
}
DRAMSys::Config::RowHammer ConfigurationTest::createTraceHammer()
{
DRAMSys::Config::RowHammer hammer;
hammer.clkMhz = 100;
hammer.dataLength = 64;
hammer.name = "MyTestHammer";
hammer.numRequests = 4000;
hammer.rowIncrement = 2097152;
return hammer;
}
TEST_F(ConfigurationTest, ToJson)
{
json_t config_json;
config_json["simulation"] = configuration;
std::ifstream file("reference.json");
ASSERT_TRUE(file.is_open());
json_t reference_json = json_t::parse(file);
std::cout << reference_json.dump(4) << std::endl;
EXPECT_EQ(config_json, reference_json);
}
TEST(Configuration, FromToJson)
{
std::ifstream file("reference.json");
ASSERT_TRUE(file.is_open());
json_t reference_json = json_t::parse(file);
DRAMSys::Config::Configuration reference_configuration =
reference_json["simulation"].get<DRAMSys::Config::Configuration>();
json_t new_json;
new_json["simulation"] = reference_configuration;
EXPECT_EQ(new_json, reference_json);
}
TEST_F(ConfigurationTest, DumpConfiguration)
{
// This test does not test anything. It just dumps the configuration to stdout for manual
// inspection.
json_t json;
json["simulation"] = configuration;
std::cout << json.dump(4) << std::endl;
}
TEST(Configuration, FromPath)
{
// Test should not throw exceptions
Configuration config = from_path("reference.json");
}
TEST(RefreshPolicyType, BackwardsCompatibility)
{
// Deserializing
EXPECT_EQ(json_t("Rankwise").get<RefreshPolicyType>(), RefreshPolicyType::AllBank);
EXPECT_EQ(json_t("Bankwise").get<RefreshPolicyType>(), RefreshPolicyType::PerBank);
EXPECT_EQ(json_t("Groupwise").get<RefreshPolicyType>(), RefreshPolicyType::SameBank);
// Serializing
EXPECT_EQ(json_t(RefreshPolicyType::AllBank).get<std::string>(), "AllBank");
EXPECT_EQ(json_t(RefreshPolicyType::PerBank).get<std::string>(), "PerBank");
EXPECT_EQ(json_t(RefreshPolicyType::SameBank).get<std::string>(), "SameBank");
}
TEST_F(ConfigurationTest, SimConfig)
{
std::string_view simconfig_string = R"(
{
"simconfig": {
"AddressOffset": 0,
"CheckTLM2Protocol": false,
"DatabaseRecording": true,
"Debug": false,
"EnableWindowing": false,
"PowerAnalysis": false,
"SimulationName": "ddr5",
"SimulationProgressBar": true,
"StoreMode": "NoStorage",
"ThermalSimulation": false,
"UseMalloc": false,
"WindowSize": 1000,
"SimulationTime": 1e-3
}
}
)";
json_t simconfig_reference = json_t::parse(simconfig_string);
json_t simconfig_test;
simconfig_test[SimConfig::KEY] = simConfig;
EXPECT_EQ(simconfig_test, simconfig_reference);
}
TEST_F(ConfigurationTest, McConfig)
{
std::string_view mcconfig_string = R"(
{
"mcconfig": {
"Arbiter": "Simple",
"CmdMux": "Oldest",
"HighWatermark": 0,
"LowWatermark": 0,
"MaxActiveTransactions": 128,
"PagePolicy": "Open",
"PowerDownPolicy": "NoPowerDown",
"RefreshMaxPostponed": 0,
"RefreshMaxPulledin": 0,
"RefreshPolicy": "AllBank",
"RequestBufferSize": 8,
"RespQueue": "Fifo",
"Scheduler": "FrFcfs",
"SchedulerBuffer": "Bankwise"
}
}
)";
json_t mcconfig_reference = json_t::parse(mcconfig_string);
json_t mcconfig_test;
mcconfig_test[McConfig::KEY] = mcConfig;
EXPECT_EQ(mcconfig_test, mcconfig_reference);
}
TEST_F(ConfigurationTest, MemSpec)
{
std::string_view memspec_string = R"(
{
"memspec": {
"memarchitecturespec": {
"RAADEC": 1,
"RAAIMT": 32,
"RAAMMT": 96,
"burstLength": 16,
"cmdMode": 1,
"dataRate": 2,
"maxBurstLength": 16,
"nbrOfBankGroups": 8,
"nbrOfBanks": 16,
"nbrOfChannels": 2,
"nbrOfColumns": 2048,
"nbrOfDIMMRanks": 1,
"nbrOfDevices": 8,
"nbrOfLogicalRanks": 1,
"nbrOfPhysicalRanks": 1,
"nbrOfRanks": 1,
"nbrOfRows": 65536,
"RefMode": 1,
"width": 4
},
"memimpedancespec": {
"ck_termination": true,
"ck_R_eq": 1e6,
"ck_dyn_E": 1e-12,
"ca_termination": true,
"ca_R_eq": 1e6,
"ca_dyn_E": 1e-12,
"rdq_termination": true,
"rdq_R_eq": 1e6,
"rdq_dyn_E": 1e-12,
"wdq_termination": true,
"wdq_R_eq": 1e6,
"wdq_dyn_E": 1e-12,
"wdqs_termination": true,
"wdqs_R_eq": 1e6,
"wdqs_dyn_E": 1e-12,
"rdqs_termination": true,
"rdqs_R_eq": 1e6,
"rdqs_dyn_E": 1e-12
},
"memoryId": "JEDEC_2x8x2Gbx4_DDR5-3200A",
"memoryType": "DDR5",
"mempowerspec": {
"vdd": 0.0,
"idd0": 0.0,
"idd2n": 0.0,
"idd3n": 0.0,
"idd4r": 0.0,
"idd4w": 0.0,
"idd5c": 0.0,
"idd6n": 0.0,
"idd2p": 0.0,
"idd3p": 0.0,
"vpp": 0.0,
"ipp0": 0.0,
"ipp2n": 0.0,
"ipp3n": 0.0,
"ipp4r": 0.0,
"ipp4w": 0.0,
"ipp5c": 0.0,
"ipp6n": 0.0,
"ipp2p": 0.0,
"ipp3p": 0.0,
"idd5b": 0.0,
"idd5f": 0.0,
"ipp5b": 0.0,
"ipp5f": 0.0,
"vddq": 0.0,
"iBeta_vdd": 0.0,
"iBeta_vpp": 0.0
},
"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_L_WR2_slr": 16,
"CCD_M_slr": 8,
"CCD_M_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_M": 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,
"tCK": 625
}
}
}
)";
json_t memspec_reference = json_t::parse(memspec_string);
json_t memspec_test;
memspec_test[MemSpecConstants::KEY] = memSpec;
EXPECT_EQ(memspec_test, memspec_reference);
}
TEST_F(ConfigurationTest, AddressMapping)
{
std::string_view addressmapping_string = R"(
{
"addressmapping": {
"BANKGROUP_BIT": [
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32
],
"BANK_BIT": [
13,
14,
15
],
"BYTE_BIT": [
0,
1
],
"COLUMN_BIT": [
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12
],
"RANK_BIT": [
33
],
"ROW_BIT": [
16
]
}
}
)";
json_t addressmapping_reference = json_t::parse(addressmapping_string);
json_t addressmapping_test;
addressmapping_test[AddressMapping::KEY] = addressMapping;
EXPECT_EQ(addressmapping_test, addressmapping_reference);
}
TEST_F(ConfigurationTest, TraceSetup)
{
std::string_view tracesetup_string = R"(
{
"tracesetup": [
{
"type": "player",
"clkMhz": 100,
"dataLength": 64,
"name": "mytrace.stl"
},
{
"type": "generator",
"addressDistribution": "random",
"clkMhz": 100,
"dataLength": 64,
"name": "MyTestGen",
"numRequests": 1000,
"rwRatio": 0.5
},
{
"type": "statemachine",
"clkMhz": 100,
"dataLength": 64,
"maxPendingReadRequests": 8,
"name": "MyTestGen",
"states": [
{
"addressDistribution": "sequential",
"addressIncrement": 256,
"id": 0,
"maxAddress": 1024,
"numRequests": 1000,
"rwRatio": 0.5
},
{
"addressDistribution": "sequential",
"addressIncrement": 512,
"id": 1,
"maxAddress": 2048,
"minAddress": 1024,
"numRequests": 100,
"rwRatio": 0.75
}
],
"transitions": [
{
"from": 0,
"probability": 1.0,
"to": 1
}
]
},
{
"type": "rowhammer",
"clkMhz": 100,
"dataLength": 64,
"name": "MyTestHammer",
"numRequests": 4000,
"rowIncrement": 2097152
}
]
}
)";
json_t tracesetup_reference = json_t::parse(tracesetup_string);
json_t tracesetup_test;
tracesetup_test[TraceSetupConstants::KEY] = traceSetup;
EXPECT_EQ(tracesetup_test, tracesetup_reference);
}