/******************************************************* * * DESCRIPTION: QBG source classes (effort and flow) * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #include #include #include "qbg_source.h" #include "message.h" #include "mainsimu.h" const RealValue QBGSource::DefaultStartTime = DEFAULT_START_TIME; const RealValue QBGSource::DefaultOffset = DEFAULT_OFFSET; /******************************************************************* * Function Name: * Description: constructor ********************************************************************/ QBGSource::QBGSource( const string &signalName, const string &name, const string &opname, const string &ipname ) : Atomic( name ) , out( addOutputPort( opname ) ) , in( addInputPort( ipname ) ) { try { try { // start time string stime( MainSimulator::Instance().getParameter( description(), "startTime" ) ); startTime = atof( stime.data() ); } catch ( MException &e ) { startTime = DefaultStartTime; } if ( startTime < 0 ) { throw MException( "Invalid start time value: " + Value2StrReal( startTime ) ); } // Paso el tiempo a milisegundos startTime = startTime / TICK_VALUE; try { // offset string off( MainSimulator::Instance().getParameter( description(), "offset" ) ); offset = atof( off.data() ); } catch ( MException &e ) { offset = DefaultOffset; } createSourceSignal( signalName ); // Quantum try { string quant( MainSimulator::Instance().getParameter( description(), "quantum" ) ); quantum = atof( quant.data() ); } catch ( MException &e ) { quantum = DEFAULT_QUANTUM; } if( quantum <= 0 ) { throw MException( "Invalid quantum value : " + Value2StrReal( quantum ) ); } // Hysteresis window try { string hystW( MainSimulator::Instance().getParameter( description(), "hystWindow" ) ); hystWindow = atof( hystW.data() ); } catch ( MException &e ) { hystWindow = DEFAULT_HYST_WINDOW; } if( hystWindow < 0 ) { throw MException( "Invalid hysteresis window value : " + Value2StrReal( hystWindow ) ); } createSourceQuantizer(); // Output file try { outFileName = MainSimulator::Instance().getParameter( description(), "outputFile" ); } catch ( MException &e ) { outFileName = DEFAULT_QBG_OUTFILENAME; } } catch ( MException &e ) { e.print( cerr ); MTHROW( e ) ; } } /******************************************************************* * Source Name: ~QBGSource * Destructor ********************************************************************/ QBGSource::~QBGSource() { if ( signal ) { delete signal; } if ( quantizer ) { delete quantizer; } outFile.close(); } /******************************************************************* * Source Name: createSourceSignal * Destructor ********************************************************************/ QBGSource& QBGSource::createSourceSignal( const string &signalName ) { signal = Signal::create( signalName ); assert( signal ); string value; // Parametros de la senal for ( int i=1; i <= signal->paramCount(); i++ ) { try { value = MainSimulator::Instance().getParameter( description(), signal->paramName( i ) ); signal->setParam( i, atof( value.data() ) ); } catch ( MException &e ) { } } signal->setOffset( offset ); signal->setStartTime( startTime ); return *this; } /******************************************************************* * Source Name: createSourceQuantizer * Destructor ********************************************************************/ QBGSource& QBGSource::createSourceQuantizer() { quantizer = new UniformQuantizer(); assert( quantizer ); ((UniformQuantizer *)quantizer)->setQuantum( quantum ); return *this; } /******************************************************************* * Function Name: initFunction ********************************************************************/ Model &QBGSource::initFunction() { // out file outFile.open( outFileName.c_str() ); outFile << "\nTime, source value"; return *this ; } /******************************************************************* * Function Name: externalFunction ********************************************************************/ Model &QBGSource::externalFunction( const ExternalMessage &msg ) { return *this; } /******************************************************************* * Function Name: outputFunction ********************************************************************/ Model &QBGSource::outputFunction( const InternalMessage &msg ) { outFile << "\n" << msg.time().asMsecs() << "," << value; sendOutput( msg.time(), out, value ) ; return *this ; } /************************************ * * Senial Constant * *************************************/ Model &QBGSource_Constant::initFunction() { QBGSource::initFunction(); value = quantizer->quantize( signal->s( 0 ) ); holdIn( active, Time::Zero ); return *this; } /******************************************************************* * Function Name: internalFunction of Constant Signal Source ********************************************************************/ Model &QBGSource_Constant::internalFunction( const InternalMessage &msg ) { passivate(); return *this ; } /************************************ * * Senial Step * *************************************/ Model &QBGSource_Step::initFunction() { QBGSource::initFunction(); value = quantizer->quantize( signal->s( 0 ) ); holdIn( active, Time::Zero ); return *this; } /******************************************************************* * Function Name: internalFunction of Step Signal Source ********************************************************************/ Model &QBGSource_Step::internalFunction( const InternalMessage &msg ) { try { RealValue time = msg.time().asMsecs(); if( time < startTime ) { RealValue nvalue = quantizer->quantize( signal->s( startTime ) ); if ( nvalue != value ) { value = nvalue; holdIn( active, Time( static_cast< float >( startTime - time ) ) ); } else { passivate(); } } else { passivate(); } } catch ( MException &e ) { e.print( cerr ); MTHROW( e ); } return *this ; } /************************************ * * Senial Sine * *************************************/ Model &QBGSource_Sine::initFunction() { QBGSource::initFunction(); signal->setParam( 3, signal->paramValue( 3 ) * TICK_VALUE ); value = signal->s( 0 ); qvalue = quantizer->quantize( value ); qvaluePrev = M_INFINITO; holdIn( active, Time::Zero ); return *this; } /******************************************************************* * Function Name: internalFunction of Sine Source ********************************************************************/ Model &QBGSource_Sine::internalFunction( const InternalMessage &msg ) { RealValue time = (RealValue)msg.time().asMsecs(); RealValue v1, v2, t1, t2, t; RealValue s = signal->s( time ); qvalue = quantizer->quantize(s); if( qvalue == qvaluePrev ) { holdIn( active, Time( static_cast( TICK_VALUE ) ) ); } else { v1 = s - quantum; v2 = s + quantum; try { t1 = ((SineSignal *)signal)->inv( v1, time ); } catch ( SignalException e ) { t1 = M_INFINITO; } try { t2 = ((SineSignal *)signal)->inv( v2, time ); } catch ( SignalException e ) { t2 = M_INFINITO; } if( t1 != M_INFINITO || t2 != M_INFINITO ) { t1 = ceil( t1 ); t2 = ceil( t2 ); if( t1 == t2 ) { // El quantum es muy chico o la frecuencia muy alta, precision no soportada MException e( "Precision not supported by the simulator! Increase the quantum value or decrease the signal frequency" ); throw e; } t = ( t1 < t2 ? t1 : t2 ); } else { // Perdida de precision, debe achicarse el quantum MException e( "Decrease the quantum value to increase the precision on signal aproximation" ); throw e; } value = signal->s( t ); qvalue= quantizer->quantize( value ); RealValue waitTime = ( t - time ) * TICK_VALUE; if( waitTime < TICK_VALUE ) { // El quantum es muy chico o la frecuencia muy alta, precision no soportada MException e( "Precision not supported by the simulator! Increase the quantum value or decrease the signal frequency" ); throw e; } holdIn( active, Time( static_cast( waitTime ) ) ); } return *this ; } /******************************************************************* * Function Name: outputFunction ********************************************************************/ Model &QBGSource_Sine::outputFunction( const InternalMessage &msg ) { if( qvalue != qvaluePrev ) { outFile << "\n" << msg.time().asMsecs() << "," << qvalue; sendOutput( msg.time(), out, qvalue ) ; qvaluePrev = qvalue; } return *this ; } /************************************ * * Senial Pulse * *************************************/ Model &QBGSource_Pulse::initFunction() { QBGSource::initFunction(); RealValue period = signal->paramValue( 2 ); RealValue width = signal->paramValue( 3 ); width = period * width/100; signal->setStartTime( startTime ); up = ( startTime != 0 ); value = quantizer->quantize( signal->s( 0 ) ); upvalue = quantizer->quantize( signal->s( startTime ) ); dwvalue = quantizer->quantize( signal->s( startTime + width ) ); widthup = width; widthdw = period - widthup; holdIn( active, Time::Zero ); return *this; } /******************************************************************* * Function Name: internalFunction of Step Signal Source ********************************************************************/ Model &QBGSource_Pulse::internalFunction( const InternalMessage &msg ) { try { RealValue time = msg.time().asMsecs(); if( time < startTime ) { if ( value != upvalue ) { value = upvalue; holdIn( active, Time( static_cast< float >( startTime - time ) ) ); } else { passivate(); } } else { if( up ) { value = upvalue; holdIn( active, Time( static_cast< float >( widthdw ) ) ); } else { value = dwvalue; holdIn( active, Time( static_cast< float >( widthup ) ) ); } } up = !up; } catch ( MException &e ) { e.print( cerr ); MTHROW( e ); } return *this ; }