integrated scheduler into core

This commit is contained in:
robert
2014-03-19 20:48:06 +01:00
parent 23076bcf7d
commit bc9e35bd61
25 changed files with 434 additions and 76 deletions

View File

@@ -14,15 +14,19 @@
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/peq_with_cb_and_phase.h>
#include <iostream>
#include <map>
#include "common/protocol.h"
#include "common/tlmDBPhaseRecorder.h"
#include "dram/core/IWrapperConnector.h"
#include "dram/core/Controller.h"
#include "../core/IWrapperConnector.h"
#include "../core/Controller.h"
#include "../scheduler/Scheduler.h"
#include "../scheduler/Fifo.h"
using namespace std;
using namespace tlm;
using namespace core;
using namespace scheduler;
template<unsigned int BUSWIDTH = 128>
struct ControllerWrapper: public sc_module, public IWrapperConnector
@@ -38,21 +42,27 @@ public:
&ControllerWrapper::controllerPEQCallback), tpr(tpr)
{
controller = new DramController(*this);
scheduler = new Fifo(controller->getBankStates());
inputBufferDelay = controller->config.Timings.clk;
iSocket.register_nb_transport_bw(this, &ControllerWrapper::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &ControllerWrapper::nb_transport_fw);
for(Bank bank:controller->getBankStates().getBanks())
bankIsFreeForRequest[bank] = true;
}
~ControllerWrapper()
{
delete controller;
delete scheduler;
}
virtual void send(const ScheduledCommand& command)
virtual void send(const ScheduledCommand& command) override
{
assert(command.getStart() >= sc_time_stamp()||command.getStart()<sc_time(100000, SC_NS));
assert(command.getStart() >= sc_time_stamp());
sc_time delay = command.getStart() - sc_time_stamp();
tlm::tlm_phase phase;
switch (command.getCommand())
{
case Read:
@@ -78,7 +88,7 @@ public:
dramPEQ.notify(command.getTransaction(), phase, delay);
}
virtual void send(Trigger trigger, sc_time time)
virtual void send(Trigger trigger, sc_time time) override
{
assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
@@ -87,6 +97,9 @@ public:
private:
DramController* controller;
Scheduler* scheduler;
map<Bank, bool> bankIsFreeForRequest;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> frontendPEQ;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> dramPEQ;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> controllerPEQ;
@@ -95,6 +108,45 @@ private:
tlm::tlm_generic_payload triggerDummy;
tlmDBPhaseRecorder& tpr;
void payloadEntersSystem(tlm_generic_payload& payload)
{
//std::cout << "----------------------------------------------------------------------- " << std::endl;
//std::cout << "Transaction enters system at " << sc_time_stamp() << std::endl;
Bank bank = DramExtension::getExtension(payload).getBank();
scheduler->schedule(&payload);
scheduleNextPayload(bank);
}
void scheduleNextPayload(Bank bank)
{
//std::cout << "----------------------------------------------------------------------- " << std::endl;
//std::cout << "In trigger for bank " << bank.ID() << std::endl;
if(controller->isBusy(sc_time_stamp(), bank))
return;
else if(scheduler->hasTransactionForBank(bank))
{
tlm_generic_payload* nextTransaction = scheduler->getTransactionForBank(bank);
if(controller->schedule(sc_time_stamp(), *nextTransaction))
{
//std::cout << "Next payload was scheduled by core " << std::endl;
scheduler->popTransactionForBank(bank);
}
else
{
//std::cout << "Next payload was not scheduled because of refresh " << std::endl;
}
}
}
void payloadLeavesSystem(tlm_generic_payload& payload)
{
}
// Initiated by dram
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
{
@@ -105,57 +157,76 @@ private:
// Initiated by dram frontend
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay)
{
if (phase == BEGIN_REQ)
payload.acquire();
else if (phase == END_RESP)
payload.release();
DramExtension::getExtension(payload);
tpr.recordPhase(payload,phase,sc_time_stamp());
if (phase == BEGIN_REQ)
{
payload.acquire();
frontendPEQ.notify(payload, phase, inputBufferDelay);
}
else if (phase == END_RESP)
{
payloadLeavesSystem(payload);
payload.release();
}
frontendPEQ.notify(payload, phase, fwDelay);
return TLM_ACCEPTED;
}
void frontendPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
{
tpr.recordPhase(payload,phase,sc_time_stamp());
if (phase == BEGIN_REQ)
{
controller->schedule(sc_time_stamp() + inputBufferDelay, payload);
frontendPEQ.notify(payload,END_REQ,inputBufferDelay);
}
else if(phase == END_REQ)
{
payloadEntersSystem(payload);
payload.set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(payload,phase,SC_ZERO_TIME);
tpr.recordPhase(payload, END_REQ, sc_time_stamp());
sendToFrontend(payload, END_REQ, SC_ZERO_TIME);
}
else if (phase == BEGIN_RESP)
{
sendToFrontend(payload, phase, SC_ZERO_TIME);
}
else if (phase == END_RESP)
{
}
else
{
SC_REPORT_FATAL(0,
"Payload event queue in controller wrapper was triggered with unknown phase");
"Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
}
}
void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
{
tpr.recordPhase(payload,phase,sc_time_stamp());
if (phase == BEGIN_RD || phase == BEGIN_WR || phase == BEGIN_REFA || phase == BEGIN_ACT
DramExtension *result = NULL;
payload.get_extension(result);
if(result==NULL)
{
cout << "ERROR AT TIME " << sc_time_stamp() << std::endl;
cout << "Payload " << payload.get_address() << " " << phase;
assert(result != NULL);
}
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
//std::cout << "BEGIN_RD at " <<sc_time_stamp() << " on Bank " << DramExtension::getExtension(payload).getBank().ID() << std::endl;
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == BEGIN_REFA || phase == BEGIN_ACT
|| phase == BEGIN_PRE)
{
sendToDram(payload, phase, SC_ZERO_TIME);//TODO delay in send mehtod instead of way through PEQ
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == END_REFA)
{
//std::cout << " --- END_REFA --- @:" <<sc_time_stamp() << std::endl;
for(Bank bank:controller->getBankStates().getBanks())
scheduleNextPayload(bank);
}
else if (phase == END_RD || phase == END_WR)
{
frontendPEQ.notify(payload, BEGIN_RESP, SC_ZERO_TIME);
tpr.recordPhase(payload, BEGIN_RESP, sc_time_stamp());
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
}
else if (phase == END_PRE || phase == END_ACT || phase == END_REFA)
else if (phase == END_PRE || phase == END_ACT)
{
}
@@ -181,6 +252,7 @@ private:
void sendToDram(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay)
{
DramExtension::getExtension(payload);
tlm_phase TPhase = phase;
sc_time TDelay = delay;
iSocket->nb_transport_fw(payload, TPhase, TDelay);