794 lines
24 KiB
C++
794 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>
|
|
|
|
// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
|
|
|
|
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.emplace_back(state0);
|
|
gen.states.emplace_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);
|
|
}
|
|
|
|
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
|