connecting components in controller

commandbus changing state when scheduling commands
added some tests
This commit is contained in:
Janik Schlemminger
2014-03-14 16:35:44 -07:00
parent 7b64552047
commit dacaec7f11
27 changed files with 272 additions and 78 deletions

View File

@@ -24,17 +24,10 @@ int runTests(int argc, char **argv)
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
/*int sc_main(int argc, char **argv) {
return runTests(argc,argv);
}*/
int main(int argc, char **argv) { int main(int argc, char **argv) {
/*sc_time clk(6, SC_NS); return runTests(argc,argv);
sc_time time(18, SC_NS); }
assert(!((time/clk)-ceil(time/clk)));
std::cout<<"good"<<(time/clk)-ceil(time/clk)<<endl;*/ int sc_main(int argc, char **argv) {
return runTests(argc,argv); return main(argc,argv);
} }

View File

@@ -6,23 +6,55 @@
*/ */
#include "Controller.h" #include "Controller.h"
#include "systemc.h"
#include "core/scheduling/checker/ActivateChecker.h"
#include "core/scheduling/checker/PrechargeChecker.h"
#include "core/scheduling/checker/ReadChecker.h"
#include "core/scheduling/checker/WriteChecker.h"
namespace controller { namespace controller {
/*Controller::Controller() Controller::Controller() :
config(), state(config.numberOfBanks), commandSequenceGenerator(state), commandChecker(), commandSequenceScheduler(
*this), refreshManager(config.Timings.refreshTimings[0], bus), bus(config, state,
allCommandChecker)
{ {
//create command scheduler addCommandChecker(Command::Activate, new ActivateChecker(config, bus));
addCommandChecker(Command::Precharge, new PrechargeChecker(config, bus));
addCommandChecker(Command::Read, new ReadChecker(config, bus));
addCommandChecker(Command::Write, new WriteChecker(config, bus));
}
void Controller::addCommandChecker(Command command, ICommandChecker* checker)
{
commandChecker[command] = checker;
allCommandChecker.push_back(checker);
} }
Controller::~Controller() Controller::~Controller()
{ {
//delete command scheduler std::map<Command, ICommandChecker*>::iterator it = commandChecker.begin();
}*/ while (it != commandChecker.end())
{
delete it->second;
}
commandChecker.clear();
}
bool Controller::schedule(sc_time currentTime, bool Controller::schedule(sc_time currentTime, tlm::tlm_generic_payload* externalTransaction)
tlm::tlm_generic_payload* externalTransaction)
{ {
assert(currentTime == SC_ZERO_TIME);
bus.cleanUpBus(currentTime); bus.cleanUpBus(currentTime);
return true;
}
const ICommandChecker& Controller::getChecker(Command command) const
{
std::map<Command, ICommandChecker*>::const_iterator result = commandChecker.find(command);
assert(result != commandChecker.end());
return *(result->second);
} }
} /* namespace controller */ } /* namespace controller */

View File

@@ -12,11 +12,11 @@
#include "scheduling/CommandSequenceGenerator.h" #include "scheduling/CommandSequenceGenerator.h"
#include "scheduling/CommandBus.h" #include "scheduling/CommandBus.h"
#include "Configuration.h" #include "Configuration.h"
#include "scheduling/CommandSequenceScheduler.h"
#include "refresh/RefreshManager.h" #include "refresh/RefreshManager.h"
#include "powerdown/PowerDownManager.h" #include "powerdown/PowerDownManager.h"
#include <map> #include <map>
#include "scheduling/checker/ICommandChecker.h" #include "scheduling/checker/ICommandChecker.h"
#include "scheduling/CommandSequenceScheduler.h"
namespace controller { namespace controller {
@@ -26,18 +26,22 @@ public:
Controller(); Controller();
virtual ~Controller(); virtual ~Controller();
bool schedule( sc_time currentTime, tlm::tlm_generic_payload* externalTransaction); //return TLM status?? bool schedule(sc_time currentTime, tlm::tlm_generic_payload* externalTransaction); //TODO return TLM status??
const ICommandChecker& getChecker(Command command) const;
private: private:
Configuration config; Configuration config;
ControllerState state; ControllerState state;
CommandSequenceGenerator commandGenerator; CommandSequenceGenerator commandSequenceGenerator;
std::map<Command, ICommandChecker*> commandScheduler; std::map<Command, ICommandChecker*> commandChecker;
std::vector<ICommandChecker*> allCommandChecker;
CommandSequenceScheduler commandSequenceScheduler; CommandSequenceScheduler commandSequenceScheduler;
RefreshManager refreshManager; RefreshManager refreshManager;
PowerDownManager powerDownManager; //PowerDownManager powerDownManager;
CommandBus bus; CommandBus bus;
void addCommandChecker(Command command, ICommandChecker* checker);
}; };
} /* namespace controller */ } /* namespace controller */

