org.pshdl.model.simulation.PStoEXCompiler.java Source code

Java tutorial

Introduction

Here is the source code for org.pshdl.model.simulation.PStoEXCompiler.java

Source

/*******************************************************************************
 * PSHDL is a library and (trans-)compiler for PSHDL input. It generates
 *     output suitable for implementation or simulation of it.
 *
 *     Copyright (C) 2013 Karsten Becker (feedback (at) pshdl (dot) org)
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *     This License does not grant permission to use the trade names, trademarks,
 *     service marks, or product names of the Licensor, except as required for
 *     reasonable and customary use in describing the origin of the Work.
 *
 * Contributors:
 *     Karsten Becker - initial API and implementation
 ******************************************************************************/
package org.pshdl.model.simulation;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.pshdl.interpreter.ExecutableModel;
import org.pshdl.interpreter.utils.Graph.CycleException;
import org.pshdl.interpreter.utils.IOUtil;
import org.pshdl.model.HDLUnit;
import org.pshdl.model.evaluation.HDLEvaluationContext;
import org.pshdl.model.extensions.FullNameExtension;
import org.pshdl.model.utils.HDLCore;
import org.pshdl.model.utils.HDLQualifiedName;
import org.pshdl.model.utils.PSAbstractCompiler;
import org.pshdl.model.utils.services.IOutputProvider;

import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;

public class PStoEXCompiler extends PSAbstractCompiler implements IOutputProvider {

    private final Map<String, ITypeOuptutProvider> providers;

    public PStoEXCompiler() {
        this(null, null);
    }

    public PStoEXCompiler(String uri, ExecutorService service) {
        super(uri, service);
        final Collection<ITypeOuptutProvider> allImplementations = HDLCore
                .getAllImplementations(ITypeOuptutProvider.class);
        providers = Maps.newTreeMap();
        for (final ITypeOuptutProvider ito : allImplementations) {
            providers.put(ito.getHookName().toLowerCase(), ito);
        }
    }

    @Override
    public String getHookName() {
        return "psex";
    }

    @SuppressWarnings("static-access")
    @Override
    public MultiOption getUsage() {
        final Options options = new Options();
        options.addOption(new Option("o", "outputDir", true,
                "Specify the directory to which the files will be written, default is: src-gen/psex/[type]"));
        options.addOption(new Option("em", "enable the output of the byte-code .em file"));
        options.addOption(new Option("allSignals", "disable the removal of redundant variables"));
        options.addOption(new Option("ir", "dump the intermediate PSHDL code"));
        options.addOption(OptionBuilder
                .withArgName(listTypes("|")).withDescription("The output type to generate. Valid options are: "
                        + listTypes(", ") + ". Each type may require additional command line arguments")
                .hasArg().create("type"));
        final MultiOption mo = new MultiOption(getHookName() + " usage: [OPTIONS] MODULE <files>", null, options);
        for (final ITypeOuptutProvider ito : providers.values()) {
            mo.subs.add(ito.getUsage());
        }
        return mo;
    }

    private String listTypes(String sep) {
        return Joiner.on(sep).join(providers.keySet());
    }

    @Override
    public String invoke(CommandLine cli) throws Exception {
        @SuppressWarnings("unchecked")
        final List<String> argList = cli.getArgList();
        if (argList.size() == 0) {
            getUsage().printHelp(System.out);
            return "Missing module and file arguments";
        }
        if (argList.size() == 1) {
            getUsage().printHelp(System.out);
            return "Missing file arguments";
        }
        final HDLQualifiedName unitName = new HDLQualifiedName(argList.get(0));
        System.out.println("Using module:\t" + unitName);
        final List<File> files = Lists.newLinkedList();
        final String type = cli.getOptionValue("type");
        if ((type != null) && !providers.containsKey(type.toLowerCase()))
            return "Invalid type argument, no such type " + type;
        System.out.println("Parsing files:");
        for (int i = 1; i < argList.size(); i++) {
            final File source = new File(argList.get(i));
            System.out.println("\t" + source.getAbsolutePath());
            if (!source.exists())
                return "The file: " + source + " can not be found";
            files.add(source);
        }
        if (addFiles(files))
            return "Exiting because of syntax errors in the input";
        System.out.println("Validating:");
        if (validatePackages())
            return "Exiting because of errors in the input";
        final HDLUnit unit = findUnit(unitName);
        if (unit == null)
            return "Unit: " + unitName + " not found";
        final String src = unit.getLibrary().getSrc(unitName);
        String outDir = cli.getOptionValue("outputDir");
        if (outDir == null) {
            outDir = "src-gen/psex";
        }
        final File dir = new File(outDir);
        if (!dir.exists()) {
            System.out.println("Output directory " + dir + " does not exist, creating it");
            if (!dir.mkdirs())
                throw new IllegalArgumentException("Failed to create direcory:" + dir);
        }
        final ExecutableModel em = createExecutable(unit, src, cli.hasOption("ir"), !cli.hasOption("allSignals"));
        if (cli.hasOption("em")) {
            IOUtil.writeExecutableModel(System.currentTimeMillis(), em, new File(dir, unitName.toString() + ".em"));
        }
        if (type != null) {
            final ITypeOuptutProvider ito = providers.get(type.toLowerCase());
            final List<CompileResult> results = ito.invoke(cli, em, null);
            for (final CompileResult cr : results) {
                writeFiles(dir, cr);
            }
        }
        return null;
    }

    public static ExecutableModel createExecutable(HDLUnit unit, String src, boolean dumpIntermediate,
            boolean purgeAliases) throws CycleException {
        final HDLEvaluationContext context = HDLEvaluationContext.createDefault(unit);
        final HDLUnit simulationModel = HDLSimulator.createSimulationModel(unit, context, src, '_');
        if (dumpIntermediate) {
            try {
                Files.write(simulationModel.toString(), new File(src + "_ir.pshdl"), Charsets.UTF_8);
            } catch (final IOException e1) {
                e1.printStackTrace();
            }
        }
        final FluidFrame model = SimulationTransformationExtension.simulationModelOf(simulationModel, context);
        final HDLQualifiedName fqn = FullNameExtension.fullNameOf(simulationModel);
        final ExecutableModel em = model.getExecutable(fqn.toString(), src);
        try {
            em.sortTopological();
        } catch (final CycleException e) {
            e.model = em;
            throw e;
        }
        return em;
    }

    public ExecutableModel createExecutable(HDLQualifiedName name, String src) throws CycleException {
        final HDLUnit findUnit = findUnit(name);
        if (findUnit == null)
            throw new IllegalArgumentException("No unit with name:" + name);
        return createExecutable(findUnit, src, false, true);
    }

}