Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

sc_lambda.cpp

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-2004 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.3 (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.cpp - Implementation of 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 #include <stdio.h>
00037 
00038 #include "systemc/utils/sc_iostream.h"
00039 #include "systemc/kernel/sc_kernel_ids.h"
00040 #include "systemc/kernel/sc_lambda.h"
00041 #include "systemc/communication/sc_port.h"
00042 
00043 
00044 // ----------------------------------------------------------------------------
00045 //  CLASS : sc_lambda
00046 //
00047 //  <summary> Dynamically created lambda objects </summary>
00048 //
00049 //  sc_lambda implements an expression-tree representation of a delay-evaluted
00050 //  expression, i.e. lambda. The eval() method is used to force the evaluation
00051 //  of the expression tree.
00052 //
00053 //  The user should not create a lambda object explicitly; rather, he writes
00054 //  an expression involving a signal of type sc_logic or int, and a smart
00055 //  pointer sc_lambda_ptr object will be automatically created.
00056 //
00057 // ----------------------------------------------------------------------------
00058 
00059 sc_lambda
00060 sc_lambda::dummy_lambda;
00061 
00062 
00063 // create a lambda out of a bool signal
00064 
00065 sc_lambda::sc_lambda( const sc_signal_in_if<bool>& b )
00066 : rator_ty( SC_LAMBDA_BOOL ),
00067   op1( new sc_lambda_rand( b ) ),
00068   op2( 0 )
00069 {
00070     ref_count = 0;
00071 }
00072 
00073 
00074 // evaluates the expression tree
00075 
00076 bool
00077 sc_lambda::eval() const
00078 {
00079     // The compiler should optimize the switch statement to a computed
00080     // branch. Otherwise, we should create a table of functions to
00081     // speed things up.
00082 
00083     switch( rator_ty ) {
00084 
00085     /* relational operators for sc_logic type */
00086     case SC_LAMBDA_SUL_EQ:
00087         return ( op1->sc_logic_read() == op2->sc_logic_read() );
00088     case SC_LAMBDA_SUL_NE:
00089         return ( op1->sc_logic_read() != op2->sc_logic_read() );
00090 
00091     /* relational operators for integer type */
00092     case SC_LAMBDA_INT_EQ:
00093         return ( op1->int_read() == op2->int_read() );
00094     case SC_LAMBDA_INT_NE:
00095         return ( op1->int_read() != op2->int_read() );
00096     case SC_LAMBDA_INT_LE:
00097         return ( op1->int_read() <= op2->int_read() );
00098     case SC_LAMBDA_INT_GE:
00099         return ( op1->int_read() >= op2->int_read() );
00100     case SC_LAMBDA_INT_LT:
00101         return ( op1->int_read() < op2->int_read() );
00102     case SC_LAMBDA_INT_GT:
00103         return ( op1->int_read() > op2->int_read() );
00104 
00105     /* boolean operators */
00106     case SC_LAMBDA_AND:
00107         return ( op1->bool_read() && op2->bool_read() );
00108     case SC_LAMBDA_OR:
00109         return ( op1->bool_read() || op2->bool_read() );
00110     case SC_LAMBDA_NOT:
00111         return ( ! op1->bool_read() );
00112     case SC_LAMBDA_BOOL:
00113         return op1->bool_read();
00114     case SC_LAMBDA_BOOL_EQ:
00115         return ( op1->bool_read() == op2->bool_read() );
00116     case SC_LAMBDA_BOOL_NE:
00117         return ( op1->bool_read() != op2->bool_read() );
00118 
00119     case SC_LAMBDA_FALSE:
00120         return false;
00121 
00122     case SC_LAMBDA_TRUE:
00123         return true;
00124 
00125     default:
00126         SC_REPORT_WARNING( SC_ID_NO_BOOL_RETURNED_,
00127          sc_string::to_string( "sc_lambda::eval(): %lx",
00128              int(rator_ty) ).c_str() );
00129         return false;
00130     }
00131 }
00132 
00133 
00134 // destructor
00135 
00136 sc_lambda::~sc_lambda()
00137 {
00138     assert( ( ref_count == 0 ) || ( this == &dummy_lambda ) );
00139     delete op1;
00140     delete op2;
00141 }
00142 
00143 
00144 // constructor - takes an operator code and two operands
00145 
00146 sc_lambda::sc_lambda( sc_lambda_rator_e op,
00147                       sc_lambda_rand*   o1,
00148                       sc_lambda_rand*   o2 )
00149 : rator_ty( op ),
00150   op1( o1 ),
00151   op2( o2 )
00152 {
00153     ref_count = 0;
00154 }
00155 
00156 
00157 // evaluates the expression as an int
00158 
00159 int
00160 sc_lambda::int_eval() const
00161 {
00162     switch( rator_ty ) {
00163 
00164     case SC_LAMBDA_INT_ADD:
00165         return ( op1->int_read() + op2->int_read() );
00166     case SC_LAMBDA_INT_SUB:
00167         return ( op1->int_read() - op2->int_read() );
00168     case SC_LAMBDA_INT_MUL:
00169         return ( op1->int_read() * op2->int_read() );
00170     case SC_LAMBDA_INT_DIV:
00171         return ( op1->int_read() / op2->int_read() );
00172     case SC_LAMBDA_INT_REM:
00173         return ( op1->int_read() % op2->int_read() );
00174     case SC_LAMBDA_INT_BITAND:
00175         return ( op1->int_read() & op2->int_read() );
00176     case SC_LAMBDA_INT_BITOR:
00177         return ( op1->int_read() | op2->int_read() );
00178     case SC_LAMBDA_INT_BITNOT:
00179         return ( ~ op1->int_read() );
00180     case SC_LAMBDA_INT_BITXOR:
00181         return ( op1->int_read() ^ op2->int_read() );
00182        
00183     default:
00184         SC_REPORT_WARNING( SC_ID_NO_INT_RETURNED_,
00185          sc_string::to_string( "sc_lambda::int_eval(): %lx",
00186              int( rator_ty ) ).c_str() );
00187         return 0;
00188     }
00189 }
00190 
00191 
00192 // evalutes the expression as a sc_logic
00193 
00194 sc_logic
00195 sc_lambda::sc_logic_eval() const
00196 {
00197     switch( rator_ty ) {
00198 
00199     case SC_LAMBDA_SUL_BITAND:
00200         return ( op1->sc_logic_read() & op2->sc_logic_read() );
00201     case SC_LAMBDA_SUL_BITOR:
00202         return ( op1->sc_logic_read() | op2->sc_logic_read() );
00203     case SC_LAMBDA_SUL_BITNOT:
00204         return ( ~ op1->sc_logic_read() );
00205     case SC_LAMBDA_SUL_BITXOR:
00206         return ( op1->sc_logic_read() ^ op2->sc_logic_read() );
00207 
00208     default:
00209         SC_REPORT_WARNING( SC_ID_NO_SC_LOGIC_RETURNED_,
00210          sc_string::to_string( "sc_lambda::sc_logic_eval(): %lx",
00211              int( rator_ty ) ).c_str() );
00212         return sc_logic();
00213     }
00214 }
00215 
00216 
00217 void
00218 sc_lambda::replace_ports( void (*replace_fn)( sc_port_registry*,
00219                 sc_lambda_rand* ),
00220                           sc_port_registry* port_registry )
00221 {
00222     if( op1 ) {
00223   op1->replace_ports( replace_fn, port_registry );
00224     }
00225     if( op2 ) {
00226   op2->replace_ports( replace_fn, port_registry );
00227     }
00228 }
00229 
00230 
00231 // This version should be used for creating the dummy_lambda only
00232 
00233 sc_lambda::sc_lambda()
00234 : rator_ty( SC_LAMBDA_FALSE ),
00235   op1( 0 ),
00236   op2( 0 )
00237 {
00238     static int one = 0;
00239 
00240     // make sure this constructor doesn't get called more than once
00241     assert( one == 0 );
00242     one ++;
00243     // make sure it doesn't get deleted
00244     ref_count = 1;
00245 }
00246 
00247 
00248 /*****************************************************************************/
00249 
00250 static const char* sc_lambda_rand_names[] = {
00251     "SC_LAMBDA_RAND_LAMBDA",
00252     "SC_LAMBDA_RAND_SIGNAL_INT",
00253     "SC_LAMBDA_RAND_SIGNAL_SUL",
00254     "SC_LAMBDA_RAND_SIGNAL_BOOL",
00255     "SC_LAMBDA_RAND_INT",
00256     "SC_LAMBDA_RAND_SUL",
00257     "SC_LAMBDA_RAND_BOOL"
00258 };
00259 
00260 sc_lambda_rand::~sc_lambda_rand()
00261 {
00262 #if 0
00263     if (SC_LAMBDA_RAND_LAMBDA == rand_ty) {
00264           ((sc_lambda_ptr*) lamb_space)->~sc_lambda_ptr();
00265   } else if (SC_LAMBDA_RAND_SUL == rand_ty) {
00266           ((sc_logic*) ch_space)->~sc_logic();
00267   }
00268 #endif
00269     switch( rand_ty ) {
00270 
00271     case SC_LAMBDA_RAND_LAMBDA:{
00272         ((sc_lambda_ptr*) lamb_space)->~sc_lambda_ptr();
00273         break;
00274     }
00275     case SC_LAMBDA_RAND_SUL:{
00276         ((sc_logic*) ch_space)->~sc_logic();
00277   break;
00278     }
00279     default:
00280       break;
00281     }
00282     return;
00283 }
00284 
00285 int
00286 sc_lambda_rand::int_read() const
00287 {
00288     switch( rand_ty ) {
00289 
00290     case SC_LAMBDA_RAND_INT:
00291         return val;
00292 
00293     case SC_LAMBDA_RAND_SIGNAL_INT:
00294         return int_sig->read();
00295 
00296     case SC_LAMBDA_RAND_LAMBDA:
00297         return (*((sc_lambda_ptr*) lamb_space))->int_eval();
00298 
00299     default:
00300         cout << "sc_lambda_rand::int_read(): operand "
00301              << sc_lambda_rand_names[rand_ty]
00302              << "is not integer." << endl;
00303         return 0;
00304     }
00305 }
00306 
00307 sc_logic
00308 sc_lambda_rand::sc_logic_read() const
00309 {
00310     switch (rand_ty) {
00311 
00312     case SC_LAMBDA_RAND_SUL:
00313         return *((sc_logic*) ch_space);
00314 
00315     case SC_LAMBDA_RAND_SIGNAL_SUL:
00316         return sul_sig->read();
00317 
00318     case SC_LAMBDA_RAND_LAMBDA:
00319         return (*((sc_lambda_ptr*) lamb_space))->sc_logic_eval();
00320 
00321     default:
00322         SC_REPORT_WARNING( SC_ID_OPERAND_NOT_SC_LOGIC_,
00323           sc_string::to_string("sc_lambda::sc_logic_read(): %s",
00324           sc_lambda_rand_names[rand_ty]).c_str());
00325         return sc_logic();
00326     }
00327 }
00328 
00329 bool
00330 sc_lambda_rand::bool_read() const
00331 {
00332     switch (rand_ty) {
00333 
00334     case SC_LAMBDA_RAND_BOOL:
00335     case SC_LAMBDA_RAND_INT:
00336         return (val != 0);
00337 
00338     case SC_LAMBDA_RAND_SIGNAL_BOOL:
00339         return edgy_sig->read();
00340 
00341     case SC_LAMBDA_RAND_LAMBDA:
00342         return (*((sc_lambda_ptr*) lamb_space))->eval();
00343 
00344     default:
00345         SC_REPORT_WARNING( SC_ID_OPERAND_NOT_BOOL_,
00346           sc_string::to_string("sc_lambda::bool_read(): %s",
00347           sc_lambda_rand_names[rand_ty]).c_str());
00348         return false;
00349     }
00350 }
00351 
00352 
00353 void
00354 sc_lambda_rand::replace_ports(  void (*replace_fn)( sc_port_registry*,
00355                 sc_lambda_rand* ),
00356                                 sc_port_registry* port_registry )
00357 {
00358     switch( rand_ty ) {
00359     case SC_LAMBDA_RAND_LAMBDA:
00360         (*((sc_lambda_ptr*) lamb_space))->replace_ports( replace_fn,
00361                port_registry );
00362         break;
00363     case SC_LAMBDA_RAND_SIGNAL_BOOL:
00364         (*replace_fn)( port_registry, this );
00365         break;
00366     default:
00367         break;
00368     }
00369 }

Generated on Fri Jan 14 08:29:03 2005 for SystemC2.1beta11(excludingMSLib)(IncludingSCV)\nProvidedby:www.openverificationfoundation.org by doxygen1.2.18