Commit c1a4ce0d authored by Nils Kaminski's avatar Nils Kaminski
Browse files

Dynamic port (request) connection

parent 3a4a1d5f
......@@ -2,6 +2,7 @@ package de.monticore.lang.monticar.generator.cpp;
import de.monticore.lang.monticar.generator.BluePrint;
import de.monticore.lang.monticar.generator.Variable;
import de.monticore.lang.monticar.generator.cpp.symbols.MathStringExpression;
import de.se_rwth.commons.logging.Log;
import java.util.*;
......@@ -40,10 +41,14 @@ public class BluePrintFixer {
}
if(isDynamic){
newVars.add(addConnectedVariableForVariable(varList, nameWithoutArray, bluePrint));
newVars.add(addConnectedRequestQueueForVariable(nameWithoutArray, bluePrint));
}
});
//TODO: Generate vectors with output functionality
// std::vector<connection<bool>> dynamic_bool_connection_IN;
// std::vector<connection<bool>> dynamic_bool_connection_OUT;
bluePrint.setVariables(newVars);
}
......@@ -51,21 +56,31 @@ public class BluePrintFixer {
protected static Variable addConnectedVariableForVariable(List<Variable> varList, String nameWithoutArray, BluePrint bluePrint){
Log.info("Adding __connected variable for "+nameWithoutArray, "Dynamic Connected Variable");
String s = "[";
for(int i = 0; i < varList.size(); ++i){
s += varList.get(i).isDynamic() ? "false" : "true";
if(i < varList.size()-1){
s += ", ";
}
}
s += "]";
Variable variable = new Variable();
variable.setName("__"+nameWithoutArray+"_connected");
VariableConstantArray variable = new VariableConstantArray("__"+nameWithoutArray+"_connected");
variable.addAdditionalInformation(Variable.ORIGINPORT);
variable.setArraySize(varList.size());
variable.setTypeNameTargetLanguage("bool");
variable.setIsConstantVariable(true);
variable.setConstantValue(s);
// variable.setIsConstantVariable(true);
// variable.setConstantValue(s);
variable.setPublic(false);
for(int i = 0; i < varList.size(); ++i){
variable.addConstantInitValue(varList.get(i).isDynamic() ? "false" : "true");
}
bluePrint.getMathInformationRegister().addVariable(variable);
return variable;
}
protected static Variable addConnectedRequestQueueForVariable(String nameWithoutArray, BluePrint bluePrint){
Log.info("Adding __connect_request variable for "+nameWithoutArray, "Dynamic Request Connect Queue for Variable");
Variable variable = new Variable();
variable.setName("__"+nameWithoutArray+"_connect_request");
variable.setTypeNameTargetLanguage("std::queue<int>");
variable.setPublic(false);
bluePrint.getMathInformationRegister().addVariable(variable);
......
package de.monticore.lang.monticar.generator.cpp;
import de.monticore.lang.monticar.generator.Method;
import de.monticore.lang.monticar.generator.TargetCodeInstruction;
import de.monticore.lang.monticar.generator.Variable;
import java.util.ArrayList;
import java.util.List;
public class VariableConstantArray extends Variable {
protected List<String> values = new ArrayList<>();
public VariableConstantArray(String name){
super();
this.setName(name);
}
@Override
public boolean isConstantVariable() {
return true;
}
@Override
public String getConstantValue() {
return String.join(", ", values);
}
public void generateInit(Method initMethod){
for(int i = 0; i < this.getArraySize(); ++i){
if(i < values.size()){
initMethod.addInstruction(new TargetCodeInstruction(
String.format("%s[%d] = %s;\n", this.getName(), i, values.get(i))
));
}
}
}
public void addConstantInitValue(String value){
values.add(value);
}
}
......@@ -73,6 +73,8 @@ public class ComponentConverter {
Method execute = ComponentConverterMethodGeneration.generateExecuteMethod(componentSymbol, bluePrint, mathStatementsSymbol, generatorCPP, includeStrings);
Method init = generateInitMethod(componentSymbol, bluePrint, generatorCPP, includeStrings);
EventConverter.generateEvents(execute, componentSymbol, bluePrint, mathStatementsSymbol,generatorCPP, includeStrings);
bluePrint.addMethod(init);
bluePrint.addMethod(execute);
......@@ -130,8 +132,10 @@ public class ComponentConverter {
for (Variable v : bluePrint.getVariables()) {
Log.info("Variable: " + v.getName(), "initBluePrintCreate:");
if(v instanceof VariablePortValueChecker){
((VariablePortValueChecker)v).addInitInstructionsToMethod(method);
if(v instanceof VariablePortValueChecker) {
((VariablePortValueChecker) v).addInitInstructionsToMethod(method);
}else if(v instanceof VariableConstantArray){
((VariableConstantArray) v).generateInit(method);
}else {
if (v.isInputVariable() && !v.isConstantVariable()) {
//method.addParameter(v);
......
......@@ -67,7 +67,7 @@ public class ComponentConverterMethodGeneration {
Collection<EMAConnectorInstanceSymbol> connectors = componentSymbol.getConnectorInstances();
generateConnectors(connectors, bluePrint, method);
EventConverter.generateEventConnectors(method, componentSymbol, bluePrint, mathStatementsSymbol,generatorCPP, includeStrings);
if (mathStatementsSymbol != null) {
handleMathStatementGeneration(method, bluePrint, mathStatementsSymbol, generatorCPP, includeStrings);
......
......@@ -6,16 +6,11 @@ import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instance
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicConnectorInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicEventHandlerInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.event._symboltable.expression.EventBracketExpressionSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.event._symboltable.expression.EventExpressionSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.event._symboltable.expression.EventLogicalOperationExpressionSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.event._symboltable.expression.EventPortExpressionValueSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicPortInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.event._symboltable.expression.*;
import de.monticore.lang.embeddedmontiarcdynamic.event._symboltable.expression.portvalueexpressionvalues.*;
import de.monticore.lang.math._symboltable.MathStatementsSymbol;
import de.monticore.lang.monticar.generator.Instruction;
import de.monticore.lang.monticar.generator.Method;
import de.monticore.lang.monticar.generator.TargetCodeInstruction;
import de.monticore.lang.monticar.generator.Variable;
import de.monticore.lang.monticar.generator.*;
import de.monticore.lang.monticar.generator.cpp.BluePrintCPP;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.monticar.generator.cpp.VariablePortValueChecker;
......@@ -23,13 +18,14 @@ import de.monticore.lang.monticar.generator.cpp.instruction.ConnectInstructionCP
import de.monticore.lang.monticar.generator.cpp.instruction.EventConnectInstructionCPP;
import de.se_rwth.commons.logging.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
public class EventConverter {
public static void generateEventConnectors(Method method, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint, MathStatementsSymbol mathStatementsSymbol, GeneratorCPP generatorCPP, List<String> includeStrings){
public static void generateEvents(Method executeMethod, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint, MathStatementsSymbol mathStatementsSymbol, GeneratorCPP generatorCPP, List<String> includeStrings){
if(!(componentSymbol instanceof EMADynamicComponentInstanceSymbol)){
return;
}
......@@ -37,33 +33,99 @@ public class EventConverter {
for(EMADynamicEventHandlerInstanceSymbol event : dynComponent.getEventHandlers()){
Log.info("Create connectors for: "+event.getFullName(), "EventConverter");
Log.info("Create Event: "+event.getName(), "EventConverter");
int number = 0;
for(EMADynamicConnectorInstanceSymbol connector : event.getConnectorsDynamic()){
if(connector.isDynamicSourceNewComponent() || connector.isDynamicSourceNewPort() || connector.isDynamicTargetNewComponent() || connector.isDynamicTargetNewPort()){
continue;
}
boolean generateCondition = false;
generateEventConnector(event.getFullName(), connector, bluePrint, method);
++number;
if(event.isDynamicPortConnectionEvent()) {
//TODO generate dynamic event
generateCondition = generateDynamicConnectEvent(event, componentSymbol, executeMethod, bluePrint);
}else{
Log.info("Create connectors for: "+event.getFullName(), "EventConverter");
generateCondition = generateValueEvent(event, executeMethod, bluePrint);
}
if (number > 0) {
if (generateCondition) {
//generate event condition method
Method condition = new Method(EventConnectInstructionCPP.getEventNameCPP(event.getFullName()), "bool");
condition.setPublic(false);
generateEventConditionMethod(event, componentSymbol, bluePrint);
}
}
}
protected static void generateEventConditionMethod(EMADynamicEventHandlerInstanceSymbol event, EMAComponentInstanceSymbol componentSymbol,BluePrintCPP bluePrint ){
Method condition = new Method(EventConnectInstructionCPP.getEventNameCPP(event.getFullName()), "bool");
condition.setPublic(false);
String conditionExpression = "return ";
conditionExpression += generateEventCondition(event.getCondition(), componentSymbol, bluePrint);
conditionExpression += ";\n";
String conditionExpression = "return ";
conditionExpression += generateEventCondition(event.getCondition(), componentSymbol, bluePrint);
conditionExpression += ";\n";
condition.addInstruction(new TargetCodeInstruction(conditionExpression));
bluePrint.addMethod(condition);
}
condition.addInstruction(new TargetCodeInstruction(conditionExpression));
bluePrint.addMethod(condition);
protected static boolean generateValueEvent(EMADynamicEventHandlerInstanceSymbol event, Method executeMethod, BluePrintCPP bluePrint ){
int number = 0;
for(EMADynamicConnectorInstanceSymbol connector : event.getConnectorsDynamic()){
if(connector.isDynamicSourceNewComponent() || connector.isDynamicSourceNewPort() ||
connector.isDynamicTargetNewComponent() || connector.isDynamicTargetNewPort()){
continue;
}
generateEventConnector(event.getFullName(), connector, bluePrint, executeMethod);
++number;
}
return number > 0;
}
protected static boolean generateDynamicConnectEvent(EMADynamicEventHandlerInstanceSymbol event, EMAComponentInstanceSymbol componentSymbol, Method executeMethod, BluePrintCPP bluePrint ) {
List<String> names= new ArrayList<>();
event.getCondition().getConnectPortNames(names);
java.util.Collections.sort(names);
String connectMethodName = "connect_"+String.join("_", names);
if(!bluePrint.getMethod(connectMethodName).isPresent()){
generateConnectMethod(connectMethodName,names, componentSymbol, bluePrint);
}
//TODO generate event body method
return true;
}
protected static void generateConnectMethod(String name,List<String> names, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint){
Log.info("Create connect method: "+name+"(...)", "EventConverter");
Method method = new Method(name, "bool");
List<String> checks = new ArrayList<>();
for(String n : names ){
Variable v = new Variable();
v.setName(n+"_indexref");
v.setTypeNameTargetLanguage("int*");
method.addParameter(v);
long counter = componentSymbol.getPortInstanceList().stream().filter(p->p.getNameWithoutArrayBracketPart().equals(n)).count();
String inst = String.format("*%s_indexref = dynamicconnect(%d, __%s_connected, &__%s_connect_request);\n", n, counter, n,n);
method.addInstruction(
new TargetCodeInstruction(inst)
);
checks.add(String.format("(*%s_indexref < 0)", n));
}
method.addInstruction(new TargetCodeInstruction(
String.format("if(%s){return false;}\n", String.join(" || ", checks))
));
method.addInstruction(new TargetCodeInstruction("return true;\n"));
bluePrint.addAdditionalIncludeString("DynamicHelper");
bluePrint.addMethod(method);
}
public static void generatePVCNextMethod(BluePrintCPP bluePrint){
Method next = new Method("next", "void");
next.setPublic(false);
......@@ -114,6 +176,8 @@ public class EventConverter {
}
}
//<editor-fold desc="Generate event condition">
protected static String generateEventCondition(EventExpressionSymbol expression, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint){
if(expression instanceof EventBracketExpressionSymbol){
return "( "+generateEventCondition(((EventBracketExpressionSymbol) expression).getInnerExpression(), componentSymbol, bluePrint)+" )";
......@@ -121,6 +185,8 @@ public class EventConverter {
return generateEventConditionEventLogicalExpressionSymbol((EventLogicalOperationExpressionSymbol) expression, componentSymbol, bluePrint);
}else if(expression instanceof EventPortExpressionValueSymbol){
return generateEventConditionEventPortValueSymbol((EventPortExpressionValueSymbol) expression, componentSymbol, bluePrint);
}else if(expression instanceof EventPortExpressionConnectSymbol){
return generateEventConditionEventPortConnectSymbol((EventPortExpressionConnectSymbol) expression, componentSymbol, bluePrint);
}
return "";
......@@ -143,7 +209,6 @@ public class EventConverter {
protected static String generateEventConditionEventPortValueSymbol(EventPortExpressionValueSymbol expressionValueSymbol, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint){
// Variable v = new Variable()
VariablePortValueChecker pvc = new VariablePortValueChecker(expressionValueSymbol.getName());
bluePrint.addVariable(pvc);
......@@ -153,13 +218,18 @@ public class EventConverter {
pvc.setVariableType(TypeConverter.getVariableTypeForMontiCarTypeName(typeNameMontiCar, pvc, portSymbol.get()).get());
}
addTest(expressionValueSymbol.getPortValue(), pvc);
return pvc.getNameTargetLanguageFormat()+".check()";
}
protected static String generateEventConditionEventPortConnectSymbol(EventPortExpressionConnectSymbol expressionConnectSymbol, EMAComponentInstanceSymbol componentSymbol, BluePrint bluePrint){
return "(!__"+expressionConnectSymbol.getName()+"_connect_request.empty())";
}
//</editor-fold>
//<editor-fold desc="Generate concrete test for port values">
public static void addTest(PortValueSymbol pvs, VariablePortValueChecker vpvc){
......
#ifndef Dynamic_Connect_Helper_h
#define Not_h
#include <queue>
#include <vector>
#ifndef CONNECTION_H
#define CONNECTION_H
template<typename T>
struct connection {
T *from;
T *to;
};
#endif
int dynamicconnect(int numPorts, bool* connected){
int port = -1;
for (port = 0; port < numPorts; ++port) {
if (!connected[port]) {
break;
}
}
if (port >= numPorts) {
//no free ports
return -1;
}
connected[port] = true;
return port;
}
int dynamicconnect(int numPorts, bool* connected, std::queue<int>* request){
int port = dynamicconnect(numPorts, connected);
if(port >= 0){
request->push(port);
}
return port;
}
#endif /* Dynamic_Connect_Helper_h */
\ No newline at end of file
package de.monticore.lang.monticar.generator.dynamics;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.AbstractSymtabTest;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class DynamicPortConnectionGenerationTest extends AbstractSymtabTest {
@BeforeClass
public static void setUp() {
// ensure an empty log
Log.getFindings().clear();
Log.enableFailQuick(false);
}
@Test
public void Test_01_PortRequest1() throws IOException {
TaggingResolver symtab = createSymTabAndTaggingResolver("src/test/resources/dynamics");
EMAComponentInstanceSymbol componentSymbol = symtab.<EMAComponentInstanceSymbol>resolve("portRequest.portRequest1", EMAComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentSymbol);
GeneratorCPP generatorCPP = new GeneratorCPP();
generatorCPP.useArmadilloBackend();
generatorCPP.setGenerationTargetPath("./target/generated-sources-cpp/dynamics/DynamicPortConnectionGenerationTest_Test_01_PortRequest1");
List<File> files = generatorCPP.generateFiles(symtab, componentSymbol, symtab);
files.stream().forEach(f -> System.out.println("Generated: "+f.getName()));
}
}
package portRequest;
dynamic component PortRequest1 {
ports
dynamic in B a[2:8],
dynamic out B b[3:8];
connect a[1] -> b[1];
connect a[2] -> b[2];
@ b::connect && a::connect {
connect a[?] -> b[?];
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment