sc_fifo.hh revision 13324:c8b709468e61
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 "messages.hh" 40#include "sc_fifo_in_if.hh" 41#include "sc_fifo_out_if.hh" 42 43namespace sc_core 44{ 45 46class sc_port_base; 47class sc_event; 48 49template <class T> 50class sc_fifo : public sc_fifo_in_if<T>, 51 public sc_fifo_out_if<T>, 52 public sc_prim_channel 53{ 54 public: 55 explicit sc_fifo(int size=16) : 56 sc_fifo_in_if<T>(), sc_fifo_out_if<T>(), 57 sc_prim_channel(sc_gen_unique_name("fifo")), 58 _size(size), _readsHappened(false), _reader(NULL), _writer(NULL) 59 {} 60 explicit sc_fifo(const char *name, int size=16) : 61 sc_fifo_in_if<T>(), sc_fifo_out_if<T>(), 62 sc_prim_channel(name), _size(size), _readsHappened(false), 63 _reader(NULL), _writer(NULL) 64 {} 65 virtual ~sc_fifo() {} 66 67 virtual void 68 register_port(sc_port_base &port, const char *iface_type_name) 69 { 70 std::string tn(iface_type_name); 71 if (tn == typeid(sc_fifo_in_if<T>).name() || 72 tn == typeid(sc_fifo_blocking_in_if<T>).name()) { 73 if (_reader) 74 SC_REPORT_ERROR(SC_ID_MORE_THAN_ONE_FIFO_READER_, ""); 75 _reader = &port; 76 } else if (tn == typeid(sc_fifo_out_if<T>).name() || 77 tn == typeid(sc_fifo_blocking_out_if<T>).name()) { 78 if (_writer) 79 SC_REPORT_ERROR(SC_ID_MORE_THAN_ONE_FIFO_WRITER_, ""); 80 _writer = &port; 81 } else { 82 SC_REPORT_ERROR(SC_ID_BIND_IF_TO_PORT_, 83 "sc_fifo<T> port not recognized"); 84 } 85 } 86 87 virtual void 88 read(T &t) 89 { 90 while (num_available() == 0) 91 sc_core::wait(_dataWriteEvent); 92 _readsHappened = true; 93 t = _entries.front(); 94 _entries.pop_front(); 95 request_update(); 96 } 97 virtual T 98 read() 99 { 100 T t; 101 read(t); 102 return t; 103 } 104 virtual bool 105 nb_read(T &t) 106 { 107 if (num_available()) { 108 read(t); 109 return true; 110 } else { 111 return false; 112 } 113 } 114 operator T() { return read(); } 115 116 virtual void 117 write(const T &t) 118 { 119 while (num_free() == 0) 120 sc_core::wait(_dataReadEvent); 121 _pending.emplace_back(t); 122 request_update(); 123 } 124 virtual bool 125 nb_write(const T &t) 126 { 127 if (num_free()) { 128 write(t); 129 return true; 130 } else { 131 return false; 132 } 133 } 134 sc_fifo<T> & 135 operator = (const T &t) 136 { 137 write(t); 138 return *this; 139 } 140 141 virtual const sc_event & 142 data_written_event() const 143 { 144 return _dataWriteEvent; 145 } 146 virtual const sc_event & 147 data_read_event() const 148 { 149 return _dataReadEvent; 150 } 151 152 virtual int num_available() const { return _entries.size(); } 153 virtual int 154 num_free() const 155 { 156 return _size - _entries.size() - _pending.size(); 157 } 158 159 virtual void 160 print(std::ostream &os=std::cout) const 161 { 162 for (typename ::std::list<T>::iterator pos = _pending.begin(); 163 pos != _pending.end(); pos++) { 164 os << *pos << ::std::endl; 165 } 166 for (typename ::std::list<T>::iterator pos = _entries.begin(); 167 pos != _entries.end(); pos++) { 168 os << *pos << ::std::endl; 169 } 170 } 171 virtual void 172 dump(std::ostream &os=std::cout) const 173 { 174 os << "name = " << name() << std::endl; 175 int idx = 0; 176 for (typename ::std::list<T>::iterator pos = _pending.begin(); 177 pos != _pending.end(); pos++) { 178 os << "value[" << idx++ << "] = " << *pos << ::std::endl; 179 } 180 for (typename ::std::list<T>::iterator pos = _entries.begin(); 181 pos != _entries.end(); pos++) { 182 os << "value[" << idx++ << "] = " << *pos << ::std::endl; 183 } 184 } 185 virtual const char *kind() const { return "sc_fifo"; } 186 187 protected: 188 virtual void 189 update() 190 { 191 if (!_pending.empty()) { 192 _dataWriteEvent.notify(SC_ZERO_TIME); 193 _entries.insert(_entries.end(), _pending.begin(), _pending.end()); 194 _pending.clear(); 195 } 196 if (_readsHappened) { 197 _readsHappened = false; 198 _dataReadEvent.notify(SC_ZERO_TIME); 199 } 200 } 201 202 private: 203 // Disabled 204 sc_fifo(const sc_fifo<T> &) : 205 sc_fifo_in_if<T>(), sc_fifo_in_if<T>(), sc_prim_channel() 206 {} 207 sc_fifo &operator = (const sc_fifo<T> &) { return *this; } 208 209 sc_gem5::InternalScEvent _dataReadEvent; 210 sc_gem5::InternalScEvent _dataWriteEvent; 211 212 sc_port_base *_reader; 213 sc_port_base *_writer; 214 215 int _size; 216 mutable std::list<T> _entries; 217 mutable std::list<T> _pending; 218 bool _readsHappened; 219}; 220 221template <class T> 222inline std::ostream & 223operator << (std::ostream &os, const sc_fifo<T> &f) 224{ 225 f.print(os); 226 return os; 227} 228 229} // namespace sc_core 230 231#endif //__SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__ 232