mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-17 00:44:40 -04:00
first working apio support
This commit is contained in:
parent
6717ce9090
commit
0101548366
@ -40,8 +40,13 @@ auftritt.}}</string>
|
|||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Not</elementName>
|
<elementName>Not</elementName>
|
||||||
<elementAttributes/>
|
<elementAttributes>
|
||||||
<pos x="180" y="180"/>
|
<entry>
|
||||||
|
<string>wideShape</string>
|
||||||
|
<boolean>true</boolean>
|
||||||
|
</entry>
|
||||||
|
</elementAttributes>
|
||||||
|
<pos x="160" y="180"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>In</elementName>
|
<elementName>In</elementName>
|
||||||
@ -261,7 +266,7 @@ C 1 1 0 1
|
|||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="140" y="180"/>
|
<p1 x="140" y="180"/>
|
||||||
<p2 x="180" y="180"/>
|
<p2 x="160" y="180"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="140" y="40"/>
|
<p1 x="140" y="40"/>
|
||||||
|
@ -778,5 +778,10 @@ public final class Keys {
|
|||||||
.setMin(0)
|
.setMin(0)
|
||||||
.setSecondary();
|
.setSecondary();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the IDE settings file
|
||||||
|
*/
|
||||||
|
public static final Key<File> SETTINGS_IDE_CONFIG =
|
||||||
|
new Key.KeyFile("ideSettings", new File("")).setSecondary().setRequiresRestart();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ import de.neemann.digital.gui.state.StateManager;
|
|||||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||||
import de.neemann.digital.hdl.verilog2.VerilogGenerator;
|
import de.neemann.digital.hdl.verilog2.VerilogGenerator;
|
||||||
import de.neemann.digital.hdl.vhdl2.VHDLGenerator;
|
import de.neemann.digital.hdl.vhdl2.VHDLGenerator;
|
||||||
|
import de.neemann.digital.ide.Configuration;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import de.neemann.digital.testing.TestCaseElement;
|
import de.neemann.digital.testing.TestCaseElement;
|
||||||
import de.neemann.digital.testing.TestingDataException;
|
import de.neemann.digital.testing.TestingDataException;
|
||||||
@ -277,7 +278,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
|||||||
|
|
||||||
enableClockShortcut();
|
enableClockShortcut();
|
||||||
|
|
||||||
new WindowSizeStorage(builder.mainFrame?"main":"sub").restore(this);
|
new WindowSizeStorage(builder.mainFrame ? "main" : "sub").restore(this);
|
||||||
|
|
||||||
if (builder.parent != null) {
|
if (builder.parent != null) {
|
||||||
Point p = builder.parent.getLocation();
|
Point p = builder.parent.getLocation();
|
||||||
@ -288,6 +289,28 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
|||||||
} else
|
} else
|
||||||
setLocationRelativeTo(null);
|
setLocationRelativeTo(null);
|
||||||
|
|
||||||
|
checkIDEIntegration(builder, menuBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIDEIntegration(MainBuilder builder, JMenuBar menuBar) {
|
||||||
|
if (builder.mainFrame) {
|
||||||
|
File f = Settings.getInstance().get(Keys.SETTINGS_IDE_CONFIG);
|
||||||
|
if (f.getPath().length() > 0) {
|
||||||
|
try {
|
||||||
|
menuBar.add(
|
||||||
|
Configuration.load(f)
|
||||||
|
.setCircuitProvider(() -> getCircuitComponent().getCircuit())
|
||||||
|
.setFilenameProvider(() -> {
|
||||||
|
saveChanges();
|
||||||
|
return filename;
|
||||||
|
})
|
||||||
|
.setLibraryProvider(() -> library)
|
||||||
|
.createMenu());
|
||||||
|
} catch (IOException e) {
|
||||||
|
SwingUtilities.invokeLater(new ErrorMessage(Lang.get("msg_errorReadingIDEConfig_N", f.getPath())).addCause(e).setComponent(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableClockShortcut() {
|
private void enableClockShortcut() {
|
||||||
|
@ -58,6 +58,7 @@ public final class Settings implements AttributeListener {
|
|||||||
intList.add(Keys.SETTINGS_ATMISP);
|
intList.add(Keys.SETTINGS_ATMISP);
|
||||||
intList.add(Keys.SETTINGS_GHDL_PATH);
|
intList.add(Keys.SETTINGS_GHDL_PATH);
|
||||||
intList.add(Keys.SETTINGS_IVERILOG_PATH);
|
intList.add(Keys.SETTINGS_IVERILOG_PATH);
|
||||||
|
intList.add(Keys.SETTINGS_IDE_CONFIG);
|
||||||
intList.add(Keys.SETTINGS_FONT_SCALING);
|
intList.add(Keys.SETTINGS_FONT_SCALING);
|
||||||
intList.add(Keys.SETTINGS_MAC_MOUSE);
|
intList.add(Keys.SETTINGS_MAC_MOUSE);
|
||||||
|
|
||||||
|
66
src/main/java/de/neemann/digital/ide/Command.java
Normal file
66
src/main/java/de/neemann/digital/ide/Command.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.ide;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a command to execute
|
||||||
|
*/
|
||||||
|
public class Command {
|
||||||
|
private final String name;
|
||||||
|
private final boolean filter;
|
||||||
|
private final String requires;
|
||||||
|
private final String[] args;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new command
|
||||||
|
*
|
||||||
|
* @param name the name of the command
|
||||||
|
* @param requires the hdl which is required, either "verilog" of "vhdl"
|
||||||
|
* @param filter the true, the commands args are filtered
|
||||||
|
* @param args the arguments
|
||||||
|
*/
|
||||||
|
public Command(String name, String requires, boolean filter, String... args) {
|
||||||
|
this.name = name;
|
||||||
|
this.requires = requires;
|
||||||
|
this.args = args;
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the commands name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the commands args
|
||||||
|
*/
|
||||||
|
public String[] getArgs() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if a hdl is required
|
||||||
|
*/
|
||||||
|
public boolean needsHDL() {
|
||||||
|
return getHDL().length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the hdl which is required, either "verilog" of "vhdl"
|
||||||
|
*/
|
||||||
|
public String getHDL() {
|
||||||
|
return requires.trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the arguments needs to be filtered
|
||||||
|
*/
|
||||||
|
public boolean isFilter() {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
}
|
338
src/main/java/de/neemann/digital/ide/Configuration.java
Normal file
338
src/main/java/de/neemann/digital/ide/Configuration.java
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.ide;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.XStream;
|
||||||
|
import com.thoughtworks.xstream.io.xml.StaxDriver;
|
||||||
|
import de.neemann.digital.core.extern.ProcessStarter;
|
||||||
|
import de.neemann.digital.draw.elements.Circuit;
|
||||||
|
import de.neemann.digital.draw.library.ElementLibrary;
|
||||||
|
import de.neemann.digital.gui.SaveAsHelper;
|
||||||
|
import de.neemann.digital.hdl.hgs.Context;
|
||||||
|
import de.neemann.digital.hdl.hgs.HGSEvalException;
|
||||||
|
import de.neemann.digital.hdl.hgs.Parser;
|
||||||
|
import de.neemann.digital.hdl.hgs.ParserException;
|
||||||
|
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||||
|
import de.neemann.digital.hdl.verilog2.VerilogGenerator;
|
||||||
|
import de.neemann.digital.hdl.vhdl2.VHDLGenerator;
|
||||||
|
import de.neemann.digital.lang.Lang;
|
||||||
|
import de.neemann.gui.ErrorMessage;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to create the IDE integration
|
||||||
|
*/
|
||||||
|
public final class Configuration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a configuration
|
||||||
|
*
|
||||||
|
* @param file the file to load
|
||||||
|
* @return the configuration
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public static Configuration load(File file) throws IOException {
|
||||||
|
return load(new FileInputStream(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a configuration
|
||||||
|
*
|
||||||
|
* @param in the file to load
|
||||||
|
* @return the configuration
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public static Configuration load(InputStream in) throws IOException {
|
||||||
|
try {
|
||||||
|
XStream xStream = getxStream();
|
||||||
|
return (Configuration) xStream.fromXML(in);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new IOException("error reading XML", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static XStream getxStream() {
|
||||||
|
final XStream xStream = new XStream(new StaxDriver());
|
||||||
|
xStream.alias("ide", Configuration.class);
|
||||||
|
xStream.aliasAttribute(Configuration.class, "name", "name");
|
||||||
|
xStream.alias("command", Command.class);
|
||||||
|
xStream.aliasAttribute(Command.class, "name", "name");
|
||||||
|
xStream.aliasAttribute(Command.class, "requires", "requires");
|
||||||
|
xStream.aliasAttribute(Command.class, "filter", "filter");
|
||||||
|
xStream.addImplicitCollection(Command.class, "args", "arg", String.class);
|
||||||
|
xStream.alias("file", FileToCreate.class);
|
||||||
|
xStream.aliasAttribute(FileToCreate.class, "name", "name");
|
||||||
|
xStream.aliasAttribute(FileToCreate.class, "overwrite", "overwrite");
|
||||||
|
xStream.aliasAttribute(FileToCreate.class, "filter", "filter");
|
||||||
|
return xStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private ArrayList<Command> commands;
|
||||||
|
private ArrayList<FileToCreate> files;
|
||||||
|
private transient FilenameProvider filenameProvider;
|
||||||
|
private transient CircuitProvider circuitProvider;
|
||||||
|
private transient LibraryProvider libraryProvider;
|
||||||
|
private transient FileWriter fileWriter;
|
||||||
|
|
||||||
|
private Configuration() {
|
||||||
|
files = new ArrayList<>();
|
||||||
|
commands = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the file name provider
|
||||||
|
*
|
||||||
|
* @param filenameProvider the file name provider
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public Configuration setFilenameProvider(FilenameProvider filenameProvider) {
|
||||||
|
this.filenameProvider = filenameProvider;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the circuit provider
|
||||||
|
*
|
||||||
|
* @param circuitProvider the circuit provider
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public Configuration setCircuitProvider(CircuitProvider circuitProvider) {
|
||||||
|
this.circuitProvider = circuitProvider;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the library provider
|
||||||
|
*
|
||||||
|
* @param libraryProvider the library provider
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public Configuration setLibraryProvider(LibraryProvider libraryProvider) {
|
||||||
|
this.libraryProvider = libraryProvider;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration setFileWriter(FileWriter fileWriter) {
|
||||||
|
this.fileWriter = fileWriter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a menu used to start the commands.
|
||||||
|
*
|
||||||
|
* @return the menu
|
||||||
|
*/
|
||||||
|
public JMenu createMenu() {
|
||||||
|
JMenu menu = new JMenu(name);
|
||||||
|
for (Command c : commands)
|
||||||
|
menu.add(new JMenuItem(new ExecuteAction(c)));
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkFilesToCreate(File fileToExecute) throws HGSEvalException, IOException, ParserException {
|
||||||
|
Context context = createContext(fileToExecute);
|
||||||
|
|
||||||
|
if (files != null)
|
||||||
|
for (FileToCreate f : files) {
|
||||||
|
context.clearOutput();
|
||||||
|
Parser p = new Parser(f.getName());
|
||||||
|
p.parse().execute(context);
|
||||||
|
File filename = new File(fileToExecute.getParent(), context.toString());
|
||||||
|
|
||||||
|
if (f.isOverwrite() || !filename.exists()) {
|
||||||
|
String content = f.getContent();
|
||||||
|
if (f.isFilter()) {
|
||||||
|
context.clearOutput();
|
||||||
|
p = new Parser(content);
|
||||||
|
p.parse().execute(context);
|
||||||
|
content = context.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (OutputStream out = getFileWriter().getOutputStream(filename)) {
|
||||||
|
out.write(content.getBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Context createContext(File fileToExecute) throws HGSEvalException {
|
||||||
|
return new Context()
|
||||||
|
.declareVar("path", fileToExecute.getPath())
|
||||||
|
.declareVar("dir", fileToExecute.getParentFile())
|
||||||
|
.declareVar("name", fileToExecute.getName())
|
||||||
|
.declareVar("shortname", createShortname(fileToExecute.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileWriter getFileWriter() {
|
||||||
|
if (fileWriter == null)
|
||||||
|
fileWriter = new DefaultFileWriter();
|
||||||
|
return fileWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createShortname(String name) {
|
||||||
|
int p = name.lastIndexOf('.');
|
||||||
|
if (p >= 0)
|
||||||
|
return name.substring(0, p);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeHDL(String hdl, File digFile) throws IOException {
|
||||||
|
switch (hdl) {
|
||||||
|
case "verilog":
|
||||||
|
File verilogFile = SaveAsHelper.checkSuffix(digFile, "v");
|
||||||
|
final CodePrinter verilogPrinter = new CodePrinter(getFileWriter().getOutputStream(verilogFile));
|
||||||
|
try (VerilogGenerator vlog = new VerilogGenerator(libraryProvider.getCurrentLibrary(), verilogPrinter)) {
|
||||||
|
vlog.export(circuitProvider.getCurrentCircuit());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "vhdl":
|
||||||
|
File vhdlFile = SaveAsHelper.checkSuffix(digFile, "vhdl");
|
||||||
|
final CodePrinter vhdlPrinter = new CodePrinter(getFileWriter().getOutputStream(vhdlFile));
|
||||||
|
try (VHDLGenerator vlog = new VHDLGenerator(libraryProvider.getCurrentLibrary(), vhdlPrinter)) {
|
||||||
|
vlog.export(circuitProvider.getCurrentCircuit());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IOException(Lang.get("err_hdlNotKnown_N", hdl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the given command
|
||||||
|
*
|
||||||
|
* @param command the command
|
||||||
|
*/
|
||||||
|
public void executeCommand(Command command) {
|
||||||
|
File digFile = filenameProvider.getCurrentFilename();
|
||||||
|
if (digFile != null) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (command.needsHDL())
|
||||||
|
writeHDL(command.getHDL(), digFile);
|
||||||
|
|
||||||
|
checkFilesToCreate(digFile);
|
||||||
|
|
||||||
|
String[] args = command.getArgs();
|
||||||
|
if (command.isFilter()) {
|
||||||
|
final int argCount = command.getArgs().length;
|
||||||
|
Context context = createContext(digFile);
|
||||||
|
for (int i = 0; i < argCount; i++) {
|
||||||
|
context.clearOutput();
|
||||||
|
new Parser(args[i]).parse().execute(context);
|
||||||
|
args[i] = context.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileWriter().startProcess(digFile.getParentFile(), args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
getFileWriter().showError(command, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class ExecuteAction extends AbstractAction {
|
||||||
|
private final Command command;
|
||||||
|
|
||||||
|
private ExecuteAction(Command command) {
|
||||||
|
super(command.getName());
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
executeCommand(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Command> getCommands() {
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used to provide a file.
|
||||||
|
*/
|
||||||
|
public interface FilenameProvider {
|
||||||
|
/**
|
||||||
|
* @return the file which is to create
|
||||||
|
*/
|
||||||
|
File getCurrentFilename();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used to provide the circuit
|
||||||
|
*/
|
||||||
|
public interface CircuitProvider {
|
||||||
|
/**
|
||||||
|
* @return the circuit which is to use
|
||||||
|
*/
|
||||||
|
Circuit getCurrentCircuit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used to provide the library.
|
||||||
|
*/
|
||||||
|
public interface LibraryProvider {
|
||||||
|
/**
|
||||||
|
* @return the library which currently used
|
||||||
|
*/
|
||||||
|
ElementLibrary getCurrentLibrary();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used to write a file
|
||||||
|
*/
|
||||||
|
public interface FileWriter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an output stream
|
||||||
|
*
|
||||||
|
* @param filename the filename
|
||||||
|
* @return the output stream
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
OutputStream getOutputStream(File filename) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a process
|
||||||
|
*
|
||||||
|
* @param dir the folder to start the process in
|
||||||
|
* @param args the arguments
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
void startProcess(File dir, String[] args) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows an error message
|
||||||
|
*
|
||||||
|
* @param command the command that failed
|
||||||
|
* @param e the error
|
||||||
|
*/
|
||||||
|
void showError(Command command, Exception e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class DefaultFileWriter implements FileWriter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream getOutputStream(File filename) throws FileNotFoundException {
|
||||||
|
return new FileOutputStream(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startProcess(File dir, String[] args) throws IOException {
|
||||||
|
ProcessStarter.start(dir, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showError(Command command, Exception e) {
|
||||||
|
new ErrorMessage(Lang.get("msg_errorStartCommand_N", command.getName())).addCause(e).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
src/main/java/de/neemann/digital/ide/FileToCreate.java
Normal file
59
src/main/java/de/neemann/digital/ide/FileToCreate.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.ide;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a file to create
|
||||||
|
*/
|
||||||
|
public class FileToCreate {
|
||||||
|
private final String name;
|
||||||
|
private final String content;
|
||||||
|
private final boolean overwrite;
|
||||||
|
private final boolean filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file to create
|
||||||
|
*
|
||||||
|
* @param name the name of the file
|
||||||
|
* @param content the files content
|
||||||
|
* @param overwrite overwrite every time a command is executed
|
||||||
|
* @param filter the files content needs to be filtered
|
||||||
|
*/
|
||||||
|
public FileToCreate(String name, String content, boolean overwrite, boolean filter) {
|
||||||
|
this.name = name;
|
||||||
|
this.content = content;
|
||||||
|
this.overwrite = overwrite;
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The file name of the file. Is always filtered
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the file needs to be overwritten, every time a command is executed.
|
||||||
|
*/
|
||||||
|
public boolean isOverwrite() {
|
||||||
|
return overwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the files contend needs to be filtered.
|
||||||
|
*/
|
||||||
|
public boolean isFilter() {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the files content
|
||||||
|
*/
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
10
src/main/java/de/neemann/digital/ide/package-info.java
Normal file
10
src/main/java/de/neemann/digital/ide/package-info.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classes used to provide the IDE integration
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.ide;
|
@ -1017,6 +1017,8 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
|||||||
<string name="err_midiInstrument_N_NotAvailable">Das MIDI-Instrument {0} ist nicht verfügbar.</string>
|
<string name="err_midiInstrument_N_NotAvailable">Das MIDI-Instrument {0} ist nicht verfügbar.</string>
|
||||||
<string name="err_midiInstrumentsNotAvailable">Die MIDI-Instrumente sind nicht verfügbar.</string>
|
<string name="err_midiInstrumentsNotAvailable">Die MIDI-Instrumente sind nicht verfügbar.</string>
|
||||||
<string name="err_whileExecutingTests_N0">Während der Ausführung der Tests "{0}" ist ein Fehler aufgetreten!</string>
|
<string name="err_whileExecutingTests_N0">Während der Ausführung der Tests "{0}" ist ein Fehler aufgetreten!</string>
|
||||||
|
<string name="err_hdlNotKnown_N">HDL nicht bekannt: {0}</string>
|
||||||
|
<string name="msg_errorStartCommand_N">Fehler beim Starten des Kommandos {0}</string>
|
||||||
|
|
||||||
<string name="key_AddrBits">Adress-Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
|
<string name="key_AddrBits">Adress-Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
|
||||||
<string name="key_AddrBits_tt">Anzahl der Adress-Bits, die verwendet werden.</string>
|
<string name="key_AddrBits_tt">Anzahl der Adress-Bits, die verwendet werden.</string>
|
||||||
@ -1330,6 +1332,10 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
|||||||
<string name="key_enabled">Aktiviert</string>
|
<string name="key_enabled">Aktiviert</string>
|
||||||
<string name="key_enabled_tt">Aktiviert oder deaktiviert diese Komponente.</string>
|
<string name="key_enabled_tt">Aktiviert oder deaktiviert diese Komponente.</string>
|
||||||
|
|
||||||
|
<string name="key_ideSettings">IDE-Einstellungen</string>
|
||||||
|
<string name="key_ideSettings_tt">Kann für eine IDE-Integration verwendet werden.
|
||||||
|
Erlaubt den Start externer Tools, um z.B. einen FPGA zu programmieren o.ä.</string>
|
||||||
|
|
||||||
<string name="mod_insertWire">Leitung eingefügt.</string>
|
<string name="mod_insertWire">Leitung eingefügt.</string>
|
||||||
<string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string>
|
<string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string>
|
||||||
<string name="mod_setKey_N0_in_element_N1">Wert ''{0}'' in Element ''{1}'' verändert.</string>
|
<string name="mod_setKey_N0_in_element_N1">Wert ''{0}'' in Element ''{1}'' verändert.</string>
|
||||||
@ -1683,6 +1689,8 @@ Stellen Sie sicher, dass der Flash-Vorgang abgeschlossen ist, bevor Sie diesen D
|
|||||||
<string name="msg_errorCreatingSvgTemplate">Fehler beim Erzeugen der SVG-Datei.</string>
|
<string name="msg_errorCreatingSvgTemplate">Fehler beim Erzeugen der SVG-Datei.</string>
|
||||||
<string name="msg_couldNotCreateStats">Statistik konnte nicht erzeugt werden.</string>
|
<string name="msg_couldNotCreateStats">Statistik konnte nicht erzeugt werden.</string>
|
||||||
|
|
||||||
|
<string name="msg_errorReadingIDEConfig_N">Fehler beim Einladen der IDE-Konfiguration {0}</string>
|
||||||
|
|
||||||
<string name="ok">Ok</string>
|
<string name="ok">Ok</string>
|
||||||
<string name="rot_0">0°</string>
|
<string name="rot_0">0°</string>
|
||||||
<string name="rot_180">180°</string>
|
<string name="rot_180">180°</string>
|
||||||
|
@ -1009,6 +1009,8 @@
|
|||||||
<string name="err_midiInstrument_N_NotAvailable">The MIDI instrument {0} is not available.</string>
|
<string name="err_midiInstrument_N_NotAvailable">The MIDI instrument {0} is not available.</string>
|
||||||
<string name="err_midiInstrumentsNotAvailable">The MIDI instruments are not available.</string>
|
<string name="err_midiInstrumentsNotAvailable">The MIDI instruments are not available.</string>
|
||||||
<string name="err_whileExecutingTests_N0">During the execution of the tests "{0}" an error has occurred!</string>
|
<string name="err_whileExecutingTests_N0">During the execution of the tests "{0}" an error has occurred!</string>
|
||||||
|
<string name="err_hdlNotKnown_N">HDL not known: {0}</string>
|
||||||
|
<string name="msg_errorStartCommand_N">Error starting the command {0}</string>
|
||||||
|
|
||||||
<string name="key_AddrBits">Address Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
|
<string name="key_AddrBits">Address Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
|
||||||
<string name="key_AddrBits_tt">Number of address bits used.</string>
|
<string name="key_AddrBits_tt">Number of address bits used.</string>
|
||||||
@ -1318,6 +1320,10 @@
|
|||||||
<string name="key_enabled">Enabled</string>
|
<string name="key_enabled">Enabled</string>
|
||||||
<string name="key_enabled_tt">Enables or disables this component.</string>
|
<string name="key_enabled_tt">Enables or disables this component.</string>
|
||||||
|
|
||||||
|
<string name="key_ideSettings">IDE settings</string>
|
||||||
|
<string name="key_ideSettings_tt">Used to configurate an IDE integration.
|
||||||
|
Allows the start of external tools, e.g. to program an FPGA or similar.</string>
|
||||||
|
|
||||||
<string name="mod_insertWire">Inserted wire.</string>
|
<string name="mod_insertWire">Inserted wire.</string>
|
||||||
<string name="mod_insertCopied">Insert from clipboard.</string>
|
<string name="mod_insertCopied">Insert from clipboard.</string>
|
||||||
<string name="mod_setKey_N0_in_element_N1">Value ''{0}'' in component ''{1}'' modified.</string>
|
<string name="mod_setKey_N0_in_element_N1">Value ''{0}'' in component ''{1}'' modified.</string>
|
||||||
@ -1665,6 +1671,7 @@ Make sure the flash process is complete before closing this dialog!</string>
|
|||||||
<string name="msg_errorImportingSvg">Error while importing the SVG file.</string>
|
<string name="msg_errorImportingSvg">Error while importing the SVG file.</string>
|
||||||
<string name="msg_errorCreatingSvgTemplate">Error creating the SVG template.</string>
|
<string name="msg_errorCreatingSvgTemplate">Error creating the SVG template.</string>
|
||||||
<string name="msg_couldNotCreateStats">Statistics could not be created.</string>
|
<string name="msg_couldNotCreateStats">Statistics could not be created.</string>
|
||||||
|
<string name="msg_errorReadingIDEConfig_N">Error while reading the IDE configuration {0}</string>
|
||||||
|
|
||||||
<string name="ok">OK</string>
|
<string name="ok">OK</string>
|
||||||
<string name="rot_0">0°</string>
|
<string name="rot_0">0°</string>
|
||||||
|
144
src/test/java/de/neemann/digital/ide/ConfigurationTest.java
Normal file
144
src/test/java/de/neemann/digital/ide/ConfigurationTest.java
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.ide;
|
||||||
|
|
||||||
|
import de.neemann.digital.core.NodeException;
|
||||||
|
import de.neemann.digital.draw.elements.PinException;
|
||||||
|
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||||
|
import de.neemann.digital.integration.Resources;
|
||||||
|
import de.neemann.digital.integration.ToBreakRunner;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class ConfigurationTest extends TestCase {
|
||||||
|
|
||||||
|
public void testStart() throws IOException, ElementNotFoundException, PinException, NodeException {
|
||||||
|
String xml = "<ide name=\"APIO\">\n" +
|
||||||
|
" <commands>\n" +
|
||||||
|
" <command name=\"build\" requires=\"verilog\" filter=\"false\">\n" +
|
||||||
|
" <arg>make</arg>\n" +
|
||||||
|
" </command>\n" +
|
||||||
|
" <command name=\"prog\" requires=\"verilog\" filter=\"true\">\n" +
|
||||||
|
" <arg>make</arg>\n" +
|
||||||
|
" <arg><?=dir?>/<?=shortname?>.v</arg>\n" +
|
||||||
|
" </command>\n" +
|
||||||
|
" </commands>\n" +
|
||||||
|
" </ide>\n";
|
||||||
|
|
||||||
|
|
||||||
|
ToBreakRunner br = new ToBreakRunner(new File(Resources.getRoot(), "dig/hdl/negSimple.dig"));
|
||||||
|
|
||||||
|
final TestFileWriter fileWriter = new TestFileWriter();
|
||||||
|
Configuration c = Configuration.load(new ByteArrayInputStream(xml.getBytes()))
|
||||||
|
.setFilenameProvider(() -> new File("z/test.dig"))
|
||||||
|
.setCircuitProvider(br::getCircuit)
|
||||||
|
.setLibraryProvider(br::getLibrary)
|
||||||
|
.setFileWriter(fileWriter);
|
||||||
|
ArrayList<Command> commands = c.getCommands();
|
||||||
|
assertEquals(2, commands.size());
|
||||||
|
|
||||||
|
c.executeCommand(commands.get(0));
|
||||||
|
|
||||||
|
assertEquals(1, fileWriter.files.size());
|
||||||
|
assertTrue(fileWriter.files.containsKey("z/test.v"));
|
||||||
|
|
||||||
|
assertEquals(1, fileWriter.commands.size());
|
||||||
|
assertEquals("z", fileWriter.commands.get(0).dir.getPath());
|
||||||
|
assertEquals("[make]", Arrays.toString(fileWriter.commands.get(0).args));
|
||||||
|
|
||||||
|
fileWriter.clear();
|
||||||
|
c.executeCommand(commands.get(1));
|
||||||
|
|
||||||
|
assertEquals(1, fileWriter.files.size());
|
||||||
|
assertTrue(fileWriter.files.containsKey("z/test.v"));
|
||||||
|
|
||||||
|
assertEquals(1, fileWriter.commands.size());
|
||||||
|
assertEquals("z", fileWriter.commands.get(0).dir.getPath());
|
||||||
|
assertEquals("[make, z/test.v]", Arrays.toString(fileWriter.commands.get(0).args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFileWriter() throws IOException, ElementNotFoundException, PinException, NodeException {
|
||||||
|
String xml = "<ide name=\"APIO\">\n" +
|
||||||
|
" <commands>\n" +
|
||||||
|
" <command name=\"build\" requires=\"verilog\" filter=\"false\">\n" +
|
||||||
|
" <arg>make</arg>\n" +
|
||||||
|
" </command>\n" +
|
||||||
|
" </commands>\n" +
|
||||||
|
" <files>\n" +
|
||||||
|
" <file name=\"file1\" overwrite=\"true\" filter=\"false\">\n" +
|
||||||
|
" <content>deal with <?=path?></content>\n" +
|
||||||
|
" </file>\n" +
|
||||||
|
" <file name=\"file2\" overwrite=\"true\" filter=\"true\">\n" +
|
||||||
|
" <content>deal with <?=path?></content>\n" +
|
||||||
|
" </file>\n" +
|
||||||
|
" <file name=\"<?=shortname?>.z\" overwrite=\"true\" filter=\"false\">\n" +
|
||||||
|
" <content>test</content>\n" +
|
||||||
|
" </file>\n" +
|
||||||
|
" </files>\n" +
|
||||||
|
" </ide>\n";
|
||||||
|
|
||||||
|
|
||||||
|
ToBreakRunner br = new ToBreakRunner(new File(Resources.getRoot(), "dig/hdl/negSimple.dig"));
|
||||||
|
|
||||||
|
final TestFileWriter fileWriter = new TestFileWriter();
|
||||||
|
Configuration c = Configuration.load(new ByteArrayInputStream(xml.getBytes()))
|
||||||
|
.setFilenameProvider(() -> new File("z/test.dig"))
|
||||||
|
.setCircuitProvider(br::getCircuit)
|
||||||
|
.setLibraryProvider(br::getLibrary)
|
||||||
|
.setFileWriter(fileWriter);
|
||||||
|
ArrayList<Command> commands = c.getCommands();
|
||||||
|
assertEquals(1, commands.size());
|
||||||
|
|
||||||
|
c.executeCommand(commands.get(0));
|
||||||
|
|
||||||
|
assertEquals(4, fileWriter.files.size());
|
||||||
|
assertEquals("deal with <?=path?>", fileWriter.files.get("z/file1").toString());
|
||||||
|
assertEquals("deal with z/test.dig", fileWriter.files.get("z/file2").toString());
|
||||||
|
assertEquals("test", fileWriter.files.get("z/test.z").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class TestFileWriter implements Configuration.FileWriter {
|
||||||
|
private HashMap<String, ByteArrayOutputStream> files = new HashMap<>();
|
||||||
|
private ArrayList<StartedCommand> commands = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream getOutputStream(File filename) {
|
||||||
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
files.put(filename.getPath(), baos);
|
||||||
|
return baos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startProcess(File dir, String[] args) {
|
||||||
|
commands.add(new StartedCommand(dir, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showError(Command command, Exception e) {
|
||||||
|
throw new RuntimeException(command.getName(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clear() {
|
||||||
|
files.clear();
|
||||||
|
commands.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StartedCommand {
|
||||||
|
private final File dir;
|
||||||
|
private final String[] args;
|
||||||
|
|
||||||
|
private StartedCommand(File dir, String[] args) {
|
||||||
|
this.dir = dir;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user