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