Show generic.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
#ifndef __GENERIC_H__
#define __GENERIC_H__
#include "gstlm/tlm.h"
#include "userAPI/basicPorts.h"
#include <stdarg.h>
#ifdef DUST_ENABLE
# include "scv.h"
#endif
#ifdef GSVERBOSE
#define GS_DELTA_WARNING SC_REPORT_WARNING("GreenBus GenericAPI", "Using an untimed GreenBus notification. If you call this method multiple times while in the same delta cycle, only the last call will be processed. As a solution, use SC_ZERO_TIME delay.")
#else
#define GS_DELTA_WARNING
#endif
namespace tlm {
//---------------------------------------------------------------------------
/**
* Interface to access the generic transaction through the master.
*/
//---------------------------------------------------------------------------
class GenericMasterAccess : public virtual TransactionBase {
public :
virtual void set_mID(const MID&) =0;
virtual void set_mCmd(const MCmd&) =0;
virtual void set_mAddr(const MAddr&) =0;
virtual void set_mData(const MData&) =0;
virtual void set_mBurstLength(const MBurstLength&) =0;
virtual const MID& get_mID() const =0;
virtual const MCmd& get_mCmd() const =0;
virtual const MAddr& get_mAddr() const =0;
virtual const MData& get_mData() const =0;
virtual const MBurstLength& get_mBurstLength() const =0;
virtual const SResp& get_sResp() const =0;
virtual const MData& get_sData() const =0;
virtual void set_mError(const Error& _mError)=0;
virtual const Error get_mError() const=0;
virtual const Error get_sError() const=0;
};
//---------------------------------------------------------------------------
/**
* Interface to access the generic transaction through the slave.
*/
//---------------------------------------------------------------------------
class GenericTargetAccess : public virtual TransactionBase {
public :
virtual void set_sResp(const SResp&) =0;
virtual void set_sData(const MData&) =0;
virtual const MID& get_mID() const =0;
virtual const MCmd& get_mCmd() const =0;
virtual const MAddr& get_mAddr() const =0;
virtual const MData& get_mData() const =0;
virtual void get_mData(const MData & _dst ) =0;
virtual const MBurstLength& get_mBurstLength() const =0;
virtual const SResp& get_sResp() const =0;
virtual const MData& get_sData() const =0;
virtual const Error get_mError() const=0;
virtual void set_sError(const Error& _sError)=0;
virtual const Error get_sError() const=0;
};
//---------------------------------------------------------------------------
/**
* Interface to access the generic transaction through the router.
*/
//---------------------------------------------------------------------------
class GenericRouterAccess : public virtual TransactionBase {
public :
virtual const MID& get_mID() const =0;
virtual const MCmd& get_mCmd() const =0;
virtual const MAddr& get_mAddr() const =0;
virtual const MBurstLength& get_mBurstLength() const =0;
virtual void set_mError(const Error& _mError)=0;
virtual const Error get_mError() const=0;
virtual void set_sError(const Error& _sError)=0;
virtual const Error get_sError() const=0;
};
//---------------------------------------------------------------------------
/**
* A generic phase class
*/
//---------------------------------------------------------------------------
char phase_desc[] = "Phases for the Generic Protocol";
class GenericPhase : public Description<phase_desc>
{
public:
enum {
Idle = 0,
RequestValid,RequestAccepted,RequestError,
DataValid, DataAccepted, DataError,
ResponseValid,ResponseAccepted, ResponseError,
LAST_GENERIC_PHASE
};
int state;
unsigned int BurstNumber;
GenericPhase() : state(Idle) {};
GenericPhase(int s):state(s){BurstNumber=0;};
GenericPhase(int s, unsigned int b):state(s),BurstNumber(b){};
inline bool isRequestValid() { return state == RequestValid; }
inline bool isRequestAccepted() { return state == RequestAccepted; }
inline bool isRequestError() { return state == RequestError; }
inline bool isDataValid() { return state == DataValid; }
inline bool isDataAccepted() { return state == DataAccepted; }
inline bool isDataError() { return state == DataError; }
inline bool isResponseValid() { return state == ResponseValid; }
inline bool isResponseAccepted() { return state == ResponseAccepted; }
inline bool isResponseError() { return state == ResponseError; }
std::string toString() {
if (isRequestValid()) return std::string("RequestValid");
else if (isRequestAccepted()) return std::string("RequestAccepted");
else if (isRequestError()) return std::string("RequestError");
else if (isDataValid()) return std::string("DataValid");
else if (isDataAccepted()) return std::string("DataAccepted");
else if (isDataError()) return std::string("DataError");
else if (isResponseValid()) return std::string("ResponseValid");
else if (isResponseAccepted()) return std::string("ResponseAccepted");
else if (isResponseError()) return std::string("ResponseError");
else return std::string("unknown phase");
}
};
//---------------------------------------------------------------------------
/**
* A generic transaction class
*/
//---------------------------------------------------------------------------
#define REQUESTPHASE GenericPhase::RequestValid, GenericPhase::RequestAccepted, GenericPhase::RequestError
#define DATAPHASE GenericPhase::DataValid, GenericPhase::DataAccepted, GenericPhase::DataError
#define RESPONSEPHASE GenericPhase::ResponseValid, GenericPhase::ResponseAccepted, GenericPhase::ResponseError
#define INITATTRIBUTE(name) \
name.set_name(#name)
#define ADDTOPHASE(name, ...) \
set_phases(name, false, __VA_ARGS__ , 65563 )
#define ADDEXTTOPHASE(name, ...) \
set_phases(name, true, __VA_ARGS__ , 65563 )
class GenericTransaction :
public virtual GenericMasterAccess,
public virtual GenericTargetAccess,
public virtual GenericRouterAccess
{
#ifdef DUST_ENABLE
friend class scv_extensions<GenericTransaction>;
#endif
protected:
MCmd mCmd;
MAddr mAddr;
MData msData;
MBurstLength mBurstLength;
SResp sResp;
Error mError;
Error sError;
MID mID;
bool is_extended;
std::string extendedType;
attribute_map attribs;
attribute_map extended_attribs;
public:
void set_mID(const MID& _mID) {mID=_mID;}
void set_mCmd(const MCmd& _mCmd){mCmd=_mCmd;}
void set_mAddr(const MAddr& _mAddr){ mAddr=_mAddr;}
void set_mData(const MasterDataType& _mData){ msData.set(_mData);}
void set_mBurstLength(const MBurstLength& _mBurstLength){ mBurstLength=_mBurstLength; }
void set_sResp(const SResp& _sResp){ sResp = _sResp; }
void set_sData(const MData& _sData){ msData.deepcopy_to( _sData ); }
// todo sData for "slices"
const MID& get_mID() const {return mID;}
const MCmd& get_mCmd() const {return mCmd; }
const MAddr& get_mAddr() const {return mAddr; }
const MData& get_mData() const {return msData; }
void get_mData(const MData & _dst ) { msData.deepcopy_from(_dst); }
// todo mData for "slices"
const MBurstLength& get_mBurstLength() const {return mBurstLength; }
const SResp& get_sResp() const {return sResp; }
const MData& get_sData() const {return msData; }
void set_mError(const Error& _mError) {mError=_mError;}
const Error get_mError() const {return mError;}
void set_sError(const Error& _sError) {sError=_sError;}
const Error get_sError() const {return sError;}
//access functions
attribute_iterator get_AttributeIterator(int phase){return attribs.find(phase);}
attribute_iterator lastAttribute(int phase){
if (attribs.find(phase)==attribs.end())
return attribs.end() ;
else
return attribs.upper_bound(phase);
}
attribute_iterator get_ExtendedAttributeIterator(int phase){return extended_attribs.find(phase);}
attribute_iterator lastExtendedAttribute(int phase){
if (extended_attribs.find(phase)==extended_attribs.end())
return extended_attribs.end() ;
else
return extended_attribs.upper_bound(phase);
}
void set_phases(AttributeRoot& attr, bool extended,...){
va_list ap;
va_start(ap, extended);
for (;;){
int a=va_arg(ap, int);
if (a==65563) break;
if (extended)
extended_attribs.insert(std::make_pair(a, &attr));
else
attribs.insert(std::make_pair(a, &attr));
}
va_end(ap);
}
bool isExtended(){return is_extended;}
std::string getExtendedType(){return extendedType;}
GenericTransaction() : mBurstLength(1), mError(0), sError(0),is_extended(false), extendedType("N/A") {
INITATTRIBUTE(mCmd);
ADDTOPHASE(mCmd,REQUESTPHASE);
INITATTRIBUTE(mAddr);
ADDTOPHASE(mAddr,REQUESTPHASE, DATAPHASE, RESPONSEPHASE);
INITATTRIBUTE(msData);
ADDTOPHASE(msData,DATAPHASE, RESPONSEPHASE);
INITATTRIBUTE(mBurstLength);
ADDTOPHASE(mBurstLength,REQUESTPHASE);
INITATTRIBUTE(sResp);
ADDTOPHASE(sResp, RESPONSEPHASE);
INITATTRIBUTE(mError);
ADDTOPHASE(mError, REQUESTPHASE, DATAPHASE, RESPONSEPHASE);
INITATTRIBUTE(sError);
ADDTOPHASE(sError, REQUESTPHASE, DATAPHASE, RESPONSEPHASE);
INITATTRIBUTE(mID);
ADDTOPHASE(mID, REQUESTPHASE, DATAPHASE, RESPONSEPHASE);
}
};
typedef boost::shared_ptr<GenericTransaction> GenericTransaction_P;
//---------------------------------------------------------------------------
/**
* Generic API to notify with three methods: now, sc_time, double+sc_time_unit
*/
//---------------------------------------------------------------------------
template <class PORT, class operation>
class Notifications
{
PORT& port;
public:
Notifications(PORT &port_) : port(port_) {}
typedef typename PORT::transaction transaction;
typedef typename PORT::transactionHandle transactionHandle;
typedef typename PORT::accessHandle accessHandle;
typedef typename PORT::phaseHandle phaseHandle;
void operator()(accessHandle th, phaseHandle _p)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p(_p);
port.out->notify(typename PORT::pair_type(t,p));
GS_DELTA_WARNING;
}
void operator()(accessHandle th, phaseHandle _p, const sc_time &d)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p(_p);
port.out->notify(typename PORT::pair_type(t,p),d);
}
void operator()(accessHandle th, phaseHandle _p, double d, sc_time_unit u)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p(_p);
port.out->notify(typename PORT::pair_type(t,p),d,u);
}
void block(accessHandle th, phaseHandle _p)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p(_p);
port.out->notify(typename PORT::pair_type(t,p));
port.wait(typename PORT::pair_type(t,p));
GS_DELTA_WARNING;
}
void block(accessHandle th, phaseHandle _p, const sc_time &d)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p(_p);
port.out->notify(typename PORT::pair_type(t,p),d);
port.wait(typename PORT::pair_type(t,p));
}
void block(accessHandle th, phaseHandle _p, double d, sc_time_unit u)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p(_p);
port.out->notify(typename PORT::pair_type(t,p,d),d,u);
port.wait(typename PORT::pair_type(t,p));
}
void operator()(accessHandle th)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p;
port.out->notify(typename PORT::pair_type(t,p));
GS_DELTA_WARNING;
}
void operator()(accessHandle th , const sc_time &d)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p;
port.out->notify(typename PORT::pair_type(t,p),d);
}
void operator()(accessHandle th , double d, sc_time_unit u)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p;
port.out->notify(typename PORT::pair_type(t,p),d,u);
}
void block(accessHandle th)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p;
port.out->notify(typename PORT::pair_type(t, p));
port.wait(typename PORT::pair_type(t,p));
GS_DELTA_WARNING;
}
void block(accessHandle th, const sc_time &d)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p;
port.out->notify(typename PORT::pair_type(t, p),d);
port.wait(typename PORT::pair_type(t,p));
}
void block(accessHandle th, double d, sc_time_unit u)
{
transactionHandle t = boost::dynamic_pointer_cast<transaction>(th);
operation p;
port.out->notify(typename PORT::pair_type(t, p),d,u);
port.wait(typename PORT::pair_type(t,p));
}
};
// Functor to be used with Notifications
struct noChangePhase : public GenericPhase
{
noChangePhase( const GenericPhase & p) :GenericPhase(p.state,p.BurstNumber){ };
};
// Functor to be used with Notifications
struct IdlePhase : public GenericPhase
{
IdlePhase( const GenericPhase& p) :GenericPhase(GenericPhase::Idle){};
IdlePhase( ) :GenericPhase(GenericPhase::Idle){};
};
// Functor to be used with Notifications
struct setRequestValid_BurstNumber0Phase : public GenericPhase
{
setRequestValid_BurstNumber0Phase( const GenericPhase & p) : GenericPhase(GenericPhase::RequestValid,0) { };
setRequestValid_BurstNumber0Phase() : GenericPhase(GenericPhase::RequestValid,0) { };
};
// Functor to be used with Notifications
struct setRequestAcceptedPhase : public GenericPhase
{
setRequestAcceptedPhase(const GenericPhase & p) : GenericPhase(GenericPhase::RequestAccepted) { };
setRequestAcceptedPhase() : GenericPhase(GenericPhase::RequestAccepted) { };
};
// Functor to be used with Notifications
struct setRequestErrorPhase : public GenericPhase
{
setRequestErrorPhase(const GenericPhase & p) : GenericPhase(GenericPhase::RequestError) { };
setRequestErrorPhase() : GenericPhase(GenericPhase::RequestError) { };
};
// Functor to be used with Notifications
struct setDataValid_BurstUpdatePhase : public GenericPhase
{
setDataValid_BurstUpdatePhase(const GenericPhase & p) : GenericPhase(GenericPhase::DataValid, p.BurstNumber+1) { };
};
// Functor to be used with Notifications
struct setDataAcceptedPhase : public GenericPhase
{
setDataAcceptedPhase(const GenericPhase & p) : GenericPhase(GenericPhase::DataAccepted,p.BurstNumber) { };
};
// Functor to be used with Notifications
struct setDataErrorPhase : public GenericPhase
{
setDataErrorPhase(const GenericPhase & p) : GenericPhase(GenericPhase::DataError,p.BurstNumber) { };
};
// Functor to be used with Notifications
struct setResponseValidPhase : public GenericPhase
{
setResponseValidPhase(const GenericPhase & p) : GenericPhase(GenericPhase::ResponseValid) { };
setResponseValidPhase() : GenericPhase(GenericPhase::ResponseValid) { };
};
// Functor to be used with Notifications
struct setResponseAcceptedPhase : public GenericPhase
{
setResponseAcceptedPhase(const GenericPhase & p) : GenericPhase(GenericPhase::ResponseAccepted) { };
setResponseAcceptedPhase() : GenericPhase(GenericPhase::ResponseAccepted) { };
};
// Functor to be used with Notifications
struct setResponseErrorPhase : public GenericPhase
{
setResponseErrorPhase(const GenericPhase & p) : GenericPhase(GenericPhase::ResponseError) { };
setResponseErrorPhase() : GenericPhase(GenericPhase::ResponseError) { };
};
//---------------------------------------------------------------------------
/**
* The API for the generic protocol that can be accessed by the initiator port.
*/
//---------------------------------------------------------------------------
template <class PORT>
class GenericInitiatorAPI :
public PORT
{
public:
GenericInitiatorAPI ( sc_module_name port_name ) :
PORT ( port_name ),
Repass(*this),
Idle(*this),
Request(*this),
SendData(*this),
AckData(*this),
ErrorData(*this),
AckResponse(*this),
ErrorResponse(*this)
{}
Notifications<PORT, noChangePhase> Repass;
Notifications<PORT, IdlePhase> Idle;
Notifications<PORT, setRequestValid_BurstNumber0Phase> Request;
Notifications<PORT, setDataValid_BurstUpdatePhase> SendData;
Notifications<PORT, setDataAcceptedPhase> AckData;
Notifications<PORT, setDataErrorPhase> ErrorData;
Notifications<PORT, setResponseAcceptedPhase> AckResponse;
Notifications<PORT, setResponseErrorPhase> ErrorResponse;
//TODO: This Transact have to go away!
typedef typename PORT::transaction transaction;
typedef typename PORT::accessHandle accessHandle;
typedef typename PORT::phaseHandle phaseHandle;
void Transact(accessHandle t)
{
PORT::b_out->b_transact(boost::dynamic_pointer_cast<transaction>(t));
// cast from base class ACCESS to derived class TRANSACTION
}
};
//---------------------------------------------------------------------------
/**
* The API for the generic protocol that can be accessed by the target port.
*/
//---------------------------------------------------------------------------
template <class PORT>
class GenericTargetAPI :
public PORT
{
public:
GenericTargetAPI ( sc_module_name port_name ) :
PORT ( port_name ),
Repass(*this),
Idle(*this),
FinishBlocking(*this),
SendData(*this),
AckData(*this),
ErrorData(*this),
Response(*this),
AckRequest(*this),
ErrorRequest(*this)
{}
Notifications<PORT, noChangePhase> Repass;
Notifications<PORT, IdlePhase> Idle;
Notifications<PORT, setRequestAcceptedPhase> FinishBlocking;
Notifications<PORT, setDataValid_BurstUpdatePhase> SendData;
Notifications<PORT, setDataAcceptedPhase> AckData;
Notifications<PORT, setDataErrorPhase> ErrorData;
Notifications<PORT, setResponseValidPhase> Response;
Notifications<PORT, setRequestAcceptedPhase> AckRequest;
Notifications<PORT, setRequestErrorPhase> ErrorRequest;
};
//---------------------------------------------------------------------------
/**
* The default master initiator port.
*/
//---------------------------------------------------------------------------
typedef GenericInitiatorAPI<master_port<GenericTransaction,GenericMasterAccess,GenericPhase> > GenericMasterPort;
//---------------------------------------------------------------------------
/**
* The default router initiator port.
*/
//---------------------------------------------------------------------------
typedef GenericInitiatorAPI<initiator_port<GenericTransaction,GenericRouterAccess,GenericPhase> > GenericRouterPort;
//---------------------------------------------------------------------------
/**
* The default slave and router target port.
*/
//---------------------------------------------------------------------------
typedef GenericTargetAPI<target_port<GenericTransaction,GenericTargetAccess,GenericPhase> > GenericTargetPort;
//---------------------------------------------------------------------------
/**
* Low level router multi-ports.
*/
//---------------------------------------------------------------------------
typedef target_multi_port<GenericTransaction,GenericTargetAccess,GenericPhase> GenericRouterTargetPort;
typedef initiator_multi_port<GenericTransaction,GenericRouterAccess,GenericPhase> GenericRouterInitiatorPort;
} // end of namespace tlm
#endif
See more files for this project here