View File

@@ -10,23 +10,21 @@
namespace controller { namespace controller {
void CommandBus::scheduleCommand(const ScheduledCommand& command) void CommandBus::scheduleCommand(const ScheduledCommand& command)
{ {
if (command.getCommand() == Command::Refresh)
{
scheduleRefresh(command);
lastCommandsOnBus.at(Command::Activate).at(command.getBank()) = command.getStart();
}
assert(!pendingBusCommands.count(command.getStart())); assert(!pendingBusCommands.count(command.getStart()));
changeControllerState(command);
pendingBusCommands.insert(command.getStart()); pendingBusCommands.insert(command.getStart());
lastCommandsOnBus[command.getCommand()][command.getBank()] = command.getStart(); lastCommandsOnBus[command.getCommand()][command.getBank()] = command.getStart();
//notify tlm wrapper
} }
void CommandBus::scheduleTrigger(const Trigger command, sc_time time) void CommandBus::scheduleTrigger(const Trigger command, sc_time time)
{ {
//notify tlm wrapper
} }
sc_time CommandBus::getLastCommand(Command command, common::Bank bank) sc_time CommandBus::getLastCommand(Command command, common::Bank bank)
@@ -71,9 +69,53 @@ void CommandBus::cleanUpBus(sc_time currentTime)
pendingBusCommands.lower_bound(currentTime)); pendingBusCommands.lower_bound(currentTime));
} }
void CommandBus::scheduleRefresh(const ScheduledCommand& command) void CommandBus::changeControllerState(const ScheduledCommand& command)
{ {
state.bankStates.closeAllRowBuffers(); switch (command.getCommand())
{
case Command::Refresh:
refresh(command);
break;
case Command::Activate:
activate(command);
break;
case Command::Precharge:
precharge(command);
default:
break;
}
}
void CommandBus::refresh(const ScheduledCommand& command)
{
if(config.RefreshBankwise)
{
state.bankStates.closeRowBuffer(command.getBank());
}
else
{
state.bankStates.closeAllRowBuffers();
}
}
void CommandBus::precharge(const ScheduledCommand& command)
{
if(command.getCommand() == Command::Precharge)
{
state.bankStates.closeRowBuffer(command.getBank());
}
else if(command.getCommand() == Command::PrechargeAll)
{
state.bankStates.closeAllRowBuffers();
}
}
void CommandBus::activate(const ScheduledCommand& command)
{
if(command.getCommand() == Command::Activate)
{
state.bankStates.openRowInRowBuffer(command.getBank(), command.getRow());
}
} }
} /* namespace controller */ } /* namespace controller */

View File

