all constraints implemented
This commit is contained in:
@@ -7,12 +7,11 @@ def simple_frfcfs():
|
||||
stlGenerator.clear()
|
||||
stlGenerator.addAction(0, 0)
|
||||
stlGenerator.addAction(0, 1)
|
||||
stlGenerator.addAction(0, 0)
|
||||
|
||||
stlGenerator.addAction(0, 1)
|
||||
stlGenerator.addAction(0, 0)
|
||||
stlGenerator.addAction(0, 1)
|
||||
stlGenerator.generateStl('test2.stl')
|
||||
stlGenerator.addAction(2, 0)
|
||||
stlGenerator.addAction(3, 0)
|
||||
stlGenerator.addAction(4, 0)
|
||||
stlGenerator.addAction(5, 0)
|
||||
stlGenerator.generateStl('../traces/test2.stl')
|
||||
|
||||
if __name__ == '__main__':
|
||||
simple_frfcfs();
|
||||
|
||||
@@ -22,7 +22,7 @@ class DramConfigReader:
|
||||
|
||||
def __init__(self):
|
||||
root = ET.parse(
|
||||
os.path.dirname(os.path.realpath(sys.argv[0])) + '/addressConfig.xml').getroot()
|
||||
os.path.dirname(os.path.realpath(sys.argv[0])) + '/../configs/addressConfig.xml').getroot()
|
||||
self.__extractAdressEncoding(root, 'channel')
|
||||
self.__extractAdressEncoding(root, 'bank')
|
||||
self.__extractAdressEncoding(root, 'row')
|
||||
|
||||
@@ -72,3 +72,8 @@ string DebugManager::senderToString(Sender sender)
|
||||
}
|
||||
return "unknown sender";
|
||||
}
|
||||
|
||||
void reportFatal(std::string sender, std::string message)
|
||||
{
|
||||
SC_REPORT_FATAL(sender.c_str(), message.c_str());
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
enum class Importance {Warning, Info};
|
||||
enum class Sender {DramController, DramWrapper, Scheduler, TracePlayer, TraceRecorder};
|
||||
|
||||
void reportFatal(std::string sender, std::string message);
|
||||
|
||||
|
||||
class DebugManager
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace core{
|
||||
|
||||
struct Configuration
|
||||
{
|
||||
Configuration(): numberOfBanks(8), burstlength(2), Timings(numberOfBanks), RefreshBankwise(false),
|
||||
Configuration(): numberOfBanks(8), burstlength(2), Timings(numberOfBanks), RefreshBankwise(true),
|
||||
nActivate(2)
|
||||
{}
|
||||
unsigned int numberOfBanks;
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
namespace core {
|
||||
|
||||
Controller::Controller(IWrapperConnector& wrapperConnector, TlmRecorder& recorder) :
|
||||
config(), state(config.numberOfBanks, config.nActivate), busChecker(config, state), wrapper(
|
||||
wrapperConnector), commandChecker(), recorder(recorder), savedState(
|
||||
config.numberOfBanks, config.nActivate), commandSequenceGenerator(state), commandSequenceScheduler(
|
||||
*this)
|
||||
config(), state(&config), wrapper(wrapperConnector), commandChecker(), recorder(recorder), savedState(
|
||||
&config), commandSequenceGenerator(state), commandSequenceScheduler(*this)
|
||||
|
||||
{
|
||||
commandChecker[Command::Activate] = new ActivateChecker(config, state);
|
||||
@@ -28,7 +26,7 @@ Controller::Controller(IWrapperConnector& wrapperConnector, TlmRecorder& recorde
|
||||
commandChecker[Command::Read] = new ReadChecker(config, state);
|
||||
commandChecker[Command::Write] = new WriteChecker(config, state);
|
||||
|
||||
if(config.RefreshBankwise)
|
||||
if (config.RefreshBankwise)
|
||||
refreshManager = new RefreshManagerBankwise(*this);
|
||||
else
|
||||
refreshManager = new RefreshManager(*this);
|
||||
@@ -55,15 +53,14 @@ void Controller::resetState()
|
||||
|
||||
void Controller::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
cleanUpBus(time);
|
||||
state.cleanUp(time);
|
||||
refreshManager->scheduleRefresh(payload, time);
|
||||
}
|
||||
|
||||
bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
cleanUpBus(start);
|
||||
|
||||
start = clkAlign(start, config.Timings.clk);
|
||||
state.cleanUp(start);
|
||||
payload.set_streaming_width(config.burstlength);
|
||||
|
||||
saveState();
|
||||
@@ -85,7 +82,7 @@ bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload)
|
||||
|
||||
bool Controller::isBusy(sc_time currentTime, Bank bank)
|
||||
{
|
||||
ScheduledCommand lastScheduledCommand = state.getLastCommand(bank);
|
||||
ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank);
|
||||
if (lastScheduledCommand.isNoCommand())
|
||||
return false;
|
||||
else if (lastScheduledCommand.getCommand() == Command::Write
|
||||
@@ -113,12 +110,5 @@ void Controller::send(const CommandSchedule& schedule) const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Controller::cleanUpBus(sc_time currentTime)
|
||||
{
|
||||
state.pendingBusCommands.erase(state.pendingBusCommands.begin(),
|
||||
state.pendingBusCommands.lower_bound(currentTime));
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "refresh/IRefreshManager.h"
|
||||
#include "scheduling/CommandSequenceGenerator.h"
|
||||
#include "scheduling/checker/ICommandChecker.h"
|
||||
#include "scheduling/checker/BusChecker.h"
|
||||
#include "scheduling/CommandSequenceScheduler.h"
|
||||
#include "../common/TlmRecorder.h"
|
||||
|
||||
@@ -39,12 +38,10 @@ public:
|
||||
void saveState();
|
||||
void resetState();
|
||||
|
||||
void cleanUpBus(sc_time time);
|
||||
void send(const CommandSchedule& schedule) const;
|
||||
|
||||
Configuration config;
|
||||
ControllerState state;
|
||||
BusChecker busChecker;
|
||||
IWrapperConnector& wrapper;
|
||||
std::map<Command, ICommandChecker*> commandChecker;
|
||||
TlmRecorder& recorder;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "ControllerState.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -27,7 +28,7 @@ const ScheduledCommand ControllerState::getLastCommand(Command command)
|
||||
return max;
|
||||
}
|
||||
|
||||
const ScheduledCommand ControllerState::getLastCommand(Bank bank)
|
||||
const ScheduledCommand ControllerState::getLastScheduledCommand(Bank bank)
|
||||
{
|
||||
ScheduledCommand lastCommand;
|
||||
for (std::map<Command, std::map<Bank, ScheduledCommand> >::iterator it =
|
||||
@@ -42,23 +43,39 @@ const ScheduledCommand ControllerState::getLastCommand(Bank bank)
|
||||
|
||||
void ControllerState::change(const ScheduledCommand& scheduledCommand)
|
||||
{
|
||||
pendingBusCommands.insert(scheduledCommand.getStart());
|
||||
bus.blockSlot(scheduledCommand.getStart());
|
||||
lastCommandsOnBus[scheduledCommand.getCommand()][scheduledCommand.getBank()] = scheduledCommand;
|
||||
lastCommandsOnBus[scheduledCommand.getCommand()][scheduledCommand.getBank()].invalidateTransaction();
|
||||
|
||||
switch (scheduledCommand.getCommand())
|
||||
{
|
||||
case Command::Read:
|
||||
lastDataStrobeCommands.emplace_back(scheduledCommand);
|
||||
break;
|
||||
case Command::ReadA:
|
||||
bankStates.closeRowBuffer(scheduledCommand.getBank());
|
||||
lastDataStrobeCommands.emplace_back(scheduledCommand);
|
||||
break;
|
||||
case Command::Write:
|
||||
lastDataStrobeCommands.emplace_back(scheduledCommand);
|
||||
break;
|
||||
case Command::WriteA:
|
||||
bankStates.closeRowBuffer(scheduledCommand.getBank());
|
||||
lastDataStrobeCommands.emplace_back(scheduledCommand);
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
break;
|
||||
case Command::Activate:
|
||||
bankStates.openRowInRowBuffer(scheduledCommand.getBank(), scheduledCommand.getRow());
|
||||
nActivateWindow.put(scheduledCommand.getStart());
|
||||
activates.blockSlots(scheduledCommand.getStart() - config->Timings.tRRD,
|
||||
scheduledCommand.getStart() + config->Timings.tRRD, true);
|
||||
break;
|
||||
case Command::Precharge:
|
||||
bankStates.closeRowBuffer(scheduledCommand.getBank());
|
||||
break;
|
||||
case Command::PrechargeAll:
|
||||
bankStates.closeAllRowBuffers();
|
||||
bankStates.closeAllRowBuffers();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -66,5 +83,21 @@ void ControllerState::change(const ScheduledCommand& scheduledCommand)
|
||||
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
void ControllerState::cleanUp(sc_time time)
|
||||
{
|
||||
bus.cleanUpSlots(time);
|
||||
activates.cleanUpSlots(time);
|
||||
//remove_if(lastDataStrobeCommands.begin(),lastDataStrobeCommands.end(), [&](ScheduledCommand command){return command.getEnd() < time;});
|
||||
vector<ScheduledCommand> tmp;
|
||||
for(ScheduledCommand& command: lastDataStrobeCommands)
|
||||
{
|
||||
if(command.getEnd() >= time )
|
||||
{
|
||||
tmp.emplace_back(command);
|
||||
}
|
||||
}
|
||||
|
||||
lastDataStrobeCommands = tmp;
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -12,32 +12,44 @@
|
||||
#include "BankStates.h"
|
||||
#include "utils/RingBuffer.h"
|
||||
#include "scheduling/ScheduledCommand.h"
|
||||
#include "Slots.h"
|
||||
#include "Configuration.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace core {
|
||||
|
||||
class ControllerState {
|
||||
class ControllerState
|
||||
{
|
||||
public:
|
||||
ControllerState(unsigned int numberOfBanks, unsigned int nActivates) : bankStates(numberOfBanks), nActivateWindow(nActivates){}
|
||||
virtual ~ControllerState(){}
|
||||
ControllerState(Configuration* config) :
|
||||
bankStates(config->numberOfBanks), nActivateWindow(config->nActivate), bus(
|
||||
config->Timings.clk), activates(config->Timings.clk), config(config)
|
||||
{
|
||||
}
|
||||
virtual ~ControllerState()
|
||||
{
|
||||
}
|
||||
|
||||
const ScheduledCommand getLastCommand(Command command, Bank bank);
|
||||
const ScheduledCommand getLastCommand(Command command);
|
||||
const ScheduledCommand getLastCommand(Bank bank);
|
||||
const ScheduledCommand getLastScheduledCommand(Bank bank);
|
||||
|
||||
void change(const ScheduledCommand& scheduledCommand);
|
||||
void cleanUp(sc_time time);
|
||||
|
||||
BankStates bankStates;
|
||||
|
||||
//used by the various checkers
|
||||
RingBuffer<sc_time> nActivateWindow;
|
||||
std::vector<sc_time> nACT;
|
||||
std::map<Command, std::map<Bank, ScheduledCommand> > lastCommandsOnBus;
|
||||
std::set<sc_time> pendingBusCommands;
|
||||
private:
|
||||
Slots bus;
|
||||
Slots activates;
|
||||
std::vector<ScheduledCommand> lastDataStrobeCommands;
|
||||
|
||||
private:
|
||||
Configuration* config;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
73
dram/src/core/Slots.cpp
Normal file
73
dram/src/core/Slots.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Slots.cpp
|
||||
*
|
||||
* Created on: Mar 29, 2014
|
||||
* Author: robert
|
||||
*/
|
||||
|
||||
#include "Slots.h"
|
||||
#include "utils/Utils.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
Slots::Slots(sc_time clk) :
|
||||
clk(clk)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Slots::~Slots()
|
||||
{
|
||||
}
|
||||
|
||||
void Slots::moveCommandToNextFreeSlot(ScheduledCommand& command)
|
||||
{
|
||||
sc_time newStart = command.getStart();
|
||||
|
||||
sc_assert(isClkAligned(newStart, clk));
|
||||
std::set<sc_time>::iterator it = slotSet.begin();
|
||||
|
||||
while (it != slotSet.end() && *it <= newStart)
|
||||
{
|
||||
if (*it == newStart)
|
||||
newStart += clk;
|
||||
++it;
|
||||
}
|
||||
command.setStart(newStart);
|
||||
}
|
||||
|
||||
void Slots::cleanUpSlots(sc_time time)
|
||||
{
|
||||
slotSet.erase(slotSet.begin(), slotSet.lower_bound(time));
|
||||
}
|
||||
|
||||
void Slots::blockSlot(sc_time time)
|
||||
{
|
||||
sc_assert(isClkAligned(time, clk));
|
||||
slotSet.insert(time);
|
||||
}
|
||||
|
||||
bool Slots::isFree(sc_time time)
|
||||
{
|
||||
return (slotSet.count(time) == 0);
|
||||
}
|
||||
|
||||
void Slots::blockSlots(sc_time begin, sc_time end, bool excludeBorders)
|
||||
{
|
||||
sc_assert(isClkAligned(begin, clk));
|
||||
sc_assert(isClkAligned(end, clk));
|
||||
|
||||
if (excludeBorders)
|
||||
{
|
||||
begin += clk;
|
||||
end -= clk;
|
||||
}
|
||||
|
||||
for (sc_time time = begin; time <= end; time += clk)
|
||||
{
|
||||
slotSet.insert(time);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
35
dram/src/core/Slots.h
Normal file
35
dram/src/core/Slots.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Slots.h
|
||||
*
|
||||
* Created on: Mar 29, 2014
|
||||
* Author: robert
|
||||
*/
|
||||
|
||||
#ifndef SLOTS_H_
|
||||
#define SLOTS_H_
|
||||
#include <systemc.h>
|
||||
#include <set>
|
||||
#include "scheduling/ScheduledCommand.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class Slots
|
||||
{
|
||||
public:
|
||||
Slots(sc_time clk);
|
||||
virtual ~Slots();
|
||||
void moveCommandToNextFreeSlot(ScheduledCommand& command);
|
||||
void cleanUpSlots(sc_time time);
|
||||
void blockSlots(sc_time begin, sc_time end, bool excludeBorders);
|
||||
void blockSlot(sc_time time);
|
||||
bool isFree(sc_time);
|
||||
|
||||
private:
|
||||
std::set<sc_time> slotSet;
|
||||
sc_time clk;
|
||||
|
||||
};
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
#endif /* SLOTS_H_ */
|
||||
@@ -45,8 +45,11 @@ struct TimingConfiguration
|
||||
tRCD = 3*clk; //act -> read/write
|
||||
|
||||
tRL = 3*clk; //read latency (read command start to data strobe)
|
||||
|
||||
tWL = 1*clk; //write latency
|
||||
tTAW = 48*clk; //two activate window
|
||||
tRR = 2*clk; //min read to read on same rank
|
||||
tWW = 1*clk; //min write to write on same rank
|
||||
tWTR = 3*clk;//write to read
|
||||
}
|
||||
|
||||
sc_time clk;
|
||||
@@ -57,6 +60,11 @@ struct TimingConfiguration
|
||||
sc_time tRCD;
|
||||
sc_time tTAW;
|
||||
sc_time tRL;
|
||||
sc_time tWL;
|
||||
sc_time tWTR;
|
||||
|
||||
sc_time tRR;
|
||||
sc_time tWW;
|
||||
|
||||
std::vector<RefreshTiming> refreshTimings;
|
||||
|
||||
|
||||
@@ -81,13 +81,13 @@ void RefreshManagerBankwise::RefreshManagerForBank::scheduleRefresh(sc_time time
|
||||
ScheduledCommand precharge(refreshPayload, Command::Precharge, time,
|
||||
controller.config.Timings.tRP);
|
||||
|
||||
controller.busChecker.findSlotOnBus(precharge);
|
||||
controller.state.bus.moveCommandToNextFreeSlot(precharge);
|
||||
nextRefresh.setStart(precharge.getEnd());
|
||||
|
||||
controller.state.change(precharge);
|
||||
controller.wrapper.send(precharge);
|
||||
}
|
||||
controller.busChecker.findSlotOnBus(nextRefresh);
|
||||
controller.state.bus.moveCommandToNextFreeSlot(nextRefresh);
|
||||
controller.state.change(nextRefresh);
|
||||
controller.wrapper.send(nextRefresh);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "CommandSequenceScheduler.h"
|
||||
#include "../Controller.h"
|
||||
#include "../../common/DebugManager.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -15,18 +16,24 @@ CommandSchedule CommandSequenceScheduler::schedule(CommandSequence commands, sc_
|
||||
{
|
||||
CommandSchedule schedule(transaction);
|
||||
|
||||
sc_time endOfPrevious = start;
|
||||
for (Command cmd : commands)
|
||||
{
|
||||
if(start >= sc_time(28723164,SC_NS))
|
||||
{
|
||||
int i = 5;
|
||||
i++;
|
||||
}
|
||||
|
||||
DebugManager::getInstance().printDebugMessage("Scheduling command " + commandToString(cmd),Sender::DramWrapper);
|
||||
|
||||
ICommandChecker& checker = *controller.commandChecker.at(cmd);
|
||||
|
||||
sc_time executionTime = checker.getExecutionTime(transaction, cmd);
|
||||
ScheduledCommand& scheduledCommand = schedule.add(cmd, endOfPrevious, executionTime);
|
||||
ScheduledCommand& scheduledCommand = schedule.add(cmd, start, executionTime);
|
||||
checker.delayToSatisfyConstraints(scheduledCommand);
|
||||
|
||||
controller.busChecker.findSlotOnBus(scheduledCommand);
|
||||
sc_assert(scheduledCommand.getStart()>=start && scheduledCommand.getStart() < scheduledCommand.getEnd());
|
||||
controller.state.change(scheduledCommand);
|
||||
endOfPrevious = scheduledCommand.getEnd();
|
||||
}
|
||||
|
||||
return schedule;
|
||||
|
||||
@@ -22,13 +22,13 @@ public:
|
||||
|
||||
ScheduledCommand(tlm::tlm_generic_payload& payload, Command command, sc_time time,
|
||||
sc_time executionTime) :
|
||||
payload(&payload), command(command), start(time), executionTime(executionTime), extension(
|
||||
DramExtension::getExtension(payload))
|
||||
payload(&payload), command(command), start(time), executionTime(executionTime), burstLength(payload.get_streaming_width()),
|
||||
extension(DramExtension::getExtension(payload))
|
||||
{
|
||||
}
|
||||
|
||||
ScheduledCommand() :
|
||||
payload(NULL), command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), extension()
|
||||
payload(NULL), command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), burstLength(0), extension()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -88,6 +88,10 @@ public:
|
||||
return extension.getRow();
|
||||
}
|
||||
|
||||
unsigned int getBurstLength()
|
||||
{
|
||||
return burstLength;
|
||||
}
|
||||
inline bool operator==(const ScheduledCommand& b) const
|
||||
{
|
||||
return b.command == command && b.start == start && b.executionTime == executionTime;
|
||||
@@ -99,13 +103,14 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
tlm::tlm_generic_payload* payload;
|
||||
|
||||
Command command;
|
||||
sc_time start;
|
||||
sc_time executionTime;
|
||||
|
||||
unsigned int burstLength;
|
||||
DramExtension extension;
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <algorithm>
|
||||
#include "../../utils/Utils.h"
|
||||
#include "ActivateChecker.h"
|
||||
|
||||
#include "../../../common/DebugManager.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace core {
|
||||
@@ -17,16 +17,24 @@ namespace core {
|
||||
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
sc_assert(command.getCommand() == Command::Activate);
|
||||
ScheduledCommand lastCommandOnBank = state.getLastCommand(command.getBank());
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
|
||||
if(lastCommandOnBank.isValidCommand())
|
||||
//implies precharge to activate (tRP) and refresh to activate (tFRC)
|
||||
sc_assert(command.getStart() >= state.getLastCommand(command.getBank()).getStart());
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
Command lastCommand = lastCommandOnBank.getCommand();
|
||||
if (lastCommand == Command::Precharge || lastCommand == Command::PrechargeAll
|
||||
|| lastCommand == Command::AutoRefresh || lastCommand == Command::ReadA
|
||||
|| lastCommand == Command::WriteA)
|
||||
command.delayStart(getDelayToMeetConstraint(lastCommandOnBank.getEnd(),command.getStart(), SC_ZERO_TIME));
|
||||
else
|
||||
reportFatal("Activate Checker", "Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
|
||||
satisfy_activateToActivate_sameBank(command);
|
||||
satisfy_activateToActivate_differentBank(command);
|
||||
satisfy_nActivateWindow(command);
|
||||
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
|
||||
@@ -38,20 +46,19 @@ sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transa
|
||||
|
||||
void ActivateChecker::satisfy_activateToActivate_differentBank(ScheduledCommand& command) const
|
||||
{
|
||||
ScheduledCommand lastActivate = state.getLastCommand(Command::Activate);
|
||||
if (lastActivate.isValidCommand())
|
||||
command.delayStart(
|
||||
delayByConstraint(lastActivate.getStart(), command.getStart(),
|
||||
config.Timings.tRRD));
|
||||
state.activates.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
void ActivateChecker::satisfy_activateToActivate_sameBank(ScheduledCommand& command) const
|
||||
{
|
||||
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank());
|
||||
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate,
|
||||
command.getBank());
|
||||
if (lastActivateOnBank.isValidCommand())
|
||||
{
|
||||
command.delayStart(
|
||||
delayByConstraint(lastActivateOnBank.getStart(), command.getStart(),
|
||||
getDelayToMeetConstraint(lastActivateOnBank.getStart(), command.getStart(),
|
||||
config.Timings.tRC));
|
||||
}
|
||||
}
|
||||
|
||||
void ActivateChecker::satisfy_nActivateWindow(ScheduledCommand& command) const
|
||||
@@ -60,7 +67,7 @@ void ActivateChecker::satisfy_nActivateWindow(ScheduledCommand& command) const
|
||||
return;
|
||||
|
||||
command.delayStart(
|
||||
delayByConstraint(state.nActivateWindow.getOldest(), command.getStart(),
|
||||
getDelayToMeetConstraint(state.nActivateWindow.getOldest(), command.getStart(),
|
||||
config.Timings.tTAW));
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* BusChecker.cpp
|
||||
*
|
||||
* Created on: Mar 21, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include "BusChecker.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
void BusChecker::findSlotOnBus(ScheduledCommand& command)
|
||||
{
|
||||
sc_time newStart = command.getStart();
|
||||
|
||||
sc_assert(isClkAligned(newStart, config.Timings.clk));
|
||||
std::set<sc_time>::iterator it = state.pendingBusCommands.begin();
|
||||
|
||||
while (it != state.pendingBusCommands.end() && *it <= newStart)
|
||||
{
|
||||
if (*it == newStart)
|
||||
newStart += config.Timings.clk;
|
||||
++it;
|
||||
}
|
||||
command.setStart(newStart);
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* BusChecker.h
|
||||
*
|
||||
* Created on: Mar 21, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef BUSCHECKER_H_
|
||||
#define BUSCHECKER_H_
|
||||
|
||||
#include "../../Configuration.h"
|
||||
#include "../../ControllerState.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class BusChecker
|
||||
{
|
||||
public:
|
||||
BusChecker(const Configuration& config, ControllerState& state) : config(config), state(state){}
|
||||
~BusChecker(){}
|
||||
|
||||
void findSlotOnBus(ScheduledCommand& command);
|
||||
|
||||
const Configuration& config;
|
||||
ControllerState& state;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
#endif /* BUSCHECKER_H_ */
|
||||
@@ -11,10 +11,30 @@ namespace core {
|
||||
|
||||
void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
sc_assert(command.getCommand() == Command::Precharge || command.getCommand() == Command::PrechargeAll);
|
||||
ScheduledCommand lastCommandOnBank = state.getLastCommand(command.getBank());
|
||||
if(lastCommandOnBank.isValidCommand())
|
||||
sc_assert(command.getStart() >= state.getLastCommand(command.getBank()).getStart());
|
||||
sc_assert(command.getCommand() == Command::Precharge || command.getCommand() == Command::PrechargeAll);
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Read)
|
||||
{
|
||||
command.delayStart(
|
||||
getDelayToMeetConstraint(lastCommandOnBank.getStart(), command.getStart(),
|
||||
lastCommandOnBank.getBurstLength() * config.Timings.clk));
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::Write)
|
||||
{
|
||||
command.delayStart(
|
||||
getDelayToMeetConstraint(lastCommandOnBank.getStart(), command.getStart(),
|
||||
(lastCommandOnBank.getBurstLength() - 1) * config.Timings.clk
|
||||
+ config.Timings.tWL));
|
||||
}
|
||||
else
|
||||
reportFatal("Precharge Checker",
|
||||
"Precharge can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
sc_time PrechargeChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
|
||||
@@ -12,21 +12,103 @@ namespace core {
|
||||
|
||||
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
ScheduledCommand lastCommand = state.getLastCommand(command.getBank());
|
||||
if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart())
|
||||
assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
|
||||
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
command.delayStart(lastCommand.getEnd()-command.getStart());
|
||||
if (lastCommandOnBank.getCommand() == Command::Activate)
|
||||
{
|
||||
command.delayStart(getDelayToMeetConstraint(lastCommandOnBank.getEnd(),command.getStart(), SC_ZERO_TIME));
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::Read
|
||||
|| lastCommandOnBank.getCommand() == Command::Write)
|
||||
{
|
||||
}
|
||||
else
|
||||
reportFatal("Read Checker",
|
||||
"Read can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
|
||||
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
|
||||
{
|
||||
command.delayStart(config.Timings.clk);
|
||||
}
|
||||
}
|
||||
|
||||
sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
assert(command == Command::Read || command == Command::ReadA);
|
||||
//return config.Timings.tRL + config.Timings.clk*getBurstLengthInBytes(transaction, config.buswidth);
|
||||
sc_time result = config.Timings.tRL + config.Timings.clk*payload.get_streaming_width();
|
||||
return result;
|
||||
|
||||
if (command == Command::Read)
|
||||
{
|
||||
return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width();
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width()
|
||||
+ config.Timings.tRP;
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
|
||||
{
|
||||
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
|
||||
{
|
||||
if (collidesWithStrobeCommand(read, strobeCommand))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
|
||||
ScheduledCommand& strobeCommand) const
|
||||
{
|
||||
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
//read to read
|
||||
TimeInterval readOnStrobe = getIntervalOnDataStrobe(read, config.Timings);
|
||||
TimeInterval otherReadOnStrobe = getIntervalOnDataStrobe(strobeCommand, config.Timings);
|
||||
|
||||
if (readOnStrobe.timeIsInInterval(otherReadOnStrobe.start))
|
||||
{
|
||||
return !isClkAligned(otherReadOnStrobe.start - readOnStrobe.start,
|
||||
2 * config.Timings.clk);
|
||||
}
|
||||
else if (otherReadOnStrobe.timeIsInInterval(readOnStrobe.start))
|
||||
{
|
||||
return !isClkAligned(readOnStrobe.start - otherReadOnStrobe.start,
|
||||
2 * config.Timings.clk);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (strobeCommand.getCommand() == Command::Write
|
||||
|| strobeCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
//read to write
|
||||
if (strobeCommand.getStart() >= read.getStart())
|
||||
{
|
||||
return !(strobeCommand.getStart() >= getIntervalOnDataStrobe(read, config.Timings).end);
|
||||
}
|
||||
//write to read
|
||||
else
|
||||
{
|
||||
return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand, config.Timings).end + config.Timings.tWTR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Read Checker",
|
||||
"Invalid strobeCommand in data strobe commands "
|
||||
+ commandToString(strobeCommand.getCommand()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
private:
|
||||
const Configuration& config;
|
||||
ControllerState& state;
|
||||
bool collidesOnDataStrobe(ScheduledCommand& read) const;
|
||||
bool collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -6,16 +6,38 @@
|
||||
*/
|
||||
|
||||
#include "WriteChecker.h"
|
||||
#include "../../utils/Utils.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
|
||||
ScheduledCommand lastCommand = state.getLastCommand(command.getBank());
|
||||
if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart())
|
||||
if(command.getStart() >= sc_time(62885689,SC_NS))
|
||||
{
|
||||
command.delayStart(lastCommand.getEnd()-command.getStart());
|
||||
int i = 5;
|
||||
i++;
|
||||
}
|
||||
assert(command.getCommand() == Command::Write || command.getCommand() == Command::WriteA);
|
||||
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Activate)
|
||||
{
|
||||
command.delayStart(getDelayToMeetConstraint(lastCommandOnBank.getEnd(),command.getStart(), SC_ZERO_TIME));
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::Read
|
||||
|| lastCommandOnBank.getCommand() == Command::Write)
|
||||
{
|
||||
}
|
||||
else
|
||||
reportFatal("Write Checker", "Write can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
|
||||
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
|
||||
{
|
||||
command.delayStart(config.Timings.clk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +45,57 @@ sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
assert(command == Command::Write || command == Command::WriteA);
|
||||
return config.Timings.clk*8;
|
||||
if (command == Command::Write)
|
||||
{
|
||||
return config.Timings.tWL + config.Timings.clk * (payload.get_streaming_width()-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.tWL + config.Timings.clk * (payload.get_streaming_width()-1) + config.Timings.tRP;
|
||||
}
|
||||
}
|
||||
|
||||
bool WriteChecker::collidesOnDataStrobe(ScheduledCommand& write) const
|
||||
{
|
||||
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
|
||||
{
|
||||
if (collidesWithStrobeCommand(write, strobeCommand))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write,
|
||||
ScheduledCommand& strobeCommand) const
|
||||
{
|
||||
if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
//write to write (implicitly checked by checking the command bus first)
|
||||
return false;
|
||||
}
|
||||
else if (strobeCommand.getCommand() == Command::Read
|
||||
|| strobeCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
//write to read
|
||||
if (strobeCommand.getStart() >= write.getStart())
|
||||
{
|
||||
return !(strobeCommand.getStart()>= getIntervalOnDataStrobe(write, config.Timings).end + config.Timings.tWTR);
|
||||
}
|
||||
|
||||
//read to write
|
||||
else
|
||||
{
|
||||
return !(write.getStart() >= getIntervalOnDataStrobe(strobeCommand, config.Timings).end);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Write Checker",
|
||||
"Invalid strobeCommand in data strobe commands "
|
||||
+ commandToString(strobeCommand.getCommand()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -23,6 +23,8 @@ public:
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
|
||||
private:
|
||||
bool collidesOnDataStrobe(ScheduledCommand& write) const;
|
||||
bool collidesWithStrobeCommand(ScheduledCommand& write, ScheduledCommand& strobeCommand) const;
|
||||
const Configuration& config;
|
||||
ControllerState& state;
|
||||
};
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
*/
|
||||
|
||||
#include "Utils.h"
|
||||
#include "../TimingConfiguration.h"
|
||||
|
||||
namespace core
|
||||
{
|
||||
|
||||
unsigned int getStartAddress(Bank bank)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int getBurstLengthInBytes(const tlm::tlm_generic_payload& payload, unsigned int buswidth)
|
||||
{
|
||||
return payload.get_data_length() / (buswidth/8);
|
||||
}
|
||||
|
||||
sc_time delayByConstraint(sc_time previous, sc_time start, sc_time constraint)
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint)
|
||||
{
|
||||
if (previous + constraint > start)
|
||||
return previous + constraint - start;
|
||||
@@ -33,7 +33,20 @@ const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment)
|
||||
return floor(time / clk) * clk;
|
||||
}
|
||||
|
||||
TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command, const TimingConfiguration& config)
|
||||
{
|
||||
sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA ||
|
||||
command.getCommand() == Command::Write ||command.getCommand() == Command::WriteA);
|
||||
|
||||
if(command.getCommand() == Command::ReadA || command.getCommand() == Command::WriteA)
|
||||
return TimeInterval(command.getStart(), command.getEnd() - config.tRP);
|
||||
else
|
||||
return TimeInterval(command.getStart(),command.getEnd());
|
||||
}
|
||||
|
||||
bool isClkAligned(sc_time time, sc_time clk)
|
||||
{
|
||||
return !((time / clk) - ceil(time / clk));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,14 +11,30 @@
|
||||
#include <systemc.h>
|
||||
#include <tlm.h>
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../scheduling/ScheduledCommand.h"
|
||||
|
||||
namespace core
|
||||
{
|
||||
unsigned int getStartAddress(Bank bank);
|
||||
unsigned int getBurstLengthInBytes(const tlm::tlm_generic_payload& payload, unsigned int buswidth);
|
||||
|
||||
sc_time delayByConstraint(sc_time previous, sc_time start, sc_time constraint);
|
||||
struct TimeInterval
|
||||
{
|
||||
sc_time start,end;
|
||||
TimeInterval(sc_time start,sc_time end) : start(start), end(end){}
|
||||
bool timeIsInInterval(sc_time time)
|
||||
{
|
||||
return (start<=time && time<=end);
|
||||
}
|
||||
};
|
||||
|
||||
struct TimingConfiguration;
|
||||
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint);
|
||||
TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command, const TimingConfiguration& config);
|
||||
|
||||
enum Alignment {UP, DOWN};
|
||||
const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = UP);
|
||||
bool isClkAligned(sc_time time, sc_time clk);
|
||||
|
||||
};
|
||||
#endif /* UTILS_H_ */
|
||||
|
||||
@@ -34,7 +34,8 @@ int sc_main(int argc, char **argv)
|
||||
string resources = pathOfFile(argv[0]) + string("/../resources/");
|
||||
xmlAddressDecoder::addressConfigURI = resources + string("configs/addressConfig.xml");
|
||||
TlmRecorder recorder("tpr.tdb", resources + string("scripts/createTraceDB.sql"));
|
||||
TracePlayer<> player("player", resources + string("traces/chstone-mips_32.stl"));
|
||||
//TracePlayer<> player("player", resources + string("traces/mediabench-fractal_32.stl"));
|
||||
TracePlayer<> player("player", resources + string("traces/mediabench-h263encode_32.stl"));
|
||||
|
||||
Dram<> dram("dram");
|
||||
Arbiter<> arbiter("arbiter");
|
||||
@@ -44,8 +45,10 @@ int sc_main(int argc, char **argv)
|
||||
arbiter.iSocket.bind(controller.tSocket);
|
||||
controller.iSocket.bind(dram.tSocket);
|
||||
|
||||
DebugManager::getInstance().addToWhiteList(Sender::TraceRecorder);
|
||||
DebugManager::getInstance().addToWhiteList(Sender::TracePlayer);
|
||||
// DebugManager::getInstance().addToWhiteList(Sender::TraceRecorder);
|
||||
// DebugManager::getInstance().addToWhiteList(Sender::TracePlayer);
|
||||
//DebugManager::getInstance().addToWhiteList(Sender::DramWrapper);
|
||||
//DebugManager::getInstance().addToWhiteList(Sender::DramController);
|
||||
|
||||
cout << "Toplevel: simulation start" << std::endl;
|
||||
clock_t begin = clock();
|
||||
|
||||
Reference in New Issue
Block a user