Implemented initial version of timing checker for WideIO.

This commit is contained in:
Lukas Steiner (2)
2019-08-20 10:58:28 +02:00
parent 2ef1c2b189
commit 4881b8ae76
7 changed files with 388 additions and 14 deletions

View File

@@ -132,7 +132,8 @@ SOURCES += \
src/controller/checker/CheckerDDR3.cpp \
src/controller/refresh/RefreshManager.cpp \
src/controller/refresh/RefreshManagerDummy.cpp \
src/controller/refresh/RefreshManagerBankwise.cpp
src/controller/refresh/RefreshManagerBankwise.cpp \
src/controller/checker/CheckerWideIO.cpp
HEADERS += \
src/common/third_party/tinyxml2/tinyxml2.h \
@@ -199,7 +200,8 @@ HEADERS += \
src/controller/refresh/RefreshManagerIF.h \
src/controller/refresh/RefreshManager.h \
src/controller/refresh/RefreshManagerDummy.h \
src/controller/refresh/RefreshManagerBankwise.h
src/controller/refresh/RefreshManagerBankwise.h \
src/controller/checker/CheckerWideIO.h
#src/common/third_party/json/include/nlohmann/json.hpp \
thermalsim = $$(THERMALSIM)

View File

@@ -43,6 +43,7 @@
#include "../common/protocol.h"
#include "core/scheduling/ScheduledCommand.h"
#include "checker/CheckerDDR3.h"
#include "checker/CheckerWideIO.h"
#include "refresh/RefreshManager.h"
#include "refresh/RefreshManagerDummy.h"
#include "refresh/RefreshManagerBankwise.h"
@@ -57,7 +58,13 @@ ControllerNew::ControllerNew(sc_module_name name) :
Configuration config = Configuration::getInstance();
checker = new CheckerDDR3();
if (config.memSpec->MemoryType == "DDR3")
checker = new CheckerDDR3();
else if (config.memSpec->MemoryType == "WIDEIO_SDR")
checker = new CheckerWideIO();
else
SC_REPORT_FATAL("ControllerNew", "Unsupported DRAM type");
if (config.ControllerCoreRefDisable)
refreshManager = new RefreshManagerDummy();
else if (config.BankwiseLogic)
@@ -70,6 +77,7 @@ ControllerNew::ControllerNew(sc_module_name name) :
refreshManager = new RefreshManager(bankMachines);
refreshEvent.notify(refreshManager->getTriggerDelay());
}
if (config.Scheduler == "FifoStrict")
{
scheduler = new SchedulerFifo();
@@ -82,6 +90,7 @@ ControllerNew::ControllerNew(sc_module_name name) :
}
else
SC_REPORT_FATAL("ControllerNew", "Selected scheduler not supported");
for (unsigned bankID = 0; bankID < Configuration::getInstance().memSpec->NumberOfBanks; bankID++)
bankMachines[Bank(bankID)] = new BankMachine(scheduler, checker, Bank(bankID));

View File

