diff --git a/CMakeLists.txt b/CMakeLists.txt index 82db41a2..05ff2ae8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,7 @@ set(DRAMSYS_EXTENSIONS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extensions") ### Build options ### option(DRAMSYS_BUILD_TESTS "Build DRAMSys unit tests" OFF) +option(DRAMSYS_BUILD_BENCHMARKS "Build DRAMSys benchmarks" OFF) option(DRAMSYS_VERBOSE_CMAKE_OUTPUT "Show detailed CMake output" OFF) option(DRAMSYS_BUILD_CLI "Build DRAMSys Command Line Tool" ON) option(DRAMSYS_WITH_DRAMPOWER "Build with DRAMPower support enabled." OFF) @@ -125,6 +126,18 @@ if(DRAMSYS_BUILD_TESTS) set_target_properties(gtest_main PROPERTIES FOLDER lib/gtest) endif() +### GoogleBenchmark ### +if(DRAMSYS_BUILD_BENCHMARKS) + set(BENCHMARK_ENABLE_TESTING OFF) + + FetchContent_Declare( + benchmark + URL https://github.com/google/benchmark/archive/refs/tags/v1.8.3.zip + ) + + FetchContent_MakeAvailable(benchmark) +endif() + ### SystemC ### if (DRAMSYS_USE_EXTERNAL_SYSTEMC) list(APPEND CMAKE_PREFIX_PATH $ENV{SYSTEMC_HOME} /opt/systemc) @@ -179,3 +192,11 @@ if(DRAMSYS_BUILD_TESTS) include(CTest) add_subdirectory(tests) endif() + +############################################### +### Benchmark Directory ### +############################################### + +if(DRAMSYS_BUILD_BENCHMARKS) + add_subdirectory(benches) +endif() diff --git a/benches/CMakeLists.txt b/benches/CMakeLists.txt new file mode 100644 index 00000000..3c6ed571 --- /dev/null +++ b/benches/CMakeLists.txt @@ -0,0 +1,58 @@ +# Copyright (c) 2023, 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 + +############################################### +### benches_dramsys ### +############################################### + +cmake_minimum_required(VERSION 3.1.0) + +project(benches_dramsys) + +add_executable(${PROJECT_NAME} + main.cpp + simulation.cpp + addressdecoder.cpp +) + +target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}) +set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER benches) +target_link_libraries(${PROJECT_NAME} + DRAMSys::util + DRAMSys::libdramsys + DRAMSys::simulator + SystemC::systemc + benchmark +) + +build_source_group() diff --git a/benches/addressdecoder.cpp b/benches/addressdecoder.cpp new file mode 100644 index 00000000..594f3e06 --- /dev/null +++ b/benches/addressdecoder.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023, 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 "addressdecoder.h" + +#include +#include + +#include + +static DRAMSys::AddressDecoder addressDecoder() +{ + auto addressMapping = nlohmann::json::parse(addressMappingJsonString) + .at("addressmapping") + .get(); + DRAMSys::AddressDecoder decoder(addressMapping); + return decoder; +} + +static void decode(benchmark::State& state) +{ + auto decoder = addressDecoder(); + + for (auto _ : state) + { + // Actual address has no significant impact on performance + auto decodedAddress = decoder.decodeAddress(0x0); + benchmark::DoNotOptimize(decodedAddress); + } +} + +BENCHMARK(decode); + +static void encode(benchmark::State& state) +{ + auto decoder = addressDecoder(); + + // Actual address has no significant impact on performance + DRAMSys::DecodedAddress decodedAddress; + + for (auto _ : state) + { + auto encodedAddress = decoder.encodeAddress(decodedAddress); + benchmark::DoNotOptimize(encodedAddress); + } +} + +BENCHMARK(encode); diff --git a/benches/addressdecoder.h b/benches/addressdecoder.h new file mode 100644 index 00000000..f42c645f --- /dev/null +++ b/benches/addressdecoder.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022, 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 + */ + +#pragma once + +#include + +inline constexpr std::string_view addressMappingJsonString = R"( +{ + "addressmapping": { + "PSEUDOCHANNEL_BIT":[ + 29 + ], + "BANKGROUP_BIT":[ + 27, + 28 + ], + "BANK_BIT": [ + 25, + 26 + ], + "BYTE_BIT": [ + 0, + 1, + 2 + ], + "COLUMN_BIT": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "ROW_BIT": [ + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24 + ] + } +} +)"; diff --git a/benches/configs/ddr3-example.json b/benches/configs/ddr3-example.json new file mode 100644 index 00000000..c9d51a95 --- /dev/null +++ b/benches/configs/ddr3-example.json @@ -0,0 +1,156 @@ +{ + "simulation": { + "addressmapping": { + "BANK_BIT": [ + [13, 16], + 14, + 15 + ], + "BYTE_BIT": [ + 0, + 1, + 2 + ], + "COLUMN_BIT": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "ROW_BIT": [ + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29 + ], + "RANK_BIT": [ + 30 + ] + }, + "mcconfig": { + "PagePolicy": "Open", + "Scheduler": "FrFcfsGrp", + "RequestBufferSize": 8, + "CmdMux": "Oldest", + "RespQueue": "Fifo", + "RefreshPolicy": "Rankwise", + "RefreshMaxPostponed": 0, + "RefreshMaxPulledin": 0, + "PowerDownPolicy": "Staggered", + "PowerDownTimeout": 100 + }, + "memspec": { + "memarchitecturespec": { + "burstLength": 8, + "dataRate": 2, + "nbrOfBanks": 8, + "nbrOfColumns": 1024, + "nbrOfRanks": 2, + "nbrOfChannels": 1, + "nbrOfRows": 16384, + "width": 64, + "nbrOfDevices": 1 + }, + "memoryId": "MICRON_2GB_DDR3-1066_64bit_D_SODIMM", + "memoryType": "DDR3", + "mempowerspec": { + "idd0": 720.0, + "idd2n": 400.0, + "idd2p0": 80.0, + "idd2p1": 200.0, + "idd3n": 440.0, + "idd3p0": 240.0, + "idd3p1": 240.0, + "idd4r": 1200.0, + "idd4w": 1200.0, + "idd5": 1760.0, + "idd6": 48.0, + "vdd": 1.5 + }, + "memtimingspec": { + "AL": 0, + "CCD": 4, + "CKE": 3, + "CKESR": 4, + "CL": 7, + "DQSCK": 0, + "FAW": 20, + "RAS": 20, + "RC": 27, + "RCD": 7, + "REFI": 4160, + "RFC": 59, + "RL": 7, + "RP": 7, + "RRD": 4, + "RTP": 4, + "WL": 6, + "WR": 8, + "WTR": 4, + "XP": 4, + "XPDLL": 13, + "XS": 64, + "XSDLL": 512, + "ACTPDEN": 1, + "PRPDEN": 1, + "REFPDEN": 1, + "RTRS": 1, + "clkMhz": 533 + } + }, + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "ECCControllerMode": "Disabled", + "EnableWindowing": false, + "ErrorCSVFile": "", + "ErrorChipSeed": 42, + "PowerAnalysis": true, + "SimulationName": "ddr3", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + }, + "simulationid": "ddr3-dual-rank", + "tracesetup": [ + { + "clkMhz": 2000, + "type": "generator", + "name": "gen0", + "numRequests": 2000, + "rwRatio": 0.85, + "addressDistribution": "sequential", + "addressIncrement": 256, + }, + { + "clkMhz": 2000, + "type": "generator", + "name": "gen1", + "numRequests": 2000, + "rwRatio": 0.85, + "addressDistribution": "random", + "seed": 123456, + } + ] + } +} diff --git a/benches/main.cpp b/benches/main.cpp new file mode 100644 index 00000000..c6b1a289 --- /dev/null +++ b/benches/main.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023, 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 + +int sc_main(int argc, char** argv) +{ + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + return 0; +} diff --git a/benches/simulation.cpp b/benches/simulation.cpp new file mode 100644 index 00000000..8153dfa7 --- /dev/null +++ b/benches/simulation.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023, 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 + +static void ddr3Simulation(benchmark::State& state) +{ + auto rdbuf = std::cout.rdbuf(nullptr); + + for (auto _ : state) + { + sc_core::sc_get_curr_simcontext()->reset(); + + std::filesystem::path configFile("configs/ddr3-example.json"); + std::filesystem::path resourceDirectory("configs"); + + DRAMSys::Config::Configuration configuration = DRAMSys::Config::from_path(configFile.c_str()); + + Simulator simulator(std::move(configuration), std::move(resourceDirectory)); + Simulator::run(); + } + + std::cout.rdbuf(rdbuf); +} + +BENCHMARK(ddr3Simulation); diff --git a/src/configuration/DRAMSys/config/AddressMapping.h b/src/configuration/DRAMSys/config/AddressMapping.h index d3127201..0c4806ed 100644 --- a/src/configuration/DRAMSys/config/AddressMapping.h +++ b/src/configuration/DRAMSys/config/AddressMapping.h @@ -43,28 +43,21 @@ namespace DRAMSys::Config { -struct XorPair -{ - unsigned int FIRST; - unsigned int SECOND; -}; - -NLOHMANN_JSONIFY_ALL_THINGS(XorPair, FIRST, SECOND) - struct AddressMapping { static constexpr std::string_view KEY = "addressmapping"; static constexpr std::string_view SUB_DIR = "addressmapping"; - std::optional> BYTE_BIT; - std::optional> COLUMN_BIT; - std::optional> ROW_BIT; - std::optional> BANK_BIT; - std::optional> BANKGROUP_BIT; - std::optional> RANK_BIT; - std::optional> PSEUDOCHANNEL_BIT; - std::optional> CHANNEL_BIT; - std::optional> XOR; + using BitEntry = std::variant>; + + std::optional> BYTE_BIT; + std::optional> COLUMN_BIT; + std::optional> ROW_BIT; + std::optional> BANK_BIT; + std::optional> BANKGROUP_BIT; + std::optional> RANK_BIT; + std::optional> PSEUDOCHANNEL_BIT; + std::optional> CHANNEL_BIT; }; NLOHMANN_JSONIFY_ALL_THINGS(AddressMapping, @@ -75,8 +68,7 @@ NLOHMANN_JSONIFY_ALL_THINGS(AddressMapping, BANKGROUP_BIT, RANK_BIT, PSEUDOCHANNEL_BIT, - CHANNEL_BIT, - XOR) + CHANNEL_BIT) } // namespace DRAMSys::Config diff --git a/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp b/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp index 12bc61bb..62aa2c61 100644 --- a/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp +++ b/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp @@ -47,57 +47,71 @@ namespace DRAMSys { -AddressDecoder::AddressDecoder(const DRAMSys::Config::AddressMapping& addressMapping, - const MemSpec& memSpec) +static void addMapping(std::vector const& mappingVector, + std::vector& bitVector, + std::vector>& xorVector) +{ + for (const auto& bitEntry : mappingVector) + { + std::visit( + [&bitVector, &xorVector](auto&& arg) + { + using T = std::decay_t; + if constexpr (std::is_same_v) + { + bitVector.push_back(arg); + } + else if constexpr (std::is_same_v>) + { + bitVector.push_back(arg.at(0)); + xorVector.push_back(arg); + } + }, + bitEntry); + } +} + +AddressDecoder::AddressDecoder(const DRAMSys::Config::AddressMapping& addressMapping) { if (const auto& channelBits = addressMapping.CHANNEL_BIT) { - std::copy(channelBits->begin(), channelBits->end(), std::back_inserter(vChannelBits)); + addMapping(*channelBits, vChannelBits, vXor); } if (const auto& rankBits = addressMapping.RANK_BIT) { - std::copy(rankBits->begin(), rankBits->end(), std::back_inserter(vRankBits)); + addMapping(*rankBits, vRankBits, vXor); } // HBM pseudo channels are internally modelled as ranks if (const auto& pseudoChannelBits = addressMapping.PSEUDOCHANNEL_BIT) { - std::copy( - pseudoChannelBits->begin(), pseudoChannelBits->end(), std::back_inserter(vRankBits)); + addMapping(*pseudoChannelBits, vRankBits, vXor); } if (const auto& bankGroupBits = addressMapping.BANKGROUP_BIT) { - std::copy(bankGroupBits->begin(), bankGroupBits->end(), std::back_inserter(vBankGroupBits)); + addMapping(*bankGroupBits, vBankGroupBits, vXor); } if (const auto& byteBits = addressMapping.BYTE_BIT) { - std::copy(byteBits->begin(), byteBits->end(), std::back_inserter(vByteBits)); - } - - if (const auto& xorBits = addressMapping.XOR) - { - for (const auto& xorBit : *xorBits) - { - vXor.emplace_back(xorBit.FIRST, xorBit.SECOND); - } + addMapping(*byteBits, vByteBits, vXor); } if (const auto& bankBits = addressMapping.BANK_BIT) { - std::copy(bankBits->begin(), bankBits->end(), std::back_inserter(vBankBits)); + addMapping(*bankBits, vBankBits, vXor); } if (const auto& rowBits = addressMapping.ROW_BIT) { - std::copy(rowBits->begin(), rowBits->end(), std::back_inserter(vRowBits)); + addMapping(*rowBits, vRowBits, vXor); } if (const auto& columnBits = addressMapping.COLUMN_BIT) { - std::copy(columnBits->begin(), columnBits->end(), std::back_inserter(vColumnBits)); + addMapping(*columnBits, vColumnBits, vXor); } unsigned channels = std::lround(std::pow(2.0, vChannelBits.size())); @@ -108,6 +122,23 @@ AddressDecoder::AddressDecoder(const DRAMSys::Config::AddressMapping& addressMap unsigned columns = std::lround(std::pow(2.0, vColumnBits.size())); unsigned bytes = std::lround(std::pow(2.0, vByteBits.size())); + maximumAddress = + static_cast(bytes) * columns * rows * banks * bankGroups * ranks * channels - 1; + + bankgroupsPerRank = bankGroups; + banksPerGroup = banks; +} + +void AddressDecoder::plausibilityCheck(const MemSpec& memSpec) +{ + unsigned channels = std::lround(std::pow(2.0, vChannelBits.size())); + unsigned ranks = std::lround(std::pow(2.0, vRankBits.size())); + unsigned bankGroups = std::lround(std::pow(2.0, vBankGroupBits.size())); + unsigned banks = std::lround(std::pow(2.0, vBankBits.size())); + unsigned rows = std::lround(std::pow(2.0, vRowBits.size())); + unsigned columns = std::lround(std::pow(2.0, vColumnBits.size())); + unsigned bytes = std::lround(std::pow(2.0, vByteBits.size())); + maximumAddress = static_cast(bytes) * columns * rows * banks * bankGroups * ranks * channels - 1; @@ -131,7 +162,8 @@ AddressDecoder::AddressDecoder(const DRAMSys::Config::AddressMapping& addressMap { highestByteBit = static_cast(*std::max_element(vByteBits.begin(), vByteBits.end())); - for (unsigned bitPosition = 0; bitPosition <= static_cast(highestByteBit); bitPosition++) + for (unsigned bitPosition = 0; bitPosition <= static_cast(highestByteBit); + bitPosition++) { if (std::find(vByteBits.begin(), vByteBits.end(), bitPosition) == vByteBits.end()) SC_REPORT_FATAL("AddressDecoder", "Byte bits are not continuous starting from 0"); @@ -148,16 +180,13 @@ AddressDecoder::AddressDecoder(const DRAMSys::Config::AddressMapping& addressMap SC_REPORT_FATAL("AddressDecoder", "No continuous column bits for maximum burst length"); } - bankgroupsPerRank = bankGroups; - bankGroups = bankgroupsPerRank * ranks; - - banksPerGroup = banks; - banks = banksPerGroup * bankGroups; + unsigned absoluteBankGroups = bankgroupsPerRank * ranks; + unsigned absoluteBanks = banksPerGroup * absoluteBankGroups; if (memSpec.numberOfChannels != channels || memSpec.ranksPerChannel != ranks || - memSpec.bankGroupsPerChannel != bankGroups || memSpec.banksPerChannel != banks || - memSpec.rowsPerBank != rows || memSpec.columnsPerRow != columns || - memSpec.devicesPerRank * memSpec.bitWidth != bytes * 8) + memSpec.bankGroupsPerChannel != absoluteBankGroups || + memSpec.banksPerChannel != absoluteBanks || memSpec.rowsPerBank != rows || + memSpec.columnsPerRow != columns || memSpec.devicesPerRank * memSpec.bitWidth != bytes * 8) SC_REPORT_FATAL("AddressDecoder", "Memspec and address mapping do not match"); } @@ -174,12 +203,16 @@ DecodedAddress AddressDecoder::decodeAddress(uint64_t encAddr) const // For each used xor: // Get the first bit and second bit. Apply a bitwise xor operator and save it back to the // first bit. + auto tempAddr = encAddr; for (const auto& it : vXor) { - uint64_t xoredBit = - (((encAddr >> it.first) & UINT64_C(1)) ^ ((encAddr >> it.second) & UINT64_C(1))); - encAddr &= ~(UINT64_C(1) << it.first); - encAddr |= xoredBit << it.first; + uint64_t xoredBit = std::accumulate(it.cbegin(), + it.cend(), + 0, + [tempAddr](uint64_t acc, unsigned xorBit) + { return acc ^= (tempAddr >> xorBit) & UINT64_C(1); }); + encAddr &= ~(UINT64_C(1) << it[0]); + encAddr |= xoredBit << it[0]; } DecodedAddress decAddr; @@ -224,12 +257,16 @@ unsigned AddressDecoder::decodeChannel(uint64_t encAddr) const // For each used xor: // Get the first bit and second bit. Apply a bitwise xor operator and save it back to the // first bit. + auto tempAddr = encAddr; for (const auto& it : vXor) { - uint64_t xoredBit = - (((encAddr >> it.first) & UINT64_C(1)) ^ ((encAddr >> it.second) & UINT64_C(1))); - encAddr &= ~(UINT64_C(1) << it.first); - encAddr |= xoredBit << it.first; + uint64_t xoredBit = std::accumulate(it.cbegin(), + it.cend(), + 0, + [tempAddr](uint64_t acc, unsigned xorBit) + { return acc ^= (tempAddr >> xorBit) & UINT64_C(1); }); + encAddr &= ~(UINT64_C(1) << it[0]); + encAddr |= xoredBit << it[0]; } unsigned channel = 0; @@ -284,10 +321,13 @@ void AddressDecoder::print() const { uint64_t addressBits = (UINT64_C(1) << vChannelBits[static_cast::size_type>(it)]); - for (auto it2 : vXor) + for (auto xorMapping : vXor) { - if (it2.first == vChannelBits[static_cast::size_type>(it)]) - addressBits |= (UINT64_C(1) << it2.second); + if (xorMapping.at(0) == vChannelBits[static_cast::size_type>(it)]) + { + for (auto it = xorMapping.cbegin() + 1; it != xorMapping.cend(); it++) + addressBits |= (UINT64_C(1) << *it); + } } std::cout << " Ch " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl; @@ -297,10 +337,13 @@ void AddressDecoder::print() const { uint64_t addressBits = (UINT64_C(1) << vRankBits[static_cast::size_type>(it)]); - for (auto it2 : vXor) + for (auto xorMapping : vXor) { - if (it2.first == vRankBits[static_cast::size_type>(it)]) - addressBits |= (UINT64_C(1) << it2.second); + if (xorMapping.at(0) == vRankBits[static_cast::size_type>(it)]) + { + for (auto it = xorMapping.cbegin() + 1; it != xorMapping.cend(); it++) + addressBits |= (UINT64_C(1) << *it); + } } std::cout << " Ra " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl; @@ -310,10 +353,14 @@ void AddressDecoder::print() const { uint64_t addressBits = (UINT64_C(1) << vBankGroupBits[static_cast::size_type>(it)]); - for (auto it2 : vXor) + for (auto xorMapping : vXor) { - if (it2.first == vBankGroupBits[static_cast::size_type>(it)]) - addressBits |= (UINT64_C(1) << it2.second); + if (xorMapping.at(0) == + vBankGroupBits[static_cast::size_type>(it)]) + { + for (auto it = xorMapping.cbegin() + 1; it != xorMapping.cend(); it++) + addressBits |= (UINT64_C(1) << *it); + } } std::cout << " Bg " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl; @@ -323,10 +370,13 @@ void AddressDecoder::print() const { uint64_t addressBits = (UINT64_C(1) << vBankBits[static_cast::size_type>(it)]); - for (auto it2 : vXor) + for (auto xorMapping : vXor) { - if (it2.first == vBankBits[static_cast::size_type>(it)]) - addressBits |= (UINT64_C(1) << it2.second); + if (xorMapping.at(0) == vBankBits[static_cast::size_type>(it)]) + { + for (auto it = xorMapping.cbegin() + 1; it != xorMapping.cend(); it++) + addressBits |= (UINT64_C(1) << *it); + } } std::cout << " Ba " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl; @@ -336,10 +386,13 @@ void AddressDecoder::print() const { uint64_t addressBits = (UINT64_C(1) << vRowBits[static_cast::size_type>(it)]); - for (auto it2 : vXor) + for (auto xorMapping : vXor) { - if (it2.first == vRowBits[static_cast::size_type>(it)]) - addressBits |= (UINT64_C(1) << it2.second); + if (xorMapping.at(0) == vRowBits[static_cast::size_type>(it)]) + { + for (auto it = xorMapping.cbegin() + 1; it != xorMapping.cend(); it++) + addressBits |= (UINT64_C(1) << *it); + } } std::cout << " Ro " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl; @@ -349,10 +402,13 @@ void AddressDecoder::print() const { uint64_t addressBits = (UINT64_C(1) << vColumnBits[static_cast::size_type>(it)]); - for (auto it2 : vXor) + for (auto xorMapping : vXor) { - if (it2.first == vColumnBits[static_cast::size_type>(it)]) - addressBits |= (UINT64_C(1) << it2.second); + if (xorMapping.at(0) == vColumnBits[static_cast::size_type>(it)]) + { + for (auto it = xorMapping.cbegin() + 1; it != xorMapping.cend(); it++) + addressBits |= (UINT64_C(1) << *it); + } } std::cout << " Co " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl; @@ -362,10 +418,13 @@ void AddressDecoder::print() const { uint64_t addressBits = (UINT64_C(1) << vByteBits[static_cast::size_type>(it)]); - for (auto it2 : vXor) + for (auto xorMapping : vXor) { - if (it2.first == vByteBits[static_cast::size_type>(it)]) - addressBits |= (UINT64_C(1) << it2.second); + if (xorMapping.at(0) == vByteBits[static_cast::size_type>(it)]) + { + for (auto it = xorMapping.cbegin() + 1; it != xorMapping.cend(); it++) + addressBits |= (UINT64_C(1) << *it); + } } std::cout << " By " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl; diff --git a/src/libdramsys/DRAMSys/simulation/AddressDecoder.h b/src/libdramsys/DRAMSys/simulation/AddressDecoder.h index 4cb01668..053940da 100644 --- a/src/libdramsys/DRAMSys/simulation/AddressDecoder.h +++ b/src/libdramsys/DRAMSys/simulation/AddressDecoder.h @@ -81,11 +81,15 @@ struct DecodedAddress class AddressDecoder { public: - AddressDecoder(const DRAMSys::Config::AddressMapping& addressMapping, const MemSpec& memSpec); + AddressDecoder(const DRAMSys::Config::AddressMapping& addressMapping); + [[nodiscard]] DecodedAddress decodeAddress(uint64_t encAddr) const; [[nodiscard]] unsigned decodeChannel(uint64_t encAddr) const; [[nodiscard]] uint64_t encodeAddress(DecodedAddress decodedAddress) const; + [[nodiscard]] uint64_t maxAddress() const { return maximumAddress; } + void print() const; + void plausibilityCheck(const MemSpec &memSpec); private: unsigned banksPerGroup; @@ -95,7 +99,7 @@ private: // This container stores for each used xor gate a pair of address bits, the first bit is // overwritten with the result - std::vector> vXor; + std::vector> vXor; std::vector vChannelBits; std::vector vRankBits; std::vector vBankGroupBits; diff --git a/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp b/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp index e085624a..dec0463d 100644 --- a/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp +++ b/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp @@ -151,7 +151,8 @@ void DRAMSys::setupDebugManager([[maybe_unused]] const std::string& traceName) c void DRAMSys::instantiateModules(const ::DRAMSys::Config::AddressMapping& addressMapping) { - addressDecoder = std::make_unique(addressMapping, *config.memSpec); + addressDecoder = std::make_unique(addressMapping); + addressDecoder->plausibilityCheck(*config.memSpec); addressDecoder->print(); // Create arbiter diff --git a/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp b/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp index 22f7ba29..5c4159df 100644 --- a/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp +++ b/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp @@ -106,7 +106,8 @@ void DRAMSysRecordable::setupTlmRecorders(const std::string& traceName, void DRAMSysRecordable::instantiateModules(const std::string& traceName, const ::DRAMSys::Config::Configuration& configLib) { - addressDecoder = std::make_unique(configLib.addressmapping, *config.memSpec); + addressDecoder = std::make_unique(configLib.addressmapping); + addressDecoder->plausibilityCheck(*config.memSpec); addressDecoder->print(); // Create and properly initialize TLM recorders. diff --git a/src/simulator/CMakeLists.txt b/src/simulator/CMakeLists.txt index a485bbd8..91a9fc47 100644 --- a/src/simulator/CMakeLists.txt +++ b/src/simulator/CMakeLists.txt @@ -55,6 +55,8 @@ target_link_libraries(${PROJECT_NAME} DRAMSys::libdramsys ) +add_library(DRAMSys::simulator ALIAS ${PROJECT_NAME}) + add_executable(DRAMSys main.cpp ) diff --git a/tests/tests_configuration/test_configuration.cpp b/tests/tests_configuration/test_configuration.cpp index 5620704a..7b0bb8b6 100644 --- a/tests/tests_configuration/test_configuration.cpp +++ b/tests/tests_configuration/test_configuration.cpp @@ -62,15 +62,19 @@ protected: 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{ - {{0, 1}}, - {{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, - {{16}}, - {{13, 14, 15}}, - {{17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}}, - {{33}}, - std::nullopt, - std::nullopt, + 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}; DRAMSys::Config::McConfig mcConfig{PagePolicyType::Open, diff --git a/tests/tests_dramsys/AddressDecoderConfigs.h b/tests/tests_dramsys/AddressDecoderConfigs.h index 86f8816c..4f997e93 100644 --- a/tests/tests_dramsys/AddressDecoderConfigs.h +++ b/tests/tests_dramsys/AddressDecoderConfigs.h @@ -37,70 +37,6 @@ #include -inline constexpr std::string_view memSpecJsonString = R"( -{ - "memspec": { - "memarchitecturespec": { - "burstLength": 16, - "dataRate": 8, - "nbrOfBankGroups": 4, - "nbrOfBanks": 16, - "nbrOfColumns": 1024, - "nbrOfRows": 65536, - "nbrOfRanks": 1, - "nbrOfDevices": 1, - "nbrOfChannels": 1, - "width": 16, - "per2BankOffset": 8 - }, - "memoryId": "JEDEC_1Gbx16_BG_LPDDR5-6400", - "memoryType": "LPDDR5", - "memtimingspec": { - "RCD_L": 15, - "RCD_S": 15, - "PPD": 2, - "RPab": 17, - "RPpb": 15, - "RAS": 34, - "RCab": 51, - "RCpb": 48, - "FAW": 16, - "RRD": 4, - "RL": 17, - "WCK2CK": 0, - "WCK2DQO": 1, - "RBTP": 4, - "RPRE": 0, - "RPST": 0, - "WL": 9, - "WCK2DQI": 0, - "WPRE": 0, - "WPST": 0, - "WR": 28, - "WTR_L": 10, - "WTR_S": 5, - "CCDMW": 16, - "REFI": 3124, - "REFIpb": 390, - "RFCab": 224, - "RFCpb": 112, - "RTRS": 1, - "BL_n_min_16": 2, - "BL_n_max_16": 4, - "BL_n_L_16": 4, - "BL_n_S_16": 2, - "BL_n_min_32": 6, - "BL_n_max_32": 8, - "BL_n_L_32": 8, - "BL_n_S_32": 2, - "pbR2act": 6, - "pbR2pbR": 72, - "clkMhz": 800 - } - } -} -)"; - inline constexpr std::string_view addressMappingJsonString = R"( { "addressmapping": { diff --git a/tests/tests_dramsys/AddressDecoderTests.cpp b/tests/tests_dramsys/AddressDecoderTests.cpp index 748ae984..4abd9705 100644 --- a/tests/tests_dramsys/AddressDecoderTests.cpp +++ b/tests/tests_dramsys/AddressDecoderTests.cpp @@ -35,32 +35,23 @@ #include "AddressDecoderConfigs.h" +#include #include -#include #include class AddressDecoderFixture : public ::testing::Test { protected: AddressDecoderFixture() : - addressMappingJson(nlohmann::json::parse(addressMappingJsonString).at("addressmapping")), - memSpecJson(nlohmann::json::parse(memSpecJsonString).at("memspec")), - addressMappingConfig(addressMappingJson.get()), - memSpecConfig(memSpecJson.get()), - memSpec(memSpecConfig), - addressDecoder(addressMappingConfig, memSpec) + addressMappingConfig(nlohmann::json::parse(addressMappingJsonString) + .at("addressmapping") + .get()), + addressDecoder(addressMappingConfig) { } - nlohmann::json addressMappingJson; - nlohmann::json memSpecJson; - - // Configs DRAMSys::Config::AddressMapping addressMappingConfig; - DRAMSys::Config::MemSpec memSpecConfig; - - DRAMSys::MemSpecLPDDR5 memSpec; DRAMSys::AddressDecoder addressDecoder; }; @@ -116,4 +107,4 @@ TEST_F(AddressDecoderFixture, DeEncoding) EXPECT_EQ(encodedAddress, address); } -} \ No newline at end of file +} diff --git a/tests/tests_regression/DDR3/ddr3-example.json b/tests/tests_regression/DDR3/ddr3-example.json index 2f4f6f56..5e0fc2b9 100644 --- a/tests/tests_regression/DDR3/ddr3-example.json +++ b/tests/tests_regression/DDR3/ddr3-example.json @@ -1,14 +1,8 @@ { "simulation": { "addressmapping": { - "XOR": [ - { - "FIRST": 13, - "SECOND": 16 - } - ], "BANK_BIT": [ - 13, + [13, 16], 14, 15 ],