From c536254e6a5d2087e896d1fae7c4948ee888d4c5 Mon Sep 17 00:00:00 2001
From: Florian Hoelzl <hoelzl@fortiss.org>
Date: Tue, 10 Oct 2017 10:00:55 +0000
Subject: [PATCH] Generating main.c works for an initial version. refs 3079

---
 .../executable/HeaderCopyGenerator.java       | 68 +++++++++++++
 .../generator/executable/MainGenerator.java   | 51 ++++++++++
 .../executable/RaspberryPIExecutable.java     | 14 ++-
 .../generator/templates/ConfigureFile.stg     |  4 +-
 .../generator/templates/MainFile.stg          | 97 +++++++++++++++++++
 .../generator/templates/MakedefsFile.stg      |  5 +-
 .../generator/templates/ProjectFile.stg       |  4 +-
 .../generator/templates/RasPiCTemplates.java  | 21 +++-
 8 files changed, 256 insertions(+), 8 deletions(-)
 create mode 100644 org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/HeaderCopyGenerator.java
 create mode 100644 org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/MainGenerator.java
 create mode 100644 org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MainFile.stg

diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/HeaderCopyGenerator.java b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/HeaderCopyGenerator.java
new file mode 100644
index 00000000..91c0ca31
--- /dev/null
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/HeaderCopyGenerator.java
@@ -0,0 +1,68 @@
+/*--------------------------------------------------------------------------+
+$Id$
+|                                                                          |
+| Copyright 2017 fortiss GmbH                     |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.af3.platform.raspberry.generator.executable;
+
+import static org.fortiss.af3.generator.common.utils.SourceModelElementFactory.createByteContentUnitForPluginFile;
+
+import org.fortiss.af3.generator.common.model.c.CSourcePackage;
+import org.fortiss.af3.generator.common.model.source.ByteContentUnit;
+import org.fortiss.af3.platform.raspberry.AF3PlatformRaspberryActivator;
+
+/**
+ * Class for copying the header files to the target folder.
+ * 
+ * @author hoelzl
+ * @author $Author$
+ * @version $Rev$
+ * @ConQAT.Rating RED Hash:
+ */
+final class HeaderCopyGenerator {
+	/** Adds the header files to the given target {@link CSourcePackage}. */
+	public static void copyHeaderFiles(CSourcePackage incLibPack) throws Exception {
+		incLibPack.addUnit(copyAF3Hal("af3.h"));
+		incLibPack.addUnit(copyAF3Hal("cancatalog.h"));
+		incLibPack.addUnit(copyAF3Hal("caninbox.h"));
+		incLibPack.addUnit(copyAF3Hal("canoutbox.h"));
+		incLibPack.addUnit(copyAF3Hal("cansocket.h"));
+		incLibPack.addUnit(copyAF3Hal("canthread.h"));
+		incLibPack.addUnit(copyAF3Hal("debugprint.h"));
+		incLibPack.addUnit(copyAF3Hal("gamepad.h"));
+		incLibPack.addUnit(copyAF3Hal("protocol_can.h"));
+		incLibPack.addUnit(copyAF3Hal("protocol_control_center.h"));
+		incLibPack.addUnit(copyAF3Hal("protocol_coordinator.h"));
+		incLibPack.addUnit(copyAF3Hal("protocol_factory.h"));
+		incLibPack.addUnit(copyAF3Hal("protocol_worker.h"));
+		incLibPack.addUnit(copyAF3Hal("timeutil.h"));
+	}
+
+	/** Copies the AF3 HAL header file. */
+	private static ByteContentUnit copyAF3Hal(String header) throws Exception {
+		return copyHeader("af3pihal/", header);
+	}
+
+	/** Copies the brick header file. */
+	private static ByteContentUnit copyBrick(String header) throws Exception {
+		return copyHeader("brick/", header);
+	}
+
+	/** Copies the header file from the plugin path. */
+	private static ByteContentUnit copyHeader(String subDir, String headerName) throws Exception {
+		return createByteContentUnitForPluginFile(AF3PlatformRaspberryActivator.PLUGIN_ID,
+				"code-gen-hal/inc/" + subDir, headerName, false);
+	}
+}
diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/MainGenerator.java b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/MainGenerator.java
new file mode 100644
index 00000000..a8a8c444
--- /dev/null
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/MainGenerator.java
@@ -0,0 +1,51 @@
+/*--------------------------------------------------------------------------+
+$Id$
+|                                                                          |
+| Copyright 2017 fortiss GmbH                     |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.af3.platform.raspberry.generator.executable;
+
+import static org.fortiss.af3.platform.raspberry.generator.templates.RasPiCTemplates.getMainCFile;
+
+import java.util.List;
+
+import org.conqat.lib.commons.collections.Pair;
+import org.fortiss.af3.component.model.Component;
+import org.fortiss.af3.component.model.Port;
+import org.fortiss.af3.generator.common.model.source.AbstractUnit;
+import org.fortiss.af3.platform.model.ExecutionUnit;
+import org.fortiss.af3.platform.model.PlatformConnectorUnit;
+import org.fortiss.af3.platform.raspberry.model.RaspberryPi;
+import org.fortiss.tooling.kernel.extension.data.ITransformationContext;
+
+/**
+ * Separate class for generating the main.c file.
+ * 
+ * @author hoelzl
+ * @author $Author$
+ * @version $Rev$
+ * @ConQAT.Rating RED Hash:
+ */
+class MainGenerator {
+	/** Creates the main.c file. */
+	public AbstractUnit createMain(RaspberryPi executionUnit,
+			List<Pair<ExecutionUnit, Component>> deployedComponents,
+			List<Pair<PlatformConnectorUnit, Port>> deployedPorts, ITransformationContext context) {
+		// TODO: generate worker and syncbox code
+		return getMainCFile(executionUnit.getName(), executionUnit.isCoordinatorUnit(),
+				executionUnit.getCanCoordinationID(), executionUnit.getCycleTime(), 250,
+				"// TODO\n", "// TODO\n");
+	}
+}
diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/RaspberryPIExecutable.java b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/RaspberryPIExecutable.java
index b1ee77a3..80041c8c 100644
--- a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/RaspberryPIExecutable.java
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/executable/RaspberryPIExecutable.java
@@ -21,6 +21,7 @@ import static org.fortiss.af3.expression.utils.ExpressionModelElementFactory.cre
 import static org.fortiss.af3.generator.common.utils.CLanguageModelElementFacade.addUserHeaderInclude;
 import static org.fortiss.af3.generator.common.utils.CLanguageModelElementFactory.createCSourcePackage;
 import static org.fortiss.af3.generator.common.utils.SourceModelElementFactory.createByteContentUnitForPluginFile;
