1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20#ifndef __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ 21#define __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ 22 23// 24// This implements put, get and peek 25// 26// It also implements 0 and infinite size fifos - but the size 27// zero fifos aren't rendezvous like zero length fifos, they simply are both 28// full and empty at the same time. 29// 30// The size can be dynamically changed using the resize interface 31// 32// To get an infinite fifo use a -ve size in the constructor. 33// The absolute value of the size is taken as the starting size of the 34// actual physical buffer. 35// 36 37#include "../../interfaces/fifo_ifs.hh" 38#include "circular_buffer.hh" 39 40namespace tlm 41{ 42 43template <typename T> 44class tlm_fifo : public virtual tlm_fifo_get_if<T>, 45 public virtual tlm_fifo_put_if<T>, public sc_core::sc_prim_channel 46{ 47 public: 48 // Constructors. 49 explicit tlm_fifo(int size_=1) : 50 sc_core::sc_prim_channel(sc_core::sc_gen_unique_name("fifo")) 51 { 52 init(size_); 53 } 54 55 explicit tlm_fifo(const char *name_, int size_=1) : 56 sc_core::sc_prim_channel(name_) 57 { 58 init(size_); 59 } 60 61 // Destructor.. 62 virtual ~tlm_fifo() {} 63 64 // Tlm get interface. 65 T get(tlm_tag<T> * =nullptr); 66 67 bool nb_get(T &); 68 bool nb_can_get(tlm_tag<T> * =nullptr) const; 69 const sc_core::sc_event & 70 ok_to_get(tlm_tag<T> * =nullptr) const 71 { 72 return m_data_written_event; 73 } 74 75 // Tlm peek interface. 76 T peek(tlm_tag<T> * =nullptr) const; 77 78 bool nb_peek(T &) const; 79 bool nb_can_peek(tlm_tag<T> * =nullptr) const; 80 const sc_core::sc_event & 81 ok_to_peek(tlm_tag<T> * =nullptr) const 82 { 83 return m_data_written_event; 84 } 85 86 // Tlm put interface. 87 void put(const T &); 88 89 bool nb_put(const T &); 90 bool nb_can_put(tlm_tag<T> * =nullptr) const; 91 const sc_core::sc_event & 92 ok_to_put(tlm_tag<T> * =nullptr) const 93 { 94 return m_data_read_event; 95 } 96 97 // Resize if. 98 void nb_expand(unsigned int n=1); 99 void nb_unbound(unsigned int n=16); 100 101 bool nb_reduce(unsigned int n=1); 102 bool nb_bound(unsigned int n); 103 104 // Debug interface. 105 bool nb_peek(T &, int n) const; 106 bool nb_poke(const T &, int n=0); 107 108 int used() const { return m_num_readable - m_num_read; } 109 int size() const { return m_size; } 110 111 void 112 debug() const 113 { 114 if (is_empty()) 115 std::cout << "empty" << std::endl; 116 if (is_full()) 117 std::cout << "full" << std::endl; 118 119 std::cout << "size " << size() << " - " << used() << " used " 120 << std::endl; 121 std::cout << "readable " << m_num_readable << std::endl; 122 std::cout << "written/read " << m_num_written << "/" << m_num_read 123 << std::endl; 124 } 125 126 // Support functions. 127 static const char * const kind_string; 128 const char *kind() const { return kind_string; } 129 130 protected: 131 sc_core::sc_event & 132 read_event(tlm_tag<T> * =nullptr) 133 { 134 return m_data_read_event; 135 } 136 137 void update(); 138 void init(int); 139 140 circular_buffer<T> buffer; 141 142 int m_size; // logical size of fifo 143 144 int m_num_readable; // #samples readable 145 int m_num_read; // #samples read during this delta cycle 146 int m_num_written; // #samples written during this delta cycle 147 bool m_expand; // has an expand occurred during this delta cycle ? 148 // #samples read without notify during this delta cycle 149 int m_num_read_no_notify; 150 151 sc_core::sc_event m_data_read_event; 152 sc_core::sc_event m_data_written_event; 153 154 private: 155 // disabled 156 tlm_fifo(const tlm_fifo<T> &); 157 tlm_fifo &operator = (const tlm_fifo<T> &); 158 159 // 160 // use nb_can_get() and nb_can_put() rather than the following two 161 // private functions 162 // 163 164 bool is_empty() const { return used() == 0; } 165 166 bool 167 is_full() const 168 { 169 if (size() < 0) 170 return false; 171 else 172 return size() <= m_num_readable + m_num_written; 173 } 174}; 175 176template <typename T> 177const char *const tlm_fifo<T>::kind_string = "tlm_fifo"; 178 179/****************************************************************** 180// 181// init and update 182// 183******************************************************************/ 184 185template <typename T> 186inline void 187tlm_fifo<T>::init(int size_) 188{ 189 if (size_ > 0) { 190 buffer.resize( size_ ); 191 } else if (size_ < 0) { 192 buffer.resize(-size_); 193 } else { 194 buffer.resize(16); 195 } 196 197 m_size = size_; 198 m_num_readable = 0; 199 m_num_read = 0; 200 m_num_written = 0; 201 m_expand = false; 202 m_num_read_no_notify = false; 203} 204 205template <typename T> 206inline void 207tlm_fifo<T>::update() 208{ 209 if (m_num_read > m_num_read_no_notify || m_expand) { 210 m_data_read_event.notify(sc_core::SC_ZERO_TIME); 211 } 212 213 if (m_num_written > 0) { 214 m_data_written_event.notify(sc_core::SC_ZERO_TIME); 215 } 216 217 m_expand = false; 218 m_num_read = 0; 219 m_num_written = 0; 220 m_num_readable = buffer.used(); 221 m_num_read_no_notify = 0; 222} 223 224} // namespace tlm 225 226#include "fifo_peek.hh" 227#include "fifo_put_get.hh" 228#include "fifo_resize.hh" 229 230#endif /* __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ */ 231