Refactoring of RefreshManager (introduced interface IRefreshManager).
This commit is contained in:
@@ -15,6 +15,8 @@ namespace controller{
|
||||
|
||||
struct Configuration
|
||||
{
|
||||
unsigned int numberOfBanks;
|
||||
bool RefreshBankwise = false;
|
||||
TimingConfiguration Timings;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,20 +10,31 @@
|
||||
|
||||
#include <tlm.h>
|
||||
#include "scheduling/CommandGenerator.h"
|
||||
#include "scheduling/InternalScheduler.h"
|
||||
#include "Configuration.h"
|
||||
#include "scheduling/CommandSequenceScheduler.h"
|
||||
#include "refresh/RefreshManager.h"
|
||||
#include "powerdown/PowerDownManager.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class Controller {
|
||||
class Controller
|
||||
{
|
||||
public:
|
||||
Controller();
|
||||
virtual ~Controller();
|
||||
|
||||
bool schedule(tlm::tlm_generic_payload* externalTransaction);//return TLM status??
|
||||
bool schedule(tlm::tlm_generic_payload* externalTransaction); //return TLM status??
|
||||
|
||||
private:
|
||||
Configuration config;
|
||||
ControllerState state;
|
||||
CommandGenerator commandGenerator;
|
||||
|
||||
CommandGenerator commandGenerator;
|
||||
CommandSequenceScheduler commandSequenceScheduler;
|
||||
RefreshManager refreshManager;
|
||||
PowerDownManager powerDownManager;
|
||||
InternalScheduler internalScheduler;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* RefreshManager.h
|
||||
*
|
||||
* Created on: Mar 6, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef REFRESHMANAGER_H_
|
||||
#define REFRESHMANAGER_H_
|
||||
|
||||
#include <systemc.h>
|
||||
#include "scheduling/InternalScheduler.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
struct PlannedRefresh{
|
||||
PlannedRefresh():time(SC_ZERO_TIME), delay(SC_ZERO_TIME){}
|
||||
sc_time time;
|
||||
sc_time delay;
|
||||
};
|
||||
|
||||
class RefreshManager
|
||||
{
|
||||
public:
|
||||
RefreshManager(Configuration& configuration, InternalScheduler& internalScheduler);
|
||||
virtual ~RefreshManager() {}
|
||||
|
||||
void refreshFinished(sc_time currentTime);
|
||||
|
||||
bool hasCollision(CommandSchedule schedule);
|
||||
sc_time getEarliestStartTime(CommandSchedule schedule);
|
||||
|
||||
private:
|
||||
Configuration& controllerConfiguration;
|
||||
InternalScheduler& internalScheduler;
|
||||
|
||||
PlannedRefresh lastRefresh;
|
||||
|
||||
//void scheduleRefreshTrigger(PlannedRefresh& refresh); idea: schedule refresh only at the regular time. Up to this point refresh can be still shifted to fit a sequence before.
|
||||
|
||||
void planNextRefresh(PlannedRefresh& refresh);
|
||||
void scheduleRefresh(const PlannedRefresh& refresh) const;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
#endif /* REFRESHMANAGER_H_ */
|
||||
23
DRAM/src/core/powerdown/PowerDownManager.cpp
Normal file
23
DRAM/src/core/powerdown/PowerDownManager.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* PowerDownManager.cpp
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include <core/PowerDownManager.h>
|
||||
|
||||
namespace controller {
|
||||
|
||||
PowerDownManager::PowerDownManager()
|
||||
{
|
||||
// TODO Auto-generated constructor stub
|
||||
|
||||
}
|
||||
|
||||
PowerDownManager::~PowerDownManager()
|
||||
{
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
22
DRAM/src/core/powerdown/PowerDownManager.h
Normal file
22
DRAM/src/core/powerdown/PowerDownManager.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* PowerDownManager.h
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef POWERDOWNMANAGER_H_
|
||||
#define POWERDOWNMANAGER_H_
|
||||
|
||||
namespace controller {
|
||||
|
||||
class PowerDownManager
|
||||
{
|
||||
public:
|
||||
PowerDownManager();
|
||||
virtual ~PowerDownManager();
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
#endif /* POWERDOWNMANAGER_H_ */
|
||||
33
DRAM/src/core/refresh/IRefreshManager.h
Normal file
33
DRAM/src/core/refresh/IRefreshManager.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* IRefreshManager.h
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef IREFRESHMANAGER_H_
|
||||
#define IREFRESHMANAGER_H_
|
||||
|
||||
#include <systemc.h>
|
||||
|
||||
namespace controller {
|
||||
|
||||
class IRefreshManager
|
||||
{
|
||||
public:
|
||||
virtual ~IRefreshManager() {}
|
||||
|
||||
//internal:
|
||||
virtual bool hasCollision(const CommandSchedule& schedule) = 0;
|
||||
virtual sc_time getEarliestStartTime(const CommandSchedule& schedule) = 0;
|
||||
|
||||
//external:
|
||||
virtual void cb_refreshFinished(sc_time currentTime) = 0;
|
||||
|
||||
private:
|
||||
virtual void scheduleRefresh(const ScheduledCommand& refresh) const = 0;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
#endif /* IREFRESHMANAGER_H_ */
|
||||
@@ -5,21 +5,19 @@
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include <core/RefreshManager.h>
|
||||
#include <core/refresh/RefreshManager.h>
|
||||
|
||||
namespace controller {
|
||||
|
||||
RefreshManager::RefreshManager(Configuration& configuration, InternalScheduler& internalScheduler) : controllerConfiguration(configuration), internalScheduler(internalScheduler)
|
||||
RefreshManager::RefreshManager(Configuration& configuration, IInternalScheduler& internalScheduler) : controllerConfiguration(configuration), internalScheduler(internalScheduler), lastRefresh(refreshTransaction, Command::Refresh, SC_ZERO_TIME)
|
||||
{
|
||||
lastRefresh.time = SC_ZERO_TIME;
|
||||
lastRefresh.delay = SC_ZERO_TIME;
|
||||
refreshFinished(SC_ZERO_TIME);
|
||||
cb_refreshFinished(SC_ZERO_TIME);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is called from TLM Wrapper when end_refresh is sent from DRAM.
|
||||
*/
|
||||
void RefreshManager::refreshFinished(sc_time currentTime)
|
||||
void RefreshManager::cb_refreshFinished(sc_time currentTime)
|
||||
{
|
||||
planNextRefresh(lastRefresh);
|
||||
assert(currentTime < lastRefresh.time);
|
||||
@@ -31,7 +29,7 @@ void RefreshManager::refreshFinished(sc_time currentTime)
|
||||
* A refresh may be postponed for a certain time, to fit the scheduled sequence anyways,
|
||||
* depending on the refresh logic.
|
||||
*/
|
||||
bool RefreshManager::hasCollision(CommandSchedule schedule)
|
||||
bool RefreshManager::hasCollision(const CommandSchedule& schedule)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -40,21 +38,19 @@ bool RefreshManager::hasCollision(CommandSchedule schedule)
|
||||
* If a scheduled CommandSequence collides, the refresh manager provides the earliest
|
||||
* start time for the new scheduling of this sequence.
|
||||
*/
|
||||
sc_time RefreshManager::getEarliestStartTime(CommandSchedule schedule)
|
||||
sc_time RefreshManager::getEarliestStartTime(const CommandSchedule& schedule)
|
||||
{
|
||||
/*stub*/
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
void RefreshManager::scheduleRefresh(const PlannedRefresh& refresh) const
|
||||
void RefreshManager::scheduleRefresh(const ScheduledCommand& refresh) const
|
||||
{
|
||||
internalScheduler.scheduleCommand(ScheduledCommand(Command::Refresh, refresh.time + refresh.delay));
|
||||
internalScheduler.scheduleCommand(refresh);
|
||||
}
|
||||
|
||||
void RefreshManager::planNextRefresh(PlannedRefresh& refresh)
|
||||
void RefreshManager::planNextRefresh(ScheduledCommand& refresh)
|
||||
{
|
||||
refresh.time += controllerConfiguration.Timings.tREF;
|
||||
refresh.delay = SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
44
DRAM/src/core/refresh/RefreshManager.h
Normal file
44
DRAM/src/core/refresh/RefreshManager.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* RefreshManager.h
|
||||
*
|
||||
* Created on: Mar 6, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef REFRESHMANAGER_H_
|
||||
#define REFRESHMANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
#include "core/scheduling/InternalScheduler.h"
|
||||
#include "core/Configuration.h"
|
||||
#include "IRefreshManager.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class RefreshManager : public IRefreshManager
|
||||
{
|
||||
public:
|
||||
RefreshManager(Configuration& configuration, IInternalScheduler& internalScheduler);
|
||||
virtual ~RefreshManager() {}
|
||||
|
||||
//internal:
|
||||
virtual bool hasCollision(const CommandSchedule& schedule);
|
||||
virtual sc_time getEarliestStartTime(const CommandSchedule& schedule);
|
||||
|
||||
//external:
|
||||
virtual void cb_refreshFinished(sc_time currentTime);
|
||||
|
||||
private:
|
||||
IInternalScheduler& internalScheduler;
|
||||
Configuration& controllerConfiguration;
|
||||
|
||||
tlm::tlm_generic_payload refreshTransaction;
|
||||
ScheduledCommand lastRefresh;
|
||||
|
||||
void planNextRefresh(ScheduledCommand& refresh);
|
||||
void scheduleRefresh(const ScheduledCommand& refresh) const;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
#endif /* REFRESHMANAGER_H_ */
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace controller {
|
||||
|
||||
enum class Command {Precharge, PrechargeAll, Activate, Read, Write, ReadA, WriteA, Refresh, RefreshTrigger};//TODO handle RefreshTrigger Event differently
|
||||
enum class Command {Precharge, PrechargeAll, Activate, Read, Write, ReadA, WriteA, Refresh};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
|
||||
@@ -7,20 +7,19 @@
|
||||
|
||||
#include "CommandGenerator.h"
|
||||
#include "common/schedulerextension.h"
|
||||
#include "vector"
|
||||
|
||||
using namespace common;
|
||||
using namespace std;
|
||||
|
||||
namespace controller {
|
||||
|
||||
vector<Command> CommandGenerator::generateCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
CommandSequence CommandGenerator::generateCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
{
|
||||
const SchedulerExtension& extension = SchedulerExtension::getExtension(&transaction);
|
||||
Bank bank = extension.getBank();
|
||||
Row row = extension.getRow();
|
||||
|
||||
vector<Command> result;
|
||||
CommandSequence result;
|
||||
|
||||
if (!controllerState.bankStates.rowBufferIsOpen(bank))
|
||||
{
|
||||
@@ -36,13 +35,13 @@ vector<Command> CommandGenerator::generateCommandSequence(tlm::tlm_generic_paylo
|
||||
}
|
||||
}
|
||||
|
||||
vector<Command> CommandGenerator::generateCommandSequence(
|
||||
CommandSequence CommandGenerator::generateCommandSequence(
|
||||
tlm::tlm_generic_payload* transaction)
|
||||
{
|
||||
return generateCommandSequence(*transaction);
|
||||
}
|
||||
|
||||
vector<Command> CommandGenerator::getBankMissCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
CommandSequence CommandGenerator::getBankMissCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
{
|
||||
vector<Command> result;
|
||||
result.push_back(Command::Activate);
|
||||
@@ -50,7 +49,7 @@ vector<Command> CommandGenerator::getBankMissCommandSequence(tlm::tlm_generic_pa
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<Command> CommandGenerator::getRowMissCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
CommandSequence CommandGenerator::getRowMissCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
{
|
||||
vector<Command> result;
|
||||
result.push_back(Command::Precharge);
|
||||
@@ -59,7 +58,7 @@ vector<Command> CommandGenerator::getRowMissCommandSequence(tlm::tlm_generic_pay
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<Command> CommandGenerator::getRowHitCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
CommandSequence CommandGenerator::getRowHitCommandSequence(tlm::tlm_generic_payload& transaction)
|
||||
{
|
||||
vector<Command> result;
|
||||
result.push_back(getReadWriteCommand(transaction));
|
||||
|
||||
@@ -9,26 +9,29 @@
|
||||
#define COMMANDGENERATOR_H_
|
||||
|
||||
#include <tlm.h>
|
||||
#include <vector>
|
||||
#include "core/ControllerState.h"
|
||||
#include "Command.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
typedef std::vector<Command> CommandSequence;
|
||||
|
||||
class CommandGenerator {
|
||||
public:
|
||||
CommandGenerator(const ControllerState& controllerState) : controllerState(controllerState) {};
|
||||
virtual ~CommandGenerator() {};
|
||||
|
||||
std::vector<Command> generateCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
std::vector<Command> generateCommandSequence(tlm::tlm_generic_payload* transaction);
|
||||
CommandSequence generateCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
CommandSequence generateCommandSequence(tlm::tlm_generic_payload* transaction);
|
||||
|
||||
private:
|
||||
const ControllerState& controllerState;
|
||||
|
||||
Command getReadWriteCommand(tlm::tlm_generic_payload& transaction);
|
||||
std::vector<Command> getBankMissCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
std::vector<Command> getRowMissCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
std::vector<Command> getRowHitCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
CommandSequence getBankMissCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
CommandSequence getRowMissCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
CommandSequence getRowHitCommandSequence(tlm::tlm_generic_payload& transaction);
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
#include <vector>
|
||||
#include <systemc.h>
|
||||
#include "Command.h"
|
||||
#include "common/schedulerextension.h"
|
||||
|
||||
|
||||
namespace controller {
|
||||
|
||||
struct ScheduledCommand{
|
||||
ScheduledCommand(Command command, sc_time time) : command(command), time(time){};
|
||||
ScheduledCommand(const tlm::tlm_generic_payload& transaction, Command command, sc_time time) : transaction(transaction), command(command), time(time){};
|
||||
|
||||
const tlm::tlm_generic_payload& transaction;
|
||||
Command command;
|
||||
sc_time time;
|
||||
|
||||
|
||||
23
DRAM/src/core/scheduling/CommandSequenceScheduler.cpp
Normal file
23
DRAM/src/core/scheduling/CommandSequenceScheduler.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* CommandSequenceScheduler.cpp
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include <core/scheduling/CommandSequenceScheduler.h>
|
||||
|
||||
namespace controller {
|
||||
|
||||
CommandSequenceScheduler::CommandSequenceScheduler()
|
||||
{
|
||||
// TODO Auto-generated constructor stub
|
||||
|
||||
}
|
||||
|
||||
CommandSequenceScheduler::~CommandSequenceScheduler()
|
||||
{
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
22
DRAM/src/core/scheduling/CommandSequenceScheduler.h
Normal file
22
DRAM/src/core/scheduling/CommandSequenceScheduler.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* CommandSequenceScheduler.h
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef COMMANDSEQUENCESCHEDULER_H_
|
||||
#define COMMANDSEQUENCESCHEDULER_H_
|
||||
|
||||
namespace controller {
|
||||
|
||||
class CommandSequenceScheduler
|
||||
{
|
||||
public:
|
||||
CommandSequenceScheduler();
|
||||
virtual ~CommandSequenceScheduler();
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
#endif /* COMMANDSEQUENCESCHEDULER_H_ */
|
||||
27
DRAM/src/core/scheduling/InternalScheduler.cpp
Normal file
27
DRAM/src/core/scheduling/InternalScheduler.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* InternalScheduler.cpp
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include "InternalScheduler.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
void InternalScheduler::scheduleCommand(const ScheduledCommand& command)
|
||||
{
|
||||
if(command.command == Command::Refresh)
|
||||
{
|
||||
scheduleRefresh(command);
|
||||
}
|
||||
}
|
||||
|
||||
void InternalScheduler::scheduleRefresh(const ScheduledCommand& command)
|
||||
{
|
||||
state.bankStates.closeAllRowBuffers();
|
||||
|
||||
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
@@ -9,14 +9,28 @@
|
||||
#define INTERNALSCHEDULER_H_
|
||||
|
||||
#include "CommandSchedule.h"
|
||||
#include "core/ControllerState.h"
|
||||
|
||||
class InternalScheduler
|
||||
namespace controller{
|
||||
|
||||
class IInternalScheduler
|
||||
{
|
||||
public:
|
||||
virtual ~InternalScheduler() {}
|
||||
virtual void scheduleCommand(controller::ScheduledCommand command) = 0;
|
||||
virtual ~IInternalScheduler() {}
|
||||
virtual void scheduleCommand(const controller::ScheduledCommand& command) = 0;
|
||||
};
|
||||
|
||||
class InternalScheduler : public IInternalScheduler
|
||||
{
|
||||
public:
|
||||
InternalScheduler(controller::ControllerState& state) : state(state) {}
|
||||
virtual void scheduleCommand(const controller::ScheduledCommand& command);
|
||||
|
||||
private:
|
||||
controller::ControllerState& state;
|
||||
|
||||
void scheduleRefresh(const controller::ScheduledCommand& command);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* INTERNALSCHEDULER_H_ */
|
||||
|
||||
12
DRAM/testing/CommandSequenceScheduler_test.cpp
Normal file
12
DRAM/testing/CommandSequenceScheduler_test.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* CommandSequenceScheduler_test.cpp
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include <core/scheduling/CommandSequenceScheduler.h>
|
||||
|
||||
namespace controller {
|
||||
|
||||
} /* namespace controller */
|
||||
12
DRAM/testing/PowerDownManager_test.cpp
Normal file
12
DRAM/testing/PowerDownManager_test.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* PowerDownManager_test.cpp
|
||||
*
|
||||
* Created on: Mar 9, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include <core/PowerDownManager.h>
|
||||
|
||||
namespace controller {
|
||||
|
||||
} /* namespace controller */
|
||||
@@ -7,18 +7,20 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include "core/RefreshManager.h"
|
||||
#include "core/refresh/RefreshManager.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::Expectation;
|
||||
|
||||
constexpr unsigned int numberOfBanks = 8;
|
||||
|
||||
namespace controller {
|
||||
|
||||
class MockInternalScheduler: public InternalScheduler
|
||||
class MockInternalScheduler: public IInternalScheduler
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD1(scheduleCommand, void (ScheduledCommand command));
|
||||
MOCK_METHOD1(scheduleCommand, void (const ScheduledCommand& command));
|
||||
};
|
||||
|
||||
TEST(RefreshManager, RefreshIsScheduledAfterStartup)
|
||||
@@ -26,7 +28,8 @@ TEST(RefreshManager, RefreshIsScheduledAfterStartup)
|
||||
Configuration config;
|
||||
MockInternalScheduler internalScheduler;
|
||||
|
||||
auto init = ScheduledCommand(Command::Refresh, config.Timings.tREF);
|
||||
tlm::tlm_generic_payload trans;
|
||||
auto init = ScheduledCommand(trans, Command::Refresh, config.Timings.tREF);
|
||||
|
||||
EXPECT_CALL(internalScheduler, scheduleCommand(init));
|
||||
|
||||
@@ -43,7 +46,7 @@ TEST(RefreshManager, FinishedRefreshTriggersNewRefresh)
|
||||
//schedule first refresh in constructor
|
||||
RefreshManager manager(config, internalScheduler);
|
||||
//schedule second refresh in callback (end_refresh)
|
||||
manager.refreshFinished(config.Timings.tREF + config.Timings.tREFA);
|
||||
manager.cb_refreshFinished(config.Timings.tREF + config.Timings.tREFA);
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
Reference in New Issue
Block a user