+import static org.fortiss.af3.platform.raspberry.generator.executable.HeaderCopyGenerator.copyHeaderFiles;
 import static org.fortiss.af3.platform.raspberry.generator.templates.RasPiCTemplates.getConfigureFile;
 import static org.fortiss.af3.platform.raspberry.generator.templates.RasPiCTemplates.getEclipseProjectFile;
 import static org.fortiss.af3.platform.raspberry.generator.templates.RasPiCTemplates.getMakedefsFile;
@@ -64,7 +65,7 @@ public class RaspberryPIExecutable extends ExecutionUnitExecutableBase<Raspberry
 	/** Folder name for library source files. */
 	private static final String SRC_LIB_SUB_PACKAGE_NAME = "src-lib";
 	/** Folder name for library include files. */
-	private static final String INC_LIB_SUB_PACKAGE_NAME = "inc-lib";
+	public static final String INC_LIB_SUB_PACKAGE_NAME = "inc-lib";
 	/** Folder name for linkable static library files. */
 	private static final String LIB_SUB_PACKAGE_NAME = "lib";
 
@@ -87,6 +88,7 @@ public class RaspberryPIExecutable extends ExecutionUnitExecutableBase<Raspberry
 			addEclipseCProjectFiles(sourcePackage, modelElement.getName());
 			addStaticLibraries(sourcePackage);
 			addConfigureAndMakedefsFiles(sourcePackage, modelElement.getName());
+			addMainFile(sourcePackage, deployedComponents, deployedPorts, context);
 		} catch(Exception ex) {
 			error(AF3PlatformRaspberryActivator.getDefault(), ex.getMessage(), ex);
 			ex.printStackTrace();
@@ -94,6 +96,15 @@ public class RaspberryPIExecutable extends ExecutionUnitExecutableBase<Raspberry
 		return sourcePackage;
 	}
 
