113521Sgabeblack@google.com/***************************************************************************** 213521Sgabeblack@google.com 313521Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 413521Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 513521Sgabeblack@google.com with this work for additional information regarding copyright ownership. 613521Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 713521Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 813521Sgabeblack@google.com License. You may obtain a copy of the License at 913521Sgabeblack@google.com 1013521Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1113521Sgabeblack@google.com 1213521Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1313521Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1413521Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1513521Sgabeblack@google.com implied. See the License for the specific language governing 1613521Sgabeblack@google.com permissions and limitations under the License. 1713521Sgabeblack@google.com 1813521Sgabeblack@google.com *****************************************************************************/ 1913521Sgabeblack@google.com 2013521Sgabeblack@google.com#ifndef __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ 2113521Sgabeblack@google.com#define __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ 2213521Sgabeblack@google.com 2313521Sgabeblack@google.com// 2413521Sgabeblack@google.com// This implements put, get and peek 2513521Sgabeblack@google.com// 2613521Sgabeblack@google.com// It also implements 0 and infinite size fifos - but the size 2713521Sgabeblack@google.com// zero fifos aren't rendezvous like zero length fifos, they simply are both 2813521Sgabeblack@google.com// full and empty at the same time. 2913521Sgabeblack@google.com// 3013521Sgabeblack@google.com// The size can be dynamically changed using the resize interface 3113521Sgabeblack@google.com// 3213521Sgabeblack@google.com// To get an infinite fifo use a -ve size in the constructor. 3313521Sgabeblack@google.com// The absolute value of the size is taken as the starting size of the 3413521Sgabeblack@google.com// actual physical buffer. 3513521Sgabeblack@google.com// 3613521Sgabeblack@google.com 3713586Sgabeblack@google.com#include "../../interfaces/fifo_ifs.hh" 3813586Sgabeblack@google.com#include "circular_buffer.hh" 3913521Sgabeblack@google.com 4013521Sgabeblack@google.comnamespace tlm 4113521Sgabeblack@google.com{ 4213521Sgabeblack@google.com 4313521Sgabeblack@google.comtemplate <typename T> 4413521Sgabeblack@google.comclass tlm_fifo : public virtual tlm_fifo_get_if<T>, 4513521Sgabeblack@google.com public virtual tlm_fifo_put_if<T>, public sc_core::sc_prim_channel 4613521Sgabeblack@google.com{ 4713521Sgabeblack@google.com public: 4813521Sgabeblack@google.com // Constructors. 4913521Sgabeblack@google.com explicit tlm_fifo(int size_=1) : 5013521Sgabeblack@google.com sc_core::sc_prim_channel(sc_core::sc_gen_unique_name("fifo")) 5113521Sgabeblack@google.com { 5213521Sgabeblack@google.com init(size_); 5313521Sgabeblack@google.com } 5413521Sgabeblack@google.com 5513521Sgabeblack@google.com explicit tlm_fifo(const char *name_, int size_=1) : 5613521Sgabeblack@google.com sc_core::sc_prim_channel(name_) 5713521Sgabeblack@google.com { 5813521Sgabeblack@google.com init(size_); 5913521Sgabeblack@google.com } 6013521Sgabeblack@google.com 6113521Sgabeblack@google.com // Destructor.. 6213521Sgabeblack@google.com virtual ~tlm_fifo() {} 6313521Sgabeblack@google.com 6413521Sgabeblack@google.com // Tlm get interface. 6513521Sgabeblack@google.com T get(tlm_tag<T> * =nullptr); 6613521Sgabeblack@google.com 6713521Sgabeblack@google.com bool nb_get(T &); 6813521Sgabeblack@google.com bool nb_can_get(tlm_tag<T> * =nullptr) const; 6913521Sgabeblack@google.com const sc_core::sc_event & 7013521Sgabeblack@google.com ok_to_get(tlm_tag<T> * =nullptr) const 7113521Sgabeblack@google.com { 7213521Sgabeblack@google.com return m_data_written_event; 7313521Sgabeblack@google.com } 7413521Sgabeblack@google.com 7513521Sgabeblack@google.com // Tlm peek interface. 7613521Sgabeblack@google.com T peek(tlm_tag<T> * =nullptr) const; 7713521Sgabeblack@google.com 7813521Sgabeblack@google.com bool nb_peek(T &) const; 7913521Sgabeblack@google.com bool nb_can_peek(tlm_tag<T> * =nullptr) const; 8013521Sgabeblack@google.com const sc_core::sc_event & 8113521Sgabeblack@google.com ok_to_peek(tlm_tag<T> * =nullptr) const 8213521Sgabeblack@google.com { 8313521Sgabeblack@google.com return m_data_written_event; 8413521Sgabeblack@google.com } 8513521Sgabeblack@google.com 8613521Sgabeblack@google.com // Tlm put interface. 8713521Sgabeblack@google.com void put(const T &); 8813521Sgabeblack@google.com 8913521Sgabeblack@google.com bool nb_put(const T &); 9013521Sgabeblack@google.com bool nb_can_put(tlm_tag<T> * =nullptr) const; 9113521Sgabeblack@google.com const sc_core::sc_event & 9213521Sgabeblack@google.com ok_to_put(tlm_tag<T> * =nullptr) const 9313521Sgabeblack@google.com { 9413521Sgabeblack@google.com return m_data_read_event; 9513521Sgabeblack@google.com } 9613521Sgabeblack@google.com 9713521Sgabeblack@google.com // Resize if. 9813521Sgabeblack@google.com void nb_expand(unsigned int n=1); 9913521Sgabeblack@google.com void nb_unbound(unsigned int n=16); 10013521Sgabeblack@google.com 10113521Sgabeblack@google.com bool nb_reduce(unsigned int n=1); 10213521Sgabeblack@google.com bool nb_bound(unsigned int n); 10313521Sgabeblack@google.com 10413521Sgabeblack@google.com // Debug interface. 10513521Sgabeblack@google.com bool nb_peek(T &, int n) const; 10613521Sgabeblack@google.com bool nb_poke(const T &, int n=0); 10713521Sgabeblack@google.com 10813521Sgabeblack@google.com int used() const { return m_num_readable - m_num_read; } 10913521Sgabeblack@google.com int size() const { return m_size; } 11013521Sgabeblack@google.com 11113521Sgabeblack@google.com void 11213521Sgabeblack@google.com debug() const 11313521Sgabeblack@google.com { 11413521Sgabeblack@google.com if (is_empty()) 11513521Sgabeblack@google.com std::cout << "empty" << std::endl; 11613521Sgabeblack@google.com if (is_full()) 11713521Sgabeblack@google.com std::cout << "full" << std::endl; 11813521Sgabeblack@google.com 11913521Sgabeblack@google.com std::cout << "size " << size() << " - " << used() << " used " 12013521Sgabeblack@google.com << std::endl; 12113521Sgabeblack@google.com std::cout << "readable " << m_num_readable << std::endl; 12213521Sgabeblack@google.com std::cout << "written/read " << m_num_written << "/" << m_num_read 12313521Sgabeblack@google.com << std::endl; 12413521Sgabeblack@google.com } 12513521Sgabeblack@google.com 12613521Sgabeblack@google.com // Support functions. 12713521Sgabeblack@google.com static const char * const kind_string; 12813521Sgabeblack@google.com const char *kind() const { return kind_string; } 12913521Sgabeblack@google.com 13013521Sgabeblack@google.com protected: 13113521Sgabeblack@google.com sc_core::sc_event & 13213521Sgabeblack@google.com read_event(tlm_tag<T> * =nullptr) 13313521Sgabeblack@google.com { 13413521Sgabeblack@google.com return m_data_read_event; 13513521Sgabeblack@google.com } 13613521Sgabeblack@google.com 13713521Sgabeblack@google.com void update(); 13813521Sgabeblack@google.com void init(int); 13913521Sgabeblack@google.com 14013521Sgabeblack@google.com circular_buffer<T> buffer; 14113521Sgabeblack@google.com 14213521Sgabeblack@google.com int m_size; // logical size of fifo 14313521Sgabeblack@google.com 14413521Sgabeblack@google.com int m_num_readable; // #samples readable 14513521Sgabeblack@google.com int m_num_read; // #samples read during this delta cycle 14613521Sgabeblack@google.com int m_num_written; // #samples written during this delta cycle 14713521Sgabeblack@google.com bool m_expand; // has an expand occurred during this delta cycle ? 14813521Sgabeblack@google.com // #samples read without notify during this delta cycle 14913521Sgabeblack@google.com int m_num_read_no_notify; 15013521Sgabeblack@google.com 15113521Sgabeblack@google.com sc_core::sc_event m_data_read_event; 15213521Sgabeblack@google.com sc_core::sc_event m_data_written_event; 15313521Sgabeblack@google.com 15413521Sgabeblack@google.com private: 15513521Sgabeblack@google.com // disabled 15613521Sgabeblack@google.com tlm_fifo(const tlm_fifo<T> &); 15713521Sgabeblack@google.com tlm_fifo &operator = (const tlm_fifo<T> &); 15813521Sgabeblack@google.com 15913521Sgabeblack@google.com // 16013521Sgabeblack@google.com // use nb_can_get() and nb_can_put() rather than the following two 16113521Sgabeblack@google.com // private functions 16213521Sgabeblack@google.com // 16313521Sgabeblack@google.com 16413521Sgabeblack@google.com bool is_empty() const { return used() == 0; } 16513521Sgabeblack@google.com 16613521Sgabeblack@google.com bool 16713521Sgabeblack@google.com is_full() const 16813521Sgabeblack@google.com { 16913521Sgabeblack@google.com if (size() < 0) 17013521Sgabeblack@google.com return false; 17113521Sgabeblack@google.com else 17213521Sgabeblack@google.com return size() <= m_num_readable + m_num_written; 17313521Sgabeblack@google.com } 17413521Sgabeblack@google.com}; 17513521Sgabeblack@google.com 17613521Sgabeblack@google.comtemplate <typename T> 17713521Sgabeblack@google.comconst char *const tlm_fifo<T>::kind_string = "tlm_fifo"; 17813521Sgabeblack@google.com 17913521Sgabeblack@google.com/****************************************************************** 18013521Sgabeblack@google.com// 18113521Sgabeblack@google.com// init and update 18213521Sgabeblack@google.com// 18313521Sgabeblack@google.com******************************************************************/ 18413521Sgabeblack@google.com 18513521Sgabeblack@google.comtemplate <typename T> 18613521Sgabeblack@google.cominline void 18713521Sgabeblack@google.comtlm_fifo<T>::init(int size_) 18813521Sgabeblack@google.com{ 18913521Sgabeblack@google.com if (size_ > 0) { 19013521Sgabeblack@google.com buffer.resize( size_ ); 19113521Sgabeblack@google.com } else if (size_ < 0) { 19213521Sgabeblack@google.com buffer.resize(-size_); 19313521Sgabeblack@google.com } else { 19413521Sgabeblack@google.com buffer.resize(16); 19513521Sgabeblack@google.com } 19613521Sgabeblack@google.com 19713521Sgabeblack@google.com m_size = size_; 19813521Sgabeblack@google.com m_num_readable = 0; 19913521Sgabeblack@google.com m_num_read = 0; 20013521Sgabeblack@google.com m_num_written = 0; 20113521Sgabeblack@google.com m_expand = false; 20213521Sgabeblack@google.com m_num_read_no_notify = false; 20313521Sgabeblack@google.com} 20413521Sgabeblack@google.com 20513521Sgabeblack@google.comtemplate <typename T> 20613521Sgabeblack@google.cominline void 20713521Sgabeblack@google.comtlm_fifo<T>::update() 20813521Sgabeblack@google.com{ 20913521Sgabeblack@google.com if (m_num_read > m_num_read_no_notify || m_expand) { 21013521Sgabeblack@google.com m_data_read_event.notify(sc_core::SC_ZERO_TIME); 21113521Sgabeblack@google.com } 21213521Sgabeblack@google.com 21313521Sgabeblack@google.com if (m_num_written > 0) { 21413521Sgabeblack@google.com m_data_written_event.notify(sc_core::SC_ZERO_TIME); 21513521Sgabeblack@google.com } 21613521Sgabeblack@google.com 21713521Sgabeblack@google.com m_expand = false; 21813521Sgabeblack@google.com m_num_read = 0; 21913521Sgabeblack@google.com m_num_written = 0; 22013521Sgabeblack@google.com m_num_readable = buffer.used(); 22113521Sgabeblack@google.com m_num_read_no_notify = 0; 22213521Sgabeblack@google.com} 22313521Sgabeblack@google.com 22413521Sgabeblack@google.com} // namespace tlm 22513521Sgabeblack@google.com 22613586Sgabeblack@google.com#include "fifo_peek.hh" 22713586Sgabeblack@google.com#include "fifo_put_get.hh" 22813586Sgabeblack@google.com#include "fifo_resize.hh" 22913521Sgabeblack@google.com 23013521Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ */ 231