From e8e4899642aaa45b7f7742ca6b596c920b0b73c8 Mon Sep 17 00:00:00 2001 From: Matthias Jung Date: Sun, 8 Jul 2018 16:16:43 +0200 Subject: [PATCH] GRP Scheduler introduced. GRP is a simple read write grouper. However, it is not aware of the row-buffer and therfore it is just optimizing w.r.t to tWTR peanelty. For the functionality of row buffer management we refer to the FR_FCFS_GRP. This scheduler is mainly intersting for ConGen based applications. --- DRAMSys/library/library.pro | 5 +- .../resources/configs/mcconfigs/grp.xml | 17 ++ DRAMSys/library/resources/resources.pri | 21 +- DRAMSys/library/src/controller/Controller.cpp | 8 +- DRAMSys/library/src/controller/Controller.h | 1 + .../library/src/controller/scheduler/grp.cpp | 180 ++++++++++++++++++ .../scheduler/{Fifo_grouper.cpp => grp.h} | 49 +++-- 7 files changed, 239 insertions(+), 42 deletions(-) create mode 100644 DRAMSys/library/resources/configs/mcconfigs/grp.xml create mode 100644 DRAMSys/library/src/controller/scheduler/grp.cpp rename DRAMSys/library/src/controller/scheduler/{Fifo_grouper.cpp => grp.h} (65%) diff --git a/DRAMSys/library/library.pro b/DRAMSys/library/library.pro index fc25e98b..c589a80d 100644 --- a/DRAMSys/library/library.pro +++ b/DRAMSys/library/library.pro @@ -126,7 +126,7 @@ SOURCES += \ src/controller/RecordableController.cpp \ src/common/AddressDecoder.cpp \ src/common/jsonAddressDecoder.cpp \ - src/controller/scheduler/Fifo_grouper.cpp + src/controller/scheduler/grp.cpp HEADERS += \ src/common/third_party/tinyxml2/tinyxml2.h \ @@ -206,7 +206,8 @@ HEADERS += \ src/controller/RecordableController.h \ src/simulation/RecordableDram.h \ src/common/AddressDecoder.h \ - src/common/jsonAddressDecoder.h + src/common/jsonAddressDecoder.h \ + src/controller/scheduler/grp.h #src/common/third_party/json/include/nlohmann/json.hpp \ thermalsim = $$(THERMALSIM) diff --git a/DRAMSys/library/resources/configs/mcconfigs/grp.xml b/DRAMSys/library/resources/configs/mcconfigs/grp.xml new file mode 100644 index 00000000..d5474610 --- /dev/null +++ b/DRAMSys/library/resources/configs/mcconfigs/grp.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/library/resources/resources.pri b/DRAMSys/library/resources/resources.pri index aed0437f..6552a741 100644 --- a/DRAMSys/library/resources/resources.pri +++ b/DRAMSys/library/resources/resources.pri @@ -56,6 +56,7 @@ OTHER_FILES += resources/simulations/ddr3-ecc.xml OTHER_FILES += resources/simulations/sms-example.xml OTHER_FILES += resources/simulations/ddr3_postpone_ref_test.xml OTHER_FILES += resources/simulations/rgrsim.xml +OTHER_FILES += resources/simulations/lpddr4-single-device.xml # Simulator Files OTHER_FILES += resources/configs/simulator/wideio.xml @@ -66,6 +67,7 @@ OTHER_FILES += resources/configs/simulator/wideio_ecc.xml OTHER_FILES += resources/configs/simulator/ddr3_ecc.xml OTHER_FILES += resources/configs/simulator/sms.xml OTHER_FILES += resources/configs/simulator/rgrsimcfg.xml +OTHER_FILES += resources/configs/simulator/lpddr4.xml # Scripts OTHER_FILES += resources/scripts/address_scrambler.pl @@ -81,6 +83,7 @@ OTHER_FILES += resources/scripts/DRAMSylva/DRAMSylva.patch OTHER_FILES += resources/scripts/DRAMSylva/DRAMSylva.sh OTHER_FILES += resources/scripts/DRAMSylva/DRAMSylvaCSVPlot.py OTHER_FILES += resources/scripts/trace_gen.py +OTHER_FILES += resources/scripts/traceGenerationForNNTraining.pl # Trace Files OTHER_FILES += resources/traces/chstone-aes_32.stl @@ -131,6 +134,7 @@ OTHER_FILES += resources/traces/ddr3_postpone_ref_test_2.stl OTHER_FILES += resources/traces/ddr3_postpone_ref_test_3.stl OTHER_FILES += resources/traces/ip*.stl OTHER_FILES += resources/traces/rgr*.stl +OTHER_FILES += resources/traces/read_write_switch.stl # Memory Controller Configs OTHER_FILES += resources/configs/mcconfigs/fifoStrict.xml @@ -140,6 +144,9 @@ OTHER_FILES += resources/configs/mcconfigs/par_bs.xml OTHER_FILES += resources/configs/mcconfigs/fifo_ecc.xml OTHER_FILES += resources/configs/mcconfigs/sms.xml OTHER_FILES += resources/configs/mcconfigs/rgrmccfg.xml +OTHER_FILES += resources/configs/mcconfigs/grp.xml +OTHER_FILES += resources/configs/mcconfigs/fr_fcfs_rp.xml +OTHER_FILES += resources/configs/mcconfigs/fr_fcfs_grp.xml # Memspecs OTHER_FILES += resources/configs/memspecs/memspec.dtd @@ -186,6 +193,7 @@ OTHER_FILES += resources/configs/memspecs/wideio.xml OTHER_FILES += resources/configs/memspecs/wideio_less_refresh.xml OTHER_FILES += resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml OTHER_FILES += resources/configs/memspecs/rgrspec.xml +OTHER_FILES += resources/configs/memspecs/MICRON_6Gb_LPDDR4-3200_NDA_NDA_NDA.xml # Address Mapping Configs OTHER_FILES += resources/configs/amconfigs/am_ddr3.xml @@ -206,6 +214,8 @@ OTHER_FILES += resources/configs/amconfigs/am_ddr3_1Gbx8_p1KB_brc.xml OTHER_FILES += resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_brc.xml OTHER_FILES += resources/configs/amconfigs/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.xml OTHER_FILES += resources/configs/amconfigs/rgram.xml +OTHER_FILES += resources/configs/amconfigs/am_test_congen_output.json +OTHER_FILES += resources/configs/amconfigs/am_lpddr4.xml # Thermal Simulation configs OTHER_FILES += resources/configs/thermalsim/core.flp @@ -220,14 +230,3 @@ OTHER_FILES += src/common/third_party/DRAMPower/src/* # Error Simulation data OTHER_FILES += resources/error/wideio.csv - -DISTFILES += \ - $$PWD/traces/read_write_switch.stl \ - $$PWD/configs/mcconfigs/fr_fcfs_rp.xml \ - $$PWD/configs/mcconfigs/fr_fcfs_grp.xml \ - $$PWD/configs/simulator/lpddr4.xml \ - $$PWD/simulations/lpddr4-single-device.xml \ - $$PWD/configs/amconfigs/am_lpddr4.xml \ - $$PWD/configs/memspecs/MICRON_6Gb_LPDDR4-3200_NDA_NDA_NDA.xml \ - $$PWD/scripts/traceGenerationForNNTraining.pl \ - $$PWD/configs/amconfigs/am_test_congen_output.json diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index ad4879a3..5c93b209 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -53,6 +53,8 @@ void Controller::buildScheduler() scheduler = new FR_FCFS_RP(*controllerCore); } else if (selectedScheduler == "FR_FCFS_GRP") { scheduler = new FR_FCFS_GRP(*controllerCore, this); + } else if (selectedScheduler == "GRP") { + scheduler = new GRP(*controllerCore, this); } else if (selectedScheduler == "SMS") { scheduler = new SMS("SMS", *controllerCore, Configuration::getInstance().SJFProbability); @@ -209,8 +211,7 @@ void Controller::controllerCorePEQCallback(tlm_generic_payload &payload, else if (containsPhase(phase, { BEGIN_RD, BEGIN_WR, BEGIN_ACTB, BEGIN_ACT, BEGIN_PREB, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA })) { printDebugMessage("Controller has sent to DRAM this: " + phaseNameToString( phase) + " bank " + to_string(bank.ID())); - } - else + } else SC_REPORT_FATAL(0, "Controller Core PEQ in controller wrapper was triggered with unsupported phase"); } @@ -433,8 +434,7 @@ void Controller::dramPEQCallback(tlm_generic_payload &payload, scheduleNextFromScheduler(bank); } else if (containsPhase(phase, {END_PREB, END_PRE, END_ACTB, END_ACT})) { scheduleNextFromScheduler(bank); - } - else if (phase == END_PRE_ALL) { + } else if (phase == END_PRE_ALL) { // No need to trigger anything for a END_PRE_ALL. It is followed by a AUTO_REFRESH anyway (in our current // scheduler implementation) } else { diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index f09fedfa..efaae49e 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -65,6 +65,7 @@ #include "core/scheduling/Trigger.h" #include "core/TimingCalculation.h" #include "scheduler/Fifo.h" +#include "scheduler/grp.h" #include "scheduler/FifoStrict.h" #include "scheduler/Fr_Fcfs.h" #include "scheduler/Fr_Fcfs_read_priority.h" diff --git a/DRAMSys/library/src/controller/scheduler/grp.cpp b/DRAMSys/library/src/controller/scheduler/grp.cpp new file mode 100644 index 00000000..652405aa --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/grp.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018, University of Kaiserslautern + * 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: + * Matthias Jung + */ + +#include "grp.h" + +// GRP just reorders w.r.t. read write grouping, however is not aware of the +// row buffer. For a row buffer aware grouper refer to FR_FCFS_GRP. +// TODO: what is missed is a check if the buffers are full. This will only work +// if we have buffers with a fixed size (Prado's future patch). + +std::pair GRP::getNextRequest(Bank bank) +{ + // If the bank is empty we do nothing: + if (buffer[bank].empty()) { + return pair(Command::NOP, NULL); + } + + // If we are in write mode we should check if we should switch to read mode + // because there are no writes anymore in the buffer. + if (readMode == false) { + if (getNumberOfRequest(tlm::TLM_WRITE_COMMAND) == 0) { + readMode = true; + } + } else { // If we are in read mode but all reads are served we switch to write + if (getNumberOfRequest(tlm::TLM_READ_COMMAND) == 0) { + readMode = false; + } + } + + // Now lets search for read and write commands. However keep in mind that + // readMode is a shared variable for all the banks! + if (readMode == true) { + // 1. Seach for read hit: + for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { + gp *read = *it; + + if (read->get_command() == tlm::TLM_READ_COMMAND) { + // If there is a row hit: + if (DramExtension::getRow(read) + == controllerCore.getRowBufferStates() + .getRowInRowBuffer(bank)) { + if (hazardDetection(bank, it) == false) { + buffer[bank].erase(it); + printDebugMessage("Read Hit found"); + return pair(getReadWriteCommand(*read), + read); + } else { + // If there was a hazard, switch the mode and try again: + readMode = false; + return getNextRequest(bank); + } + } else { // if there is a row miss: + if (hazardDetection(bank, it) == false) { + printDebugMessage("Read miss found"); + return pair(getNextCommand(read), read); + } else { + // If there was a hazard, switch the mode and try again: + readMode = false; + return getNextRequest(bank); + } + } + } + } + + } else { // write mode: + // 3. Search for write hit: + for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) { + gp *write = *it; + + if (write->get_command() == tlm::TLM_WRITE_COMMAND) { + // If there is a row hit: + if (DramExtension::getRow(write) + == controllerCore.getRowBufferStates() + .getRowInRowBuffer(bank)) { + buffer[bank].erase(it); + printDebugMessage("Write Hit found"); + return pair(getReadWriteCommand(*write), + write); + } else { + printDebugMessage("Write miss found"); + return pair(getNextCommand(write), write); + } + } + } + } + + // If nothing was found we check the other banks before we switch the mode: + pair other(Command::NOP, NULL); + unsigned int B = Configuration::getInstance().memSpec.NumberOfBanks; + + for (unsigned int i = 1; i < B; i++) { + Bank nextBank((bank.ID() + i) % B); + ctrl->scheduleNextFromScheduler(nextBank); + } + + // If nothing was found in the current mode, switch the mode and try again: + // FIXME: this is in my opinion not so clever yet, because we switch maybe + // even though there are still reads/writes request on other banks ... + readMode = !readMode; + return getNextRequest(bank); + + reportFatal("GRP", "Never should go here ..."); +} + +// There is a hazard if a read is found which will be scheduled before a write +// to the same column and the same row of the same bank: +bool GRP::hazardDetection(Bank bank, std::deque::iterator ext) +{ + gp *read = *ext; + + //for(unsigned long i=0; i < id; i++) + for (auto it = buffer[bank].begin(); it != ext; it++) { + gp *write = *it; + if (write->get_command() == tlm::TLM_WRITE_COMMAND) { + if ((DramExtension::getExtension(read).getColumn() + == DramExtension::getExtension(write).getColumn()) + && (DramExtension::getExtension(read).getRow() + == DramExtension::getExtension(write).getRow())) { + printDebugMessage("Hazard Detected"); + return true; + } + } + } + return false; +} + +// Estimate the number of writes/reads in all bank buffers: +unsigned int GRP::getNumberOfRequest(tlm::tlm_command cmd) +{ + unsigned int numberOfRequests = 0; + for (unsigned int i = 0; + i < Configuration::getInstance().memSpec.NumberOfBanks; + i++) { + for (auto it = buffer[i].begin(); it != buffer[i].end(); it++) { + gp *trans = *it; + if (trans->get_command() == cmd) { + numberOfRequests++; + } + } + } + + return numberOfRequests; +} + +void GRP::printDebugMessage(std::string message) +{ + DebugManager::getInstance().printDebugMessage("FR_FCFS_GRP", message); +} diff --git a/DRAMSys/library/src/controller/scheduler/Fifo_grouper.cpp b/DRAMSys/library/src/controller/scheduler/grp.h similarity index 65% rename from DRAMSys/library/src/controller/scheduler/Fifo_grouper.cpp rename to DRAMSys/library/src/controller/scheduler/grp.h index fe041319..2ffc46e0 100644 --- a/DRAMSys/library/src/controller/scheduler/Fifo_grouper.cpp +++ b/DRAMSys/library/src/controller/scheduler/grp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2018, University of Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,38 +30,37 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: - * Robert Gernhardt * Matthias Jung */ -#include "Fifo.h" +#ifndef GROUPER_H +#define GROUPER_H -using namespace std; +#include "Fr_Fcfs.h" +#include "../Controller.h" -void Fifo::schedule(gp *payload) +class Controller; + +class GRP : public FR_FCFS { - buffer[DramExtension::getExtension(payload).getBank()].emplace_back(payload); -} - -pair Fifo::getNextRequest(Bank bank) -{ - if (!buffer[bank].empty()) { - gp *payload = buffer[bank].front(); - Command command = IScheduler::getNextCommand(*payload); - if (command == Command::Read || command == Command::ReadA - || command == Command::Write || command == Command::WriteA) { - buffer[bank].pop_front(); - } - - return pair(command, payload); +public: + GRP(ControllerCore &controllerCore, Controller *c) : + FR_FCFS(controllerCore), + ctrl(c), + readMode(true) + { } - return pair(Command::NOP, NULL); -} + std::pair + getNextRequest(Bank bank) override; -gp *Fifo::getPendingRequest(Bank /*bank*/) -{ - return NULL; -} +private: + Controller *ctrl; + bool hazardDetection(Bank bank, std::deque::iterator ext); + unsigned int getNumberOfRequest(tlm::tlm_command cmd); + void printDebugMessage(std::string message); + bool readMode; +}; +#endif // GROUPER_H