merged everythin into one project
This commit is contained in:
270
dram/src/simulation/controllerwrapper.h
Normal file
270
dram/src/simulation/controllerwrapper.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* ControllerWrapper.h
|
||||
*
|
||||
* Created on: Mar 15, 2014
|
||||
* Author: gernhard
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLERWRAPPER_H_
|
||||
#define CONTROLLERWRAPPER_H_
|
||||
|
||||
#include <tlm.h>
|
||||
#include <systemc.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#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 "../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
|
||||
{
|
||||
public:
|
||||
|
||||
tlm_utils::simple_initiator_socket<ControllerWrapper, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
|
||||
tlm_utils::simple_target_socket<ControllerWrapper, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
|
||||
|
||||
ControllerWrapper(sc_module_name name, tlmDBPhaseRecorder& tpr):
|
||||
frontendPEQ(this, &ControllerWrapper::frontendPEQCallback), dramPEQ(
|
||||
this, &ControllerWrapper::dramPEQCallback), controllerPEQ(this,
|
||||
&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) override
|
||||
{
|
||||
assert(command.getStart() >= sc_time_stamp());
|
||||
sc_time delay = command.getStart() - sc_time_stamp();
|
||||
tlm::tlm_phase phase;
|
||||
|
||||
switch (command.getCommand())
|
||||
{
|
||||
case Read:
|
||||
phase = BEGIN_RD;
|
||||
break;
|
||||
case Write:
|
||||
phase = BEGIN_WR;
|
||||
break;
|
||||
case Refresh:
|
||||
phase = BEGIN_REFA;
|
||||
break;
|
||||
case Activate:
|
||||
phase = BEGIN_ACT;
|
||||
break;
|
||||
case Precharge:
|
||||
phase = BEGIN_PRE;
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL(0, "unsupported command in controller wrapper");
|
||||
break;
|
||||
}
|
||||
|
||||
dramPEQ.notify(command.getTransaction(), phase, delay);
|
||||
}
|
||||
|
||||
virtual void send(Trigger trigger, sc_time time) override
|
||||
{
|
||||
assert(time >= sc_time_stamp());
|
||||
sc_time delay = time - sc_time_stamp();
|
||||
controllerPEQ.notify(triggerDummy, REFRESH_TRIGGER, delay);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
sc_time inputBufferDelay;
|
||||
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)
|
||||
{
|
||||
dramPEQ.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
// Initiated by dram frontend
|
||||
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void frontendPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
|
||||
{
|
||||
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
payloadEntersSystem(payload);
|
||||
payload.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
tpr.recordPhase(payload, END_REQ, sc_time_stamp());
|
||||
sendToFrontend(payload, END_REQ, SC_ZERO_TIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0,
|
||||
"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());
|
||||
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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
tpr.recordPhase(payload, BEGIN_RESP, sc_time_stamp());
|
||||
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
|
||||
}
|
||||
else if (phase == END_PRE || phase == END_ACT)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0,
|
||||
"dramPEQCallback queue in controller wrapper was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
void controllerPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
|
||||
{
|
||||
if (phase == REFRESH_TRIGGER)
|
||||
{
|
||||
controller->scheduleRefresh(sc_time_stamp());
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0,
|
||||
"controllerPEQCallback queue in controller wrapper was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void sendToFrontend(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay)
|
||||
{
|
||||
tlm_phase TPhase = phase;
|
||||
sc_time TDelay = delay;
|
||||
tSocket->nb_transport_bw(payload, TPhase, TDelay);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERWRAPPER_H_ */
|
||||
Reference in New Issue
Block a user