Show tlm_port.h syntax highlighted
// LICENSETEXT
//
// Copyright (C) 2005,2006 :
// GreenSocs Ltd
// (http://www.greensocs.com/),
//
// email: info@greensocs.com
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
// ENDLICENSETEXT
/*******************************************************************************
**
** $Log: tlm_port.h,v $
** Revision 1.2 2006/06/02 15:57:25 klingauf
** A first GenericRouter implementation plus example protocol, scheduler and addressmap
**
** Revision 1.1 2006/05/30 14:56:09 guenzel
** *** empty log message ***
**
**
**
*******************************************************************************/
#ifndef __TLM_PORT_H__
#define __TLM_PORT_H__
#include <systemc.h>
#include "utils/payload_event_queue.h"
#ifdef DUST_ENABLE
#include "utils/gs_dust_port.h"
#endif
namespace tlm {
//forward declaration
template <class PV, class PVT>
class tlm_multi_port;
template <class PV, class PVT>
class tlm_port_forwarder_base;
//---------------------------------------------------------------------------
/**
* Base for all TLM ports. The communication uses events for both
* sending and receiving.
*/
//---------------------------------------------------------------------------
template <class PV, class PVT>
class tlm_port
: public sc_module
{
public:
typedef PV b_if_type;
typedef PVT if_type;
typedef payload_event_queue_if<if_type> peq_if_type;
#ifdef DUST_ENABLE
gs_dust_port<b_if_type> b_out;
sc_export<b_if_type> b_in;
gs_dust_port<peq_if_type> out;
sc_export<peq_if_type> in;
#else
sc_port<b_if_type> b_out;
sc_export<b_if_type> b_in;
sc_port<peq_if_type> out;
sc_export<peq_if_type> in;
#endif
payload_event_queue<if_type> peq;
SC_HAS_PROCESS(tlm_port);
tlm_port( sc_module_name port_name ) :
sc_module(port_name),
b_out(sc_gen_unique_name("b_out")),
b_in(sc_gen_unique_name("b_in")),
out(sc_gen_unique_name("out")),
in(sc_gen_unique_name("in"))
{
in(peq);
}
virtual ~tlm_port() {
}
void operator() (tlm_port<b_if_type,if_type>& other) {
b_out(other.b_in);
other.b_out(b_in);
out(other.in);
other.out(in);
}
void bind_b_if(b_if_type& other) {
b_in(other);
}
void operator() (tlm_multi_port<b_if_type,if_type>& other) {
b_out(other.b_in);
other.b_bind_out_port(b_in);
out(other.in);
other.bind_out_port(in);
}
void operator() (tlm_port_forwarder_base<b_if_type,if_type>& port_fw_) {
port_fw_.forward(*this);
}
void wait() {
sc_core::wait(in->default_event());
}
void wait(if_type payload) {
in->wait(payload);
}
if_type get_payload() {
return in->get_payload();
}
const sc_event& default_event() {
return in->default_event();
}
// const bool fired() {
// return in->fired();
// }
};
//---------------------------------------------------------------------------
/**
* A TLM multi port.
*/
//---------------------------------------------------------------------------
template <class PV, class PVT>
class tlm_multi_port
: public sc_module
{
public:
typedef PVT if_type;
typedef PV b_if_type;
typedef payload_event_queue_if<if_type> peq_if_type;
#ifdef DUST_ENABLE
gs_dust_port<peq_if_type, 0> out;
sc_export<peq_if_type> in;
gs_dust_port<b_if_type, 0> b_out;
sc_export<b_if_type> b_in;
#else
sc_port<peq_if_type, 0> out;
sc_export<peq_if_type> in;
sc_port<b_if_type, 0> b_out;
sc_export<b_if_type> b_in;
#endif
std::vector< sc_export<b_if_type>* > connected_b_in_ports;
payload_event_queue<if_type> peq;
std::vector< sc_export<peq_if_type>* > connected_in_ports;
tlm_multi_port( sc_module_name port_name ) :
sc_module(port_name),
out(sc_gen_unique_name("out")),
in(sc_gen_unique_name("in")),
b_out(sc_gen_unique_name("b_out")),
b_in(sc_gen_unique_name("b_in"))
{
in(peq);
}
virtual ~tlm_multi_port() {
}
void operator() (tlm_port<b_if_type,if_type>& other) {
b_bind_out_port(other.b_in);
other.b_out(b_in);
bind_out_port(other.in);
other.out(in);
}
void bind_b_if(b_if_type& other) {
b_in(other);
}
void operator() (tlm_multi_port<b_if_type,if_type>& other) {
SC_REPORT_FATAL(sc_core::SC_ID_NOT_IMPLEMENTED_, "multi-to-multi-port binding not supported (yet).");
}
void operator() (tlm_port_forwarder_base<b_if_type,if_type>& port_fw_) {
port_fw_.forward(*this);
}
void bind_out_port(sc_export<peq_if_type>& in){
connected_in_ports.push_back(&in);
out(in);
}
void b_bind_out_port(sc_export<b_if_type>& b_in){
connected_b_in_ports.push_back(&b_in);
b_out(b_in);
}
void wait() {
sc_core::wait(in->default_event());
}
void wait(if_type payload) {
in->wait(payload);
}
if_type get_payload() {
return in->get_payload();
}
const sc_event& default_event() {
return in->default_event();
}
const bool fired() {
return in->fired();
}
};
//---------------------------------------------------------------------------
/**
* Base class from which port forwarders can be created
*/
//---------------------------------------------------------------------------
template <class PV, class PVT>
class tlm_port_forwarder_base : public sc_module{
public:
tlm_port_forwarder_base(sc_module_name name): sc_module(name), singleNmulti(false),bound(false),forwarding(false){}
//bind forward port to tlm_port
void bind(tlm_port<PV, PVT>& port_){
if(bound) SC_REPORT_ERROR(name(), "Port is already bound.");
bound=true;
if (singleNmulti) (*m_port)(port_);
else (*m_multi_port)(port_);
}
//bind forward port to tlm_multi_port
void bind( tlm_multi_port<PV, PVT>& port_ )
{
if(bound) SC_REPORT_ERROR(name(), "Port is already bound.");
bound=true;
if (singleNmulti) (*m_port)(port_);
else (*m_multi_port)(port_);
}
//this method binds a forward port to another forward port
//unfortunately there can be no short notation for this as the () operator is already used to forward a forward port... Dang!
void bind(tlm_port_forwarder_base<PV, PVT>& port_)
{
if(bound) SC_REPORT_ERROR(name(), "Port is already bound.");
bound=true;
port_.setBound();
if(singleNmulti){
if(port_.getSNM())
(*m_port)(*(port_.getTlmPort()));
else
(*m_port)(*(port_.getTlmMultiPort()));
}
else{
if(port_.getSNM())
(*m_multi_port)(*(port_.getTlmPort()));
else
(*m_multi_port)(*(port_.getTlmMultiPort()));
}
}
//forward a forward port
void forward( tlm_port_forwarder_base<PV, PVT>& port_ )
{
//from the point of view of the fw port, it's bound when it is being forwarded to another fw port
//that's why bound is checked within a forward method
if(bound) SC_REPORT_ERROR(name(), "Port is already bound a port.");
bound=true;
if (singleNmulti) port_.forward(*m_port);
else port_.forward(*m_multi_port);
}
//this method gets called when a forward port is bound to a tlm_port
//this could either mean to forward this port or to bind it
//the default implemtation assumes forwarding
virtual void forward(tlm_port<PV, PVT>& port_)
{
if(forwarding) SC_REPORT_ERROR(name(), "Port is already forwarding a port.");
forwarding=true;
m_port=&port_;
singleNmulti=true;
}
//this method gets called when a forward port is bound to a tlm_multi_port
//this could either mean to forward this port or to bind it
//the default implemtation assumes forwarding
virtual void forward(tlm_multi_port<PV, PVT>& port_)
{
if(forwarding) SC_REPORT_ERROR(name(), "Port is already forwarding a port.");
forwarding=true;
m_multi_port=&port_;
singleNmulti=false;
}
virtual void start_of_simulation(){
if (!bound)
SC_REPORT_ERROR(name(), "Port is not bound.");
if (!forwarding)
SC_REPORT_ERROR(name(), "Port is not forwarding a port.");
}
//some getters
bool getSNM(){return singleNmulti;}
tlm_port<PV, PVT>* getTlmPort(){return m_port;}
tlm_multi_port<PV, PVT>* getTlmMultiPort(){return m_multi_port;}
void setBound(){bound=true;}
private:
tlm_port<PV, PVT>* m_port;
tlm_multi_port<PV, PVT>* m_multi_port;
bool singleNmulti;
bool bound;
bool forwarding;
};
} // end of namespace tlm
#endif
See more files for this project here