blob: e8e77fcaa77735b36daf4078b425412ddd5304fd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 20 mai 2010
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AvmSchedulingPrimitive.h"
#include <computer/ExecutionEnvironment.h>
#include <computer/PathConditionProcessor.h>
#include <fml/expression/AvmCode.h>
#include <fml/expression/ExpressionConstant.h>
#include <fml/operator/OperatorManager.h>
#include <fml/runtime/ExecutionData.h>
#include <fml/runtime/RuntimeID.h>
namespace sep
{
/**
***************************************************************************
* execution of an EXCLUSIVE program
***************************************************************************
*/
bool AvmPrimitive_Exclusive::run(ExecutionEnvironment & ENV)
{
ENV.inED->setEnabledLocalNodeCondition( true );
ListOfAPExecutionData oneListOfED;
ListOfAPExecutionData resultListOfED;
AvmCode::const_iterator it = ENV.inCODE->begin();
AvmCode::const_iterator itEnd = ENV.inCODE->end();
// Initialisation du process
ExecutionEnvironment tmpENV(ENV, *it);
if( not tmpENV.run() )
{
return( false );
}
oneListOfED.splice( tmpENV.outEDS );
// Recurrence
for( ++it ; it != itEnd ; ++it )
{
if( not tmpENV.run(*it) )
{
return( false );
}
// COMPUTE STRONG FUSION
if( oneListOfED.empty() )
{
resultListOfED.splice( tmpENV.outEDS );
}
else if( tmpENV.outEDS.empty() )
{
resultListOfED.splice( oneListOfED );
}
else
{
ListOfAPExecutionData::iterator itOther = tmpENV.outEDS.begin();
ListOfAPExecutionData::iterator endOther = tmpENV.outEDS.end();
for( ; itOther != endOther ; ++itOther )
{
// Compute OTHER where NOT ONE
if( not evalExclusive(ENV.inED,
oneListOfED, (*itOther), resultListOfED) )
{
//return( false );
}
// Compute ONE where NOT OTHERS
if( not evalExclusive(ENV.inED,
(*itOther), oneListOfED, resultListOfED) )
{
//return( false );
}
}
oneListOfED.clear();
resultListOfED.makeUnique();
}
while( resultListOfED.nonempty() )
{
resultListOfED.last()->setEnabledLocalNodeCondition( false );
oneListOfED.append( resultListOfED.pop_last() );
}
}
ENV.inED->setEnabledLocalNodeCondition( false );
ENV.outEDS.splice( oneListOfED );
ENV.spliceNotOutput( tmpENV );
return( true );
}
/**
***************************************************************************
* execution of an NONDETERMINISM program
***************************************************************************
*/
bool AvmPrimitive_Nondeterminism::run(ExecutionEnvironment & ENV)
{
AvmCode::const_iterator endIt = ENV.inCODE->end();
for( AvmCode::const_iterator it = ENV.inCODE->begin() ; it != endIt ; ++it )
{
ENV.run( *it );
}
return( true );
}
/**
***************************************************************************
* execution of a PRIOR program
***************************************************************************
*/
bool AvmPrimitive_Prior::run(ExecutionEnvironment & ENV)
{
APExecutionData tmpED;
BF aPathCondition;
BF aPriorityCondition = ExpressionConstant::BOOLEAN_TRUE;
BFCode theNodeCondition( OperatorManager::OPERATOR_OR );
BF saveParamsRF = ENV.inED->bfParametersRuntimeForm();
BF bfUpdateParamsRF = saveParamsRF;
bfUpdateParamsRF.makeWritable();
ParametersRuntimeForm * updateParamsRF =
bfUpdateParamsRF.to_ptr< ParametersRuntimeForm >();
// Recurrence
AvmCode::const_iterator itEnd = ENV.inCODE->end();
for( AvmCode::const_iterator it = ENV.inCODE->begin() ; it != itEnd ; ++it )
{
ENV.inED->assignParametersRuntimeForm( bfUpdateParamsRF );
ExecutionEnvironment tmpENV(ENV, *it);
tmpENV.inED->setEnabledLocalNodeCondition( true );
tmpENV.run();
if( tmpENV.outEDS.nonempty() || tmpENV.exitEDS.nonempty() )
{
while( tmpENV.outEDS.nonempty() )
{
tmpENV.outEDS.pop_last_to( tmpED );
if( aPriorityCondition.isEqualTrue() )
{
aPathCondition = tmpED->getPathCondition();
}
else if( tmpED->getPathCondition().isEqualTrue() )
{
aPathCondition = aPriorityCondition;
}
else
{
aPathCondition = ExpressionConstructor::andExpr(
aPriorityCondition, tmpED->getPathCondition());
if( not PathConditionProcessor::isWeakSatisfiable(
aPathCondition) )
{
aPathCondition = ExpressionConstant::BOOLEAN_FALSE;
AVM_IF_DEBUG_FLAG( STATEMENT_TEST_DECISION )
AVM_OS_TRACE << "PATH CONDITION : "
<< tmpED->getPathCondition().str() << std::endl
<< "PRIORITY CONDITION : " << aPriorityCondition.str() << std::endl
<< "FIREABLE CONDITION : " << aPathCondition.str() << std::endl
<< "THROW UNSATISFIED << PRIOR CONDITION >> : "
<< tmpED->mRID.strUniqId() << " |=> " << (*it).str() << std::endl;
AVM_ENDIF_DEBUG_FLAG( STATEMENT_TEST_DECISION )
}
}
if( aPathCondition.isNotEqualFalse() )
{
if( tmpED->getAllNodeCondition().isNotEqualTrue() )
{
theNodeCondition->append( tmpED->getAllNodeCondition() );
updateParamsRF->update( tmpED->getAllNodeCondition() );
}
tmpED->setPathCondition( aPathCondition );
tmpED->setEnabledLocalNodeCondition( false );
ENV.outEDS.append( tmpED );
}
}
while( tmpENV.exitEDS.nonempty() )
{
tmpENV.exitEDS.pop_last_to( tmpED );
if( aPriorityCondition.isEqualTrue() )
{
aPathCondition = tmpED->getPathCondition();
}
else if( tmpED->getPathCondition().isEqualTrue() )
{
aPathCondition = aPriorityCondition;
}
else
{
aPathCondition = ExpressionConstructor::andExpr(
aPriorityCondition, tmpED->getPathCondition());
if( not PathConditionProcessor::isWeakSatisfiable(
aPathCondition) )
{
aPathCondition = ExpressionConstant::BOOLEAN_FALSE;
AVM_IF_DEBUG_FLAG( STATEMENT_TEST_DECISION )
AVM_OS_TRACE << "PATH CONDITION : "
<< tmpED->getPathCondition().str() << std::endl
<< "PRIORITY CONDITION : " << aPriorityCondition.str() << std::endl
<< "FIREABLE CONDITION : " << aPathCondition.str() << std::endl
<< "THROW UNSATISFIED << PRIOR CONDITION >> : "
<< tmpED->mRID.strUniqId() << " |=> " << (*it).str() << std::endl;
AVM_ENDIF_DEBUG_FLAG( STATEMENT_TEST_DECISION )
}
}
if( aPathCondition.isNotEqualFalse() )
{
if( tmpED->getAllNodeCondition().isNotEqualTrue() )
{
theNodeCondition->append( tmpED->getAllNodeCondition() );
updateParamsRF->update( tmpED->getAllNodeCondition() );
}
tmpED->setPathCondition( aPathCondition );
tmpED->setEnabledLocalNodeCondition( false );
ENV.exitEDS.append( tmpED );
}
}
if( theNodeCondition->empty() )
{
//aPriorityCondition = ExpressionConstant::BOOLEAN_FALSE; // <=> not true
break;
}
else if( theNodeCondition->populated() )
{
aPriorityCondition = ExpressionConstructor::notExpr(
theNodeCondition );
}
else
{
aPriorityCondition = ExpressionConstructor::notExpr(
theNodeCondition->pop_last() );
}
if( not PathConditionProcessor::isWeakSatisfiable(
aPriorityCondition) )
{
break;
}
AVM_IF_DEBUG_FLAG( STATEMENT_TEST_DECISION )
AVM_OS_TRACE << "PRIORITY CONDITION : " << aPriorityCondition.str() << std::endl;
AVM_ENDIF_DEBUG_FLAG( STATEMENT_TEST_DECISION )
}
ENV.spliceNotOutput( tmpENV );
}
ENV.inED->assignParametersRuntimeForm( saveParamsRF );
return( true );
}
/**
***************************************************************************
* execution of an AND#THEN program
***************************************************************************
*/
bool AvmPrimitive_ScheduleAndThen::run(ExecutionEnvironment & ENV)
{
ExecutionEnvironment tmpENV(ENV, BF::REF_NULL);
tmpENV.outEDS.append(tmpENV.inED);
AvmCode::const_iterator itArg = ENV.inCODE->begin();
AvmCode::const_iterator endArg = ENV.inCODE->end();
for( ; itArg != endArg ; ++itArg )
{
if( tmpENV.runFromOutputs( (*itArg).bfCode() ) )
{
if( tmpENV.outEDS.empty() && tmpENV.exitEDS.empty() &&
tmpENV.syncEDS.empty() && tmpENV.irqEDS.empty() )
{
break;
}
else
{
// THEN case
}
}
}
ENV.spliceOutput( tmpENV );
return( true );
}
/**
***************************************************************************
* execution of an OR#ELSE program
***************************************************************************
*/
bool AvmPrimitive_ScheduleOrElse::run(ExecutionEnvironment & ENV)
{
ExecutionEnvironment tmpENV(ENV, BF::REF_NULL);
AvmCode::const_iterator itArg = ENV.inCODE->begin();
AvmCode::const_iterator endArg = ENV.inCODE->end();
for( ; itArg != endArg ; ++itArg )
{
if( tmpENV.run( (*itArg).bfCode() ) )
{
if( tmpENV.outEDS.nonempty() || tmpENV.exitEDS.nonempty() ||
tmpENV.syncEDS.nonempty() || tmpENV.irqEDS.nonempty() )
{
ENV.spliceOutput( tmpENV );
break;
}
else
{
// ELSE case
}
}
ENV.spliceOutput( tmpENV );
}
return( true );
}
}