diff --git a/src/libdramsys/DRAMSys/controller/Controller.cpp b/src/libdramsys/DRAMSys/controller/Controller.cpp index fedc589c..e609cf04 100644 --- a/src/libdramsys/DRAMSys/controller/Controller.cpp +++ b/src/libdramsys/DRAMSys/controller/Controller.cpp @@ -81,8 +81,9 @@ namespace DRAMSys Controller::Controller(const sc_module_name& name, const Configuration& config, + const MemSpec& memSpec, const AddressDecoder& addressDecoder) : - ControllerIF(name, config), + memSpec(memSpec), thinkDelayFw(config.thinkDelayFw), thinkDelayBw(config.thinkDelayBw), phyDelayFw(config.phyDelayFw), @@ -96,6 +97,13 @@ Controller::Controller(const sc_module_name& name, SC_METHOD(controllerMethod); sensitive << beginReqEvent << endRespEvent << controllerEvent << dataResponseEvent; + tSocket.register_nb_transport_fw(this, &Controller::nb_transport_fw); + tSocket.register_transport_dbg(this, &Controller::transport_dbg); + tSocket.register_b_transport(this, &Controller::b_transport); + iSocket.register_nb_transport_bw(this, &Controller::nb_transport_bw); + + idleTimeCollector.start(); + ranksNumberOfPayloads = ControllerVector(memSpec.ranksPerChannel); // reserve buffer for command tuples @@ -273,11 +281,6 @@ Controller::Controller(const sc_module_name& name, SC_REPORT_FATAL("Controller", "Selected refresh mode not supported!"); } -bool Controller::idle() const -{ - return totalNumberOfPayloads == 0; -} - void Controller::registerIdleCallback(std::function idleCallback) { this->idleCallback = std::move(idleCallback); @@ -736,4 +739,42 @@ void Controller::createChildTranses(tlm::tlm_generic_payload& parentTrans) ParentExtension::setExtension(parentTrans, std::move(childTranses)); } +void Controller::end_of_simulation() +{ + idleTimeCollector.end(); + + sc_core::sc_time activeTime = static_cast(numberOfBeatsServed) / memSpec.dataRate * + memSpec.tCK / memSpec.pseudoChannelsPerChannel; + + double bandwidth = activeTime / sc_core::sc_time_stamp(); + double bandwidthWoIdle = + activeTime / (sc_core::sc_time_stamp() - idleTimeCollector.getIdleTime()); + + double maxBandwidth = ( + // fCK in GHz e.g. 1 [GHz] (tCK in ps): + (1000 / memSpec.tCK.to_double()) + // DataRate e.g. 2 + * memSpec.dataRate + // BusWidth e.g. 8 or 64 + * memSpec.bitWidth + // Number of devices that form a rank, e.g., 8 on a DDR3 DIMM + * memSpec.devicesPerRank + // HBM specific, one or two pseudo channels per channel + * memSpec.pseudoChannelsPerChannel); + + std::cout << name() << std::string(" Total Time: ") << sc_core::sc_time_stamp().to_string() + << std::endl; + std::cout << name() << std::string(" AVG BW: ") << std::fixed << std::setprecision(2) + << std::setw(6) << (bandwidth * maxBandwidth) << " Gb/s | " << std::setw(6) + << (bandwidth * maxBandwidth / 8) << " GB/s | " << std::setw(6) << (bandwidth * 100) + << " %" << std::endl; + std::cout << name() << std::string(" AVG BW\\IDLE: ") << std::fixed << std::setprecision(2) + << std::setw(6) << (bandwidthWoIdle * maxBandwidth) << " Gb/s | " << std::setw(6) + << (bandwidthWoIdle * maxBandwidth / 8) << " GB/s | " << std::setw(6) + << (bandwidthWoIdle * 100) << " %" << std::endl; + std::cout << name() << std::string(" MAX BW: ") << std::fixed << std::setprecision(2) + << std::setw(6) << maxBandwidth << " Gb/s | " << std::setw(6) << maxBandwidth / 8 + << " GB/s | " << std::setw(6) << 100.0 << " %" << std::endl; +} + } // namespace DRAMSys diff --git a/src/libdramsys/DRAMSys/controller/Controller.h b/src/libdramsys/DRAMSys/controller/Controller.h index 39dae470..5102f1c8 100644 --- a/src/libdramsys/DRAMSys/controller/Controller.h +++ b/src/libdramsys/DRAMSys/controller/Controller.h @@ -35,9 +35,9 @@ #ifndef CONTROLLER_H #define CONTROLLER_H +#include "DRAMSys/common/DebugManager.h" #include "DRAMSys/controller/BankMachine.h" #include "DRAMSys/controller/Command.h" -#include "DRAMSys/controller/ControllerIF.h" #include "DRAMSys/controller/checker/CheckerIF.h" #include "DRAMSys/controller/cmdmux/CmdMuxIF.h" #include "DRAMSys/controller/powerdown/PowerDownManagerIF.h" @@ -45,41 +45,51 @@ #include "DRAMSys/controller/respqueue/RespQueueIF.h" #include "DRAMSys/simulation/AddressDecoder.h" +#include #include #include #include +#include +#include #include #include namespace DRAMSys { -class Controller : public ControllerIF +class Controller : public sc_core::sc_module { public: + tlm_utils::simple_target_socket tSocket{"tSocket"}; // Arbiter side + tlm_utils::simple_initiator_socket iSocket{"iSocket"}; // DRAM side + Controller(const sc_core::sc_module_name& name, const Configuration& config, + const MemSpec& memSpec, const AddressDecoder& addressDecoder); SC_HAS_PROCESS(Controller); - [[nodiscard]] bool idle() const override; + [[nodiscard]] bool idle() const { return totalNumberOfPayloads == 0; } void registerIdleCallback(std::function idleCallback); protected: - tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans, + void end_of_simulation() override; + + virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, - sc_core::sc_time& delay) override; - tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans, + sc_core::sc_time& delay); + virtual tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, - sc_core::sc_time& delay) override; - void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) override; - unsigned int transport_dbg(tlm::tlm_generic_payload& trans) override; + sc_core::sc_time& delay); + void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay); + unsigned int transport_dbg(tlm::tlm_generic_payload& trans); virtual void sendToFrontend(tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay); virtual void controllerMethod(); + const MemSpec& memSpec; std::unique_ptr scheduler; const sc_core::sc_time scMaxTime = sc_core::sc_max_time(); @@ -90,7 +100,7 @@ protected: const sc_core::sc_time blockingReadDelay; const sc_core::sc_time blockingWriteDelay; -private: + uint64_t numberOfBeatsServed = 0; unsigned totalNumberOfPayloads = 0; std::function idleCallback; ControllerVector ranksNumberOfPayloads; @@ -139,6 +149,37 @@ private: private: std::stack freePayloads; } memoryManager; + + class IdleTimeCollector + { + public: + void start() + { + if (!isIdle) + { + PRINTDEBUGMESSAGE("IdleTimeCollector", "IDLE start"); + idleStart = sc_core::sc_time_stamp(); + isIdle = true; + } + } + + void end() + { + if (isIdle) + { + PRINTDEBUGMESSAGE("IdleTimeCollector", "IDLE end"); + idleTime += sc_core::sc_time_stamp() - idleStart; + isIdle = false; + } + } + + sc_core::sc_time getIdleTime() { return idleTime; } + + private: + bool isIdle = false; + sc_core::sc_time idleTime = sc_core::SC_ZERO_TIME; + sc_core::sc_time idleStart; + } idleTimeCollector; }; } // namespace DRAMSys diff --git a/src/libdramsys/DRAMSys/controller/ControllerIF.h b/src/libdramsys/DRAMSys/controller/ControllerIF.h deleted file mode 100644 index 4b0de78d..00000000 --- a/src/libdramsys/DRAMSys/controller/ControllerIF.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2019, 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: - * Kirill Bykov - * Lukas Steiner - */ - -#ifndef CONTROLLERIF_H -#define CONTROLLERIF_H - -#include "DRAMSys/common/DebugManager.h" -#include "DRAMSys/configuration/Configuration.h" - -#include -#include -#include -#include -#include - -namespace DRAMSys -{ - -// Utility class to pass around DRAMSys, without having to propagate the template definitions -// throughout all classes -class ControllerIF : public sc_core::sc_module -{ -public: - // Already create and bind sockets to the virtual functions - tlm_utils::simple_target_socket tSocket; // Arbiter side - tlm_utils::simple_initiator_socket iSocket; // DRAM side - - void end_of_simulation() override - { - idleTimeCollector.end(); - - sc_core::sc_time activeTime = static_cast(numberOfBeatsServed) / memSpec.dataRate * - memSpec.tCK / memSpec.pseudoChannelsPerChannel; - - double bandwidth = activeTime / sc_core::sc_time_stamp(); - double bandwidthWoIdle = - activeTime / (sc_core::sc_time_stamp() - idleTimeCollector.getIdleTime()); - - double maxBandwidth = ( - // fCK in GHz e.g. 1 [GHz] (tCK in ps): - (1000 / memSpec.tCK.to_double()) - // DataRate e.g. 2 - * memSpec.dataRate - // BusWidth e.g. 8 or 64 - * memSpec.bitWidth - // Number of devices that form a rank, e.g., 8 on a DDR3 DIMM - * memSpec.devicesPerRank - // HBM specific, one or two pseudo channels per channel - * memSpec.pseudoChannelsPerChannel); - - std::cout << name() << std::string(" Total Time: ") - << sc_core::sc_time_stamp().to_string() << std::endl; - std::cout << name() << std::string(" AVG BW: ") << std::fixed - << std::setprecision(2) << std::setw(6) << (bandwidth * maxBandwidth) - << " Gb/s | " << std::setw(6) << (bandwidth * maxBandwidth / 8) << " GB/s | " - << std::setw(6) << (bandwidth * 100) << " %" << std::endl; - std::cout << name() << std::string(" AVG BW\\IDLE: ") << std::fixed - << std::setprecision(2) << std::setw(6) << (bandwidthWoIdle * maxBandwidth) - << " Gb/s | " << std::setw(6) << (bandwidthWoIdle * maxBandwidth / 8) - << " GB/s | " << std::setw(6) << (bandwidthWoIdle * 100) << " %" << std::endl; - std::cout << name() << std::string(" MAX BW: ") << std::fixed - << std::setprecision(2) << std::setw(6) << maxBandwidth << " Gb/s | " - << std::setw(6) << maxBandwidth / 8 << " GB/s | " << std::setw(6) << 100.0 << " %" - << std::endl; - } - - [[nodiscard]] virtual bool idle() const = 0; - -protected: - const MemSpec& memSpec; - - // Bind sockets with virtual functions - ControllerIF(const sc_core::sc_module_name& name, const Configuration& config) : - sc_core::sc_module(name), - tSocket("tSocket"), - iSocket("iSocket"), - memSpec(*config.memSpec) - { - tSocket.register_nb_transport_fw(this, &ControllerIF::nb_transport_fw); - tSocket.register_transport_dbg(this, &ControllerIF::transport_dbg); - tSocket.register_b_transport(this, &ControllerIF::b_transport); - iSocket.register_nb_transport_bw(this, &ControllerIF::nb_transport_bw); - - idleTimeCollector.start(); - } - SC_HAS_PROCESS(ControllerIF); - - // Virtual transport functions - virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans, - tlm::tlm_phase& phase, - sc_core::sc_time& delay) = 0; - virtual tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans, - tlm::tlm_phase& phase, - sc_core::sc_time& delay) = 0; - virtual void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) = 0; - virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans) = 0; - - // Bandwidth related - class IdleTimeCollector - { - public: - void start() - { - if (!isIdle) - { - PRINTDEBUGMESSAGE("IdleTimeCollector", "IDLE start"); - idleStart = sc_core::sc_time_stamp(); - isIdle = true; - } - } - - void end() - { - if (isIdle) - { - PRINTDEBUGMESSAGE("IdleTimeCollector", "IDLE end"); - idleTime += sc_core::sc_time_stamp() - idleStart; - isIdle = false; - } - } - - sc_core::sc_time getIdleTime() { return idleTime; } - - private: - bool isIdle = false; - sc_core::sc_time idleTime = sc_core::SC_ZERO_TIME; - sc_core::sc_time idleStart; - } idleTimeCollector; - - uint64_t numberOfBeatsServed = 0; -}; - -} // namespace DRAMSys - -#endif // CONTROLLERIF_H diff --git a/src/libdramsys/DRAMSys/controller/ControllerRecordable.cpp b/src/libdramsys/DRAMSys/controller/ControllerRecordable.cpp index c5af3390..1c2f618d 100644 --- a/src/libdramsys/DRAMSys/controller/ControllerRecordable.cpp +++ b/src/libdramsys/DRAMSys/controller/ControllerRecordable.cpp @@ -44,9 +44,10 @@ namespace DRAMSys ControllerRecordable::ControllerRecordable(const sc_module_name& name, const Configuration& config, + const MemSpec& memSpec, const AddressDecoder& addressDecoder, TlmRecorder& tlmRecorder) : - Controller(name, config, addressDecoder), + Controller(name, config, memSpec, addressDecoder), tlmRecorder(tlmRecorder), windowSizeTime(config.windowSize * memSpec.tCK), activeTimeMultiplier(config.memSpec->tCK / config.memSpec->dataRate), diff --git a/src/libdramsys/DRAMSys/controller/ControllerRecordable.h b/src/libdramsys/DRAMSys/controller/ControllerRecordable.h index ac21c5b4..1cda2d27 100644 --- a/src/libdramsys/DRAMSys/controller/ControllerRecordable.h +++ b/src/libdramsys/DRAMSys/controller/ControllerRecordable.h @@ -49,6 +49,7 @@ class ControllerRecordable final : public Controller public: ControllerRecordable(const sc_core::sc_module_name& name, const Configuration& config, + const MemSpec& memSpec, const AddressDecoder& addressDecoder, TlmRecorder& tlmRecorder); diff --git a/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp b/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp index dec0463d..2b80ad43 100644 --- a/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp +++ b/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp @@ -167,7 +167,7 @@ void DRAMSys::instantiateModules(const ::DRAMSys::Config::AddressMapping& addres for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++) { controllers.emplace_back(std::make_unique( - ("controller" + std::to_string(i)).c_str(), config, *addressDecoder)); + ("controller" + std::to_string(i)).c_str(), config, *config.memSpec, *addressDecoder)); drams.emplace_back(std::make_unique(("dram" + std::to_string(i)).c_str(), config)); diff --git a/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp b/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp index 5c4159df..33a8753b 100644 --- a/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp +++ b/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp @@ -125,8 +125,12 @@ void DRAMSysRecordable::instantiateModules(const std::string& traceName, // Create controllers and DRAMs for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++) { - controllers.emplace_back(std::make_unique( - ("controller" + std::to_string(i)).c_str(), config, *addressDecoder, tlmRecorders[i])); + controllers.emplace_back( + std::make_unique(("controller" + std::to_string(i)).c_str(), + config, + *config.memSpec, + *addressDecoder, + tlmRecorders[i])); drams.emplace_back(std::make_unique( ("dram" + std::to_string(i)).c_str(), config, tlmRecorders[i]));