diff options
Diffstat (limited to 'ext/systemc/src/sysc/communication')
39 files changed, 12328 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/communication/sc_buffer.h b/ext/systemc/src/sysc/communication/sc_buffer.h new file mode 100644 index 000000000..e91c1a7c9 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_buffer.h @@ -0,0 +1,194 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_buffer.h -- The sc_buffer<T> primitive channel class. + Like sc_signal<T>, but *every* write causes an event. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_BUFFER_H +#define SC_BUFFER_H + + +#include "sysc/communication/sc_signal.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_buffer<T> +// +// The sc_buffer<T> primitive channel class. +// ---------------------------------------------------------------------------- + +template< typename T, sc_writer_policy POL = SC_DEFAULT_WRITER_POLICY > +class sc_buffer +: public sc_signal<T,POL> +{ +public: + + // typedefs + + typedef sc_buffer<T,POL> this_type; + typedef sc_signal<T,POL> base_type; + +public: + + // constructors + + sc_buffer() + : base_type( sc_gen_unique_name( "buffer" ) ) + {} + + explicit sc_buffer( const char* name_ ) + : base_type( name_ ) + {} + + sc_buffer( const char* name_, const T& initial_value_ ) + : base_type( name_, initial_value_ ) + {} + + // interface methods + + // write the new value + virtual void write( const T& ); + + + // other methods + + this_type& operator = ( const T& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<T>& a ) + { write( a.read() ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + virtual const char* kind() const + { return "sc_buffer"; } + +protected: + + virtual void update(); + +private: + + // disabled + sc_buffer( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// write the new value + +template< typename T, sc_writer_policy POL > +inline +void +sc_buffer<T,POL>::write( const T& value_ ) +{ + if( !base_type::policy_type::check_write(this,true) ) + return; + + this->m_new_val = value_; + this->request_update(); +} + + +template< typename T, sc_writer_policy POL > +inline +void +sc_buffer<T,POL>::update() +{ + base_type::policy_type::update(); + base_type::do_update(); +} + +} // namespace sc_core + +#endif + +//$Log: sc_buffer.h,v $ +//Revision 1.7 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.6 2011/04/08 18:22:45 acg +// Philipp A. Hartmann: use the context of the primitive channel to get +// the change stamp value. +// +//Revision 1.5 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +//Revision 1.4 2011/04/05 06:15:18 acg +// Philipp A. Hartmann: sc_writer_policy: ignore no-ops in delta check. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/12/07 19:50:36 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.8 2006/03/13 20:19:43 acg +// Andy Goodrich: changed sc_event instances into pointers to sc_event instances +// that are allocated as needed. This saves considerable storage for large +// numbers of signals, etc. +// +//Revision 1.7 2006/01/26 21:00:49 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +//Revision 1.6 2006/01/24 20:46:31 acg +//Andy Goodrich: changes to eliminate use of deprecated features. For instance, +//using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +//Revision 1.5 2006/01/19 19:18:25 acg +//Andy Goodrich: eliminated check_writer in favor of inline code within the +//write() method since we always execute the check_writer code even when +//check writing is turned off. +// +//Revision 1.4 2006/01/19 00:30:57 acg +//Andy Goodrich: Yet another implementation for disabling write checks on +//signals. This version uses an environment variable, SC_SIGNAL_WRITE_CHECK, +//that when set to DISABLE will turn off write checking. +// +//Revision 1.3 2006/01/13 18:47:20 acg +//Reversed sense of multiwriter signal check. It now defaults to ON unless the +//user defines SC_NO_WRITE_CHEK before inclusion of the file. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_clock.cpp b/ext/systemc/src/sysc/communication/sc_clock.cpp new file mode 100644 index 000000000..158d54b7a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_clock.cpp @@ -0,0 +1,409 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_clock.cpp -- The clock channel. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +// using notify_delayed(). +// +// Revision 1.4 2006/01/18 21:42:26 acg +// Andy Goodrich: Changes for check writer support, and tightening up sc_clock +// port usage. +// +// Revision 1.3 2006/01/13 18:47:41 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +#include "sysc/communication/sc_clock.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_spawn.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_clock +// +// The clock channel. +// ---------------------------------------------------------------------------- + +// constructors + +sc_clock::sc_clock() : + base_type( sc_gen_unique_name( "clock" ) ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + "_next_negedge_event").c_str()) + +{ + init( sc_time::from_value(simcontext()->m_time_params->default_time_unit), + 0.5, + SC_ZERO_TIME, + true ); + + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time::from_value(simcontext()->m_time_params->default_time_unit), + 0.5, + SC_ZERO_TIME, + true ); + + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_, + const sc_time& period_, + double duty_cycle_, + const sc_time& start_time_, + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( period_, + duty_cycle_, + start_time_, + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + +sc_clock::sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time( period_v_, period_tu_, simcontext() ), + duty_cycle_, + SC_ZERO_TIME, + true ); + + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_, + double start_time_v_, + sc_time_unit start_time_tu_, + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time( period_v_, period_tu_, simcontext() ), + duty_cycle_, + sc_time( start_time_v_, start_time_tu_, simcontext() ), + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + +// for backward compatibility with 1.0 +sc_clock::sc_clock( const char* name_, + double period_, // in default time units + double duty_cycle_, + double start_time_, // in default time units + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + static bool warn_sc_clock=true; + if ( warn_sc_clock ) + { + warn_sc_clock = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "\n sc_clock(const char*, double, double, double, bool)\n" + " is deprecated use a form that includes sc_time or\n" + " sc_time_unit"); + } + + sc_time default_time = + sc_time::from_value( simcontext()->m_time_params->default_time_unit ); + + init( ( period_ * default_time ), + duty_cycle_, + ( start_time_ * default_time ), + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_clock::before_end_of_elaboration" +// +// This callback is used to spawn the edge processes for this object instance. +// The processes are created here rather than the constructor for the object +// so that the processes are registered with the global simcontext rather +// than the scope of the clock's parent. +//------------------------------------------------------------------------------ +#if ( defined(_MSC_VER) && _MSC_VER < 1300 ) //VC++6.0 doesn't support sc_spawn with functor. +# define sc_clock_posedge_callback(ptr) sc_clock_posedge_callback + +# define sc_clock_negedge_callback(ptr) sc_clock_negedge_callback + +# define sc_spawn(a,b,c) { \ + sc_process_handle result(new sc_spawn_object<a>(a(this),b,c)); \ + } +#endif // ( defined(_MSC_VER) && _MSC_VER < 1300 ) + +void sc_clock::before_end_of_elaboration() +{ + std::string gen_base; + sc_spawn_options posedge_options; // Options for posedge process. + sc_spawn_options negedge_options; // Options for negedge process. + + posedge_options.spawn_method(); + posedge_options.dont_initialize(); + posedge_options.set_sensitivity(&m_next_posedge_event); + gen_base = basename(); + gen_base += "_posedge_action"; + sc_spawn(sc_clock_posedge_callback(this), + sc_gen_unique_name( gen_base.c_str() ), &posedge_options); + + negedge_options.spawn_method(); + negedge_options.dont_initialize(); + negedge_options.set_sensitivity(&m_next_negedge_event); + gen_base = basename(); + gen_base += "_negedge_action"; + sc_spawn( sc_clock_negedge_callback(this), + sc_gen_unique_name( gen_base.c_str() ), &negedge_options ); +} + +//clear VC++6.0 macros +#undef sc_clock_posedge_callback +#undef sc_clock_negedge_callback +#undef sc_spawn + +// destructor (does nothing) + +sc_clock::~sc_clock() +{} + +void sc_clock::register_port( sc_port_base& /*port*/, const char* if_typename_ ) +{ + std::string nm( if_typename_ ); + if( nm == typeid( sc_signal_inout_if<bool> ).name() ) { + SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_BIND_CLOCK_TO_OUTPUT_, ""); + } +} + +void +sc_clock::write( const bool& /* value */ ) +{ + SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_WRITE_TO_CLOCK_, ""); +} + +// interface methods + +// get the current time + +const sc_time& +sc_clock::time_stamp() +{ + return sc_time_stamp(); +} + + +// error reporting + +void +sc_clock::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: clock '%s'", add_msg, name() ); + } else { + std::sprintf( msg, "clock '%s'", name() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +void +sc_clock::init( const sc_time& period_, + double duty_cycle_, + const sc_time& start_time_, + bool posedge_first_ ) +{ + if( period_ == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_PERIOD_ZERO_, + "increase the period" ); + } + m_period = period_; + m_posedge_first = posedge_first_; + + if( duty_cycle_ <= 0.0 || duty_cycle_ >= 1.0 ) { + m_duty_cycle = 0.5; + } else { + m_duty_cycle = duty_cycle_; + } + + m_negedge_time = m_period * m_duty_cycle; + m_posedge_time = m_period - m_negedge_time; + + if( m_negedge_time == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_HIGH_TIME_ZERO_, + "increase the period or increase the duty cycle" ); + } + if( m_posedge_time == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_LOW_TIME_ZERO_, + "increase the period or decrease the duty cycle" ); + } + + if( posedge_first_ ) { + this->m_cur_val = false; + this->m_new_val = false; + } else { + this->m_cur_val = true; + this->m_new_val = true; + } + + m_start_time = start_time_; + +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + Andy Goodrich, Forte Design Systems, + 3 October, 2003 + Description of Modification: sc_clock inherits from sc_signal<bool> only + instead of sc_signal_in_if<bool> and sc_module. + The 2 methods posedge_action() and + negedge_action() are created using sc_spawn(). + boost::bind() is not required, instead a local + bind function can be used since the signatures + of the spawned functions are statically known. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_clock.cpp,v $ +// Revision 1.7 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/08/24 22:05:35 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.4 2011/03/12 21:07:42 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.3 2011/03/06 15:55:08 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.8 2006/04/18 23:36:50 acg +// Andy Goodrich: made add_trace_internal public until I can figure out +// how to do a friend specification for sc_trace in an environment where +// there are partial template and full template specifications for its +// arguments. +// +// Revision 1.7 2006/04/17 16:38:42 acg +// Andy Goodrich: added more context to the deprecation message for the +// sc_clock constructor. +// +// Revision 1.6 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.5 2006/01/24 20:43:24 acg +// Andy Goodrich: convert notify_delayed() calls into notify_internal() calls. +// notify_internal() is an implementation dependent version of notify_delayed() +// that is simpler, and does not trigger the deprecation warning one would get + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_clock.h b/ext/systemc/src/sysc/communication/sc_clock.h new file mode 100644 index 000000000..634936ce6 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_clock.h @@ -0,0 +1,275 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_clock.h -- The clock channel. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_CLOCK_H +#define SC_CLOCK_H + + +#include "sysc/kernel/sc_module.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/tracing/sc_trace.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_clock +// +// The clock channel. +// ---------------------------------------------------------------------------- + +class sc_clock + : public sc_signal<bool,SC_ONE_WRITER> +{ + typedef sc_signal<bool,SC_ONE_WRITER> base_type; +public: + + friend class sc_clock_posedge_callback; + friend class sc_clock_negedge_callback; + + // constructors + + sc_clock(); + + explicit sc_clock( const char* name_ ); + + sc_clock( const char* name_, + const sc_time& period_, + double duty_cycle_ = 0.5, + const sc_time& start_time_ = SC_ZERO_TIME, + bool posedge_first_ = true ); + + sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_ = 0.5 ); + + sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_, + double start_time_v_, + sc_time_unit start_time_tu_, + bool posedge_first_ = true ); + + // for backward compatibility with 1.0 + sc_clock( const char* name_, + double period_, // in default time units + double duty_cycle_ = 0.5, + double start_time_ = 0.0, // in default time units + bool posedge_first_ = true ); + + // destructor (does nothing) + virtual ~sc_clock(); + + virtual void register_port( sc_port_base&, const char* if_type ); + virtual void write( const bool& ); + + // get the period + const sc_time& period() const + { return m_period; } + + // get the duty cycle + double duty_cycle() const + { return m_duty_cycle; } + + + // get the current time / clock characteristics + + bool posedge_first() const + { return m_posedge_first; } + + sc_time start_time() const + { return m_start_time; } + + static const sc_time& time_stamp(); + + virtual const char* kind() const + { return "sc_clock"; } + + +#if 0 // @@@@#### REMOVE + // for backward compatibility with 1.0 + + sc_signal_in_if<bool>& signal() + { return *this; } + + const sc_signal_in_if<bool>& signal() const + { return *this; } + + static void start( const sc_time& duration ) + { sc_start( duration ); } + + static void start( double v, sc_time_unit tu ) + { sc_start( sc_time(v, tu) ); } + + static void start( double duration = -1 ) + { sc_start( duration ); } + + static void stop() + { sc_stop(); } +#endif + +protected: + + void before_end_of_elaboration(); + + // processes + void posedge_action(); + void negedge_action(); + + + // error reporting + void report_error( const char* id, const char* add_msg = 0 ) const; + + + void init( const sc_time&, double, const sc_time&, bool ); + + bool is_clock() const { return true; } + +protected: + + sc_time m_period; // the period of this clock + double m_duty_cycle; // the duty cycle (fraction of period) + sc_time m_start_time; // the start time of the first edge + bool m_posedge_first; // true if first edge is positive + sc_time m_posedge_time; // time till next positive edge + sc_time m_negedge_time; // time till next negative edge + + sc_event m_next_posedge_event; + sc_event m_next_negedge_event; + +private: + + // disabled + sc_clock( const sc_clock& ); + sc_clock& operator = ( const sc_clock& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// processes + +inline +void +sc_clock::posedge_action() +{ + m_next_negedge_event.notify_internal( m_negedge_time ); + m_new_val = true; + request_update(); +} + +inline +void +sc_clock::negedge_action() +{ + m_next_posedge_event.notify_internal( m_posedge_time ); + m_new_val = false; + request_update(); +} + + +// ---------------------------------------------------------------------------- + +class sc_clock_posedge_callback { +public: + sc_clock_posedge_callback(sc_clock* target_p) : m_target_p(target_p) {} + inline void operator () () { m_target_p->posedge_action(); } + protected: + sc_clock* m_target_p; +}; + +class sc_clock_negedge_callback { + public: + sc_clock_negedge_callback(sc_clock* target_p) : m_target_p(target_p) {} + inline void operator () () { m_target_p->negedge_action(); } + protected: + sc_clock* m_target_p; +}; + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 3 October, 2003 + Description of Modification: sc_clock inherits from sc_signal<bool> only + instead of sc_signal_in_if<bool> and sc_module. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +//$Log: sc_clock.h,v $ +//Revision 1.5 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.4 2011/08/24 22:05:35 acg +// Torsten Maehne: initialization changes to remove warnings. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.5 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +//Revision 1.4 2006/01/24 20:43:25 acg +// Andy Goodrich: convert notify_delayed() calls into notify_internal() calls. +// notify_internal() is an implementation dependent version of notify_delayed() +// that is simpler, and does not trigger the deprecation warning one would get +// using notify_delayed(). +// +//Revision 1.3 2006/01/18 21:42:26 acg +//Andy Goodrich: Changes for check writer support, and tightening up sc_clock +//port usage. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.14 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_clock_ports.h b/ext/systemc/src/sysc/communication/sc_clock_ports.h new file mode 100644 index 000000000..70ac80c1d --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_clock_ports.h @@ -0,0 +1,72 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_clock_ports.h -- The clock ports. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_CLOCK_PORTS_H +#define SC_CLOCK_PORTS_H + + +#include "sysc/communication/sc_signal_ports.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// The clock ports. +// +// (Provided for backward compatibility reasons.) +// ---------------------------------------------------------------------------- + +typedef sc_in<bool> sc_in_clk; +typedef sc_inout<bool> sc_inout_clk; +typedef sc_out<bool> sc_out_clk; + +} // namespace sc_core + +//$Log: sc_clock_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_communication_ids.h b/ext/systemc/src/sysc/communication/sc_communication_ids.h new file mode 100644 index 000000000..fe9995775 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_communication_ids.h @@ -0,0 +1,164 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_communication_ids.h -- Report ids for the communication code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_COMMUNICATION_IDS_H +#define SC_COMMUNICATION_IDS_H + + +#include "sysc/utils/sc_report.h" + + +// ---------------------------------------------------------------------------- +// Report ids (communication) +// +// Report ids in the range of 100-199. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +namespace sc_core { + extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +} // namespace sc_core +#endif + +SC_DEFINE_MESSAGE( SC_ID_PORT_OUTSIDE_MODULE_, 100, + "port specified outside of module" ) +SC_DEFINE_MESSAGE( SC_ID_CLOCK_PERIOD_ZERO_, 101, + "sc_clock period is zero" ) +SC_DEFINE_MESSAGE( SC_ID_CLOCK_HIGH_TIME_ZERO_, 102, + "sc_clock high time is zero" ) +SC_DEFINE_MESSAGE( SC_ID_CLOCK_LOW_TIME_ZERO_, 103, + "sc_clock low time is zero" ) +SC_DEFINE_MESSAGE( SC_ID_MORE_THAN_ONE_FIFO_READER_, 104, + "sc_fifo<T> cannot have more than one reader" ) +SC_DEFINE_MESSAGE( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 105, + "sc_fifo<T> cannot have more than one writer" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_FIFO_SIZE_, 106, + "sc_fifo<T> must have a size of at least 1" ) +SC_DEFINE_MESSAGE( SC_ID_BIND_IF_TO_PORT_, 107, + "bind interface to port failed" ) +SC_DEFINE_MESSAGE( SC_ID_BIND_PORT_TO_PORT_, 108, + "bind parent port to port failed" ) +SC_DEFINE_MESSAGE( SC_ID_COMPLETE_BINDING_, 109, + "complete binding failed" ) +SC_DEFINE_MESSAGE( SC_ID_INSERT_PORT_, 110, + "insert port failed" ) +SC_DEFINE_MESSAGE( SC_ID_REMOVE_PORT_, 111, + "remove port failed" ) +SC_DEFINE_MESSAGE( SC_ID_GET_IF_, 112, + "get interface failed" ) +SC_DEFINE_MESSAGE( SC_ID_INSERT_PRIM_CHANNEL_, 113, + "insert primitive channel failed" ) +SC_DEFINE_MESSAGE( SC_ID_REMOVE_PRIM_CHANNEL_, 114, + "remove primitive channel failed" ) +SC_DEFINE_MESSAGE( SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, 115, + "sc_signal<T> cannot have more than one driver" ) +SC_DEFINE_MESSAGE( SC_ID_NO_DEFAULT_EVENT_, 116, + "channel doesn't have a default event" ) +SC_DEFINE_MESSAGE( SC_ID_RESOLVED_PORT_NOT_BOUND_, 117, + "resolved port not bound to resolved signal" ) +SC_DEFINE_MESSAGE( SC_ID_FIND_EVENT_, 118, + "find event failed" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_SEMAPHORE_VALUE_, 119, + "sc_semaphore requires an initial value >= 0" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_HAS_NO_INTERFACE_, 120, + "sc_export instance has no interface" ) +SC_DEFINE_MESSAGE( SC_ID_INSERT_EXPORT_, 121, + "insert sc_export failed" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_NOT_REGISTERED_, 123, + "remove sc_export failed, sc_export not registered" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_NOT_BOUND_AFTER_CONSTRUCTION_, 124, + "sc_export instance not bound to interface at end of construction" ) +SC_DEFINE_MESSAGE( SC_ID_ATTEMPT_TO_WRITE_TO_CLOCK_, 125, + "attempt to write the value of an sc_clock instance" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_ALREADY_BOUND_, 126, + "sc_export instance already bound" ) +SC_DEFINE_MESSAGE( SC_ID_OPERATION_ON_NON_SPECIALIZED_SIGNAL_, 127, + "attempted specalized signal operation on non-specialized signal" ) +SC_DEFINE_MESSAGE( SC_ID_ATTEMPT_TO_BIND_CLOCK_TO_OUTPUT_, 128, + "attempted to bind sc_clock instance to sc_inout or sc_out" ) +SC_DEFINE_MESSAGE( SC_ID_NO_ASYNC_UPDATE_, 129, + "this build has no asynchronous update support" ) + +/* +$Log: sc_communication_ids.h,v $ +Revision 1.5 2011/08/26 20:45:39 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.4 2011/04/19 02:36:26 acg + Philipp A. Hartmann: new aysnc_update and mutex support. + +Revision 1.3 2011/02/18 20:23:45 acg + Andy Goodrich: Copyright update. + +Revision 1.2 2011/02/14 17:50:16 acg + Andy Goodrich: testing for sc_port and sc_export instantiations during + end of elaboration and issuing appropriate error messages. + +Revision 1.1.1.1 2006/12/15 20:20:04 acg +SystemC 2.3 + +Revision 1.5 2006/01/25 00:31:11 acg + Andy Goodrich: Changed over to use a standard message id of + SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. + +Revision 1.4 2006/01/24 20:46:31 acg +Andy Goodrich: changes to eliminate use of deprecated features. For instance, +using notify(SC_ZERO_TIME) in place of notify_delayed(). + +Revision 1.3 2006/01/18 21:42:26 acg +Andy Goodrich: Changes for check writer support, and tightening up sc_clock +port usage. + +Revision 1.2 2006/01/03 23:18:26 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:43 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.12 2005/04/03 22:52:51 acg +Namespace changes. + +Revision 1.11 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.10 2004/10/28 00:21:48 acg +Added check that sc_export instances are not bound twice. + +Revision 1.9 2004/09/27 21:02:54 acg +Andy Goodrich - Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments will appear in + checked out source. + +*/ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_event_finder.cpp b/ext/systemc/src/sysc/communication/sc_event_finder.cpp new file mode 100644 index 000000000..25d16a1f5 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_finder.cpp @@ -0,0 +1,113 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_finder.cpp -- + + Original Author: Martin Janssen, Synopsys, Inc. + Stan Y. Liao, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_event_finder.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_finder +// +// Event finder base class. +// ---------------------------------------------------------------------------- + +// error reporting + +void +sc_event_finder::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: port '%s' (%s)", + add_msg, m_port.name(), m_port.kind() ); + } else { + std::sprintf( msg, "port '%s' (%s)", m_port.name(), m_port.kind() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// constructor + +sc_event_finder::sc_event_finder( const sc_port_base& port_ ) +: m_port( port_ ) +{ +} + + +// destructor (does nothing) + +sc_event_finder::~sc_event_finder() +{} + +} // namespace sc_core + +// $Log: sc_event_finder.cpp,v $ +// Revision 1.3 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.7 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +// Revision 1.6 2006/02/02 21:26:34 acg +// Andy Goodrich: pulled out the check I just stuck into the +// sc_event_finder::free_instances() method. It turns out the LRM says that +// sc_event_finder instances are valid as long as the sc_module hierarchy is +// valid, so we can't give the user a call to free the instances. +// +// Revision 1.5 2006/02/02 21:10:52 acg +// Andy Goodrich: added check for end of elaboration to the static method +// sc_event_finder::free_instances(). This will allow the method to be +// made public if that is desired. +// +// Revision 1.4 2006/02/02 20:43:09 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +// Revision 1.3 2006/01/13 18:47:41 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_event_finder.h b/ext/systemc/src/sysc/communication/sc_event_finder.h new file mode 100644 index 000000000..15205553f --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_finder.h @@ -0,0 +1,178 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_finder.h -- + + Original Author: Martin Janssen, Synopsys, Inc. + Stan Y. Liao, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_EVENT_FINDER +#define SC_EVENT_FINDER + + +#include "sysc/communication/sc_port.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_finder +// +// Event finder base class. +// ---------------------------------------------------------------------------- + +class sc_event_finder +{ + friend class sc_simcontext; + +public: + + const sc_port_base& port() const + { return m_port; } + + // destructor (does nothing) + virtual ~sc_event_finder(); + + virtual const sc_event& find_event( sc_interface* if_p = 0 ) const = 0; + +protected: + + // constructor + sc_event_finder( const sc_port_base& ); + + // error reporting + void report_error( const char* id, const char* add_msg = 0 ) const; + + +private: + const sc_port_base& m_port; // port providing the event. + +private: + + // disabled + sc_event_finder(); + sc_event_finder( const sc_event_finder& ); + sc_event_finder& operator = ( const sc_event_finder& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_finder_t<IF> +// +// Interface specific event finder class. +// ---------------------------------------------------------------------------- + +template <class IF> +class sc_event_finder_t +: public sc_event_finder +{ +public: + + // constructor + + sc_event_finder_t( const sc_port_base& port_, + const sc_event& (IF::*event_method_) () const ) + : sc_event_finder( port_ ), m_event_method( event_method_ ) + {} + + // destructor (does nothing) + + virtual ~sc_event_finder_t() + {} + + virtual const sc_event& find_event( sc_interface* if_p = 0 ) const; + +private: + + const sc_event& (IF::*m_event_method) () const; + +private: + + // disabled + sc_event_finder_t(); + sc_event_finder_t( const sc_event_finder_t<IF>& ); + sc_event_finder_t<IF>& operator = ( const sc_event_finder_t<IF>& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template <class IF> +inline +const sc_event& +sc_event_finder_t<IF>::find_event( sc_interface* if_p ) const +{ + const IF* iface = ( if_p ) ? DCAST<const IF*>( if_p ) : + DCAST<const IF*>( port().get_interface() ); + if( iface == 0 ) { + report_error( SC_ID_FIND_EVENT_, "port is not bound" ); + } + return (CCAST<IF*>( iface )->*m_event_method) (); +} + +} // namespace sc_core + +//$Log: sc_event_finder.h,v $ +//Revision 1.3 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +//Revision 1.3 2006/02/02 20:43:09 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_event_queue.cpp b/ext/systemc/src/sysc/communication/sc_event_queue.cpp new file mode 100644 index 000000000..7e1ebc864 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_queue.cpp @@ -0,0 +1,146 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_queue.cpp -- Event Queue Support + + Original Author: Stuart Swan, Cadence Inc. + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_event_queue.h" +#include "sysc/kernel/sc_method_process.h" + +namespace sc_core { + +static int +sc_time_compare( const void* p1, const void* p2 ) +{ + const sc_time* t1 = static_cast<const sc_time*>( p1 ); + const sc_time* t2 = static_cast<const sc_time*>( p2 ); + + if( *t1 < *t2 ) { + return 1; + } else if( *t1 > *t2 ) { + return -1; + } else { + return 0; + } +} + +sc_event_queue::sc_event_queue( sc_module_name name_ ) + : sc_module( name_ ), + m_ppq( 128, sc_time_compare ), + m_e( (std::string(SC_KERNEL_EVENT_PREFIX)+"_event").c_str() ), + m_change_stamp(0), + m_pending_delta(0) +{ + SC_METHOD( fire_event ); + sensitive << m_e; + dont_initialize(); +} + +sc_event_queue::~sc_event_queue() +{ + while (m_ppq.size() > 0) { + delete m_ppq.extract_top(); + } +} + +void sc_event_queue::cancel_all() +{ + m_pending_delta = 0; + while( m_ppq.size() > 0 ) + delete m_ppq.extract_top(); + m_e.cancel(); +} + +void sc_event_queue::notify (const sc_time& when) +{ + m_change_stamp = simcontext()->change_stamp(); + sc_time* t = new sc_time( when+sc_time_stamp() ); + if ( m_ppq.size()==0 || *t < *m_ppq.top() ) { + m_e.notify( when ); + } + m_ppq.insert( t ); +} + +void sc_event_queue::fire_event() +{ + if ( m_ppq.empty() ) { // event has been cancelled + return; + } + sc_time* t = m_ppq.extract_top(); + assert( *t==sc_time_stamp() ); + delete t; + + if ( m_ppq.size() > 0 ) { + m_e.notify( *m_ppq.top() - sc_time_stamp() ); + } +} + +} // namespace sc_core + +// $Log: sc_event_queue.cpp,v $ +// Revision 1.9 2011/08/26 22:45:53 acg +// Torsten Maehne: remove redundant initialization assignment. +// +// Revision 1.8 2011/08/26 21:44:58 acg +// Andy Goodrich: fix internal event naming. +// +// Revision 1.7 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/08/24 22:05:35 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/04/08 18:22:46 acg +// Philipp A. Hartmann: use the context of the primitive channel to get +// the change stamp value. +// +// Revision 1.4 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2010/07/22 20:02:30 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.5 2006/11/28 20:30:48 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +// Revision 1.4 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. + +// taf diff --git a/ext/systemc/src/sysc/communication/sc_event_queue.h b/ext/systemc/src/sysc/communication/sc_event_queue.h new file mode 100644 index 000000000..4438de9ef --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_queue.h @@ -0,0 +1,181 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_queue.h -- Event Queue Facility Definitions + + Original Author: Ulli Holtmann, Synopsys, Inc. + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_EVENT_QUEUE_H +#define SC_EVENT_QUEUE_H + + +/* + Class sc_event_queue + + A queue that can contain any number of pending notifications. + The queue has a similiar interface like an sc_event but has different + semantics: it can carry any number of pending notification. The + general rule is that _every_ call to notify() will cause a + corresponding trigger at the specified wall-clock time that can be + observed (the only exception is when notifications are explicitly + cancelled). + + If multiple notifications are pending at the same wall-clock + time, then the event queue will trigger in different delta cycles + in order to ensure that sensitive processes can notice each + trigger. The first trigger happens in the earliest delta cycle + possible which is the same behavior as a normal timed event. + +*/ + +#include "sysc/communication/sc_interface.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/communication/sc_port.h" + +namespace sc_core { + + +// --------------------------------------------------------------------------- +// sc_event_queue_if +// --------------------------------------------------------------------------- + +class sc_event_queue_if : public virtual sc_interface +{ +public: + virtual void notify (double when, sc_time_unit base) =0; + virtual void notify (const sc_time& when) =0; + virtual void cancel_all() =0; +}; + +// --------------------------------------------------------------------------- +// sc_event_queue: a queue that can contain any number of pending +// delta, or timed events. +// --------------------------------------------------------------------------- + +class sc_event_queue: + public sc_event_queue_if, + public sc_module +{ + public: + + SC_HAS_PROCESS( sc_event_queue ); + + sc_event_queue( sc_module_name name_ = sc_gen_unique_name("event_queue") ); + ~sc_event_queue(); + + // API of sc_object + inline virtual const char* kind() const { return "sc_event_queue"; } + + // + // API of sc_event_queue_if + // + inline virtual void notify (double when, sc_time_unit base); + virtual void notify (const sc_time& when); + virtual void cancel_all(); + + // + // API for using the event queue in processes + // + + // get the default event + inline virtual const sc_event& default_event() const; + +/* + // + // Possible extensions: + // + + // Cancel an events at a specific time + void cancel (const sc_time& when); + void cancel (double when, sc_time_unit base); + + // How many events are pending altogether? + unsigned pending() const; + + // How many events are pending at the specific time? + unsigned pending(const sc_time& when) const; + unsigned pending(double when, sc_time_unit base) const; +*/ + + private: + void fire_event(); + + private: + sc_ppq<sc_time*> m_ppq; + sc_event m_e; + sc_dt::uint64 m_change_stamp; + unsigned m_pending_delta; +}; + +inline +void sc_event_queue::notify (double when, sc_time_unit base ) +{ + notify( sc_time(when,base) ); +} + +inline +const sc_event& sc_event_queue::default_event() const +{ + return m_e; +} + + +// +// Using event queue as a port +// +typedef sc_port<sc_event_queue_if,1,SC_ONE_OR_MORE_BOUND> sc_event_queue_port; + +} // namespace sc_core + +// $Log: sc_event_queue.h,v $ +// Revision 1.5 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2008/05/20 16:45:52 acg +// Andy Goodrich: changed which unique name generator is used from the +// global one to the one for sc_modules. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/11/28 20:30:48 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +#endif // SC_EVENT_QUEUE_H diff --git a/ext/systemc/src/sysc/communication/sc_export.cpp b/ext/systemc/src/sysc/communication/sc_export.cpp new file mode 100644 index 000000000..2da7a1533 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_export.cpp @@ -0,0 +1,305 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_export.cpp -- + + Original Author: Bishnupriya Bhattachary, Cadence, Design Systems, + 25 August, 2003 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_export.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object_int.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_export_base +// +// ---------------------------------------------------------------------------- + +sc_export_base::sc_export_base() : sc_object(sc_gen_unique_name("export")) +{ + simcontext()->get_export_registry()->insert(this); +} + +sc_export_base::sc_export_base(const char* name_) : sc_object(name_) +{ + simcontext()->get_export_registry()->insert(this); +} + +sc_export_base::~sc_export_base() +{ + simcontext()->get_export_registry()->remove(this); +} + +// called by construction_done() (does nothing by default) + +void +sc_export_base::before_end_of_elaboration() +{ +} + +// called when construction is done + +void +sc_export_base::construction_done() +{ + if ( get_interface() == 0 ) + { + report_error( SC_ID_SC_EXPORT_NOT_BOUND_AFTER_CONSTRUCTION_, 0); + } + + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + before_end_of_elaboration(); +} + +// called by elaboration_done() (does nothing by default) + +void +sc_export_base::end_of_elaboration() +{} + +// called when elaboration is done + +void +sc_export_base::elaboration_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_elaboration(); +} + +// called by start_simulation (does nothing) + +void +sc_export_base::start_of_simulation() +{} + +// called before simulation starts + +void +sc_export_base::start_simulation() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + start_of_simulation(); +} + +// called by simulation_done (does nothing) + +void +sc_export_base::end_of_simulation() +{} + +// called after simulation ends + +void +sc_export_base::simulation_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_simulation(); +} + +void +sc_export_base::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: export '%s' (%s)", add_msg, name(), kind() ); + } else { + std::sprintf( msg, "export '%s' (%s)", name(), kind() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_export_registry +// +// Registry for all exports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_export_registry::insert( sc_export_base* export_ ) +{ + if( sc_is_running() ) { + export_->report_error(SC_ID_INSERT_EXPORT_, "simulation running"); + } + + if( m_simc->elaboration_done() ) { + export_->report_error(SC_ID_INSERT_EXPORT_, "elaboration done"); + } + + +#ifdef DEBUG_SYSTEMC + // check if port_ is already inserted + for( int i = size() - 1; i >= 0; -- i ) { + if( export_ == m_export_vec[i] ) { + export_->report_error( SC_ID_INSERT_EXPORT_, + "export already inserted "); + } + } +#endif + +/* + //TBD: maybe we want to do this stuf for later + + // append the port to the current module's vector of ports + sc_module* curr_module = m_simc->hierarchy_curr(); + if( curr_module == 0 ) { + port_->report_error( SC_ID_PORT_OUTSIDE_MODULE_ ); + } + curr_module->append_port( port_ ); +*/ + + // insert + m_export_vec.push_back( export_ ); +} + +void +sc_export_registry::remove( sc_export_base* export_ ) +{ + if (size()==0) return; + int i; + for( i = size() - 1; i >= 0; -- i ) { + if( export_ == m_export_vec[i] ) { + break; + } + } + if( i == -1 ) { + export_->report_error( SC_ID_SC_EXPORT_NOT_REGISTERED_ ); + } + + // remove + m_export_vec[i] = m_export_vec[size() - 1]; + m_export_vec.resize(size()-1); +} + +// constructor + +sc_export_registry::sc_export_registry( sc_simcontext& simc_ ) +: m_construction_done(0), + m_export_vec(), + m_simc( &simc_ ) +{ +} + + +// destructor + +sc_export_registry::~sc_export_registry() +{ +} + +// called when construction is done + +bool +sc_export_registry::construction_done() +{ + if( m_construction_done == size() ) + // nothing has been updated + return true; + + for( int i = size()-1; i >= m_construction_done; --i ) { + m_export_vec[i]->construction_done(); + } + + m_construction_done = size(); + return false; +} + +// called when elaboration is done + +void +sc_export_registry::elaboration_done() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_export_vec[i]->elaboration_done(); + } +} + +// called before simulation begins + +void +sc_export_registry::start_simulation() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_export_vec[i]->start_simulation(); + } +} + +void +sc_export_registry::simulation_done() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_export_vec[i]->simulation_done(); + } +} + +} // namespace sc_core + +// $Log: sc_export.cpp,v $ +// Revision 1.8 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.6 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.5 2011/02/18 20:31:05 acg +// Philipp A. Hartmann: added error messages for calls that cannot be done +// after elaboration. +// +// Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.3 2011/02/18 20:07:04 acg +// Philipp A. Hartmann: Patch to revert to sprintf from snprintf to keep +// some versions of MSVC happy. +// +// Revision 1.2 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_export.h b/ext/systemc/src/sysc/communication/sc_export.h new file mode 100644 index 000000000..81edc8cc2 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_export.h @@ -0,0 +1,299 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_export.h -- Base classes of all export classes. + + Original Author: Andy Goodrich, Forte Design Systems + Bishnupriya Bhattacharya, Cadence Design Systems + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_EXPORT_H +#define SC_EXPORT_H +#include <typeinfo> + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_interface.h" +#include "sysc/kernel/sc_object.h" + +#if ! defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_VIRTUAL_ virtual +#else +# define SC_VIRTUAL_ /* non-virtual */ +#endif + +namespace sc_core { + +//============================================================================= +// CLASS : sc_export_base +// +// Abstract base class for class sc_export<IF>. +//============================================================================= + +class sc_export_base : public sc_object +{ + friend class sc_export_registry; +public: + + // typedefs + + typedef sc_export_base this_type; + +public: + + virtual sc_interface* get_interface() = 0; + virtual const sc_interface* get_interface() const = 0; + +protected: + + // constructors + + sc_export_base(); + sc_export_base(const char* name); + + // destructor + + virtual ~sc_export_base(); + +protected: + + // called when construction is done + virtual void before_end_of_elaboration(); + + // called when elaboration is done (does nothing by default) + virtual void end_of_elaboration(); + + // called before simulation starts (does nothing by default) + virtual void start_of_simulation(); + + // called after simulation ends (does nothing) + virtual void end_of_simulation(); + + virtual const char* if_typename() const = 0; + + // error reporting + void report_error( const char* id, const char* add_msg = 0) const; + +private: + + void construction_done(); + void elaboration_done(); + void start_simulation(); + void simulation_done(); + + // disabled + sc_export_base(const this_type&); + this_type& operator = (const this_type& ); + +}; + +//============================================================================= +// CLASS : sc_export +// +// Generic export class for other export classes. This +// class provides a binding point for access to an interface. +//============================================================================= +template<class IF> +class sc_export : public sc_export_base +{ + typedef sc_export<IF> this_type; + +public: // constructors: + sc_export() : sc_export_base() + { + m_interface_p = 0; + } + + explicit sc_export( const char* name_ ) : sc_export_base(name_) + { + m_interface_p = 0; + } + +public: // destructor: + virtual ~sc_export() + { + } + +public: // interface access: + + virtual sc_interface* get_interface() + { + return m_interface_p; + } + + virtual const sc_interface* get_interface() const + { + return m_interface_p; + } + + const IF* operator -> () const { + if ( m_interface_p == 0 ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_HAS_NO_INTERFACE_,name()); + } + return m_interface_p; + } + + IF* operator -> () { + if ( m_interface_p == 0 ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_HAS_NO_INTERFACE_,name()); + } + return m_interface_p; + } + + operator IF& () + { + if ( m_interface_p == 0 ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_HAS_NO_INTERFACE_,name()); + } + return *m_interface_p; + } + operator const IF&() const + { return *const_cast<this_type*>(this); } + + +public: // binding: + SC_VIRTUAL_ void bind( IF& interface_ ) + { + if ( m_interface_p ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_ALREADY_BOUND_,name()); + } + else + { + m_interface_p = &interface_; + } + } + + void operator () ( IF& interface_ ) + { + this->bind(interface_); + } + +public: // identification: + virtual const char* kind() const { return "sc_export"; } + +protected: + const char* if_typename() const { + return typeid( IF ).name(); + } + +private: // disabled + sc_export( const this_type& ); + this_type& operator = ( const this_type& ); + +protected: // data fields: + IF* m_interface_p; // Interface this port provides. +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_export_registry +// +// Registry for all exports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_export_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_export_base* ); + void remove( sc_export_base* ); + + int size() const + { return m_export_vec.size(); } + +private: + + // constructor + explicit sc_export_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_export_registry(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + +private: + + int m_construction_done; + std::vector<sc_export_base*> m_export_vec; + sc_simcontext* m_simc; + +private: + + // disabled + sc_export_registry(); + sc_export_registry( const sc_export_registry& ); + sc_export_registry& operator = ( const sc_export_registry& ); +}; + +} // namespace sc_core + +#undef SC_VIRTUAL_ + +// $Log: sc_export.h,v $ +// Revision 1.7 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.5 2011/04/02 00:02:14 acg +// Philipp A. Hartmann: add const overload for sc_export::operator IF& +// +// Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.3 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_fifo.h b/ext/systemc/src/sysc/communication/sc_fifo.h new file mode 100644 index 000000000..868c0304e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_fifo.h @@ -0,0 +1,479 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fifo.h -- The sc_fifo<T> primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_FIFO_H +#define SC_FIFO_H + + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/communication/sc_fifo_ifs.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/tracing/sc_trace.h" +#include <typeinfo> + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo<T> +// +// The sc_fifo<T> primitive channel class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo +: public sc_fifo_in_if<T>, + public sc_fifo_out_if<T>, + public sc_prim_channel +{ +public: + + // constructors + + explicit sc_fifo( int size_ = 16 ) + : sc_prim_channel( sc_gen_unique_name( "fifo" ) ), + m_data_read_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), + m_data_written_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) + { init( size_ ); } + + explicit sc_fifo( const char* name_, int size_ = 16 ) + : sc_prim_channel( name_ ), + m_data_read_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), + m_data_written_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) + { init( size_ ); } + + + // destructor + + virtual ~sc_fifo() + { delete [] m_buf; } + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + + // blocking read + virtual void read( T& ); + virtual T read(); + + // non-blocking read + virtual bool nb_read( T& ); + + + // get the number of available samples + + virtual int num_available() const + { return ( m_num_readable - m_num_read ); } + + + // get the data written event + + virtual const sc_event& data_written_event() const + { return m_data_written_event; } + + + // blocking write + virtual void write( const T& ); + + // non-blocking write + virtual bool nb_write( const T& ); + + + // get the number of free spaces + + virtual int num_free() const + { return ( m_size - m_num_readable - m_num_written ); } + + + // get the data read event + + virtual const sc_event& data_read_event() const + { return m_data_read_event; } + + + // other methods + + operator T () + { return read(); } + + + sc_fifo<T>& operator = ( const T& a ) + { write( a ); return *this; } + + + void trace( sc_trace_file* tf ) const; + + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_fifo"; } + +protected: + + virtual void update(); + + // support methods + + void init( int ); + + void buf_init( int ); + bool buf_write( const T& ); + bool buf_read( T& ); + +protected: + + int m_size; // size of the buffer + T* m_buf; // the buffer + int m_free; // number of free spaces + int m_ri; // index of next read + int m_wi; // index of next write + + sc_port_base* m_reader; // used for static design rule checking + sc_port_base* m_writer; // used for static design rule checking + + 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 + + sc_event m_data_read_event; + sc_event m_data_written_event; + +private: + + // disabled + sc_fifo( const sc_fifo<T>& ); + sc_fifo& operator = ( const sc_fifo<T>& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template <class T> +inline +void +sc_fifo<T>::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + std::string nm( if_typename_ ); + if( nm == typeid( sc_fifo_in_if<T> ).name() || + nm == typeid( sc_fifo_blocking_in_if<T> ).name() + ) { + // only one reader can be connected + if( m_reader != 0 ) { + SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 ); + } + m_reader = &port_; + } else if( nm == typeid( sc_fifo_out_if<T> ).name() || + nm == typeid( sc_fifo_blocking_out_if<T> ).name() + ) { + // only one writer can be connected + if( m_writer != 0 ) { + SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 ); + } + m_writer = &port_; + } + else + { + SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, + "sc_fifo<T> port not recognized" ); + } +} + + +// blocking read + +template <class T> +inline +void +sc_fifo<T>::read( T& val_ ) +{ + while( num_available() == 0 ) { + sc_core::wait( m_data_written_event ); + } + m_num_read ++; + buf_read( val_ ); + request_update(); +} + +template <class T> +inline +T +sc_fifo<T>::read() +{ + T tmp; + read( tmp ); + return tmp; +} + +// non-blocking read + +template <class T> +inline +bool +sc_fifo<T>::nb_read( T& val_ ) +{ + if( num_available() == 0 ) { + return false; + } + m_num_read ++; + buf_read( val_ ); + request_update(); + return true; +} + + +// blocking write + +template <class T> +inline +void +sc_fifo<T>::write( const T& val_ ) +{ + while( num_free() == 0 ) { + sc_core::wait( m_data_read_event ); + } + m_num_written ++; + buf_write( val_ ); + request_update(); +} + +// non-blocking write + +template <class T> +inline +bool +sc_fifo<T>::nb_write( const T& val_ ) +{ + if( num_free() == 0 ) { + return false; + } + m_num_written ++; + buf_write( val_ ); + request_update(); + return true; +} + + +template <class T> +inline +void +sc_fifo<T>::trace( sc_trace_file* tf ) const +{ +#if defined(DEBUG_SYSTEMC) + char buf[32]; + std::string nm = name(); + for( int i = 0; i < m_size; ++ i ) { + std::sprintf( buf, "_%d", i ); + sc_trace( tf, m_buf[i], nm + buf ); + } +#endif +} + + +template <class T> +inline +void +sc_fifo<T>::print( ::std::ostream& os ) const +{ + if( m_free != m_size ) { + int i = m_ri; + do { + os << m_buf[i] << ::std::endl; + i = ( i + 1 ) % m_size; + } while( i != m_wi ); + } +} + +template <class T> +inline +void +sc_fifo<T>::dump( ::std::ostream& os ) const +{ + os << "name = " << name() << ::std::endl; + if( m_free != m_size ) { + int i = m_ri; + int j = 0; + do { + os << "value[" << i << "] = " << m_buf[i] << ::std::endl; + i = ( i + 1 ) % m_size; + j ++; + } while( i != m_wi ); + } +} + + +template <class T> +inline +void +sc_fifo<T>::update() +{ + if( m_num_read > 0 ) { + m_data_read_event.notify(SC_ZERO_TIME); + } + + if( m_num_written > 0 ) { + m_data_written_event.notify(SC_ZERO_TIME); + } + + m_num_readable = m_size - m_free; + m_num_read = 0; + m_num_written = 0; +} + + +// support methods + +template <class T> +inline +void +sc_fifo<T>::init( int size_ ) +{ + buf_init( size_ ); + + m_reader = 0; + m_writer = 0; + + m_num_readable = 0; + m_num_read = 0; + m_num_written = 0; +} + + +template <class T> +inline +void +sc_fifo<T>::buf_init( int size_ ) +{ + if( size_ <= 0 ) { + SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 ); + } + m_size = size_; + m_buf = new T[m_size]; + m_free = m_size; + m_ri = 0; + m_wi = 0; +} + +template <class T> +inline +bool +sc_fifo<T>::buf_write( const T& val_ ) +{ + if( m_free == 0 ) { + return false; + } + m_buf[m_wi] = val_; + m_wi = ( m_wi + 1 ) % m_size; + m_free --; + return true; +} + +template <class T> +inline +bool +sc_fifo<T>::buf_read( T& val_ ) +{ + if( m_free == m_size ) { + return false; + } + val_ = m_buf[m_ri]; + m_buf[m_ri] = T(); // clear entry for boost::shared_ptr, et al. + m_ri = ( m_ri + 1 ) % m_size; + m_free ++; + return true; +} + + +// ---------------------------------------------------------------------------- + +template <class T> +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fifo<T>& a ) +{ + a.print( os ); + return os; +} + +} // namespace sc_core + +//$Log: sc_fifo.h,v $ +//Revision 1.6 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.5 2011/03/23 16:17:22 acg +// Andy Goodrich: hide the sc_events that are kernel related. +// +//Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.3 2009/10/14 19:05:40 acg +// Andy Goodrich: added check for blocking interfaces in addition to the +// combined blocking/nonblocking interface. +// +//Revision 1.2 2009/05/22 16:06:24 acg +// Andy Goodrich: process control updates. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/01/24 20:46:31 acg +//Andy Goodrich: changes to eliminate use of deprecated features. For instance, +//using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +//Revision 1.3 2006/01/13 20:41:59 acg +//Andy Goodrich: Changes to add port registration to the things that are +//checked when SC_NO_WRITE_CHECK is not defined. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.12 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.11 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_fifo_ifs.h b/ext/systemc/src/sysc/communication/sc_fifo_ifs.h new file mode 100644 index 000000000..915fc9f0c --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_fifo_ifs.h @@ -0,0 +1,209 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fifo_ifs.h -- The sc_fifo<T> interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_FIFO_IFS_H +#define SC_FIFO_IFS_H + + +#include "sysc/communication/sc_interface.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_nonblocking_in_if<T> +// +// The sc_fifo<T> input nonblocking interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_nonblocking_in_if +: virtual public sc_interface +{ +public: + + // non-blocking read + virtual bool nb_read( T& ) = 0; + + // get the data written event + virtual const sc_event& data_written_event() const = 0; +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_blocking_in_if<T> +// +// The sc_fifo<T> input blocking interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_blocking_in_if +: virtual public sc_interface +{ +public: + + // blocking read + virtual void read( T& ) = 0; + virtual T read() = 0; +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_in_if<T> +// +// The sc_fifo<T> input interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_in_if +: public sc_fifo_nonblocking_in_if<T>, + public sc_fifo_blocking_in_if<T> +{ +public: + + // get the number of available samples + virtual int num_available() const = 0; + +protected: + + // constructor + + sc_fifo_in_if() + {} + +private: + + // disabled + sc_fifo_in_if( const sc_fifo_in_if<T>& ); + sc_fifo_in_if<T>& operator = ( const sc_fifo_in_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_nonblocking_out_if<T> +// +// The sc_fifo<T> nonblocking output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_nonblocking_out_if +: virtual public sc_interface +{ +public: + + // non-blocking write + virtual bool nb_write( const T& ) = 0; + + // get the data read event + virtual const sc_event& data_read_event() const = 0; +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_blocking_out_if<T> +// +// The sc_fifo<T> blocking output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_blocking_out_if +: virtual public sc_interface +{ +public: + + // blocking write + virtual void write( const T& ) = 0; + +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_out_if<T> +// +// The sc_fifo<T> output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_out_if +: public sc_fifo_nonblocking_out_if<T>, + public sc_fifo_blocking_out_if<T> +{ +public: + + // get the number of free spaces + virtual int num_free() const = 0; + +protected: + + // constructor + + sc_fifo_out_if() + {} + +private: + + // disabled + sc_fifo_out_if( const sc_fifo_out_if<T>& ); + sc_fifo_out_if<T>& operator = ( const sc_fifo_out_if<T>& ); +}; + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharye, Cadence Design Systems, + 30 Jan, 2004 + Description of Modification: Split up the interfaces into blocking and + non blocking parts + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +//$Log: sc_fifo_ifs.h,v $ +//Revision 1.3 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +} // namespace sc_core + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_fifo_ports.h b/ext/systemc/src/sysc/communication/sc_fifo_ports.h new file mode 100644 index 000000000..72727d4be --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_fifo_ports.h @@ -0,0 +1,296 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fifo_ports.h -- The sc_fifo<T> port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_FIFO_PORTS_H +#define SC_FIFO_PORTS_H + + +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_fifo_ifs.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_in<T> +// +// The sc_fifo<T> input port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_in +: public sc_port<sc_fifo_in_if<T>,0,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_fifo_in_if<data_type> if_type; + typedef sc_port<if_type,0,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_fifo_in<data_type> this_type; + + typedef if_type in_if_type; + typedef sc_port_b<in_if_type> in_port_type; + +public: + + // constructors + + sc_fifo_in() + : base_type() + {} + + explicit sc_fifo_in( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_fifo_in( in_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_fifo_in( const char* name_, in_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_fifo_in( in_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_fifo_in( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_fifo_in() + {} + + + // interface access shortcut methods + + // blocking read + + void read( data_type& value_ ) + { (*this)->read( value_ ); } + + data_type read() + { return (*this)->read(); } + + + // non-blocking read + + bool nb_read( data_type& value_ ) + { return (*this)->nb_read( value_ ); } + + + // get the number of available samples + + int num_available() const + { return (*this)->num_available(); } + + + // get the data written event + + const sc_event& data_written_event() const + { return (*this)->data_written_event(); } + + + // use for static sensitivity to data written event + + sc_event_finder& data_written() const + { + return *new sc_event_finder_t<in_if_type>( + *this, &in_if_type::data_written_event ); + } + + virtual const char* kind() const + { return "sc_fifo_in"; } + +private: + + // disabled + sc_fifo_in( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_out<T> +// +// The sc_fifo<T> output port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_out +: public sc_port<sc_fifo_out_if<T>,0,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_fifo_out_if<data_type> if_type; + typedef sc_port<if_type,0,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_fifo_out<data_type> this_type; + + typedef if_type out_if_type; + typedef sc_port_b<out_if_type> out_port_type; + +public: + + // constructors + + sc_fifo_out() + : base_type() + {} + + explicit sc_fifo_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_fifo_out( out_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_fifo_out( const char* name_, out_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_fifo_out( out_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_out( const char* name_, out_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_fifo_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_fifo_out() + {} + + + // interface access shortcut methods + + // blocking write + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + + // non-blocking write + + bool nb_write( const data_type& value_ ) + { return (*this)->nb_write( value_ ); } + + + // get the number of free spaces + + int num_free() const + { return (*this)->num_free(); } + + + // get the data read event + + const sc_event& data_read_event() const + { return (*this)->data_read_event(); } + + + // use for static sensitivity to data read event + + sc_event_finder& data_read() const + { + return *new sc_event_finder_t<out_if_type>( + *this, &out_if_type::data_read_event ); + } + + virtual const char* kind() const + { return "sc_fifo_out"; } + +private: + + // disabled + sc_fifo_out( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +} // namespace sc_core + +//$Log: sc_fifo_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_host_mutex.h b/ext/systemc/src/sysc/communication/sc_host_mutex.h new file mode 100644 index 000000000..58f1c4c3a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_host_mutex.h @@ -0,0 +1,160 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_host_mutex.h -- A "real" mutex for the underlying host system + + Original Author: Philipp A. Hartmann, OFFIS + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_HOST_MUTEX_H_INCLUDED_ +#define SC_HOST_MUTEX_H_INCLUDED_ + +#ifndef SC_INCLUDE_WINDOWS_H +# define SC_INCLUDE_WINDOWS_H // include Windows.h, if needed +#endif +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/communication/sc_mutex_if.h" + +#if defined(WIN32) || defined(_WIN32) + +#define SC_MTX_TYPE_ CRITICAL_SECTION + +#define SC_MTX_INIT_( Mutex ) \ + InitializeCriticalSection( &(Mutex) ) +#define SC_MTX_LOCK_( Mutex ) \ + EnterCriticalSection( &(Mutex) ) +#define SC_MTX_UNLOCK_( Mutex ) \ + LeaveCriticalSection( &(Mutex) ) +#define SC_MTX_TRYLOCK_( Mutex ) \ + ( TryEnterCriticalSection( &(Mutex) ) != 0 ) +#define SC_MTX_DESTROY_( Mutex ) \ + DeleteCriticalSection( &(Mutex) ) + +#else // use pthread mutex + +#include <pthread.h> +#define SC_MTX_TYPE_ pthread_mutex_t + +#if defined(__hpux) +# define SC_PTHREAD_NULL_ cma_c_null +#else // !defined(__hpux) +# define SC_PTHREAD_NULL_ NULL +#endif + +#define SC_MTX_INIT_( Mutex ) \ + pthread_mutex_init( &(Mutex), SC_PTHREAD_NULL_ ) +#define SC_MTX_LOCK_( Mutex ) \ + pthread_mutex_lock( &(Mutex) ) +#define SC_MTX_UNLOCK_( Mutex ) \ + pthread_mutex_unlock( &(Mutex) ) + +#ifdef _XOPEN_SOURCE +# define SC_MTX_TRYLOCK_( Mutex ) \ + ( pthread_mutex_trylock( &(Mutex) ) == 0 ) +#else // no try_lock available +# define SC_MTX_TRYLOCK_( Mutex ) \ + ( false ) +#endif + +#define SC_MTX_DESTROY_( Mutex ) \ + pthread_mutex_destroy( &(Mutex) ) + +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_host_mutex +// +// The sc_host_mutex class, wrapping an OS mutex on the simulation host +// ---------------------------------------------------------------------------- + +class sc_host_mutex : public sc_mutex_if +{ + typedef SC_MTX_TYPE_ underlying_type; +public: + + // constructors and destructor + + sc_host_mutex() + { SC_MTX_INIT_(m_mtx); } + virtual ~sc_host_mutex() + { SC_MTX_DESTROY_(m_mtx); } + + + // interface methods + + // blocks until mutex could be locked + virtual int lock() + { SC_MTX_LOCK_(m_mtx); return 0; } + + // returns -1 if mutex could not be locked + virtual int trylock() + { return SC_MTX_TRYLOCK_(m_mtx) ? 0 : -1; } + + // should return -1 if mutex was not locked by caller, + // but is not yet able to check this + virtual int unlock() + { SC_MTX_UNLOCK_(m_mtx); return 0; } + +private: + underlying_type m_mtx; +}; + +} // namespace sc_core + +#undef SC_MTX_TYPE_ +#undef SC_MTX_INIT_ +#undef SC_MTX_DESTROY_ +#undef SC_MTX_LOCK_ +#undef SC_MTX_TRYLOCK_ +#undef SC_MTX_UNLOCK_ +#undef SC_PTHREAD_NULL_ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + *****************************************************************************/ +//$Log: sc_host_mutex.h,v $ +//Revision 1.4 2011/08/30 21:53:23 acg +// Jerome Cornet: include window.h for gnu c in windows case. +// +//Revision 1.3 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +//Revision 1.2 2011/06/25 17:08:38 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +//Revision 1.1 2011/04/18 19:04:11 acg +// Philipp A. Hartmann: first check in of file. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_interface.cpp b/ext/systemc/src/sysc/communication/sc_interface.cpp new file mode 100644 index 000000000..eabe870e9 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_interface.cpp @@ -0,0 +1,100 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_interface.cpp -- Abstract base class of all interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_interface.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/kernel/sc_event.h" + + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_interface +// +// Abstract base class of all interface classes. +// BEWARE: Direct inheritance from this class must be done virtual. +// ---------------------------------------------------------------------------- + +// register a port with this interface (does nothing by default) + +void +sc_interface::register_port( sc_port_base&, const char* ) +{} + + +// get the default event + +const sc_event& +sc_interface::default_event() const +{ + SC_REPORT_WARNING( SC_ID_NO_DEFAULT_EVENT_, 0 ); + return m_never_notified; +} + + +// destructor (does nothing) + +sc_interface::~sc_interface() +{} + + +// constructor (does nothing) + +sc_interface::sc_interface() +{} + + +// special event for never notified cases, note the special name to keep +// it out of the named event structures. + +sc_event sc_interface::m_never_notified(SC_KERNEL_EVENT_PREFIX); + +} // namespace sc_core + +// $Log: sc_interface.cpp,v $ +// Revision 1.5 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/03/12 21:07:42 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.3 2011/03/06 15:55:08 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_interface.h b/ext/systemc/src/sysc/communication/sc_interface.h new file mode 100644 index 000000000..b21d3c27d --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_interface.h @@ -0,0 +1,107 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_interface.h -- Abstract base class of all interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_INTERFACE_H +#define SC_INTERFACE_H + +namespace sc_core { + +class sc_event; +class sc_port_base; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_interface +// +// Abstract base class of all interface classes. +// BEWARE: Direct inheritance from this class must be done virtual. +// ---------------------------------------------------------------------------- + +class sc_interface +{ +public: + + // register a port with this interface (does nothing by default) + virtual void register_port( sc_port_base& port_, + const char* if_typename_ ); + + // get the default event + virtual const sc_event& default_event() const; + + // destructor (does nothing) + virtual ~sc_interface(); + +protected: + + // constructor (does nothing) + sc_interface(); + +private: + + // disabled + sc_interface( const sc_interface& ); + sc_interface& operator = ( const sc_interface& ); + +private: + + static sc_event m_never_notified; + +#if defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x520) + // Workaround for a bug in the Sun WorkShop 6 update 2 compiler. + // An empty virtual base class can cause the optimizer to + // generate wrong code. + char dummy; +#endif +}; + +} // namespace sc_core + +//$Log: sc_interface.h,v $ +//Revision 1.3 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.7 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_mutex.cpp b/ext/systemc/src/sysc/communication/sc_mutex.cpp new file mode 100644 index 000000000..d2c43244c --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_mutex.cpp @@ -0,0 +1,140 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mutex.cpp -- The sc_mutex primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_mutex.h" +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_mutex +// +// The sc_mutex primitive channel class. +// ---------------------------------------------------------------------------- + +// constructors + +sc_mutex::sc_mutex() +: sc_object( sc_gen_unique_name( "mutex" ) ), + m_owner( 0 ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ) +{} + +sc_mutex::sc_mutex( const char* name_ ) +: sc_object( name_ ), + m_owner( 0 ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ) +{} + + +// destructor + +sc_mutex::~sc_mutex() +{} + +// interface methods + +// blocks until mutex could be locked + +int +sc_mutex::lock() +{ + if ( m_owner == sc_get_current_process_b()) return 0; + while( in_use() ) { + sc_core::wait( m_free, sc_get_curr_simcontext() ); + } + m_owner = sc_get_current_process_b(); + return 0; +} + + +// returns -1 if mutex could not be locked + +int +sc_mutex::trylock() +{ + if ( m_owner == sc_get_current_process_b()) return 0; + if( in_use() ) { + return -1; + } + m_owner = sc_get_current_process_b(); + return 0; +} + + +// returns -1 if mutex was not locked by caller + +int +sc_mutex::unlock() +{ + if( m_owner != sc_get_current_process_b() ) { + return -1; + } + m_owner = 0; + m_free.notify(); + return 0; +} + +} // namespace sc_core + +// $Log: sc_mutex.cpp,v $ +// Revision 1.7 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/03/28 13:02:29 acg +// Andy Goodrich: removed sc_event in sc_mutex class from the object +// hierarchy since it is considered a "kernel" event. +// +// Revision 1.5 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.4 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +// Revision 1.3 2008/11/13 15:29:46 acg +// David C. Black, ESLX, Inc: lock & trylock now allow owner to apply +// lock more than once without incident. Previous behavior locked up the +// owning process. +// +// Revision 1.2 2008/05/20 16:46:18 acg +// Andy Goodrich: added checks for multiple writers. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/21 00:00:27 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_mutex.h b/ext/systemc/src/sysc/communication/sc_mutex.h new file mode 100644 index 000000000..e3cef36c3 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_mutex.h @@ -0,0 +1,124 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mutex.h -- The sc_mutex primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_MUTEX_H +#define SC_MUTEX_H + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/communication/sc_mutex_if.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_mutex +// +// The sc_mutex primitive channel class. +// ---------------------------------------------------------------------------- + +class sc_mutex +: public sc_mutex_if, + public sc_object +{ +public: + + // constructors and destructor + + sc_mutex(); + explicit sc_mutex( const char* name_ ); + virtual ~sc_mutex(); + + + // interface methods + + // blocks until mutex could be locked + virtual int lock(); + + // returns -1 if mutex could not be locked + virtual int trylock(); + + // returns -1 if mutex was not locked by caller + virtual int unlock(); + + virtual const char* kind() const + { return "sc_mutex"; } + +protected: + + // support methods + + bool in_use() const + { return ( m_owner != 0 ); } + +protected: + + sc_process_b* m_owner; + sc_event m_free; + +private: + + // disabled + sc_mutex( const sc_mutex& ); + sc_mutex& operator = ( const sc_mutex& ); +}; + +} // namespace sc_core + +//$Log: sc_mutex.h,v $ +//Revision 1.4 2011/08/26 20:45:41 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_mutex_if.h b/ext/systemc/src/sysc/communication/sc_mutex_if.h new file mode 100644 index 000000000..6fa934135 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_mutex_if.h @@ -0,0 +1,146 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mutex_if.h -- The sc_mutex_if interface class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_MUTEX_IF_H +#define SC_MUTEX_IF_H + +#include "sysc/communication/sc_interface.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_mutex_if +// +// The sc_mutex_if interface class. +// ---------------------------------------------------------------------------- + +class sc_mutex_if +: virtual public sc_interface +{ +public: + + // the classical operations: lock(), trylock(), and unlock() + + // blocks until mutex could be locked + virtual int lock() = 0; + + // returns -1 if mutex could not be locked + virtual int trylock() = 0; + + // returns -1 if mutex was not locked by caller + virtual int unlock() = 0; + +protected: + + // constructor + + sc_mutex_if() + {} + +private: + + // disabled + sc_mutex_if( const sc_mutex_if& ); + sc_mutex_if& operator = ( const sc_mutex_if& ); +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_scoped_lock +// +// The sc_scoped_lock class to lock (and automatically release) a mutex. +// ---------------------------------------------------------------------------- + +//template< typename Lockable = sc_mutex_if > +class sc_scoped_lock +{ +public: + //typedef Lockable lockable_type; + typedef sc_mutex_if lockable_type; + + explicit + sc_scoped_lock( lockable_type& mtx ) + : m_ref(mtx) + , m_active(true) + { + m_ref.lock(); + } + + bool release() + { + if( m_active ) + { + m_ref.unlock(); + m_active = false; + return true; + } + return false; + } + + ~sc_scoped_lock() + { + release(); + } + +private: + // disabled + sc_scoped_lock( const sc_scoped_lock& ); + sc_scoped_lock& operator=( const sc_scoped_lock& ); + + lockable_type& m_ref; + bool m_active; +}; + +} // namespace sc_core + +//$Log: sc_mutex_if.h,v $ +//Revision 1.4 2011/08/26 20:45:41 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_port.cpp b/ext/systemc/src/sysc/communication/sc_port.cpp new file mode 100644 index 000000000..01291e6b5 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_port.cpp @@ -0,0 +1,835 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_port.cpp -- Base classes of all port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object_int.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/communication/sc_event_finder.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_signal_ifs.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_elem +// ---------------------------------------------------------------------------- + +struct sc_bind_elem +{ + // constructors + sc_bind_elem(); + explicit sc_bind_elem( sc_interface* interface_ ); + explicit sc_bind_elem( sc_port_base* parent_ ); + + sc_interface* iface; + sc_port_base* parent; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructors + +sc_bind_elem::sc_bind_elem() +: iface( 0 ), + parent( 0 ) +{} + +sc_bind_elem::sc_bind_elem( sc_interface* interface_ ) +: iface( interface_ ), + parent( 0 ) +{} + +sc_bind_elem::sc_bind_elem( sc_port_base* parent_ ) +: iface( 0 ), + parent( parent_ ) +{} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_ef +// ---------------------------------------------------------------------------- + +struct sc_bind_ef +{ + // constructor + sc_bind_ef( sc_process_b* , sc_event_finder* ); + + // destructor + ~sc_bind_ef(); + + sc_process_b* handle; + sc_event_finder* event_finder; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructor + +sc_bind_ef::sc_bind_ef( sc_process_b* handle_, + sc_event_finder* event_finder_ ) +: handle( handle_ ), + event_finder( event_finder_ ) +{} + + +// destructor + +sc_bind_ef::~sc_bind_ef() +{ +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_info +// ---------------------------------------------------------------------------- + +struct sc_bind_info +{ + // constructor + explicit sc_bind_info( int max_size_, + sc_port_policy policy_=SC_ONE_OR_MORE_BOUND ); + + // destructor + ~sc_bind_info(); + + int max_size() const; + sc_port_policy policy() const; + int size() const; + + int m_max_size; + sc_port_policy m_policy; + std::vector<sc_bind_elem*> vec; + bool has_parent; + int last_add; + bool is_leaf; + bool complete; + + std::vector<sc_bind_ef*> thread_vec; + std::vector<sc_bind_ef*> method_vec; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructor + +sc_bind_info::sc_bind_info( int max_size_, sc_port_policy policy_ ) +: m_max_size( max_size_ ), + m_policy( policy_ ), + vec(), + has_parent( false ), + last_add( -1 ), + is_leaf( true ), + complete( false ), + thread_vec(), + method_vec() +{} + + +// destructor + +sc_bind_info::~sc_bind_info() +{ + for( int i = size() - 1; i >= 0; -- i ) { + delete vec[i]; + } +} + + +int +sc_bind_info::max_size() const +{ + return m_max_size ? m_max_size : (int) vec.size(); +} + +sc_port_policy +sc_bind_info::policy() const +{ + return m_policy; +} + +int +sc_bind_info::size() const +{ + return vec.size(); +} + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_base +// +// Abstract base class for class sc_port_b. +// ---------------------------------------------------------------------------- + +// This method exists to get around a problem in VCC 6.0 where you cannot +// have a friend class that is templated. So sc_port_b<IF> calls this class +// instead of sc_process_b::add_static_event. + +void sc_port_base::add_static_event( + sc_method_handle process_p, const sc_event& event ) const +{ + process_p->add_static_event( event ); +} + +void sc_port_base::add_static_event( + sc_thread_handle process_p, const sc_event& event ) const +{ + process_p->add_static_event( event ); +} + +// return number of interfaces that will be bound, or are bound: + +int sc_port_base::bind_count() +{ + if ( m_bind_info ) + return m_bind_info->size(); + else + return interface_count(); +} + +// error reporting + +void +sc_port_base::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: port '%s' (%s)", add_msg, name(), kind() ); + } else { + std::sprintf( msg, "port '%s' (%s)", name(), kind() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// constructors + +sc_port_base::sc_port_base( + int max_size_, sc_port_policy policy +) : + sc_object( sc_gen_unique_name( "port" ) ), + m_bind_info(NULL) +{ + simcontext()->get_port_registry()->insert( this ); + m_bind_info = new sc_bind_info( max_size_, policy ); +} + +sc_port_base::sc_port_base( + const char* name_, int max_size_, sc_port_policy policy +) : + sc_object( name_ ), + m_bind_info(NULL) +{ + simcontext()->get_port_registry()->insert( this ); + m_bind_info = new sc_bind_info( max_size_, policy ); +} + + +// destructor + +sc_port_base::~sc_port_base() +{ + simcontext()->get_port_registry()->remove( this ); + delete m_bind_info; +} + + +// bind interface to this port + +void +sc_port_base::bind( sc_interface& interface_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind an interface after elaboration + report_error( SC_ID_BIND_IF_TO_PORT_, "simulation running" ); + } + + m_bind_info->vec.push_back( new sc_bind_elem( &interface_ ) ); + + if( ! m_bind_info->has_parent ) { + // add (cache) the interface + add_interface( &interface_ ); + m_bind_info->last_add ++; + } +} + + +// bind parent port to this port + +void +sc_port_base::bind( this_type& parent_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind a parent port after elaboration + report_error( SC_ID_BIND_PORT_TO_PORT_, "simulation running" ); + } + + if( &parent_ == this ) { + report_error( SC_ID_BIND_PORT_TO_PORT_, "same port" ); + } + + // check if parent port is already bound to this port +#if 0 + for( int i = m_bind_info->size() - 1; i >= 0; -- i ) { + if( &parent_ == m_bind_info->vec[i]->parent ) { + report_error( SC_ID_BIND_PORT_TO_PORT_, "already bound" ); + } + } +#endif // + + m_bind_info->vec.push_back( new sc_bind_elem( &parent_ ) ); + m_bind_info->has_parent = true; + parent_.m_bind_info->is_leaf = false; +} + +// called by construction_done (null by default) + +void sc_port_base::before_end_of_elaboration() +{} + +// called by elaboration_done (does nothing) + +void +sc_port_base::end_of_elaboration() +{} + +// called by sc_port_registry::start_simulation (does nothing by default) + +void sc_port_base::start_of_simulation() +{} + +// called by sc_port_registry::simulation_done (does nothing by default) + +void sc_port_base::end_of_simulation() +{} + + +// called by class sc_module for positional binding + +int +sc_port_base::pbind( sc_interface& interface_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind an interface after elaboration + report_error( SC_ID_BIND_IF_TO_PORT_, "simulation running" ); + } + + if( m_bind_info->size() != 0 ) { + // first interface already bound + return 1; + } + + return vbind( interface_ ); +} + +int +sc_port_base::pbind( sc_port_base& parent_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind a parent port after elaboration + report_error( SC_ID_BIND_PORT_TO_PORT_, "simulation running" ); + } + + if( m_bind_info->size() != 0 ) { + // first interface already bound + return 1; + } + + return vbind( parent_ ); +} + + +// called by the sc_sensitive* classes + +void +sc_port_base::make_sensitive( sc_thread_handle handle_, + sc_event_finder* event_finder_ ) const +{ + assert( m_bind_info != 0 ); + m_bind_info->thread_vec.push_back( + new sc_bind_ef( (sc_process_b*)handle_, event_finder_ ) ); +} + +void +sc_port_base::make_sensitive( sc_method_handle handle_, + sc_event_finder* event_finder_ ) const +{ + assert( m_bind_info != 0 ); + m_bind_info->method_vec.push_back( + new sc_bind_ef( (sc_process_b*)handle_, event_finder_ ) ); +} + + +// support methods + +int +sc_port_base::first_parent() +{ + for( int i = 0; i < m_bind_info->size(); ++ i ) { + if( m_bind_info->vec[i]->parent != 0 ) { + return i; + } + } + return -1; +} + +void +sc_port_base::insert_parent( int i ) +{ + std::vector<sc_bind_elem*>& vec = m_bind_info->vec; + + this_type* parent = vec[i]->parent; + + + // IF OUR PARENT HAS NO BINDING THEN IGNORE IT: + // + // Note that the zeroing of the parent pointer must occur before this + // test + + vec[i]->parent = 0; + if ( parent->m_bind_info->vec.size() == 0 ) return; + + vec[i]->iface = parent->m_bind_info->vec[0]->iface; + int n = parent->m_bind_info->size() - 1; + if( n > 0 ) { + // resize the bind vector (by adding new elements) + for( int k = 0; k < n; ++ k ) { + vec.push_back( new sc_bind_elem() ); + } + // move elements in the bind vector + for( int k = m_bind_info->size() - n - 1; k > i; -- k ) { + vec[k + n]->iface = vec[k]->iface; + vec[k + n]->parent = vec[k]->parent; + } + // insert parent interfaces into the bind vector + for( int k = i + 1; k <= i + n; ++ k ) { + vec[k]->iface = parent->m_bind_info->vec[k - i]->iface; + vec[k]->parent = 0; + } + } +} + + +// called when elaboration is done + +void +sc_port_base::complete_binding() +{ + char msg_buffer[128]; // For error message construction. + + // IF BINDING HAS ALREADY BEEN COMPLETED IGNORE THIS CALL: + + assert( m_bind_info != 0 ); + if( m_bind_info->complete ) { + return; + } + + // COMPLETE BINDING OF OUR PARENT PORTS SO THAT WE CAN USE THAT INFORMATION: + + int i = first_parent(); + while( i >= 0 ) { + m_bind_info->vec[i]->parent->complete_binding(); + insert_parent( i ); + i = first_parent(); + } + + // LOOP OVER BINDING INFORMATION TO COMPLETE THE BINDING PROCESS: + + int size; + for( int j = 0; j < m_bind_info->size(); ++ j ) { + sc_interface* iface = m_bind_info->vec[j]->iface; + + // if the interface is zero this was for an unbound port. + if ( iface == 0 ) continue; + + // add (cache) the interface + if( j > m_bind_info->last_add ) { + add_interface( iface ); + } + + // only register "leaf" ports (ports without children) + if( m_bind_info->is_leaf ) { + iface->register_port( *this, if_typename() ); + } + + // complete static sensitivity for methods + size = m_bind_info->method_vec.size(); + for( int k = 0; k < size; ++ k ) { + sc_bind_ef* p = m_bind_info->method_vec[k]; + const sc_event& event = ( p->event_finder != 0 ) + ? p->event_finder->find_event(iface) + : iface->default_event(); + p->handle->add_static_event( event ); + } + + // complete static sensitivity for threads + size = m_bind_info->thread_vec.size(); + for( int k = 0; k < size; ++ k ) { + sc_bind_ef* p = m_bind_info->thread_vec[k]; + const sc_event& event = ( p->event_finder != 0 ) + ? p->event_finder->find_event(iface) + : iface->default_event(); + p->handle->add_static_event( event ); + } + + } + + // MAKE SURE THE PROPER NUMBER OF BINDINGS OCCURRED: + // + // Make sure there are enough bindings, and not too many. + + int actual_binds = interface_count(); + + if ( actual_binds > m_bind_info->max_size() ) + { + sprintf(msg_buffer, "%d binds exceeds maximum of %d allowed", + actual_binds, m_bind_info->max_size() ); + report_error( SC_ID_COMPLETE_BINDING_, msg_buffer ); + } + switch ( m_bind_info->policy() ) + { + case SC_ONE_OR_MORE_BOUND: + if ( actual_binds < 1 ) { + report_error( SC_ID_COMPLETE_BINDING_, "port not bound" ); + } + break; + case SC_ALL_BOUND: + if ( actual_binds < m_bind_info->max_size() || actual_binds < 1 ) { + sprintf(msg_buffer, "%d actual binds is less than required %d", + actual_binds, m_bind_info->max_size() ); + report_error( SC_ID_COMPLETE_BINDING_, msg_buffer ); + } + break; + default: // SC_ZERO_OR_MORE_BOUND: + break; + } + + + // CLEAN UP: FREE BINDING STORAGE: + + size = m_bind_info->method_vec.size(); + for( int k = 0; k < size; ++ k ) { + delete m_bind_info->method_vec[k]; + } + m_bind_info->method_vec.resize(0); + + size = m_bind_info->thread_vec.size(); + for( int k = 0; k < size; ++ k ) { + delete m_bind_info->thread_vec[k]; + } + m_bind_info->thread_vec.resize(0); + + m_bind_info->complete = true; +} + +void +sc_port_base::construction_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + before_end_of_elaboration(); +} + +void +sc_port_base::elaboration_done() +{ + assert( m_bind_info != 0 && m_bind_info->complete ); + delete m_bind_info; + m_bind_info = 0; + + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_elaboration(); +} + +void +sc_port_base::start_simulation() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + start_of_simulation(); +} + +void +sc_port_base::simulation_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_simulation(); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_registry +// +// Registry for all ports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_port_registry::insert( sc_port_base* port_ ) +{ + if( sc_is_running() ) { + port_->report_error( SC_ID_INSERT_PORT_, "simulation running" ); + } + + if( m_simc->elaboration_done() ) { + port_->report_error( SC_ID_INSERT_PORT_, "elaboration done" ); + } + +#if defined(DEBUG_SYSTEMC) + // check if port_ is already inserted + for( int i = size() - 1; i >= 0; -- i ) { + if( port_ == m_port_vec[i] ) { + port_->report_error( SC_ID_INSERT_PORT_, "port already inserted" ); + } + } +#endif + + // append the port to the current module's vector of ports + sc_module* curr_module = m_simc->hierarchy_curr(); + if( curr_module == 0 ) { + port_->report_error( SC_ID_PORT_OUTSIDE_MODULE_ ); + } + curr_module->append_port( port_ ); + + // insert + m_port_vec.push_back( port_ ); +} + +void +sc_port_registry::remove( sc_port_base* port_ ) +{ + int i; + for( i = size() - 1; i >= 0; -- i ) { + if( port_ == m_port_vec[i] ) { + break; + } + } + if( i == -1 ) { + port_->report_error( SC_ID_REMOVE_PORT_, "port not registered" ); + } + + // remove + m_port_vec[i] = m_port_vec[size() - 1]; + m_port_vec.resize(size()-1); +} + + +// constructor + +sc_port_registry::sc_port_registry( sc_simcontext& simc_ ) +: m_construction_done(0), + m_port_vec(), + m_simc( &simc_ ) +{ +} + + +// destructor + +sc_port_registry::~sc_port_registry() +{ +} + +// called when construction is done + +bool +sc_port_registry::construction_done() +{ + if( size() == m_construction_done ) + // nothing has been updated + return true; + + for( int i = size()-1; i >= m_construction_done; --i ) { + m_port_vec[i]->construction_done(); + } + + m_construction_done = size(); + return false; +} + +// called when when elaboration is done + +void +sc_port_registry::complete_binding() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->complete_binding(); + } +} + + +// called when elaboration is done + +void +sc_port_registry::elaboration_done() +{ + complete_binding(); + + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->elaboration_done(); + } +} + +// called before simulation begins + +void +sc_port_registry::start_simulation() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->start_simulation(); + } +} + +// called after simulation ends + +void +sc_port_registry::simulation_done() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->simulation_done(); + } +} + +// This is a static member function. + +void +sc_port_registry::replace_port( sc_port_registry* /* registry */ ) +{ +} + +void sc_warn_port_constructor() +{ + static bool warn_port_constructor=true; + if ( warn_port_constructor ) + { + warn_port_constructor = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "interface and/or port binding in port constructors is deprecated" + ); + } +} + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: phase callbacks + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 12 December, 2005 + Description of Modification: multiport binding policy changes + + *****************************************************************************/ + + +// $Log: sc_port.cpp,v $ +// Revision 1.8 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.7 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.6 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.5 2011/08/07 18:53:09 acg +// Philipp A. Hartmann: add virtual instances of the bind function for +// base classes to eliminate warning messages for clang platforms. +// +// Revision 1.4 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.11 2006/08/29 23:34:59 acg +// Andy Goodrich: added bind_count() method to allow users to determine which +// ports are connected in before_end_of_elaboration(). +// +// Revision 1.10 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +// Revision 1.9 2006/02/02 20:43:09 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +// Revision 1.7 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.6 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.5 2006/01/24 20:46:31 acg +// Andy Goodrich: changes to eliminate use of deprecated features. For instance, +// using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +// Revision 1.4 2006/01/13 20:41:59 acg +// Andy Goodrich: Changes to add port registration to the things that are +// checked when SC_NO_WRITE_CHECK is not defined. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_port.h b/ext/systemc/src/sysc/communication/sc_port.h new file mode 100644 index 000000000..a126657e6 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_port.h @@ -0,0 +1,732 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_port.h -- Base classes of all port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_PORT_H +#define SC_PORT_H + + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_interface.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_process.h" +#include <typeinfo> + +#if ! defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_VIRTUAL_ virtual +#else +# define SC_VIRTUAL_ /* non-virtual */ +#endif + +namespace sc_core { + +class sc_event_finder; + +struct sc_bind_info; + +enum sc_port_policy +{ + SC_ONE_OR_MORE_BOUND, // Default + SC_ZERO_OR_MORE_BOUND, + SC_ALL_BOUND +}; + + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// BEWARE: Ports can only be created and bound during elaboration. +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_base +// +// Abstract base class for class sc_port_b. +// ---------------------------------------------------------------------------- + +class sc_port_base +: public sc_object +{ + friend class sc_module; + friend class sc_port_registry; + friend class sc_sensitive; + friend class sc_sensitive_pos; + friend class sc_sensitive_neg; + +public: + + // typedefs + + typedef sc_port_base this_type; + +public: + + int bind_count(); + + // get the first interface without checking for nil + virtual sc_interface* get_interface() = 0; + virtual const sc_interface* get_interface() const = 0; + + virtual const char* kind() const + { return "sc_port_base"; } + +protected: + + // constructors + explicit sc_port_base( int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ); + sc_port_base( const char* name_, int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ); + + // destructor + virtual ~sc_port_base(); + + // bind interface to this port + void bind( sc_interface& interface_ ); + + // bind parent port to this port + void bind( this_type& parent_ ); + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ) = 0; + virtual int vbind( sc_port_base& ) = 0; + + // called by complete_binding (for internal use only) + virtual void add_interface( sc_interface* ) = 0; + virtual int interface_count() = 0; + virtual const char* if_typename() const = 0; + + // called by construction_done (does nothing by default) + virtual void before_end_of_elaboration(); + + // called by elaboration_done (does nothing) + virtual void end_of_elaboration(); + + // called by start_simulation (does nothing by default) + virtual void start_of_simulation(); + + // called by simulation_done (does nothing by default) + virtual void end_of_simulation(); + + // error reporting + void report_error( const char* id, const char* add_msg = 0) const; + +protected: + // called by the sc_sensitive* classes + virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const; + virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const; + void add_static_event( + sc_method_handle process_p, const sc_event& event) const; + void add_static_event( + sc_thread_handle process_p, const sc_event& event) const; + +private: + + // called by class sc_module for positional binding + int pbind( sc_interface& ); + int pbind( sc_port_base& ); + + + // support methods + int first_parent(); + void insert_parent( int ); + + // called when construction is done + void construction_done(); + + // called when elaboration is done + void complete_binding(); + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + +protected: + + sc_bind_info* m_bind_info; + +private: + + // disabled + sc_port_base(); + sc_port_base( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_registry +// +// Registry for all ports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_port_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_port_base* ); + void remove( sc_port_base* ); + + int size() const + { return m_port_vec.size(); } + +private: + + // constructor + explicit sc_port_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_port_registry(); + + // called when by construction_done and elaboration done + void complete_binding(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + static void replace_port( sc_port_registry* ); + +private: + + int m_construction_done; + std::vector<sc_port_base*> m_port_vec; + sc_simcontext* m_simc; + +private: + + // disabled + sc_port_registry(); + sc_port_registry( const sc_port_registry& ); + sc_port_registry& operator = ( const sc_port_registry& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_b +// +// Abstract base class for class sc_port. +// ---------------------------------------------------------------------------- + +template <class IF> +class sc_port_b +: public sc_port_base +{ +public: + + friend class sc_sensitive; + friend class sc_sensitive_neg; + friend class sc_sensitive_pos; + + // typedefs + + typedef sc_port_base base_type; + typedef sc_port_b<IF> this_type; + typedef this_type port_type; + +public: + + // bind an interface of type IF to this port + + SC_VIRTUAL_ void bind( IF& interface_ ) + { base_type::bind( interface_ ); } + + void operator () ( IF& interface_ ) + { this->bind( interface_ ); } + + + // bind a parent port with type IF to this port + + SC_VIRTUAL_ void bind( port_type& parent_ ) + { base_type::bind( parent_ ); } + + void operator () ( port_type& parent_ ) + { this->bind( parent_ ); } + + + // number of connected interfaces + + int size() const + { return m_interface_vec.size(); } + + + // allow to call methods provided by the first interface + IF* operator -> (); + const IF* operator -> () const; + + + // allow to call methods provided by interface at index + inline const IF* get_interface( int iface_i ) const; + inline IF* get_interface( int iface_i ); + IF* operator [] ( int index_ ) + { return get_interface( index_ ); } + const IF* operator [] ( int index_ ) const + { return get_interface( index_ ); } + + + // get the first interface without checking for nil + + virtual sc_interface* get_interface() + { return m_interface; } + + virtual const sc_interface* get_interface() const + { return m_interface; } + +protected: + + // constructors + + explicit sc_port_b( int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) : + base_type( max_size_, policy ), m_interface( 0 ), m_interface_vec() + {} + + sc_port_b( const char* name_, int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) : + base_type( name_, max_size_, policy ), m_interface( 0 ), + m_interface_vec() + {} + + + // destructor (does nothing) + + virtual ~sc_port_b() + {} + + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + +protected: + + // called by the sc_sensitive* classes + virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const; + virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const; + +private: + + // called by complete_binding (for internal use only) + virtual void add_interface( sc_interface* ); + virtual const char* if_typename() const; + virtual int interface_count(); + + // disabled + sc_port_b(); + sc_port_b( const this_type& ); + this_type& operator = ( const this_type& ); + +private: + + IF* m_interface; // first interface in interface vec + std::vector<IF*> m_interface_vec; +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port +// +// Generic port class and base class for other port classes. +// N is the maximum number of channels (with interface IF) that can be bound +// to this port. N <= 0 means no maximum. +// ---------------------------------------------------------------------------- + +extern void sc_warn_port_constructor(); + +template <class IF, int N = 1, sc_port_policy P=SC_ONE_OR_MORE_BOUND> +class sc_port +: public sc_port_b<IF> +{ + // typdefs + + typedef sc_port_b<IF> base_type; + typedef sc_port<IF,N,P> this_type; + +public: + + // constructors + + sc_port() + : base_type( N, P ) + {} + + explicit sc_port( const char* name_ ) + : base_type( name_, N, P ) + {} + + explicit sc_port( IF& interface_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( interface_ ); } + + sc_port( const char* name_, IF& interface_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( interface_ ); } + + explicit sc_port( base_type& parent_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( const char* name_, base_type& parent_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( this_type& parent_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( const char* name_, this_type& parent_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + + // destructor (does nothing) + + virtual ~sc_port() + {} + + virtual const char* kind() const + { return "sc_port"; } + +private: + + // disabled + sc_port( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_b +// +// Abstract base class for class sc_port. +// ---------------------------------------------------------------------------- + +// allow to call methods provided by the first interface + +template <class IF> +inline +IF* +sc_port_b<IF>::operator -> () +{ + if( m_interface == 0 ) { + report_error( SC_ID_GET_IF_, "port is not bound" ); + } + return m_interface; +} + +template <class IF> +inline +const IF* +sc_port_b<IF>::operator -> () const +{ + if( m_interface == 0 ) { + report_error( SC_ID_GET_IF_, "port is not bound" ); + } + return m_interface; +} + + +// allow to call methods provided by interface at index +// +// note that we special-case index of zero, since the method may be +// called before binding has occurred, and we need to return a zero +// in that case not an error. + +template <class IF> +inline +IF* +sc_port_b<IF>::get_interface( int index_ ) +{ + if ( index_ == 0 ) { + return m_interface; + } + else if( index_ < 0 || index_ >= size() ) { + report_error( SC_ID_GET_IF_, "index out of range" ); + } + return m_interface_vec[index_]; +} + +template <class IF> +inline +const IF* +sc_port_b<IF>::get_interface( int index_ ) const +{ + if ( index_ == 0 ) { + return m_interface; + } + else if( index_ < 0 || index_ >= size() ) { + report_error( SC_ID_GET_IF_, "index out of range" ); + } + return m_interface_vec[index_]; +} + + +// called by pbind (for internal use only) + +template <class IF> +inline +int +sc_port_b<IF>::vbind( sc_interface& interface_ ) +{ + IF* iface = DCAST<IF*>( &interface_ ); + if( iface == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *iface ); + return 0; +} + +template <class IF> +inline +int +sc_port_b<IF>::vbind( sc_port_base& parent_ ) +{ + this_type* parent = DCAST<this_type*>( &parent_ ); + if( parent == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *parent ); + return 0; +} + + +// called by complete_binding (for internal use only) + +template <class IF> +inline +void +sc_port_b<IF>::add_interface( sc_interface* interface_ ) +{ + IF* iface = DCAST<IF*>( interface_ ); + assert( iface != 0 ); + + // make sure that the interface is not already bound: + + int size = m_interface_vec.size(); + for ( int i = 0; i < size; i++ ) + { + if ( iface == m_interface_vec[i] ) + { + report_error( SC_ID_BIND_IF_TO_PORT_, + "interface already bound to port" ); + } + } + + // "bind" the interface and make sure our short cut for 0 is set up. + + m_interface_vec.push_back( iface ); + m_interface = m_interface_vec[0]; +} + +template <class IF> +inline +const char* +sc_port_b<IF>::if_typename() const +{ + return typeid( IF ).name(); +} + +template <class IF> +inline +int +sc_port_b<IF>::interface_count() +{ + return m_interface_vec.size(); +} + +template <class IF> +void +sc_port_b<IF>::make_sensitive( sc_thread_handle handle_p, + sc_event_finder* event_finder_ ) const +{ + if ( m_bind_info == 0 ) + { + int if_n = m_interface_vec.size(); + for ( int if_i = 0; if_i < if_n; if_i++ ) + { + IF* iface_p = m_interface_vec[if_i]; + assert( iface_p != 0 ); + add_static_event( handle_p, iface_p->default_event() ); + } + } + else + { + sc_port_base::make_sensitive( handle_p, event_finder_ ); + } +} + +template <class IF> +void +sc_port_b<IF>::make_sensitive( sc_method_handle handle_p, + sc_event_finder* event_finder_ ) const +{ + if ( m_bind_info == 0 ) + { + int if_n = m_interface_vec.size(); + for ( int if_i = 0; if_i < if_n; if_i++ ) + { + IF* iface_p = m_interface_vec[if_i]; + assert( iface_p != 0 ); + add_static_event( handle_p, iface_p->default_event() ); + } + } + else + { + sc_port_base::make_sensitive( handle_p, event_finder_ ); + } +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_port +// +// Generic port class and base class for other port classes. +// N is the maximum number of channels (with interface IF) that can be bound +// to this port. N <= 0 means no maximum. +// ---------------------------------------------------------------------------- + +} // namespace sc_core + +#undef SC_VIRTUAL_ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: phase callbacks + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 12 December, 2005 + Description of Modification: multiport binding policy changes + + + *****************************************************************************/ + +/* +$Log: sc_port.h,v $ +Revision 1.10 2011/08/26 20:45:41 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.9 2011/08/24 22:05:36 acg + Torsten Maehne: initialization changes to remove warnings. + +Revision 1.8 2011/08/07 19:08:01 acg + Andy Goodrich: moved logs to end of file so line number synching works + better between versions. + +Revision 1.7 2011/08/07 18:53:09 acg + Philipp A. Hartmann: add virtual instances of the bind function for + base classes to eliminate warning messages for clang platforms. + +Revision 1.6 2011/05/09 04:07:37 acg + Philipp A. Hartmann: + (1) Restore hierarchy in all phase callbacks. + (2) Ensure calls to before_end_of_elaboration. + +Revision 1.5 2011/03/30 16:46:10 acg + Andy Goodrich: added a signature and removed a virtual specification + to eliminate warnings with certain compilers. + +Revision 1.4 2011/02/18 20:23:45 acg + Andy Goodrich: Copyright update. + +Revision 1.3 2011/01/20 16:52:15 acg + Andy Goodrich: changes for IEEE 1666 2011. + +Revision 1.2 2010/08/03 18:01:11 acg + Andy Goodrich: formatting. + +Revision 1.1.1.1 2006/12/15 20:20:04 acg +SystemC 2.3 + +Revision 1.5 2006/08/29 23:35:00 acg + Andy Goodrich: added bind_count() method to allow users to determine which + ports are connected in before_end_of_elaboration(). + +Revision 1.4 2006/05/08 17:52:47 acg + Andy Goodrich: + (1) added David Long's forward declarations for friend functions, + methods, and operators to keep the Microsoft compiler happy. + (2) Added delta_count() method to sc_prim_channel for use by + sc_signal so that the friend declaration in sc_simcontext.h + can be for a non-templated class (i.e., sc_prim_channel.) + +Revision 1.3 2006/01/24 20:46:31 acg +Andy Goodrich: changes to eliminate use of deprecated features. For instance, +using notify(SC_ZERO_TIME) in place of notify_delayed(). + +Revision 1.2 2006/01/03 23:18:26 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:43 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/15 23:01:51 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.9 2005/08/10 01:35:59 acg +Changes for 64-bit support. + +Revision 1.8 2005/04/03 22:52:51 acg +Namespace changes. + +Revision 1.7 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.6 2004/09/27 21:02:54 acg +Andy Goodrich - Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments will appear in + checked out source. + +*/ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_prim_channel.cpp b/ext/systemc/src/sysc/communication/sc_prim_channel.cpp new file mode 100644 index 000000000..067884281 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_prim_channel.cpp @@ -0,0 +1,429 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_prim_channel.cpp -- Abstract base class of all primitive channel + classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object_int.h" + +#ifndef SC_DISABLE_ASYNC_UPDATES +# include "sysc/communication/sc_host_mutex.h" +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel +// +// Abstract base class of all primitive channel classes. +// ---------------------------------------------------------------------------- + +// constructors + +sc_prim_channel::sc_prim_channel() +: sc_object( 0 ), + m_registry( simcontext()->get_prim_channel_registry() ), + m_update_next_p( 0 ) +{ + m_registry->insert( *this ); +} + +sc_prim_channel::sc_prim_channel( const char* name_ ) +: sc_object( name_ ), + m_registry( simcontext()->get_prim_channel_registry() ), + m_update_next_p( 0 ) +{ + m_registry->insert( *this ); +} + + +// destructor + +sc_prim_channel::~sc_prim_channel() +{ + m_registry->remove( *this ); +} + + +// the update method (does nothing by default) + +void +sc_prim_channel::update() +{} + + +// called by construction_done (does nothing by default) + +void sc_prim_channel::before_end_of_elaboration() +{} + +// called when construction is done + +void +sc_prim_channel::construction_done() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + before_end_of_elaboration(); +} + +// called by elaboration_done (does nothing by default) + +void +sc_prim_channel::end_of_elaboration() +{} + + +// called when elaboration is done + +void +sc_prim_channel::elaboration_done() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + end_of_elaboration(); +} + +// called by start_simulation (does nothing) + +void +sc_prim_channel::start_of_simulation() +{} + +// called before simulation begins + +void +sc_prim_channel::start_simulation() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + start_of_simulation(); +} + +// called by simulation_done (does nothing) + +void +sc_prim_channel::end_of_simulation() +{} + +// called after simulation ends + +void +sc_prim_channel::simulation_done() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + end_of_simulation(); +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry::async_update_list +// +// Thread-safe list of pending external updates +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_prim_channel_registry::async_update_list +{ +#ifndef SC_DISABLE_ASYNC_UPDATES +public: + + bool pending() const + { + return m_push_queue.size() != 0; + } + + void append( sc_prim_channel& prim_channel_ ) + { + sc_scoped_lock lock( m_mutex ); + m_push_queue.push_back( &prim_channel_ ); + // return releases the mutex + } + + void accept_updates() + { + sc_assert( ! m_pop_queue.size() ); + { + sc_scoped_lock lock( m_mutex ); + m_push_queue.swap( m_pop_queue ); + // leaving the block releases the mutex + } + + std::vector< sc_prim_channel* >::const_iterator + it = m_pop_queue.begin(), end = m_pop_queue.end(); + while( it!= end ) + { + // we use request_update instead of perform_update + // to skip duplicates + (*it++)->request_update(); + } + m_pop_queue.clear(); + } + +private: + sc_host_mutex m_mutex; + std::vector< sc_prim_channel* > m_push_queue; + std::vector< sc_prim_channel* > m_pop_queue; + +#endif // ! SC_DISABLE_ASYNC_UPDATES +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry +// +// Registry for all primitive channels. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_prim_channel_registry::insert( sc_prim_channel& prim_channel_ ) +{ + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "simulation running" ); + } + + if( m_simc->elaboration_done() ) { + + SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "elaboration done" ); + } + +#ifdef DEBUG_SYSTEMC + // check if prim_channel_ is already inserted + for( int i = 0; i < size(); ++ i ) { + if( &prim_channel_ == m_prim_channel_vec[i] ) { + SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "already inserted" ); + } + } +#endif + + // insert + m_prim_channel_vec.push_back( &prim_channel_ ); + +} + +void +sc_prim_channel_registry::remove( sc_prim_channel& prim_channel_ ) +{ + int i; + for( i = 0; i < size(); ++ i ) { + if( &prim_channel_ == m_prim_channel_vec[i] ) { + break; + } + } + if( i == size() ) { + SC_REPORT_ERROR( SC_ID_REMOVE_PRIM_CHANNEL_, 0 ); + } + + // remove + m_prim_channel_vec[i] = m_prim_channel_vec[size() - 1]; + m_prim_channel_vec.resize(size()-1); +} + +bool +sc_prim_channel_registry::pending_async_updates() const +{ +#ifndef SC_DISABLE_ASYNC_UPDATES + return m_async_update_list_p->pending(); +#else + return false; +#endif +} + +void +sc_prim_channel_registry::async_request_update( sc_prim_channel& prim_channel_ ) +{ +#ifndef SC_DISABLE_ASYNC_UPDATES + m_async_update_list_p->append( prim_channel_ ); +#else + SC_REPORT_ERROR( SC_ID_NO_ASYNC_UPDATE_, prim_channel_.name() ); +#endif +} + +// +---------------------------------------------------------------------------- +// |"sc_prim_channel_registry::perform_update" +// | +// | This method updates the values of the primitive channels in its update +// | lists. +// +---------------------------------------------------------------------------- +void +sc_prim_channel_registry::perform_update() +{ + // Update the values for the primitive channels set external to the + // simulator. + +#ifndef SC_DISABLE_ASYNC_UPDATES + if( m_async_update_list_p->pending() ) + m_async_update_list_p->accept_updates(); +#endif + + sc_prim_channel* next_p; // Next update to perform. + sc_prim_channel* now_p; // Update now performing. + + // Update the values for the primitive channels in the simulator's list. + + now_p = m_update_list_p; + m_update_list_p = (sc_prim_channel*)sc_prim_channel::list_end; + for ( ; now_p != (sc_prim_channel*)sc_prim_channel::list_end; + now_p = next_p ) + { + next_p = now_p->m_update_next_p; + now_p->perform_update(); + } +} + +// constructor + +sc_prim_channel_registry::sc_prim_channel_registry( sc_simcontext& simc_ ) + : m_async_update_list_p(0) + , m_construction_done(0) + , m_prim_channel_vec() + , m_simc( &simc_ ) + , m_update_list_p((sc_prim_channel*)sc_prim_channel::list_end) +{ +# ifndef SC_DISABLE_ASYNC_UPDATES + m_async_update_list_p = new async_update_list(); +# endif +} + + +// destructor + +sc_prim_channel_registry::~sc_prim_channel_registry() +{ + delete m_async_update_list_p; +} + +// called when construction is done + +bool +sc_prim_channel_registry::construction_done() +{ + if( size() == m_construction_done ) + // nothing has been updated + return true; + + for( ; m_construction_done < size(); ++m_construction_done ) { + m_prim_channel_vec[m_construction_done]->construction_done(); + } + + return false; +} + + +// called when elaboration is done + +void +sc_prim_channel_registry::elaboration_done() +{ + for( int i = 0; i < size(); ++ i ) { + m_prim_channel_vec[i]->elaboration_done(); + } +} + +// called before simulation begins + +void +sc_prim_channel_registry::start_simulation() +{ + for( int i = 0; i < size(); ++ i ) { + m_prim_channel_vec[i]->start_simulation(); + } +} + +// called after simulation ends + +void +sc_prim_channel_registry::simulation_done() +{ + for( int i = 0; i < size(); ++ i ) { + m_prim_channel_vec[i]->simulation_done(); + } +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + Description of Modification: phase callbacks + + *****************************************************************************/ + + +// $Log: sc_prim_channel.cpp,v $ +// Revision 1.11 2011/08/26 21:38:32 acg +// Philipp A. Hartmann: removed unused switch m_construction_done. +// +// Revision 1.10 2011/08/26 20:45:41 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.9 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.8 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.7 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +// Revision 1.6 2011/02/18 20:31:05 acg +// Philipp A. Hartmann: added error messages for calls that cannot be done +// after elaboration. +// +// Revision 1.5 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.4 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.3 2010/12/07 20:36:49 acg +// Andy Goodrich: fix pointer that should have been initialized to zero. +// +// Revision 1.2 2010/12/07 19:50:36 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_prim_channel.h b/ext/systemc/src/sysc/communication/sc_prim_channel.h new file mode 100644 index 000000000..4a52fe7cb --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_prim_channel.h @@ -0,0 +1,420 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_prim_channel.h -- Abstract base class of all primitive channel classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_PRIM_CHANNEL_H +#define SC_PRIM_CHANNEL_H + +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/kernel/sc_wait_cthread.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel +// +// Abstract base class of all primitive channel classes. +// ---------------------------------------------------------------------------- + +class sc_prim_channel +: public sc_object +{ + friend class sc_prim_channel_registry; + +public: + enum { list_end = 0xdb }; +public: + virtual const char* kind() const + { return "sc_prim_channel"; } + + inline bool update_requested() + { return m_update_next_p != (sc_prim_channel*)list_end; } + + // request the update method to be executed during the update phase + inline void request_update(); + + // request the update method to be executed during the update phase + // from a process external to the simulator. + void async_request_update(); + +protected: + + // constructors + sc_prim_channel(); + explicit sc_prim_channel( const char* ); + + // destructor + virtual ~sc_prim_channel(); + + // the update method (does nothing by default) + virtual void update(); + + // called by construction_done (does nothing by default) + virtual void before_end_of_elaboration(); + + // called by elaboration_done (does nothing by default) + virtual void end_of_elaboration(); + + // called by start_simulation (does nothing by default) + virtual void start_of_simulation(); + + // called by simulation_done (does nothing by default) + virtual void end_of_simulation(); + +protected: + + // to avoid calling sc_get_curr_simcontext() + + // static sensitivity for SC_THREADs and SC_CTHREADs + + void wait() + { sc_core::wait( simcontext() ); } + + + // dynamic sensitivity for SC_THREADs and SC_CTHREADs + + void wait( const sc_event& e ) + { sc_core::wait( e, simcontext() ); } + + void wait( const sc_event_or_list& el ) + { sc_core::wait( el, simcontext() ); } + + void wait( const sc_event_and_list& el ) + { sc_core::wait( el, simcontext() ); } + + void wait( const sc_time& t ) + { sc_core::wait( t, simcontext() ); } + + void wait( double v, sc_time_unit tu ) + { sc_core::wait( sc_time( v, tu, simcontext() ), simcontext() ); } + + void wait( const sc_time& t, const sc_event& e ) + { sc_core::wait( t, e, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event& e ) + { sc_core::wait( sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void wait( const sc_time& t, const sc_event_or_list& el ) + { sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_or_list& el ) + { sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void wait( const sc_time& t, const sc_event_and_list& el ) + { sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_and_list& el ) + { sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void wait( int n ) + { sc_core::wait( n, simcontext() ); } + + + // static sensitivity for SC_METHODs + + void next_trigger() + { sc_core::next_trigger( simcontext() ); } + + + // dynamic sensitivity for SC_METHODs + + void next_trigger( const sc_event& e ) + { sc_core::next_trigger( e, simcontext() ); } + + void next_trigger( const sc_event_or_list& el ) + { sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_event_and_list& el ) + { sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_time& t ) + { sc_core::next_trigger( t, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu ) + {sc_core::next_trigger( sc_time( v, tu, simcontext() ), simcontext() );} + + void next_trigger( const sc_time& t, const sc_event& e ) + { sc_core::next_trigger( t, e, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event& e ) + { sc_core::next_trigger( + sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_or_list& el ) + { sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_or_list& el ) + { sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_and_list& el ) + { sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_and_list& el ) + { sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + + // for SC_METHODs and SC_THREADs and SC_CTHREADs + + bool timed_out() + { return sc_core::timed_out( simcontext() ); } + + +#if 0 // @@@@#### + // delta count maintenance + sc_dt::uint64 delta_count() + { return simcontext()->m_delta_count; } +#endif + +private: + + // called during the update phase of a delta cycle (if requested) + void perform_update(); + + // called when construction is done + void construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + // disabled + sc_prim_channel( const sc_prim_channel& ); + sc_prim_channel& operator = ( const sc_prim_channel& ); + +private: + + sc_prim_channel_registry* m_registry; // Update list manager. + sc_prim_channel* m_update_next_p; // Next entry in update list. +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry +// +// Registry for all primitive channels. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_prim_channel_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_prim_channel& ); + void remove( sc_prim_channel& ); + + + int size() const + { return m_prim_channel_vec.size(); } + + inline void request_update( sc_prim_channel& ); + void async_request_update( sc_prim_channel& ); + + bool pending_updates() const + { + return m_update_list_p != (sc_prim_channel*)sc_prim_channel::list_end + || pending_async_updates(); + } + + bool pending_async_updates() const; + +private: + + // constructor + explicit sc_prim_channel_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_prim_channel_registry(); + + // called during the update phase of a delta cycle + void perform_update(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + // disabled + sc_prim_channel_registry(); + sc_prim_channel_registry( const sc_prim_channel_registry& ); + sc_prim_channel_registry& operator = ( const sc_prim_channel_registry& ); + +private: + class async_update_list; + + async_update_list* m_async_update_list_p; // external updates. + int m_construction_done; // # of constructs. + std::vector<sc_prim_channel*> m_prim_channel_vec; // existing channels. + sc_simcontext* m_simc; // simulator context. + sc_prim_channel* m_update_list_p; // internal updates. +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry +// +// Registry for all primitive channels. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +inline +void +sc_prim_channel_registry::request_update( sc_prim_channel& prim_channel_ ) +{ + prim_channel_.m_update_next_p = m_update_list_p; + m_update_list_p = &prim_channel_; +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel +// +// Abstract base class of all primitive channel classes. +// ---------------------------------------------------------------------------- + +// request the update method (to be executed during the update phase) + +inline +void +sc_prim_channel::request_update() +{ + if( ! m_update_next_p ) { + m_registry->request_update( *this ); + } +} + +// request the update method from external to the simulator (to be executed +// during the update phase) + +inline +void +sc_prim_channel::async_request_update() +{ + m_registry->async_request_update(*this); +} + + +// called during the update phase of a delta cycle (if requested) + +inline +void +sc_prim_channel::perform_update() +{ + update(); + m_update_next_p = 0; +} + + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: phase callbacks + + *****************************************************************************/ +//$Log: sc_prim_channel.h,v $ +//Revision 1.10 2011/08/26 21:38:32 acg +// Philipp A. Hartmann: removed unused switch m_construction_done. +// +//Revision 1.9 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +//Revision 1.8 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +//Revision 1.7 2011/05/05 17:44:01 acg +// Philip A. Hartmann: change in the name of pending_async_updates. +// +//Revision 1.6 2011/04/19 15:03:48 acg +// Philipp A. Hartmann: remove ASYNC_UPDATE preprocessor check from header. +// +//Revision 1.5 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.4 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.3 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/07/30 03:44:11 acg +//Changes from 2.1. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_semaphore.cpp b/ext/systemc/src/sysc/communication/sc_semaphore.cpp new file mode 100644 index 000000000..d90424431 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_semaphore.cpp @@ -0,0 +1,148 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_semaphore.cpp -- The sc_semaphore primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_semaphore.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_wait.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_semaphore +// +// The sc_semaphore primitive channel class. +// ---------------------------------------------------------------------------- + +// error reporting + +void +sc_semaphore::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: semaphore '%s'", add_msg, name() ); + } else { + std::sprintf( msg, "semaphore '%s'", name() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// constructors + +sc_semaphore::sc_semaphore( int init_value_ ) +: sc_object( sc_gen_unique_name( "semaphore" ) ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ), + m_value( init_value_ ) +{ + if( m_value < 0 ) { + report_error( SC_ID_INVALID_SEMAPHORE_VALUE_ ); + } +} + +sc_semaphore::sc_semaphore( const char* name_, int init_value_ ) +: sc_object( name_ ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ), + m_value( init_value_ ) +{ + if( m_value < 0 ) { + report_error( SC_ID_INVALID_SEMAPHORE_VALUE_ ); + } +} + + +// interface methods + +// lock (take) the semaphore, block if not available + +int +sc_semaphore::wait() +{ + while( in_use() ) { + sc_core::wait( m_free, sc_get_curr_simcontext() ); + } + -- m_value; + return 0; +} + + +// lock (take) the semaphore, return -1 if not available + +int +sc_semaphore::trywait() +{ + if( in_use() ) { + return -1; + } + -- m_value; + return 0; +} + + +// unlock (give) the semaphore + +int +sc_semaphore::post() +{ + ++m_value; + m_free.notify(); + return 0; +} + +} // namespace sc_core + +// $Log: sc_semaphore.cpp,v $ +// Revision 1.5 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/03/23 16:17:22 acg +// Andy Goodrich: hide the sc_events that are kernel related. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.6 2006/11/28 20:30:49 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_semaphore.h b/ext/systemc/src/sysc/communication/sc_semaphore.h new file mode 100644 index 000000000..3ce991ebf --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_semaphore.h @@ -0,0 +1,133 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_semaphore.h -- The sc_semaphore primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SEMAPHORE_H +#define SC_SEMAPHORE_H + + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/communication/sc_semaphore_if.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_semaphore +// +// The sc_semaphore primitive channel class. +// ---------------------------------------------------------------------------- + +class sc_semaphore +: public sc_semaphore_if, + public sc_object +{ +public: + + // constructors + + explicit sc_semaphore( int init_value_ ); + sc_semaphore( const char* name_, int init_value_ ); + + + // interface methods + + // lock (take) the semaphore, block if not available + virtual int wait(); + + // lock (take) the semaphore, return -1 if not available + virtual int trywait(); + + // unlock (give) the semaphore + virtual int post(); + + // get the value of the semaphore + virtual int get_value() const + { return m_value; } + + virtual const char* kind() const + { return "sc_semaphore"; } + +protected: + + // support methods + + bool in_use() const + { return ( m_value <= 0 ); } + + + // error reporting + void report_error( const char* id, const char* add_msg = 0 ) const; + +protected: + + sc_event m_free; // event to block on when m_value is negative + int m_value; // current value of the semaphore + +private: + + // disabled + sc_semaphore( const sc_semaphore& ); + sc_semaphore& operator = ( const sc_semaphore& ); +}; + +} // namespace sc_core + +//$Log: sc_semaphore.h,v $ +//Revision 1.4 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/11/28 20:30:49 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_semaphore_if.h b/ext/systemc/src/sysc/communication/sc_semaphore_if.h new file mode 100644 index 000000000..b0839e40a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_semaphore_if.h @@ -0,0 +1,100 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_semaphore_if.h -- The sc_semaphore_if interface class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SEMAPHORE_IF_H +#define SC_SEMAPHORE_IF_H + +#include "sysc/communication/sc_interface.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_semaphore_if +// +// The sc_semaphore_if interface class. +// ---------------------------------------------------------------------------- + +class sc_semaphore_if +: virtual public sc_interface +{ +public: + + // the classical operations: wait(), trywait(), and post() + + // lock (take) the semaphore, block if not available + virtual int wait() = 0; + + // lock (take) the semaphore, return -1 if not available + virtual int trywait() = 0; + + // unlock (give) the semaphore + virtual int post() = 0; + + // get the value of the semphore + virtual int get_value() const = 0; + +protected: + + // constructor + + sc_semaphore_if() + {} + +private: + + // disabled + sc_semaphore_if( const sc_semaphore_if& ); + sc_semaphore_if& operator = ( const sc_semaphore_if& ); +}; + +} // namespace sc_core + +//$Log: sc_semaphore_if.h,v $ +//Revision 1.3 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal.cpp b/ext/systemc/src/sysc/communication/sc_signal.cpp new file mode 100644 index 000000000..3b2df8a7c --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal.cpp @@ -0,0 +1,456 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal.cpp -- The sc_signal<T> primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/kernel/sc_reset.h" + +#include <sstream> + +using sc_dt::sc_lv_base; +using sc_dt::sc_signed; +using sc_dt::sc_unsigned; +using sc_dt::int64; +using sc_dt::uint64; + +namespace sc_core { + +// to avoid code bloat in sc_signal<T> + +void +sc_signal_invalid_writer( sc_object* target, sc_object* first_writer, + sc_object* second_writer, bool check_delta ) +{ + if ( second_writer ) + { + std::stringstream msg; + + msg + << "\n signal " + "`" << target->name() << "' " + "(" << target->kind() << ")" + << "\n first driver " + "`" << first_writer->name() << "' " + " (" << first_writer->kind() << ")" + << "\n second driver " + "`" << second_writer->name() << "' " + "(" << second_writer->kind() << ")"; + + if( check_delta ) + { + msg << "\n first conflicting write in delta cycle " + << sc_delta_count(); + } + SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, + msg.str().c_str() ); + } +} + +bool +sc_writer_policy_check_port:: + check_port( sc_object* target, sc_port_base * port_, bool is_output ) +{ + if ( is_output && sc_get_curr_simcontext()->write_check() ) + { + // an out or inout port; only one can be connected + if( m_output != 0) { + sc_signal_invalid_writer( target, m_output, port_, false ); + return false; + } else { + m_output = port_; + } + } + return true; +} + +void sc_deprecated_get_data_ref() +{ + static bool warn_get_data_ref_deprecated=true; + if ( warn_get_data_ref_deprecated ) + { + warn_get_data_ref_deprecated=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "get_data_ref() is deprecated, use read() instead" ); + } +} + +void sc_deprecated_get_new_value() +{ + static bool warn_new_value=true; + if ( warn_new_value ) + { + warn_new_value=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_signal<T>::get_new_value() is deprecated"); + } +} + +void sc_deprecated_trace() +{ + static bool warn_trace_deprecated=true; + if ( warn_trace_deprecated ) + { + warn_trace_deprecated=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_signal<T>::trace() is deprecated"); + } +} + +sc_event* +sc_lazy_kernel_event( sc_event** ev, const char* name ) +{ + if ( !*ev ) { + std::string kernel_name = SC_KERNEL_EVENT_PREFIX "_"; + kernel_name.append( name ); + *ev = new sc_event( kernel_name.c_str() ); + } + return *ev; + +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); + if( !policy_type::check_port( this, &port_, is_output ) ) + ((void)0); // fallback? error has been suppressed ... +} + + +// write the new value + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::write( const bool& value_ ) +{ + bool value_changed = !( m_cur_val == value_ ); + if ( !policy_type::check_write(this, value_changed) ) + return; + m_new_val = value_; + if( value_changed ) { + request_update(); + } +} + +template< sc_writer_policy POL > +inline +void +sc_signal<bool,POL>::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::dump( ::std::ostream& os ) const +{ + os << " name = " << name() << ::std::endl; + os << " value = " << m_cur_val << ::std::endl; + os << "new value = " << m_new_val << ::std::endl; +} + + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::do_update() +{ + // order of execution below is important, the notify_processes() call + // must come after the update of m_cur_val for things to work properly! + + m_cur_val = m_new_val; + + if ( m_reset_p ) m_reset_p->notify_processes(); + + if ( m_change_event_p ) m_change_event_p->notify_next_delta(); + + sc_event* event_p = this->m_cur_val + ? m_posedge_event_p : m_negedge_event_p; + if ( event_p ) event_p->notify_next_delta(); + + m_change_stamp = simcontext()->change_stamp(); +} + +// (edge) event methods + +template< sc_writer_policy POL > +const sc_event& +sc_signal<bool,POL>::value_changed_event() const +{ + return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<bool,POL>::posedge_event() const +{ + return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<bool,POL>::negedge_event() const +{ + return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event"); +} + + +// reset support: + +template< sc_writer_policy POL > +sc_reset* +sc_signal<bool,POL>::is_reset() const +{ + sc_reset* result_p; + if ( !m_reset_p ) m_reset_p = new sc_reset( this ); + result_p = m_reset_p; + return result_p; +} + +// destructor + +template< sc_writer_policy POL > +sc_signal<bool,POL>::~sc_signal() +{ + delete m_change_event_p; + delete m_negedge_event_p; + delete m_posedge_event_p; + delete m_reset_p; +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); + if( !policy_type::check_port( this, &port_, is_output ) ) + ((void)0); // fallback? error has been suppressed ... +} + + +// write the new value + +template< sc_writer_policy POL > +inline +void +sc_signal<sc_dt::sc_logic,POL>::write( const sc_dt::sc_logic& value_ ) +{ + bool value_changed = !( m_cur_val == value_ ); + if ( !policy_type::check_write(this, value_changed) ) + return; + + m_new_val = value_; + if( value_changed ) { + request_update(); + } +} + +template< sc_writer_policy POL > +inline +void +sc_signal<sc_dt::sc_logic,POL>::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::dump( ::std::ostream& os ) const +{ + os << " name = " << name() << ::std::endl; + os << " value = " << m_cur_val << ::std::endl; + os << "new value = " << m_new_val << ::std::endl; +} + + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::do_update() +{ + m_cur_val = m_new_val; + + if ( m_change_event_p ) m_change_event_p->notify_next_delta(); + + if( m_posedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_1) ) { + m_posedge_event_p->notify_next_delta(); + } + else if( m_negedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_0) ) { + m_negedge_event_p->notify_next_delta(); + } + + m_change_stamp = simcontext()->change_stamp(); +} + +// (edge) event methods + +template< sc_writer_policy POL > +const sc_event& +sc_signal<sc_dt::sc_logic,POL>::value_changed_event() const +{ + return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<sc_dt::sc_logic,POL>::posedge_event() const +{ + return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<sc_dt::sc_logic,POL>::negedge_event() const +{ + return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event"); +} + + +// template instantiations for writer policies + +template class sc_signal<bool,SC_ONE_WRITER>; +template class sc_signal<bool,SC_MANY_WRITERS>; +template class sc_signal<bool,SC_UNCHECKED_WRITERS>; + +template class sc_signal<sc_dt::sc_logic,SC_ONE_WRITER>; +template class sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS>; +template class sc_signal<sc_dt::sc_logic,SC_UNCHECKED_WRITERS>; + +} // namespace sc_core + +/* +$Log: sc_signal.cpp,v $ +Revision 1.9 2011/08/26 20:45:42 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.8 2011/02/18 20:23:45 acg + Andy Goodrich: Copyright update. + +Revision 1.7 2011/02/18 20:08:14 acg + Philipp A. Hartmann: addition of include for sstream for MSVC. + +Revision 1.6 2011/01/25 20:50:37 acg + Andy Goodrich: changes for IEEE 1666 2011. + +Revision 1.5 2010/12/07 19:50:36 acg + Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. + +Revision 1.3 2007/04/09 21:59:49 acg + Andy Goodrich: fixed multiple write notification bug where writes + done outside the simulator were being treated as multiple writes. + +Revision 1.2 2007/04/02 17:24:01 acg + Andy Goodrich: added check for null writer pointers in sc_signal invalid + writer method. + +Revision 1.1.1.1 2006/12/15 20:20:04 acg +SystemC 2.3 + +Revision 1.7 2006/04/11 23:11:57 acg + Andy Goodrich: Changes for reset support that only includes + sc_cthread_process instances. + +Revision 1.6 2006/03/13 20:19:44 acg + Andy Goodrich: changed sc_event instances into pointers to sc_event instances + that are allocated as needed. This saves considerable storage for large + numbers of signals, etc. + +Revision 1.5 2006/01/25 00:31:11 acg + Andy Goodrich: Changed over to use a standard message id of + SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. + +Revision 1.4 2006/01/24 20:46:32 acg +Andy Goodrich: changes to eliminate use of deprecated features. For instance, +using notify(SC_ZERO_TIME) in place of notify_delayed(). + +Revision 1.3 2006/01/18 21:42:26 acg +Andy Goodrich: Changes for check writer support, and tightening up sc_clock +port usage. + +Revision 1.2 2006/01/03 23:18:26 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:43 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.14 2005/09/15 23:01:51 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.13 2005/05/08 19:04:06 acg +Fix bug in concat_set(int64,off). Other changes from 2.1 examples usage. + +Revision 1.12 2005/04/04 00:15:51 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.10 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.9 2004/09/27 21:02:54 acg +Andy Goodrich - Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments will appear in + checked out source. + +*/ + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal.h b/ext/systemc/src/sysc/communication/sc_signal.h new file mode 100644 index 000000000..2a72ef55e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal.h @@ -0,0 +1,741 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal.h -- The sc_signal<T> primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_H +#define SC_SIGNAL_H + +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/communication/sc_signal_ifs.h" +#include "sysc/communication/sc_writer_policy.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/tracing/sc_trace.h" +#include <typeinfo> + +namespace sc_core { + +// to avoid code bloat in sc_signal<T> + +extern void sc_deprecated_get_data_ref(); +extern void sc_deprecated_get_new_value(); +extern void sc_deprecated_trace(); +extern sc_event * sc_lazy_kernel_event( sc_event**, const char* name ); + +inline +bool +sc_writer_policy_check_write::check_write( sc_object* target, bool ) +{ + sc_object* writer_p = sc_get_curr_simcontext()->get_current_writer(); + if( SC_UNLIKELY_(m_writer_p == 0) ) { + m_writer_p = writer_p; + } else if( SC_UNLIKELY_(m_writer_p != writer_p && writer_p != 0) ) { + sc_signal_invalid_writer( target, m_writer_p, writer_p, m_check_delta ); + // error has been suppressed, ignore check as well + // return false; + } + return true; +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal<T> +// +// The sc_signal<T> primitive channel class. +// ---------------------------------------------------------------------------- + +template< class T, sc_writer_policy POL /* = SC_DEFAULT_WRITER_POLICY */ > +class sc_signal + : public sc_signal_inout_if<T> + , public sc_prim_channel + , protected sc_writer_policy_check<POL> +{ +protected: + typedef sc_signal_inout_if<T> if_type; + typedef sc_signal<T,POL> this_type; + typedef sc_writer_policy_check<POL> policy_type; + +public: // constructors and destructor: + + sc_signal() + : sc_prim_channel( sc_gen_unique_name( "signal" ) ), + m_change_event_p( 0 ), m_cur_val( T() ), + m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() ) + {} + + explicit sc_signal( const char* name_) + : sc_prim_channel( name_ ), + m_change_event_p( 0 ), m_cur_val( T() ), + m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() ) + {} + + sc_signal( const char* name_, const T& initial_value_ ) + : sc_prim_channel( name_ ) + , m_change_event_p( 0 ) + , m_cur_val( initial_value_ ) + , m_change_stamp( ~sc_dt::UINT64_ONE ) + , m_new_val( initial_value_ ) + {} + + virtual ~sc_signal() + { + delete m_change_event_p; + } + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + virtual sc_writer_policy get_writer_policy() const + { return POL; } + + // get the default event + virtual const sc_event& default_event() const + { return value_changed_event(); } + + // get the value changed event + virtual const sc_event& value_changed_event() const + { + return *sc_lazy_kernel_event( &m_change_event_p + , "value_changed_event"); + } + + + // read the current value + virtual const T& read() const + { return m_cur_val; } + + // get a reference to the current value (for tracing) + virtual const T& get_data_ref() const + { sc_deprecated_get_data_ref(); return m_cur_val; } + + + // was there an event? + virtual bool event() const + { return simcontext()->event_occurred(m_change_stamp); } + + // write the new value + virtual void write( const T& ); + + + // other methods + + operator const T& () const + { return read(); } + + + this_type& operator = ( const T& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<T>& a ) + { write( a.read() ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + + const T& get_new_value() const + { sc_deprecated_get_new_value(); return m_new_val; } + + + void trace( sc_trace_file* tf ) const + { + sc_deprecated_trace(); +# ifdef DEBUG_SYSTEMC + sc_trace( tf, read(), name() ); +# else + if ( tf ) {} +# endif + } + + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_signal"; } + +protected: + + virtual void update(); + void do_update(); + +protected: + + mutable sc_event* m_change_event_p; + T m_cur_val; + sc_dt::uint64 m_change_stamp; // delta of last event + T m_new_val; + +private: + + // disabled + sc_signal( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +template< class T, sc_writer_policy POL > +inline +void +sc_signal<T,POL>::register_port( sc_port_base& port_ + , const char* if_typename_ ) +{ + + bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); + if( !policy_type::check_port( this, &port_, is_output ) ) + ((void)0); // fallback? error has been suppressed ... +} + + +// write the new value + +template< class T, sc_writer_policy POL > +inline +void +sc_signal<T,POL>::write( const T& value_ ) +{ + bool value_changed = !( m_cur_val == value_ ); + if ( !policy_type::check_write(this, value_changed) ) + return; + + m_new_val = value_; + if( value_changed ) { + request_update(); + } +} + + +template< class T, sc_writer_policy POL > +inline +void +sc_signal<T,POL>::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< class T, sc_writer_policy POL > +void +sc_signal<T,POL>::dump( ::std::ostream& os ) const +{ + os << " name = " << name() << ::std::endl; + os << " value = " << m_cur_val << ::std::endl; + os << "new value = " << m_new_val << ::std::endl; +} + + +template< class T, sc_writer_policy POL > +void +sc_signal<T,POL>::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< class T, sc_writer_policy POL > +void +sc_signal<T,POL>::do_update() +{ + m_cur_val = m_new_val; + if ( m_change_event_p ) m_change_event_p->notify_next_delta(); + m_change_stamp = simcontext()->change_stamp(); +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal<bool> +// +// Specialization of sc_signal<T> for type bool. +// ---------------------------------------------------------------------------- + +class sc_reset; + +template< sc_writer_policy POL > +class sc_signal<bool,POL> + : public sc_signal_inout_if<bool> + , public sc_prim_channel + , protected sc_writer_policy_check<POL> +{ +protected: + typedef sc_signal_inout_if<bool> if_type; + typedef sc_signal<bool,POL> this_type; + typedef sc_writer_policy_check<POL> policy_type; + +public: // constructors and destructor: + + sc_signal() + : sc_prim_channel( sc_gen_unique_name( "signal" ) ), + m_change_event_p( 0 ), + m_cur_val( false ), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val( false ), + m_posedge_event_p( 0 ), + m_reset_p( 0 ) + {} + + explicit sc_signal( const char* name_ ) + : sc_prim_channel( name_ ), + m_change_event_p( 0 ), + m_cur_val( false ), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val( false ), + m_posedge_event_p( 0 ), + m_reset_p( 0 ) + {} + + sc_signal( const char* name_, bool initial_value_ ) + : sc_prim_channel( name_ ) + , m_change_event_p( 0 ) + , m_cur_val( initial_value_ ) + , m_change_stamp( ~sc_dt::UINT64_ONE ) + , m_negedge_event_p( 0 ) + , m_new_val( initial_value_ ) + , m_posedge_event_p( 0 ) + , m_reset_p( 0 ) + {} + + virtual ~sc_signal(); + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + virtual sc_writer_policy get_writer_policy() const + { return POL; } + + // get the default event + virtual const sc_event& default_event() const + { return value_changed_event(); } + + // get the value changed event + virtual const sc_event& value_changed_event() const; + + // get the positive edge event + virtual const sc_event& posedge_event() const; + + // get the negative edge event + virtual const sc_event& negedge_event() const; + + + // read the current value + virtual const bool& read() const + { return m_cur_val; } + + // get a reference to the current value (for tracing) + virtual const bool& get_data_ref() const + { sc_deprecated_get_data_ref(); return m_cur_val; } + + + // was there a value changed event? + virtual bool event() const + { return simcontext()->event_occurred(m_change_stamp); } + + // was there a positive edge event? + virtual bool posedge() const + { return ( event() && m_cur_val ); } + + // was there a negative edge event? + virtual bool negedge() const + { return ( event() && ! m_cur_val ); } + + // write the new value + virtual void write( const bool& ); + + // other methods + + operator const bool& () const + { return read(); } + + + this_type& operator = ( const bool& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<bool>& a ) + { write( a.read() ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + + const bool& get_new_value() const + { sc_deprecated_get_new_value(); return m_new_val; } + + + void trace( sc_trace_file* tf ) const + { + sc_deprecated_trace(); +# ifdef DEBUG_SYSTEMC + sc_trace( tf, read(), name() ); +# else + if ( tf ) {} +# endif + } + + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_signal"; } + +protected: + + virtual void update(); + void do_update(); + + virtual bool is_clock() const { return false; } + +protected: + mutable sc_event* m_change_event_p; // value change event if present. + bool m_cur_val; // current value of object. + sc_dt::uint64 m_change_stamp; // delta of last event + mutable sc_event* m_negedge_event_p; // negative edge event if present. + bool m_new_val; // next value of object. + mutable sc_event* m_posedge_event_p; // positive edge event if present. + mutable sc_reset* m_reset_p; // reset mechanism if present. + +private: + + // reset creation + virtual sc_reset* is_reset() const; + + // disabled + sc_signal( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal<sc_dt::sc_logic> +// +// Specialization of sc_signal<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template< sc_writer_policy POL > +class sc_signal<sc_dt::sc_logic,POL> + : public sc_signal_inout_if<sc_dt::sc_logic> + , public sc_prim_channel + , protected sc_writer_policy_check<POL> +{ +protected: + typedef sc_signal_inout_if<sc_dt::sc_logic> if_type; + typedef sc_signal<sc_dt::sc_logic,POL> this_type; + typedef sc_writer_policy_check<POL> policy_type; + +public: // constructors and destructor: + + sc_signal() + : sc_prim_channel( sc_gen_unique_name( "signal" ) ), + m_change_event_p( 0 ), + m_cur_val(), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val(), + m_posedge_event_p( 0 ) + {} + + explicit sc_signal( const char* name_ ) + : sc_prim_channel( name_ ), + m_change_event_p( 0 ), + m_cur_val(), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val(), + m_posedge_event_p( 0 ) + {} + + sc_signal( const char* name_, sc_dt::sc_logic initial_value_ ) + : sc_prim_channel( name_ ) + , m_change_event_p( 0 ) + , m_cur_val( initial_value_ ) + , m_change_stamp( ~sc_dt::UINT64_ONE ) + , m_negedge_event_p( 0 ) + , m_new_val( initial_value_ ) + , m_posedge_event_p( 0 ) + {} + + virtual ~sc_signal() + { + delete m_change_event_p; + delete m_negedge_event_p; + delete m_posedge_event_p; + } + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + virtual sc_writer_policy get_writer_policy() const + { return POL; } + + // get the default event + virtual const sc_event& default_event() const + { return value_changed_event(); } + + // get the value changed event + virtual const sc_event& value_changed_event() const; + + // get the positive edge event + virtual const sc_event& posedge_event() const; + + // get the negative edge event + virtual const sc_event& negedge_event() const; + + + // read the current value + virtual const sc_dt::sc_logic& read() const + { return m_cur_val; } + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_logic& get_data_ref() const + { sc_deprecated_get_data_ref(); return m_cur_val; } + + + // was there an event? + virtual bool event() const + { return simcontext()->event_occurred(m_change_stamp); } + + // was there a positive edge event? + virtual bool posedge() const + { return ( event() && m_cur_val == sc_dt::SC_LOGIC_1 ); } + + // was there a negative edge event? + virtual bool negedge() const + { return ( event() && m_cur_val == sc_dt::SC_LOGIC_0 ); } + + + // write the new value + virtual void write( const sc_dt::sc_logic& ); + + + // other methods + + operator const sc_dt::sc_logic& () const + { return read(); } + + + this_type& operator = ( const sc_dt::sc_logic& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<sc_dt::sc_logic>& a ) + { write( a.read() ); return *this; } + + this_type& operator = (const this_type& a) + { write( a.read() ); return *this; } + + + const sc_dt::sc_logic& get_new_value() const + { sc_deprecated_get_new_value(); return m_new_val; } + + + void trace( sc_trace_file* tf ) const + { + sc_deprecated_trace(); +# ifdef DEBUG_SYSTEMC + sc_trace( tf, read(), name() ); +# else + if ( tf ) {} +# endif + } + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_signal"; } + +protected: + + virtual void update(); + void do_update(); + +protected: + + mutable sc_event* m_change_event_p; // value change event if present. + sc_dt::sc_logic m_cur_val; // current value of object. + sc_dt::uint64 m_change_stamp; // delta of last event + mutable sc_event* m_negedge_event_p; // negative edge event if present. + sc_dt::sc_logic m_new_val; // next value of object. + mutable sc_event* m_posedge_event_p; // positive edge event if present. + +private: + + // disabled + sc_signal( const this_type& ); +}; + +// ---------------------------------------------------------------------------- + +template< typename T, sc_writer_policy POL > +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_signal<T,POL>& a ) +{ + return ( os << a.read() ); +} + + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +//$Log: sc_signal.h,v $ +//Revision 1.16 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.15 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +//Revision 1.14 2011/06/25 17:08:38 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +//Revision 1.13 2011/04/13 02:59:09 acg +// Andy Goodrich: made events internal to signals into kernel events. +// +//Revision 1.12 2011/04/08 18:22:46 acg +// Philipp A. Hartmann: use the context of the primitive channel to get +// the change stamp value. +// +//Revision 1.11 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +//Revision 1.10 2011/04/05 07:10:55 acg +// Andy Goodrich: added line that I dropped in sc_signal<sc_dt::sc_logic>. +// +//Revision 1.9 2011/04/05 06:15:18 acg +// Philipp A. Hartmann: sc_writer_policy: ignore no-ops in delta check. +// +//Revision 1.8 2011/03/23 16:17:22 acg +// Andy Goodrich: hide the sc_events that are kernel related. +// +//Revision 1.7 2011/03/06 15:55:08 acg +// Andy Goodrich: Changes for named events. +// +//Revision 1.6 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.5 2011/02/07 19:16:50 acg +// Andy Goodrich: changes for handling multiple writers. +// +//Revision 1.4 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.3 2010/12/07 19:50:37 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.14 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +//Revision 1.12 2006/04/11 23:11:57 acg +// Andy Goodrich: Changes for reset support that only includes +// sc_cthread_process instances. +// +//Revision 1.11 2006/03/13 20:19:44 acg +// Andy Goodrich: changed sc_event instances into pointers to sc_event instances +// that are allocated as needed. This saves considerable storage for large +// numbers of signals, etc. +// +//Revision 1.10 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +//Revision 1.9 2006/01/24 20:45:41 acg +//Andy Goodrich: converted notify_delayed() calls into notify_next_delta() calls +//to eliminate deprecation warnings. notify_next_delta() is an implemenation- +//dependent method of sc_event. It is simpler than notify_delayed(), and should +//speed up simulation speeds. +// +//Revision 1.8 2006/01/19 19:18:25 acg +//Andy Goodrich: eliminated check_writer in favor of inline code within the +//write() method since we always execute the check_writer code even when +//check writing is turned off. +// +//Revision 1.7 2006/01/19 00:30:57 acg +//Andy Goodrich: Yet another implementation for disabling write checks on +//signals. This version uses an environment variable, SC_SIGNAL_WRITE_CHECK, +//that when set to DISABLE will turn off write checking. +// +//Revision 1.6 2006/01/18 21:42:26 acg +//Andy Goodrich: Changes for check writer support, and tightening up sc_clock +//port usage. +// +//Revision 1.5 2006/01/13 20:41:59 acg +//Andy Goodrich: Changes to add port registration to the things that are +//checked when SC_NO_WRITE_CHECK is not defined. +// +//Revision 1.4 2006/01/13 18:47:20 acg +//Reversed sense of multiwriter signal check. It now defaults to ON unless the +//user defines SC_NO_WRITE_CHEK before inclusion of the file. +// +//Revision 1.3 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.2 2005/12/20 21:58:18 acg +//Removed Makefile.in, changed the event() methods to use sc_simcontext::event_occurred. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.19 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.18 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_ifs.h b/ext/systemc/src/sysc/communication/sc_signal_ifs.h new file mode 100644 index 000000000..ad703aaa7 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_ifs.h @@ -0,0 +1,305 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_ifs.h -- The sc_signal<T> interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_IFS_H +#define SC_SIGNAL_IFS_H + + +#include "sysc/communication/sc_interface.h" +#include "sysc/communication/sc_writer_policy.h" + + +namespace sc_dt +{ + class sc_logic; +} + +namespace sc_core { + +class sc_signal_bool_deval; +class sc_signal_logic_deval; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if<T> +// +// The sc_signal<T> input interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_signal_in_if +: virtual public sc_interface +{ +public: + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + + // read the current value + virtual const T& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const T& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + +protected: + + // constructor + + sc_signal_in_if() + {} + +private: + + // disabled + sc_signal_in_if( const sc_signal_in_if<T>& ); + sc_signal_in_if<T>& operator = ( const sc_signal_in_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if<bool> +// +// Specialization of sc_signal_in_if<T> for type bool. +// ---------------------------------------------------------------------------- + +class sc_reset; + +template <> +class sc_signal_in_if<bool> +: virtual public sc_interface +{ + friend class sc_reset; +public: + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + // get the positive edge event + virtual const sc_event& posedge_event() const = 0; + + // get the negative edge event + virtual const sc_event& negedge_event() const = 0; + + + // read the current value + virtual const bool& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const bool& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + // was there a positive edge event? + virtual bool posedge() const = 0; + + // was there a negative edge event? + virtual bool negedge() const = 0; + +protected: + + // constructor + + sc_signal_in_if() + {} + +private: + + // disabled + sc_signal_in_if( const sc_signal_in_if<bool>& ); + sc_signal_in_if<bool>& operator = ( const sc_signal_in_if<bool>& ); + + // designate this object as a reset signal + virtual sc_reset* is_reset() const + { return NULL; } +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if<sc_dt::sc_logic> +// +// Specialization of sc_signal_in_if<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_signal_in_if<sc_dt::sc_logic> +: virtual public sc_interface +{ +public: + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + // get the positive edge event + virtual const sc_event& posedge_event() const = 0; + + // get the negative edge event + virtual const sc_event& negedge_event() const = 0; + + + // read the current value + virtual const sc_dt::sc_logic& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_logic& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + // was there a positive edge event? + virtual bool posedge() const = 0; + + // was there a negative edge event? + virtual bool negedge() const = 0; + + +protected: + + // constructor + + sc_signal_in_if() + {} + +private: + + // disabled + sc_signal_in_if( const sc_signal_in_if<sc_dt::sc_logic>& ); + sc_signal_in_if<sc_dt::sc_logic>& operator = ( + const sc_signal_in_if<sc_dt::sc_logic>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_write_if<T> +// +// The standard output interface class. +// ---------------------------------------------------------------------------- +template< typename T > +class sc_signal_write_if : public virtual sc_interface +{ +public: + sc_signal_write_if() {} + // write the new value + virtual void write( const T& ) = 0; + virtual sc_writer_policy get_writer_policy() const + { return SC_DEFAULT_WRITER_POLICY; } +private: + // disabled + sc_signal_write_if( const sc_signal_write_if<T>& ); + sc_signal_write_if<T>& operator = ( const sc_signal_write_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_inout_if<T> +// +// The sc_signal<T> input/output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_signal_inout_if +: public sc_signal_in_if<T>, public sc_signal_write_if<T> +{ + +protected: + + // constructor + + sc_signal_inout_if() + {} + +private: + + // disabled + sc_signal_inout_if( const sc_signal_inout_if<T>& ); + sc_signal_inout_if<T>& operator = ( const sc_signal_inout_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_out_if<T> +// +// The sc_signal<T> output interface class. +// ---------------------------------------------------------------------------- + +// sc_signal_out_if can also be read from, hence no difference with +// sc_signal_inout_if. + +#define sc_signal_out_if sc_signal_inout_if + +} // namespace sc_core + +//$Log: sc_signal_ifs.h,v $ +//Revision 1.4 2011/08/26 20:45:43 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/12/07 19:50:37 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/08/29 23:35:00 acg +// Andy Goodrich: added bind_count() method to allow users to determine which +// ports are connected in before_end_of_elaboration(). +// +//Revision 1.3 2006/04/11 23:11:57 acg +// Andy Goodrich: Changes for reset support that only includes +// sc_cthread_process instances. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/29 18:12:12 acg +//Added $log. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_ports.cpp b/ext/systemc/src/sysc/communication/sc_signal_ports.cpp new file mode 100644 index 000000000..d3a182e54 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_ports.cpp @@ -0,0 +1,441 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_ports.cpp -- The sc_signal<T> port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-08-20 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<bool> +// +// Specialization of sc_in<T> for type bool. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in<bool>::end_of_elaboration() +{ + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + +// called by sc_trace + +void +sc_in<bool>::add_trace_internal(sc_trace_file* tf_, + const std::string& name_) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +void +sc_in<bool>::add_trace(sc_trace_file* tf_, + const std::string& name_) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_in<bool>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// called by pbind (for internal use only) + +int +sc_in<bool>::vbind( sc_interface& interface_ ) +{ + return sc_port_b<if_type>::vbind( interface_ ); +} + +int +sc_in<bool>::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<sc_logic> +// +// Specialization of sc_in<T> for type sc_logic. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in<sc_dt::sc_logic>::end_of_elaboration() +{ + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_in<sc_dt::sc_logic>::add_trace_internal( sc_trace_file* tf_, + const std::string& name_ ) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +void +sc_in<sc_dt::sc_logic>::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_in<sc_dt::sc_logic>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// called by pbind (for internal use only) + +int +sc_in<sc_dt::sc_logic>::vbind( sc_interface& interface_ ) +{ + return sc_port_b<if_type>::vbind( interface_ ); +} + +int +sc_in<sc_dt::sc_logic>::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<bool> +// +// Specialization of sc_inout<T> for type bool. +// ---------------------------------------------------------------------------- + +// destructor + +sc_inout<bool>::~sc_inout() +{ + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + delete m_init_val; + remove_traces(); +} + + +// set initial value (can also be called when port is not bound yet) + +void +sc_inout<bool>::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST<inout_if_type*>( get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val == 0 ) { + m_init_val = new data_type; + } + *m_init_val = value_; + } +} + + +// called when elaboration is done + +void +sc_inout<bool>::end_of_elaboration() +{ + if( m_init_val != 0 ) { + write( *m_init_val ); + delete m_init_val; + m_init_val = 0; + } + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_inout<bool>::add_trace_internal( sc_trace_file* tf_, + const std::string& name_ ) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +void +sc_inout<bool>::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_inout<bool>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<sc_dt::sc_logic> +// +// Specialization of sc_inout<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +// destructor + +sc_inout<sc_dt::sc_logic>::~sc_inout() +{ + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + delete m_init_val; + remove_traces(); +} + + +// set initial value (can also be called when port is not bound yet) + +void +sc_inout<sc_dt::sc_logic>::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST<inout_if_type*>( get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val == 0 ) { + m_init_val = new data_type; + } + *m_init_val = value_; + } +} + + +// called when elaboration is done + +void +sc_inout<sc_dt::sc_logic>::end_of_elaboration() +{ + if( m_init_val != 0 ) { + write( *m_init_val ); + delete m_init_val; + m_init_val = 0; + } + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_inout<sc_dt::sc_logic>::add_trace_internal( sc_trace_file* tf_, + const std::string& name_ ) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + + +void +sc_inout<sc_dt::sc_logic>::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_inout<sc_dt::sc_logic>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + +void sc_deprecated_add_trace() +{ + static bool warn_add_trace_deprecated=true; + if ( warn_add_trace_deprecated ) + { + warn_add_trace_deprecated=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_signal<T>::addtrace() is deprecated"); + } +} +} // namespace sc_core + +// $Log: sc_signal_ports.cpp,v $ +// Revision 1.3 2011/08/26 20:45:43 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.8 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +// Revision 1.7 2006/04/18 18:01:26 acg +// Andy Goodrich: added an add_trace_internal() method to the various port +// classes so that sc_trace has something to call that won't emit an +// IEEE 1666 deprecation message. +// +// Revision 1.6 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +// Revision 1.5 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:46:32 acg +// Andy Goodrich: changes to eliminate use of deprecated features. For instance, +// using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_ports.h b/ext/systemc/src/sysc/communication/sc_signal_ports.h new file mode 100644 index 000000000..22c83c583 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_ports.h @@ -0,0 +1,1931 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_ports.h -- The sc_signal<T> port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_PORTS_H +#define SC_SIGNAL_PORTS_H + + +#include "sysc/communication/sc_event_finder.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_signal_ifs.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/tracing/sc_trace.h" + +#if ! defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_VIRTUAL_ virtual +#else +# define SC_VIRTUAL_ /* non-virtual */ +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// STRUCT : sc_trace_params +// +// Struct for storing the trace file and object name of an sc_trace call. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +extern void sc_deprecated_add_trace(); + +struct sc_trace_params +{ + sc_trace_file* tf; + std::string name; + + sc_trace_params( sc_trace_file* tf_, const std::string& name_ ) + : tf( tf_ ), name( name_ ) + {} +}; + + +typedef std::vector<sc_trace_params*> sc_trace_params_vec; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<T> +// +// The sc_signal<T> input port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_in +: public sc_port<sc_signal_in_if<T>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_signal_in_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<data_type> this_type; + typedef typename base_type::port_type base_port_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<data_type> inout_if_type; + typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; + +public: + + // constructors + + sc_in() + : base_type(), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ), + m_change_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + + // destructor + + virtual ~sc_in() + { + remove_traces(); + delete m_change_finder_p; + } + + + // bind to in interface + + SC_VIRTUAL_ void bind( const in_if_type& interface_ ) + { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST<const in_if_type&>( interface_ ) ); } + + void operator () ( const in_if_type& interface_ ) + { this->bind( interface_ ); } + + + // bind to parent in port + + SC_VIRTUAL_ void bind( in_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( in_port_type& parent_ ) + { this->bind( parent_ ); } + + + // bind to parent inout port + + SC_VIRTUAL_ void bind( inout_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( inout_port_type& parent_ ) + { this->bind( parent_ ); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in"; } + + + void add_trace( sc_trace_file*, const std::string& ) const; + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +protected: + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + + // implement virtual base_type port-binding function + // - avoids warnings on some compilers + // - should only be called, when using sc_port_b explicitly + // - errors are detected during elaboration + + SC_VIRTUAL_ void bind( base_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + +private: + mutable sc_event_finder* m_change_finder_p; + +private: + + // disabled + sc_in( const this_type& ); + this_type& operator = ( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + +template<typename T> +::std::ostream& operator << ( ::std::ostream& os, const sc_in<T>& a ) +{ + return os << a->read(); +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// called when elaboration is done + +template <class T> +inline +void +sc_in<T>::end_of_elaboration() +{ + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( this->get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +template <class T> +inline +void +sc_in<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_ ) +const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +template <class T> +inline +void +sc_in<T>::add_trace( sc_trace_file* tf_, const std::string& name_ ) +const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +template <class T> +inline +void +sc_in<T>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = (int)m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// called by pbind (for internal use only) + +template <class T> +inline +int +sc_in<T>::vbind( sc_interface& interface_ ) +{ + return sc_port_b<if_type>::vbind( interface_ ); +} + +template <class T> +inline +int +sc_in<T>::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<bool> +// +// Specialization of sc_in<T> for type bool. +// ---------------------------------------------------------------------------- + +template <> +class sc_in<bool> : + public sc_port<sc_signal_in_if<bool>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef bool data_type; + + typedef sc_signal_in_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<data_type> this_type; + typedef /* typename */ base_type::port_type base_port_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<data_type> inout_if_type; + typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; + +public: + + // constructors + + sc_in() + : base_type(), m_traces( 0 ), m_change_finder_p(0), + m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ), m_change_finder_p(0), + m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + +#if defined(TESTING) + sc_in( const this_type& parent_ ) + : base_type( *(in_if_type*)parent_.get_interface() ) , m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} +#endif + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_in() + { + remove_traces(); + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + } + + + // bind to in interface + + SC_VIRTUAL_ void bind( const in_if_type& interface_ ) + { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST<const in_if_type&>( interface_ ) ); } + + void operator () ( const in_if_type& interface_ ) + { this->bind( interface_ ); } + + + // bind to parent in port + + SC_VIRTUAL_ void bind( in_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( in_port_type& parent_ ) + { this->bind( parent_ ); } + + + // bind to parent inout port + + SC_VIRTUAL_ void bind( inout_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( inout_port_type& parent_ ) + { this->bind( parent_ ); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in"; } + + + void add_trace( sc_trace_file*, const std::string& ) const; + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +protected: + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + + // implement virtual base_type port-binding function + // - avoids warnings on some compilers + // - should only be called, when using sc_port_b explicitly + // - errors are detected during elaboration + + SC_VIRTUAL_ void bind( base_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled +#if defined(TESTING) +#else + sc_in( const this_type& ); +#endif + this_type& operator = ( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<sc_dt::sc_logic> +// +// Specialization of sc_in<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_in<sc_dt::sc_logic> +: public sc_port<sc_signal_in_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_signal_in_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<data_type> this_type; + typedef /* typename */ base_type::port_type base_port_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<data_type> inout_if_type; + typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; + +public: + + // constructors + + sc_in() + : base_type(), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_in() + { + remove_traces(); + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + } + + + // bind to in interface + + SC_VIRTUAL_ void bind( const in_if_type& interface_ ) + { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST<const in_if_type&>( interface_ ) ); } + + void operator () ( const in_if_type& interface_ ) + { this->bind( interface_ ); } + + + // bind to parent in port + + SC_VIRTUAL_ void bind( in_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( in_port_type& parent_ ) + { this->bind( parent_ ); } + + + // bind to parent inout port + + SC_VIRTUAL_ void bind( inout_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( inout_port_type& parent_ ) + { this->bind( parent_ ); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in"; } + + + void add_trace( sc_trace_file*, const std::string& ) const; + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +protected: + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + + // implement virtual base_type port-binding function + // - avoids warnings on some compilers + // - should only be called, when using sc_port_b explicitly + // - errors are detected during elaboration + + SC_VIRTUAL_ void bind( base_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled + sc_in( const this_type& ); + this_type& operator = ( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<T> +// +// The sc_signal<T> input/output port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_inout +: public sc_port<sc_signal_inout_if<T>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_signal_inout_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<data_type> this_type; + + typedef sc_signal_in_if<data_type> in_if_type; + typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; + typedef if_type inout_if_type; + typedef base_type inout_port_type; + +public: + + // constructors + + sc_inout() + : base_type(), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + + // destructor + + virtual ~sc_inout(); + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // write the new value + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // set initial value (can also be called when port is not bound yet) + + void initialize( const data_type& value_ ); + + void initialize( const in_if_type& interface_ ) + { initialize( interface_.read() ); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + virtual const char* kind() const + { return "sc_inout"; } + +protected: + + data_type* m_init_val; + +public: + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + + void add_trace( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +private: + mutable sc_event_finder* m_change_finder_p; + +private: + + // disabled + sc_inout( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + +template<typename T> +::std::ostream& operator << ( ::std::ostream& os, const sc_inout<T>& a ) +{ + return os << a->read(); +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// destructor + +template <class T> +inline +sc_inout<T>::~sc_inout() +{ + delete m_change_finder_p; + delete m_init_val; + remove_traces(); +} + + +// set initial value (can also be called when port is not bound yet) + +template <class T> +inline +void +sc_inout<T>::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST<inout_if_type*>( this->get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val == 0 ) { + m_init_val = new data_type; + } + *m_init_val = value_; + } +} + + +// called when elaboration is done + +template <class T> +inline +void +sc_inout<T>::end_of_elaboration() +{ + if( m_init_val != 0 ) { + write( *m_init_val ); + delete m_init_val; + m_init_val = 0; + } + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( this->get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +template <class T> +inline +void +sc_inout<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_) +const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +template <class T> +inline +void +sc_inout<T>::add_trace( sc_trace_file* tf_, const std::string& name_) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +template <class T> +inline +void +sc_inout<T>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<bool> +// +// Specialization of sc_inout<T> for type bool. +// ---------------------------------------------------------------------------- + +template <> +class sc_inout<bool> : + public sc_port<sc_signal_inout_if<bool>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef bool data_type; + + typedef sc_signal_inout_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<data_type> this_type; + + typedef sc_signal_in_if<data_type> in_if_type; + typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; + typedef if_type inout_if_type; + typedef base_type inout_port_type; + +public: + + // constructors + + sc_inout() + : base_type(), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_inout(); + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // write the new value + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // set initial value (can also be called when port is not bound yet) + + void initialize( const data_type& value_ ); + + void initialize( const in_if_type& interface_ ) + { initialize( interface_.read() ); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + virtual const char* kind() const + { return "sc_inout"; } + +protected: + + data_type* m_init_val; + +public: + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + + void add_trace( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled + sc_inout( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<sc_dt::sc_logic> +// +// Specialization of sc_inout<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_inout<sc_dt::sc_logic> +: public sc_port<sc_signal_inout_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_signal_inout_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<data_type> this_type; + + typedef sc_signal_in_if<data_type> in_if_type; + typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; + typedef if_type inout_if_type; + typedef base_type inout_port_type; + +public: + + // constructors + + sc_inout() + : base_type(), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_inout(); + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // write the new value + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // set initial value (can also be called when port is not bound yet) + + void initialize( const data_type& value_ ); + + void initialize( const in_if_type& interface_ ) + { initialize( interface_.read() ); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + virtual const char* kind() const + { return "sc_inout"; } + +protected: + + data_type* m_init_val; + +public: + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + + void add_trace( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled + sc_inout( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out<T> +// +// The sc_signal<T> output port class. +// ---------------------------------------------------------------------------- + +// sc_out can also read from its port, hence no difference with sc_inout. +// For debugging reasons, a class is provided instead of a define. + +template <class T> +class sc_out +: public sc_inout<T> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_out<data_type> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_out() + : base_type() + {} + + explicit sc_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_out() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + virtual const char* kind() const + { return "sc_out"; } + +private: + + // disabled + sc_out( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_trace +// ---------------------------------------------------------------------------- + +template <class T> +inline +void +sc_trace(sc_trace_file* tf, const sc_in<T>& port, const std::string& name) +{ + const sc_signal_in_if<T>* iface = 0; + if (sc_get_curr_simcontext()->elaboration_done() ) + { + iface = DCAST<const sc_signal_in_if<T>*>( port.get_interface() ); + } + + if ( iface ) + sc_trace( tf, iface->read(), name ); + else + port.add_trace_internal( tf, name ); +} + +template <class T> +inline +void +sc_trace( sc_trace_file* tf, const sc_inout<T>& port, + const std::string& name ) +{ + const sc_signal_in_if<T>* iface = 0; + if (sc_get_curr_simcontext()->elaboration_done() ) + { + iface =DCAST<const sc_signal_in_if<T>*>( port.get_interface() ); + } + + if ( iface ) + sc_trace( tf, iface->read(), name ); + else + port.add_trace_internal( tf, name ); +} + +} // namespace sc_core + +#undef SC_VIRTUAL_ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Jason Elbaum, Motorola, Inc., 2001-11-12 + Description of Modification: Added a static, private, otherwise + unused data member to the sc_in + and sc_inout classes to address + a bug in the GNU compiler *only*. + This works around a bug in g++ 2.95.2 + regarding implicit casting from a + templated class to a C++ intrinsic type. + + *****************************************************************************/ +//$Log: sc_signal_ports.h,v $ +//Revision 1.10 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +//Revision 1.9 2011/08/26 20:45:43 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.8 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +//Revision 1.7 2011/08/07 18:53:09 acg +// Philipp A. Hartmann: add virtual instances of the bind function for +// base classes to eliminate warning messages for clang platforms. +// +//Revision 1.6 2011/04/02 00:03:23 acg +// Andy Goodrich: catch the other bind()'s that I missed in Philipp's update. +// +//Revision 1.5 2011/04/01 22:33:31 acg +// Philipp A. Harmann: Use const interface signature to implement non-const +// interface signature for virtual bind(...). +// +//Revision 1.4 2011/03/30 16:46:10 acg +// Andy Goodrich: added a signature and removed a virtual specification +// to eliminate warnings with certain compilers. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.11 2006/04/18 23:36:50 acg +// Andy Goodrich: made add_trace_internal public until I can figure out +// how to do a friend specification for sc_trace in an environment where +// there are partial template and full template specifications for its +// arguments. +// +//Revision 1.10 2006/04/18 18:01:26 acg +// Andy Goodrich: added an add_trace_internal() method to the various port +// classes so that sc_trace has something to call that won't emit an +// IEEE 1666 deprecation message. +// +//Revision 1.9 2006/03/13 20:19:44 acg +// Andy Goodrich: changed sc_event instances into pointers to sc_event instances +// that are allocated as needed. This saves considerable storage for large +// numbers of signals, etc. +// +//Revision 1.8 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +//Revision 1.7 2006/02/02 21:38:12 acg +// Andy Goodrich: fix to the comment log. +// +//Revision 1.4 2006/01/24 20:46:32 acg +//Andy Goodrich: changes to eliminate use of deprecated features. For instance, +//using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +//Revision 1.3 2006/01/13 18:47:42 acg +//Added $Log command so that CVS comments are reproduced in the source. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.18 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.17 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved.cpp b/ext/systemc/src/sysc/communication/sc_signal_resolved.cpp new file mode 100644 index 000000000..2b0aeca0b --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved.cpp @@ -0,0 +1,152 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved.cpp -- The resolved signal class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/communication/sc_signal_resolved.h" + +namespace sc_core { + +// Note that we assume that two drivers driving the resolved signal to a 1 or +// 0 is O.K. This might not be true for all technologies, but is certainly +// true for CMOS, the predominant technology in use today. + +const sc_dt::sc_logic_value_t +sc_logic_resolution_tbl[4][4] = +{ // 0 1 Z X + { sc_dt::Log_0, sc_dt::Log_X, sc_dt::Log_0, sc_dt::Log_X }, // 0 + { sc_dt::Log_X, sc_dt::Log_1, sc_dt::Log_1, sc_dt::Log_X }, // 1 + { sc_dt::Log_0, sc_dt::Log_1, sc_dt::Log_Z, sc_dt::Log_X }, // Z + { sc_dt::Log_X, sc_dt::Log_X, sc_dt::Log_X, sc_dt::Log_X } // X +}; + + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_logic_resolve +// +// Resolution function for sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +// resolves sc_dt::sc_logic values and returns the resolved value + +static void +sc_logic_resolve( sc_dt::sc_logic& result_, + const std::vector<sc_dt::sc_logic>& values_ ) +{ + int sz = values_.size(); + + assert( sz != 0 ); + + if( sz == 1 ) { + result_ = values_[0]; + return; + } + + sc_dt::sc_logic_value_t res = values_[0].value(); + for( int i = sz - 1; i > 0 && res != sc_dt::Log_X; -- i ) { + res = sc_logic_resolution_tbl[res][values_[i].value()]; + } + result_ = res; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_resolved +// +// The resolved signal class. +// ---------------------------------------------------------------------------- + +// write the new value + +void +sc_signal_resolved::write( const data_type& value_ ) +{ + sc_process_b* cur_proc = sc_get_current_process_b(); + + bool value_changed = false; + bool found = false; + + for( int i = m_proc_vec.size() - 1; i >= 0; -- i ) { + if( cur_proc == m_proc_vec[i] ) { + if( value_ != m_val_vec[i] ) { + m_val_vec[i] = value_; + value_changed = true; + } + found = true; + break; + } + } + + if( ! found ) { + m_proc_vec.push_back( cur_proc ); + m_val_vec.push_back( value_ ); + value_changed = true; + } + + if( value_changed ) { + request_update(); + } +} + + +void +sc_signal_resolved::update() +{ + sc_logic_resolve( m_new_val, m_val_vec ); + base_type::update(); +} + + +} // namespace sc_core + +// $Log: sc_signal_resolved.cpp,v $ +// Revision 1.5 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.3 2011/02/07 19:16:50 acg +// Andy Goodrich: changes for handling multiple writers. +// +// Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/21 00:00:27 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved.h b/ext/systemc/src/sysc/communication/sc_signal_resolved.h new file mode 100644 index 000000000..f5e8c714e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved.h @@ -0,0 +1,153 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved.h -- The resolved signal class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_SIGNAL_RESOLVED_H +#define SC_SIGNAL_RESOLVED_H + + +#include "sysc/communication/sc_signal.h" + +namespace sc_core { + +class sc_process_b; + +extern const sc_dt::sc_logic_value_t sc_logic_resolution_tbl[4][4]; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_resolved +// +// The resolved signal class. +// ---------------------------------------------------------------------------- + +class sc_signal_resolved +: public sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS> +{ +public: + + // typedefs + + typedef sc_signal_resolved this_type; + typedef sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS> base_type; + typedef sc_dt::sc_logic data_type; + +public: + + // constructors + + sc_signal_resolved() : + base_type( sc_gen_unique_name( "signal_resolved" ) ), m_proc_vec(), + m_val_vec() + {} + + explicit sc_signal_resolved( const char* name_ ): + base_type( name_ ), m_proc_vec(), m_val_vec() + {} + + sc_signal_resolved( const char* name_, const data_type & initial_value_ ) + : base_type( name_, initial_value_ ) + , m_proc_vec() + , m_val_vec() + {} + + // interface methods + + virtual void register_port( sc_port_base&, const char* ) + {} + + + // write the new value + virtual void write( const data_type& ); + + + // other methods + + this_type& operator = ( const data_type& a ) + { write( a ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + virtual const char* kind() const + { return "sc_signal_resolved"; } + +protected: + + virtual void update(); + +protected: + + std::vector<sc_process_b*> m_proc_vec; // processes writing this signal + std::vector<data_type> m_val_vec; // new values written this signal + +private: + + // disabled + sc_signal_resolved( const this_type& ); +}; + +} // namespace sc_core + +//$Log: sc_signal_resolved.h,v $ +//Revision 1.6 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.5 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +//Revision 1.4 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.cpp b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.cpp new file mode 100644 index 000000000..17da6396a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.cpp @@ -0,0 +1,107 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved_ports.cpp -- The sc_signal_resolved port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-08-20 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include <cstdio> + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_signal_resolved.h" +#include "sysc/communication/sc_signal_resolved_ports.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in_resolved +// +// The sc_signal_resolved input port class. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in_resolved::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_resolved*>( get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout_resolved +// +// The sc_signal_resolved input/output port class. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_inout_resolved::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_resolved*>( get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out_resolved +// +// The sc_signal_resolved output port class. +// ---------------------------------------------------------------------------- + +} // namespace sc_core + +// $Log: sc_signal_resolved_ports.cpp,v $ +// Revision 1.4 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2011/02/07 19:16:50 acg +// Andy Goodrich: changes for handling multiple writers. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.h b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.h new file mode 100644 index 000000000..6b0d777d7 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.h @@ -0,0 +1,349 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved_ports.h -- The sc_signal_resolved port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-08-20 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_RESOLVED_PORTS_H +#define SC_SIGNAL_RESOLVED_PORTS_H + + +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/datatypes/bit/sc_logic.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in_resolved +// +// The sc_signal_resolved input port class. +// ---------------------------------------------------------------------------- + +class sc_in_resolved + : public sc_in<sc_dt::sc_logic> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_in_resolved this_type; + typedef sc_in<data_type> base_type; + + typedef base_type::in_if_type in_if_type; + typedef base_type::in_port_type in_port_type; + typedef base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_in_resolved() + : base_type() + {} + + explicit sc_in_resolved( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_in_resolved( const in_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_in_resolved( const char* name_, const in_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_in_resolved( in_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_resolved( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + explicit sc_in_resolved( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_resolved( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_in_resolved( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_resolved( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_in_resolved() + {} + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in_resolved"; } + +private: + + // disabled + sc_in_resolved( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout_resolved +// +// The sc_signal_resolved input/output port class. +// ---------------------------------------------------------------------------- + +class sc_inout_resolved + : public sc_inout<sc_dt::sc_logic> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_inout_resolved this_type; + typedef sc_inout<data_type> base_type; + + typedef base_type::in_if_type in_if_type; + typedef base_type::in_port_type in_port_type; + typedef base_type::inout_if_type inout_if_type; + typedef base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_inout_resolved() + : base_type() + {} + + explicit sc_inout_resolved( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_inout_resolved( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_inout_resolved( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_inout_resolved( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_resolved( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_inout_resolved( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_resolved( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_inout_resolved() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_inout_resolved"; } + +private: + + // disabled + sc_inout_resolved( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out_resolved +// +// The sc_signal_resolved output port class. +// ---------------------------------------------------------------------------- + +// sc_out_resolved can also read from its port, hence no difference with +// sc_inout_resolved. For debugging reasons, a class is provided instead +// of a typedef. + +class sc_out_resolved + : public sc_inout_resolved +{ +public: + + // typedefs + + typedef sc_out_resolved this_type; + typedef sc_inout_resolved base_type; + + typedef base_type::data_type data_type; + + typedef base_type::in_if_type in_if_type; + typedef base_type::in_port_type in_port_type; + typedef base_type::inout_if_type inout_if_type; + typedef base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_out_resolved() + : base_type() + {} + + explicit sc_out_resolved( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out_resolved( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out_resolved( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out_resolved( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_resolved( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out_resolved( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_resolved( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_out_resolved() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + virtual const char* kind() const + { return "sc_out_resolved"; } + +private: + + // disabled + sc_out_resolved( const this_type& ); +}; + +} // namespace sc_core + +//$Log: sc_signal_resolved_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_rv.h b/ext/systemc/src/sysc/communication/sc_signal_rv.h new file mode 100644 index 000000000..0d870e78e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_rv.h @@ -0,0 +1,255 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_rv.h -- The resolved vector signal class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_RV_H +#define SC_SIGNAL_RV_H + +#include "sysc/communication/sc_signal.h" +#include "sysc/datatypes/bit/sc_lv.h" + +namespace sc_core { + +class sc_process_b; + + +// ---------------------------------------------------------------------------- +// CLASS sc_lv_resolve<W> +// +// Resolution function for sc_dt::sc_lv<W>. +// ---------------------------------------------------------------------------- + +extern const sc_dt::sc_logic_value_t sc_logic_resolution_tbl[4][4]; + + +template <int W> +class sc_lv_resolve +{ +public: + + // resolves sc_dt::sc_lv<W> values and returns the resolved value + static void resolve(sc_dt::sc_lv<W>&, const std::vector<sc_dt::sc_lv<W>*>&); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// resolves sc_dt::sc_lv<W> values and returns the resolved value + +template <int W> +inline +void +sc_lv_resolve<W>::resolve( sc_dt::sc_lv<W>& result_, + const std::vector<sc_dt::sc_lv<W>*>& values_ ) +{ + int sz = values_.size(); + + assert( sz != 0 ); + + if( sz == 1 ) { + result_ = *values_[0]; + return; + } + + for( int j = result_.length() - 1; j >= 0; -- j ) { + sc_dt::sc_logic_value_t res = (*values_[0])[j].value(); + for( int i = sz - 1; i > 0 && res != 3; -- i ) { + res = sc_logic_resolution_tbl[res][(*values_[i])[j].value()]; + } + result_[j] = res; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_rv<W> +// +// The resolved vector signal class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_signal_rv +: public sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS> +{ +public: + + // typedefs + + typedef sc_signal_rv<W> this_type; + typedef sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS> base_type; + typedef sc_dt::sc_lv<W> data_type; + +public: + + // constructors + + sc_signal_rv() + : base_type( sc_gen_unique_name( "signal_rv" ) ) + {} + + explicit sc_signal_rv( const char* name_ ) + : base_type( name_ ) + {} + + + // destructor + virtual ~sc_signal_rv(); + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ) + {} + + + // write the new value + virtual void write( const data_type& ); + + + // other methods + + this_type& operator = ( const data_type& a ) + { write( a ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + virtual const char* kind() const + { return "sc_signal_rv"; } + +protected: + + virtual void update(); + +protected: + + std::vector<sc_process_b*> m_proc_vec; // processes writing this signal + std::vector<data_type*> m_val_vec; // new values written this signal + +private: + + // disabled + sc_signal_rv( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// destructor + +template <int W> +inline +sc_signal_rv<W>::~sc_signal_rv() +{ + for( int i = m_val_vec.size() - 1; i >= 0; -- i ) { + delete m_val_vec[i]; + } +} + + +// write the new value + +template <int W> +inline +void +sc_signal_rv<W>::write( const data_type& value_ ) +{ + sc_process_b* cur_proc = sc_get_current_process_b(); + + bool value_changed = false; + bool found = false; + + for( int i = m_proc_vec.size() - 1; i >= 0; -- i ) { + if( cur_proc == m_proc_vec[i] ) { + if( value_ != *m_val_vec[i] ) { + *m_val_vec[i] = value_; + value_changed = true; + } + found = true; + break; + } + } + + if( ! found ) { + m_proc_vec.push_back( cur_proc ); + m_val_vec.push_back( new data_type( value_ ) ); + value_changed = true; + } + + if( value_changed ) { + this->request_update(); + } +} + + +template <int W> +inline +void +sc_signal_rv<W>::update() +{ + sc_lv_resolve<W>::resolve( this->m_new_val, m_val_vec ); + base_type::update(); +} + +} // namespace sc_core + +//$Log: sc_signal_rv.h,v $ +//Revision 1.4 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.3 2006/03/21 00:00:27 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_rv_ports.h b/ext/systemc/src/sysc/communication/sc_signal_rv_ports.h new file mode 100644 index 000000000..ee6d17b25 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_rv_ports.h @@ -0,0 +1,401 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_rv_ports.h -- The resolved vector signal ports. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_RV_PORTS_H +#define SC_SIGNAL_RV_PORTS_H + + +#include <cstdio> + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/communication/sc_signal_rv.h" +#include "sysc/datatypes/bit/sc_lv.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in_rv<W> +// +// The sc_signal_rv<W> input port class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_in_rv + : public sc_in<sc_dt::sc_lv<W> > +{ +public: + + // typedefs + + typedef sc_dt::sc_lv<W> data_type; + + typedef sc_in_rv<W> this_type; + typedef sc_in<data_type> base_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_in_rv() + : base_type() + {} + + explicit sc_in_rv( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_in_rv( const in_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_in_rv( const char* name_, const in_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_in_rv( in_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_rv( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + explicit sc_in_rv( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_rv( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_in_rv( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_rv( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_in_rv() + {} + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in_rv"; } + +private: + + // disabled + sc_in_rv( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// called when elaboration is done + +template <int W> +void +sc_in_rv<W>::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_rv<W>*>( this->get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", this->name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout_rv<W> +// +// The sc_signal_rv<W> input/output port class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_inout_rv + : public sc_inout<sc_dt::sc_lv<W> > +{ +public: + + // typedefs + + typedef sc_dt::sc_lv<W> data_type; + + typedef sc_inout_rv<W> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_inout_rv() + : base_type() + {} + + explicit sc_inout_rv( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_inout_rv( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_inout_rv( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_inout_rv( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_rv( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_inout_rv( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_rv( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_inout_rv() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_inout_rv"; } + +private: + + // disabled + sc_inout_rv( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// called when elaboration is done + +template <int W> +void +sc_inout_rv<W>::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_rv<W>*>( this->get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", this->name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out_rv<W> +// +// The sc_signal_rv<W> output port class. +// ---------------------------------------------------------------------------- + +// sc_out_rv can also read from its port, hence no difference with +// sc_inout_rv. For debugging reasons, a class is provided instead +// of a define. + +template <int W> +class sc_out_rv + : public sc_inout_rv<W> +{ +public: + + // typedefs + + typedef sc_out_rv<W> this_type; + typedef sc_inout_rv<W> base_type; + + typedef typename base_type::data_type data_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_out_rv() + : base_type() + {} + + explicit sc_out_rv( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out_rv( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out_rv( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out_rv( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_rv( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out_rv( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_rv( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_out_rv() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + virtual const char* kind() const + { return "sc_out_rv"; } + +private: + + // disabled + sc_out_rv( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +} // namespace sc_core + +//$Log: sc_signal_rv_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:27 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.11 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.10 2005/06/10 22:43:56 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_writer_policy.h b/ext/systemc/src/sysc/communication/sc_writer_policy.h new file mode 100644 index 000000000..93b80f861 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_writer_policy.h @@ -0,0 +1,143 @@ +/***************************************************************************** + + 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. + + *****************************************************************************/ + +/***************************************************************************** + + sc_writer_policy.h -- The sc_signal<T> writer policy definition + + Original Author: Philipp A: Hartmann, OFFIS + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_WRITER_POLICY_H_INCLUDED_ +#define SC_WRITER_POLICY_H_INCLUDED_ + +#if !defined(SC_DEFAULT_WRITER_POLICY) +# if defined(SC_NO_WRITE_CHECK) +# define SC_DEFAULT_WRITER_POLICY SC_UNCHECKED_WRITERS +# else +# define SC_DEFAULT_WRITER_POLICY SC_ONE_WRITER +# endif +#endif + +namespace sc_core { + +class sc_object; +class sc_port_base; +extern +void +sc_signal_invalid_writer( sc_object* target, sc_object* first_writer, + sc_object* second_writer, bool check_delta ); + +// SIGNAL WRITING POLICIES +// +// Note: if you add a new policy to the enum below you will need to add +// an additional overload of sc_reset::reset_signal_is() for the sc_signal<bool> +// instance. That will require changes to sysc/kernel/sc_reset.cpp and +// sysc/kernel/sc_reset.h + +enum sc_writer_policy +{ + SC_ONE_WRITER = 0, ///< unique writer (from a unique port) + SC_MANY_WRITERS = 1, ///< allow multiple writers (with different ports) + SC_UNCHECKED_WRITERS = 3 ///< even allow delta cycle conflicts (non-standard) +}; + +// signal forward declaration +template< typename T, sc_writer_policy POL = SC_DEFAULT_WRITER_POLICY > +class sc_signal; + +template< sc_writer_policy > +struct sc_writer_policy_check; + +struct sc_writer_policy_nocheck_write +{ + bool check_write( sc_object* /* target */, bool /* value_changed */ ) + { return true; } + void update(){} +}; + +struct sc_writer_policy_check_write +{ + bool check_write( sc_object* target, bool value_changed ); + void update(){} +protected: + sc_writer_policy_check_write( bool check_delta = false ) + : m_check_delta( check_delta ), m_writer_p(NULL) {} + const bool m_check_delta; + sc_object* m_writer_p; +}; + +struct sc_writer_policy_check_delta + : sc_writer_policy_check_write +{ + + sc_writer_policy_check_delta() + : sc_writer_policy_check_write(true) {} + + bool check_write( sc_object* target, bool value_changed ) + { + if( value_changed ) + return sc_writer_policy_check_write::check_write( target, true ); + return true; + } + + void update(){ m_writer_p = NULL; } +}; + +struct sc_writer_policy_nocheck_port +{ + bool check_port( sc_object*, sc_port_base*, bool ) + { return true; } +}; + +struct sc_writer_policy_check_port +{ + bool check_port( sc_object* target, sc_port_base* port, bool is_output ); + +protected: + sc_writer_policy_check_port() : m_output(0) {} + sc_port_base* m_output; +}; + +template<> +struct sc_writer_policy_check<SC_ONE_WRITER> + : sc_writer_policy_check_port + , sc_writer_policy_check_write +{}; + +template<> +struct sc_writer_policy_check<SC_MANY_WRITERS> + : sc_writer_policy_nocheck_port + , sc_writer_policy_check_delta +{}; + +template<> +struct sc_writer_policy_check<SC_UNCHECKED_WRITERS> + : sc_writer_policy_nocheck_port + , sc_writer_policy_nocheck_write +{}; + +} // namespace sc_core + +#endif + +// Taf! |