/******************************************************* * * DESCRIPTION: CD++ compiler for BG models * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #include #include "cdppcompiler.h" #define endl "\n" #define tab "\t" #define DEFAULT_QUANTUM 0.01 #define DEFAULT_HWIN 0.01 const QuantizerParams BG_CDPP_Compiler::DefaultQuantizerParams = { DEFAULT_QUANTUM, DEFAULT_HWIN }; /******************************************************************* * Function Name: *******************************************************************/ BG_CDPP_Compiler::BG_CDPP_Compiler() : separator( '@' ) , labelSeparator( ':' ) , modelLSeparator( '[' ) , modelRSeparator( ']' ) , topModelLabel( "[top]" ) , componentLabel( "components" ) , inPortsLabel("in") , outPortsLabel("out") , linkLabel("link") , devsImpl( QDEVS_IMPLEMENTATION ) , outputDirectory( "" ) , dirSeparator( '/' ) { compsQuantizerParams = new CompsQuantizerParams(); assert( compsQuantizerParams != NULL ); quantizerParamsForAll = NULL; } /******************************************************************* * Function Name: *******************************************************************/ BG_CDPP_Compiler::~BG_CDPP_Compiler() { if( quantizerParamsForAll != NULL ) delete quantizerParamsForAll; clearQuantizerParams(); if( compsQuantizerParams != NULL ) delete compsQuantizerParams; } /******************************************************************* * Function Name: *******************************************************************/ bool BG_CDPP_Compiler::generateMA( BondGraph &bg, ostream &out ) { // Genera la especificacion MA (CD++) del modelo DEVS acoplado // correspondiente al Bond Graph // Seccion de declaracion de componentes del modelo acoplado if ( !generateComponentsDeclaration( bg, out ) ) return false; // Seccion de declaracion de ports (input y output) if ( !generatePortsDeclaration( bg, out ) ) return false; // Seccion de declaracion de links entre componentes if ( !generateLinksDeclaration( bg, out ) ) return false; // Seccion de variables de los modelos if ( !generateComponentsVars( bg, out ) ) return false; return true; } /******************************************************************* * Function Name: *******************************************************************/ bool BG_CDPP_Compiler::generateMAToFile( BondGraph &bg, const char *fileName ) { ofstream fp( fileName ); if ( !fp ) throw BG_CDPP_CompilerException( "Error, unable to open output file: " + string( fileName ) ); generateMA( bg, fp ); fp.close(); return true; } /******************************************************************* * Function Name: *******************************************************************/ QuantizerParams *BG_CDPP_Compiler::getQuantizerParamsFor( const Id &compId ) const { if( compsQuantizerParams->find( lowerCase(compId) ) == compsQuantizerParams->end() ) return quantizerParamsForAll; return ( compsQuantizerParams->find( lowerCase( compId ) )->second ); } /******************************************************************* * Function Name: *******************************************************************/ string BG_CDPP_Compiler::getOutputFileNameFor( const Id &compId ) const { return ( outputDirectory == "" ? "" : outputDirectory + dirSeparator + compId + DEFAULT_OUT_FILE_EXT ); } /******************************************************************* * Function Name: *******************************************************************/ BG_CDPP_Compiler &BG_CDPP_Compiler::setQuantizerParamsFor( const Id &compId, const QuantizerParams &qParams ) { QuantizerParams *quantizerParams = new QuantizerParams(); if( quantizerParams != NULL ) { quantizerParams->quantum = qParams.quantum; quantizerParams->hystWindow = qParams.hystWindow; compsQuantizerParams->insert( CompsQuantizerParams::value_type( lowerCase( compId ), quantizerParams ) ); } return *this; } /******************************************************************* * Function Name: *******************************************************************/ BG_CDPP_Compiler &BG_CDPP_Compiler::setQuantizerParamsFile( const string &fileName ) { Ini ini; Ini::GroupList lista; Ini::GroupList::iterator it; string id, quantum, hystWind; QuantizerParams qparams; ini.parse( fileName ); lista = ini.groupList(); // Setea los parametros de quantificacion para cada componente // segun lo especificado en el archivo de parametros for( it = lista.begin(); it != lista.end(); it++ ) { id = it->first; quantum = getParameter( ini, id, "quantum" ); qparams.quantum = ( quantum == "" ? DefaultQuantizerParams.quantum : atof( quantum.data() ) ); hystWind = getParameter( ini, id, "hystWindow" ); qparams.hystWindow = ( hystWind == "" ? DefaultQuantizerParams.hystWindow : atof( hystWind.data() ) ); this->setQuantizerParamsFor( id, qparams ); } return *this; } /******************************************************************* * Function Name: *******************************************************************/ BG_CDPP_Compiler &BG_CDPP_Compiler::clearQuantizerParams() { if( compsQuantizerParams != NULL ) { CompsQuantizerParams::iterator it; for( it = compsQuantizerParams->begin(); it != compsQuantizerParams->end(); it++ ) { if( it->second != NULL ) delete ( it->second ); } compsQuantizerParams->clear(); } return *this; } /******************************************************************* * Function Name: *******************************************************************/ bool BG_CDPP_Compiler::generateComponentsDeclaration( BondGraph &bg, ostream &out ) { // Declaro todos los modelos DEVS atomicos que conformam el BondGraph out << endl; out << topModelLabel; out << endl; out << componentLabel << " " << labelSeparator << " "; BondGraph::Iterator it = bg.begin(); BGComp *comp; for ( ; it != bg.end(); it++ ) { comp = (*it); if( devsImpl == QDEVS_IMPLEMENTATION ) { out << comp->getId() << separator << QDEVS_COMPONENT_PREFIX << comp->causalizedComponentName() << " "; } else throw BG_CDPP_CompilerException( "Error, DEVS component's implementation not supported!" ); } out << endl; return true; } /******************************************************************* * Function Name: *******************************************************************/ bool BG_CDPP_Compiler::generatePortsDeclaration( BondGraph &bg, ostream &out ) { // Declaro todos los ports de input y output que conforman el modelo out << endl; // Input Ports: no existen ya que el modelo no recibe entradas desde el exterior out << inPortsLabel << " " << labelSeparator << endl; // Output Ports: no existen out << outPortsLabel << " " << labelSeparator << endl; out << endl; return true; } /******************************************************************* * Function Name: *******************************************************************/ bool BG_CDPP_Compiler::generateLinksDeclaration( BondGraph &bg, ostream &out ) { // Declaro los links entre los componentes del modelo out << endl; BondGraph::Iterator it = bg.begin(); for ( ; it != bg.end(); it++ ) { return ( generateLinksDeclarationFromComponent( bg, out, *it ) ); } return true; } /******************************************************************* * Function Name: *******************************************************************/ bool BG_CDPP_Compiler::generateComponentsVars( BondGraph &bg, ostream &out ) { // Declaro todas las variables de los componentes que conforman el modelo out << endl; BondGraph::Iterator it = bg.begin(); BGComp *comp; QuantizerParams *qParams; for ( ; it != bg.end(); it++ ) { comp = (*it); out << modelLSeparator << comp->getId() << modelRSeparator << endl; if ( comp->quantifiable() ) { qParams = getQuantizerParamsFor( comp->getId() ); if( qParams != NULL ) { out << "quantum " << labelSeparator << " " << qParams->quantum << endl; out << "hystWindow " << labelSeparator << " " << qParams->hystWindow << endl; } } out << comp->getVarsAsString() << endl; out << "outputFile " << labelSeparator << " " << getOutputFileNameFor( comp->getId() ) << endl; out << endl; } out << endl; return true; } /******************************************************************* * Function Name: *******************************************************************/ bool BG_CDPP_Compiler::generateLinksDeclarationFromComponent( BondGraph &bg, ostream &out, BGComp *comp ) { // Declaro los links entre un componente y sus adyacentes list *adjs; list::iterator it; BGComp *adj; BGEdgeData edata; int cbid, abid; comp->setMark(); adjs = bg.adjacents( comp->getId() ); assert( adjs ); for ( it = adjs->begin(); it != adjs->end(); it++ ) { adj = *it; assert( adj ); if ( !adj->marked() ) { edata = bg.getBondData( *comp, *adj ); cbid = comp->generateBondId( edata ); abid = adj->generateBondId( edata ); // link: comp@out adj@in out << linkLabel << " " << labelSeparator << " "; out << getOutPortName( *comp, edata, cbid ) << separator << comp->getId() << tab; out << getInPortName( *adj, edata, abid ) << separator << adj->getId() << endl; // link: adj@out comp@in out << linkLabel << " " << labelSeparator << " "; out << getOutPortName( *adj, edata, abid ) << separator << adj->getId() << tab; out << getInPortName( *comp, edata, cbid ) << separator << comp->getId() << endl; generateLinksDeclarationFromComponent( bg, out, adj ); } } return true; } /******************************************************************* * Function Name: *******************************************************************/ string BG_CDPP_Compiler::getParameter( const Ini &ini, const string &compName, const string ¶mName ) const { try { const Ini::IdList &idList( ini.definition( compName, paramName ) ); if( idList.empty() ) return ""; return idList.front(); } catch ( MException e ) { } return ""; }