113521Sgabeblack@google.com/*****************************************************************************
213521Sgabeblack@google.com
313521Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413521Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513521Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613521Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713521Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813521Sgabeblack@google.com  License.  You may obtain a copy of the License at
913521Sgabeblack@google.com
1013521Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113521Sgabeblack@google.com
1213521Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313521Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413521Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513521Sgabeblack@google.com  implied.  See the License for the specific language governing
1613521Sgabeblack@google.com  permissions and limitations under the License.
1713521Sgabeblack@google.com
1813521Sgabeblack@google.com *****************************************************************************/
1913521Sgabeblack@google.com
2013521Sgabeblack@google.com#ifndef __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__
2113521Sgabeblack@google.com#define __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__
2213521Sgabeblack@google.com
2313521Sgabeblack@google.com//
2413521Sgabeblack@google.com// This implements put, get and peek
2513521Sgabeblack@google.com//
2613521Sgabeblack@google.com// It also implements 0 and infinite size fifos - but the size
2713521Sgabeblack@google.com// zero fifos aren't rendezvous like zero length fifos, they simply are both
2813521Sgabeblack@google.com// full and empty at the same time.
2913521Sgabeblack@google.com//
3013521Sgabeblack@google.com// The size can be dynamically changed using the resize interface
3113521Sgabeblack@google.com//
3213521Sgabeblack@google.com// To get an infinite fifo use a -ve size in the constructor.
3313521Sgabeblack@google.com// The absolute value of the size is taken as the starting size of the
3413521Sgabeblack@google.com// actual physical buffer.
3513521Sgabeblack@google.com//
3613521Sgabeblack@google.com
3713586Sgabeblack@google.com#include "../../interfaces/fifo_ifs.hh"
3813586Sgabeblack@google.com#include "circular_buffer.hh"
3913521Sgabeblack@google.com
4013521Sgabeblack@google.comnamespace tlm
4113521Sgabeblack@google.com{
4213521Sgabeblack@google.com
4313521Sgabeblack@google.comtemplate <typename T>
4413521Sgabeblack@google.comclass tlm_fifo : public virtual tlm_fifo_get_if<T>,
4513521Sgabeblack@google.com    public virtual tlm_fifo_put_if<T>, public sc_core::sc_prim_channel
4613521Sgabeblack@google.com{
4713521Sgabeblack@google.com  public:
4813521Sgabeblack@google.com    // Constructors.
4913521Sgabeblack@google.com    explicit tlm_fifo(int size_=1) :
5013521Sgabeblack@google.com        sc_core::sc_prim_channel(sc_core::sc_gen_unique_name("fifo"))
5113521Sgabeblack@google.com    {
5213521Sgabeblack@google.com        init(size_);
5313521Sgabeblack@google.com    }
5413521Sgabeblack@google.com
5513521Sgabeblack@google.com    explicit tlm_fifo(const char *name_, int size_=1) :
5613521Sgabeblack@google.com        sc_core::sc_prim_channel(name_)
5713521Sgabeblack@google.com    {
5813521Sgabeblack@google.com        init(size_);
5913521Sgabeblack@google.com    }
6013521Sgabeblack@google.com
6113521Sgabeblack@google.com    // Destructor..
6213521Sgabeblack@google.com    virtual ~tlm_fifo() {}
6313521Sgabeblack@google.com
6413521Sgabeblack@google.com    // Tlm get interface.
6513521Sgabeblack@google.com    T get(tlm_tag<T> * =nullptr);
6613521Sgabeblack@google.com
6713521Sgabeblack@google.com    bool nb_get(T &);
6813521Sgabeblack@google.com    bool nb_can_get(tlm_tag<T> * =nullptr) const;
6913521Sgabeblack@google.com    const sc_core::sc_event &
7013521Sgabeblack@google.com    ok_to_get(tlm_tag<T> * =nullptr) const
7113521Sgabeblack@google.com    {
7213521Sgabeblack@google.com        return m_data_written_event;
7313521Sgabeblack@google.com    }
7413521Sgabeblack@google.com
7513521Sgabeblack@google.com    // Tlm peek interface.
7613521Sgabeblack@google.com    T peek(tlm_tag<T> * =nullptr) const;
7713521Sgabeblack@google.com
7813521Sgabeblack@google.com    bool nb_peek(T &) const;
7913521Sgabeblack@google.com    bool nb_can_peek(tlm_tag<T> * =nullptr) const;
8013521Sgabeblack@google.com    const sc_core::sc_event &
8113521Sgabeblack@google.com    ok_to_peek(tlm_tag<T> * =nullptr) const
8213521Sgabeblack@google.com    {
8313521Sgabeblack@google.com        return m_data_written_event;
8413521Sgabeblack@google.com    }
8513521Sgabeblack@google.com
8613521Sgabeblack@google.com    // Tlm put interface.
8713521Sgabeblack@google.com    void put(const T &);
8813521Sgabeblack@google.com
8913521Sgabeblack@google.com    bool nb_put(const T &);
9013521Sgabeblack@google.com    bool nb_can_put(tlm_tag<T> * =nullptr) const;
9113521Sgabeblack@google.com    const sc_core::sc_event &
9213521Sgabeblack@google.com    ok_to_put(tlm_tag<T> * =nullptr) const
9313521Sgabeblack@google.com    {
9413521Sgabeblack@google.com        return m_data_read_event;
9513521Sgabeblack@google.com    }
9613521Sgabeblack@google.com
9713521Sgabeblack@google.com    // Resize if.
9813521Sgabeblack@google.com    void nb_expand(unsigned int n=1);
9913521Sgabeblack@google.com    void nb_unbound(unsigned int n=16);
10013521Sgabeblack@google.com
10113521Sgabeblack@google.com    bool nb_reduce(unsigned int n=1);
10213521Sgabeblack@google.com    bool nb_bound(unsigned int n);
10313521Sgabeblack@google.com
10413521Sgabeblack@google.com    // Debug interface.
10513521Sgabeblack@google.com    bool nb_peek(T &, int n) const;
10613521Sgabeblack@google.com    bool nb_poke(const T &, int n=0);
10713521Sgabeblack@google.com
10813521Sgabeblack@google.com    int used() const { return m_num_readable - m_num_read; }
10913521Sgabeblack@google.com    int size() const { return m_size; }
11013521Sgabeblack@google.com
11113521Sgabeblack@google.com    void
11213521Sgabeblack@google.com    debug() const
11313521Sgabeblack@google.com    {
11413521Sgabeblack@google.com        if (is_empty())
11513521Sgabeblack@google.com            std::cout << "empty" << std::endl;
11613521Sgabeblack@google.com        if (is_full())
11713521Sgabeblack@google.com            std::cout << "full" << std::endl;
11813521Sgabeblack@google.com
11913521Sgabeblack@google.com        std::cout << "size " << size() << " - " << used() << " used "
12013521Sgabeblack@google.com                  << std::endl;
12113521Sgabeblack@google.com        std::cout << "readable " << m_num_readable << std::endl;
12213521Sgabeblack@google.com        std::cout << "written/read " << m_num_written << "/" << m_num_read
12313521Sgabeblack@google.com                  << std::endl;
12413521Sgabeblack@google.com    }
12513521Sgabeblack@google.com
12613521Sgabeblack@google.com    // Support functions.
12713521Sgabeblack@google.com    static const char * const kind_string;
12813521Sgabeblack@google.com    const char *kind() const { return kind_string; }
12913521Sgabeblack@google.com
13013521Sgabeblack@google.com  protected:
13113521Sgabeblack@google.com    sc_core::sc_event &
13213521Sgabeblack@google.com    read_event(tlm_tag<T> * =nullptr)
13313521Sgabeblack@google.com    {
13413521Sgabeblack@google.com        return m_data_read_event;
13513521Sgabeblack@google.com    }
13613521Sgabeblack@google.com
13713521Sgabeblack@google.com    void update();
13813521Sgabeblack@google.com    void init(int);
13913521Sgabeblack@google.com
14013521Sgabeblack@google.com    circular_buffer<T> buffer;
14113521Sgabeblack@google.com
14213521Sgabeblack@google.com    int m_size; // logical size of fifo
14313521Sgabeblack@google.com
14413521Sgabeblack@google.com    int m_num_readable; // #samples readable
14513521Sgabeblack@google.com    int m_num_read; // #samples read during this delta cycle
14613521Sgabeblack@google.com    int m_num_written; // #samples written during this delta cycle
14713521Sgabeblack@google.com    bool m_expand; // has an expand occurred during this delta cycle ?
14813521Sgabeblack@google.com    // #samples read without notify during this delta cycle
14913521Sgabeblack@google.com    int m_num_read_no_notify;
15013521Sgabeblack@google.com
15113521Sgabeblack@google.com    sc_core::sc_event m_data_read_event;
15213521Sgabeblack@google.com    sc_core::sc_event m_data_written_event;
15313521Sgabeblack@google.com
15413521Sgabeblack@google.com  private:
15513521Sgabeblack@google.com    // disabled
15613521Sgabeblack@google.com    tlm_fifo(const tlm_fifo<T> &);
15713521Sgabeblack@google.com    tlm_fifo &operator = (const tlm_fifo<T> &);
15813521Sgabeblack@google.com
15913521Sgabeblack@google.com    //
16013521Sgabeblack@google.com    // use nb_can_get() and nb_can_put() rather than the following two
16113521Sgabeblack@google.com    // private functions
16213521Sgabeblack@google.com    //
16313521Sgabeblack@google.com
16413521Sgabeblack@google.com    bool is_empty() const { return used() == 0; }
16513521Sgabeblack@google.com
16613521Sgabeblack@google.com    bool
16713521Sgabeblack@google.com    is_full() const
16813521Sgabeblack@google.com    {
16913521Sgabeblack@google.com        if (size() < 0)
17013521Sgabeblack@google.com            return false;
17113521Sgabeblack@google.com        else
17213521Sgabeblack@google.com            return size() <= m_num_readable + m_num_written;
17313521Sgabeblack@google.com    }
17413521Sgabeblack@google.com};
17513521Sgabeblack@google.com
17613521Sgabeblack@google.comtemplate <typename T>
17713521Sgabeblack@google.comconst char *const tlm_fifo<T>::kind_string = "tlm_fifo";
17813521Sgabeblack@google.com
17913521Sgabeblack@google.com/******************************************************************
18013521Sgabeblack@google.com//
18113521Sgabeblack@google.com// init and update
18213521Sgabeblack@google.com//
18313521Sgabeblack@google.com******************************************************************/
18413521Sgabeblack@google.com
18513521Sgabeblack@google.comtemplate <typename T>
18613521Sgabeblack@google.cominline void
18713521Sgabeblack@google.comtlm_fifo<T>::init(int size_)
18813521Sgabeblack@google.com{
18913521Sgabeblack@google.com    if (size_ > 0) {
19013521Sgabeblack@google.com        buffer.resize( size_ );
19113521Sgabeblack@google.com    } else if (size_ < 0) {
19213521Sgabeblack@google.com        buffer.resize(-size_);
19313521Sgabeblack@google.com    } else {
19413521Sgabeblack@google.com        buffer.resize(16);
19513521Sgabeblack@google.com    }
19613521Sgabeblack@google.com
19713521Sgabeblack@google.com    m_size = size_;
19813521Sgabeblack@google.com    m_num_readable = 0;
19913521Sgabeblack@google.com    m_num_read = 0;
20013521Sgabeblack@google.com    m_num_written = 0;
20113521Sgabeblack@google.com    m_expand = false;
20213521Sgabeblack@google.com    m_num_read_no_notify = false;
20313521Sgabeblack@google.com}
20413521Sgabeblack@google.com
20513521Sgabeblack@google.comtemplate <typename T>
20613521Sgabeblack@google.cominline void
20713521Sgabeblack@google.comtlm_fifo<T>::update()
20813521Sgabeblack@google.com{
20913521Sgabeblack@google.com    if (m_num_read > m_num_read_no_notify || m_expand) {
21013521Sgabeblack@google.com        m_data_read_event.notify(sc_core::SC_ZERO_TIME);
21113521Sgabeblack@google.com    }
21213521Sgabeblack@google.com
21313521Sgabeblack@google.com    if (m_num_written > 0) {
21413521Sgabeblack@google.com        m_data_written_event.notify(sc_core::SC_ZERO_TIME);
21513521Sgabeblack@google.com    }
21613521Sgabeblack@google.com
21713521Sgabeblack@google.com    m_expand = false;
21813521Sgabeblack@google.com    m_num_read = 0;
21913521Sgabeblack@google.com    m_num_written = 0;
22013521Sgabeblack@google.com    m_num_readable = buffer.used();
22113521Sgabeblack@google.com    m_num_read_no_notify = 0;
22213521Sgabeblack@google.com}
22313521Sgabeblack@google.com
22413521Sgabeblack@google.com} // namespace tlm
22513521Sgabeblack@google.com
22613586Sgabeblack@google.com#include "fifo_peek.hh"
22713586Sgabeblack@google.com#include "fifo_put_get.hh"
22813586Sgabeblack@google.com#include "fifo_resize.hh"
22913521Sgabeblack@google.com
23013521Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ */
231