@@ -13,6 +13,7 @@
#include "core/scheduling/Trigger.h" #include "core/scheduling/Trigger.h"
#include "IInternalScheduler.h" #include "IInternalScheduler.h"
#include "core/Configuration.h" #include "core/Configuration.h"
#include "core/scheduling/checker/ICommandChecker.h"
#include <map> #include <map>
#include <set> #include <set>
@@ -21,7 +22,7 @@ namespace controller{
class CommandBus : public IInternalScheduler class CommandBus : public IInternalScheduler
{ {
public: public:
CommandBus(const Configuration& config, controller::ControllerState& state) : state(state), config(config) {} CommandBus(const Configuration& config, controller::ControllerState& state,std::vector<ICommandChecker*>& checker) : config(config), state(state), checker(checker) {}
virtual void scheduleCommand(const ScheduledCommand& command); virtual void scheduleCommand(const ScheduledCommand& command);
virtual void scheduleTrigger(const Trigger trigger, sc_time time); virtual void scheduleTrigger(const Trigger trigger, sc_time time);
@@ -35,13 +36,17 @@ public:
const std::set<sc_time>& getPendingBusCommands() const {return pendingBusCommands;} const std::set<sc_time>& getPendingBusCommands() const {return pendingBusCommands;}
private: private:
controller::ControllerState& state;
const Configuration& config; const Configuration& config;
controller::ControllerState& state;
std::vector<ICommandChecker*>& checker;
std::map<Command,std::map<common::Bank, sc_time>> lastCommandsOnBus; std::map<Command,std::map<common::Bank, sc_time>> lastCommandsOnBus;
void scheduleRefresh(const controller::ScheduledCommand& command);
std::set<sc_time> pendingBusCommands; std::set<sc_time> pendingBusCommands;
void refresh(const ScheduledCommand& command);
void precharge(const ScheduledCommand& command);
void activate(const ScheduledCommand& command);
void changeControllerState(const ScheduledCommand& command);
}; };
} }

View File

@@ -20,16 +20,11 @@ public:
CommandSchedule(const tlm::tlm_generic_payload& transaction) : transaction(transaction) {}; CommandSchedule(const tlm::tlm_generic_payload& transaction) : transaction(transaction) {};
virtual ~CommandSchedule() {} virtual ~CommandSchedule() {}
void add(Command command, sc_time time, sc_time executionTime) ScheduledCommand& add(Command command, sc_time time, sc_time executionTime)
{ {
assert(scheduledCommands.empty() || time >= scheduledCommands.back().getEnd()); assert(scheduledCommands.empty() || time >= scheduledCommands.back().getEnd());
scheduledCommands.push_back(ScheduledCommand(transaction, command, time, executionTime)); scheduledCommands.push_back(ScheduledCommand(transaction, command, time, executionTime));
} return scheduledCommands.back();
void add(ScheduledCommand scheduledCommand)
{
assert(&scheduledCommand.getTransaction() == &transaction);
scheduledCommands.push_back(scheduledCommand);
} }
const std::vector<ScheduledCommand>& getScheduledCommands() const const std::vector<ScheduledCommand>& getScheduledCommands() const

View File

