EMAM2Cpp issueshttps://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues2020-09-30T20:21:49+02:00https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/46Index conversion bug2020-09-30T20:21:49+02:00Sascha DewesIndex conversion bugThere seems to be a bug with the conversion from EMA indices to Cpp indices. In the following example it looks like the ceil function was mistaken for an array as the generator applies the decrementation twice to the inputarray index.
I...There seems to be a bug with the conversion from EMA indices to Cpp indices. In the following example it looks like the ceil function was mistaken for an array as the generator applies the decrementation twice to the inputarray index.
Input Code:
```
implementation Math {
for i=1:3
outputarray(i) = ceil(inputarray(i));
end
}
```
Output Code:
```
void execute()
{
for( auto i=1;i<=3;++i){
outputarray(i-1) = ceil(inputarray(i-1-1));
}
}
```
The same Problem occurs when there is no actual array inside the function brackets.
Input Code:
```
implementation Math {
for i=1:3
Q x = inputarray(i);
outputarray(i) = ceil(x);
end
}
```
Output Code:
```
void execute()
{
for( auto i=1;i<=3;++i){
double x = inputarray(i-1);
outputarray(i-1) = ceil(x-1);
}
}
```https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/32Issues with dynamic using2019-07-11T17:19:56+02:00Wei XuIssues with dynamic usingSome bugs occurred when dynamic ports are used in cooperative Autopilot development.
1. Generation of connecting method<br>
Duplicate Method for the copy of dynamic message inputs shows as follows:<br>
```js
dynamic component St...Some bugs occurred when dynamic ports are used in cooperative Autopilot development.
1. Generation of connecting method<br>
Duplicate Method for the copy of dynamic message inputs shows as follows:<br>
```js
dynamic component Statusduplicate{
ports
// copy statusmessage for dupilcate in ports
dynamic in Statusmessage status_msg[0:32],
dynamic out Statusmessage status_msg1[0:32],
...
out Statusmessage smsg;
@ status_msg::connect{/*interface for dynamic ports*/}
implementation Math{
for i = 1:32
if is_connected(status_msg,i)
smsg = status_msg(i);
if ports_connect(status_msg1, i, smsg)
status_msg1(i) = smsg;
end
....
end
end
}
}
```
Once the Statusduplicate component is instantiated is the structure like follows
```js
dynamic component Autopilot{
ports
dynamic in Statusmessage status_msg[0:32],
...
instance Statusduplicate s_dup;
instance Autopilot1 ap1;
@ status_msg::connect{
connect status_msg[?] -> s_dup.status_msg[?];
}
@ s_dup.status_msg1::connect{
connect s_dup.status_msg1 -> ap1.status_msg[?];
}
}
dynamic component Autopilot1{
ports
dynamic in Statusmessage status_msg[0:32],
...
instance Statusduplicate s_dup;
@ status_msg::connect{
connect status_msg[?] -> s_dup.status_msg[?];
}
}
```
the generated c++ file of Statusduplicate instance in Autopilot1 wont't contain the ports_connect methods.
2. When there are dynamic connects and static connects in one component, sometimes the execution order in generated c++ file is not correct, but it happens irregularly, so current the detailed problems cannot locate.
3. Generation of C++ files costs too long time when there are dynamic ports and connects in the model, the generation of around 4000 lines component costs over 10 hours(without dynamic using only 10 - 20 minutes), it may due to some redundant processes. Evgeny KusmenkoEvgeny Kusmenkohttps://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/31Issues of dynamic port and connect2019-06-06T10:56:43+02:00Wei XuIssues of dynamic port and connectProblems occurs when the dynamic port and connect are applied in the Autopilot model.<br>
1. Dynamic ports free problem <br>
After every execution of Autopilot model, dynamic input and output ports should be free by the `free_#port_n...Problems occurs when the dynamic port and connect are applied in the Autopilot model.<br>
1. Dynamic ports free problem <br>
After every execution of Autopilot model, dynamic input and output ports should be free by the `free_#port_name#` method in Autopilot.h, which is called in AutopilotAdapter.cpp. <br>
For simple component like:<br>
```js
dynamic component Autopilot {
port
dynamic in Q input[0:32],
dynamic out Q output[0:32];
@input::connect{
connect input[?] -> output[?];
}
}
```
Free of dynamic inputs and outputs works, when we use the `free_input` method of autopilot.h in AutopilotAdapter.cpp, like follows:<br>
```js
bool free_input(int input_indexref)
{
if( (input_indexref < 0) || (32 <= input_indexref) || (!__input_connected[input_indexref]) ){ return false;}
__input_free_request.push(input_indexref);
dynamicfree();
return true;
}
```
It‘s because in the `dynamicfree()` method, `__output_free_request` will be pushed and then free, when it connects to in the dynamic input port.
```js
void __event_body_free_EventHandler_1_(){
while(input_has_free_request()){
int _input_dynPortID = input_free_request_front();
for(long i = __event_connects_EventHandler_1_.size()-1; i >= 0; --i){
int* _connected_idxs = __event_connects_EventHandler_1_.at(i);
if( (_input_dynPortID == _connected_idxs[0]) ){
int _output_dynPortID = _connected_idxs[1]; __output_free_request.push(_output_dynPortID);
if(__parent != NULL){__parent_dynamic(__parent, false, true);}
if(__output_free_request.front() == _output_dynPortID){ __output_free_request.pop(); }
dynamicconnect_remove(&__dynamic_double_connect, NULL, &(input[_input_dynPortID]), &(output[_output_dynPortID]));
__event_connects_EventHandler_1_.erase(__event_connects_EventHandler_1_.begin()+i);
__output_connected[_output_dynPortID] = false;
free(_connected_idxs);
}
}
}
}
```
But when component is defined as follows:
```js
dynamic component Autopilot {
port
dynamic in Q input[0:32],
dynamic out Q output[0:32];
instance Autopilot1 ap1;
@ input::connect{
connect input[?] -> ap1.input[?];
}
@ ap1.output1::connect{
connect ap1.output1[?] -> output[?];
}
}
```
```js
dynamic component Autopilot1{
port
dynamic in Q input[0:32],
dynamic out Q output1[0:32],
dynamic out Q output2[0:32];
@ input::connect{}
implementation Math{
for i = 1:32
if is_connected(input,i)
if ports_connect(output1, i, input(i))
output1(i) = input(i);
end
if ports_connect(output2, i, input(i))
output2(i) = input(i);
end
end
end
}
}
```
Free of dynamic output ports depends on the free event:
```js
void __event_body_free_EventHandler_3_(){
while(ap1.output1_has_free_request()){
int _ap1_output1_dynPortID = ap1.output1_free_request_front();
for(long i = __event_connects_EventHandler_3_.size()-1; i >= 0; --i){
int* _connected_idxs = __event_connects_EventHandler_3_.at(i);
if( (_ap1_output1_dynPortID == _connected_idxs[0]) ){
int _output_dynPortID = _connected_idxs[1]; __output_free_request.push(_output_dynPortID);
if(__parent != NULL){__parent_dynamic(__parent, false, true);}
if(__output_free_request.front() == _output_dynPortID){ __output_free_request.pop(); }
dynamicconnect_remove(&__dynamic_double_connect, NULL, &(ap1.output1[_ap1_output1_dynPortID]), &(output[_output_dynPortID]));
__event_connects_EventHandler_3_.erase(__event_connects_EventHandler_3_.begin()+i);
__output_connected[_output_dynPortID] = false;
free(_connected_idxs);
}
}
}
}
```
But, the `ap1.output1_has_free_request()` is never pushed in instance ap1, because there is no connect between the dynamic input ports and output1 ports in instance ap1, so dynamic output ports of Autopilot can not be free correctly.<br>
When we use the ports_free method in Autopilot1 component:
```js
dynamic component Autopilot1{
port
dynamic in Q input[0:32],
dynamic out Q output1[0:32],
dynamic out Q output2[0:32];
@ input::connect{}
implementation Math{
for i = 1:32
if is_connected(input,i)
if ports_connect(output1, i, input(i))
output1(i) = input(i);
end
Z r = ports_free(output1,i);
if ports_connect(output2, i, input(i))
output2(i) = input(i);
end
Z r = ports_free(output2,i);
end
end
}
}
```
The free request can be pushed into `ap1.output1_has_free_request()` with `__ports_free_1` method:
```js
bool __ports_free_1(int idx0){
if((idx0 < 0) || (32 <= idx0) || (!__output1_connected[idx0])){return false;}__output1_free_request.push(idx0);
if(__parent != NULL){__parent_dynamic(__parent, false, true);}
__output1_connected[idx0] = false;
return true;
}
```
Problem is that `__output1_connected[idx0]` can not be set to false in this method, it means this port is free now and next connect will occupy this port, which leads to error that no matter how many inputs request there is just one output connect request.<br>
Also, when component like follows, there are two Autopilot1 instances:
```js
dynamic component Autopilot {
port
dynamic in Q input[0:32],
dynamic out Q output[0:32];
instance Autopilot1 ap1,ap2;
@ input::connect{
connect input[?] -> ap1.input[?];
}
@ ap1.output1::connect{
connect ap1.output1[?] -> ap2.input[?];
}
@ ap2.output1::connect{
connect ap2.output1[?] -> output[?];
}
}
```
```js
dynamic component Autopilot1{
port
dynamic in Q input[0:32],
dynamic out Q output1[0:32],
dynamic out Q output2[0:32];
@ input::connect{}
implementation Math{
for i = 1:32
if is_connected(input,i)
if ports_connect(output1, i, input(i))
output1(i) = input(i);
end
Z r = ports_free(output1,i);
if ports_connect(output2, i, input(i))
output2(i) = input(i);
end
Z r = ports_free(output2,i);
end
end
}
}
```
Free of dynamic output ports depends on the free event:
```js
void __event_body_free_EventHandler_4_(){
while(ap2.output1_has_free_request()){
int _ap2_output1_dynPortID = ap2.output1_free_request_front();
for(long i = __event_connects_EventHandler_4_.size()-1; i >= 0; --i){
int* _connected_idxs = __event_connects_EventHandler_4_.at(i);
if( (_ap2_output1_dynPortID == _connected_idxs[0]) ){
int _output_dynPortID = _connected_idxs[1]; __output_free_request.push(_output_dynPortID);
if(__parent != NULL){__parent_dynamic(__parent, false, true);}
if(__output_free_request.front() == _output_dynPortID){ __output_free_request.pop(); }
dynamicconnect_remove(&__dynamic_double_connect, NULL, &(ap2.output1[_ap2_output1_dynPortID]), &(output[_output_dynPortID]));
__event_connects_EventHandler_4_.erase(__event_connects_EventHandler_4_.begin()+i);
__output_connected[_output_dynPortID] = false;
free(_connected_idxs);
}
}
}
}
```
Free of dynamic output port in Autopilot depends on `ap2.output1_has_free_request()`, although ports_free method is defined in Autopilot1, there is no `__ports_free#number#` method in generated autopilot_ap2.h file. It means that ports_free method can just be converted in the outer layer of the whole component.<br>
The structure like this problem occurs component is very important in the autopilot. Because there are several subcomponents, which all need the content of dynamic input. But once dynamic input port connects to the dynamic port in sub-component, connect request of dynamic input will be pop, so we need the component like Autopilot1, which aims to copy the connect request of dynamic input port.<br>
When the dynamic port in Autopilot can not be free, after several frames of simulation, all ports will be occupied and over flow. JVM is broken down and shows RUNTIME error.
2. Problems in instance ports<br>
When the structure of Autopilot Model like follows:
```js
dynamic component Autopilot {
port
dynamic in Q input[0:32],
dynamic out Q output[0:32];
instance Autopilot1 ap1[0:32];
instance Autopilot2 ap2[0:32];
instance Autopilot3 ap3;
@ input::connect{
connect input[?] -> ap1[?].input;
connect ap1[?].output1 -> ap3.input1[?];
connect ap1[?].output2 -> ap3.input2[?];
connect input[?] -> ap2[?].input;
connect ap2[?].output3 -> ap3.input3[?];
connect ap2[?].output4 -> ap3.input4[?];
}
@ ap3.output1::connect{
connect ap3.output1[?] -> output[?];
}
@ ap3.output2::connect{
connect ap3.output2[?] -> output[?];
}
}
```
```js
component Autopilot1{
port
in Q input,
out Q output1,
out Q output2;
implementation Math{
output1 = input;
output2 = input;
}
}
```
```js
component Autopilot2{
port
in Q input,
out Q output3,
out Q output4;
implementation Math{
output3 = input;
output4 = input;
}
}
```
```js
dynamic component Autopilot4{
port
dynamic in Q input1[0:32],
dynamic in Q input2[0:32],
dynamic out Q output[0:32];
@input1::connect{}
@input2::connect{}
implementation Math{
for i = 1:32
if is_connected(input1,i)&&is_connected(input2,i)
if ports_connect(output,i,42.123)
output(i) = input1(i) + input2(i);
end
end
end
}
}
```
```js
dynamic component Autopilot3{
port
dynamic in Q input1[0:32],
dynamic in Q input2[0:32],
dynamic in Q input3[0:32],
dynamic in Q input4[0:32],
dynamic out Q output1[0:32],
dynamic out Q output2[0:32];
instance Autopilot4 ap4,ap5;
@ input1::connect{
connect input1[?] -> ap4.input1[?];
}
@ input2::connect{
connect input2[?] -> ap4.input2[?];
}
@ ap4.output::connect{
connect ap4.output[?] -> output1[?];
}
@ input3::connect{
connect input3[?] -> ap5.input1[?];
}
@ input4::connect{
connect input4[?] -> ap5.input2[?];
}
@ ap5.output::connect{
connect ap5.output[?] -> output2[?];
}
}
```
The structure can be shown in a Figure:![Structure](/uploads/4e347387c743ee3060d235ac372904c3/Structure.png)
In the generated c++ file of autopilot, there is a undefined connect method `ap3.connect_input1_input2_input3_input4`, which is called in autopilot.h. This leads to the error when c++ files are compiled to dll file.
```js
void __event_body_EventHandler_9_()
{
while(__event_condition_EventHandler_9_()){
int* _connected_idxs = (int *)calloc(7, sizeof(int));
int _input_dynPortID = __input_connect_request.front(); __input_connect_request.pop(); _connected_idxs[0] = _input_dynPortID;
int _ap2_dynINSTID = dynamicconnect(32, __ap2_connected); if( _ap2_dynINSTID < 0 ){ free(_connected_idxs); return; } _connected_idxs[1] = _ap2_dynINSTID;
int _ap1_dynINSTID = dynamicconnect(32, __ap1_connected); if( _ap1_dynINSTID < 0 ){ free(_connected_idxs); return; } _connected_idxs[2] = _ap1_dynINSTID;
int _ap3_input1_dynPortID = -1;
int _ap3_input2_dynPortID = -1;
int _ap3_input3_dynPortID = -1;
int _ap3_input4_dynPortID = -1;
if(!ap3.connect_input1_input2_input3_input4(&_ap3_input1_dynPortID, ap1[_ap1_dynINSTID].output1, &_ap3_input2_dynPortID, ap1[_ap1_dynINSTID].output2, &_ap3_input3_dynPortID, ap2[_ap2_dynINSTID].output3, &_ap3_input4_dynPortID, ap2[_ap2_dynINSTID].output4)){ free(_connected_idxs); return ;}
_connected_idxs[3] = _ap3_input1_dynPortID;_connected_idxs[4] = _ap3_input2_dynPortID;_connected_idxs[5] = _ap3_input3_dynPortID;_connected_idxs[6] = _ap3_input4_dynPortID;
__dynamic_double_connect.push_back({&ap1[_ap1_dynINSTID], &(input[_input_dynPortID]), &(ap1[_ap1_dynINSTID].input)});
__dynamic_double_connect.push_back({&ap3, &(ap1[_ap1_dynINSTID].output1), &(ap3.input1[_ap3_input1_dynPortID])});
__dynamic_double_connect.push_back({&ap3, &(ap1[_ap1_dynINSTID].output2), &(ap3.input2[_ap3_input2_dynPortID])});
__dynamic_double_connect.push_back({&ap2[_ap2_dynINSTID], &(input[_input_dynPortID]), &(ap2[_ap2_dynINSTID].input)});
__dynamic_double_connect.push_back({&ap3, &(ap2[_ap2_dynINSTID].output3), &(ap3.input3[_ap3_input3_dynPortID])});
__dynamic_double_connect.push_back({&ap3, &(ap2[_ap2_dynINSTID].output4), &(ap3.input4[_ap3_input4_dynPortID])});
__event_connects_EventHandler_9_.push_back(_connected_idxs);
}
}
```
3. Port free in Streamtest<br>
Dynamic ports can not be free in current Streamtest project, when dynamic component is tested with TestWrapper and Stream File. Because free_methods of dynamic component are not called. So, the length of Stream data can just be one. Otherwise, it leads to error when tests second group of stream data, the reason is that last used ports are not free.Evgeny KusmenkoEvgeny Kusmenkohttps://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/26Invalid MontiMath functions do not throw an error2022-04-28T12:57:50+02:00Alexander David HellwigInvalid MontiMath functions do not throw an errore.g. `out1 = ... + rand()` generates, but cannot be compiled(as rand is not specific)e.g. `out1 = ... + rand()` generates, but cannot be compiled(as rand is not specific)Jan Philipp HallerJan Philipp Hallerhttps://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/22Automatic stream test generation2018-08-16T17:41:34+02:00Sascha Niklas SchneidersAutomatic stream test generationThe generator should be able to generate a stream test for a given emam model.
This functionality can then be used to add tests for every component.
Together with #23 starting from the version this feature was added, it can be ensured t...The generator should be able to generate a stream test for a given emam model.
This functionality can then be used to add tests for every component.
Together with #23 starting from the version this feature was added, it can be ensured that the generator still behaves the same without comparing the generated source code directly.Sascha Niklas SchneidersSascha Niklas Schneidershttps://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/21Update EMAM2Cpp in Emam2Wasm2020-07-02T19:24:35+02:00Malte HeithoffUpdate EMAM2Cpp in Emam2WasmIs someone able to include the current version of emam2cpp in emam2wasm?Is someone able to include the current version of emam2cpp in emam2wasm?https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/11Structs Do not work for arrays / matrices2018-07-04T09:23:52+02:00vonWencksternStructs Do not work for arrays / matrices@sascha.schneiders can you create a test, to verify whether this bug exists@sascha.schneiders can you create a test, to verify whether this bug existsSascha Niklas SchneidersSascha Niklas Schneidershttps://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/8Refactor all conversions2018-07-01T18:20:26+02:00Sascha Niklas SchneidersRefactor all conversions# Preliminary:
The math language needs to store all relevant information in the astnodes, and not everything in different symbols, as symbols will change in the next monticore version, and the generated monticore visitor for a language ...# Preliminary:
The math language needs to store all relevant information in the astnodes, and not everything in different symbols, as symbols will change in the next monticore version, and the generated monticore visitor for a language can only be used on astnodes, not on their symbols. (astnode.getSymbol() is deprecated and will be removed soon, so no direct connection between astnode -> symbol anymore; Every symbol needs to habe a unique name for identification)
# Conversion:
The conversions should be done using the generated monticore visitor for all astnodes of a language.
This includes the optimizations, and general transformations.
As the generator currently works mostly with the Math languge symbols only, a huge refactoring is required.
# Goal:
Reduce bugs, increase robustness and readability.https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/7Generics are missing when no default value is provided2018-07-01T00:03:20+02:00Sascha Niklas SchneidersGenerics are missing when no default value is providedExsample:
```
component ComponentA<N value>{
}
```
The generator does not now anything about value.
This is an issue with the EmbeddedMontiArc language and should be fixed there.
Components like:
```
component ComponentA<N value = ...Exsample:
```
component ComponentA<N value>{
}
```
The generator does not now anything about value.
This is an issue with the EmbeddedMontiArc language and should be fixed there.
Components like:
```
component ComponentA<N value = 1>{
}
```
Work as expected.https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/6Generics Inistialization in SubComponents does not work correctly, when Gener...2018-07-01T00:03:51+02:00Sascha Niklas SchneidersGenerics Inistialization in SubComponents does not work correctly, when Generics of parent component are used as valueExample:
```
component ComponentA<N value = 1>{
instance ComponentB<value> compB; // in compB instance creation the default value will be used
}
```
```
component ComponentB<N value = 2>{
port in Z testPorts[value];
}
```
```
co...Example:
```
component ComponentA<N value = 1>{
instance ComponentB<value> compB; // in compB instance creation the default value will be used
}
```
```
component ComponentB<N value = 2>{
port in Z testPorts[value];
}
```
```
component ComponentC{
instance ComponentA<5> compA;
}
```
Should be fixed in Generics Resolution in EmbeddedMontiArc language.
(ExpandedComponentInstance creation should probably be changed, as the error is related to this)https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/4Create many new Tests for different generator states (e.g. Optimizations)2018-07-14T06:44:03+02:00Sascha Niklas SchneidersCreate many new Tests for different generator states (e.g. Optimizations)This includes existing components with enabled and disabled optimizations,
as well as additoional test taht are derived from the usage of EMAStudio.This includes existing components with enabled and disabled optimizations,
as well as additoional test taht are derived from the usage of EMAStudio.https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/EMAM2Cpp/-/issues/2Gerneric type in initialization parameter2018-06-12T22:00:51+02:00Nils KaminskiGerneric type in initialization parameterConsider the following two components:
```
package test;
component Delay<T> (T initval) {
port
in T in1,
out T out1;
implementation Math {
static T sval = initval;
out1 = sval;
sval = in1;
}
}
package test;
co...Consider the following two components:
```
package test;
component Delay<T> (T initval) {
port
in T in1,
out T out1;
implementation Math {
static T sval = initval;
out1 = sval;
sval = in1;
}
}
package test;
component DelayTest {
port
in Q in1,
out Q out1;
instance Delay<Q>(2) delayInstanceZ;
connect in1 -> delayInstanceZ.in1;
connect delayInstanceZ.out1 -> out1;
}
```
While generating it produces an error and terminates:
[ERROR] Case not handled!