all constraints implemented

This commit is contained in:
robert
2014-03-30 12:52:12 +02:00
parent e13f2b0868
commit 75a5dca81e
26 changed files with 471 additions and 146 deletions

View File

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

View File

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

View File

@@ -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());
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
View 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
View 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_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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_ */

View File

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