CppGenerator.xtend 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. package be.uantwerpen.ansymo.semanticadaptation.cg.cpp.generation
  2. import be.uantwerpen.ansymo.semanticadaptation.generator.SemanticAdaptationGenerator
  3. import org.eclipse.xtext.generator.IFileSystemAccess2
  4. import org.eclipse.xtext.generator.IGeneratorContext
  5. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
  6. import org.eclipse.emf.ecore.resource.Resource
  7. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Adaptation
  8. import java.util.ArrayList
  9. import java.util.LinkedHashMap
  10. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.MappedScalarVariable
  11. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMU
  12. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.exceptions.IncorrectAmountOfElementsException
  13. import java.io.File
  14. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.SAScalarVariable
  15. import org.eclipse.emf.common.util.EList
  16. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Port
  17. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.SVCausality
  18. import java.util.Collection
  19. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InOutRules
  20. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InRulesBlock
  21. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.InOutRulesBlockResult
  22. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.OutRulesBlock
  23. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.GlobalInOutVariable
  24. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.ControlRuleBlock
  25. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.RulesBlockResult
  26. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.ScalarVariable
  27. import java.util.List
  28. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.SVType
  29. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.ParamDeclarations
  30. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.InnerFMUData
  31. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.IORuleType
  32. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.RuleType
  33. import org.eclipse.emf.ecore.EObject
  34. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Declaration
  35. class CppGenerator extends SemanticAdaptationGenerator {
  36. private var IFileSystemAccess2 fsa;
  37. private List<File> resourcePaths = newArrayList();
  38. override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
  39. this.fsa = fsa;
  40. for (SemanticAdaptation type : resource.allContents.toIterable.filter(SemanticAdaptation)) {
  41. type.compile;
  42. }
  43. }
  44. // TODO: Verify adaptation.name is not a C++ keyword
  45. def void compile(SemanticAdaptation adaptation) {
  46. for (Adaptation adap : adaptation.elements.filter(Adaptation)) {
  47. // Value used for scoping variables in the .sa file
  48. val adapInteralRefName = adap.name;
  49. // The CPP class name
  50. val adapClassName = adap.name.toFirstUpper;
  51. // This is the external name used in the model description file for the semantic adaptation FMU.
  52. val adapExternalName = adap.type.name;
  53. // List of FMUs with a pairing between its name and its type.name.
  54. var ArrayList<InnerFMUData> innerFMUsData = newArrayList();
  55. val innerFmus = adap.inner.eAllContents.toList.filter(InnerFMU);
  56. if (innerFmus.isEmpty) {
  57. throw new IncorrectAmountOfElementsException("The adaptation does not contain any InnerFMUs.")
  58. }
  59. /*
  60. * This map will contain scalar variables from the FMUs defined in InnerFMU.
  61. * The structure is fmuName -> (SVName -> mappedSV) where SVName = mappedSV.name for easy lookup.
  62. * The mappedSV contains the original scalar variable and extra data such as define name.
  63. */
  64. var LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mappedScalarVariables = newLinkedHashMap();
  65. /*
  66. * Loading the FMU defined in InnerFMU, the related model description file and its scalar variables.
  67. */
  68. // TODO: Add support for multiple inner fmus. Only partially supported
  69. var ModelDescription md;
  70. for (fmu : adap.inner.eAllContents.toList.filter(InnerFMU)) {
  71. val fmuFile = new File(fmu.path.replace('\"', ''));
  72. this.resourcePaths.add(fmuFile);
  73. md = new ModelDescription(fmu.name, fmu.type.name, fmuFile);
  74. innerFMUsData.add(new InnerFMUData(fmu.name, fmu.type.name, md.guid));
  75. // fmus.add(fmu.name -> fmu.type.name);
  76. val LinkedHashMap<String, MappedScalarVariable> mSV = newLinkedHashMap();
  77. for (sv : md.sv.values) {
  78. var mappedSv = new MappedScalarVariable(sv);
  79. mappedSv.define = (mappedSv.mappedSv.owner + mappedSv.mappedSv.name).toUpperCase;
  80. mSV.put(mappedSv.mappedSv.name, mappedSv);
  81. }
  82. mappedScalarVariables.put(fmu.name, mSV);
  83. }
  84. // C++ Defines for accessing FMU scalar variables.
  85. val String fmusDefines = calcDefines(mappedScalarVariables);
  86. // Compile Params
  87. var LinkedHashMap<String, GlobalInOutVariable> params = newLinkedHashMap;
  88. val String paramsConstructorSource = compileParams(params, adap.params);
  89. /*
  90. * This map contains all the ScalarVariables for the semantic adaptation.
  91. * Some of them are not populated yet, but they will be during the compilation of the in and out rule blocks.
  92. */
  93. var LinkedHashMap<String, SAScalarVariable> SASVs = calcSASVsFromInportsOutports(adapInteralRefName,
  94. adap.inports, adap.outports, mappedScalarVariables)
  95. //val outPortsWithSrcDep = adap.outports.filter[x|x.sourcedependency !== null];
  96. // C++ defines for accessing semantic adaptation scalar variables
  97. val String SADefines = calcSADefines(SASVs.values);
  98. // The three rule blocks
  99. val inRuleBlock = adap.in;
  100. val outRuleBlock = adap.out;
  101. val crtlRuleBlock = adap.control;
  102. // Get the control vars, in vars, and out vars
  103. val inVars = if(inRuleBlock !== null) compileRuleBlockVars(inRuleBlock.globalInVars, params);
  104. val outVars = if(outRuleBlock !== null) compileRuleBlockVars(outRuleBlock.globalOutVars, params);
  105. val crtlVars = if(crtlRuleBlock !== null) compileRuleBlockVars(crtlRuleBlock.globalCtrlVars, params);
  106. //
  107. // Compile the in rules
  108. val inRuleResult = compileInOutRuleBlocks(IORuleType.Input, adaptation.eAllContents.toIterable.filter(
  109. InRulesBlock).map[x|x as InOutRules], adapClassName, adapInteralRefName, mappedScalarVariables, SASVs,
  110. params, inVars.value, outVars.value, crtlVars.value);
  111. // Compile the out rules
  112. val outRuleResult = compileInOutRuleBlocks(IORuleType.Output, adaptation.eAllContents.toIterable.filter(
  113. OutRulesBlock).map[x|x as InOutRules], adapClassName, adapInteralRefName, mappedScalarVariables, SASVs,
  114. params, inVars.value, outVars.value, crtlVars.value);
  115. // Compile the Control Rules. These might use the out vars, so pass these along.
  116. val crtlRuleResult = compileControlRuleBlock(adaptation.eAllContents.toIterable.filter(ControlRuleBlock),
  117. adapClassName, adapInteralRefName, mappedScalarVariables, SASVs, params, inVars.value, outVars.value,
  118. crtlVars.value);
  119. /*
  120. * Compile the constructor, destructor and initialize functions
  121. */
  122. val String deAndConstructorAndInitializeSource = compileDeAndConstructorAndInitialize(
  123. adapClassName,
  124. innerFMUsData,
  125. md.guid,
  126. paramsConstructorSource,
  127. inVars.key,
  128. outVars.key,
  129. crtlVars.key
  130. );
  131. /*
  132. * Compile getRuleThis function
  133. */
  134. val String getRuleThisSource = compileGetRuleThis(adapClassName);
  135. /*
  136. * The in and out rules have populated the semantic adaptation scalar variables we can generate the getFmiValue* and setFmiValue functions.
  137. */
  138. val String getFuncsSource = compileGetFmiValueFunctions(adapClassName, SASVs);
  139. val String setFuncsSource = compileSetFmiValueFunctions(adapClassName, SASVs);
  140. // Compile the source file
  141. val String sourceInclude = '''#include "«adapClassName».h"''';
  142. val sourceFile = compileSource(
  143. sourceInclude,
  144. deAndConstructorAndInitializeSource,
  145. getRuleThisSource,
  146. getFuncsSource,
  147. setFuncsSource,
  148. inRuleResult.generatedCpp,
  149. outRuleResult.generatedCpp,
  150. crtlRuleResult.generatedCpp
  151. );
  152. fsa.generateFile(adapClassName + ".cpp", sourceFile);
  153. // Merge the global variables for use in compiling the header file.
  154. // TODO: Check for duplicates
  155. var LinkedHashMap<String, GlobalInOutVariable> allGVars = newLinkedHashMap();
  156. allGVars.putAll(params);
  157. allGVars.putAll(inVars.value);
  158. allGVars.putAll(outVars.value);
  159. allGVars.putAll(crtlVars.value);
  160. // Compile the header file
  161. val headerFile = compileHeader(
  162. adapClassName,
  163. fmusDefines,
  164. SADefines,
  165. inRuleResult.functionSignatures,
  166. outRuleResult.functionSignatures,
  167. crtlRuleResult.functionSignatures,
  168. allGVars,
  169. innerFMUsData,
  170. SASVs.values.map[CalcSVar()].toList
  171. );
  172. fsa.generateFile(adapClassName + ".h", headerFile);
  173. // Compile the model description file
  174. val modelDescCreator = new ModelDescriptionCreator(adapExternalName);
  175. val modelDescription = modelDescCreator.generateModelDescription(SASVs.values);
  176. fsa.generateFile("modelDescription.xml", modelDescription);
  177. // Compile the fmu.cpp file
  178. val fmuCppFile = StaticGenerators.GenFmuCppFile(adapClassName);
  179. fsa.generateFile("Fmu.cpp", fmuCppFile);
  180. }
  181. }
  182. def String compileParams(LinkedHashMap<String, GlobalInOutVariable> gVars, EList<ParamDeclarations> params) {
  183. val paramsConditionSwitch = new ParamConditionSwitch(gVars);
  184. var String paramsConstructorSource = "";
  185. for (paramDecl : params) {
  186. val doSwitchRes = paramsConditionSwitch.doSwitch(paramDecl);
  187. paramsConstructorSource += doSwitchRes.code;
  188. }
  189. return paramsConstructorSource;
  190. }
  191. def calcSADefines(Collection<SAScalarVariable> variables) {
  192. var ArrayList<String> defines = newArrayList();
  193. for (SASV : variables) {
  194. defines.add("#define " + SASV.defineName + " " + SASV.valueReference);
  195. }
  196. return defines.join("\n");
  197. }
  198. def calcDefines(LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> map) {
  199. var ArrayList<String> defines = newArrayList();
  200. for (fmuEntries : map.entrySet) {
  201. for (MappedScalarVariable mSV : fmuEntries.value.values) {
  202. defines.add("#define " + mSV.define + " " + mSV.valueReference);
  203. }
  204. }
  205. return defines.join("\n");
  206. }
  207. // Compiles the final source file
  208. def String compileSource(String include, String constructor, String getRuleThis, String getFunctions,
  209. String setFunctions, String inFunctions, String outFunctions, String controlFunction) {
  210. return '''
  211. «include»
  212. namespace adaptation
  213. {
  214. «constructor»
  215. «getRuleThis»
  216. «getFunctions»
  217. «setFunctions»
  218. «inFunctions»
  219. «controlFunction»
  220. «outFunctions»
  221. }
  222. '''
  223. }
  224. /*
  225. * Compiles the header file split into two: The first part contains the includes and using namespace definitions and start the ,
  226. * the second part contains the class
  227. */
  228. def String compileHeader(String adapClassName, String fmusDefines, String SADefines,
  229. List<String> inRulesFuncSig, List<String> outRulesFuncSig, List<String> crtlRulesFuncSig,
  230. LinkedHashMap<String, GlobalInOutVariable> globalVariables, ArrayList<InnerFMUData> fmus,
  231. Collection<ScalarVariable> sVars) {
  232. return '''
  233. #ifndef SRC_«adapClassName.toUpperCase»_H
  234. #define SRC_«adapClassName.toUpperCase»_H
  235. #include "SemanticAdaptation.h"
  236. #include <memory>
  237. #include "Fmu.h"
  238. using namespace std;
  239. using namespace fmi2;
  240. namespace adaptation
  241. {
  242. «fmusDefines»
  243. «SADefines»
  244. class «adapClassName» : public SemanticAdaptation<«adapClassName»>, public enable_shared_from_this<«adapClassName»>
  245. {
  246. public:
  247. «adapClassName»(shared_ptr<std::string> fmiInstanceName, shared_ptr<string> resourceLocation, const fmi2CallbackFunctions* functions);
  248. void initialize();
  249. virtual ~«adapClassName»();
  250. void setFmiValue(fmi2ValueReference id, int value);
  251. void setFmiValue(fmi2ValueReference id, bool value);
  252. void setFmiValue(fmi2ValueReference id, double value);
  253. void setFmiValue(fmi2ValueReference id, string value);
  254. int getFmiValueInteger(fmi2ValueReference id);
  255. bool getFmiValueBoolean(fmi2ValueReference id);
  256. double getFmiValueReal(fmi2ValueReference id);
  257. string getFmiValueString(fmi2ValueReference id);
  258. private:
  259. «adapClassName»* getRuleThis();
  260. /*in rules*/
  261. «inRulesFuncSig.map[x | x+";"].join("\n")»
  262. /*out rules*/
  263. «outRulesFuncSig.map[x | x+";"].join("\n")»
  264. «crtlRulesFuncSig.map[x | x+";"].join("\n")»
  265. «FOR fmu : fmus»
  266. shared_ptr<FmuComponent> «fmu.name»;
  267. «ENDFOR»
  268. «FOR sv : sVars»
  269. «Conversions.fmiTypeToCppType(sv.type)» «sv.name»;
  270. «IF sv.causality == SVCausality.input»
  271. bool isSet«sv.name»;
  272. «ENDIF»
  273. «ENDFOR»
  274. «FOR v : globalVariables.entrySet»
  275. «Conversions.fmiTypeToCppType(v.value.type)» «v.key»;
  276. «ENDFOR»
  277. };
  278. }
  279. #endif
  280. ''';
  281. }
  282. /*
  283. * Compiles the source file constructor, destructor and the initialize function
  284. */
  285. def String compileDeAndConstructorAndInitialize(String adapClassName, ArrayList<InnerFMUData> fmus, String guid,
  286. String paramsCons, String inCons, String outCons, String crtlCons) {
  287. var ArrayList<String> initialisations = newArrayList();
  288. for (fmu : fmus) {
  289. initialisations.add('''
  290. auto path = make_shared<string>(*resourceLocation);
  291. path->append(string("«fmu.typeName».fmu"));
  292. auto «fmu.name»Fmu = make_shared<fmi2::Fmu>(*path);
  293. «fmu.name»Fmu->initialize();
  294. this->«fmu.name» = «fmu.name»Fmu->instantiate("«fmu.name»",fmi2CoSimulation, "«fmu.guid»", true, true, shared_from_this());
  295. if(this->«fmu.name»->component == NULL)
  296. this->lastErrorState = fmi2Fatal;
  297. this->instances->push_back(this->«fmu.name»);
  298. ''');
  299. }
  300. return '''
  301. «adapClassName»::«adapClassName»(shared_ptr<std::string> fmiInstanceName,shared_ptr<string> resourceLocation, const fmi2CallbackFunctions* functions) :
  302. SemanticAdaptation(fmiInstanceName, resourceLocation, createInputRules(),createOutputRules(), functions)
  303. {
  304. «paramsCons»
  305. «inCons»
  306. «outCons»
  307. «crtlCons»
  308. }
  309. void «adapClassName»::initialize()
  310. {
  311. «initialisations.join("\r\n")»
  312. ««« «FOR fmu : fmus»
  313. ««« auto path = make_shared<string>(*resourceLocation);
  314. ««« path->append(string("«fmu.value».fmu"));
  315. ««« auto «fmu.key»Fmu = make_shared<fmi2::Fmu>(*path);
  316. ««« «fmu.key»Fmu->initialize();
  317. ««« this->«fmu.key» = «fmu.key»Fmu->instantiate("«fmu.key»",fmi2CoSimulation, "«guid»", true, true, shared_from_this());
  318. «««
  319. ««« if(this->«fmu.key»->component == NULL)
  320. ««« this->lastErrorState = fmi2Fatal;
  321. ««« this->instances->push_back(this->«fmu.key»);
  322. ««« «ENDFOR»
  323. }
  324. «adapClassName»::~«adapClassName»()
  325. {
  326. }
  327. ''';
  328. }
  329. /*
  330. * Compiles the source file function getRuleThis
  331. */
  332. def String compileGetRuleThis(String adaptationName) {
  333. return '''
  334. «adaptationName»* «adaptationName»::getRuleThis()
  335. {
  336. return this;
  337. }
  338. '''
  339. }
  340. /*
  341. * Compiles the source file functions getFmiValue<double, int, string, bool>
  342. */
  343. def String compileGetFmiValueFunctions(String adaptationName,
  344. LinkedHashMap<String, SAScalarVariable> variables) {
  345. var ArrayList<String> cpp = newArrayList();
  346. var List<ScalarVariable> convertedSASVs = variables.values.map[CalcSVar()].toList;
  347. var convertedSASVsOrdered = convertedSASVs.filter[causality === SVCausality.output].groupBy[type];
  348. for (SVType type : SVType.values) {
  349. val functionSignature = '''«Conversions.fmiTypeToCppType(type)» «adaptationName»::getFmiValue«type.toString»(fmi2ValueReference id)''';
  350. val functionReturn = '''return «Conversions.fmiTypeToCppDefaultValue(type)»''';
  351. if (convertedSASVsOrdered.containsKey(type)) {
  352. cpp.add(
  353. '''
  354. «functionSignature»
  355. {
  356. switch (id)
  357. {
  358. «FOR svInner : convertedSASVsOrdered.get(type)»
  359. case «variables.get(svInner.name).defineName»:
  360. {
  361. return this->«svInner.name»;
  362. }
  363. «ENDFOR»
  364. default:
  365. {
  366. «functionReturn»;
  367. }
  368. }
  369. }
  370. '''
  371. );
  372. } else {
  373. cpp.add(
  374. '''
  375. «functionSignature»
  376. {
  377. «functionReturn»;
  378. }
  379. '''
  380. );
  381. }
  382. }
  383. return cpp.join("\n");
  384. }
  385. /*
  386. * Compiles the source file functions setFmiValue<double, int, string, bool>*
  387. */
  388. def String compileSetFmiValueFunctions(String adapClassName,
  389. LinkedHashMap<String, SAScalarVariable> variables) {
  390. var ArrayList<String> cpp = newArrayList();
  391. var List<ScalarVariable> convertedSASVs = variables.values.map[CalcSVar()].filter [
  392. causality === SVCausality.input
  393. ].toList;
  394. var convertedSASVsOrdered = convertedSASVs.groupBy[type];
  395. for (SVType type : SVType.values) {
  396. cpp.add(
  397. '''
  398. void «adapClassName»::setFmiValue(fmi2ValueReference id, «Conversions.fmiTypeToCppType(type)» value)
  399. {
  400. «IF convertedSASVsOrdered.containsKey(type)»
  401. switch (id)
  402. {
  403. «FOR svInner : convertedSASVsOrdered.get(type)»
  404. case «variables.get(svInner.name).defineName»:
  405. {
  406. this->«svInner.name» = value;
  407. this->isSet«svInner.name» = true;
  408. break;
  409. }
  410. «ENDFOR»
  411. default:
  412. {
  413. }
  414. }
  415. «ENDIF»
  416. }
  417. '''
  418. );
  419. }
  420. return cpp.join("\n");
  421. }
  422. /*
  423. * Compiles the source file function executeInternalControlFlow.
  424. * Calculates necessary information on function signatures necessary for generation of the header file.
  425. */
  426. def InOutRulesBlockResult compileControlRuleBlock(Iterable<ControlRuleBlock> crtlRuleBlocks,
  427. String adaptationClassName, String adaptationName,
  428. LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mSVars,
  429. LinkedHashMap<String, SAScalarVariable> SASVs, LinkedHashMap<String, GlobalInOutVariable> params,
  430. LinkedHashMap<String, GlobalInOutVariable> inVars, LinkedHashMap<String, GlobalInOutVariable> outVars,
  431. LinkedHashMap<String, GlobalInOutVariable> crtlVars) {
  432. var cpp = "";
  433. val visitor = new ControlConditionSwitch(adaptationClassName, adaptationName, mSVars, SASVs, params, inVars,
  434. outVars, crtlVars);
  435. for (crtlRule : crtlRuleBlocks) {
  436. cpp += visitor.doSwitch(crtlRule).code;
  437. }
  438. return new InOutRulesBlockResult(cpp, visitor.functionSignatures);
  439. }
  440. def String SplitAtSpaceAndRemoveFirst(String content) {
  441. content.substring(content.indexOf(" ") + 1, content.length);
  442. }
  443. def String removeEmptyArgumentParenthesis(String content) {
  444. return content.substring(0, content.length - 2);
  445. }
  446. /*
  447. * Calculates necessary information on global in/out variables
  448. */
  449. def Pair<String, LinkedHashMap<String, GlobalInOutVariable>> compileRuleBlockVars(
  450. EList<Declaration> gVars,
  451. LinkedHashMap<String, GlobalInOutVariable> params) {
  452. val visitor = new RulesConditionSwitch("", "", "", null, null, params, null,
  453. null, null)
  454. return visitor.getGlobalVars(gVars);
  455. }
  456. /*
  457. * Compiles the source file functions <in/out>_rule_<condition, body, flush>.
  458. * Calculates necessary information on function signatures necessary for generation of the header file.
  459. */
  460. def InOutRulesBlockResult compileInOutRuleBlocks(IORuleType ioType,
  461. Iterable<InOutRules> rulesBlocks,
  462. String adaptationClassName,
  463. String adaptationName,
  464. LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mSVars,
  465. LinkedHashMap<String, SAScalarVariable> SASVs,
  466. LinkedHashMap<String, GlobalInOutVariable> params,
  467. LinkedHashMap<String, GlobalInOutVariable> inVars,
  468. LinkedHashMap<String, GlobalInOutVariable> outVars,
  469. LinkedHashMap<String, GlobalInOutVariable> crtlVars) {
  470. val visitor = if (ioType == IORuleType.Input)
  471. new InRulesConditionSwitch(adaptationClassName, adaptationName, mSVars, SASVs, params, inVars,
  472. outVars, crtlVars)
  473. else
  474. new OutRulesConditionSwitch(adaptationClassName, adaptationName, mSVars, SASVs, params, inVars,
  475. outVars, crtlVars);
  476. //
  477. val functionName = "create" + ioType + "Rules()";
  478. var String cpp = "";
  479. val ruleBlock = rulesBlocks.head;
  480. if (ruleBlock !== null) {
  481. cpp += visitor.doSwitch(ruleBlock).code;
  482. if (!visitor.functionSignatures.empty) {
  483. var ArrayList<String> createRulesFunction = newArrayList();
  484. for (var int i = 0; i < (visitor.functionSignatures.length); i += 3) {
  485. createRulesFunction.add(
  486. '''
  487. list->push_back(
  488. (Rule<«adaptationClassName»>){
  489. &«adaptationClassName»::«visitor.functionSignatures.get(i).SplitAtSpaceAndRemoveFirst.removeEmptyArgumentParenthesis»,
  490. &«adaptationClassName»::«visitor.functionSignatures.get(i+1).SplitAtSpaceAndRemoveFirst.removeEmptyArgumentParenthesis»,
  491. &«adaptationClassName»::«visitor.functionSignatures.get(i+2).SplitAtSpaceAndRemoveFirst.removeEmptyArgumentParenthesis»
  492. });
  493. ''');
  494. }
  495. val functionPrefix = '''shared_ptr<list<Rule<«adaptationClassName»>>>''';
  496. visitor.functionSignatures.add(functionPrefix + " " + functionName)
  497. cpp += '''
  498. «functionPrefix» «adaptationClassName»::«functionName»
  499. {
  500. auto list = make_shared<std::list<Rule<«adaptationClassName»>>>();
  501. «createRulesFunction.join("\n")»
  502. return list;
  503. }
  504. '''
  505. }
  506. }
  507. return new InOutRulesBlockResult(cpp, visitor.functionSignatures);
  508. }
  509. /*
  510. * Calculates the semantic adaptation scalar variables via input ports and output ports.
  511. * Note: These a not fully populated yet as the in rules and out rules must be compiled first.
  512. */
  513. def LinkedHashMap<String, SAScalarVariable> calcSASVsFromInportsOutports(String definePrefix,
  514. EList<Port> inports, EList<Port> outports,
  515. LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mSVs) {
  516. var LinkedHashMap<String, SAScalarVariable> saSVs = newLinkedHashMap();
  517. var int valueReference = 0;
  518. for (inport : inports) {
  519. var saSV = new SAScalarVariable();
  520. saSV.SetPartOfMD(true);
  521. saSV.valueReference = valueReference++;
  522. saSV.name = inport.name;
  523. saSV.defineName = (definePrefix + inport.name).toUpperCase
  524. saSV.causality = SVCausality.input;
  525. saSVs.put(saSV.name, saSV);
  526. }
  527. for (outport : outports) {
  528. var saSV = new SAScalarVariable();
  529. if (outport.sourcedependency !== null) {
  530. saSV.type = mSVs.get(outport.sourcedependency.owner.name).get(outport.sourcedependency.port.name).
  531. mappedSv.type;
  532. saSV.variability = mSVs.get(outport.sourcedependency.owner.name).get(
  533. outport.sourcedependency.port.name).mappedSv.variability;
  534. }
  535. saSV.SetPartOfMD(true);
  536. saSV.valueReference = valueReference++;
  537. saSV.defineName = (definePrefix + outport.name).toUpperCase
  538. saSV.name = outport.name;
  539. saSV.causality = SVCausality.output;
  540. saSVs.put(saSV.name, saSV);
  541. }
  542. return saSVs;
  543. }
  544. def List<File> getResourcePaths() {
  545. return resourcePaths;
  546. }
  547. }