@@ -172,7 +172,6 @@ void CheckerDDR3::insert(const ScheduledCommand &scheduledCommand)
lastScheduledByCommand[command] = scheduledCommand;
lastScheduled = scheduledCommand;
// TODO: implement FAW for ACTB
if (command == Command::ACT)
{
if (lastActivates.size() == 4)

View File

@@ -58,9 +58,6 @@ private:
std::queue<sc_time> lastActivates;
void delayToSatisfyFAW(sc_time &);
sc_time timeForNextREFA;
sc_time timeForNextPREA;
RefreshCheckerDDR3Dummy *refreshChecker;
// PowerDown TODO: Implement this method?

View File

@@ -0,0 +1,252 @@
/*
* Copyright (c) 2019, 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.
*
* Author: Lukas Steiner
*/
#include "CheckerWideIO.h"
CheckerWideIO::CheckerWideIO()
{
Configuration config = Configuration::getInstance();
memSpec = dynamic_cast<MemSpecWideIO *>(config.memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerWideIO", "Wrong MemSpec chosen");
if (config.ControllerCoreRefDisable)
refreshChecker = new RefreshCheckerWideIODummy(memSpec);
else if (config.BankwiseLogic)
refreshChecker = new RefreshCheckerWideIOBankwise(memSpec);
else
refreshChecker = new RefreshCheckerWideIO(memSpec);
}
CheckerWideIO::~CheckerWideIO()
{
delete refreshChecker;
}
sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Bank bank)
{
ScheduledCommand lastCommand;
sc_time earliestTimeToStart = sc_time_stamp();
if (command == Command::ACT)
{
lastCommand = lastScheduledByCommandAndBank[Command::RDA][bank];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRTP + memSpec->tRP);
lastCommand = lastScheduledByCommandAndBank[Command::WRA][bank];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->tRP);
lastCommand = lastScheduledByCommandAndBank[Command::PRE][bank];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRP);
lastCommand = lastScheduledByCommandAndBank[Command::ACT][bank];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRC);
lastCommand = lastScheduledByCommand[Command::ACT];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRRD);
lastCommand = lastScheduledByCommand[Command::REFA];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRFC);
lastCommand = lastScheduledByCommandAndBank[Command::REFB][bank];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRFC);
delayToSatisfyTAW(earliestTimeToStart);
refreshChecker->delayToSatisfyACT(bank, earliestTimeToStart);
}
else if (command == Command::RD || command == Command::RDA)
{
lastCommand = lastScheduledByCommandAndBank[Command::ACT][bank];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRCD);
lastCommand = lastScheduledByCommand[Command::RD];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tCCD);
lastCommand = lastScheduledByCommand[Command::WR];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tWL + memSpec->tCCD + memSpec->tWTR);
refreshChecker->delayToSatisfyRD(bank, earliestTimeToStart);
}
else if (command == Command::WR || command == Command::WRA)
{
lastCommand = lastScheduledByCommandAndBank[Command::ACT][bank];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRCD);
lastCommand = lastScheduledByCommand[Command::RD];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRL + memSpec->tCCD + 2 * memSpec->clk - memSpec->tWL);
lastCommand = lastScheduledByCommand[Command::WR];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tCCD);
refreshChecker->delayToSatisfyWR(bank, earliestTimeToStart);
}
else if (command == Command::PRE)
{
lastCommand = lastScheduledByCommandAndBank[Command::ACT][bank];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRAS);
lastCommand = lastScheduledByCommandAndBank[Command::RD][bank];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRTP);
lastCommand = lastScheduledByCommandAndBank[Command::WR][bank];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tWL + memSpec->tCCD + memSpec->tWR);
refreshChecker->delayToSatisfyPRE(bank, earliestTimeToStart);
}
else
{
reportFatal("CheckerWideIO", "Unknown command!");
}
// Check if command bus is free
if (lastScheduled.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled.getStart() + memSpec->clk);
return (earliestTimeToStart - sc_time_stamp());
}
void CheckerWideIO::delayToSatisfyTAW(sc_time &earliestTimeToStart)
{
if (lastActivates.size() >= 2)
{
sc_time earliestTime = lastActivates.front() + memSpec->tTAW;
if (earliestTime > earliestTimeToStart)
earliestTimeToStart = earliestTime;
}
}
void CheckerWideIO::insert(const ScheduledCommand &scheduledCommand)
{
Command command = scheduledCommand.getCommand();
Bank bank = scheduledCommand.getBank();
PRINTDEBUGMESSAGE("CheckerWideIO", "Changing state on bank " +
to_string(scheduledCommand.getBank().ID()) +
" command is " + commandToString(command));
lastScheduledByCommandAndBank[command][bank] = scheduledCommand;
lastScheduledByCommand[command] = scheduledCommand;
lastScheduled = scheduledCommand;
if (command == Command::ACT)
{
if (lastActivates.size() == 2)
lastActivates.pop();
lastActivates.push(scheduledCommand.getStart());
}
else if (command == Command::REFA || command == Command::REFB)
refreshChecker->insert(bank);
}
// TODO: max(earliestTimeToStart, ...) needed?
void RefreshCheckerWideIO::delayToSatisfyACT(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRAS))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::delayToSatisfyRD(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRTP))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::delayToSatisfyWR(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::delayToSatisfyPRE(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= timeForNextPREA)
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::insert(Bank)
{
timeForNextREFA += memSpec->tREFI;
timeForNextPREA += memSpec->tREFI;
}
RefreshCheckerWideIOBankwise::RefreshCheckerWideIOBankwise(const MemSpecWideIO *memSpec)
: RefreshCheckerWideIODummy(memSpec)
{
sc_time currentREFB = memSpec->tREFI - memSpec->clk * (memSpec->NumberOfBanks - 1);
sc_time currentPRE = currentREFB - std::max(memSpec->clk * memSpec->NumberOfBanks, memSpec->tRP);
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
{
timesForNextREFB[Bank(bankID)] = currentREFB;
timesForNextPRE[Bank(bankID)] = currentPRE;
currentREFB += memSpec->clk;
currentPRE += memSpec->clk;
}
}
void RefreshCheckerWideIOBankwise::delayToSatisfyACT(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank] - memSpec->tRAS))
earliestTimeToStart = timesForNextREFB[bank] + memSpec->tRFC;
}
void RefreshCheckerWideIOBankwise::delayToSatisfyRD(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank] - memSpec->tRTP))
earliestTimeToStart = timesForNextREFB[bank] + memSpec->tRFC;
}
void RefreshCheckerWideIOBankwise::delayToSatisfyWR(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank] - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timesForNextREFB[bank] + memSpec->tRFC;
}
void RefreshCheckerWideIOBankwise::insert(Bank bank)
{
timesForNextREFB[bank] += memSpec->tREFI;
timesForNextPRE[bank] += memSpec->tREFI;
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2019, 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.
*
* Author: Lukas Steiner
*/
#ifndef CHECKERWIDEIO_H
#define CHECKERWIDEIO_H
#include "CheckerIF.h"
#include <queue>
#include <map>
#include "../core/configuration/MemSpec.h"
#include "../core/configuration/Configuration.h"
class RefreshCheckerWideIODummy;
class CheckerWideIO final : public CheckerIF
{
public:
CheckerWideIO();
~CheckerWideIO();
sc_time delayToSatisfyConstraints(Command, Bank);
void insert(const ScheduledCommand &);
private:
const MemSpecWideIO *memSpec;
// Four activate window
std::queue<sc_time> lastActivates;
void delayToSatisfyTAW(sc_time &);
RefreshCheckerWideIODummy *refreshChecker;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
class RefreshCheckerWideIODummy
{
protected:
friend class CheckerWideIO;
RefreshCheckerWideIODummy(const MemSpecWideIO *memSpec) : memSpec(memSpec) {}
virtual ~RefreshCheckerWideIODummy() {}
virtual void delayToSatisfyACT(Bank, sc_time &) {}
virtual void delayToSatisfyRD(Bank, sc_time &) {}
virtual void delayToSatisfyWR(Bank, sc_time &) {}
virtual void delayToSatisfyPRE(Bank, sc_time &) {}
virtual void insert(Bank) {}
const MemSpecWideIO *memSpec;
};
class RefreshCheckerWideIO final : public RefreshCheckerWideIODummy
{
private:
friend class CheckerWideIO;
RefreshCheckerWideIO(const MemSpecWideIO *memSpec)
: RefreshCheckerWideIODummy(memSpec) {}
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void delayToSatisfyPRE(Bank, sc_time &);
void insert(Bank);
sc_time timeForNextREFA = memSpec->tREFI;
sc_time timeForNextPREA = timeForNextREFA - memSpec->tRP;
};
class RefreshCheckerWideIOBankwise final : public RefreshCheckerWideIODummy
{
private:
friend class CheckerWideIO;
RefreshCheckerWideIOBankwise(const MemSpecWideIO *);
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void insert(Bank);
std::map<Bank, sc_time> timesForNextREFB;
std::map<Bank, sc_time> timesForNextPRE;
};
#endif // CHECKERWIDEIO_H

View File

@@ -269,13 +269,6 @@ void DRAMSys::instantiateModules(const string &traceName,
else
dram = new DramDDR3(str.c_str());
}
else if (memoryType == "DDR4")
{
if (recordingEnabled)
dram = new DramRecordable<DramDDR4>(str.c_str(), tlmRecorders[i]);
else
dram = new DramDDR4(str.c_str());
}
else if (memoryType == "WIDEIO_SDR")
{
if (recordingEnabled)
@@ -283,6 +276,13 @@ void DRAMSys::instantiateModules(const string &traceName,
else
dram = new DramWideIO(str.c_str());
}
else if (memoryType == "DDR4")
{
if (recordingEnabled)
dram = new DramRecordable<DramDDR4>(str.c_str(), tlmRecorders[i]);
else
dram = new DramDDR4(str.c_str());
}
else
{
SC_REPORT_FATAL("DRAMSys", "Unsupported DRAM type");