@@ -5,25 +5,25 @@
* Author: jonny * Author: jonny
*/ */
#include <core/scheduling/CommandSequenceScheduler.h> #include "core/scheduling/CommandSequenceScheduler.h"
#include "core/Controller.h"
namespace controller { namespace controller {
CommandSequenceScheduler::CommandSequenceScheduler() CommandSchedule CommandSequenceScheduler::prepareSchedule(sc_time start,
{ tlm::tlm_generic_payload& transaction, CommandSequence commands)
// TODO Auto-generated constructor stub
}
CommandSchedule CommandSequenceScheduler::prepareSchedule(tlm::tlm_generic_payload& transaction, CommandSequence commands)
{ {
CommandSchedule schedule(transaction); CommandSchedule schedule(transaction);
for(unsigned int i = 0; i < commands.size(); ++i) for (unsigned int i = 0; i < commands.size(); ++i)
{ {
Command command = commands.at(i); Command command = commands.at(i);
sc_time start; const ICommandChecker& checker = controller.getChecker(command);
sc_time executionTime;
schedule.add(command, start, executionTime); if (i > 0)
start = schedule.getEnd();
sc_time executionTime(checker.getExecutionTime(transaction, command));
ScheduledCommand& scheduledCommand = schedule.add(command, start, executionTime);
checker.check(scheduledCommand);
} }
return schedule; return schedule;
} }

View File

@@ -10,16 +10,24 @@
#include "CommandSchedule.h" #include "CommandSchedule.h"
#include "Command.h" #include "Command.h"
#include <map>
#include "core/scheduling/checker/ICommandChecker.h"
namespace controller { namespace controller {
class Controller;
class CommandSequenceScheduler class CommandSequenceScheduler
{ {
public: public:
CommandSequenceScheduler(); CommandSequenceScheduler(const Controller& controller) : controller(controller){}
virtual ~CommandSequenceScheduler(){} virtual ~CommandSequenceScheduler(){}
CommandSchedule prepareSchedule(sc_time start, tlm::tlm_generic_payload& transaction, CommandSequence commands);
CommandSchedule prepareSchedule(tlm::tlm_generic_payload& transaction, CommandSequence commands); private:
const Controller& controller;
}; };
} /* namespace controller */ } /* namespace controller */

View File

@@ -59,6 +59,11 @@ public:
return common::DramExtension::getExtension(&transaction).getBank(); return common::DramExtension::getExtension(&transaction).getBank();
} }
common::Row getRow() const
{
return common::DramExtension::getExtension(&transaction).getRow();
}
inline bool operator==(const ScheduledCommand& b) const inline bool operator==(const ScheduledCommand& b) const
{ {
return b.command == command && b.start == start && b.executionTime == executionTime return b.command == command && b.start == start && b.executionTime == executionTime

View File

@@ -23,6 +23,13 @@ void ActivateChecker::check(ScheduledCommand& command) const
check_bus(command); check_bus(command);
} }
sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
Command command) const
{
assert(command == Command::Activate);
return config.Timings.tRCD;
}
void ActivateChecker::check_activateToActivate(ScheduledCommand& command) const void ActivateChecker::check_activateToActivate(ScheduledCommand& command) const
{ {
if (bus.notYetScheduled(Command::Activate)) if (bus.notYetScheduled(Command::Activate))

View File

@@ -23,17 +23,18 @@ public:
virtual ~ActivateChecker(){} virtual ~ActivateChecker(){}
virtual void check(ScheduledCommand& command) const; virtual void check(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const;
virtual void cb_IInternalScheduler(const ScheduledCommand& command); virtual void cb_IInternalScheduler(const ScheduledCommand& command);
private: private:
const Configuration& config; const Configuration& config;
CommandBus& bus;//should be const .. but fucking map access operator!!!! CommandBus& bus;//TODO should be const .. but fucking map access operator!!!!
void check_activateToActivate(ScheduledCommand& command) const; void check_activateToActivate(ScheduledCommand& command) const;
void check_prechargeToActivate(ScheduledCommand& command) const; void check_prechargeToActivate(ScheduledCommand& command) const;
void check_nActivateWindow(ScheduledCommand& command) const; void check_nActivateWindow(ScheduledCommand& command) const;
void check_bus(ScheduledCommand& command) const; void check_bus(ScheduledCommand& command) const;
RingBuffer nActivateWindow; RingBuffer<sc_time> nActivateWindow;
}; };
} /* namespace controller */ } /* namespace controller */

View File

@@ -18,7 +18,8 @@ class ICommandChecker
public: public:
virtual ~ICommandChecker() {} virtual ~ICommandChecker() {}
virtual void schedule(ScheduledCommand& command) const = 0; virtual void check(ScheduledCommand& command) const = 0;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const = 0;
virtual void cb_IInternalScheduler(const ScheduledCommand& command) = 0; virtual void cb_IInternalScheduler(const ScheduledCommand& command) = 0;
}; };

View File

