sc_fifo.hh revision 13274
1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#ifndef __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__ 31#define __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__ 32 33#include <list> 34#include <string> 35 36#include "../core/sc_module.hh" // for sc_gen_unique_name 37#include "../core/sc_prim.hh" 38#include "../utils/sc_report_handler.hh" 39#include "sc_fifo_in_if.hh" 40#include "sc_fifo_out_if.hh" 41 42namespace sc_core 43{ 44 45class sc_port_base; 46class sc_event; 47 48template <class T> 49class sc_fifo : public sc_fifo_in_if<T>, 50 public sc_fifo_out_if<T>, 51 public sc_prim_channel 52{ 53 public: 54 explicit sc_fifo(int size=16) : 55 sc_fifo_in_if<T>(), sc_fifo_out_if<T>(), 56 sc_prim_channel(sc_gen_unique_name("fifo")), 57 _size(size), _readsHappened(false), _reader(NULL), _writer(NULL) 58 {} 59 explicit sc_fifo(const char *name, int size=16) : 60 sc_fifo_in_if<T>(), sc_fifo_out_if<T>(), 61 sc_prim_channel(name), _size(size), _readsHappened(false), 62 _reader(NULL), _writer(NULL) 63 {} 64 virtual ~sc_fifo() {} 65 66 virtual void 67 register_port(sc_port_base &port, const char *iface_type_name) 68 { 69 std::string tn(iface_type_name); 70 if (tn == typeid(sc_fifo_in_if<T>).name() || 71 tn == typeid(sc_fifo_blocking_in_if<T>).name()) { 72 if (_reader) { 73 SC_REPORT_ERROR( 74 "(E104) sc_fifo<T> cannot have more than one reader", 75 ""); 76 } 77 _reader = &port; 78 } else if (tn == typeid(sc_fifo_out_if<T>).name() || 79 tn == typeid(sc_fifo_blocking_out_if<T>).name()) { 80 if (_writer) { 81 SC_REPORT_ERROR( 82 "(E105) sc_fifo<T> cannot have more than one writer", 83 ""); 84 } 85 _writer = &port; 86 } else { 87 SC_REPORT_ERROR("(E107) bind interface to port failed", 88 "sc_fifo<T> port not recognized"); 89 } 90 } 91 92 virtual void 93 read(T &t) 94 { 95 while (num_available() == 0) 96 sc_core::wait(_dataWriteEvent); 97 _readsHappened = true; 98 t = _entries.front(); 99 _entries.pop_front(); 100 request_update(); 101 } 102 virtual T 103 read() 104 { 105 T t; 106 read(t); 107 return t; 108 } 109 virtual bool 110 nb_read(T &t) 111 { 112 if (num_available()) { 113 read(t); 114 return true; 115 } else { 116 return false; 117 } 118 } 119 operator T() { return read(); } 120 121 virtual void 122 write(const T &t) 123 { 124 while (num_free() == 0) 125 sc_core::wait(_dataReadEvent); 126 _pending.emplace_back(t); 127 request_update(); 128 } 129 virtual bool 130 nb_write(const T &t) 131 { 132 if (num_free()) { 133 write(t); 134 return true; 135 } else { 136 return false; 137 } 138 } 139 sc_fifo<T> & 140 operator = (const T &t) 141 { 142 write(t); 143 return *this; 144 } 145 146 virtual const sc_event & 147 data_written_event() const 148 { 149 return _dataWriteEvent; 150 } 151 virtual const sc_event & 152 data_read_event() const 153 { 154 return _dataReadEvent; 155 } 156 157 virtual int num_available() const { return _entries.size(); } 158 virtual int 159 num_free() const 160 { 161 return _size - _entries.size() - _pending.size(); 162 } 163 164 virtual void 165 print(std::ostream &os=std::cout) const 166 { 167 for (typename ::std::list<T>::iterator pos = _pending.begin(); 168 pos != _pending.end(); pos++) { 169 os << *pos << ::std::endl; 170 } 171 for (typename ::std::list<T>::iterator pos = _entries.begin(); 172 pos != _entries.end(); pos++) { 173 os << *pos << ::std::endl; 174 } 175 } 176 virtual void 177 dump(std::ostream &os=std::cout) const 178 { 179 os << "name = " << name() << std::endl; 180 int idx = 0; 181 for (typename ::std::list<T>::iterator pos = _pending.begin(); 182 pos != _pending.end(); pos++) { 183 os << "value[" << idx++ << "] = " << *pos << ::std::endl; 184 } 185 for (typename ::std::list<T>::iterator pos = _entries.begin(); 186 pos != _entries.end(); pos++) { 187 os << "value[" << idx++ << "] = " << *pos << ::std::endl; 188 } 189 } 190 virtual const char *kind() const { return "sc_fifo"; } 191 192 protected: 193 virtual void 194 update() 195 { 196 if (!_pending.empty()) { 197 _dataWriteEvent.notify(SC_ZERO_TIME); 198 _entries.insert(_entries.end(), _pending.begin(), _pending.end()); 199 _pending.clear(); 200 } 201 if (_readsHappened) { 202 _readsHappened = false; 203 _dataReadEvent.notify(SC_ZERO_TIME); 204 } 205 } 206 207 private: 208 // Disabled 209 sc_fifo(const sc_fifo<T> &) : 210 sc_fifo_in_if<T>(), sc_fifo_in_if<T>(), sc_prim_channel() 211 {} 212 sc_fifo &operator = (const sc_fifo<T> &) { return *this; } 213 214 sc_event _dataReadEvent; 215 sc_event _dataWriteEvent; 216 217 sc_port_base *_reader; 218 sc_port_base *_writer; 219 220 int _size; 221 mutable std::list<T> _entries; 222 mutable std::list<T> _pending; 223 bool _readsHappened; 224}; 225 226template <class T> 227inline std::ostream & 228operator << (std::ostream &os, const sc_fifo<T> &f) 229{ 230 f.print(os); 231 return os; 232} 233 234} // namespace sc_core 235 236#endif //__SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__ 237