Skip to content

Commit

Permalink
Merge branch 'verilog'
Browse files Browse the repository at this point in the history
  • Loading branch information
hneemann committed Jun 11, 2018
2 parents 19193e9 + 814c703 commit d06f69e
Show file tree
Hide file tree
Showing 81 changed files with 5,078 additions and 59 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ buildNumber.properties
/Digital.sh
/upload.sh
/copyToPluginExample.sh

#netbeans project files
nbactions.xml
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ These are the main features of Digital:
See this [example](https://github.com/hneemann/digitalCustomComponents) for details.
- Simple remote TCP interface which e.g. allows an [assembler IDE](https://github.com/hneemann/Assembler) to control
the simulator.
- Components can be described using VHDL. The open source VHDL simulator [ghdl](http://ghdl.free.fr/) is required to
- Components can be described using VHDL. The open source VHDL simulator [ghdl](http://ghdl.free.fr/) is required to
simulate a VHDL defined component. The ghdl source code is also available at [GitHub](https://github.com/ghdl/ghdl).
- Export to VHDL: A circuit can be exported to VHDL. There is also support for the
- Export to VHDL: A circuit can be exported to VHDL. There is also support for the
[BASYS3 Board](https://reference.digilentinc.com/reference/programmable-logic/basys-3/start). See the documentation
for details. The examples folder contains a variant of the example CPU, which runs on a BASYS3 board.
- Direct export of JEDEC files which you can flash to a [GAL16v8](https://www.microchip.com/wwwproducts/en/ATF16V8C)
- Components can be described using Verilog. The open source Verilog simulator [Icarus Verilog](http://iverilog.icarus.com/) is required to
simulate a Verilog defined component. The Icarus Verilog source code is also available at [GitHub](https://github.com/steveicarus/iverilog).
- Exporting a circuit to Verilog is also possible. Special thanks to Ivan de Jesus Deras Tabora, who has
implemented the Verilog code generator and all the necessary Verilog templates!
- Direct export of JEDEC files which you can flash to a [GAL16v8](https://www.microchip.com/wwwproducts/en/ATF16V8C)
or a [GAL22v10](https://www.microchip.com/wwwproducts/en/ATF22V10C). These chips are somewhat outdated (introduced in 1985!)
but sufficient for beginners exercises, easy to understand and well documented. Also the
[ATF150x](https://www.microchip.com/design-centers/programmable-logic/spld-cpld/cpld-atf15xx-family) chips are
Expand Down
2 changes: 2 additions & 0 deletions distribution/ReleaseNotes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ HEAD, planned as v0.19
- Added a tabbed pane to the attributes dialog to make it more beginner friendly.
- Added support for asynchronous sequential circuits such as the Muller-pipeline.
Take a look at the new asynchronous examples for illustration.
- Added export to Verilog. Special thanks to Ivan de Jesus Deras Tabora, who has
implemented the Verilog code generator and all the necessary Verilog templates!
- All examples are translated to english.
- A "test all" function has been added to start all tests in all circuits in
the current folder.
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/de/neemann/digital/core/element/Keys.java
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,12 @@ private Keys() {
public static final Key<File> SETTINGS_GHDL_PATH
= new Key.KeyFile("ghdlPath", new File("ghdl")).setSecondary();

/**
* Path to iverilog installation directory
*/
public static final Key<File> SETTINGS_IVERILOG_PATH
= new Key.KeyFile("iverilogPath", new File("iverilog")).setSecondary();

/**
* Avoid component tooltips in the main panel
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ enum Type {
/**
* ghdl vhdl interpreter
*/
GHDL
GHDL,
/**
* Icarus verilog interpreter
*/
IVERILOG
}

/**
Expand All @@ -41,6 +45,8 @@ static Application create(Type type) {
return new ApplicationGeneric();
case GHDL:
return new ApplicationGHDL();
case IVERILOG:
return new ApplicationIVerilog();
default:
return null;
}
Expand Down
177 changes: 177 additions & 0 deletions src/main/java/de/neemann/digital/core/extern/ApplicationIVerilog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* Copyright (c) 2018 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.core.extern;

import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.extern.handler.ProcessInterface;
import de.neemann.digital.core.extern.handler.StdIOInterface;
import de.neemann.digital.gui.Settings;
import de.neemann.digital.lang.Lang;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;

/**
* Abstraction of the iverilog Application.
* See http://iverilog.icarus.com/
*/
public class ApplicationIVerilog extends ApplicationVerilogStdIO {
private String iverilogFolder;
private String iverilog;
private String vvp;
private final boolean hasIverilog;

/**
* Initialize a new instance
*/
public ApplicationIVerilog() {
iverilogFolder = "";
hasIverilog = findIVerilog();
}

@Override
public ProcessInterface start(String label, String code, PortDefinition inputs, PortDefinition outputs) throws IOException {
File file = null;

if (!hasIverilog) {
throw new IOException(Lang.get("err_iverilogNotInstalled"));
}

try {
String ivlModuleDir = iverilogFolder + File.separator + "lib" + File.separator + "ivl";

file = createVerilogFile(label, code, inputs, outputs);
String testOutputName = label + ".out";
String m1 = ProcessStarter.start(file.getParentFile(), iverilog, "-tvvp", "-o" + testOutputName, file.getName());
ProcessBuilder pb = new ProcessBuilder(vvp, "-M", ivlModuleDir, testOutputName).redirectErrorStream(true).directory(file.getParentFile());
return new IVerilogProcessInterface(pb.start(), file.getParentFile());
} catch (IOException e) {
if (file != null)
ProcessStarter.removeFolder(file.getParentFile());
if (iverilogNotFound(e))
throw new IOException(Lang.get("err_iverilogNotInstalled"));
else
throw e;
}
}

private boolean iverilogNotFound(Throwable e) {
while (e != null) {
if (e instanceof ProcessStarter.CouldNotStartProcessException)
return true;
e = e.getCause();
}
return false;
}

@Override
public boolean checkSupported() {
return true;
}

@Override
public String checkCode(String label, String code, PortDefinition inputs, PortDefinition outputs) throws IOException {
File file = null;

if (!hasIverilog) {
throw new IOException(Lang.get("err_iverilogNotInstalled"));
}
try {
file = createVerilogFile(label, code, inputs, outputs);
String testOutputName = label + ".out";

return ProcessStarter.start(file.getParentFile(), iverilog, "-tvvp", "-o" + testOutputName, file.getName());
} catch (IOException e) {
if (iverilogNotFound(e))
throw new IOException(Lang.get("err_iverilogNotInstalled"));
else
throw e;
} finally {
if (file != null)
ProcessStarter.removeFolder(file.getParentFile());
}
}

private boolean findIVerilog() {
Path ivp = null;
File ivDir = Settings.getInstance().get(Keys.SETTINGS_IVERILOG_PATH);

if (ivDir != null) {
Path p = Paths.get(ivDir.getAbsolutePath());

if (Files.isExecutable(p)) {
ivp = p;
if (Files.isSymbolicLink(p)) {
try {
ivp = Files.readSymbolicLink(ivp);
} catch (IOException ex) {
return false;
}
}
}
}

if (ivp == null) {
// Let's try to find iverilog in the system path
String[] strPaths = System.getenv("PATH").split(File.pathSeparator);

for (String sp : strPaths) {
Path p = Paths.get(sp, "iverilog");

if (Files.isExecutable(p)) {
ivp = p;
if (Files.isSymbolicLink(p)) {
try {
ivp = Files.readSymbolicLink(ivp);
} catch (IOException ex) {
return false;
}
}
break;
}
}
}

if (ivp != null) {
iverilogFolder = ivp.getParent().getParent().toString();
iverilog = ivp.getParent().resolve("iverilog").toString();
vvp = ivp.getParent().resolve("vvp").toString();

return true;
} else {
return false;
}
}

private static final class IVerilogProcessInterface extends StdIOInterface {
private final File folder;

private IVerilogProcessInterface(Process process, File folder) {
super(process);
this.folder = folder;
}

@Override
public String getConsoleOutNoWarn(LinkedList<String> consoleOut) {
StringBuilder sb = new StringBuilder();
for (String s : consoleOut) {
if (!s.contains(": warning:") && !s.contains(": :"))
sb.append(s).append("\n");
}
return sb.toString();
}

@Override
public void close() throws IOException {
super.close();
ProcessStarter.removeFolder(folder);
}
}
}
Loading

0 comments on commit d06f69e

Please sign in to comment.