Changeset 13703


Ignore:
Timestamp:
Oct 8, 2019 8:28:35 PM (2 months ago)
Author:
Christian Andersson
Message:

Reverted changeset:13700. Related to ticket:5837

Location:
trunk
Files:
11 deleted
30 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/CHANGELOG.txt

    r13700 r13703  
    11================= Unreleased ==================
    2 # Feature ; Minor ; Compiler; #5837
    3 Added a pre-compiled evaluator used for evaluating external functions
    4 during the compilation (for performance). Activated by the option
    5 "external_constant_evaluation_dynamic"
    6 
    72# Fixed ; Minor ; Compiler ; #5855
    83Nominal are now always positive in the FMI model description.
  • trunk/Compiler/ModelicaCBackEnd/src/jastadd/CCodeGen/CCodeGenExternalCeval.jrag

    r13700 r13703  
    248248        Collection<ExternalArgument> res = new LinkedHashSet<>();
    249249        if (hasReturnVar()) {
    250             res.add(returnVarToSerialize());
    251         }
    252         res.addAll(argVarsToSerialize());
    253         return res;
    254     }
    255    
    256     syn ExternalArgument FExternalStmt.returnVarToSerialize() = getReturnVar().externalArgument();
    257     syn Collection<ExternalArgument> FExternalStmt.argVarsToSerialize() {
    258         Collection<ExternalArgument> res = new LinkedHashSet<>();
     250            res.add(getReturnVar().externalArgument());
     251        }
    259252        for (FExp e : getArgs()) {
    260253            res.add(e.externalArgument());
     
    295288        }
    296289        return functionArgs;
    297     }
    298    
    299 
    300     syn String FType.cMappedTypeString() = cMappedTypeStringScalar() + (isArray() ? "v" : "");
    301 
    302     syn String FType.cMappedTypeStringScalar() {
    303         throw new InternalCompilerError("cMappedTypeStringScalar() is not supported for class type " + getClass().getSimpleName());
    304     }
    305     eq FArrayType.cMappedTypeStringScalar() = getFPrimitiveType().cMappedTypeStringScalar();
    306     eq FIntegerType.cMappedTypeStringScalar() = "i";
    307     eq FEnumType.cMappedTypeStringScalar() = "i";
    308     eq FBooleanType.cMappedTypeStringScalar() = "i";
    309     eq FRealType.cMappedTypeStringScalar() = "d";
    310     eq FStringType.cMappedTypeStringScalar() = "s";
    311     eq FRecordType.cMappedTypeStringScalar() {
    312         String o = "R[";
    313         for (FRecordComponentType rType: getComponents()) {
    314                 o = o.concat(rType.getFType().cMappedTypeStringScalar());
    315                 o = o.concat(",");
    316         }
    317         return o.concat("]");
    318     }
    319    
    320     syn String FExternalStmt.functionReturnArgSerialized() {
    321         if (hasReturnVar()) {
    322             return returnVarToSerialize().type().cMappedTypeString();
    323         } else {
    324             return "void";
    325         }
    326     }
    327    
    328     syn String FExternalStmt.functionArgsSerialized() {
    329         String input = "";
    330         for (ExternalArgument var : argVarsToSerialize()) {
    331             if (var.isOutput()) {
    332                input = input.concat("*");
    333             }
    334             input += var.type().cMappedTypeString() + ",";
    335         }
    336         return input;
    337290    }
    338291   
     
    394347            }
    395348        }
    396     }
    397    
    398     public String FClass.externalCTypes() {
    399         StringBuilder sb = new StringBuilder();
    400         for (FExternalStmt stmt : myExternals()) {
    401             if (stmt.dynamicEvaluatorEnabled()) {
    402                 sb.append(stmt.getName());
    403                 sb.append("\n");
    404                 sb.append(stmt.functionReturnArgSerialized());
    405                 sb.append("\n");
    406                 sb.append(stmt.functionArgsSerialized());
    407                 sb.append("\n");
    408             }
    409         }
    410         return sb.toString();
    411349    }
    412350
  • trunk/Compiler/ModelicaCBackEnd/templates/ceval_external_template.c

    r13700 r13703  
    1414*/
    1515
    16 #include "jmi_evaluator_util.h"
    17 
    18 /* Must be defined here in order to override the methods from jmi_global.c */
    19 void jmi_global_log(int warning, const char* name, const char* fmt, const char* value) {
    20     _jmi_global_log(warning, name, fmt, value);
    21 }
    22 void jmi_throw() {
    23     _jmi_throw();
    24 }
    25 void* jmi_global_calloc(size_t n, size_t s) {
    26     return _jmi_global_calloc(n,s);
    27 }
     16#include <stdio.h>
     17#include <stdlib.h>
     18#include <string.h>
     19#include "jmi.h"
     20#include "jmi_dyn_mem.h"
     21#include "ModelicaUtilities.h"
     22#include <fcntl.h>
    2823
    2924$ECE_external_includes$
    3025 
     26/* Manual debugging */
     27#define JMCEVAL_DEBUG 0
     28#define JMCEVAL_DBGP(x) if (JMCEVAL_DEBUG) { printf(x); fflush(stdout);}
     29
     30/* Format specifier when printing jmi_real_t */
     31#define JMCEVAL_realFormat "%.16f"
     32
    3133/* Used record definitions */
    3234$ECE_record_definitions$
     35
     36/* Parses ND dimensions into dimension buffer d*/
     37#define JMCEVAL_parseArrayDims(ND) \
     38    for (di = 0; di < ND; di++) { scanf("%d",&d[di]); }
     39
     40/* Parse/print basic types */
     41double JMCEVAL_parseReal() {
     42    /* Char buffer when reading jmi_real_t. This is necessary
     43       since "%lf" is not allowed in c89. */
     44    char buff[32];
     45    JMCEVAL_DBGP("Parse number: ");
     46    scanf("%s",buff);
     47    return strtod(buff, 0);
     48}
     49
     50void JMCEVAL_printReal(double x) {
     51    printf(JMCEVAL_realFormat, x); \
     52    printf("\n"); \
     53    fflush(stdout); \
     54}
     55
     56char* JMCEVAL_parseString() {
     57    int d[1];
     58    char* str;
     59    size_t si,di;
     60    JMCEVAL_parseArrayDims(1);
     61    getchar();
     62    str = ModelicaAllocateString(d[0]);
     63    JMCEVAL_DBGP("Parse string: ");
     64    for (si = 0; si < d[0]; si++) str[si] = getchar();
     65    str[d[0]] = '\0';
     66    return str;
     67}
     68
     69void JMCEVAL_printString(const char* str) {
     70    printf("%u\n%s\n", (unsigned)strlen(str), str);
     71    fflush(stdout);
     72}
     73
     74#define JMCEVAL_parseInteger()  JMCEVAL_parseReal()
     75#define JMCEVAL_parseBoolean()  JMCEVAL_parseInteger()
     76#define JMCEVAL_parseEnum()     JMCEVAL_parseInteger()
     77#define JMCEVAL_printInteger(X) JMCEVAL_printReal(X)
     78#define JMCEVAL_printBoolean(X) JMCEVAL_printInteger(X)
     79#define JMCEVAL_printEnum(X)    JMCEVAL_printInteger(X)
     80#define JMCEVAL_parse(TYPE, X)  X = JMCEVAL_parse##TYPE()
     81#define JMCEVAL_print(TYPE, X)  JMCEVAL_print##TYPE(X)
     82
     83/* Parse/print arrays */
     84#define JMCEVAL_parseArray(TYPE,ARR) for (vi = 1; vi <= ARR->num_elems; vi++) { JMCEVAL_parse(TYPE, jmi_array_ref_1(ARR,vi)); }
     85#define JMCEVAL_printArray(TYPE,ARR) for (vi = 1; vi <= ARR->num_elems; vi++) { JMCEVAL_print(TYPE, jmi_array_val_1(ARR,vi)); }
     86
     87/* Used by ModelicaUtilities */
     88void jmi_global_log(int warning, const char* name, const char* fmt, const char* value)
     89{
     90    printf("LOG\n");
     91    JMCEVAL_printInteger((double)warning);
     92    JMCEVAL_printString(name);
     93    JMCEVAL_printString(fmt);
     94    JMCEVAL_printString(value);
     95}
     96
     97jmp_buf jmceval_try_location;
     98
     99#define JMCEVAL_try() (setjmp(jmceval_try_location) == 0)
     100
     101void jmi_throw()
     102{
     103    longjmp(jmceval_try_location, 1);
     104}
     105
     106jmi_dynamic_function_memory_t* dyn_fcn_mem = NULL;
     107
     108jmi_dynamic_function_memory_t* jmi_dynamic_function_memory() {
     109    if (dyn_fcn_mem == NULL) { dyn_fcn_mem = jmi_dynamic_function_pool_create(1024*1024); }
     110    return dyn_fcn_mem;
     111}
     112
     113void* jmi_global_calloc(size_t n, size_t s)
     114{
     115    return jmi_dynamic_function_pool_direct_alloc(dyn_fcn_mem, n*s, 1);
     116}
     117
     118void JMCEVAL_setup() {
     119#ifdef _WIN32
     120    /* Prevent win from translating \n to \r\n */
     121    _setmode(fileno(stdout), _O_BINARY);
     122#endif
     123}
     124
     125int JMCEVAL_cont(const char* word) {
     126    char l[10];
     127    char* s = fgets(l, 10, stdin);
     128    if (strlen(s) == 1) {
     129        s = fgets(l, 10, stdin); /* Extra call to fix stray newline */
     130    }
     131    if (s == NULL) {
     132        exit(2);
     133    }
     134    if (strlen(s) == strlen(word)) {
     135        return strncmp(l, word, strlen(word)) == 0;
     136    }
     137    return 0;
     138}
     139
     140void JMCEVAL_check(const char* str) {
     141    printf("%s\n",str);
     142    fflush(stdout);
     143}
     144
     145void JMCEVAL_failed() {
     146    JMCEVAL_check("ABORT");
     147}
    33148
    34149/* Main */
     
    80195        JMCEVAL_failed();
    81196    }
    82     _jmi_dynamic_function_pool_destroy();
     197    jmi_dynamic_function_pool_destroy(dyn_fcn_mem);
    83198    JMCEVAL_check("END");
    84199    return 0;
  • trunk/Compiler/ModelicaCBackEnd/test/modelica/CCodeGenExternalCevalTests.mo

    r13700 r13703  
    1717
    1818package CCodeGenExternalCevalTests
    19 
    20 model ExtDynFcn1
    21         type E = enumeration(A,B);
    22     function f
    23         input Real a1;
    24         input Integer a2;
    25         input Boolean a3;
    26         input String a4;
    27         input E a5;
    28         output Real b1;
    29         output Integer b2;
    30         output Boolean b3;
    31         output String b4;
    32         output E b5;
    33         external;
    34     end f;
    35    
    36     Real x1;
    37     Integer x2;
    38     Boolean x3;
    39     String x4;
    40     E x5;
    41 equation
    42     (x1,x2,x3,x4,x5) = f(1,2,true,"s",E.A);
    43 
    44     annotation(__JModelica(UnitTesting(tests={
    45         FClassMethodTestCase(
    46             name="ExtDynFcn1",
    47             methodName="externalCTypes",
    48             description="Test that the different primitive types generates the correct C mapping",
    49             methodResult="
    50 f
    51 void
    52 d,i,i,s,i,*d,*i,*i,*s,*i,
    53 ")})));
    54 end ExtDynFcn1;
    55 
    56 model ExtDynFcn2
    57 type E = enumeration(A,B);
    58 function f
    59     input Real[:] a1;
    60     input Integer[:] a2;
    61     input Boolean[:] a3;
    62     input String[:] a4;
    63     input E[:] a5;
    64     output Real[size(a1,1)] b1;
    65     output Integer[size(a2,1)] b2;
    66     output Boolean[size(a3,1)] b3;
    67     output String[size(a4,1)] b4;
    68     output E[size(a5,1)] b5;
    69     external;
    70 end f;
    71     Real[1] x1;
    72     Integer[1] x2;
    73     Boolean[1] x3;
    74     String[1] x4;
    75     E[1] x5;
    76 equation
    77     (x1,x2,x3,x4,x5) = f({1},{2},{true},{"s"},{E.A});
    78 
    79     annotation(__JModelica(UnitTesting(tests={
    80         FClassMethodTestCase(
    81             name="ExtDynFcn2",
    82             methodName="externalCTypes",
    83             description="Test that the different primitive types (arrays of) generates the correct C mapping",
    84             methodResult="
    85 f
    86 void
    87 dv,i,iv,i,iv,i,sv,i,iv,i,*dv,i,*iv,i,*iv,i,*sv,i,*iv,i,
    88 ")})));
    89 end ExtDynFcn2;
    90 
    91 model ExtDynFcn3
    92     type E = enumeration(A,B);
    93     record R
    94         Real a1;
    95         Integer a2;
    96         Boolean a3;
    97         String a4;
    98         E a5;
    99         R2 r2;
    100     end R;
    101     record R2
    102         Real x;
    103     end R2;
    104    
    105     function f
    106         input R a;
    107         output R b;
    108         external f(a,b);
    109     end f;
    110    
    111     R r = f(R(1,2,true,"s",E.A, R2(3)));
    112 
    113     annotation(__JModelica(UnitTesting(tests={
    114         FClassMethodTestCase(
    115             name="ExtDynFcn3",
    116             methodName="externalCTypes",
    117             description="Test that records generates the correct C mapping",
    118             methodResult="
    119 f
    120 void
    121 R[d,i,i,s,i,R[d,],],*R[d,i,i,s,i,R[d,],],
    122 ")})));
    123 end ExtDynFcn3;
    124 
    12519
    12620model Scalar
     
    895789end ExtObj5;
    896790
    897 model ExtDynObj1
    898     function use1
    899         input  Os.Obj1 o1;
    900         output Real x;
    901         external annotation(Library="extObjectsUse", Include="#include \"extObjectsUse.h\"",
    902             LibraryDirectory="modelica://Library2", IncludeDirectory="Include2");
    903     end use1;
    904 
    905     Os.Obj1 o1 = Os.Obj1(3.13, 3, true, "A message");
    906     Real x = use1(o1);
    907 
    908     annotation(__JModelica(UnitTesting(tests={
    909         FClassMethodTestCase(
    910             name="ExtDynObj1",
    911             methodName="externalCTypes",
    912             description="Verifies that external objects are not handled by the dynamic evaluator",
    913             methodResult="
    914 ")})));
    915 end ExtDynObj1;
    916 
    917 
    918791model Dgelsx
    919792    function dgelsx
  • trunk/Compiler/ModelicaCompiler/module.options

    r13700 r13703  
    136136external objects during compilation.If less than 1, no processes will be kept
    137137alive, i.e. this feature is turned off."
    138 
    139 ********************************************************************************
    140 BOOLEAN external_constant_evaluation_dynamic compiler experimental false
    141 
    142 "If enabled, calls to external functions will be evaluated during compilation
    143 using a pre-compiled program (instead of generating and compiling one), if
    144 possible."
    145138
    146139********************************************************************************
     
    465458
    466459********************************************************************************
     460
  • trunk/Compiler/ModelicaCompiler/src/jastadd/ModelicaCompiler.jrag

    r13700 r13703  
    12661266        /* Temporary fix to problems with long compilation times due to later evaluations */
    12671267        getExternalFunctionCache().tearDown();
    1268         options.external_constant_evaluation.setValue(0);
     1268        options.setIntegerOption("external_constant_evaluation", 0);
    12691269       
    12701270        hookModelTransformed(fc);
  • trunk/Compiler/ModelicaCompiler/src/java/org/jmodelica/util/ccompiler/CCompilerDelegator.java

    r13700 r13703  
    351351        };
    352352    }
    353 
    354     public abstract Set<String> expandCompilerSpecificLibraryPaths(ModelicaLogger log, AbstractOptionRegistry options,
    355             Set<String> extLibDirs, String platform);
    356353}
    357354
  • trunk/Compiler/ModelicaCompiler/src/java/org/jmodelica/util/ccompiler/GccCompilerDelegator.java

    r13700 r13703  
    2626import java.util.Set;
    2727
    28 import org.jmodelica.common.options.AbstractOptionRegistry;
    2928import org.jmodelica.util.EnvironmentUtils;
    3029import org.jmodelica.util.exceptions.CcodeCompilationException;
     
    107106            vars.put("AR", new File(mingw_bin, "ar").getPath());
    108107        }
    109     }
    110    
    111     @Override
    112     public Set<String> expandCompilerSpecificLibraryPaths(ModelicaLogger log, AbstractOptionRegistry options, Set<String> extLibDirs, String platform) {
    113         Set<String> expandedLibDirs = expandLibraries(extLibDirs, platform, "gcc" + compilerVersionNumber());
    114         return expandedLibDirs;
    115108    }
    116109   
  • trunk/Compiler/ModelicaFlatTree/src/jastadd/ConstantEvaluation/ConstantEvaluation.jrag

    r13700 r13703  
    50795079        }
    50805080       
    5081         public AlgorithmEvaluator createAlgorithmEvaluator(OptionRegistry options, Map<CommonVariableDecl, CValue> values) {
     5081        public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) {
    50825082            return new AlgorithmEvaluator(externalEvaluationEnabled, options, values);
    50835083        }
    50845084       
    5085         public AlgorithmEvaluator createEmptyAlgorithmEvaluator(OptionRegistry options) {
     5085        public AlgorithmEvaluator createEmptyAlgorithmEvaluator(AbstractOptionRegistry options) {
    50865086            return new AlgorithmEvaluator(true, options, Collections.<CommonVariableDecl, CValue>emptyMap());
    50875087        }
     
    51495149       
    51505150        @Override
    5151         public AlgorithmEvaluator createAlgorithmEvaluator(OptionRegistry options, Map<CommonVariableDecl, CValue> values) {
     5151        public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) {
    51525152            return new PartialAlgorithmEvaluator(externalEvaluationEnabled(), options, values, this);
    51535153        }
     
    51835183       
    51845184        @Override
    5185         public AlgorithmEvaluator createAlgorithmEvaluator(OptionRegistry options, Map<CommonVariableDecl, CValue> values) {
     5185        public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) {
    51865186            if (this.values == null) {
    51875187                this.values = values;
     
    52775277    public class AlgorithmEvaluator extends VariableEvaluator {
    52785278       
    5279         protected final Map<CommonVariableDecl, CValue> values;
    5280         private final OptionRegistry options;
    5281        
    5282         public AlgorithmEvaluator(boolean evaluateExternalEnabled, OptionRegistry options, Map<CommonVariableDecl, CValue> values) {
     5279        protected Map<CommonVariableDecl, CValue> values;
     5280        private AbstractOptionRegistry options;
     5281       
     5282        public AlgorithmEvaluator(boolean evaluateExternalEnabled, AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) {
    52835283            super(evaluateExternalEnabled);
    52845284            this.values  = values;
     
    52875287       
    52885288        public int externalEvaluation() {
    5289             return externalEvaluationEnabled() ? options.external_constant_evaluation.getValue() : 0;
     5289            return externalEvaluationEnabled() ? options.getIntegerOption("external_constant_evaluation") : 0;
    52905290        }
    52915291       
     
    53515351        protected ArrayList<IfEvaluation> ifStack;
    53525352       
    5353         public PartialAlgorithmEvaluator(boolean evaluateExternalEnabled, OptionRegistry options,
     5353        public PartialAlgorithmEvaluator(boolean evaluateExternalEnabled, AbstractOptionRegistry options,
    53545354                Map<CommonVariableDecl, CValue> values, PartialVariableEvaluator variableEvaluator) {
    53555355            super(evaluateExternalEnabled, options, values);
     
    53685368       
    53695369        @Override
    5370         public AlgorithmEvaluator createAlgorithmEvaluator(OptionRegistry options, Map<CommonVariableDecl, CValue> values) {
     5370        public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) {
    53715371            return variableEvaluator.createAlgorithmEvaluator(options, values);
    53725372        }
  • trunk/Compiler/ModelicaFlatTree/src/jastadd/ConstantEvaluation/ExternalConstantEvaluation.jrag

    r13700 r13703  
    2626import java.util.TimerTask;
    2727
    28 import org.jmodelica.common.evaluation.ExternalFunctionCompiler;
    2928import org.jmodelica.common.evaluation.ExternalFunction;
    3029import org.jmodelica.common.evaluation.ExternalProcessCache;
    3130import org.jmodelica.common.evaluation.ExternalProcessCacheImpl;
    3231import org.jmodelica.common.evaluation.ExternalProcessMultiCache;
    33 import org.jmodelica.common.evaluation.FailedExternalFunction;
    3432import org.jmodelica.common.evaluation.ProcessCommunicator;
    3533
     
    5149    class ModelicaCompiler {}
    5250   
    53     ModelicaCompiler   implements ExternalFunctionCompiler<ExternalArgument, FExternalStmt>;
     51    ModelicaCompiler   implements ExternalProcessMultiCache.Compiler<ExternalArgument, FExternalStmt>;
    5452    FExternalStmt      implements ExternalProcessMultiCache.External<ExternalArgument>;
    5553    ExternalArgument   extends    ExternalProcessMultiCache.Variable<CValue,FType>;
     
    9189     * Check if this external function should be cached as a live process.
    9290     */
    93     syn int FExternalStmt.processLimit() =
    94             myOptions().external_constant_evaluation_max_proc.getValue();
    95    
    96     syn boolean FExternalStmt.dynamicEvaluatorEnabled() =
    97             myOptions().external_constant_evaluation_dynamic.getValue()
    98             && !externalObjectsToSerialize().iterator().hasNext();
     91    syn boolean FExternalStmt.shouldCacheProcess() {
     92        return myOptions().getIntegerOption("external_constant_evaluation_max_proc") > 0;
     93    }
    9994   
    10095    /**
     
    174169        ExternalFunctionCache efc = root().getUtilInterface().getExternalFunctionCache();
    175170        if (efc == null) {
    176             return FailedExternalFunction.<ExternalArgument, CValue, FType, FExternalStmt>failedEval(
    177                     root().getUtilInterface().getModelicaCompiler(),
    178                     this, "external function cache unavailable", false);
     171            return new ExternalProcessCacheImpl<>(root().getUtilInterface().getModelicaCompiler())
     172                .failedEval(this, "external function cache unavailable", false);
    179173        }
    180174        return efc.getExternalProcessCache(getLibTopPackagePath()).getExternalFunction(this);
     
    211205       
    212206        if (error != null) {
    213             throw new ConstantEvaluationException(null, FailedExternalFunction.failedEvalMsg(getName(), error));
     207            throw new ConstantEvaluationException(null, ExternalProcessCacheImpl.failedEvalMsg(getName(), error));
    214208        }
    215209       
  • trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessCache.java

    r13700 r13703  
    2424
    2525    protected abstract void tearDown();
     26
     27    public abstract ExternalFunction<K, V> failedEval(External<?> ext, String msg, boolean log);
    2628   
    2729
  • trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessCacheImpl.java

    r13700 r13703  
    33import java.io.File;
    44import java.io.FileNotFoundException;
     5import java.io.IOException;
    56import java.io.PrintStream;
    67import java.util.ArrayList;
    78import java.util.HashMap;
    8 import java.util.HashSet;
    99import java.util.LinkedHashSet;
    1010import java.util.Map;
    11 import java.util.Set;
    12 
     11
     12import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Compiler;
    1313import org.jmodelica.common.evaluation.ExternalProcessMultiCache.External;
    1414import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Type;
     
    1616import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Variable;
    1717import org.jmodelica.util.EnvironmentUtils;
    18 import org.jmodelica.util.SystemUtil;
    1918import org.jmodelica.util.ccompiler.CCompilerDelegator;
    2019import org.jmodelica.util.exceptions.CcodeCompilationException;
    2120import org.jmodelica.util.logging.ModelicaLogger;
     21import org.jmodelica.util.values.ConstantEvaluationException;
    2222
    2323public class ExternalProcessCacheImpl<K extends Variable<V, T>, V extends Value, T extends Type<V>, E extends External<K>> extends ExternalProcessCache<K, V, T, E> {
     
    2626     * Maps external functions names to compiled executables.
    2727     */
    28     private final Map<String, ExternalFunction<K, V>> cachedExternals = new HashMap<String, ExternalFunction<K, V>>();
     28    private Map<String, ExternalFunction<K, V>> cachedExternals = new HashMap<String, ExternalFunction<K, V>>();
    2929
    3030    /**
    3131     * Keeps track of all living processes, least recently used first.
    3232     */
    33     private final LinkedHashSet<ExternalFunction<K, V>> livingCachedExternals = new LinkedHashSet<ExternalFunction<K, V>>();
    34 
    35     private final ExternalFunctionCompiler<K, E> mc;
    36 
    37     public ExternalProcessCacheImpl(ExternalFunctionCompiler<K, E> mc) {
     33    private LinkedHashSet<ExternalFunction<K, V>> livingCachedExternals = new LinkedHashSet<ExternalFunction<K, V>>();
     34
     35    private Compiler<K, E> mc;
     36
     37    public ExternalProcessCacheImpl(Compiler<K, E> mc) {
    3838        this.mc = mc;
    3939    }
     
    4242        return mc.log();
    4343    }
    44    
    45     private String getPlatform() {
    46         return CCompilerDelegator.reduceBits(EnvironmentUtils.getJavaPlatform(),
    47                 mc.getCCompiler().getTargetPlatforms());
    48     }
    49    
    50     private String getSharedLibrary(External<K> ext) {
    51         String sharedLib = "";
    52         String extLibrary = "";
    53        
    54         if (ext.library() != null && ext.library().length == 1) {
    55             extLibrary = ext.library()[0];
    56         } else {
    57             return sharedLib;
    58         }
    59        
    60         HashSet<String> externalLibraryDirectories = new HashSet<String>();
    61         externalLibraryDirectories.add(ext.libraryDirectory());
    62         Set<String> expandedLibDirs = mc.getCCompiler().expandCompilerSpecificLibraryPaths(mc.log(), ext.myOptions(),
    63                                                    externalLibraryDirectories, getPlatform());
    64        
    65         for (String dir : expandedLibDirs) {
    66             File testlib1 = new File(dir, extLibrary + SystemUtil.sharedLibraryExtension());
    67             File testlib2 = new File(dir, "lib" + extLibrary + SystemUtil.sharedLibraryExtension());
    68            
    69             if (testlib1.exists() && !testlib1.isDirectory()) {
    70                 sharedLib = testlib1.toString();
    71                 break;
    72             }
    73             if (testlib2.exists() && !testlib2.isDirectory()) {
    74                 sharedLib = testlib2.toString();
    75                 break;
    76             }
    77         }
    78        
    79         return sharedLib;
    80     }
    81    
    82     private static ArrayList<String> builtinExternalFunctions = new ArrayList<String>() {{
    83         add("ModelicaStrings_substring");
    84         add("ModelicaStrings_length");
    85         add("ModelicaStrings_skipWhiteSpace");
    86         add("ModelicaStrings_compare");
    87     }};
    88    
    89     private static ArrayList<String> supportedSignatures = new ArrayList<String>() {{
    90         add("d+d,d,");
    91         add("d+i,");
    92         add("d+i,d,d,");
    93         add("s+s,i,i,");
    94         add("i+s,");
    95         add("i+s,i,");
    96         add("i+s,s,i,");
    97         add("i+i,i,");
    98         add("void+i,d,d,*R[d,d,d,d,d,d,d,d,d,d,d,],");
    99         add("void+d,d,*d,");
    100     }};
    101    
    102     public boolean canUseEvaluator(E ext, ArrayList<String> arguments) {
    103         if (!ext.dynamicEvaluatorEnabled()) {
    104             return false;
    105         }
    106        
    107         String sharedLibrary = getSharedLibrary(ext);
    108         String functionName  = ext.getName();
    109         String outputArguments = ext.functionReturnArgSerialized();
    110         String inputArguments  = ext.functionArgsSerialized();
    111        
    112         if (sharedLibrary.equals("")) {
    113             if (builtinExternalFunctions.contains(functionName)) {
    114                 sharedLibrary = "NoSharedLibrary";
    115             } else {
    116                 mc.log().debug("Could not find a shared library containing '" + functionName + "'. Disabling use of the evaluator...");
    117                 return false;
    118             }
    119         }
    120        
    121         if (!supportedSignatures.contains(outputArguments+"+"+inputArguments)) {
    122             mc.log().debug("The function signature, outputs '" + outputArguments + "', inputs '" + inputArguments + "', is not supported. Disabling use of the evaluator...");
    123             return false;
    124         }
    125        
    126         arguments.add(sharedLibrary);
    127         arguments.add(functionName);
    128         arguments.add(outputArguments);
    129         arguments.add(inputArguments);
    130 
    131         return true;
    132     }
    133    
     44
    13445    @Override
    13546    public ExternalFunction<K, V> getExternalFunction(E ext) {
     
    13748        if (ef == null) {
    13849            if (mc == null) {
    139                 return FailedExternalFunction.<K,V,T,E>failedEval(mc, ext, "Missing ModelicaCompiler", false);
     50                return failedEval(ext, "Missing ModelicaCompiler", false);
    14051            }
    14152            try {
    14253                long time = System.currentTimeMillis();
    143                 String executable = null;
    144                 ArrayList<String> arguments = new ArrayList<String>();
    145                 String debugMsg = "";
    146                 ExternalFunctionExecutable extFunctionExecutable;
    147                 if (canUseEvaluator(ext, arguments)) {
    148                     String jmHome = System.getenv("JMODELICA_HOME");
    149                     String bits = getPlatform().contains("64") && SystemUtil.isWindows() ? "64" : "";
    150                     executable = jmHome + File.separator + "bin" + bits + File.separator + "jmi_evaluator" + SystemUtil.executableExtension();
    151                    
    152                     arguments.add(0, executable); /* Needs to be first */
    153                    
    154                     extFunctionExecutable = new ExternalFunctionExecutableDynamic(arguments);
    155                    
    156                     debugMsg = "Succesfully connected external function '" + ext.getName() + "' to the evaluator '"
    157                             + executable + "' with outputs: '" + ext.functionReturnArgSerialized() + "' and inputs: '" + ext.functionArgsSerialized() + "'";
     54                String executable = mc.compileExternal(ext);
     55                if (ext.shouldCacheProcess()) {
     56                    ef = new MappedExternalFunction(ext, executable);
    15857                } else {
    159                     executable = mc.compileExternal(ext);
    160                    
    161                     extFunctionExecutable = new ExternalFunctionExecutableGenerated(executable);
    162                    
    163                     debugMsg = "Succesfully compiled external function '" + ext.getName() + "' to executable '"
    164                             + executable + "' code for evaluation";
    165                 }
    166                
    167                 if (ext.processLimit() > 0) {
    168                     ef = new MappedExternalFunction<K,V,T,E>(mc, ext, extFunctionExecutable, livingCachedExternals);
    169                 } else {
    170                     ef = new ExternalFunctionImpl<K,V,T,E>(mc, ext, extFunctionExecutable);
     58                    ef = new CompiledExternalFunction(ext, executable);
    17159                }
    17260                time = System.currentTimeMillis() - time;
    173                 mc.log().debug(debugMsg +", time: " + time + "ms");
     61                mc.log().debug("Succesfully compiled external function '" + ext.getName() + "' to executable '"
     62                        + executable + "' code for evaluation, time: " + time + "ms");
    17463            } catch (FileNotFoundException e) {
    175                 ef = FailedExternalFunction.<K,V,T,E>failedEval(mc, ext, "c-code generation failed '" + e.getMessage() + "'", true);
     64                ef = failedEval(ext, "c-code generation failed '" + e.getMessage() + "'", true);
    17665                mc.log().debug(ef.getMessage());
    17766            } catch (CcodeCompilationException e) {
    178                 ef = FailedExternalFunction.<K,V,T,E>failedEval(mc, ext, "c-code compilation failed '" + e.getMessage() + "'", true);
     67                ef = failedEval(ext, "c-code compilation failed '" + e.getMessage() + "'", true);
    17968                mc.log().debug(ef.getMessage());
    18069                e.printStackTrace(new PrintStream(mc.log().debugStream()));
     
    20695    }
    20796
     97    @Override
     98    public ExternalFunction<K, V> failedEval(External<?> ext, String msg, boolean log) {
     99        return new FailedExternalFunction(failedEvalMsg(ext.getName(), msg), log);
     100    }
     101
     102    public static String failedEvalMsg(String name, String msg) {
     103        return "Failed to evaluate external function '" + name + "', " + msg;
     104    }
     105
     106    private class FailedExternalFunction implements ExternalFunction<K, V> {
     107        private String msg;
     108        private boolean log;
     109
     110        public FailedExternalFunction(String msg, boolean log) {
     111            this.msg = msg;
     112            this.log = log;
     113        }
     114
     115        @Override
     116        public String getMessage() {
     117            return msg;
     118        }
     119
     120        @Override
     121        public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
     122            if (log) {
     123                log().debug("Evaluating failed external function: " + ext.getName());
     124            }
     125            throw new ConstantEvaluationException(null, getMessage());
     126        }
     127
     128        @Override
     129        public void destroyProcess() {
     130            // Do nothing
     131        }
     132
     133        @Override
     134        public void remove() {
     135            // Do nothing
     136        }
     137    }
     138
     139    /**
     140     * Represents an external function that has been compiled successfully.
     141     */
     142    private class CompiledExternalFunction implements ExternalFunction<K, V> {
     143        protected String executable;
     144        protected ProcessBuilder processBuilder;
     145        private String msg;
     146
     147        public CompiledExternalFunction(External<K> ext, String executable) {
     148            this.executable = executable;
     149            this.processBuilder = createProcessBuilder(ext);
     150            this.msg = "Succesfully compiled external function '" + ext.getName() + "'";
     151        }
     152
     153        @Override
     154        public String getMessage() {
     155            return msg;
     156        }
     157
     158        protected ProcessCommunicator<V, T> createProcessCommunicator() throws IOException {
     159            return new ProcessCommunicator<V, T>(mc, processBuilder.start());
     160        }
     161
     162        @Override
     163        public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
     164            log().debug("Evaluating compiled external function: " + ext.getName());
     165            ProcessCommunicator<V, T> com = null;
     166            try {
     167                com = createProcessCommunicator();
     168                setup(ext, values, timeout, com);
     169                evaluate(ext, values, timeout, com);
     170                return teardown(timeout, com);
     171            } finally {
     172                if (com != null) {
     173                    com.destroy();
     174                }
     175            }
     176        }
     177
     178        public void setup(External<K> ext, Map<K, V> values, int timeout, ProcessCommunicator<V, T> com)
     179                throws IOException {
     180            com.startTimer(timeout);
     181            com.accept("START");
     182            for (K eo : ext.externalObjectsToSerialize()) {
     183                com.put(values.containsKey(eo) ? values.get(eo) : eo.ceval(), eo.type());
     184            }
     185            com.accept("READY");
     186            com.cancelTimer();
     187        }
     188
     189        public void evaluate(External<K> ext, Map<K, V> values, int timeout, ProcessCommunicator<V, T> com)
     190                throws IOException {
     191            com.startTimer(timeout);
     192            com.check("EVAL");
     193
     194            for (K arg : ext.functionArgsToSerialize()) {
     195                com.put(values.containsKey(arg) ? values.get(arg) : arg.ceval(), arg.type());
     196            }
     197            com.accept("CALC");
     198            com.accept("DONE");
     199            for (K cvd : ext.varsToDeserialize())
     200                values.put(cvd, com.get(cvd.type()));
     201            com.accept("READY");
     202            com.cancelTimer();
     203        }
     204
     205        public int teardown(int timeout, ProcessCommunicator<V, T> com) throws IOException {
     206            com.startTimer(timeout);
     207            com.check("EXIT");
     208            com.accept("END");
     209            int result = com.end();
     210            com.cancelTimer();
     211            // log().debug("SUCCESS TEARDOWN");
     212            return result;
     213        }
     214
     215        @Override
     216        public void destroyProcess() {
     217            // Do nothing
     218        }
     219
     220        @Override
     221        public void remove() {
     222            new File(executable).delete();
     223        }
     224
     225        private ProcessBuilder createProcessBuilder(External<K> ext) {
     226            ProcessBuilder pb = new ProcessBuilder(executable);
     227            Map<String, String> env = pb.environment();
     228            if (env.keySet().contains("Path")) {
     229                env.put("PATH", env.get("Path"));
     230                env.remove("Path");
     231            }
     232            pb.redirectErrorStream(true);
     233            if (ext.libraryDirectory() != null) {
     234                // Update environment in case of shared library
     235                String platform = CCompilerDelegator.reduceBits(EnvironmentUtils.getJavaPlatform(),
     236                        mc.getCCompiler().getTargetPlatforms());
     237                File f = new File(ext.libraryDirectory(), platform);
     238                String libLoc = f.isDirectory() ? f.getPath() : ext.libraryDirectory();
     239                appendPath(env, libLoc, platform);
     240            }
     241            return pb;
     242        }
     243
     244        /**
     245         * Append a library location <code>libLoc</code> to the path variable in
     246         * environment <code>env</code>.
     247         */
     248        private void appendPath(Map<String, String> env, String libLoc, String platform) {
     249            String sep = platform.startsWith("win") ? ";" : ":";
     250            String var = platform.startsWith("win") ? "PATH" : "LD_LIBRARY_PATH";
     251            String res = env.get(var);
     252            if (res == null)
     253                res = libLoc;
     254            else
     255                res = res + sep + libLoc;
     256            env.put(var, res);
     257        }
     258    }
     259
     260    /**
     261     * A CompiledExternalFunction which can cache several processes with external
     262     * object constructor only called once.
     263     */
     264    private class MappedExternalFunction extends CompiledExternalFunction {
     265
     266        private Map<String, ExternalFunction<K, V>> lives = new HashMap<>();
     267
     268        private final int externalConstantEvaluationMaxProc;
     269
     270        public MappedExternalFunction(External<K> ext, String executable) {
     271            super(ext, executable);
     272            externalConstantEvaluationMaxProc = ext.myOptions()
     273                    .getIntegerOption("external_constant_evaluation_max_proc");
     274        }
     275
     276        /**
     277         * Find a LiveExternalFunction based on the external object of this external
     278         * function. Start a new process if not up already. Failure to set up (call
     279         * constructor) will cache and return a Failed external function.
     280         */
     281        private ExternalFunction<K, V> getActual(External<K> ext, Map<K, V> values, int timeout) {
     282            Variable<V, T> cvd = ext.cachedExternalObject();
     283            String name = cvd == null ? "" : cvd.ceval().getMarkedExternalObject();
     284            ExternalFunction<K, V> ef = lives.get(name);
     285            if (ef == null) {
     286                LiveExternalFunction lef = new LiveExternalFunction();
     287                try {
     288                    lef.ready(ext, values, timeout);
     289                    ef = lef;
     290                } catch (IOException e) {
     291                    lef.destroyProcess();
     292                    ef = failedEval(ext, " error starting process '" + e.getMessage() + "'", true);
     293                } catch (ConstantEvaluationException e) {
     294                    lef.destroyProcess();
     295                    ef = failedEval(ext, " error starting process '" + e.getMessage() + "'", true);
     296                }
     297                lives.put(name, ef);
     298            }
     299            return ef;
     300        }
     301
     302        @Override
     303        public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
     304            return getActual(ext, values, timeout).evaluate(ext, values, timeout);
     305        }
     306
     307        @Override
     308        public void destroyProcess() {
     309            for (ExternalFunction<K, V> ef : lives.values()) {
     310                ef.destroyProcess();
     311            }
     312            lives.clear();
     313        }
     314
     315        /**
     316         * Represents a (possible) living external function process.
     317         */
     318        private class LiveExternalFunction implements ExternalFunction<K, V> {
     319
     320            protected ProcessCommunicator<V, T> com;
     321
     322            public LiveExternalFunction() {
     323                super();
     324            }
     325
     326            @Override
     327            public String getMessage() {
     328                return MappedExternalFunction.this.getMessage();
     329            }
     330
     331            @Override
     332            public int evaluate(External<K> ext, Map<K, V> values, int timeout) throws IOException {
     333                log().debug("Evaluating live external function: " + ext.getName());
     334                try {
     335                    ready(ext, values, timeout);
     336                    long time = System.currentTimeMillis();
     337                    MappedExternalFunction.this.evaluate(ext, values, timeout, com);
     338                    time = System.currentTimeMillis() - time;
     339                    log().debug("Finished evaluating live external function, time: " + time + "ms");
     340                } catch (ProcessCommunicator.AbortConstantEvaluationException e) {
     341
     342                } catch (ConstantEvaluationException e) {
     343                    destroyProcess();
     344                    throw e;
     345                } catch (IOException e) {
     346                    destroyProcess();
     347                    throw e;
     348                }
     349                return 0;
     350            }
     351
     352            /**
     353             * Make sure process is ready for evaluation call.
     354             */
     355            protected void ready(External<K> ext, Map<K, V> values, int timeout) throws IOException {
     356                if (com == null) {
     357                    long time1 = System.currentTimeMillis();
     358                    // Start process if not live.
     359                    com = createProcessCommunicator();
     360                    long time2 = System.currentTimeMillis();
     361                    // Send external object constructor inputs
     362                    MappedExternalFunction.this.setup(ext, values, timeout, com);
     363                    long time3 = System.currentTimeMillis();
     364                    log().debug("Setup live external function: " + ext.getName()
     365                              + ", createProcessCommunicator() time: " + (time2 - time1)
     366                              + "ms, setup time: " + (time3 - time2) + "ms");
     367                }
     368
     369                // Mark as most recently used
     370                livingCachedExternals.remove(this);
     371                livingCachedExternals.add(this);
     372
     373                // If we are over the allowed number of cached processes
     374                // we kill the least recently used.
     375                if (livingCachedExternals.size() > externalConstantEvaluationMaxProc) {
     376                    livingCachedExternals.iterator().next().destroyProcess();
     377                }
     378            }
     379
     380            @Override
     381            public void destroyProcess() {
     382                if (com != null) {
     383                    livingCachedExternals.remove(this);
     384                    com.destroy();
     385                    com = null;
     386                }
     387            }
     388
     389            @Override
     390            public void remove() {
     391                // Removing this executable is handled by surrounding MappedExternalFunction
     392                throw new UnsupportedOperationException();
     393            }
     394        }
     395    }
    208396}
  • trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessMultiCache.java

    r13700 r13703  
    22
    33import java.io.BufferedWriter;
     4import java.io.FileNotFoundException;
    45import java.io.IOException;
    56import java.util.LinkedHashMap;
    67import java.util.Map;
    78
     9import org.jmodelica.common.LogContainer;
    810import org.jmodelica.common.options.AbstractOptionRegistry;
     11import org.jmodelica.util.ccompiler.CCompilerDelegator;
     12import org.jmodelica.util.exceptions.CcodeCompilationException;
    913
    1014public class ExternalProcessMultiCache<K extends ExternalProcessMultiCache.Variable<V, T>, V extends ExternalProcessMultiCache.Value, T extends ExternalProcessMultiCache.Type<V>, E extends ExternalProcessMultiCache.External<K>> {
     15
     16    public interface Compiler<K, E extends External<K>> extends LogContainer {
     17        public String compileExternal(E ext) throws FileNotFoundException, CcodeCompilationException;
     18
     19        public CCompilerDelegator getCCompiler();
     20    }
    1121
    1222    public interface External<K> {
    1323        public String getName();
    1424
    15         public int processLimit();
    16 
    17         public boolean dynamicEvaluatorEnabled();
     25        public boolean shouldCacheProcess();
    1826
    1927        public AbstractOptionRegistry myOptions();
     
    2735        public Iterable<K> functionArgsToSerialize();
    2836
    29         public String functionArgsSerialized();
    30 
    31         public String functionReturnArgSerialized();
    32 
    3337        public Iterable<K> varsToDeserialize();
    34 
    35         public String[] library();
    3638    }
    3739
     
    5456    private Map<String, ExternalProcessCache<K, V, T, E>> map = new LinkedHashMap<>();
    5557
    56     private ExternalFunctionCompiler<K, E> mc;
     58    private Compiler<K, E> mc;
    5759
    58     public ExternalProcessMultiCache(ExternalFunctionCompiler<K, E> mc) {
     60    public ExternalProcessMultiCache(Compiler<K, E> mc) {
    5961        this.mc = mc;
    6062    }
  • trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/util/SystemUtil.java

    r13700 r13703  
    7272        return isLinux() ? "" : ".exe";
    7373    }
    74    
    75     public static String sharedLibraryExtension() {
    76         if (isWindows()) {
    77             return ".dll";
    78         } else if (isLinux()) {
    79             return ".so";
    80         } else {
    81             return ".dylib";
    82         }
    83     }
    8474
    8575    /**
  • trunk/Compiler/ModelicaFrontEnd/test/junit/org/jmodelica/test/common/ExternalProcessCacheTest.java

    r13700 r13703  
    99import java.io.IOException;
    1010
    11 import org.jmodelica.common.evaluation.ExternalFunctionCompiler;
     11import org.jmodelica.common.evaluation.ExternalProcessCache;
    1212import org.jmodelica.common.evaluation.ExternalFunction;
    13 import org.jmodelica.common.evaluation.ExternalProcessCache;
    1413import org.jmodelica.common.evaluation.ExternalProcessMultiCache;
     14import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Variable;
     15import org.jmodelica.common.options.AbstractOptionRegistry;
     16import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Value;
     17import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Type;
    1518import org.jmodelica.common.evaluation.ExternalProcessMultiCache.External;
    16 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Type;
    17 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Value;
    18 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Variable;
    1919import org.jmodelica.common.evaluation.ProcessCommunicator;
    20 import org.jmodelica.common.options.AbstractOptionRegistry;
    2120import org.jmodelica.util.ccompiler.CCompilerDelegator;
    2221import org.jmodelica.util.exceptions.CcodeCompilationException;
     
    7574    class ExternalProcessCacheMock<K extends Variable<V,T>, V extends Value, T extends Type<V>, E extends External<K>> extends ExternalProcessMultiCache<K,V,T,E> {
    7675
    77         public ExternalProcessCacheMock(ExternalFunctionCompiler<K,E> mc) {
     76        public ExternalProcessCacheMock(Compiler<K,E> mc) {
    7877            super(mc);
    7978        }
     
    109108        }
    110109
    111     }
    112 
    113     class CompilerMock implements ExternalFunctionCompiler<VariableMock, ExternalMock> {
     110        @Override
     111        public ExternalFunction<K,V> failedEval(External<?> ext, String msg, boolean log) {
     112            // TODO Auto-generated method stub
     113            return null;
     114        }
     115       
     116    }
     117
     118    class CompilerMock implements ExternalProcessMultiCache.Compiler<VariableMock, ExternalMock> {
    114119
    115120        @Override
     
    184189
    185190        @Override
    186         public int processLimit() {
    187             // TODO Auto-generated method stub
    188             return 0;
    189         }
    190 
    191         @Override
    192         public boolean dynamicEvaluatorEnabled() {
     191        public boolean shouldCacheProcess() {
     192            // TODO Auto-generated method stub
    193193            return false;
    194194        }
     
    223223            return null;
    224224        }
    225        
    226         @Override
    227         public String functionArgsSerialized() {
    228             // TODO Auto-generated method stub
    229             return null;
    230         }
    231        
    232         @Override
    233         public String functionReturnArgSerialized() {
    234             // TODO Auto-generated method stub
    235             return null;
    236         }
    237225
    238226        @Override
     
    241229            return null;
    242230        }
    243        
    244         @Override
    245         public String[] library() {
    246             // TODO Auto-generated method stub
    247             return null;
    248         }
    249231
    250232    }
  • trunk/Python/src/tests_jmodelica/files/Modelica/ExtFunctionTests.mo

    r13700 r13703  
    11package ExtFunctionTests
    2 
    3 model Evaluator_Double
    4     function d_i
    5      input Integer a;
    6      output Real b;
    7 
    8      external "C" b=f_d_i(a) annotation(Library="evaluatorTestsShared",
    9                              Include="#include \"evaluatorTests.h\"");
    10     end d_i;
    11    
    12     function d_idd
    13      input Integer a;
    14      input Real b;
    15      input Real c;
    16      output Real d;
    17 
    18      external "C" d=f_d_idd(a,b,c) annotation(Library="evaluatorTestsShared",
    19                              Include="#include \"evaluatorTests.h\"");
    20     end d_idd;
    21    
    22    
    23     Real c = d_i(1);
    24     Real d = d_idd(1, 2.0, 3.0);
    25 end Evaluator_Double;
    26 
    27 model Evaluator_Integer
    28     function i_ii
    29      input Integer a;
    30      input Integer b;
    31      output Integer c;
    32 
    33      external "C" c=f_i_ii(a,b) annotation(Library="evaluatorTestsShared",
    34                              Include="#include \"evaluatorTests.h\"");
    35     end i_ii;
    36    
    37     Integer c = i_ii(1,2);
    38 end Evaluator_Integer;
    39 
    40 model Evaluator_Record
    41     record R
    42         Real x0;
    43         Real x1;
    44         Real x2;
    45         Real x3;
    46         Real x4;
    47         Real x5;
    48         Real x6;
    49         Real x7;
    50         Real x8;
    51         Real x9;
    52         Real x10;
    53     end R;
    54     function iddpR_ddddddddddd_
    55      input Integer a;
    56      input Real b;
    57      input Real c;
    58      output R d;
    59 
    60      external "C" f___iddpR_ddddddddddd_(a,b,c,d) annotation(Library="evaluatorTestsShared",
    61                              Include="#include \"evaluatorTests.h\"");
    62     end iddpR_ddddddddddd_;
    63    
    64     R c = iddpR_ddddddddddd_(1,2.0,3.0);
    65 end Evaluator_Record;
    66 
    67 
    68 model Evaluator_Substring
    69     constant String full="Yy00";
    70     constant String sub=Modelica.Utilities.Strings.substring(full,1,1);
    71     constant String string1 = "This is line 111";
    72     constant String string2 = Modelica.Utilities.Strings.substring(string1,9,12); // string2 = \"line\"
    73     constant Integer len = Modelica.Utilities.Strings.length(string1);
    74     constant Integer start = Modelica.Utilities.Strings.Advanced.skipWhiteSpace("   Hello", 1);
    75     constant Boolean not_equal = Modelica.Utilities.Strings.isEqual("Temp", "test", true);
    76     constant Boolean equal = Modelica.Utilities.Strings.isEqual("Temp", "Temp", true);
    77 end Evaluator_Substring;
    78 
    79 model Evaluator_Add
    80  function add1
    81      input Real a;
    82      input Real b;
    83      output Real c;
    84 
    85      external "C" c=add(a,b) annotation(Library="addNumbersShared",
    86                              Include="#include \"addNumbers.h\"");
    87  end add1;
    88  
    89  function add2
    90      input Real a;
    91      input Real b;
    92      output Real c;
    93 
    94      external "C" add_output(a,b,c) annotation(Library="addNumbersShared",
    95                              Include="#include \"addNumbers.h\"");
    96  end add2;
    97 
    98  constant Real a = 1;
    99  constant Real b = 2;
    100  Real c = add1(a,b);
    101  Real d = add2(a,b);
    102 end Evaluator_Add;
    103 
    104 model Evaluator_Multiple_Add
    105  function add
    106      input Real a;
    107      input Real b;
    108      input Real c;
    109      input Real d;
    110      input Real e;
    111      input Real f;
    112      input Real g;
    113      input Real h;
    114      input Real i;
    115      output Real o;
    116 
    117      external "C" o=multiple_add(a,b,c,d,e,f,g,h,i) annotation(Library="addNumbersShared",
    118                              Include="#include \"addNumbers.h\"");
    119  end add;
    120  
    121  constant Real a = 1;
    122  constant Real b = 2;
    123  Real c = add(a,b,a,b,a,b,a,b,a);
    124 end Evaluator_Multiple_Add;
    125 
    126 model Evaluator_Unknown_Shared
    127     function unknown_function
    128         input Real a;
    129         output Real b;
    130         external "C" b = unknown(a) annotation(Library="unknown");
    131     end unknown_function;
    132    
    133     constant Real a = unknown_function(1.0);
    134 end Evaluator_Unknown_Shared;
    1352
    1363model ExtFunctionTest1
  • trunk/Python/src/tests_jmodelica/files/Modelica/Resources/CMakeLists.txt

    r13700 r13703  
    3838include_directories(${TOP_SRC}/RuntimeLibrary/src/jmi)
    3939
    40 set(EVALUATORTESTS_Sources
    41     src/evaluatorTests.c
    42     Include/evaluatorTests.h
    43 )
    44 
    4540set(ADDNUMBERS_Sources
    4641    src/addNumbers.c
     
    7570endif()
    7671
    77 #Build evaluatorTests library
    78 add_library(evaluatorTestsShared SHARED ${EVALUATORTESTS_Sources})
    79 if(NOT MSVC)
    80     set_target_properties(evaluatorTestsShared PROPERTIES COMPILE_FLAGS "-Wall -g -std=c89 -pedantic -Werror -O2")
    81 endif()
    82 
    8372#Build addNumbers library
    8473add_library(addNumbers STATIC ${ADDNUMBERS_Sources})
    85 add_library(addNumbersShared SHARED ${ADDNUMBERS_Sources})
    8674if(NOT MSVC)
    8775    set_target_properties(addNumbers PROPERTIES COMPILE_FLAGS "-Wall -g -std=c89 -pedantic -Werror -O2")
    88     set_target_properties(addNumbersShared PROPERTIES COMPILE_FLAGS "-Wall -g -std=c89 -pedantic -Werror -O2")
    8976endif()
    9077
     
    119106
    120107#Install the libraries
    121 install(TARGETS evaluatorTestsShared DESTINATION "${TEST_LIBRARY_INSTALL_DIR}")
    122108install(TARGETS addNumbers DESTINATION "${TEST_LIBRARY_INSTALL_DIR}")
    123 install(TARGETS addNumbersShared DESTINATION "${TEST_LIBRARY_INSTALL_DIR}")
    124109install(TARGETS arrayFunctions DESTINATION "${TEST_LIBRARY_INSTALL_DIR}")
    125110install(TARGETS externalFunctionsC DESTINATION "${TEST_LIBRARY_INSTALL_DIR}")
  • trunk/Python/src/tests_jmodelica/files/Modelica/Resources/Include/addNumbers.h

    r13700 r13703  
    22#define ADDNUMBERS_H
    33
    4 #if defined _WIN32
    5     #define DllExport __declspec(dllexport)
    6 #else
    7     #define DllExport
    8 #endif
    9 
    10 DllExport double add(double a, double b);
    11 DllExport void add_output(double a, double b, double *c);
    12 DllExport double multiple_add(double a, double b, double c, double d, double e, double f, double g, double h, double i);
     4double add(double a, double b);
    135void multiplyAnArray(int* inputs, int* outputs, int size, int m);
    146
  • trunk/Python/src/tests_jmodelica/files/Modelica/Resources/src/addNumbers.c

    r13700 r13703  
    11#include "addNumbers.h"
    22
    3 DllExport double add(double a, double b)
     3double add(double a, double b)
    44{
    5   return a + b;
    6 }
    7 
    8 DllExport void add_output(double a, double b, double *c)
    9 {
    10   *c = a + b;
    11 }
    12 
    13 DllExport double multiple_add(double a, double b, double c, double d, double e, double f, double g, double h, double i)
    14 {
    15   return a+b+c+d+e+f+g+h+i;
     5  return a+b;
    166}
    177
  • trunk/Python/src/tests_jmodelica/general/test_extfunctions.py

    r13700 r13703  
    2222
    2323import nose
    24 import fnmatch
    2524
    2625from pymodelica import compile_fmu
     
    3433path_to_mofiles = os.path.join(get_files_path(), 'Modelica')
    3534
    36 class TestEvaluator:
    37     @classmethod
    38     def setUpClass(cls):
    39         """
    40         Sets up the test class.
    41         """
    42         cls.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
    43    
    44     @testattr(stddist_base = True)
    45     def test_builtin_substring(self):
    46         cpath = "ExtFunctionTests.Evaluator_Substring"
    47         fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
    48        
    49         nbr_of_evaluator_calls = 0
    50         with open("log.txt") as f:
    51             res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
    52             nbr_of_evaluator_calls = len(res)
    53        
    54         assert nbr_of_evaluator_calls == 4, "Wrong number of external function calls, check log."
    55        
    56         model = load_fmu(fmu_name)
    57        
    58         assert model.get("sub")[0] == "Y", model.get("sub")
    59         assert model.get("string2")[0] == "line", model.get("string2")
    60         assert model.get("len") == 16, model.get("len")
    61         assert model.get("start") == 4, model.get("start")
    62         assert not model.get("not_equal"), model.get("not_equal")
    63         assert model.get("equal"), model.get("equal")
    64    
    65     @testattr(stddist_base = True)
    66     def test_add(self):
    67         cpath = "ExtFunctionTests.Evaluator_Add"
    68         fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
    69        
    70         nbr_of_evaluator_calls = 0
    71         with open("log.txt") as f:
    72             res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
    73             nbr_of_evaluator_calls = len(res)
    74        
    75         assert nbr_of_evaluator_calls == 2, "Wrong number of external function calls, check log."
    76        
    77         model = load_fmu(fmu_name)
    78        
    79         assert model.get("c") == 3, model.get("c")
    80         assert model.get("d") == 3, model.get("d")
    81    
    82     @testattr(stddist_base = True)
    83     def test_unsupported_signature(self):
    84         cpath = "ExtFunctionTests.Evaluator_Multiple_Add"
    85         fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
    86        
    87         matches = 0
    88         with open("log.txt") as f:
    89             res = fnmatch.filter(f, "*is not supported. Disabling use of the evaluator*")
    90             matches = len(res)
    91        
    92         assert matches == 1, "Does not seem to disabling the evaluator"
    93 
    94     @testattr(stddist_base = True)
    95     def test_unknown_shared_library(self):
    96         cpath = "ExtFunctionTests.Evaluator_Unknown_Shared"
    97         try:
    98             fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log_unknown_shared.txt")
    99         except: #The compilation will fail, the interesting parts will though still be contained in the log file
    100             pass
    101        
    102         matches = 0
    103         with open("log_unknown_shared.txt") as f:
    104             res = fnmatch.filter(f, "Could not find a shared library containing*")
    105             matches = len(res)
    106        
    107         assert matches == 1, "Seems to have found an unknown shared library"
    108    
    109     @testattr(stddist_base = True)
    110     def test_double_return(self):
    111         cpath = "ExtFunctionTests.Evaluator_Double"
    112         fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
    113        
    114         nbr_of_evaluator_calls = 0
    115         with open("log.txt") as f:
    116             res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
    117             nbr_of_evaluator_calls = len(res)
    118        
    119         assert nbr_of_evaluator_calls == 2, "Wrong number of external function calls, check log."
    120        
    121         model = load_fmu(fmu_name)
    122        
    123         assert model.get("c") == 3.0, model.get("c")
    124         assert model.get("d") == 9.0, model.get("d")
    125    
    126     @testattr(stddist_base = True)
    127     def test_integer_return(self):
    128         cpath = "ExtFunctionTests.Evaluator_Integer"
    129         fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
    130        
    131         nbr_of_evaluator_calls = 0
    132         with open("log.txt") as f:
    133             res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
    134             nbr_of_evaluator_calls = len(res)
    135        
    136         assert nbr_of_evaluator_calls == 1, "Wrong number of external function calls, check log."
    137        
    138         model = load_fmu(fmu_name)
    139        
    140         assert model.get("c") == 3.0, model.get("c")
    141    
    142     @testattr(stddist_base = True)
    143     def test_record(self):
    144         cpath = "ExtFunctionTests.Evaluator_Record"
    145         fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
    146        
    147         nbr_of_evaluator_calls = 0
    148         with open("log.txt") as f:
    149             res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
    150             nbr_of_evaluator_calls = len(res)
    151        
    152         assert nbr_of_evaluator_calls == 1, "Wrong number of external function calls, check log."
    153        
    154         model = load_fmu(fmu_name)
    155        
    156         assert model.get("c.x0") == 1.0, model.get("c.x0")
    157         assert model.get("c.x1") == 2.0, model.get("c.x1")
    158         assert model.get("c.x2") == 3.0, model.get("c.x2")
    159         assert model.get("c.x3") == 3.0, model.get("c.x3")
    160         assert model.get("c.x4") == 4.0, model.get("c.x4")
    161         assert model.get("c.x5") == 5.0, model.get("c.x5")
    162         assert model.get("c.x6") == 6.0, model.get("c.x6")
    163         assert model.get("c.x7") == 7.0, model.get("c.x7")
    164         assert model.get("c.x8") == 8.0, model.get("c.x8")
    165         assert model.get("c.x9") == 9.0, model.get("c.x9")
    166         assert model.get("c.x10") == 10.0, model.get("c.x10")
    167    
    16835class TestExternalStatic:
    16936
  • trunk/RuntimeLibrary/CMakeLists.txt

    r13700 r13703  
    5555if(" ${CMAKE_C_FLAGS} " MATCHES " -m64 ")
    5656    set(RTLIB_LIB_DIR ${JMODELICA_INSTALL_DIR}/lib/RuntimeLibrary64)
    57     set(RTLIB_BIN_DIR ${JMODELICA_INSTALL_DIR}/bin64)
    5857else()
    5958    set(RTLIB_LIB_DIR ${JMODELICA_INSTALL_DIR}/lib/RuntimeLibrary)
    60     set(RTLIB_BIN_DIR ${JMODELICA_INSTALL_DIR}/bin)
    6159endif()
    6260install(CODE "file(MAKE_DIRECTORY $ENV{DESTDIR}${RTLIB_LIB_DIR})")
     
    9391add_subdirectory(src/modules)
    9492
    95 #Add evaluator
    96 include_directories(src/evaluator)
    97 add_subdirectory(src/evaluator)
    9893
    9994if(EXTRA_RUNTIME_MODULES)
  • trunk/RuntimeLibrary/Makefiles/Makefile.linux

    r13700 r13703  
    126126LIBS_FMUCS10 = -lfmi1_cs -lfmi1_me $(LIBS_FMU_STD) $(LIB_COMMON) -l:libsundials_cvode.a
    127127LIBS_FMU20   = -lfmi2 $(LIBS_FMU_STD) $(LIB_COMMON) -l:libsundials_cvode.a
    128 LIBS_CEVAL   = -ljmi_evaluator_util $(LIBS_FMU_STD)
     128LIBS_CEVAL   = $(LIBS_FMU_STD)
    129129
    130130# Include paths for compilation
  • trunk/RuntimeLibrary/Makefiles/Makefile.macosx

    r13700 r13703  
    125125LIBS_FMUCS10 = -lfmi1_cs -lfmi1_me $(LIBS_FMU_STD) $(LIB_COMMON) $(SUNDIALS_HOME)/lib/libsundials_cvode.a
    126126LIBS_FMU20   = -lfmi2 $(LIBS_FMU_STD) $(LIB_COMMON) $(SUNDIALS_HOME)/lib/libsundials_cvode.a
    127 LIBS_CEVAL   = -ljmi_evaluator_util $(LIBS_FMU_STD)
     127LIBS_CEVAL   = $(LIBS_FMU_STD)
    128128
    129129# Include paths for compilation
  • trunk/RuntimeLibrary/Makefiles/Makefile.windows

    r13700 r13703  
    160160LIBS_FMUCS10 = -lfmi1_cs -lfmi1_me $(LIBS_FMU_ALL)
    161161LIBS_FMU20   = -lfmi2              $(LIBS_FMU_ALL)
    162 LIBS_CEVAL = -ljmi_evaluator_util $(LIBS_FMU_STD)
     162LIBS_CEVAL = $(LIBS_FMU_STD)
    163163
    164164# Include paths for compilation
  • trunk/RuntimeLibrary/src

  • trunk/RuntimeLibrary/src/fmi1_cs/CMakeLists.txt

    r13700 r13703  
    3737
    3838#Install the libraries
    39 if (NOT MSVC)
    40     install(TARGETS fmi1_cs DESTINATION "${RTLIB_LIB_DIR}")
    41 endif()
     39install(TARGETS fmi1_cs DESTINATION "${RTLIB_LIB_DIR}")
    4240
    4341#Install header files
  • trunk/RuntimeLibrary/src/fmi1_me/CMakeLists.txt

    r13700 r13703  
    3939
    4040#Install the libraries
    41 if (NOT MSVC)
    42     install(TARGETS fmi1_me DESTINATION "${RTLIB_LIB_DIR}")
    43 endif()
     41install(TARGETS fmi1_me DESTINATION "${RTLIB_LIB_DIR}")
    4442
    4543#Install header files
  • trunk/RuntimeLibrary/src/fmi2/CMakeLists.txt

    r13700 r13703  
    4949
    5050#Install the libraries
    51 if (NOT MSVC)
    52     install(TARGETS fmi2 DESTINATION "${RTLIB_LIB_DIR}")
    53 endif()
     51install(TARGETS fmi2 DESTINATION "${RTLIB_LIB_DIR}")
    5452
    5553#Install header files
  • trunk/RuntimeLibrary/src/jmi/CMakeLists.txt

    r13700 r13703  
    202202
    203203    #Install the libraries
    204     if (NOT MSVC)
    205         install(TARGETS jmi
    206             DESTINATION "${RTLIB_LIB_DIR}")
    207     endif()
     204    install(TARGETS jmi
     205        DESTINATION "${RTLIB_LIB_DIR}")
    208206
    209207    #Install header files
     
    249247
    250248    #Install the libraries
    251     if (NOT MSVC)
    252         install(TARGETS ModelicaExternalC ModelicaStandardTables ModelicaIO ModelicaMatIO zlib
    253             DESTINATION "${RTLIB_LIB_DIR}")
    254     endif()
     249    install(TARGETS ModelicaExternalC ModelicaStandardTables ModelicaIO ModelicaMatIO zlib
     250        DESTINATION "${RTLIB_LIB_DIR}")
    255251
    256252    install(DIRECTORY "${MSLCSOURCES}/"
Note: See TracChangeset for help on using the changeset viewer.