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.
This commit is contained in:
Matthias Jung
2018-07-08 16:16:43 +02:00
parent e422aee1c8
commit e8e4899642
7 changed files with 239 additions and 42 deletions

View File

@@ -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)

View File

@@ -0,0 +1,17 @@
<mcconfig>
<BankwiseLogic value="0"/>
<OpenPagePolicy value="1" />
<MaxNrOfTransactions value="32" />
<Scheduler value="GRP" />
<Capsize value="5" />
<!-- 4 Modes: NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF -->
<PowerDownMode value="NoPowerDown" />
<PowerDownTimeout value="100" />
<!-- Error Modelling -->
<ControllerCoreDisableRefresh value="0"/>
<ControllerCoreForceMaxRefBurst value="0"/>
<ControllerCoreEnableRefPostpone value="0"/>
<ControllerCoreEnableRefPullIn value="0"/>
<ControllerCoreMaxPostponedARCmd value="8"/>
<ControllerCoreMaxPulledInARCmd value="8"/>
</mcconfig>

View File

@@ -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

View File

@@ -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 {

View File

@@ -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"

View File

@@ -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<Command, gp *> GRP::getNextRequest(Bank bank)
{
// If the bank is empty we do nothing:
if (buffer[bank].empty()) {
return pair<Command, tlm::tlm_generic_payload *>(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<Command, gp *>(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<Command, gp *>(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<Command, gp *>(getReadWriteCommand(*write),
write);
} else {
printDebugMessage("Write miss found");
return pair<Command, gp *>(getNextCommand(write), write);
}
}
}
}
// If nothing was found we check the other banks before we switch the mode:
pair<Command, gp *> 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<gp *>::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);
}

View File

@@ -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<Command, tlm::tlm_generic_payload *> 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, tlm::tlm_generic_payload *>(command, payload);
public:
GRP(ControllerCore &controllerCore, Controller *c) :
FR_FCFS(controllerCore),
ctrl(c),
readMode(true)
{
}
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
std::pair<Command, tlm::tlm_generic_payload *>
getNextRequest(Bank bank) override;
gp *Fifo::getPendingRequest(Bank /*bank*/)
{
return NULL;
}
private:
Controller *ctrl;
bool hazardDetection(Bank bank, std::deque<gp *>::iterator ext);
unsigned int getNumberOfRequest(tlm::tlm_command cmd);
void printDebugMessage(std::string message);
bool readMode;
};
#endif // GROUPER_H