moved controllerwrapper

This commit is contained in:
robert
2014-03-17 11:15:28 +01:00
parent 1bc6b106ea
commit 368f067f2f

View File

@@ -0,0 +1,198 @@
/*
* 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 "common/protocol.h"
#include "common/tlmDBPhaseRecorder.h"
#include "dram/tlm/IControllerWrapper.h"
#include "dram/core/Controller.h"
using namespace std;
using namespace tlm;
using namespace core;
template<unsigned int BUSWIDTH = 128>
struct ControllerWrapper: public sc_module, public IControllerWrapper
{
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);
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);
}
~ControllerWrapper()
{
delete controller;
}
virtual void sendCommand(sc_time startTime, tlm::tlm_generic_payload& payload,
Command command)
{
assert(startTime >= sc_time_stamp());
sc_time delay = startTime - sc_time_stamp();
tlm::tlm_phase phase;
switch (command)
{
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(payload, phase, delay);
}
virtual void sendTrigger(sc_time time, Trigger trigger)
{
assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
controllerPEQ.notify(triggerDummy,REFRESH_TRIGGER,delay);
}
private:
DramController* controller;
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;
// 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)
{
if (phase == BEGIN_REQ)
payload.acquire();
else if (phase == END_RESP)
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)
{
payload.set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(payload,phase,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");
}
}
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
|| phase == BEGIN_PRE)
{
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if (phase == END_RD || phase == END_WR)
{
frontendPEQ.notify(payload, BEGIN_RESP, SC_ZERO_TIME);
}
else if (phase == END_PRE || phase == END_ACT || phase == END_REFA)
{
}
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)
{
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_ */