+	/** Creates the main file by using the {@link MainGenerator} helper class. */
+	private void addMainFile(CSourcePackage sourcePackage,
+			List<Pair<ExecutionUnit, Component>> deployedComponents,
+			List<Pair<PlatformConnectorUnit, Port>> deployedPorts, ITransformationContext context) {
+		CSourcePackage srcGenPack = (CSourcePackage)sourcePackage.getSrcGenPackage();
+		MainGenerator mg = new MainGenerator();
+		srcGenPack.addUnit(mg.createMain(modelElement, deployedComponents, deployedPorts, context));
+	}
+
 	/** Adds the build process files: configure and Makedefs. */
 	private void addConfigureAndMakedefsFiles(CSourcePackage sourcePackage, String binaryName) {
 		sourcePackage.addUnit(getConfigureFile(binaryName));
@@ -117,6 +128,7 @@ public class RaspberryPIExecutable extends ExecutionUnitExecutableBase<Raspberry
 		sourcePackage.getSubPackages().add(lib);
 		lib.addUnit(getStaticLibraryUnit("libbrick.a"));
 		lib.addUnit(getStaticLibraryUnit("libaf3pihal.a"));
+		copyHeaderFiles(incLib);
 	}
 
 	/** Creates a {@link ByteContentUnit} for the given static library. */
diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ConfigureFile.stg b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ConfigureFile.stg
index b218b7ba..9357649f 100644
--- a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ConfigureFile.stg
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ConfigureFile.stg
@@ -1,10 +1,10 @@
 group ConfigureFile;
 
-ConfigureFile(binary) ::= <<
+ConfigureFile(UNIT_NAME) ::= <<
 #!/bin/sh
 
 # The application's name.
-APPL="$binary$";
+APPL="$UNIT_NAME$";
 
 # The root path for this script.
 if [ -z "\$ROOT" ]; then ROOT="."; fi;
diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MainFile.stg b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MainFile.stg
new file mode 100644
index 00000000..4eeca49f
--- /dev/null
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MainFile.stg
@@ -0,0 +1,97 @@
+group MainFile;
+
+MainFile(UNIT_NAME,
+	COORDINATOR_OR_WORKER,
+	CAN_ID_UNIT_DONE,
+	CYCLE_TIME_IN_MILLIS,
+	WAITING_SLEEPTIME_IN_MICROS,
+	SYNC_BOX_SETUP_CODE,
+	WORKER_CODE) ::= <<
+#include <stdbool.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include <af3.h>
+#include <cancatalog.h>
+#include <caninbox.h>
+#include <canoutbox.h>
+#include <debugprint.h>
+#include <protocol_control_center.h>
+#include <protocol_coordinator.h>
+#include <protocol_factory.h>
+
+#define WAITING_SLEEPTIME_IN_MICROS		(uint64_t)$WAITING_SLEEPTIME_IN_MICROS$
+
+#define STOP_AT_LOGICAL_CLOCK			(uint64_t)0 // run infinitely
+
+#define BRICK_HOST "localhost"
+#define BRICK_PORT 4223
+
+#define CAN_ID_GLOBAL_SHUTDOWN			0x00
+#define CAN_ID_COORDINATOR_CLOCK		0x01
+#define CAN_ID_UNIT_DONE				$CAN_ID_UNIT_DONE$
+
+static const char* can_device = "can0";
+static can_inbox_t* app_inbox = NULL;
+static can_inbox_t* sync_inbox= NULL;
+static can_outbox_t* app_outbox = NULL;
+
+static uint64_t step = 0;
+
+static void worker() {
+	step++;
+	$WORKER_CODE$
+}
+
+int main(int argc, char** argv) {
+	// initialize CAN interface with catalog implementation
+	can_catalog_initialize(can_device, $WAITING_SLEEPTIME_IN_MICROS$);
+
+	// set AF3 unit name used when communicating with CC
+	af3_set_execution_unit_identifier("$UNIT_NAME$");
+	// TODO: initialize ControlCenter connection
+
+	// snychronization message box
+	sync_inbox = can_inbox_create("$UNIT_NAME$_sync_inbox", 2);
+	$SYNC_BOX_SETUP_CODE$
+
+	// application message boxes
+	app_inbox = can_inbox_create("$UNIT_NAME$_app_inbox", 1);
+	app_outbox = can_outbox_create("$UNIT_NAME$_sensor_app_outbox");
+
+	protocol_can_config_t* can_config = protocol_can_config_create(
+			$CAN_ID_UNIT_DONE$,
+			CAN_ID_COORDINATOR_CLOCK,
+			CAN_ID_GLOBAL_SHUTDOWN);
+
+	protocol_worker_clock_config_t* clock_config = protocol_worker_clock_config_create(
+			$CYCLE_TIME_IN_MILLIS$,
+			STOP_AT_LOGICAL_CLOCK,
+			$WAITING_SLEEPTIME_IN_MICROS$);
+
+	protocol_worker_computation_config_t* computation_config = protocol_worker_computation_config_create(
+			"$UNIT_NAME$",
+			worker,
+			sync_inbox,
+			app_inbox,
+			app_outbox,
+			0);
+
+#if $COORDINATOR_OR_WORKER$
+	int result = protocol_coordinator_main(can_config, clock_config, computation_config);
+#else
+	int result = protocol_worker_main(can_config, clock_config, computation_config);
+#endif
+	debug_print(DEBUG_PRINT_LEVEL_NONE, "$UNIT_NAME$ main() returned %i.\n", result);
+
+	// clean up
+	can_inbox_destroy(sync_inbox);
+	can_inbox_destroy(app_inbox);
+	can_outbox_destroy(app_outbox);
+	free(can_config);
+	free(clock_config);
+	free(computation_config);
+
+	return result;
+}
+>>
diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MakedefsFile.stg b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MakedefsFile.stg
index 8ac69bc8..6d2f56de 100644
--- a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MakedefsFile.stg
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/MakedefsFile.stg
@@ -48,5 +48,8 @@ clean:
 \${BPATH}/%.run:
 	@echo "linking application '\${@}' ..."
 	@\${CROSSLD} \${LDFLAGS} -o \${@} \$(filter %.o %.a, \${^})
