/* * Copyright (c) 2009, Ecole Polytechnique Fédérale de Lausanne * 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 Ecole Polytechnique Fédérale de Lausanne 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.promela; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import net.sf.orcc.backends.AbstractBackend; import net.sf.orcc.backends.promela.transform.ControlTokenActorModel; import net.sf.orcc.backends.promela.transform.GuardsExtractor; import net.sf.orcc.backends.promela.transform.IdentifyStatelessActors; import net.sf.orcc.backends.promela.transform.PromelaAddPrefixToStateVar; import net.sf.orcc.backends.promela.transform.PromelaDeadGlobalElimination; import net.sf.orcc.backends.promela.transform.PromelaSchedulabilityTest; import net.sf.orcc.backends.promela.transform.PromelaSchedulingModel; import net.sf.orcc.backends.promela.transform.ScheduleBalanceEq; import net.sf.orcc.backends.promela.transform.Scheduler; import net.sf.orcc.backends.transform.Inliner; import net.sf.orcc.backends.util.Validator; import net.sf.orcc.df.Action; import net.sf.orcc.df.Actor; import net.sf.orcc.df.Network; import net.sf.orcc.df.transform.BroadcastAdder; import net.sf.orcc.df.transform.Instantiator; import net.sf.orcc.df.transform.NetworkFlattener; import net.sf.orcc.df.transform.UnitImporter; import net.sf.orcc.df.util.DfVisitor; import net.sf.orcc.df.util.NetworkValidator; import net.sf.orcc.ir.Expression; import net.sf.orcc.ir.InstLoad; import net.sf.orcc.ir.transform.DeadCodeElimination; import net.sf.orcc.ir.transform.DeadVariableRemoval; import net.sf.orcc.ir.transform.PhiRemoval; import net.sf.orcc.ir.transform.RenameTransformation; import net.sf.orcc.tools.classifier.Classifier; import net.sf.orcc.util.FilesManager; import net.sf.orcc.util.Result; import net.sf.orcc.util.Void; import org.eclipse.emf.ecore.EObject; /** * This class defines a template-based PROMELA back-end. * * @author Ghislain Roquier * @author Johan Ersfolk */ public class PromelaBackend extends AbstractBackend { private Map<Action, List<Expression>> guards = new HashMap<Action, List<Expression>>(); private Map<Action, List<InstLoad>> loadPeeks = new HashMap<Action, List<InstLoad>>(); private Map<EObject, List<Action>> priority = new HashMap<EObject, List<Action>>(); private PromelaSchedulingModel schedulingModel; private ScheduleBalanceEq balanceEq; private Set<Scheduler> actorSchedulers; private final NetworkPrinter networkPrinter; private final SchedulePrinter schedulerPrinter; private final ScriptPrinter scriptPrinter; private final InstancePrinter instancePrinter; public PromelaBackend() { actorSchedulers = new HashSet<Scheduler>(); networkPrinter = new NetworkPrinter(); schedulerPrinter = new SchedulePrinter(actorSchedulers); scriptPrinter = new ScriptPrinter(); instancePrinter = new InstancePrinter(); } @Override protected void doInitializeOptions() { actorSchedulers.clear(); guards.clear(); priority.clear(); loadPeeks.clear(); getOptions().put("guards", guards); getOptions().put("priority", priority); getOptions().put("loadPeeks", loadPeeks); networkPrinter.setOptions(getOptions()); schedulerPrinter.setOptions(getOptions()); scriptPrinter.setOptions(getOptions()); instancePrinter.setOptions(getOptions()); final Map<String, String> renameMap = new HashMap<String, String>(); renameMap.put("abs", "abs_prml"); renameMap.put("getw", "getw_prml"); renameMap.put("index", "index_prml"); renameMap.put("max", "max_prml"); renameMap.put("min", "min_prml"); renameMap.put("select", "select_prml"); renameMap.put("len", "len_prml"); networkTransfos.add(new BroadcastAdder()); networkTransfos.add(new Instantiator(true)); networkTransfos.add(new NetworkFlattener()); networkTransfos.add(new Classifier(true)); networkTransfos.add(new UnitImporter()); networkTransfos.add(new DfVisitor<Void>(new Inliner(true, true))); networkTransfos.add(new RenameTransformation(renameMap)); networkTransfos.add(new DfVisitor<Void>(new PhiRemoval())); networkTransfos.add(new PromelaAddPrefixToStateVar()); networkTransfos.add(new GuardsExtractor(guards, priority, loadPeeks)); } @Override protected Result doLibrariesExtraction() { return FilesManager.extract("/runtime/Promela/pylibs", outputPath); } @Override protected void doValidate(Network network) { Validator.checkTopLevel(network); // We don't have to print Warnings for 'potential deadlocks' // Validator.checkMinimalFifoSize(network, fifoSize); new NetworkValidator().doSwitch(network); } @Override protected void beforeGeneration(Network network) { schedulingModel = new PromelaSchedulingModel(network); schedulingModel.printDependencyGraph(); for (Actor actor : network.getAllActors()) { final ControlTokenActorModel actorModel = schedulingModel .getActorModel(actor); final List<DfVisitor<?>> additionalTransfos = new ArrayList<DfVisitor<?>>(); additionalTransfos.add(new IdentifyStatelessActors(actorModel)); additionalTransfos.add(new PromelaDeadGlobalElimination(actorModel .getAllReacableSchedulingVars(), actorModel .getPortsUsedInScheduling())); additionalTransfos.add(new DfVisitor<Void>(new DeadCodeElimination())); additionalTransfos.add(new DfVisitor<Void>(new DeadVariableRemoval())); applyTransformations(actor, additionalTransfos, debug); final PromelaSchedulabilityTest actorScheduler = new PromelaSchedulabilityTest( actorModel); actorScheduler.doSwitch(actor); actorSchedulers.add(actorScheduler.getScheduler()); } balanceEq = new ScheduleBalanceEq(actorSchedulers, network); network.computeTemplateMaps(); } @Override protected Result doGenerateNetwork(Network network) { networkPrinter.setNetwork(network); return FilesManager.writeFile(networkPrinter.getNetworkFileContent(), outputPath, "main_" + network.getSimpleName() + ".pml"); } @Override protected Result doAdditionalGeneration(Network network) { // Could be better to have a printer instance for all runs final ScheduleInfoPrinter scheduleInfoPrinter = new ScheduleInfoPrinter( balanceEq); schedulerPrinter.setNetwork(network); scheduleInfoPrinter.setNetwork(network); scheduleInfoPrinter.setOptions(getOptions()); scriptPrinter.setNetwork(network); final Result result = Result.newInstance(); result.merge(FilesManager.writeFile( schedulerPrinter.getSchedulerFileContent(), outputPath, "schedule_" + network.getSimpleName() + ".xml")); result.merge(FilesManager.writeFile( scheduleInfoPrinter.getSchedulerFileContent(), outputPath, "schedule_info_" + network.getSimpleName() + ".xml")); result.merge(FilesManager.writeFile(scriptPrinter.getScriptFileContent(), outputPath, "run_checker_" + network.getSimpleName() + ".py")); return result; } @Override protected Result doGenerateActor(Actor actor) { instancePrinter.setActor(actor); instancePrinter.setSchedulingModel(schedulingModel); return FilesManager.writeFile(instancePrinter.getInstanceFileContent(), outputPath, actor.getName() + ".pml"); } }