Changeset 13703
- Timestamp:
- Oct 8, 2019 8:28:35 PM (2 months ago)
- Location:
- trunk
- Files:
-
- 11 deleted
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/dev-cw-evaluator removed
- Property svn:mergeinfo changed
-
trunk/CHANGELOG.txt
r13700 r13703 1 1 ================= Unreleased ================== 2 # Feature ; Minor ; Compiler; #58373 Added a pre-compiled evaluator used for evaluating external functions4 during the compilation (for performance). Activated by the option5 "external_constant_evaluation_dynamic"6 7 2 # Fixed ; Minor ; Compiler ; #5855 8 3 Nominal are now always positive in the FMI model description. -
trunk/Compiler/ModelicaCBackEnd/src/jastadd/CCodeGen/CCodeGenExternalCeval.jrag
r13700 r13703 248 248 Collection<ExternalArgument> res = new LinkedHashSet<>(); 249 249 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 } 259 252 for (FExp e : getArgs()) { 260 253 res.add(e.externalArgument()); … … 295 288 } 296 289 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;337 290 } 338 291 … … 394 347 } 395 348 } 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();411 349 } 412 350 -
trunk/Compiler/ModelicaCBackEnd/templates/ceval_external_template.c
r13700 r13703 14 14 */ 15 15 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> 28 23 29 24 $ECE_external_includes$ 30 25 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 31 33 /* Used record definitions */ 32 34 $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 */ 41 double 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 50 void JMCEVAL_printReal(double x) { 51 printf(JMCEVAL_realFormat, x); \ 52 printf("\n"); \ 53 fflush(stdout); \ 54 } 55 56 char* 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 69 void 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 */ 88 void 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 97 jmp_buf jmceval_try_location; 98 99 #define JMCEVAL_try() (setjmp(jmceval_try_location) == 0) 100 101 void jmi_throw() 102 { 103 longjmp(jmceval_try_location, 1); 104 } 105 106 jmi_dynamic_function_memory_t* dyn_fcn_mem = NULL; 107 108 jmi_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 113 void* 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 118 void JMCEVAL_setup() { 119 #ifdef _WIN32 120 /* Prevent win from translating \n to \r\n */ 121 _setmode(fileno(stdout), _O_BINARY); 122 #endif 123 } 124 125 int 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 140 void JMCEVAL_check(const char* str) { 141 printf("%s\n",str); 142 fflush(stdout); 143 } 144 145 void JMCEVAL_failed() { 146 JMCEVAL_check("ABORT"); 147 } 33 148 34 149 /* Main */ … … 80 195 JMCEVAL_failed(); 81 196 } 82 _jmi_dynamic_function_pool_destroy();197 jmi_dynamic_function_pool_destroy(dyn_fcn_mem); 83 198 JMCEVAL_check("END"); 84 199 return 0; -
trunk/Compiler/ModelicaCBackEnd/test/modelica/CCodeGenExternalCevalTests.mo
r13700 r13703 17 17 18 18 package CCodeGenExternalCevalTests 19 20 model ExtDynFcn121 type E = enumeration(A,B);22 function f23 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 equation42 (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 f51 void52 d,i,i,s,i,*d,*i,*i,*s,*i,53 ")})));54 end ExtDynFcn1;55 56 model ExtDynFcn257 type E = enumeration(A,B);58 function f59 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 equation77 (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 f86 void87 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 ExtDynFcn392 type E = enumeration(A,B);93 record R94 Real a1;95 Integer a2;96 Boolean a3;97 String a4;98 E a5;99 R2 r2;100 end R;101 record R2102 Real x;103 end R2;104 105 function f106 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 f120 void121 R[d,i,i,s,i,R[d,],],*R[d,i,i,s,i,R[d,],],122 ")})));123 end ExtDynFcn3;124 125 19 126 20 model Scalar … … 895 789 end ExtObj5; 896 790 897 model ExtDynObj1898 function use1899 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 918 791 model Dgelsx 919 792 function dgelsx -
trunk/Compiler/ModelicaCompiler/module.options
r13700 r13703 136 136 external objects during compilation.If less than 1, no processes will be kept 137 137 alive, i.e. this feature is turned off." 138 139 ********************************************************************************140 BOOLEAN external_constant_evaluation_dynamic compiler experimental false141 142 "If enabled, calls to external functions will be evaluated during compilation143 using a pre-compiled program (instead of generating and compiling one), if144 possible."145 138 146 139 ******************************************************************************** … … 465 458 466 459 ******************************************************************************** 460 -
trunk/Compiler/ModelicaCompiler/src/jastadd/ModelicaCompiler.jrag
r13700 r13703 1266 1266 /* Temporary fix to problems with long compilation times due to later evaluations */ 1267 1267 getExternalFunctionCache().tearDown(); 1268 options. external_constant_evaluation.setValue(0);1268 options.setIntegerOption("external_constant_evaluation", 0); 1269 1269 1270 1270 hookModelTransformed(fc); -
trunk/Compiler/ModelicaCompiler/src/java/org/jmodelica/util/ccompiler/CCompilerDelegator.java
r13700 r13703 351 351 }; 352 352 } 353 354 public abstract Set<String> expandCompilerSpecificLibraryPaths(ModelicaLogger log, AbstractOptionRegistry options,355 Set<String> extLibDirs, String platform);356 353 } 357 354 -
trunk/Compiler/ModelicaCompiler/src/java/org/jmodelica/util/ccompiler/GccCompilerDelegator.java
r13700 r13703 26 26 import java.util.Set; 27 27 28 import org.jmodelica.common.options.AbstractOptionRegistry;29 28 import org.jmodelica.util.EnvironmentUtils; 30 29 import org.jmodelica.util.exceptions.CcodeCompilationException; … … 107 106 vars.put("AR", new File(mingw_bin, "ar").getPath()); 108 107 } 109 }110 111 @Override112 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;115 108 } 116 109 -
trunk/Compiler/ModelicaFlatTree/src/jastadd/ConstantEvaluation/ConstantEvaluation.jrag
r13700 r13703 5079 5079 } 5080 5080 5081 public AlgorithmEvaluator createAlgorithmEvaluator( OptionRegistry options, Map<CommonVariableDecl, CValue> values) {5081 public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) { 5082 5082 return new AlgorithmEvaluator(externalEvaluationEnabled, options, values); 5083 5083 } 5084 5084 5085 public AlgorithmEvaluator createEmptyAlgorithmEvaluator( OptionRegistry options) {5085 public AlgorithmEvaluator createEmptyAlgorithmEvaluator(AbstractOptionRegistry options) { 5086 5086 return new AlgorithmEvaluator(true, options, Collections.<CommonVariableDecl, CValue>emptyMap()); 5087 5087 } … … 5149 5149 5150 5150 @Override 5151 public AlgorithmEvaluator createAlgorithmEvaluator( OptionRegistry options, Map<CommonVariableDecl, CValue> values) {5151 public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) { 5152 5152 return new PartialAlgorithmEvaluator(externalEvaluationEnabled(), options, values, this); 5153 5153 } … … 5183 5183 5184 5184 @Override 5185 public AlgorithmEvaluator createAlgorithmEvaluator( OptionRegistry options, Map<CommonVariableDecl, CValue> values) {5185 public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) { 5186 5186 if (this.values == null) { 5187 5187 this.values = values; … … 5277 5277 public class AlgorithmEvaluator extends VariableEvaluator { 5278 5278 5279 protected finalMap<CommonVariableDecl, CValue> values;5280 private finalOptionRegistry 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) { 5283 5283 super(evaluateExternalEnabled); 5284 5284 this.values = values; … … 5287 5287 5288 5288 public int externalEvaluation() { 5289 return externalEvaluationEnabled() ? options. external_constant_evaluation.getValue() : 0;5289 return externalEvaluationEnabled() ? options.getIntegerOption("external_constant_evaluation") : 0; 5290 5290 } 5291 5291 … … 5351 5351 protected ArrayList<IfEvaluation> ifStack; 5352 5352 5353 public PartialAlgorithmEvaluator(boolean evaluateExternalEnabled, OptionRegistry options,5353 public PartialAlgorithmEvaluator(boolean evaluateExternalEnabled, AbstractOptionRegistry options, 5354 5354 Map<CommonVariableDecl, CValue> values, PartialVariableEvaluator variableEvaluator) { 5355 5355 super(evaluateExternalEnabled, options, values); … … 5368 5368 5369 5369 @Override 5370 public AlgorithmEvaluator createAlgorithmEvaluator( OptionRegistry options, Map<CommonVariableDecl, CValue> values) {5370 public AlgorithmEvaluator createAlgorithmEvaluator(AbstractOptionRegistry options, Map<CommonVariableDecl, CValue> values) { 5371 5371 return variableEvaluator.createAlgorithmEvaluator(options, values); 5372 5372 } -
trunk/Compiler/ModelicaFlatTree/src/jastadd/ConstantEvaluation/ExternalConstantEvaluation.jrag
r13700 r13703 26 26 import java.util.TimerTask; 27 27 28 import org.jmodelica.common.evaluation.ExternalFunctionCompiler;29 28 import org.jmodelica.common.evaluation.ExternalFunction; 30 29 import org.jmodelica.common.evaluation.ExternalProcessCache; 31 30 import org.jmodelica.common.evaluation.ExternalProcessCacheImpl; 32 31 import org.jmodelica.common.evaluation.ExternalProcessMultiCache; 33 import org.jmodelica.common.evaluation.FailedExternalFunction;34 32 import org.jmodelica.common.evaluation.ProcessCommunicator; 35 33 … … 51 49 class ModelicaCompiler {} 52 50 53 ModelicaCompiler implements External FunctionCompiler<ExternalArgument, FExternalStmt>;51 ModelicaCompiler implements ExternalProcessMultiCache.Compiler<ExternalArgument, FExternalStmt>; 54 52 FExternalStmt implements ExternalProcessMultiCache.External<ExternalArgument>; 55 53 ExternalArgument extends ExternalProcessMultiCache.Variable<CValue,FType>; … … 91 89 * Check if this external function should be cached as a live process. 92 90 */ 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 } 99 94 100 95 /** … … 174 169 ExternalFunctionCache efc = root().getUtilInterface().getExternalFunctionCache(); 175 170 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); 179 173 } 180 174 return efc.getExternalProcessCache(getLibTopPackagePath()).getExternalFunction(this); … … 211 205 212 206 if (error != null) { 213 throw new ConstantEvaluationException(null, FailedExternalFunction.failedEvalMsg(getName(), error));207 throw new ConstantEvaluationException(null, ExternalProcessCacheImpl.failedEvalMsg(getName(), error)); 214 208 } 215 209 -
trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessCache.java
r13700 r13703 24 24 25 25 protected abstract void tearDown(); 26 27 public abstract ExternalFunction<K, V> failedEval(External<?> ext, String msg, boolean log); 26 28 27 29 -
trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessCacheImpl.java
r13700 r13703 3 3 import java.io.File; 4 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 5 6 import java.io.PrintStream; 6 7 import java.util.ArrayList; 7 8 import java.util.HashMap; 8 import java.util.HashSet;9 9 import java.util.LinkedHashSet; 10 10 import java.util.Map; 11 import java.util.Set; 12 11 12 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Compiler; 13 13 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.External; 14 14 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Type; … … 16 16 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Variable; 17 17 import org.jmodelica.util.EnvironmentUtils; 18 import org.jmodelica.util.SystemUtil;19 18 import org.jmodelica.util.ccompiler.CCompilerDelegator; 20 19 import org.jmodelica.util.exceptions.CcodeCompilationException; 21 20 import org.jmodelica.util.logging.ModelicaLogger; 21 import org.jmodelica.util.values.ConstantEvaluationException; 22 22 23 23 public class ExternalProcessCacheImpl<K extends Variable<V, T>, V extends Value, T extends Type<V>, E extends External<K>> extends ExternalProcessCache<K, V, T, E> { … … 26 26 * Maps external functions names to compiled executables. 27 27 */ 28 private finalMap<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>>(); 29 29 30 30 /** 31 31 * Keeps track of all living processes, least recently used first. 32 32 */ 33 private finalLinkedHashSet<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) { 38 38 this.mc = mc; 39 39 } … … 42 42 return mc.log(); 43 43 } 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 134 45 @Override 135 46 public ExternalFunction<K, V> getExternalFunction(E ext) { … … 137 48 if (ef == null) { 138 49 if (mc == null) { 139 return FailedExternalFunction.<K,V,T,E>failedEval(mc,ext, "Missing ModelicaCompiler", false);50 return failedEval(ext, "Missing ModelicaCompiler", false); 140 51 } 141 52 try { 142 53 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); 158 57 } 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); 171 59 } 172 60 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"); 174 63 } 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); 176 65 mc.log().debug(ef.getMessage()); 177 66 } 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); 179 68 mc.log().debug(ef.getMessage()); 180 69 e.printStackTrace(new PrintStream(mc.log().debugStream())); … … 206 95 } 207 96 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 } 208 396 } -
trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/common/evaluation/ExternalProcessMultiCache.java
r13700 r13703 2 2 3 3 import java.io.BufferedWriter; 4 import java.io.FileNotFoundException; 4 5 import java.io.IOException; 5 6 import java.util.LinkedHashMap; 6 7 import java.util.Map; 7 8 9 import org.jmodelica.common.LogContainer; 8 10 import org.jmodelica.common.options.AbstractOptionRegistry; 11 import org.jmodelica.util.ccompiler.CCompilerDelegator; 12 import org.jmodelica.util.exceptions.CcodeCompilationException; 9 13 10 14 public 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 } 11 21 12 22 public interface External<K> { 13 23 public String getName(); 14 24 15 public int processLimit(); 16 17 public boolean dynamicEvaluatorEnabled(); 25 public boolean shouldCacheProcess(); 18 26 19 27 public AbstractOptionRegistry myOptions(); … … 27 35 public Iterable<K> functionArgsToSerialize(); 28 36 29 public String functionArgsSerialized();30 31 public String functionReturnArgSerialized();32 33 37 public Iterable<K> varsToDeserialize(); 34 35 public String[] library();36 38 } 37 39 … … 54 56 private Map<String, ExternalProcessCache<K, V, T, E>> map = new LinkedHashMap<>(); 55 57 56 private ExternalFunctionCompiler<K, E> mc;58 private Compiler<K, E> mc; 57 59 58 public ExternalProcessMultiCache( ExternalFunctionCompiler<K, E> mc) {60 public ExternalProcessMultiCache(Compiler<K, E> mc) { 59 61 this.mc = mc; 60 62 } -
trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/util/SystemUtil.java
r13700 r13703 72 72 return isLinux() ? "" : ".exe"; 73 73 } 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 }84 74 85 75 /** -
trunk/Compiler/ModelicaFrontEnd/test/junit/org/jmodelica/test/common/ExternalProcessCacheTest.java
r13700 r13703 9 9 import java.io.IOException; 10 10 11 import org.jmodelica.common.evaluation.External FunctionCompiler;11 import org.jmodelica.common.evaluation.ExternalProcessCache; 12 12 import org.jmodelica.common.evaluation.ExternalFunction; 13 import org.jmodelica.common.evaluation.ExternalProcessCache;14 13 import org.jmodelica.common.evaluation.ExternalProcessMultiCache; 14 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Variable; 15 import org.jmodelica.common.options.AbstractOptionRegistry; 16 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Value; 17 import org.jmodelica.common.evaluation.ExternalProcessMultiCache.Type; 15 18 import 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;19 19 import org.jmodelica.common.evaluation.ProcessCommunicator; 20 import org.jmodelica.common.options.AbstractOptionRegistry;21 20 import org.jmodelica.util.ccompiler.CCompilerDelegator; 22 21 import org.jmodelica.util.exceptions.CcodeCompilationException; … … 75 74 class ExternalProcessCacheMock<K extends Variable<V,T>, V extends Value, T extends Type<V>, E extends External<K>> extends ExternalProcessMultiCache<K,V,T,E> { 76 75 77 public ExternalProcessCacheMock( ExternalFunctionCompiler<K,E> mc) {76 public ExternalProcessCacheMock(Compiler<K,E> mc) { 78 77 super(mc); 79 78 } … … 109 108 } 110 109 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> { 114 119 115 120 @Override … … 184 189 185 190 @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 193 193 return false; 194 194 } … … 223 223 return null; 224 224 } 225 226 @Override227 public String functionArgsSerialized() {228 // TODO Auto-generated method stub229 return null;230 }231 232 @Override233 public String functionReturnArgSerialized() {234 // TODO Auto-generated method stub235 return null;236 }237 225 238 226 @Override … … 241 229 return null; 242 230 } 243 244 @Override245 public String[] library() {246 // TODO Auto-generated method stub247 return null;248 }249 231 250 232 } -
trunk/Python/src/tests_jmodelica/files/Modelica/ExtFunctionTests.mo
r13700 r13703 1 1 package ExtFunctionTests 2 3 model Evaluator_Double4 function d_i5 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_idd13 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_Integer28 function i_ii29 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_Record41 record R42 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_Substring69 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_Add80 function add181 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 add290 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_Add105 function add106 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_Shared127 function unknown_function128 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;135 2 136 3 model ExtFunctionTest1 -
trunk/Python/src/tests_jmodelica/files/Modelica/Resources/CMakeLists.txt
r13700 r13703 38 38 include_directories(${TOP_SRC}/RuntimeLibrary/src/jmi) 39 39 40 set(EVALUATORTESTS_Sources41 src/evaluatorTests.c42 Include/evaluatorTests.h43 )44 45 40 set(ADDNUMBERS_Sources 46 41 src/addNumbers.c … … 75 70 endif() 76 71 77 #Build evaluatorTests library78 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 83 72 #Build addNumbers library 84 73 add_library(addNumbers STATIC ${ADDNUMBERS_Sources}) 85 add_library(addNumbersShared SHARED ${ADDNUMBERS_Sources})86 74 if(NOT MSVC) 87 75 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")89 76 endif() 90 77 … … 119 106 120 107 #Install the libraries 121 install(TARGETS evaluatorTestsShared DESTINATION "${TEST_LIBRARY_INSTALL_DIR}")122 108 install(TARGETS addNumbers DESTINATION "${TEST_LIBRARY_INSTALL_DIR}") 123 install(TARGETS addNumbersShared DESTINATION "${TEST_LIBRARY_INSTALL_DIR}")124 109 install(TARGETS arrayFunctions DESTINATION "${TEST_LIBRARY_INSTALL_DIR}") 125 110 install(TARGETS externalFunctionsC DESTINATION "${TEST_LIBRARY_INSTALL_DIR}") -
trunk/Python/src/tests_jmodelica/files/Modelica/Resources/Include/addNumbers.h
r13700 r13703 2 2 #define ADDNUMBERS_H 3 3 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); 4 double add(double a, double b); 13 5 void multiplyAnArray(int* inputs, int* outputs, int size, int m); 14 6 -
trunk/Python/src/tests_jmodelica/files/Modelica/Resources/src/addNumbers.c
r13700 r13703 1 1 #include "addNumbers.h" 2 2 3 DllExportdouble add(double a, double b)3 double add(double a, double b) 4 4 { 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; 16 6 } 17 7 -
trunk/Python/src/tests_jmodelica/general/test_extfunctions.py
r13700 r13703 22 22 23 23 import nose 24 import fnmatch25 24 26 25 from pymodelica import compile_fmu … … 34 33 path_to_mofiles = os.path.join(get_files_path(), 'Modelica') 35 34 36 class TestEvaluator:37 @classmethod38 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 = 050 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 = 071 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 = 088 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 file100 pass101 102 matches = 0103 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 = 0115 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 = 0132 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 = 0148 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 168 35 class TestExternalStatic: 169 36 -
trunk/RuntimeLibrary/CMakeLists.txt
r13700 r13703 55 55 if(" ${CMAKE_C_FLAGS} " MATCHES " -m64 ") 56 56 set(RTLIB_LIB_DIR ${JMODELICA_INSTALL_DIR}/lib/RuntimeLibrary64) 57 set(RTLIB_BIN_DIR ${JMODELICA_INSTALL_DIR}/bin64)58 57 else() 59 58 set(RTLIB_LIB_DIR ${JMODELICA_INSTALL_DIR}/lib/RuntimeLibrary) 60 set(RTLIB_BIN_DIR ${JMODELICA_INSTALL_DIR}/bin)61 59 endif() 62 60 install(CODE "file(MAKE_DIRECTORY $ENV{DESTDIR}${RTLIB_LIB_DIR})") … … 93 91 add_subdirectory(src/modules) 94 92 95 #Add evaluator96 include_directories(src/evaluator)97 add_subdirectory(src/evaluator)98 93 99 94 if(EXTRA_RUNTIME_MODULES) -
trunk/RuntimeLibrary/Makefiles/Makefile.linux
r13700 r13703 126 126 LIBS_FMUCS10 = -lfmi1_cs -lfmi1_me $(LIBS_FMU_STD) $(LIB_COMMON) -l:libsundials_cvode.a 127 127 LIBS_FMU20 = -lfmi2 $(LIBS_FMU_STD) $(LIB_COMMON) -l:libsundials_cvode.a 128 LIBS_CEVAL = -ljmi_evaluator_util$(LIBS_FMU_STD)128 LIBS_CEVAL = $(LIBS_FMU_STD) 129 129 130 130 # Include paths for compilation -
trunk/RuntimeLibrary/Makefiles/Makefile.macosx
r13700 r13703 125 125 LIBS_FMUCS10 = -lfmi1_cs -lfmi1_me $(LIBS_FMU_STD) $(LIB_COMMON) $(SUNDIALS_HOME)/lib/libsundials_cvode.a 126 126 LIBS_FMU20 = -lfmi2 $(LIBS_FMU_STD) $(LIB_COMMON) $(SUNDIALS_HOME)/lib/libsundials_cvode.a 127 LIBS_CEVAL = -ljmi_evaluator_util$(LIBS_FMU_STD)127 LIBS_CEVAL = $(LIBS_FMU_STD) 128 128 129 129 # Include paths for compilation -
trunk/RuntimeLibrary/Makefiles/Makefile.windows
r13700 r13703 160 160 LIBS_FMUCS10 = -lfmi1_cs -lfmi1_me $(LIBS_FMU_ALL) 161 161 LIBS_FMU20 = -lfmi2 $(LIBS_FMU_ALL) 162 LIBS_CEVAL = -ljmi_evaluator_util$(LIBS_FMU_STD)162 LIBS_CEVAL = $(LIBS_FMU_STD) 163 163 164 164 # Include paths for compilation -
trunk/RuntimeLibrary/src
- Property svn:mergeinfo changed
/branches/dev-cw-evaluator/RuntimeLibrary/src removed
- Property svn:mergeinfo changed
-
trunk/RuntimeLibrary/src/fmi1_cs/CMakeLists.txt
r13700 r13703 37 37 38 38 #Install the libraries 39 if (NOT MSVC) 40 install(TARGETS fmi1_cs DESTINATION "${RTLIB_LIB_DIR}") 41 endif() 39 install(TARGETS fmi1_cs DESTINATION "${RTLIB_LIB_DIR}") 42 40 43 41 #Install header files -
trunk/RuntimeLibrary/src/fmi1_me/CMakeLists.txt
r13700 r13703 39 39 40 40 #Install the libraries 41 if (NOT MSVC) 42 install(TARGETS fmi1_me DESTINATION "${RTLIB_LIB_DIR}") 43 endif() 41 install(TARGETS fmi1_me DESTINATION "${RTLIB_LIB_DIR}") 44 42 45 43 #Install header files -
trunk/RuntimeLibrary/src/fmi2/CMakeLists.txt
r13700 r13703 49 49 50 50 #Install the libraries 51 if (NOT MSVC) 52 install(TARGETS fmi2 DESTINATION "${RTLIB_LIB_DIR}") 53 endif() 51 install(TARGETS fmi2 DESTINATION "${RTLIB_LIB_DIR}") 54 52 55 53 #Install header files -
trunk/RuntimeLibrary/src/jmi/CMakeLists.txt
r13700 r13703 202 202 203 203 #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}") 208 206 209 207 #Install header files … … 249 247 250 248 #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}") 255 251 256 252 install(DIRECTORY "${MSLCSOURCES}/"
Note: See TracChangeset
for help on using the changeset viewer.