/* * 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 */ #include #include #include #include #include #include using namespace DRAMSys::Config; class ConfigurationTest : public ::testing::Test { protected: ConfigurationTest() : memSpec(createMemSpec()), tracePlayer(createTracePlayer()), traceGeneratorOneState(createTraceGeneratorOneState()), traceGeneratorMultipleStates(createTraceGeneratorMultipleStates()), traceHammer(createTraceHammer()) { } static DRAMSys::Config::MemSpec createMemSpec(); static DRAMSys::Config::TracePlayer createTracePlayer(); static DRAMSys::Config::TrafficGenerator createTraceGeneratorOneState(); static DRAMSys::Config::TrafficGeneratorStateMachine createTraceGeneratorMultipleStates(); static DRAMSys::Config::RowHammer createTraceHammer(); static std::vector addressMapBitVector(std::vector 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}; 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}; DRAMSys::Config::MemSpec memSpec; DRAMSys::Config::TracePlayer tracePlayer; DRAMSys::Config::TrafficGenerator traceGeneratorOneState; DRAMSys::Config::TrafficGeneratorStateMachine traceGeneratorMultipleStates; DRAMSys::Config::RowHammer traceHammer; std::vector traceSetup{ {tracePlayer, traceGeneratorOneState, traceGeneratorMultipleStates, traceHammer}}; DRAMSys::Config::Configuration configuration{ addressMapping, mcConfig, memSpec, simConfig, "std::string_simulationId", traceSetup}; }; DRAMSys::Config::MemSpec ConfigurationTest::createMemSpec() { MemArchitectureSpecType memArchitectureSpec{{{"burstLength", 16}, {"dataRate", 2}, {"nbrOfBankGroups", 8}, {"nbrOfBanks", 16}, {"nbrOfColumns", 2048}, {"nbrOfRanks", 1}, {"nbrOfDIMMRanks", 1}, {"nbrOfPhysicalRanks", 1}, {"nbrOfLogicalRanks", 1}, {"nbrOfRows", 65536}, {"width", 4}, {"nbrOfDevices", 8}, {"nbrOfChannels", 2}, {"cmdMode", 1}, {"refMode", 1}, {"RAAIMT", 32}, {"RAAMMT", 96}, {"RAADEC", 1}}}; MemTimingSpecType 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_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}, {"tCK", 625}, }}}; return {memArchitectureSpec, "JEDEC_2x8x2Gbx4_DDR5-3200A", DRAMSys::Config::MemoryType::DDR5, memTimingSpec, {}}; } DRAMSys::Config::TracePlayer ConfigurationTest::createTracePlayer() { DRAMSys::Config::TracePlayer player; player.clkMhz = 100; player.name = "mytrace.stl"; return player; } DRAMSys::Config::TrafficGenerator ConfigurationTest::createTraceGeneratorOneState() { DRAMSys::Config::TrafficGenerator gen; gen.clkMhz = 100; 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.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.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(); 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, ResourceDirectory) { // Test should not throw exceptions Configuration config = from_path("resources/ddr5-example.json", "resources"); } 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::AllBank); EXPECT_EQ(json_t("Bankwise").get(), RefreshPolicyType::PerBank); EXPECT_EQ(json_t("Groupwise").get(), RefreshPolicyType::SameBank); // Serializing EXPECT_EQ(json_t(RefreshPolicyType::AllBank).get(), "AllBank"); EXPECT_EQ(json_t(RefreshPolicyType::PerBank).get(), "PerBank"); EXPECT_EQ(json_t(RefreshPolicyType::SameBank).get(), "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 } } )"; 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, "nbrOfBankGroups": 8, "nbrOfBanks": 16, "nbrOfChannels": 2, "nbrOfColumns": 2048, "nbrOfDIMMRanks": 1, "nbrOfDevices": 8, "nbrOfLogicalRanks": 1, "nbrOfPhysicalRanks": 1, "nbrOfRanks": 1, "nbrOfRows": 65536, "refMode": 1, "width": 4 }, "memoryId": "JEDEC_2x8x2Gbx4_DDR5-3200A", "memoryType": "DDR5", "memtimingspec": { "ACTPDEN": 2, "CCD_L_WR2_slr": 16, "CCD_L_WR_slr": 32, "CCD_L_slr": 8, "CCD_S_WR_slr": 8, "CCD_S_slr": 8, "CCD_WR_dlr": 0, "CCD_WR_dpr": 0, "CCD_dlr": 0, "CPDED": 8, "FAW_dlr": 0, "FAW_slr": 32, "PD": 12, "PPD": 2, "PRPDEN": 2, "RAS": 52, "RCD": 22, "RDDQS": 0, "REFI1": 6240, "REFI2": 3120, "REFISB": 1560, "REFPDEN": 2, "REFSBRD_dlr": 0, "REFSBRD_slr": 48, "RFC1_dlr": 0, "RFC1_dpr": 0, "RFC1_slr": 312, "RFC2_dlr": 0, "RFC2_dpr": 0, "RFC2_slr": 208, "RFCsb_dlr": 0, "RFCsb_slr": 184, "RL": 22, "RP": 22, "RPRE": 1, "RPST": 0, "RRD_L_slr": 8, "RRD_S_slr": 8, "RRD_dlr": 0, "RTP": 12, "RTRS": 2, "WL": 20, "WPRE": 2, "WPST": 0, "WR": 48, "WTR_L": 16, "WTR_S": 4, "XP": 12, "tCK": 625 } } } )"; json_t memspec_reference = json_t::parse(memspec_string); json_t memspec_test; memspec_test[MemSpec::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": [ { "clkMhz": 100, "name": "mytrace.stl" }, { "addressDistribution": "random", "clkMhz": 100, "name": "MyTestGen", "numRequests": 1000, "rwRatio": 0.5 }, { "clkMhz": 100, "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 } ] }, { "clkMhz": 100, "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); }