@@ -9,11 +9,17 @@
namespace controller { namespace controller {
void controller::PrechargeChecker::check(ScheduledCommand& command) const void PrechargeChecker::check(ScheduledCommand& command) const
{ {
} }
void controller::PrechargeChecker::cb_IInternalScheduler(const ScheduledCommand& command) sc_time PrechargeChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
Command command) const
{
assert(command == Command::Precharge || command == Command::PrechargeAll);
return config.Timings.tRP;
}
void PrechargeChecker::cb_IInternalScheduler(const ScheduledCommand& command)
{ {
} }

View File

@@ -21,6 +21,7 @@ public:
virtual ~PrechargeChecker() {} virtual ~PrechargeChecker() {}
virtual void check(ScheduledCommand& command) const; virtual void check(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const;
virtual void cb_IInternalScheduler(const ScheduledCommand& command); virtual void cb_IInternalScheduler(const ScheduledCommand& command);
private: private:
const Configuration& config; const Configuration& config;

View File

@@ -13,6 +13,13 @@ void ReadChecker::check(ScheduledCommand& command) const
{ {
} }
sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
Command command) const
{
assert(command == Command::Read || command == Command::ReadA);
return config.Timings.clk*8;
}
void ReadChecker::cb_IInternalScheduler(const ScheduledCommand& command) void ReadChecker::cb_IInternalScheduler(const ScheduledCommand& command)
{ {
} }

View File

@@ -21,6 +21,7 @@ public:
virtual ~ReadChecker() {} virtual ~ReadChecker() {}
virtual void check(ScheduledCommand& command) const; virtual void check(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const;
virtual void cb_IInternalScheduler(const ScheduledCommand& command); virtual void cb_IInternalScheduler(const ScheduledCommand& command);
private: private:
const Configuration& config; const Configuration& config;

View File

@@ -13,6 +13,13 @@ void WriteChecker::check(ScheduledCommand& command) const
{ {
} }
sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
Command command) const
{
assert(command == Command::Write || command == Command::WriteA);
return config.Timings.clk*8;
}
void WriteChecker::cb_IInternalScheduler(const ScheduledCommand& command) void WriteChecker::cb_IInternalScheduler(const ScheduledCommand& command)
{ {
} }

View File

@@ -21,6 +21,7 @@ public:
virtual ~WriteChecker() {} virtual ~WriteChecker() {}
virtual void check(ScheduledCommand& command) const; virtual void check(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const;
virtual void cb_IInternalScheduler(const ScheduledCommand& command); virtual void cb_IInternalScheduler(const ScheduledCommand& command);
private: private:
const Configuration& config; const Configuration& config;

View File

@@ -10,26 +10,29 @@
#include <systemc.h> #include <systemc.h>
template<typename T>
class RingBuffer class RingBuffer
{ {
public: public:
RingBuffer(unsigned int maxSize) : maxSize(maxSize) {} RingBuffer(unsigned int maxSize) : maxSize(maxSize) {}
void put(sc_time t) void put(T t)
{ {
buffer.push_front(t); buffer.push_back(t);
if(getSize()>maxSize) if(getSize()>maxSize)
buffer.pop_back(); buffer.pop_front();
} }
sc_time getOldest() const T getOldest() const
{ {
assert(!isEmpty());
return buffer.front(); return buffer.front();
} }
sc_time getNewest() const T getNewest() const
{ {
assert(!isEmpty());
return buffer.back(); return buffer.back();
} }
@@ -48,13 +51,14 @@ public:
return buffer.size(); return buffer.size();
} }
const sc_time get(unsigned int i) const const T get(unsigned int i) const
{ {
return buffer.at(i); assert(i<getSize());
return buffer[i];
} }
private: private:
std::deque<sc_time> buffer; std::deque<T> buffer;
unsigned int maxSize; unsigned int maxSize;
}; };

View File

@@ -16,15 +16,13 @@ unsigned int getStartAddress(Bank bank)
sc_time delayByConstraint(sc_time previous, sc_time start, sc_time constraint) sc_time delayByConstraint(sc_time previous, sc_time start, sc_time constraint)
{ {
assert(start > previous); if (previous + constraint > start)
sc_time distance = start - previous; return previous + constraint - start;
if (distance < constraint)
return constraint - distance;
else else
return SC_ZERO_TIME; return SC_ZERO_TIME;
} }
sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment) const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment)
{ {
if (alignment == Alignment::UP) if (alignment == Alignment::UP)
return ceil(time / clk) * clk; return ceil(time / clk) * clk;

View File

@@ -17,7 +17,7 @@ sc_time delayByConstraint(sc_time previous, sc_time start, sc_time constraint);
enum class Alignment {UP, DOWN}; enum class Alignment {UP, DOWN};
sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = Alignment::UP); const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = Alignment::UP);
bool isClkAligned(sc_time time, sc_time clk); bool isClkAligned(sc_time time, sc_time clk);
#endif /* UTILS_H_ */ #endif /* UTILS_H_ */