-
+	
+# The rule to clean and remove generated Makefile
+mrproper: clean
+	@rm -f Makefile
 >>
diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ProjectFile.stg b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ProjectFile.stg
index 743d23b1..cd3d18c3 100644
--- a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ProjectFile.stg
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/ProjectFile.stg
@@ -1,9 +1,9 @@
 group ProjectFile;
 
-ProjectFile(projectname) ::= <<
+ProjectFile(PROJECT_NAME) ::= <<
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>$projectname$</name>
+	<name>$PROJECT_NAME$</name>
 	<comment></comment>
 	<projects>
 	</projects>
diff --git a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/RasPiCTemplates.java b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/RasPiCTemplates.java
index 6cf4b58d..7eeb36d8 100644
--- a/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/RasPiCTemplates.java
+++ b/org.fortiss.af3.platform.raspberry/trunk/src/org/fortiss/af3/platform/raspberry/generator/templates/RasPiCTemplates.java
@@ -39,10 +39,27 @@ import org.fortiss.af3.generator.common.model.source.StaticContentSourceUnit;
  * @ConQAT.Rating RED Hash:
  */
 public final class RasPiCTemplates {
+	/** Returns the 'main.c' file configured using the given arguments. */
+	public static AbstractUnit getMainCFile(String unitName, boolean coordinatorOrWorker,
+			int canIdUnitDone, int cycletimeInMillis, int waitingSleepInMicros,
+			String syncBoxSetupCode, String workerCode) {
+		StringTemplate template = makeTemplate("MainFile.stg", "MainFile");
+		template.setAttribute("UNIT_NAME", unitName);
+		template.setAttribute("COORDINATOR_OR_WORKER", coordinatorOrWorker ? 1 : 0);
+		template.setAttribute("CAN_ID_UNIT_DONE", canIdUnitDone);
+		template.setAttribute("CYCLE_TIME_IN_MILLIS", cycletimeInMillis);
+		template.setAttribute("WAITING_SLEEPTIME_IN_MICROS", waitingSleepInMicros);
+		template.setAttribute("SYNC_BOX_SETUP_CODE", syncBoxSetupCode);
+		template.setAttribute("WORKER_CODE", workerCode);
+		StaticContentSourceUnit unit =
+				createStaticContentSourceUnit("main.c", template.toString(), false);
+		return unit;
+	}
+
 	/** Returns the '.project' file used for Eclipse project. */
 	public static AbstractUnit getEclipseProjectFile(String projectName) {
 		StringTemplate template = makeTemplate("ProjectFile.stg", "ProjectFile");
-		template.setAttribute("projectname", projectName);
+		template.setAttribute("PROJECT_NAME", projectName);
 		StaticContentSourceUnit unit =
 				createStaticContentSourceUnit(".project", template.toString(), false);
 		return unit;
@@ -51,7 +68,7 @@ public final class RasPiCTemplates {
 	/** Returns the 'configure' file used to create a Makefile. */
 	public static AbstractUnit getConfigureFile(String binaryName) {
 		StringTemplate template = makeTemplate("ConfigureFile.stg", "ConfigureFile");
-		template.setAttribute("binary", binaryName);
+		template.setAttribute("UNIT_NAME", binaryName);
 		return createStaticContentSourceUnit("configure", template.toString(), true);
 	}
 
-- 
GitLab