sc_fifo.hh revision 13274
112950Sgabeblack@google.com/* 212950Sgabeblack@google.com * Copyright 2018 Google, Inc. 312950Sgabeblack@google.com * 412950Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 512950Sgabeblack@google.com * modification, are permitted provided that the following conditions are 612950Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 712950Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 812950Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 912950Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1012950Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1112950Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1212950Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1312950Sgabeblack@google.com * this software without specific prior written permission. 1412950Sgabeblack@google.com * 1512950Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612950Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712950Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812950Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912950Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012950Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112950Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212950Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312950Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412950Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512950Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612950Sgabeblack@google.com * 2712950Sgabeblack@google.com * Authors: Gabe Black 2812950Sgabeblack@google.com */ 2912950Sgabeblack@google.com 3012950Sgabeblack@google.com#ifndef __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__ 3112950Sgabeblack@google.com#define __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__ 3212988Sgabeblack@google.com 3313268Sgabeblack@google.com#include <list> 3412988Sgabeblack@google.com#include <string> 3512950Sgabeblack@google.com 3613127Sgabeblack@google.com#include "../core/sc_module.hh" // for sc_gen_unique_name 3712950Sgabeblack@google.com#include "../core/sc_prim.hh" 3812953Sgabeblack@google.com#include "../utils/sc_report_handler.hh" 3913161Sgabeblack@google.com#include "sc_fifo_in_if.hh" 4012950Sgabeblack@google.com#include "sc_fifo_out_if.hh" 4112950Sgabeblack@google.com 4212950Sgabeblack@google.comnamespace sc_core 4312950Sgabeblack@google.com{ 4412950Sgabeblack@google.com 4512950Sgabeblack@google.comclass sc_port_base; 4612950Sgabeblack@google.comclass sc_event; 4712950Sgabeblack@google.com 4812950Sgabeblack@google.comtemplate <class T> 4912950Sgabeblack@google.comclass sc_fifo : public sc_fifo_in_if<T>, 5012950Sgabeblack@google.com public sc_fifo_out_if<T>, 5112950Sgabeblack@google.com public sc_prim_channel 5212950Sgabeblack@google.com{ 5312950Sgabeblack@google.com public: 5412950Sgabeblack@google.com explicit sc_fifo(int size=16) : 5512950Sgabeblack@google.com sc_fifo_in_if<T>(), sc_fifo_out_if<T>(), 5612950Sgabeblack@google.com sc_prim_channel(sc_gen_unique_name("fifo")), 5712950Sgabeblack@google.com _size(size), _readsHappened(false), _reader(NULL), _writer(NULL) 5812950Sgabeblack@google.com {} 5912950Sgabeblack@google.com explicit sc_fifo(const char *name, int size=16) : 6012950Sgabeblack@google.com sc_fifo_in_if<T>(), sc_fifo_out_if<T>(), 6112950Sgabeblack@google.com sc_prim_channel(name), _size(size), _readsHappened(false), 6212950Sgabeblack@google.com _reader(NULL), _writer(NULL) 6312950Sgabeblack@google.com {} 6412950Sgabeblack@google.com virtual ~sc_fifo() {} 6512950Sgabeblack@google.com 6612950Sgabeblack@google.com virtual void 6712950Sgabeblack@google.com register_port(sc_port_base &port, const char *iface_type_name) 6812950Sgabeblack@google.com { 6912950Sgabeblack@google.com std::string tn(iface_type_name); 7012950Sgabeblack@google.com if (tn == typeid(sc_fifo_in_if<T>).name() || 7112950Sgabeblack@google.com tn == typeid(sc_fifo_blocking_in_if<T>).name()) { 7212950Sgabeblack@google.com if (_reader) { 7313127Sgabeblack@google.com SC_REPORT_ERROR( 7413127Sgabeblack@google.com "(E104) sc_fifo<T> cannot have more than one reader", 7513127Sgabeblack@google.com ""); 7613127Sgabeblack@google.com } 7713127Sgabeblack@google.com _reader = &port; 7813127Sgabeblack@google.com } else if (tn == typeid(sc_fifo_out_if<T>).name() || 7913127Sgabeblack@google.com tn == typeid(sc_fifo_blocking_out_if<T>).name()) { 8013127Sgabeblack@google.com if (_writer) { 8113127Sgabeblack@google.com SC_REPORT_ERROR( 8213127Sgabeblack@google.com "(E105) sc_fifo<T> cannot have more than one writer", 8313127Sgabeblack@google.com ""); 8413127Sgabeblack@google.com } 8512950Sgabeblack@google.com _writer = &port; 8612950Sgabeblack@google.com } else { 8713161Sgabeblack@google.com SC_REPORT_ERROR("(E107) bind interface to port failed", 8812950Sgabeblack@google.com "sc_fifo<T> port not recognized"); 8912955Sgabeblack@google.com } 9013085Sgabeblack@google.com } 9112950Sgabeblack@google.com 9212950Sgabeblack@google.com virtual void 9313161Sgabeblack@google.com read(T &t) 9412950Sgabeblack@google.com { 9513268Sgabeblack@google.com while (num_available() == 0) 9612950Sgabeblack@google.com sc_core::wait(_dataWriteEvent); 9712950Sgabeblack@google.com _readsHappened = true; 9812950Sgabeblack@google.com t = _entries.front(); 9912950Sgabeblack@google.com _entries.pop_front(); 10012950Sgabeblack@google.com request_update(); 10112950Sgabeblack@google.com } 10212950Sgabeblack@google.com virtual T 10313179Sgabeblack@google.com read() 10413179Sgabeblack@google.com { 10513127Sgabeblack@google.com T t; 10613127Sgabeblack@google.com read(t); 10713126Sgabeblack@google.com return t; 10813127Sgabeblack@google.com } 10912955Sgabeblack@google.com virtual bool 11012950Sgabeblack@google.com nb_read(T &t) 11112955Sgabeblack@google.com { 11212950Sgabeblack@google.com if (num_available()) { 11312950Sgabeblack@google.com read(t); 11413179Sgabeblack@google.com return true; 11512950Sgabeblack@google.com } else { 11613179Sgabeblack@google.com return false; 11712952Sgabeblack@google.com } 11812950Sgabeblack@google.com } 11913179Sgabeblack@google.com operator T() { return read(); } 12013179Sgabeblack@google.com 12113179Sgabeblack@google.com virtual void 12213179Sgabeblack@google.com write(const T &t) 12313179Sgabeblack@google.com { 12413179Sgabeblack@google.com while (num_free() == 0) 12513179Sgabeblack@google.com sc_core::wait(_dataReadEvent); 12613179Sgabeblack@google.com _pending.emplace_back(t); 12712950Sgabeblack@google.com request_update(); 12812950Sgabeblack@google.com } 12912955Sgabeblack@google.com virtual bool 13012955Sgabeblack@google.com nb_write(const T &t) 13112950Sgabeblack@google.com { 13212950Sgabeblack@google.com if (num_free()) { 13312950Sgabeblack@google.com write(t); 13412950Sgabeblack@google.com return true; 13512950Sgabeblack@google.com } else { 13612950Sgabeblack@google.com return false; 13712950Sgabeblack@google.com } 13812950Sgabeblack@google.com } 13912950Sgabeblack@google.com sc_fifo<T> & 14012950Sgabeblack@google.com operator = (const T &t) 14112984Sgabeblack@google.com { 14212984Sgabeblack@google.com write(t); 14312984Sgabeblack@google.com return *this; 14412984Sgabeblack@google.com } 14512984Sgabeblack@google.com 14612984Sgabeblack@google.com virtual const sc_event & 14712950Sgabeblack@google.com data_written_event() const 14813295Sgabeblack@google.com { 14913295Sgabeblack@google.com return _dataWriteEvent; 15013295Sgabeblack@google.com } 15112950Sgabeblack@google.com virtual const sc_event & 15212950Sgabeblack@google.com data_read_event() const 15312950Sgabeblack@google.com { 15412950Sgabeblack@google.com return _dataReadEvent; 15512950Sgabeblack@google.com } 15612950Sgabeblack@google.com 15712950Sgabeblack@google.com virtual int num_available() const { return _entries.size(); } 15812950Sgabeblack@google.com virtual int 15912950Sgabeblack@google.com num_free() const 16012950Sgabeblack@google.com { 16112950Sgabeblack@google.com return _size - _entries.size() - _pending.size(); 16212950Sgabeblack@google.com } 16312950Sgabeblack@google.com 16412950Sgabeblack@google.com virtual void 16512950Sgabeblack@google.com print(std::ostream &os=std::cout) const 16612950Sgabeblack@google.com { 16712950Sgabeblack@google.com for (typename ::std::list<T>::iterator pos = _pending.begin(); 16812950Sgabeblack@google.com pos != _pending.end(); pos++) { 16912950Sgabeblack@google.com os << *pos << ::std::endl; 17012950Sgabeblack@google.com } 17112950Sgabeblack@google.com for (typename ::std::list<T>::iterator pos = _entries.begin(); 17212950Sgabeblack@google.com pos != _entries.end(); pos++) { 17312950Sgabeblack@google.com os << *pos << ::std::endl; 17412950Sgabeblack@google.com } 17512950Sgabeblack@google.com } 17612950Sgabeblack@google.com virtual void 17712950Sgabeblack@google.com dump(std::ostream &os=std::cout) const 17812950Sgabeblack@google.com { 17912950Sgabeblack@google.com os << "name = " << name() << std::endl; 18012955Sgabeblack@google.com int idx = 0; 18112950Sgabeblack@google.com for (typename ::std::list<T>::iterator pos = _pending.begin(); 18212950Sgabeblack@google.com pos != _pending.end(); pos++) { 18312950Sgabeblack@google.com os << "value[" << idx++ << "] = " << *pos << ::std::endl; 18412950Sgabeblack@google.com } 18512950Sgabeblack@google.com for (typename ::std::list<T>::iterator pos = _entries.begin(); 18612950Sgabeblack@google.com pos != _entries.end(); pos++) { 18712950Sgabeblack@google.com os << "value[" << idx++ << "] = " << *pos << ::std::endl; 18812950Sgabeblack@google.com } 18912950Sgabeblack@google.com } 19012950Sgabeblack@google.com virtual const char *kind() const { return "sc_fifo"; } 19112950Sgabeblack@google.com 19212950Sgabeblack@google.com protected: 19312950Sgabeblack@google.com virtual void 19412950Sgabeblack@google.com update() 19512950Sgabeblack@google.com { 19612950Sgabeblack@google.com if (!_pending.empty()) { 19712950Sgabeblack@google.com _dataWriteEvent.notify(SC_ZERO_TIME); 19812950Sgabeblack@google.com _entries.insert(_entries.end(), _pending.begin(), _pending.end()); 19912950Sgabeblack@google.com _pending.clear(); 20012950Sgabeblack@google.com } 20112950Sgabeblack@google.com if (_readsHappened) { 20212950Sgabeblack@google.com _readsHappened = false; 20312950Sgabeblack@google.com _dataReadEvent.notify(SC_ZERO_TIME); 20412950Sgabeblack@google.com } 20512950Sgabeblack@google.com } 20612950Sgabeblack@google.com 20712950Sgabeblack@google.com private: 20812950Sgabeblack@google.com // Disabled 20912950Sgabeblack@google.com sc_fifo(const sc_fifo<T> &) : 21012950Sgabeblack@google.com sc_fifo_in_if<T>(), sc_fifo_in_if<T>(), sc_prim_channel() 21112950Sgabeblack@google.com {} 21212950Sgabeblack@google.com sc_fifo &operator = (const sc_fifo<T> &) { return *this; } 21312950Sgabeblack@google.com 21412950Sgabeblack@google.com sc_event _dataReadEvent; 21512950Sgabeblack@google.com sc_event _dataWriteEvent; 21612950Sgabeblack@google.com 21712950Sgabeblack@google.com sc_port_base *_reader; 21812950Sgabeblack@google.com sc_port_base *_writer; 21912950Sgabeblack@google.com 22012950Sgabeblack@google.com int _size; 22112950Sgabeblack@google.com mutable std::list<T> _entries; 22212950Sgabeblack@google.com mutable std::list<T> _pending; 22312950Sgabeblack@google.com bool _readsHappened; 22412950Sgabeblack@google.com}; 22512950Sgabeblack@google.com 22612950Sgabeblack@google.comtemplate <class T> 22712950Sgabeblack@google.cominline std::ostream & 22812950Sgabeblack@google.comoperator << (std::ostream &os, const sc_fifo<T> &f) 22912950Sgabeblack@google.com{ 23012950Sgabeblack@google.com f.print(os); 23112950Sgabeblack@google.com return os; 23212950Sgabeblack@google.com} 23312950Sgabeblack@google.com 23412950Sgabeblack@google.com} // namespace sc_core 23512950Sgabeblack@google.com 23612950Sgabeblack@google.com#endif //__SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__ 23712950Sgabeblack@google.com