#ifndef TLM_ANNOTATED_FIFO_HEADER
#define TLM_ANNOTATED_FIFO_HEADER
#include "tlm_annotated/tlm_annotated_ifs/tlm_annotated_ifs.h"
#include "tlm_annotated/tlm_annotated_channels/tlm_peq.h"
using analysis::analysis_port
;
using analysis::analysis_if
;
using tlm_core::tlm_fifo
;
class tlm_internal_annotated_fifo
:
public virtual analysis_if
<T
> ,
public virtual analysis_if
< tlm_tag
< T
> * > {
typedef tlm_tag
<T
> *my_tag_ptr
;
tlm_internal_annotated_fifo( const char *nm
, int size
) :
tlm_fifo
<T
>( nm
, size
) {}
void write( const T
&t
) {
assert( nb_can_put( (my_tag_ptr
)0 ) );
void write( const my_tag_ptr
& ) {
read_event( (my_tag_ptr
)0 ).notify( SC_ZERO_TIME
);
// From the put point of view, delayed puts are immediate. The transaction T is
// considered to be in the fifo from the time at which nb_put( T , t ) was
// However, from the get point of view, the effect of the delayed put is not
// seen until t has expired. We cannot see the new data on the get side until
// The same rules apply to a delayed get : a get( T , t ) gets T immediately,
// but the put side does not see the extra space in the fifo until time t.
// In summary : put->put and get->get is immediate, but put->get and get->put
// Although the precise effects of put and get may vary from channel to channel
// these observability rules are part of the definition of the annotated
class tlm_annotated_fifo
:
public virtual tlm_annotated_put_if
< T
> ,
public virtual tlm_annotated_get_peek_if
< T
> {
tlm_annotated_fifo( sc_module_name nm
, int size
= 1 ) :
m_fifo("internal_fifo" , size
) ,
tlm_annotated_fifo( int size
= 1 ) :
sc_module( sc_gen_unique_name("annotated_fifo") ) ,
m_fifo("internal_fifo" , size
) ,
// non annotated nb_can_* methods
bool nb_can_put( tlm_tag
<T
> *t
= 0 ) const {
return m_fifo
.nb_can_put( m_put_peq
.size() + m_get_peq
.size() + 1 );
bool nb_can_get( tlm_tag
<T
> *t
= 0 ) const {
return m_fifo
.nb_can_get();
bool nb_can_peek( tlm_tag
<T
> *t
= 0 ) const {
return m_fifo
.nb_can_peek();
// annotated nb_can_* methods
// these are virtual because we may want to add some additional time based
// restrictions re: what can can be put and popped when : for example, we
// might want to insist that we only ever post to the end of both peqs, to
// preserve the ordering of the transactions.
// nb_can_put is part of the annotated non blocking put interface
virtual bool nb_can_put( const sc_time
&time
, tlm_tag
<T
> *t
= 0 ) const {
virtual bool nb_can_get( const sc_time
&time
, tlm_tag
<T
> *t
= 0 ) const {
const sc_event
&ok_to_put( tlm_tag
<T
> *t
= 0 ) const {
return m_fifo
.ok_to_put();
const sc_event
&ok_to_get( tlm_tag
<T
> *t
= 0 ) const {
return m_fifo
.ok_to_get();
const sc_event
&ok_to_peek( tlm_tag
<T
> *t
= 0 ) const {
return m_fifo
.ok_to_peek();
// non annotated nonblocking put, get + peek
bool nb_put( const T
&t
) {
assert( m_fifo
.nb_can_put() );
assert( m_fifo
.nb_can_get() );
bool nb_peek( T
&t
) const {
return m_fifo
.nb_peek( t
);
// annotated nonblocking methods
bool nb_put( const T
&transaction
, const sc_time
&time
) {
if( !nb_can_put( time
) ) {
m_put_peq
.write( transaction
, time
);
virtual bool nb_get( T
&transaction
, const sc_time
&time
) {
if( !m_fifo
.nb_get_no_notify( transaction
) ) {
m_get_peq
.write( t
, time
);
// blocking put, get and peek
T
get( tlm_tag
<T
> *t
= 0 ) {
while( !nb_get( trans
) ) {
T
peek( tlm_tag
<T
> *t
= 0 ) const {
int size() { return m_size
; }
protected: // to allow for overriding of annotated can_put and can_get
tlm_internal_annotated_fifo
<T
> m_fifo
;
tlm_peq
< tlm_tag
<T
> *> m_get_peq
;