src/sysc/kernel/sc_lambda.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2005 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_lambda.h -- Dynamically created lambdas.
00021 
00022   Original Author: Stan Y. Liao, Synopsys, Inc.
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date:
00032   Description of Modification:
00033 
00034  *****************************************************************************/
00035 
00036 #ifndef SC_LAMBDA_H
00037 #define SC_LAMBDA_H
00038 
00039 
00040 #include <cassert>
00041 
00042 #include "sysc/kernel/sc_cmnhdr.h"
00043 #include "sysc/kernel/sc_macros.h"
00044 #include "sysc/communication/sc_signal_ifs.h"
00045 #include "sysc/datatypes/bit/sc_logic.h"
00046 #include "sysc/utils/sc_mempool.h"
00047 
00048 namespace sc_core {
00049 
00050 class sc_port_registry;
00051 
00052 
00053 // forward declarations
00054 class sc_lambda;
00055 class sc_lambda_ptr;
00056 class sc_lambda_rand;
00057 
00058 
00059 /*
00060  *  ABBREVIATIONS:
00061  *    rator = operator
00062  *    rand  = operand
00063  */
00064 
00065 
00066 // ----------------------------------------------------------------------------
00067 //  ENUM : sc_lambda_rator_e
00068 //
00069 //  Enumeration of lambda operators.
00070 // ----------------------------------------------------------------------------
00071 
00072 enum sc_lambda_rator_e
00073 {
00074     SC_LAMBDA_FALSE = 0x00000000,
00075     SC_LAMBDA_TRUE,
00076 
00077     // logical operators
00078     SC_LAMBDA_AND,
00079     SC_LAMBDA_OR,
00080     SC_LAMBDA_NOT,
00081 
00082     SC_LAMBDA_BOOL,
00083     SC_LAMBDA_BOOL_EQ,
00084     SC_LAMBDA_BOOL_NE,
00085 
00086     // relational operators for sc_dt::sc_logic
00087     SC_LAMBDA_SUL_EQ,
00088     SC_LAMBDA_SUL_NE,
00089 
00090     // relational operators for int
00091     SC_LAMBDA_INT_EQ,
00092     SC_LAMBDA_INT_NE,
00093     SC_LAMBDA_INT_LE,
00094     SC_LAMBDA_INT_GE,
00095     SC_LAMBDA_INT_LT,
00096     SC_LAMBDA_INT_GT,
00097 
00098     // bitwise operators for sc_dt::sc_logic
00099     SC_LAMBDA_SUL_BITAND,
00100     SC_LAMBDA_SUL_BITOR,
00101     SC_LAMBDA_SUL_BITNOT,
00102     SC_LAMBDA_SUL_BITXOR,
00103 
00104     // arithmetic operators for int
00105     SC_LAMBDA_INT_ADD,
00106     SC_LAMBDA_INT_SUB,
00107     SC_LAMBDA_INT_MUL,
00108     SC_LAMBDA_INT_DIV,
00109     SC_LAMBDA_INT_REM,
00110 
00111     // bitwise operators for int
00112     SC_LAMBDA_INT_BITAND,
00113     SC_LAMBDA_INT_BITOR,
00114     SC_LAMBDA_INT_BITNOT,
00115     SC_LAMBDA_INT_BITXOR
00116 };
00117 
00118 
00119 // ----------------------------------------------------------------------------
00120 //  CLASS : sc_lambda
00121 //
00122 //  <summary> Dynamically created lambda objects </summary>
00123 //
00124 //  sc_lambda implements an expression-tree representation of a delay-evaluted
00125 //  expression, i.e. lambda. The eval() method is used to force the evaluation
00126 //  of the expression tree.
00127 //
00128 //  The user should not create a lambda object explicitly; rather, he writes
00129 //  an expression involving a signal of type sc_dt::sc_logic or int, and a smart
00130 //  pointer sc_lambda_ptr object will be automatically created.
00131 //
00132 // ----------------------------------------------------------------------------
00133 
00134 class sc_lambda
00135 {
00136     friend class sc_lambda_ptr;
00137     friend class sc_lambda_rand;
00138     friend class sc_port_registry;
00139 
00140 #include "sysc/kernel/sc_lambda_friends.h"
00141 
00142 public:
00143 
00144     static void* operator new( size_t sz )
00145         { return sc_mempool::allocate( sz ); }
00146 
00147     static void operator delete( void* p, size_t sz )
00148         { sc_mempool::release( p, sz ); }
00149 
00150     // create a lambda out of a bool signal
00151     explicit sc_lambda( const sc_signal_in_if<bool>& );
00152 
00153     // evaluates the expression tree
00154     bool eval() const;
00155 
00156     // destructor
00157     ~sc_lambda();
00158 
00159 private:
00160 
00161     // constructor - takes an operator code and two operands
00162     sc_lambda( sc_lambda_rator_e op,
00163                sc_lambda_rand* o1 = 0, sc_lambda_rand* o2 = 0 );
00164 
00165     // evaluates the expression as an int
00166     int int_eval() const;
00167 
00168     // evalutes the expression as a sc_dt::sc_logic
00169     sc_dt::sc_logic sc_logic_eval() const;
00170 
00171     // returns true if the type of the expression tree is bool
00172     bool is_bool() const
00173     {
00174         return ( ( SC_LAMBDA_AND <= rator_ty ) &&
00175                  ( rator_ty <= SC_LAMBDA_INT_GT ) );
00176     }
00177 
00178     // returns true if the type of the expression tree is int
00179     bool is_int() const
00180     {
00181         return ( ( SC_LAMBDA_INT_ADD <= rator_ty ) &&
00182                  ( rator_ty <= SC_LAMBDA_INT_BITXOR ) );
00183     }
00184 
00185     // returns true if the type of the expression tree is sc_dt::sc_logic
00186     bool is_sc_logic() const
00187     {
00188         return ( ( SC_LAMBDA_SUL_BITAND <= rator_ty ) &&
00189                  ( rator_ty <= SC_LAMBDA_SUL_BITXOR ) );
00190     }
00191 
00192     void replace_ports( void (*fn)( sc_port_registry*, sc_lambda_rand* ),
00193                         sc_port_registry* );
00194 
00195 private:
00196 
00197     sc_lambda_rator_e rator_ty;
00198     sc_lambda_rand*   op1;
00199     sc_lambda_rand*   op2;
00200     int               ref_count;  // reference count
00201 
00202 private:
00203 
00204     sc_lambda();
00205 
00206     static sc_lambda dummy_lambda;
00207 };
00208 
00209 
00210 // ----------------------------------------------------------------------------
00211 //  CLASS : sc_lambda_ptr
00212 //
00213 //  <summary> Smart pointer for sc_lambda </summary>
00214 //
00215 //  sc_lambda_ptr is a smart pointer type that is created by the various
00216 //  overloaded operators declared in sc_lambda_friends.h_
00217 //
00218 //  The user should not define an object of type sc_lambda_ptr directly.
00219 //  Instead, the overloaded operators that return sc_lambda_ptr should be
00220 //  used.
00221 //
00222 // ----------------------------------------------------------------------------
00223 
00224 class sc_lambda_ptr
00225 {
00226     friend class sc_cthread_process;
00227     friend class sc_lambda;
00228     friend class sc_lambda_rand;
00229     friend class sc_port_registry;
00230 
00231 #include "sysc/kernel/sc_lambda_friends.h"
00232 
00233 public:
00234 
00235     static void* operator new( size_t sz )
00236         { return sc_mempool::allocate( sz ); }
00237 
00238     static void* operator new( size_t, void* p )
00239         { return p; }
00240 
00241     static void operator delete( void* p, size_t sz )
00242         { sc_mempool::release( p, sz ); }
00243 
00244     // constructors
00245     // <group>
00246     sc_lambda_ptr()
00247     : ptr( &sc_lambda::dummy_lambda )
00248     {
00249         ptr->ref_count ++;
00250     }
00251 
00252     sc_lambda_ptr( const sc_lambda_ptr& p )
00253     : ptr( p.ptr )
00254     {
00255         ptr->ref_count ++;
00256     }
00257 
00258     explicit sc_lambda_ptr( const sc_signal_bool_deval& b )
00259     : ptr( new sc_lambda( RCAST<const sc_signal_in_if<bool>&>( b ) ) )
00260     {
00261         ptr->ref_count ++;
00262     }
00263     // </group>
00264 
00265     ~sc_lambda_ptr()
00266     {
00267         if( -- ( ptr->ref_count ) == 0 )
00268             delete ptr;
00269     }
00270 
00271     // assignment operator - simply copy the pointer member
00272     sc_lambda_ptr& operator = ( const sc_lambda_ptr& p )
00273     {
00274         if( &p == this )
00275             return *this;
00276         // update reference count on original lambda
00277         if (--(ptr->ref_count) == 0)
00278             delete ptr;
00279         ptr = p.ptr;
00280         // Update reference count
00281         ptr->ref_count++;
00282         return *this;
00283     }
00284 
00285     operator bool() const
00286     {
00287         // Provide this implicit type conversion so that the code
00288         // would still work even if the user makes a mistake, e.g.
00289         // if (foo == '1') as opposed to if (foo.read() == '1').
00290         // Should a warning be issued here?
00291         // cout << "SystemC: warning: implicit conversion of lambda to bool\n";
00292         return ptr->eval();
00293     }
00294 
00295 private:
00296 
00297     sc_lambda* ptr;
00298     sc_lambda_ptr( sc_lambda* p )
00299         : ptr(p)
00300     {
00301         // Update reference count
00302         ptr->ref_count++;
00303     }
00304     sc_lambda_ptr& operator=( sc_lambda* p )
00305     {
00306         // Update reference count on original lambda
00307         if (--(ptr->ref_count) == 0)
00308             delete ptr;
00309         ptr = p;
00310         ptr->ref_count++;
00311         return *this;
00312     }
00313     sc_lambda* operator->() const { return ptr; }
00314 };
00315 
00316 
00317 // ----------------------------------------------------------------------------
00318 //  CLASS : sc_lambda_rand
00319 //
00320 //
00321 //  <summary> Operand for the lambda expression tree </summary>
00322 //
00323 //  sc_lambda_rand is the representation of nodes in the lambda
00324 //  expression trees.  Nodes could be of type lambda (a subtree),
00325 //  int, signal of int, sc_dt::sc_logic, or signal of sc_dt::sc_logic.
00326 //  The type is tagged in a member variable.  There's nothing of
00327 //  interest to the user in this class.
00328 //
00329 // ----------------------------------------------------------------------------
00330 
00331 enum sc_lambda_rand_e
00332 {
00333     SC_LAMBDA_RAND_LAMBDA,
00334     SC_LAMBDA_RAND_SIGNAL_INT,
00335     SC_LAMBDA_RAND_SIGNAL_SUL,
00336     SC_LAMBDA_RAND_SIGNAL_BOOL,
00337     SC_LAMBDA_RAND_INT,
00338     SC_LAMBDA_RAND_SUL,
00339     SC_LAMBDA_RAND_BOOL
00340 };
00341 
00342 
00343 class sc_lambda_rand
00344 {
00345     friend class sc_lambda;
00346     friend class sc_port_registry;
00347 
00348 public:
00349 
00350     static void* operator new( size_t sz )
00351         { return sc_mempool::allocate( sz ); }
00352 
00353     static void operator delete( void* p, size_t sz )
00354         { sc_mempool::release( p, sz ); }
00355 
00356 #include "sysc/kernel/sc_lambda_friends.h"
00357 
00358 private:
00359 
00360     sc_lambda_rand_e rand_ty;
00361     union {
00362         char lamb_space[sizeof(sc_lambda_ptr)];
00363         char ch_space[sizeof(sc_dt::sc_logic)];
00364         const sc_signal_in_if<sc_dt::sc_logic>* sul_sig;
00365         const sc_signal_in_if<int>* int_sig;
00366         const sc_signal_in_if<bool>* edgy_sig;
00367         int val;
00368     };
00369 
00370     sc_lambda_rand( int i )
00371         : rand_ty( SC_LAMBDA_RAND_INT )
00372     {
00373         val = i;
00374     }
00375     sc_lambda_rand( bool b )
00376         : rand_ty( SC_LAMBDA_RAND_BOOL )
00377     {
00378         val = int(b);
00379     }
00380     sc_lambda_rand( const sc_dt::sc_logic& c )
00381         : rand_ty( SC_LAMBDA_RAND_SUL )
00382     {
00383         (void) new(ch_space) sc_dt::sc_logic(c);
00384     }
00385     sc_lambda_rand( const sc_signal_logic_deval& s )
00386         : rand_ty( SC_LAMBDA_RAND_SIGNAL_SUL )
00387     {
00388         sul_sig = RCAST<const sc_signal_in_if<sc_dt::sc_logic>*>( &s );
00389     }
00390     sc_lambda_rand( const sc_signal_in_if<int>& s )
00391         : rand_ty( SC_LAMBDA_RAND_SIGNAL_INT )
00392     {
00393         int_sig = &s;
00394     }
00395     sc_lambda_rand( const sc_signal_in_if<bool>& s )
00396         : rand_ty( SC_LAMBDA_RAND_SIGNAL_BOOL )
00397     {
00398         edgy_sig = &s;
00399     }
00400     sc_lambda_rand( const sc_signal_bool_deval& s )
00401         : rand_ty( SC_LAMBDA_RAND_SIGNAL_BOOL )
00402     {
00403         edgy_sig = RCAST<const sc_signal_in_if<bool>*>( &s );
00404     }
00405 
00406     sc_lambda_rand( const sc_lambda_ptr& l )
00407         : rand_ty( SC_LAMBDA_RAND_LAMBDA )
00408     {
00409         (void) new(lamb_space) sc_lambda_ptr(l);
00410     }
00411 
00412     ~sc_lambda_rand();
00413 
00414     int int_read() const;
00415     sc_dt::sc_logic sc_logic_read() const;
00416     bool bool_read() const;
00417 
00418     void replace_ports( void (*fn)(sc_port_registry*, sc_lambda_rand* ),
00419                         sc_port_registry* );
00420 };
00421 
00422 
00423 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00424 
00425 #include "sysc/kernel/sc_lambda_defs.h"
00426 
00427 } // namespace sc_core
00428 
00429 #endif

Generated on Wed Apr 25 13:53:27 2007 for SystemC by  doxygen 1.5.1