/* * Copyright (c) 2009-2011, IETR/INSA of Rennes * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the IETR/INSA of Rennes nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package net.sf.orcc.backends; import static net.sf.orcc.OrccActivator.getDefault; import static net.sf.orcc.OrccLaunchConstants.BACKEND; import static net.sf.orcc.OrccLaunchConstants.CLASSIFY; import static net.sf.orcc.OrccLaunchConstants.COMPILE_XDF; import static net.sf.orcc.OrccLaunchConstants.DEBUG_MODE; import static net.sf.orcc.OrccLaunchConstants.DEFAULT_DEBUG; import static net.sf.orcc.OrccLaunchConstants.DEFAULT_FIFO_SIZE; import static net.sf.orcc.OrccLaunchConstants.ENABLE_TRACES; import static net.sf.orcc.OrccLaunchConstants.FIFO_SIZE; import static net.sf.orcc.OrccLaunchConstants.MAPPING; import static net.sf.orcc.OrccLaunchConstants.MERGE_ACTIONS; import static net.sf.orcc.OrccLaunchConstants.MERGE_ACTORS; import static net.sf.orcc.OrccLaunchConstants.NO_LIBRARY_EXPORT; import static net.sf.orcc.OrccLaunchConstants.OUTPUT_FOLDER; import static net.sf.orcc.OrccLaunchConstants.PROJECT; import static net.sf.orcc.OrccLaunchConstants.TRACES_FOLDER; import static net.sf.orcc.OrccLaunchConstants.XDF_FILE; import static net.sf.orcc.backends.BackendsConstants.ADDITIONAL_TRANSFOS; import static net.sf.orcc.backends.BackendsConstants.CONVERT_MULTI2MONO; import static net.sf.orcc.backends.BackendsConstants.LLVM_TARGET_DATALAYOUT; import static net.sf.orcc.backends.BackendsConstants.LLVM_TARGET_TRIPLE; import static net.sf.orcc.backends.BackendsConstants.NEW_SCHEDULER; import static net.sf.orcc.backends.BackendsConstants.PAPIFY; import static net.sf.orcc.backends.BackendsConstants.PROFILE; import static net.sf.orcc.backends.BackendsConstants.TTA_PROCESSORS_CONFIGURATION; import static net.sf.orcc.backends.BackendsConstants.LINK_NATIVE_LIBRARY; import static net.sf.orcc.backends.BackendsConstants.LINK_NATIVE_LIBRARY_FOLDER; import static net.sf.orcc.backends.BackendsConstants.LINK_NATIVE_LIBRARY_HEADERS; import static net.sf.orcc.preferences.PreferenceConstants.P_SOLVER; import static net.sf.orcc.preferences.PreferenceConstants.P_SOLVER_OPTIONS; import static net.sf.orcc.util.OrccUtil.getFile; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.orcc.OrccRuntimeException; import net.sf.orcc.backends.util.Validator; import net.sf.orcc.df.Actor; import net.sf.orcc.df.Instance; import net.sf.orcc.df.Network; import net.sf.orcc.df.util.DfVisitor; import net.sf.orcc.df.util.NetworkValidator; import net.sf.orcc.graph.Vertex; import net.sf.orcc.ir.util.ValueUtil; import net.sf.orcc.util.FilesManager; import net.sf.orcc.util.OrccLogger; import net.sf.orcc.util.OrccUtil; import net.sf.orcc.util.Result; import net.sf.orcc.util.util.EcoreHelper; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.apache.commons.cli.UnrecognizedOptionException; import org.apache.commons.lang.StringUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; import org.osgi.framework.Bundle; /** * <p> * This class is an abstract implementation of {@link Backend}. It supports * standard back-ends to generate code from a network and its (instantiated or * not children). It also can be used to produce a Video Tool Library (VTL) from * CAL projects. To do so, simply use {@link #AbstractBackend(boolean)} * signature in the constructor of the concrete back-end class. signature. * </p> * * <p> * When a back-end is launched, the method {@link #setOptions(Map)} is called to * configure back-end options, then {@link #compile(IProgressMonitor)} calls all * the methods required to transform the IR, validate the result, generate the * target code and extract the required libraries. * </p> * * <p> * The following methods may be extended by back-ends depending on their needs. * </p> * * <ul> * <li>{@link #doInitializeOptions()} is called at the end of * {@link #setOptions(Map)} to initialize some member variables. It is also used * to fill transformations maps {@link #networkTransfos} and * {@link #childrenTransfos}.</li> * </ul> * <p> * Then the full compilation is run: * </p> * <ol> * <li>{@link #doValidate(Network)} checks some constraints on the given network * </li> * <li>{@link #beforeGeneration(Network)} can be used to perform some additional * operations</li> * <li>{@link #doGenerateNetwork(Network)} produces code from the given network * </li> * <li>{@link #doAdditionalGeneration(Network)} can be used to generate other * files from the given network</li> * <li>{@link #beforeGeneration(Actor)} or {@link #beforeGeneration(Instance)} * </li> * <li>{@link #doGenerateActor(Actor)} or {@link #doGenerateInstance(Instance)} * </li> * <li>{@link #doAdditionalGeneration(Actor)} or * {@link #doAdditionalGeneration(Instance)}</li> * </ol> * * @author Matthieu Wipliez * @author Antoine Lorence * */ public abstract class AbstractBackend implements Backend, IApplication { /** * Indicates that this is a VTL back-end or not (i.e. a standard back-end). */ private boolean isVTLBackend; /** * Indicates that the back-end has been launched in debug mode or not */ protected boolean debug; /** * Fifo size used in back-end. */ protected int fifoSize; /** * Contains mapping information configured before back-end launch. Key is * the name of an instance, value is a core identifier. */ protected Map<String, String> mapping; /** * List of transformations to apply on each network */ protected List<DfVisitor<?>> networkTransfos; /** * List of transformations to apply on each child. */ protected List<DfVisitor<?>> childrenTransfos; /** * Options of back-end execution. Its content can be manipulated with * {@link #getOption} methods. */ private Map<String, Object> options; // Other options protected boolean classify; protected boolean mergeActions; protected boolean mergeActors; protected boolean convertMulti2Mono; /** * Path where output files will be written */ protected String outputPath; /** * Represents the project where application to build is located */ protected IProject project; /** * Common ResourceSet can be used by concrete back-ends if needed */ protected ResourceSet currentResourceSet; /** * the progress monitor */ protected IProgressMonitor monitor; /** * Construct a new standard back-end. */ public AbstractBackend() { this(false); } /** * Construct a new back-end instance. * * @param isVTLBackend * Set to true if this back-end will generate a complete VTL. */ public AbstractBackend(boolean isVTLBackend) { networkTransfos = new ArrayList<DfVisitor<?>>(); childrenTransfos = new ArrayList<DfVisitor<?>>(); this.isVTLBackend = isVTLBackend; } /** * Calculate the time elapsed between the given <em>t0</em> and the current * timestamp. * * @return The number of seconds, as a float */ final private float getDuration(long t0) { return (float) (System.currentTimeMillis() - t0) / 1000; } @Override public void compile(IProgressMonitor progressMonitor) { // New ResourceSet for a new compilation currentResourceSet = new ResourceSetImpl(); // Initialize the monitor. Can be used to stop the back-end // execution and provide feedback to user monitor = progressMonitor; // Does code generation at network level should happen ? boolean compileXdf = getOption(COMPILE_XDF, false); // ----------------------------------------------------- // Configure the console log header // ----------------------------------------------------- String orccVersion = "<unknown>"; Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID); if (bundle != null) { orccVersion = bundle.getHeaders().get("Bundle-Version"); } String backendName = getOption(BACKEND, "<unknown>"); OrccLogger.traceln("*********************************************" + "************************************"); OrccLogger.traceln("* Orcc version: " + orccVersion); OrccLogger.traceln("* Backend: " + backendName); OrccLogger.traceln("* Project: " + project.getName()); if (compileXdf) { String topNetwork = getOption(XDF_FILE, "<unknown>"); OrccLogger.traceln("* Network: " + topNetwork); } OrccLogger.traceln("* Output folder: " + outputPath); OrccLogger.traceln("*********************************************" + "************************************"); // ----------------------------------------------------- // Libraries files export // ----------------------------------------------------- // If user checked the option "Don't export library", the method // extractLibraries() must not be called if (!getOption(NO_LIBRARY_EXPORT, false)) { stopIfRequested(); final long t0 = System.currentTimeMillis(); final Result result = doLibrariesExtraction(); if (!result.isEmpty()) { OrccLogger.traceln("Library export done in " + getDuration(t0) + "s"); } } // ----------------------------------------------------- // Network level code generation // ----------------------------------------------------- final Network network; final String networkQName = getOption(XDF_FILE, ""); final IFile xdfFile = getFile(project, networkQName, OrccUtil.NETWORK_SUFFIX); if (xdfFile == null) { throw new OrccRuntimeException( "Unable to find the XDF file " + "corresponding to the network " + networkQName + "."); } else { network = EcoreHelper.getEObject(currentResourceSet, xdfFile); } if (compileXdf) { if (network == null) { throw new OrccRuntimeException("The input file seems to not contains any network"); } beforeTransformations(network); if (!networkTransfos.isEmpty()) { stopIfRequested(); OrccLogger.traceln("Network transformations"); final long t0 = System.currentTimeMillis(); applyTransformations(network, networkTransfos, debug); OrccLogger.traceln("Done in " + getDuration(t0) + "s"); } stopIfRequested(); beforeGeneration(network); stopIfRequested(); OrccLogger.traceln("Network validation"); doValidate(network); stopIfRequested(); OrccLogger.traceln("Network generation"); final long t0 = System.currentTimeMillis(); final Result result = doGenerateNetwork(network); result.merge(doAdditionalGeneration(network)); OrccLogger.traceln("Done in " + getDuration(t0) + "s. " + result); } // ----------------------------------------------------- // VTL back-ends code generation // ----------------------------------------------------- if (isVTLBackend) { stopIfRequested(); OrccLogger.traceln("Compute the list of actors to generate"); List<IFolder> projectsFolders = OrccUtil.getOutputFolders(project); List<IFile> irFiles = OrccUtil.getAllFiles(OrccUtil.IR_SUFFIX, projectsFolders); OrccLogger.traceln("Parsing " + irFiles.size() + " IR files"); List<Actor> actors = new ArrayList<Actor>(); for (IFile file : irFiles) { final EObject eObject = EcoreHelper.getEObject(currentResourceSet, file); // do not add units if (eObject instanceof Actor) { actors.add((Actor) eObject); } } OrccLogger.traceln(actors.size() + " actors will be added to the VTL (other IR files are units)"); if (!childrenTransfos.isEmpty()) { stopIfRequested(); OrccLogger.traceln("Actors transformations"); final long t0 = System.currentTimeMillis(); applyTransformations(actors, childrenTransfos, debug); OrccLogger.traceln("Done in " + getDuration(t0) + "s"); } stopIfRequested(); OrccLogger.traceln("Actors generation"); final long t0 = System.currentTimeMillis(); final Result result = Result.newInstance(); for (final Actor actor : actors) { beforeGeneration(actor); result.merge(doGenerateActor(actor)); result.merge(doAdditionalGeneration(actor)); } OrccLogger.traceln("Done in " + getDuration(t0) + "s. " + result); } // ----------------------------------------------------- // Standard back-ends children level code generation // ----------------------------------------------------- else { if (!childrenTransfos.isEmpty()) { stopIfRequested(); OrccLogger.traceln("Children transformations"); final long t0 = System.currentTimeMillis(); applyTransformations(network.getAllActors(), childrenTransfos, debug); OrccLogger.traceln("Done in " + getDuration(t0) + "s"); } stopIfRequested(); OrccLogger.traceln("Children generation"); final long t0 = System.currentTimeMillis(); final Result result = Result.newInstance(); for (final Vertex vertex : network.getChildren()) { stopIfRequested(); final Instance instance = vertex.getAdapter(Instance.class); final Actor actor = vertex.getAdapter(Actor.class); if (instance != null) { beforeGeneration(instance); result.merge(doGenerateInstance(instance)); result.merge(doAdditionalGeneration(instance)); } else if (actor != null) { beforeGeneration(actor); result.merge(doGenerateActor(actor)); result.merge(doAdditionalGeneration(actor)); } } OrccLogger.traceln("Done in " + getDuration(t0) + "s. " + result); } // ----------------------------------------------------- // After Code generation for Network // ----------------------------------------------------- afterGeneration(network); OrccLogger.traceln("Orcc backend done."); } /** * Validate the network. The default implementation calls * {@link Validator#checkTopLevel(Network)} and * {@link Validator#checkMinimalFifoSize(Network, int)} * * @param network */ protected void doValidate(Network network) { Validator.checkTopLevel(network); Validator.checkMinimalFifoSize(network, fifoSize); new NetworkValidator().doSwitch(network); } /** * Called by {@link #setOptions(Map)} when options are initialized. This * method must be implemented by back-end to set specific member variables * and additional back-end specific options. */ abstract protected void doInitializeOptions(); /** * Callback called before network generation, just after network * transformations. It can be used to perform additional transformations, * validations, or other operations at network level. * * @param network */ protected void beforeGeneration(final Network network) { // Does nothing by default } /** * Callback called before network transformations. It can be used to perform * initial validations, or other operations at network level. * * @param network */ protected void beforeTransformations(final Network network) { // Does nothing by default } /** * Callback called after network and instance/actor generation. It can be * used to perform additional code generation. * * @param network */ protected Result afterGeneration(final Network network) { return Result.newInstance(); } /** * This method may be implemented by subclasses to do the code generation at * network level. * * @param network * a network * @return The generation Result object */ protected Result doGenerateNetwork(Network network) { return Result.newInstance(); } /** * Can be overridden in back-ends to generates files at network level, but * not directly related to the network itself. * * @param network * @return The generation Result object */ protected Result doAdditionalGeneration(final Network network) { return Result.newInstance(); } /** * <p> * This method may be implemented in concrete back-ends if some runtime * libraries files have to be extracted while code generation. * </p> * * <p> * This method is called from {@link #compile()} only if user didn't check * the back-end option "Don't export library". * </p> * * @return A Result instance representing the number of files really written * to the disk and the number cached (not written because already * up-to-date) */ protected Result doLibrariesExtraction() { return Result.newInstance(); } /** * Apply given <em>transformations</em> on given <em>objects</em>. * * @param objects * @param transformations * @param validate * Indicates that transformation result must be validated */ final protected <T extends EObject> void applyTransformations(Iterable<T> objects, Iterable<DfVisitor<?>> transformations, boolean validate) { for (final T object : objects) { applyTransformations(object, transformations, validate); } } /** * Apply given <em>transformations</em> on given <em>object</em>. * * @param object * @param transformations * @param validate * Indicates that transformation result must be validated */ final protected void applyTransformations(EObject object, Iterable<DfVisitor<?>> transformations, boolean validate) { for (final DfVisitor<?> transformation : transformations) { transformation.doSwitch(object); if (validate) { OrccUtil.validateObject(transformation + " on " + object, object); } } } /** * Returns the boolean-valued option with the given name. Returns the given * default value if the option is undefined. * * @param optionName * the name of the option * @param defaultValue * the value to use if no value is found * @return the value or the fallback default value */ final public boolean getOption(String optionName, boolean defaultValue) { Object obj = options.get(optionName); if (obj instanceof Boolean) { return (Boolean) obj; } else { return defaultValue; } } /** * Returns the integer-valued option with the given name. Returns the given * default value if the option is undefined. * * @param optionName * the name of the option * @param defaultValue * the value to use if no value is found * @return the value or the fallback default value */ final public int getOption(String optionName, int defaultValue) { Object obj = options.get(optionName); if (obj instanceof Integer) { return (Integer) obj; } else { return defaultValue; } } /** * Returns the map-valued option with the given name. Returns the given * default value if the option is undefined. * * @param optionName * the name of the option * @param defaultValue * the value to use if no value is found * @return the value or the fallback default value */ @SuppressWarnings("unchecked") final public Map<String, String> getOption(String optionName, Map<String, String> defaultValue) { Object obj = options.get(optionName); if (obj instanceof Map<?, ?>) { return (Map<String, String>) obj; } else { return defaultValue; } } /** * Returns the string-valued option with the given name. Returns the given * default value if the option is undefined. * * @param optionName * the name of the option * @param defaultValue * the value to use if no value is found * @return the value or the fallback default value */ final public String getOption(String optionName, String defaultValue) { Object obj = options.get(optionName); if (obj instanceof String) { return (String) obj; } else { return defaultValue; } } /** * Returns a map containing the back-end options in this launch * configuration. Returns an empty map if the back-end configuration has no * options. * * @return a map of options keys and values. */ final public Map<String, Object> getOptions() { return options; } /** * Check the current ProgressMonitor for cancellation, and throws a * OperationCanceledException if needed. This will simply stop the back-end * execution. */ private void stopIfRequested() { if (monitor != null) { if (monitor.isCanceled()) { throw new OperationCanceledException(); } } } /** * Callback called before actor generation, just after actors * transformations. It can be used to perform additional transformations, * validations, or other operations at actor level. * * @param actor */ protected void beforeGeneration(final Actor actor) { // Does nothing by default } /** * This method may be implemented by subclasses to do the code generation at * actor level. It will automatically be called at code generation time by * VTL back-ends and by standard back-ends (if network has been fully * instantiated). * * @param actor * an actor * @see #doAdditionalGeneration(Actor) * @return The generation Result object */ protected Result doGenerateActor(final Actor actor) { return Result.newInstance(); } /** * This method may be implemented by subclasses to do additional generation * at actor level. * * @param actor * an actor * @return The generation Result object */ protected Result doAdditionalGeneration(final Actor actor) { return Result.newInstance(); } /** * Callback called before instance generation, just after instances * transformations. It can be used to perform additional transformations, * validations, or other operations at instance level. * * @param instance */ protected void beforeGeneration(final Instance instance) { // Does nothing by default } /** * This method may be implemented by subclasses to do the code generation at * instance level. It will automatically be called at code generation time * by standard back-ends. * * @param instance * an instance * @see #doAdditionalGeneration(Actor) * @return The generation Result object */ protected Result doGenerateInstance(final Instance instance) { return Result.newInstance(); } /** * This method may be implemented by subclasses to do additional generation * at instance level. * * @param instance * an instance * @return The generation Result object */ protected Result doAdditionalGeneration(final Instance instance) { return Result.newInstance(); } /** * Print command line documentation on options * * @param context * @param options * @param parserMsg */ private void printUsage(Options options, String parserMsg) { String footer = ""; if (parserMsg != null && !parserMsg.isEmpty()) { footer = "\nMessage of the command line parser :\n" + parserMsg; } HelpFormatter helpFormatter = new HelpFormatter(); helpFormatter.setWidth(80); helpFormatter.printHelp(getClass().getSimpleName() + " [options] <network.qualified.name>", "Valid options are :", options, footer); } @Override final public void setOptions(Map<String, Object> options) { this.options = options; IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); project = root.getProject(getOption(PROJECT, "")); fifoSize = getOption(FIFO_SIZE, DEFAULT_FIFO_SIZE); debug = getOption(DEBUG_MODE, DEFAULT_DEBUG); mapping = getOption(MAPPING, new HashMap<String, String>()); classify = getOption(CLASSIFY, false); // Merging transformations need the results of classification mergeActions = classify && getOption(MERGE_ACTIONS, false); mergeActors = classify && getOption(MERGE_ACTORS, false); convertMulti2Mono = getOption(CONVERT_MULTI2MONO, false); String outputFolder = getOption(OUTPUT_FOLDER, ""); if (outputFolder.isEmpty()) { File tempOrccDir = new File(System.getProperty("java.io.tmpdir"), "orcc"); tempOrccDir.mkdir(); outputFolder = tempOrccDir.getAbsolutePath(); } else { outputFolder = FilesManager.sanitize(outputFolder); } // set output path outputPath = new File(outputFolder).getAbsolutePath(); if (debug) { OrccLogger.setLevel(OrccLogger.DEBUG); OrccLogger.debugln("Debug mode is enabled"); } // To avoid applying many times the same transformations when the same // back-end is re-run, we have to clear transfos lists. They will be // filled in doInitializeOptions() networkTransfos.clear(); childrenTransfos.clear(); doInitializeOptions(); } @Override public Object start(IApplicationContext context) throws Exception { Options options = new Options(); Option opt; // Required command line arguments opt = new Option("p", "project", true, "Project name"); opt.setRequired(true); options.addOption(opt); opt = new Option("o", "output", true, "Output folder"); opt.setRequired(true); options.addOption(opt); // Optional command line arguments options.addOption("d", "debug", false, "Enable debug mode"); options.addOption("s", "fifo-size", true, "Default size of the FIFO channels"); options.addOption("c", "classify", false, "Classify the given network"); options.addOption("smt", "smt-solver", true, "Set path to the binary of the SMT solver (Z3 v4.12+)"); options.addOption("m", "merge", true, "Merge (1) static actions " + "(2) static actors (3) both"); options.addOption("as", "advanced-scheduler", false, "(C) Use the " + "data-driven/demand-driven strategy for the actor-scheduler"); options.addOption("m2m", "multi2mono", false, "Transform high-level actors with multi-tokens actions" + " in low-level actors with mono-token actions"); options.addOption("prof", "profile", false, "(C) Enable profiling"); options.addOption("papify", false, "(C) Enable papi performance tool analyzer code printing."); options.addOption("et", "enable-traces", true, "(C) Enable tracing of the FIFOs in the given directory"); options.addOption("natLib", "native-lib", false, "(C) Enable linking with a native library containing native functions"); options.addOption("natLibF", "native-lib-folder", true, "(C) Path to the native lib project"); options.addOption("natLibH", "native-lib-headers", true, "(C) Names of the header files defining functions implemented in native library"); options.addOption("ttapc", "tta-processorconf", true, "(TTA) Predefined configurations for the processors (Standard|Custom|Fast|Huge)"); options.addOption("dt", "data-layout", true, "(LLVM) Configure the DataLayout printed in generated files"); options.addOption("tt", "target-triple", true, "(LLVM) Configure the target triple printed in generated files"); // FIXME: choose independently the transformation to apply options.addOption("t", "transfo_add", false, "Execute additional transformations before generate code"); try { CommandLineParser parser = new PosixParser(); String cliOpts = StringUtils .join((Object[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS), " "); OrccLogger.traceln("Command line arguments: " + cliOpts); // parse the command line arguments CommandLine line = parser.parse(options, (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS)); if (line.getArgs().length != 1) { throw new ParseException("Expected network name as last argument"); } String networkName = line.getArgs()[0]; Map<String, Object> optionMap = new HashMap<String, Object>(); optionMap.put(COMPILE_XDF, true); optionMap.put(PROJECT, line.getOptionValue('p')); optionMap.put(XDF_FILE, networkName); optionMap.put(OUTPUT_FOLDER, line.getOptionValue('o')); optionMap.put(DEBUG_MODE, line.hasOption('d')); if (line.hasOption('s')) { try { int size = Integer.parseInt(line.getOptionValue('s')); optionMap.put(FIFO_SIZE, size); if (!ValueUtil.isPowerOfTwo(size)) { OrccLogger.severeln("FIFO size must be power of two."); return IApplication.EXIT_OK; } } catch (NumberFormatException e) { throw new ParseException("Expected integer as FIFO size"); } } optionMap.put(CLASSIFY, line.hasOption('c')); if (line.hasOption("smt")) { String smt_path = line.getOptionValue("smt"); String smt_option = new String(); if (smt_path.contains("z3")) { if (Platform.OS_WIN32.equals(Platform.getOS())) { smt_option = "/smt2"; } else { smt_option = "-smt2"; } getDefault().setPreference(P_SOLVER, smt_path); getDefault().setPreference(P_SOLVER_OPTIONS, smt_option); } else { OrccLogger.warnln("Unknown SMT solver."); } } if (line.hasOption('m')) { String type = line.getOptionValue('m'); optionMap.put(MERGE_ACTIONS, type.equals("1") || type.equals("3")); optionMap.put(MERGE_ACTORS, type.equals("2") || type.equals("3")); } if (line.hasOption("et")) { optionMap.put(ENABLE_TRACES, true); optionMap.put(TRACES_FOLDER, line.getOptionValue("et")); } if (line.hasOption("ttapc")) { String pc = line.getOptionValue("ttapc"); if (pc.equals("Standard") || pc.equals("Custom") || pc.equals("Fast") || pc.equals("Huge")) { optionMap.put(TTA_PROCESSORS_CONFIGURATION, pc); } else { OrccLogger .warnln("Unknown processors configuration for TTA. Standard configuration will be apply."); } } if (line.hasOption("dl")) { optionMap.put(LLVM_TARGET_DATALAYOUT, line.getOptionValue("dl")); } if (line.hasOption("tt")) { optionMap.put(LLVM_TARGET_TRIPLE, line.getOptionValue("tt")); } optionMap.put(NEW_SCHEDULER, line.hasOption("as")); optionMap.put(CONVERT_MULTI2MONO, line.hasOption("m2m")); optionMap.put(ADDITIONAL_TRANSFOS, line.hasOption('t')); optionMap.put(PROFILE, line.hasOption("prof")); optionMap.put(PAPIFY, line.hasOption("papify")); optionMap.put(LINK_NATIVE_LIBRARY, line.hasOption("natLib")); if (line.hasOption("natLibF")) { optionMap.put(LINK_NATIVE_LIBRARY_FOLDER, line.getOptionValue("natLibF")); } if (line.hasOption("natLibH")) { optionMap.put(LINK_NATIVE_LIBRARY_HEADERS, line.getOptionValue("natLibH")); } // Set back-end name in options map String backend = this.getClass().getName(); IConfigurationElement[] elements = Platform.getExtensionRegistry() .getConfigurationElementsFor(Activator.PLUGIN_ID + ".backends"); for (IConfigurationElement element : elements) { if (backend.equals(element.getAttribute("class"))) { backend = element.getAttribute("name"); break; } } optionMap.put(BACKEND, backend); try { setOptions(optionMap); compile(new NullProgressMonitor()); return IApplication.EXIT_OK; } catch (OrccRuntimeException e) { if (e.getMessage() != null && !e.getMessage().isEmpty()) { OrccLogger.severeln(e.getMessage()); } OrccLogger.severeln( backend + " backend could not generate code (" + e.getCause() + ")[OrccRuntimeException]"); } catch (Exception e) { if (e.getMessage() != null && !e.getMessage().isEmpty()) { OrccLogger.severeln(e.getMessage()); } OrccLogger.severeln(backend + " backend could not generate code (" + e.getCause() + ")[Exception]"); e.printStackTrace(); } } catch (UnrecognizedOptionException uoe) { printUsage(options, uoe.getLocalizedMessage()); } catch (ParseException exp) { printUsage(options, exp.getLocalizedMessage()); } return IApplication.EXIT_RELAUNCH; } @Override public void stop() { OrccLogger.traceln("The "); monitor.setCanceled(true); } }