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/***************************************************************************** 21 22 sc_fifo.h -- The sc_fifo<T> primitive channel class. 23 24 Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 25 26 CHANGE LOG IS AT THE END OF THE FILE 27 *****************************************************************************/ 28 29#ifndef SC_FIFO_H 30#define SC_FIFO_H 31 32 33#include "sysc/communication/sc_communication_ids.h" 34#include "sysc/communication/sc_prim_channel.h" 35#include "sysc/communication/sc_fifo_ifs.h" 36#include "sysc/kernel/sc_event.h" 37#include "sysc/kernel/sc_simcontext.h" 38#include "sysc/tracing/sc_trace.h" 39#include <typeinfo> 40 41namespace sc_core { 42 43// ---------------------------------------------------------------------------- 44// CLASS : sc_fifo<T> 45// 46// The sc_fifo<T> primitive channel class. 47// ---------------------------------------------------------------------------- 48 49template <class T> 50class sc_fifo 51: public sc_fifo_in_if<T>, 52 public sc_fifo_out_if<T>, 53 public sc_prim_channel 54{ 55public: 56 57 // constructors 58 59 explicit sc_fifo( int size_ = 16 ) 60 : sc_prim_channel( sc_gen_unique_name( "fifo" ) ), 61 m_data_read_event( 62 (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), 63 m_data_written_event( 64 (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) 65 { init( size_ ); } 66 67 explicit sc_fifo( const char* name_, int size_ = 16 ) 68 : sc_prim_channel( name_ ), 69 m_data_read_event( 70 (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), 71 m_data_written_event( 72 (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) 73 { init( size_ ); } 74 75 76 // destructor 77 78 virtual ~sc_fifo() 79 { delete [] m_buf; } 80 81 82 // interface methods 83 84 virtual void register_port( sc_port_base&, const char* ); 85 86 87 // blocking read 88 virtual void read( T& ); 89 virtual T read(); 90 91 // non-blocking read 92 virtual bool nb_read( T& ); 93 94 95 // get the number of available samples 96 97 virtual int num_available() const 98 { return ( m_num_readable - m_num_read ); } 99 100 101 // get the data written event 102 103 virtual const sc_event& data_written_event() const 104 { return m_data_written_event; } 105 106 107 // blocking write 108 virtual void write( const T& ); 109 110 // non-blocking write 111 virtual bool nb_write( const T& ); 112 113 114 // get the number of free spaces 115 116 virtual int num_free() const 117 { return ( m_size - m_num_readable - m_num_written ); } 118 119 120 // get the data read event 121 122 virtual const sc_event& data_read_event() const 123 { return m_data_read_event; } 124 125 126 // other methods 127 128 operator T () 129 { return read(); } 130 131 132 sc_fifo<T>& operator = ( const T& a ) 133 { write( a ); return *this; } 134 135 136 void trace( sc_trace_file* tf ) const; 137 138 139 virtual void print( ::std::ostream& = ::std::cout ) const; 140 virtual void dump( ::std::ostream& = ::std::cout ) const; 141 142 virtual const char* kind() const 143 { return "sc_fifo"; } 144 145protected: 146 147 virtual void update(); 148 149 // support methods 150 151 void init( int ); 152 153 void buf_init( int ); 154 bool buf_write( const T& ); 155 bool buf_read( T& ); 156 157protected: 158 159 int m_size; // size of the buffer 160 T* m_buf; // the buffer 161 int m_free; // number of free spaces 162 int m_ri; // index of next read 163 int m_wi; // index of next write 164 165 sc_port_base* m_reader; // used for static design rule checking 166 sc_port_base* m_writer; // used for static design rule checking 167 168 int m_num_readable; // #samples readable 169 int m_num_read; // #samples read during this delta cycle 170 int m_num_written; // #samples written during this delta cycle 171 172 sc_event m_data_read_event; 173 sc_event m_data_written_event; 174 175private: 176 177 // disabled 178 sc_fifo( const sc_fifo<T>& ); 179 sc_fifo& operator = ( const sc_fifo<T>& ); 180}; 181 182 183// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 184 185template <class T> 186inline 187void 188sc_fifo<T>::register_port( sc_port_base& port_, 189 const char* if_typename_ ) 190{ 191 std::string nm( if_typename_ ); 192 if( nm == typeid( sc_fifo_in_if<T> ).name() || 193 nm == typeid( sc_fifo_blocking_in_if<T> ).name() 194 ) { 195 // only one reader can be connected 196 if( m_reader != 0 ) { 197 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 ); 198 } 199 m_reader = &port_; 200 } else if( nm == typeid( sc_fifo_out_if<T> ).name() || 201 nm == typeid( sc_fifo_blocking_out_if<T> ).name() 202 ) { 203 // only one writer can be connected 204 if( m_writer != 0 ) { 205 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 ); 206 } 207 m_writer = &port_; 208 } 209 else 210 { 211 SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, 212 "sc_fifo<T> port not recognized" ); 213 } 214} 215 216 217// blocking read 218 219template <class T> 220inline 221void 222sc_fifo<T>::read( T& val_ ) 223{ 224 while( num_available() == 0 ) { 225 sc_core::wait( m_data_written_event ); 226 } 227 m_num_read ++; 228 buf_read( val_ ); 229 request_update(); 230} 231 232template <class T> 233inline 234T 235sc_fifo<T>::read() 236{ 237 T tmp; 238 read( tmp ); 239 return tmp; 240} 241 242// non-blocking read 243 244template <class T> 245inline 246bool 247sc_fifo<T>::nb_read( T& val_ ) 248{ 249 if( num_available() == 0 ) { 250 return false; 251 } 252 m_num_read ++; 253 buf_read( val_ ); 254 request_update(); 255 return true; 256} 257 258 259// blocking write 260 261template <class T> 262inline 263void 264sc_fifo<T>::write( const T& val_ ) 265{ 266 while( num_free() == 0 ) { 267 sc_core::wait( m_data_read_event ); 268 } 269 m_num_written ++; 270 buf_write( val_ ); 271 request_update(); 272} 273 274// non-blocking write 275 276template <class T> 277inline 278bool 279sc_fifo<T>::nb_write( const T& val_ ) 280{ 281 if( num_free() == 0 ) { 282 return false; 283 } 284 m_num_written ++; 285 buf_write( val_ ); 286 request_update(); 287 return true; 288} 289 290 291template <class T> 292inline 293void 294sc_fifo<T>::trace( sc_trace_file* tf ) const 295{ 296#if defined(DEBUG_SYSTEMC) 297 char buf[32]; 298 std::string nm = name(); 299 for( int i = 0; i < m_size; ++ i ) { 300 std::sprintf( buf, "_%d", i ); 301 sc_trace( tf, m_buf[i], nm + buf ); 302 } 303#endif 304} 305 306 307template <class T> 308inline 309void 310sc_fifo<T>::print( ::std::ostream& os ) const 311{ 312 if( m_free != m_size ) { 313 int i = m_ri; 314 do { 315 os << m_buf[i] << ::std::endl; 316 i = ( i + 1 ) % m_size; 317 } while( i != m_wi ); 318 } 319} 320 321template <class T> 322inline 323void 324sc_fifo<T>::dump( ::std::ostream& os ) const 325{ 326 os << "name = " << name() << ::std::endl; 327 if( m_free != m_size ) { 328 int i = m_ri; 329 int j = 0; 330 do { 331 os << "value[" << i << "] = " << m_buf[i] << ::std::endl; 332 i = ( i + 1 ) % m_size; 333 j ++; 334 } while( i != m_wi ); 335 } 336} 337 338 339template <class T> 340inline 341void 342sc_fifo<T>::update() 343{ 344 if( m_num_read > 0 ) { 345 m_data_read_event.notify(SC_ZERO_TIME); 346 } 347 348 if( m_num_written > 0 ) { 349 m_data_written_event.notify(SC_ZERO_TIME); 350 } 351 352 m_num_readable = m_size - m_free; 353 m_num_read = 0; 354 m_num_written = 0; 355} 356 357 358// support methods 359 360template <class T> 361inline 362void 363sc_fifo<T>::init( int size_ ) 364{ 365 buf_init( size_ ); 366 367 m_reader = 0; 368 m_writer = 0; 369 370 m_num_readable = 0; 371 m_num_read = 0; 372 m_num_written = 0; 373} 374 375 376template <class T> 377inline 378void 379sc_fifo<T>::buf_init( int size_ ) 380{ 381 if( size_ <= 0 ) { 382 SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 ); 383 } 384 m_size = size_; 385 m_buf = new T[m_size]; 386 m_free = m_size; 387 m_ri = 0; 388 m_wi = 0; 389} 390 391template <class T> 392inline 393bool 394sc_fifo<T>::buf_write( const T& val_ ) 395{ 396 if( m_free == 0 ) { 397 return false; 398 } 399 m_buf[m_wi] = val_; 400 m_wi = ( m_wi + 1 ) % m_size; 401 m_free --; 402 return true; 403} 404 405template <class T> 406inline 407bool 408sc_fifo<T>::buf_read( T& val_ ) 409{ 410 if( m_free == m_size ) { 411 return false; 412 } 413 val_ = m_buf[m_ri]; 414 m_buf[m_ri] = T(); // clear entry for boost::shared_ptr, et al. 415 m_ri = ( m_ri + 1 ) % m_size; 416 m_free ++; 417 return true; 418} 419 420 421// ---------------------------------------------------------------------------- 422 423template <class T> 424inline 425::std::ostream& 426operator << ( ::std::ostream& os, const sc_fifo<T>& a ) 427{ 428 a.print( os ); 429 return os; 430} 431 432} // namespace sc_core 433 434//$Log: sc_fifo.h,v $ 435//Revision 1.6 2011/08/26 20:45:40 acg 436// Andy Goodrich: moved the modification log to the end of the file to 437// eliminate source line number skew when check-ins are done. 438// 439//Revision 1.5 2011/03/23 16:17:22 acg 440// Andy Goodrich: hide the sc_events that are kernel related. 441// 442//Revision 1.4 2011/02/18 20:23:45 acg 443// Andy Goodrich: Copyright update. 444// 445//Revision 1.3 2009/10/14 19:05:40 acg 446// Andy Goodrich: added check for blocking interfaces in addition to the 447// combined blocking/nonblocking interface. 448// 449//Revision 1.2 2009/05/22 16:06:24 acg 450// Andy Goodrich: process control updates. 451// 452//Revision 1.1.1.1 2006/12/15 20:20:04 acg 453//SystemC 2.3 454// 455//Revision 1.4 2006/01/24 20:46:31 acg 456//Andy Goodrich: changes to eliminate use of deprecated features. For instance, 457//using notify(SC_ZERO_TIME) in place of notify_delayed(). 458// 459//Revision 1.3 2006/01/13 20:41:59 acg 460//Andy Goodrich: Changes to add port registration to the things that are 461//checked when SC_NO_WRITE_CHECK is not defined. 462// 463//Revision 1.2 2006/01/03 23:18:26 acg 464//Changed copyright to include 2006. 465// 466//Revision 1.1.1.1 2005/12/19 23:16:43 acg 467//First check in of SystemC 2.1 into its own archive. 468// 469//Revision 1.12 2005/09/15 23:01:51 acg 470//Added std:: prefix to appropriate methods and types to get around 471//issues with the Edison Front End. 472// 473//Revision 1.11 2005/06/10 22:43:55 acg 474//Added CVS change log annotation. 475// 476 477#endif 478 479// Taf! 480