149 lines
3.8 KiB
C++
149 lines
3.8 KiB
C++
/*
|
|
* arbiter.h
|
|
*
|
|
* Created on: Mar 16, 2014
|
|
* Author: robert
|
|
*/
|
|
|
|
#ifndef ARBITER_H_
|
|
#define ARBITER_H_
|
|
|
|
|
|
#include <deque>
|
|
#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 "../common/xmlAddressdecoder.h"
|
|
#include "../common/dramExtension.h"
|
|
#include "../core/utils/Utils.h"
|
|
#include <iostream>
|
|
|
|
|
|
using namespace std;
|
|
using namespace tlm;
|
|
|
|
template<unsigned int NUMBER_OF_THREADS = 1, unsigned int BUSWIDTH = 128>
|
|
struct Arbiter: public sc_module
|
|
{
|
|
public:
|
|
tlm_utils::simple_initiator_socket<Arbiter,BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
|
|
tlm_utils::simple_target_socket_tagged<Arbiter, BUSWIDTH, tlm::tlm_base_protocol_types> tSockets[NUMBER_OF_THREADS];
|
|
|
|
SC_CTOR(Arbiter) :
|
|
payloadEventQueue(this, &Arbiter::peqCallback), channelIsFree(true)
|
|
{
|
|
iSocket.register_nb_transport_bw(this, &Arbiter::nb_transport_bw);
|
|
|
|
for (unsigned int i = 0; i < NUMBER_OF_THREADS; ++i)
|
|
{
|
|
tSockets[i].register_nb_transport_fw(this, &Arbiter::nb_transport_fw, i);
|
|
}
|
|
}
|
|
|
|
private:
|
|
tlm_utils::peq_with_cb_and_phase<Arbiter> payloadEventQueue;
|
|
bool channelIsFree;
|
|
deque<tlm_generic_payload* > backpressure;
|
|
|
|
|
|
// Initiated by schedulerWrapper
|
|
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
|
|
{
|
|
payloadEventQueue.notify(payload, phase, bwDelay);
|
|
return TLM_ACCEPTED;
|
|
}
|
|
|
|
// Initiated by .stl players
|
|
tlm_sync_enum nb_transport_fw(int socketId, tlm_generic_payload& payload, tlm_phase& phase,
|
|
sc_time& fwDelay)
|
|
{
|
|
if(phase == BEGIN_REQ)
|
|
{
|
|
appendDramExtension(socketId, payload);
|
|
payload.acquire();
|
|
}
|
|
else if(phase == END_RESP)
|
|
payload.release();
|
|
|
|
payloadEventQueue.notify(payload, phase, fwDelay);
|
|
return TLM_ACCEPTED;
|
|
}
|
|
|
|
void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase)
|
|
{
|
|
//Phases initiated by .stl players
|
|
if (phase == BEGIN_REQ)
|
|
{
|
|
if(channelIsFree)
|
|
{
|
|
channelIsFree = false;
|
|
sendToChannel(payload, phase, SC_ZERO_TIME );
|
|
}
|
|
else
|
|
{
|
|
backpressure.push_back(&payload);
|
|
}
|
|
}
|
|
|
|
else if (phase == END_RESP)
|
|
{
|
|
sendToChannel(payload, phase, SC_ZERO_TIME );
|
|
}
|
|
|
|
//Phases initiated by dram backend
|
|
else if (phase == END_REQ)
|
|
{
|
|
channelIsFree = true;
|
|
sendToTraceplayer(DramExtension::getExtension(payload).getThread().ID()-1, payload, phase, SC_ZERO_TIME);
|
|
|
|
if(!backpressure.empty())
|
|
{
|
|
tlm_generic_payload* payloadToSend = backpressure.front();
|
|
backpressure.pop_front();
|
|
sendToChannel(*payloadToSend, BEGIN_REQ, SC_ZERO_TIME );
|
|
channelIsFree = false;
|
|
}
|
|
}
|
|
else if (phase == BEGIN_RESP)
|
|
{
|
|
sendToTraceplayer(DramExtension::getExtension(payload).getThread().ID()-1, payload, phase, SC_ZERO_TIME);
|
|
}
|
|
|
|
else
|
|
{
|
|
SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase");
|
|
}
|
|
}
|
|
|
|
void sendToChannel(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 sendToTraceplayer(unsigned int id, tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay)
|
|
{
|
|
tlm_phase TPhase = phase;
|
|
sc_time TDelay = delay;
|
|
tSockets[id]->nb_transport_bw(payload, TPhase, TDelay);
|
|
}
|
|
|
|
void appendDramExtension(int socketId, tlm_generic_payload& payload)
|
|
{
|
|
unsigned int burstlength = payload.get_streaming_width();
|
|
node n;
|
|
xmlAddressDecoder::getInstance().getNode(static_cast<unsigned int>(payload.get_address()), &n);
|
|
Bank bank(n.bank);
|
|
DramExtension* extension = new DramExtension(Thread(socketId+1), Channel(n.channel), bank, bank.getBankGroup(), Row(n.row), Column(n.colum),burstlength);
|
|
payload.set_auto_extension(extension);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif /* ARBITER_H_ */
|