View File

@@ -23,14 +23,14 @@ namespace controller {
class CommandBusTest: public Test class CommandBusTest: public Test
{ {
public: public:
CommandBusTest() : config(), state(config.numberOfBanks), bus(config, state), clk(config.Timings.clk){} CommandBusTest() : config(), state(config.numberOfBanks), bus(config, state, checker), clk(config.Timings.clk){}
Configuration config; Configuration config;
ControllerState state; ControllerState state;
CommandBus bus; CommandBus bus;
std::vector<ICommandChecker*> checker;
sc_time clk; sc_time clk;
}; };
TEST_F(CommandBusTest, cleanUpBusWorks) TEST_F(CommandBusTest, cleanUpBusWorks)

View File

@@ -0,0 +1,76 @@
/*
* Utils_test.cpp
*
* Created on: Mar 14, 2014
* Author: jonny
*/
#include <gtest/gtest.h>
#include "core/utils/Utils.h"
#include "core/utils/RingBuffer.h"
//using namespace testing;
namespace controller {
TEST(UtilsTest, clkAlignWorks)
{
sc_time clk(6, SC_NS);
sc_time aligned = 2* clk;
sc_time not_aligned = 2.5*clk;
EXPECT_EQ(aligned, clkAlign(aligned, clk, Alignment::UP));
EXPECT_EQ(aligned, clkAlign(aligned, clk, Alignment::DOWN));
EXPECT_EQ(aligned+clk, clkAlign(not_aligned, clk, Alignment::UP));
EXPECT_EQ(aligned+clk, clkAlign(not_aligned, clk));
EXPECT_EQ(aligned, clkAlign(not_aligned, clk, Alignment::DOWN));
}
TEST(UtilsTest, isClkAlignedWorks)
{
sc_time clk(6, SC_NS);
sc_time aligned = 2*clk;
sc_time not_aligned = 2.5 * clk;
EXPECT_TRUE(isClkAligned(aligned, clk));
EXPECT_FALSE(isClkAligned(not_aligned, clk));
}
TEST(UtilsTest, delayByConstraintWorks)
{
sc_time start(10, SC_NS);
sc_time previous(8, SC_NS);
sc_time constraint(4, SC_NS);
EXPECT_EQ(sc_time(2, SC_NS), delayByConstraint(previous, start, constraint));
EXPECT_EQ(sc_time(4, SC_NS), delayByConstraint(previous, sc_time(8, SC_NS), constraint));
EXPECT_EQ(sc_time(6, SC_NS), delayByConstraint(previous, sc_time(6, SC_NS), constraint));
EXPECT_EQ(sc_time(0, SC_NS), delayByConstraint(previous, sc_time(12, SC_NS), constraint));
EXPECT_EQ(sc_time(0, SC_NS), delayByConstraint(previous, sc_time(14, SC_NS), constraint));
}
TEST(UtilsTest, RingBufferWorks)
{
RingBuffer<int> buffer(4);
EXPECT_TRUE(buffer.isEmpty());
EXPECT_EQ(0, buffer.getSize());
EXPECT_DEATH(buffer.get(0), ".*");
EXPECT_FALSE(buffer.isFull());
buffer.put(3);
EXPECT_EQ(1, buffer.getSize());
EXPECT_FALSE(buffer.isFull());
buffer.put(5);
buffer.put(4);
EXPECT_EQ(4, buffer.getNewest());
EXPECT_EQ(3, buffer.getOldest());
EXPECT_FALSE(buffer.isFull());
buffer.put(9);
buffer.put(10);
EXPECT_EQ(10, buffer.getNewest());
EXPECT_EQ(5, buffer.getOldest());
EXPECT_EQ(9, buffer.get(2));
EXPECT_TRUE(buffer.isFull());
}
} /* namespace controller */