Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
monticore
EmbeddedMontiArc
generators
EMAM2Cpp
Commits
0d5b35e1
Commit
0d5b35e1
authored
Aug 18, 2018
by
Sascha Niklas Schneiders
Browse files
execution can finally create log files now
parent
c5f57c8d
Pipeline
#69092
passed with stage
in 13 minutes and 45 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/main/java/de/monticore/lang/monticar/generator/cpp/ArmadilloHelperSource.java
View file @
0d5b35e1
...
...
@@ -30,7 +30,64 @@ public class ArmadilloHelperSource {
"#include \"armadillo.h\"\n"
+
"#include <stdarg.h>\n"
+
"#include <initializer_list>\n"
+
"#include <fstream>\n"
+
"using namespace arma;\n"
+
"#ifndef _FILESTRING_CONVERSION___A\n"
+
"#define _FILESTRING_CONVERSION___A\n"
+
"#include \"armadillo.h\"\n"
+
"using namespace arma;\n"
+
"void toFileString(std::ofstream& myfile, mat A){\n"
+
" myfile << \"[\";\n"
+
" for (int i = 0; i < A.n_rows; i++){\n"
+
" for (int j = 0; j < A.n_cols; j++){\n"
+
" myfile << A(i,j);\n"
+
" if(j + 1 < A.n_cols){\n"
+
" myfile << \", \";\n"
+
" }\n"
+
" }\n"
+
" if(i + 1 < A.n_rows){\n"
+
" myfile << \";\";\n"
+
" }\n"
+
" }\n"
+
" myfile << \"]\";\n"
+
"}\n"
+
"void toFileString(std::ofstream& myfile, double A){\n"
+
" myfile << A;\n"
+
"}\n"
+
"void toFileString(std::ofstream& myfile, float A){\n"
+
" myfile << A;\n"
+
"}\n"
+
"void toFileString(std::ofstream& myfile, int A){\n"
+
" myfile << A;\n"
+
"}\n"
+
"void toFileString(std::ofstream& myfile, bool A){\n"
+
" myfile << A;\n"
+
"}\n"
+
"bool Is_close(mat& X, mat& Y, double tol)\n"
+
"{\n"
+
" // abs returns a mat type then max checks columns and returns a row_vec\n"
+
" // max used again will return the biggest element in the row_vec\n"
+
" bool close(false);\n"
+
" if(arma::max(arma::max(arma::abs(X-Y))) < tol)\n"
+
" {\n"
+
" close = true;\n"
+
" }\n"
+
" return close;\n"
+
"}\n"
+
"void rangeValueCheck(double A, double lower, double upper){\n"
+
" REQUIRE( A >= lower );\n"
+
" REQUIRE( A <= upper );\n"
+
"}\n"
+
"\n"
+
"void rangeValueCheck(int A, double lower, double upper){\n"
+
" REQUIRE( A >= lower );\n"
+
" REQUIRE( A <= upper );\n"
+
"}\n"
+
"void rangeValueCheck(mat& A, mat& lower , mat& upper){\n"
+
" REQUIRE(Is_close(A, lower, 0.0001));\n"
+
" REQUIRE(Is_close(A, upper, 0.0001));\n"
+
"}\n"
+
"#endif\n"
+
"class HelperA{\n"
+
"public:\n"
+
"static mat getEigenVectors(mat A){\n"
+
...
...
src/main/java/de/monticore/lang/monticar/generator/cpp/GeneratorCPP.java
View file @
0d5b35e1
...
...
@@ -56,6 +56,7 @@ public class GeneratorCPP implements Generator {
private
boolean
isGenerateTests
=
false
;
private
boolean
isGenerateAutopilotAdapter
=
false
;
private
boolean
isGenerateServerWrapper
=
false
;
protected
boolean
isExecutionLoggingActive
=
false
;
private
final
List
<
BluePrintCPP
>
bluePrints
=
new
ArrayList
<>();
protected
String
generationTargetPath
=
"./target/generated-sources-cpp/"
;
...
...
@@ -76,6 +77,14 @@ public class GeneratorCPP implements Generator {
currentInstance
=
this
;
}
public
boolean
isExecutionLoggingActive
()
{
return
isExecutionLoggingActive
;
}
public
void
setExecutionLoggingActive
(
boolean
executionLoggingActive
)
{
isExecutionLoggingActive
=
executionLoggingActive
;
}
public
void
useArmadilloBackend
()
{
MathConverter
.
curBackend
=
new
ArmadilloBackend
();
}
...
...
src/main/java/de/monticore/lang/monticar/generator/cpp/GeneratorCppCli.java
View file @
0d5b35e1
...
...
@@ -99,6 +99,13 @@ public final class GeneratorCppCli {
.
required
(
false
)
.
build
();
public
static
final
Option
OPTION_FLAG_EXEC_LOGGING
=
Option
.
builder
(
"a"
)
.
longOpt
(
"flag-use-exec-logging"
)
.
desc
(
"optional flag indicating if execution logging should be on"
)
.
hasArg
(
false
)
.
required
(
false
)
.
build
();
public
static
final
Option
OPTION_FLAG_AUTOPILOT_ADAPTER
=
Option
.
builder
()
.
longOpt
(
"flag-generate-autopilot-adapter"
)
...
...
@@ -145,6 +152,7 @@ public final class GeneratorCppCli {
options
.
addOption
(
OPTION_FLAG_SERVER_WRAPPER
);
options
.
addOption
(
OPTION_FLAG_ALGEBRAIC
);
options
.
addOption
(
OPTION_FLAG_THREADING
);
options
.
addOption
(
OPTION_FLAG_EXEC_LOGGING
);
return
options
;
}
...
...
@@ -183,6 +191,8 @@ public final class GeneratorCppCli {
g
.
setUseAlgebraicOptimizations
(
cliArgs
.
hasOption
(
OPTION_FLAG_ALGEBRAIC
.
getLongOpt
()));
g
.
setUseThreadingOptimization
(
cliArgs
.
hasOption
(
OPTION_FLAG_THREADING
.
getLongOpt
()));
g
.
setExecutionLoggingActive
(
cliArgs
.
hasOption
(
OPTION_FLAG_EXEC_LOGGING
.
getLongOpt
()));
try
{
if
(
componentSymbol
!=
null
)
{
g
.
generateFiles
(
componentSymbol
,
symTab
);
...
...
src/main/java/de/monticore/lang/monticar/generator/cpp/LanguageUnitCPP.java
View file @
0d5b35e1
...
...
@@ -111,11 +111,20 @@ public class LanguageUnitCPP extends LanguageUnit {
resultString
+=
"#include \""
+
v
.
getVariableType
().
getIncludeName
()
+
".h\"\n"
;
}
}
}
if
(!
alreadyGeneratedIncludes
.
contains
(
"HelperA"
)
&&
generatorCPP
.
isExecutionLoggingActive
)
{
alreadyGeneratedIncludes
.
add
(
"HelperA"
);
resultString
+=
"#include \""
+
"HelperA"
+
".h\"\n"
;
}
for
(
String
string
:
bluePrint
.
getAdditionalIncludeStrings
())
resultString
+=
"#include \""
+
string
+
".h\"\n"
;
if
(
generatorCPP
.
isExecutionLoggingActive
)
resultString
+=
"#include <fstream>\n"
;
for
(
String
include
:
includeStrings
)
{
resultString
+=
include
;
}
...
...
@@ -136,7 +145,9 @@ public class LanguageUnitCPP extends LanguageUnit {
for
(
String
constString
:
bluePrint
.
getConsts
())
resultString
+=
constString
;
resultString
+=
"public:\n"
;
if
(
generatorCPP
.
isExecutionLoggingActive
)
{
resultString
+=
"int __EXECCOUNTER;\n"
;
}
//input variable
for
(
Variable
v
:
bluePrint
.
getVariables
())
{
if
(!
v
.
isArray
())
...
...
@@ -147,8 +158,10 @@ public class LanguageUnitCPP extends LanguageUnit {
//generate methods
for
(
Method
method
:
bluePrint
.
getMethods
())
{
int
counter
=
0
;
resultString
+=
method
.
getReturnTypeName
()
+
" "
+
method
.
getName
()
+
"("
;
for
(
Variable
param
:
method
.
getParameters
())
{
if
(
counter
==
0
)
{
++
counter
;
...
...
@@ -163,7 +176,11 @@ public class LanguageUnitCPP extends LanguageUnit {
//method body start
resultString
+=
"{\n"
;
if
(
generatorCPP
.
isExecutionLoggingActive
&&
method
.
getName
().
equals
(
"execute"
))
{
resultString
+=
"std::ofstream __LogExecutionFile;\n"
;
resultString
+=
"__LogExecutionFile.open(\"execution\"+std::to_string(__EXECCOUNTER)+\".res\");\n"
;
}
for
(
Instruction
instruction
:
method
.
getInstructions
())
{
if
(
instruction
instanceof
ConnectInstructionCPP
)
{
ConnectInstructionCPP
connectInstructionCPP
=
(
ConnectInstructionCPP
)
instruction
;
...
...
@@ -176,7 +193,22 @@ public class LanguageUnitCPP extends LanguageUnit {
resultString
+=
instruction
.
getTargetLanguageInstruction
();
Log
.
info
(
resultString
,
"afterRes:"
);
}
if
(
generatorCPP
.
isExecutionLoggingActive
&&
method
.
getName
().
equals
(
"execute"
))
{
for
(
Variable
v
:
bluePrint
.
getVariables
())
{
if
(
v
.
hasAdditionalInformation
(
Variable
.
ORIGINPORT
))
{
resultString
+=
"__LogExecutionFile << \""
+
v
.
getNameTargetLanguageFormat
()
+
" : \";\n"
;
resultString
+=
"toFileString(__LogExecutionFile, "
+
v
.
getNameTargetLanguageFormat
()
+
");\n"
;
resultString
+=
"__LogExecutionFile << \"\\n\";\n"
;
}
}
}
if
(
generatorCPP
.
isExecutionLoggingActive
&&
method
.
getName
().
equals
(
"execute"
))
{
resultString
+=
"__LogExecutionFile.close();\n"
;
resultString
+=
"__EXECCOUNTER = __EXECCOUNTER + 1;\n"
;
}
if
(
generatorCPP
.
isExecutionLoggingActive
&&
method
.
getName
().
equals
(
"init"
))
{
resultString
+=
"__EXECCOUNTER = 0;\n"
;
}
//method body end
resultString
+=
"}\n"
;
}
...
...
src/main/resources/template/test/ComponentStreamTest2.ftl
View file @
0d5b35e1
...
...
@@ -7,7 +7,7 @@
#
include
<iostream>
#
include
<fstream>
#
include
<string>
void
toFileString(std::ofstream& myfile, mat A)
{
/*
void
toFileString(std::ofstream& myfile, mat A)
{
myfile
<<
"["
;
for
(
int
i
=
0
;
i
<
A
.n_rows
;
i
++
){
for
(
int
j
=
0
;
j
<
A
.n_cols
;
j
++
){
...
...
@@ -57,7 +57,7 @@ void rangeValueCheck(int A, double lower, double upper){
void
rangeValueCheck(mat& A, mat& lower , mat& upper)
{
REQUIRE
(
I
s_close
(
A
,
lower
,
0.0
001
))
;
REQUIRE
(
I
s_close
(
A
,
upper
,
0.0
001
))
;
}
}
*
/
<#
list
viewModel.streams as stream>
TEST_CASE
("${
stream
.name
}",
"[$
{
viewModel
.componentName
}
]")
{
mat
tmpA
;
...
...
src/main/resources/template/test/ComponentStreamTest2NoFileInfo.ftl
0 → 100644
View file @
0d5b35e1
<#
include
"/Common.ftl">
#
ifndef
$
{
viewModel
.fileNameWithoutExtension
?
upper_case
}
#
define
$
{
viewModel
.fileNameWithoutExtension
?
upper_case
}
#
include
"catch.hpp"
#
include
"../$
{
viewModel
.componentName
}
.h"
#
include
<iostream>
#
include
<fstream>
#
include
<string>
void
toFileString(std::ofstream& myfile, mat A)
{
myfile
<<
"["
;
for
(
int
i
=
0
;
i
<
A
.n_rows
;
i
++
){
for
(
int
j
=
0
;
j
<
A
.n_cols
;
j
++
){
myfile
<<
A
(
i
,
j
)
;
if
(
j
+
1
<
A
.n_cols
){
myfile
<<
", "
;
}
}
if
(
i
+
1
<
A
.n_rows
){
myfile
<<
";"
;
}
}
myfile
<<
"]"
;
}
void
toFileString(std::ofstream& myfile, double A)
{
myfile
<<
A
;
}
void
toFileString(std::ofstream& myfile, float A)
{
myfile
<<
A
;
}
void
toFileString(std::ofstream& myfile, int A)
{
myfile
<<
A
;
}
void
toFileString(std::ofstream& myfile, bool A)
{
myfile
<<
A
;
}
bool
Is_close(mat& X, mat& Y, double tol)
{
// abs returns a mat type then max checks columns and returns a row_vec
// max used again will return the biggest element in the row_vec
bool close(false);
if(arma::max(arma::max(arma::abs(X-Y))) < tol)
{
close
=
true
;
}
return close;
}
void
rangeValueCheck(double A, double lower, double upper)
{
REQUIRE
(
A
>=
lower
)
;
REQUIRE
(
A
<=
upper
)
;
}
void
rangeValueCheck(int A, double lower, double upper)
{
REQUIRE
(
A
>=
lower
)
;
REQUIRE
(
A
<=
upper
)
;
}
void
rangeValueCheck(mat& A, mat& lower , mat& upper)
{
REQUIRE
(
I
s_close
(
A
,
lower
,
0.0
001
))
;
REQUIRE
(
I
s_close
(
A
,
upper
,
0.0
001
))
;
}
<#
list
viewModel.streams as stream>
TEST_CASE
("${
stream
.name
}",
"[$
{
viewModel
.componentName
}
]")
{
mat
tmpA
;
mat
tmpB
;
$
{
viewModel
.componentName
}
component
;
std
::
ofstream
myfile
;
myfile
.open
(
"${stream.name}"
)
;
myfile
.precision
(
64
)
;
component
.init
()
;
<#
list
stream
.checks
as
check
>
<#
list
check
.inputPortName2Value
?
keys
as
portName
>
component
.$
{
portName
}
$
{
check
.inputPortName2Value
[
portName
]}
;
</#
list
>
component
.execute
()
;
<#
list
check
.outputPortName2Check
?
keys
as
outputPortName
>
<@
renderPortCheck
outputPortName
=
outputPortName
check
=
check
.outputPortName2Check
[
outputPortName
]
/>
</#
list
>
<#
list
stream
.outputPortNames
as
outputPortName
>
myfile
<<
"${outputPortName}: "
;
toFileString
(
myfile
,
component
.$
{
outputPortName
})
;
myfile
<<
"
\n
"
;
</#
list
>
</#
list
>
myfile
.close
()
;
std
::
cout
<<
"${stream.name}: success
\n
"
;
}
</#
list
>
#
endif
<#
macro
renderPortCheck outputPortName check>
<#
assign
portValue="component.$
{
outputPortName
}
">
<#
if
helper.isBooleanOutputPortCheck(check)>
<#if helper.isTrueExpectedCheck(check)>
REQUIRE( $
{
portValue
}
);
<#else>
REQUIRE_FALSE( $
{
portValue
}
);
</#if>
<#
elseif
helper.isRangeOutputPortCheck(check)>
<#if check.isMatrix??>
<#if check.isMatrix()>
tmpA = mat();
tmpA $
{
check
.lowerBound
}
;
tmpB = mat();
tmpB $
{
check
.upperBound
}
;
rangeValueCheck($
{
portValue
}
, tmpA , tmpB);
<#else>
rangeValueCheck($
{
portValue
}
, $
{
check
.lowerBound
}
, $
{
check
.upperBound
}
);
</#if>
<#else>
rangeValueCheck($
{
portValue
}
, $
{
check
.lowerBound
}
, $
{
check
.upperBound
}
);
</#if>
<#
else
>
</#
if
>
</#
macro
>
src/main/resources/vendor/catch.hpp
View file @
0d5b35e1
...
...
@@ -8,6 +8,7 @@
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
// start catch.hpp
...
...
@@ -12010,3 +12011,59 @@ using Catch::Detail::Approx;
// end catch.hpp
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
#ifndef _FILESTRING_CONVERSION___A
#define _FILESTRING_CONVERSION___A
#include
"armadillo.h"
using
namespace
arma
;
void
toFileString
(
std
::
ofstream
&
myfile
,
mat
A
){
myfile
<<
"["
;
for
(
int
i
=
0
;
i
<
A
.
n_rows
;
i
++
){
for
(
int
j
=
0
;
j
<
A
.
n_cols
;
j
++
){
myfile
<<
A
(
i
,
j
);
if
(
j
+
1
<
A
.
n_cols
){
myfile
<<
", "
;
}
}
if
(
i
+
1
<
A
.
n_rows
){
myfile
<<
";"
;
}
}
myfile
<<
"]"
;
}
void
toFileString
(
std
::
ofstream
&
myfile
,
double
A
){
myfile
<<
A
;
}
void
toFileString
(
std
::
ofstream
&
myfile
,
float
A
){
myfile
<<
A
;
}
void
toFileString
(
std
::
ofstream
&
myfile
,
int
A
){
myfile
<<
A
;
}
void
toFileString
(
std
::
ofstream
&
myfile
,
bool
A
){
myfile
<<
A
;
}
bool
Is_close
(
mat
&
X
,
mat
&
Y
,
double
tol
)
{
// abs returns a mat type then max checks columns and returns a row_vec
// max used again will return the biggest element in the row_vec
bool
close
(
false
);
if
(
arma
::
max
(
arma
::
max
(
arma
::
abs
(
X
-
Y
)))
<
tol
)
{
close
=
true
;
}
return
close
;
}
void
rangeValueCheck
(
double
A
,
double
lower
,
double
upper
){
REQUIRE
(
A
>=
lower
);
REQUIRE
(
A
<=
upper
);
}
void
rangeValueCheck
(
int
A
,
double
lower
,
double
upper
){
REQUIRE
(
A
>=
lower
);
REQUIRE
(
A
<=
upper
);
}
void
rangeValueCheck
(
mat
&
A
,
mat
&
lower
,
mat
&
upper
){
REQUIRE
(
Is_close
(
A
,
lower
,
0.0001
));
REQUIRE
(
Is_close
(
A
,
upper
,
0.0001
));
}
#endif
\ No newline at end of file
src/test/java/de/monticore/lang/monticar/generator/cpp/AutomaticStreamTestGenerationTest.java
View file @
0d5b35e1
...
...
@@ -233,6 +233,30 @@ public class AutomaticStreamTestGenerationTest extends AbstractSymtabTest {
"de.rwth.armin.modeling.autopilot.common.compass2CurrentDirectionTest1"
);
}
@Test
public
void
testLoggingExample1
()
throws
Exception
{
AutomaticStreamTestGenerator
generator
=
new
AutomaticStreamTestGenerator
();
generator
.
generateTests
(
""
,
"src/test/resources/emastudio/autopilot"
,
"N:/target/generated-sources-cpp/streamtest/autopilot/"
,
"1"
,
10
);
testGenCPPFilesAndExecWithExecLogging
(
"./target/generated-sources-cpp/streamtest"
,
"/autopilot"
,
"./src/test/resources/emastudio/autopilot"
,
"./target/generated-sources-cpp/streamtest/autopilot"
,
"de.rwth.armin.modeling.autopilot.motion.calculatePidError"
,
"de.rwth.armin.modeling.autopilot.motion.CalculatePidErrorTest1"
);
}
@Test
public
void
testLoggingExample2
()
throws
Exception
{
AutomaticStreamTestGenerator
generator
=
new
AutomaticStreamTestGenerator
();
generator
.
generateTests
(
""
,
"src/test/resources/emastudio/autopilot"
,
"N:/target/generated-sources-cpp/streamtest/autopilot/"
,
"1"
,
10
);
testGenCPPFilesAndExecWithExecLogging
(
"./target/generated-sources-cpp/streamtest"
,
"/autopilot"
,
"./src/test/resources/emastudio/autopilot"
,
"./target/generated-sources-cpp/streamtest/autopilot"
,
"de.rwth.armin.modeling.autopilot.motion.calculateEngineAndBrakes"
,
"de.rwth.armin.modeling.autopilot.motion.CalculateEngineAndBrakesTest1"
);
}
@Ignore
//Does not work in maven for some reason
@Test
public
void
testComponent
()
throws
Exception
{
...
...
@@ -273,6 +297,34 @@ public class AutomaticStreamTestGenerationTest extends AbstractSymtabTest {
StreamTestExecution
.
compileTests
(
targetFullPath
,
targetBasePath
);
StreamTestExecution
.
executeTests
(
targetBasePath
);
}
public
void
testGenCPPFilesAndExecWithExecLogging
(
String
targetBasePath
,
String
targetRestPath
,
String
modelDirectory
,
String
outputDirectory
,
String
fullComponentInstanceName
,
String
fullStreamTestName
)
throws
Exception
{
String
targetFullPath
=
targetBasePath
+
targetRestPath
;
String
fullStreamTestPathName
=
fullStreamTestName
.
replaceAll
(
"\\."
,
"\\/"
);
String
args
[]
=
{
"--models-dir="
+
outputDirectory
,
"--output-dir="
+
outputDirectory
,
"--root-model="
+
fullComponentInstanceName
,
"--flag-generate-tests"
,
"--flag-use-armadillo-backend"
,
"--flag-use-exec-logging"
};
File
srcDir
=
new
File
(
modelDirectory
);
File
destDir
=
new
File
(
outputDirectory
);
FileUtils
.
copyDirectory
(
srcDir
,
destDir
);
GeneratorCppCli
.
main
(
args
);
StreamTestExecution
.
compileTests
(
targetFullPath
,
targetBasePath
);
StreamTestExecution
.
executeTests
(
targetBasePath
);
//Execute again to check if tests pass
StreamTestModifier
.
updateStreamTestWithResults
(
"N:/target/generated-sources-cpp/streamtest/"
+
targetRestPath
+
"/"
+
fullStreamTestPathName
+
".stream"
,
"N:/target/generated-sources-cpp/streamtest/exec/"
+
fullStreamTestName
);
GeneratorCppCli
.
main
(
args
);
StreamTestExecution
.
compileTests
(
targetFullPath
,
targetBasePath
);
StreamTestExecution
.
executeTests
(
targetBasePath
);
}
//Maybe add test that executes all stream tests in the resource dir(will take longer than an hour to execute) later
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment