fifo.hh (13521:74fa3ac44057) fifo.hh (13586:008fe87c1ad4)
1/*****************************************************************************
2
3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4 more contributor license agreements. See the NOTICE file distributed
5 with this work for additional information regarding copyright ownership.
6 Accellera licenses this file to you under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with the
8 License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 implied. See the License for the specific language governing
16 permissions and limitations under the License.
17
18 *****************************************************************************/
19
20#ifndef __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__
21#define __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__
22
23//
24// This implements put, get and peek
25//
26// It also implements 0 and infinite size fifos - but the size
27// zero fifos aren't rendezvous like zero length fifos, they simply are both
28// full and empty at the same time.
29//
30// The size can be dynamically changed using the resize interface
31//
32// To get an infinite fifo use a -ve size in the constructor.
33// The absolute value of the size is taken as the starting size of the
34// actual physical buffer.
35//
36
1/*****************************************************************************
2
3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4 more contributor license agreements. See the NOTICE file distributed
5 with this work for additional information regarding copyright ownership.
6 Accellera licenses this file to you under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with the
8 License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 implied. See the License for the specific language governing
16 permissions and limitations under the License.
17
18 *****************************************************************************/
19
20#ifndef __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__
21#define __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__
22
23//
24// This implements put, get and peek
25//
26// It also implements 0 and infinite size fifos - but the size
27// zero fifos aren't rendezvous like zero length fifos, they simply are both
28// full and empty at the same time.
29//
30// The size can be dynamically changed using the resize interface
31//
32// To get an infinite fifo use a -ve size in the constructor.
33// The absolute value of the size is taken as the starting size of the
34// actual physical buffer.
35//
36
37#include "tlm_core/1/req_rsp/channels/fifo/circular_buffer.hh"
38#include "tlm_core/1/req_rsp/interfaces/fifo_ifs.hh"
37#include "../../interfaces/fifo_ifs.hh"
38#include "circular_buffer.hh"
39
40namespace tlm
41{
42
43template <typename T>
44class tlm_fifo : public virtual tlm_fifo_get_if<T>,
45 public virtual tlm_fifo_put_if<T>, public sc_core::sc_prim_channel
46{
47 public:
48 // Constructors.
49 explicit tlm_fifo(int size_=1) :
50 sc_core::sc_prim_channel(sc_core::sc_gen_unique_name("fifo"))
51 {
52 init(size_);
53 }
54
55 explicit tlm_fifo(const char *name_, int size_=1) :
56 sc_core::sc_prim_channel(name_)
57 {
58 init(size_);
59 }
60
61 // Destructor..
62 virtual ~tlm_fifo() {}
63
64 // Tlm get interface.
65 T get(tlm_tag<T> * =nullptr);
66
67 bool nb_get(T &);
68 bool nb_can_get(tlm_tag<T> * =nullptr) const;
69 const sc_core::sc_event &
70 ok_to_get(tlm_tag<T> * =nullptr) const
71 {
72 return m_data_written_event;
73 }
74
75 // Tlm peek interface.
76 T peek(tlm_tag<T> * =nullptr) const;
77
78 bool nb_peek(T &) const;
79 bool nb_can_peek(tlm_tag<T> * =nullptr) const;
80 const sc_core::sc_event &
81 ok_to_peek(tlm_tag<T> * =nullptr) const
82 {
83 return m_data_written_event;
84 }
85
86 // Tlm put interface.
87 void put(const T &);
88
89 bool nb_put(const T &);
90 bool nb_can_put(tlm_tag<T> * =nullptr) const;
91 const sc_core::sc_event &
92 ok_to_put(tlm_tag<T> * =nullptr) const
93 {
94 return m_data_read_event;
95 }
96
97 // Resize if.
98 void nb_expand(unsigned int n=1);
99 void nb_unbound(unsigned int n=16);
100
101 bool nb_reduce(unsigned int n=1);
102 bool nb_bound(unsigned int n);
103
104 // Debug interface.
105 bool nb_peek(T &, int n) const;
106 bool nb_poke(const T &, int n=0);
107
108 int used() const { return m_num_readable - m_num_read; }
109 int size() const { return m_size; }
110
111 void
112 debug() const
113 {
114 if (is_empty())
115 std::cout << "empty" << std::endl;
116 if (is_full())
117 std::cout << "full" << std::endl;
118
119 std::cout << "size " << size() << " - " << used() << " used "
120 << std::endl;
121 std::cout << "readable " << m_num_readable << std::endl;
122 std::cout << "written/read " << m_num_written << "/" << m_num_read
123 << std::endl;
124 }
125
126 // Support functions.
127 static const char * const kind_string;
128 const char *kind() const { return kind_string; }
129
130 protected:
131 sc_core::sc_event &
132 read_event(tlm_tag<T> * =nullptr)
133 {
134 return m_data_read_event;
135 }
136
137 void update();
138 void init(int);
139
140 circular_buffer<T> buffer;
141
142 int m_size; // logical size of fifo
143
144 int m_num_readable; // #samples readable
145 int m_num_read; // #samples read during this delta cycle
146 int m_num_written; // #samples written during this delta cycle
147 bool m_expand; // has an expand occurred during this delta cycle ?
148 // #samples read without notify during this delta cycle
149 int m_num_read_no_notify;
150
151 sc_core::sc_event m_data_read_event;
152 sc_core::sc_event m_data_written_event;
153
154 private:
155 // disabled
156 tlm_fifo(const tlm_fifo<T> &);
157 tlm_fifo &operator = (const tlm_fifo<T> &);
158
159 //
160 // use nb_can_get() and nb_can_put() rather than the following two
161 // private functions
162 //
163
164 bool is_empty() const { return used() == 0; }
165
166 bool
167 is_full() const
168 {
169 if (size() < 0)
170 return false;
171 else
172 return size() <= m_num_readable + m_num_written;
173 }
174};
175
176template <typename T>
177const char *const tlm_fifo<T>::kind_string = "tlm_fifo";
178
179/******************************************************************
180//
181// init and update
182//
183******************************************************************/
184
185template <typename T>
186inline void
187tlm_fifo<T>::init(int size_)
188{
189 if (size_ > 0) {
190 buffer.resize( size_ );
191 } else if (size_ < 0) {
192 buffer.resize(-size_);
193 } else {
194 buffer.resize(16);
195 }
196
197 m_size = size_;
198 m_num_readable = 0;
199 m_num_read = 0;
200 m_num_written = 0;
201 m_expand = false;
202 m_num_read_no_notify = false;
203}
204
205template <typename T>
206inline void
207tlm_fifo<T>::update()
208{
209 if (m_num_read > m_num_read_no_notify || m_expand) {
210 m_data_read_event.notify(sc_core::SC_ZERO_TIME);
211 }
212
213 if (m_num_written > 0) {
214 m_data_written_event.notify(sc_core::SC_ZERO_TIME);
215 }
216
217 m_expand = false;
218 m_num_read = 0;
219 m_num_written = 0;
220 m_num_readable = buffer.used();
221 m_num_read_no_notify = 0;
222}
223
224} // namespace tlm
225
39
40namespace tlm
41{
42
43template <typename T>
44class tlm_fifo : public virtual tlm_fifo_get_if<T>,
45 public virtual tlm_fifo_put_if<T>, public sc_core::sc_prim_channel
46{
47 public:
48 // Constructors.
49 explicit tlm_fifo(int size_=1) :
50 sc_core::sc_prim_channel(sc_core::sc_gen_unique_name("fifo"))
51 {
52 init(size_);
53 }
54
55 explicit tlm_fifo(const char *name_, int size_=1) :
56 sc_core::sc_prim_channel(name_)
57 {
58 init(size_);
59 }
60
61 // Destructor..
62 virtual ~tlm_fifo() {}
63
64 // Tlm get interface.
65 T get(tlm_tag<T> * =nullptr);
66
67 bool nb_get(T &);
68 bool nb_can_get(tlm_tag<T> * =nullptr) const;
69 const sc_core::sc_event &
70 ok_to_get(tlm_tag<T> * =nullptr) const
71 {
72 return m_data_written_event;
73 }
74
75 // Tlm peek interface.
76 T peek(tlm_tag<T> * =nullptr) const;
77
78 bool nb_peek(T &) const;
79 bool nb_can_peek(tlm_tag<T> * =nullptr) const;
80 const sc_core::sc_event &
81 ok_to_peek(tlm_tag<T> * =nullptr) const
82 {
83 return m_data_written_event;
84 }
85
86 // Tlm put interface.
87 void put(const T &);
88
89 bool nb_put(const T &);
90 bool nb_can_put(tlm_tag<T> * =nullptr) const;
91 const sc_core::sc_event &
92 ok_to_put(tlm_tag<T> * =nullptr) const
93 {
94 return m_data_read_event;
95 }
96
97 // Resize if.
98 void nb_expand(unsigned int n=1);
99 void nb_unbound(unsigned int n=16);
100
101 bool nb_reduce(unsigned int n=1);
102 bool nb_bound(unsigned int n);
103
104 // Debug interface.
105 bool nb_peek(T &, int n) const;
106 bool nb_poke(const T &, int n=0);
107
108 int used() const { return m_num_readable - m_num_read; }
109 int size() const { return m_size; }
110
111 void
112 debug() const
113 {
114 if (is_empty())
115 std::cout << "empty" << std::endl;
116 if (is_full())
117 std::cout << "full" << std::endl;
118
119 std::cout << "size " << size() << " - " << used() << " used "
120 << std::endl;
121 std::cout << "readable " << m_num_readable << std::endl;
122 std::cout << "written/read " << m_num_written << "/" << m_num_read
123 << std::endl;
124 }
125
126 // Support functions.
127 static const char * const kind_string;
128 const char *kind() const { return kind_string; }
129
130 protected:
131 sc_core::sc_event &
132 read_event(tlm_tag<T> * =nullptr)
133 {
134 return m_data_read_event;
135 }
136
137 void update();
138 void init(int);
139
140 circular_buffer<T> buffer;
141
142 int m_size; // logical size of fifo
143
144 int m_num_readable; // #samples readable
145 int m_num_read; // #samples read during this delta cycle
146 int m_num_written; // #samples written during this delta cycle
147 bool m_expand; // has an expand occurred during this delta cycle ?
148 // #samples read without notify during this delta cycle
149 int m_num_read_no_notify;
150
151 sc_core::sc_event m_data_read_event;
152 sc_core::sc_event m_data_written_event;
153
154 private:
155 // disabled
156 tlm_fifo(const tlm_fifo<T> &);
157 tlm_fifo &operator = (const tlm_fifo<T> &);
158
159 //
160 // use nb_can_get() and nb_can_put() rather than the following two
161 // private functions
162 //
163
164 bool is_empty() const { return used() == 0; }
165
166 bool
167 is_full() const
168 {
169 if (size() < 0)
170 return false;
171 else
172 return size() <= m_num_readable + m_num_written;
173 }
174};
175
176template <typename T>
177const char *const tlm_fifo<T>::kind_string = "tlm_fifo";
178
179/******************************************************************
180//
181// init and update
182//
183******************************************************************/
184
185template <typename T>
186inline void
187tlm_fifo<T>::init(int size_)
188{
189 if (size_ > 0) {
190 buffer.resize( size_ );
191 } else if (size_ < 0) {
192 buffer.resize(-size_);
193 } else {
194 buffer.resize(16);
195 }
196
197 m_size = size_;
198 m_num_readable = 0;
199 m_num_read = 0;
200 m_num_written = 0;
201 m_expand = false;
202 m_num_read_no_notify = false;
203}
204
205template <typename T>
206inline void
207tlm_fifo<T>::update()
208{
209 if (m_num_read > m_num_read_no_notify || m_expand) {
210 m_data_read_event.notify(sc_core::SC_ZERO_TIME);
211 }
212
213 if (m_num_written > 0) {
214 m_data_written_event.notify(sc_core::SC_ZERO_TIME);
215 }
216
217 m_expand = false;
218 m_num_read = 0;
219 m_num_written = 0;
220 m_num_readable = buffer.used();
221 m_num_read_no_notify = 0;
222}
223
224} // namespace tlm
225
226#include "tlm_core/1/req_rsp/channels/fifo/fifo_peek.hh"
227#include "tlm_core/1/req_rsp/channels/fifo/fifo_put_get.hh"
228#include "tlm_core/1/req_rsp/channels/fifo/fifo_resize.hh"
226#include "fifo_peek.hh"
227#include "fifo_put_get.hh"
228#include "fifo_resize.hh"
229
230#endif /* __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ */
229
230#endif /* __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_FIFO_HH__ */