summaryrefslogtreecommitdiff
path: root/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h
blob: 25a1834597e6976419d28190efdabfa2747baaf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*****************************************************************************

  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
  more contributor license agreements.  See the NOTICE file distributed
  with this work for additional information regarding copyright ownership.
  Accellera licenses this file to you under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with the
  License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  implied.  See the License for the specific language governing
  permissions and limitations under the License.

 *****************************************************************************/

#ifndef \
    __SYSTEMC_EXT_TLM_CORE_TLM_1_TLM_REQ_RSP_TLM_CHANNELS_TLM_FIFO_TLM_FIFO_H__
#define \
    __SYSTEMC_EXT_TLM_CORE_TLM_1_TLM_REQ_RSP_TLM_CHANNELS_TLM_FIFO_TLM_FIFO_H__

//
// This implements put, get and peek
//
// It also implements 0 and infinite size fifos - but the size
// zero fifos aren't rendezvous like zero length fifos, they simply are both
// full and empty at the same time.
//
// The size can be dynamically changed using the resize interface
//
// To get an infinite fifo use a -ve size in the constructor.
// The absolute value of the size is taken as the starting size of the
// actual physical buffer.
//

#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h"
#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h"

namespace tlm
{

template <typename T>
class tlm_fifo : public virtual tlm_fifo_get_if<T>,
    public virtual tlm_fifo_put_if<T>, public sc_core::sc_prim_channel
{
  public:
    // Constructors.
    explicit tlm_fifo(int size_=1) :
        sc_core::sc_prim_channel(sc_core::sc_gen_unique_name("fifo"))
    {
        init(size_);
    }

    explicit tlm_fifo(const char *name_, int size_=1) :
        sc_core::sc_prim_channel(name_)
    {
        init(size_);
    }

    // Destructor..
    virtual ~tlm_fifo() {}

    // Tlm get interface.
    T get(tlm_tag<T> * =nullptr);

    bool nb_get(T &);
    bool nb_can_get(tlm_tag<T> * =nullptr) const;
    const sc_core::sc_event &
    ok_to_get(tlm_tag<T> * =nullptr) const
    {
        return m_data_written_event;
    }

    // Tlm peek interface.
    T peek(tlm_tag<T> * =nullptr) const;

    bool nb_peek(T &) const;
    bool nb_can_peek(tlm_tag<T> * =nullptr) const;
    const sc_core::sc_event &
    ok_to_peek(tlm_tag<T> * =nullptr) const
    {
        return m_data_written_event;
    }

    // Tlm put interface.
    void put(const T &);

    bool nb_put(const T &);
    bool nb_can_put(tlm_tag<T> * =nullptr) const;
    const sc_core::sc_event &
    ok_to_put(tlm_tag<T> * =nullptr) const
    {
        return m_data_read_event;
    }

    // Resize if.
    void nb_expand(unsigned int n=1);
    void nb_unbound(unsigned int n=16);

    bool nb_reduce(unsigned int n=1);
    bool nb_bound(unsigned int n);

    // Debug interface.
    bool nb_peek(T &, int n) const;
    bool nb_poke(const T &, int n=0);

    int used() const { return m_num_readable - m_num_read; }
    int size() const { return m_size; }

    void
    debug() const
    {
        if (is_empty())
            std::cout << "empty" << std::endl;
        if (is_full())
            std::cout << "full" << std::endl;

        std::cout << "size " << size() << " - " << used() << " used "
                  << std::endl;
        std::cout << "readable " << m_num_readable << std::endl;
        std::cout << "written/read " << m_num_written << "/" << m_num_read
                  << std::endl;
    }

    // Support functions.
    static const char * const kind_string;
    const char *kind() const { return kind_string; }

  protected:
    sc_core::sc_event &
    read_event(tlm_tag<T> * =nullptr)
    {
        return m_data_read_event;
    }

    void update();
    void init(int);

    circular_buffer<T> buffer;

    int m_size; // logical size of fifo

    int m_num_readable; // #samples readable
    int m_num_read; // #samples read during this delta cycle
    int m_num_written; // #samples written during this delta cycle
    bool m_expand; // has an expand occurred during this delta cycle ?
    // #samples read without notify during this delta cycle
    int m_num_read_no_notify;

    sc_core::sc_event m_data_read_event;
    sc_core::sc_event m_data_written_event;

  private:
    // disabled
    tlm_fifo(const tlm_fifo<T> &);
    tlm_fifo &operator = (const tlm_fifo<T> &);

    //
    // use nb_can_get() and nb_can_put() rather than the following two
    // private functions
    //

    bool is_empty() const { return used() == 0; }

    bool
    is_full() const
    {
        if (size() < 0)
            return false;
        else
            return size() <= m_num_readable + m_num_written;
    }
};

template <typename T>
const char *const tlm_fifo<T>::kind_string = "tlm_fifo";

/******************************************************************
//
// init and update
//
******************************************************************/

template <typename T>
inline void
tlm_fifo<T>::init(int size_)
{
    if (size_ > 0) {
        buffer.resize( size_ );
    } else if (size_ < 0) {
        buffer.resize(-size_);
    } else {
        buffer.resize(16);
    }

    m_size = size_;
    m_num_readable = 0;
    m_num_read = 0;
    m_num_written = 0;
    m_expand = false;
    m_num_read_no_notify = false;
}

template <typename T>
inline void
tlm_fifo<T>::update()
{
    if (m_num_read > m_num_read_no_notify || m_expand) {
        m_data_read_event.notify(sc_core::SC_ZERO_TIME);
    }

    if (m_num_written > 0) {
        m_data_written_event.notify(sc_core::SC_ZERO_TIME);
    }

    m_expand = false;
    m_num_read = 0;
    m_num_written = 0;
    m_num_readable = buffer.used();
    m_num_read_no_notify = 0;
}

} // namespace tlm

#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h"
#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h"
#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h"

#endif
/*__SYSTEMC_EXT_TLM_CORE_TLM_1_TLM_REQ_RSP_TLM_CHANNELS_TLM_FIFO_TLM_FIFO_H__*/