diff --git a/src/main/java/de/neemann/digital/core/element/Keys.java b/src/main/java/de/neemann/digital/core/element/Keys.java index 775745e7d..288a0fe3e 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -537,5 +537,10 @@ public final class Keys { */ public static final Key.KeyFile SETTINGS_GHDL_PATH = new Key.KeyFile("ghdlPath", new File("ghdl")); + /** + * Path to iverilog + */ + public static final Key.KeyFile SETTINGS_IVERILOG_PATH + = new Key.KeyFile("iverilogPath", new File("iverilog")); } diff --git a/src/main/java/de/neemann/digital/hdl/verilog/ModuleList.java b/src/main/java/de/neemann/digital/hdl/verilog/ModuleList.java index 43ce02d0f..b126350e0 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/ModuleList.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/ModuleList.java @@ -63,4 +63,13 @@ public class ModuleList { public boolean isEmpty() { return moduleNameList.isEmpty(); } + + /** + * Returns the number of registered modules + * + * @return the number of registered modules + */ + public int size() { + return moduleCodeList.size(); + } } diff --git a/src/main/java/de/neemann/digital/hdl/verilog/VerilogCodeBuilder.java b/src/main/java/de/neemann/digital/hdl/verilog/VerilogCodeBuilder.java index 8f6bc0129..5c6bec47f 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/VerilogCodeBuilder.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/VerilogCodeBuilder.java @@ -94,6 +94,15 @@ public class VerilogCodeBuilder { } } + /** + * Return the HDL model associated with the builder + * + * @return the HDL model + */ + public HDLModel getModel() { + return model; + } + /** * Return the HDL node associated with the signal. * @@ -169,19 +178,12 @@ public class VerilogCodeBuilder { * @param codeIr the code IR */ public void setCodeIrForSignal(String signalName, VIRNode codeIr) { - if (signalName.equals("S25")) { - System.out.println("S25"); - } if (codeIrMap.containsKey(signalName)) { // The signal has been registered already, this can happen when // there is a loop between components VIRNode n = getSignalCodeIr(signalName); - if (n instanceof VEmptyStatement) { - VEmptyStatement dstmt = (VEmptyStatement) n; - - - } else if (n instanceof VDelegatedExpr) { + if (n instanceof VDelegatedExpr) { VDelegatedExpr dexpr = (VDelegatedExpr) n; statements.remove(dexpr.getStatement()); @@ -205,7 +207,7 @@ public class VerilogCodeBuilder { } else { throw new RuntimeException("BUG in the machine: Invalid code IR node '" + codeIr.getClass().toString() + "'"); } - } else { + } else if (!(n instanceof VEmptyStatement)) { throw new RuntimeException("BUG in the machine: Called twice to setCodeIR"); } } diff --git a/src/main/java/de/neemann/digital/hdl/verilog/VerilogGenerator.java b/src/main/java/de/neemann/digital/hdl/verilog/VerilogGenerator.java index 82fd19a9d..e1191af59 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/VerilogGenerator.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/VerilogGenerator.java @@ -74,6 +74,17 @@ public class VerilogGenerator implements Closeable { vlibrary = new VerilogLibrary(library); } + /** + * If called the integration of clock dividers and so on is omitted. + * Mainly used for tests. + * + * @return this for chained calls + */ + public VerilogGenerator omitClockDividers() { + this.omitClockDividers = true; + return this; + } + /** * Writes the file to the given stream * @@ -91,7 +102,7 @@ public class VerilogGenerator implements Closeable { BoardInterface board = BoardProvider.getInstance().getBoard(circuit); ModelList modelList = new ModelList(library); - File f = circuit.getOrigin(); + File f = out.getFile(); String moduleName = getBaseName(f.getName()); HDLModel model = new HDLModel(circuit, library, modelList).setName(moduleName); ModuleList moduleSet = new ModuleList(); @@ -120,7 +131,7 @@ public class VerilogGenerator implements Closeable { out.print(m).println(); } - //nodesWritten += vhdlLibrary.finish(out); + nodesWritten += moduleSet.size(); File outFile = out.getFile(); if (board != null && outFile != null) @@ -370,6 +381,13 @@ public class VerilogGenerator implements Closeable { return baseName; } + /** + * @return the test bench creator + */ + public VerilogTestBenchCreator getTestBenches() { + return testBenches; + } + @Override public void close() throws IOException { out.close(); diff --git a/src/main/java/de/neemann/digital/hdl/verilog/VerilogLibrary.java b/src/main/java/de/neemann/digital/hdl/verilog/VerilogLibrary.java index b3504b04f..dbb9caf98 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/VerilogLibrary.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/VerilogLibrary.java @@ -24,6 +24,7 @@ import de.neemann.digital.core.io.VDD; import de.neemann.digital.core.memory.Register; import de.neemann.digital.core.wiring.BitSelector; import de.neemann.digital.core.wiring.Decoder; +import de.neemann.digital.core.wiring.Demultiplexer; import de.neemann.digital.core.wiring.Driver; import de.neemann.digital.core.wiring.DriverInvSel; import de.neemann.digital.core.wiring.Multiplexer; @@ -42,6 +43,7 @@ import de.neemann.digital.hdl.verilog.lib.ComparatorVerilog; import de.neemann.digital.hdl.verilog.lib.ConstVerilog; import de.neemann.digital.hdl.verilog.lib.CustomElemVerilog; import de.neemann.digital.hdl.verilog.lib.DecoderVerilog; +import de.neemann.digital.hdl.verilog.lib.DemultiplexerVerilog; import de.neemann.digital.hdl.verilog.lib.DriverVerilog; import de.neemann.digital.hdl.verilog.lib.MulVerilog; import de.neemann.digital.hdl.verilog.lib.MultiplexerVerilog; @@ -93,6 +95,7 @@ public class VerilogLibrary { put(Ground.DESCRIPTION, new ConstVerilog(Ground.DESCRIPTION)); put(PriorityEncoder.DESCRIPTION, new PriorityEncoderVerilog()); put(Multiplexer.DESCRIPTION, new MultiplexerVerilog()); + put(Demultiplexer.DESCRIPTION, new DemultiplexerVerilog()); put(BitExtender.DESCRIPTION, new BitExtenderVerilog()); put(BitSelector.DESCRIPTION, new BitSelectorVerilog()); put(Add.DESCRIPTION, new AddVerilog(Add.DESCRIPTION, VOperator.ADD)); diff --git a/src/main/java/de/neemann/digital/hdl/verilog/VerilogTestBenchCreator.java b/src/main/java/de/neemann/digital/hdl/verilog/VerilogTestBenchCreator.java index 696487b27..7df2e009a 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/VerilogTestBenchCreator.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/VerilogTestBenchCreator.java @@ -220,7 +220,7 @@ public class VerilogTestBenchCreator { out.inc(); out.print("$display(\"") .print(line).print(": ") - .print(p.getName()).print(": Assert failed. Expected %h, found %h\", ") + .print(p.getName()).print(": (assertion error). Expected %h, found %h\", ") .print(valStr).print(", ").print(p.getName()).print(");").println(); out.println("$finish;"); out.dec().println("end"); diff --git a/src/main/java/de/neemann/digital/hdl/verilog/lib/CustomElemVerilog.java b/src/main/java/de/neemann/digital/hdl/verilog/lib/CustomElemVerilog.java index 1104b6b8f..9bea3ff7f 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/lib/CustomElemVerilog.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/lib/CustomElemVerilog.java @@ -41,9 +41,6 @@ public class CustomElemVerilog extends VerilogElement { VIRNode irnode = vcBuilder.getSignalCodeIr(p.getSignal()); VExpr inExpr = irnode.resolveToExpr(vcBuilder); - if (p.getSignal().getName().equals("S25")) { - System.out.println("buildCodeIr"); - } signalMappings.add(new VInstanceMapping(p.getName(), inExpr)); } diff --git a/src/main/java/de/neemann/digital/hdl/verilog/lib/DemultiplexerVerilog.java b/src/main/java/de/neemann/digital/hdl/verilog/lib/DemultiplexerVerilog.java new file mode 100644 index 000000000..300a1f301 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/verilog/lib/DemultiplexerVerilog.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Ivan Deras + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.hdl.verilog.lib; + +import de.neemann.digital.core.element.Keys; +import de.neemann.digital.core.wiring.Demultiplexer; +import de.neemann.digital.hdl.model.HDLException; +import de.neemann.digital.hdl.model.HDLNode; +import de.neemann.digital.hdl.model.Port; +import de.neemann.digital.hdl.model.Signal; +import de.neemann.digital.hdl.verilog.VerilogCodeBuilder; +import de.neemann.digital.hdl.verilog.ir.VIRNode; +import de.neemann.digital.hdl.verilog.ir.VOperator; +import de.neemann.digital.hdl.verilog.ir.VSignalDecl; +import de.neemann.digital.hdl.verilog.ir.expr.VBinaryExpr; +import de.neemann.digital.hdl.verilog.ir.expr.VConditionalExpr; +import de.neemann.digital.hdl.verilog.ir.expr.VConstExpr; +import de.neemann.digital.hdl.verilog.ir.expr.VExpr; +import de.neemann.digital.hdl.verilog.ir.stmt.VAssignStatement; +import de.neemann.digital.hdl.verilog.ir.stmt.VStatement; +import de.neemann.digital.hdl.verilog.ir.stmt.VStatementPlace; +import java.util.ArrayList; + +/** + * Demultiplexer verilog element + * + * @author ideras + */ +public class DemultiplexerVerilog extends VerilogElement { + + /** + * Initialize a new instance + */ + public DemultiplexerVerilog() { + super(Demultiplexer.DESCRIPTION); + } + + @Override + public void buildCodeIr(VerilogCodeBuilder vcBuilder, HDLNode node) throws HDLException { + int dataBits = node.get(Keys.BITS); + int selBits = node.get(Keys.SELECTOR_BITS); + + Signal selSignal = node.getPorts().getInputs().get(0).getSignal(); + Signal inSignal = node.getPorts().getInputs().get(1).getSignal(); + VIRNode selNode = vcBuilder.getSignalCodeIr(selSignal); + VIRNode inNode = vcBuilder.getSignalCodeIr(inSignal); + VExpr selExpr = selNode.resolveToExpr(vcBuilder); + VExpr inExpr = inNode.resolveToExpr(vcBuilder); + + ArrayList outputPorts = node.getPorts().getOutputs(); + for (int i = 0; i < outputPorts.size(); i++) { + Signal outSignal = outputPorts.get(i).getSignal(); + VStatementPlace outPlace = new VStatementPlace(outSignal); + VStatement stmt = new VAssignStatement(outPlace, + new VConditionalExpr( + new VBinaryExpr(selExpr, new VConstExpr(selBits, i), VOperator.EQ), + inExpr, + new VConstExpr(dataBits, 0)) + ); + + vcBuilder.registerSignalDecl(outSignal, VSignalDecl.Type.WIRE); + vcBuilder.setCodeIrForSignal(outSignal, stmt); + } + } + +} diff --git a/src/main/java/de/neemann/digital/hdl/verilog/lib/SplitterVerilog.java b/src/main/java/de/neemann/digital/hdl/verilog/lib/SplitterVerilog.java index f526bec7f..b682ebccf 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/lib/SplitterVerilog.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/lib/SplitterVerilog.java @@ -32,10 +32,36 @@ public class SplitterVerilog extends VerilogElement { @Override public void buildCodeIr(VerilogCodeBuilder vcBuilder, HDLNode node) throws HDLException { - if (node.getPorts().getInputs().size() == 1) { + VExpr inExpr; + + if (node.getPorts().getInputs().size() != 1) { + ArrayList exprList = new ArrayList<>(); + + int totalBits = 0; + for (Port p : node.getPorts().getInputs()) { + VIRNode inCodeIrNode = vcBuilder.getSignalCodeIr(p.getSignal()); + + exprList.add(0, inCodeIrNode.resolveToExpr(vcBuilder)); + totalBits += p.getBits(); + } + Signal s = vcBuilder.getModel().createSignal().setBits(totalBits); + inExpr = new VConcatExpr(exprList).setSignal(s); + } else { Signal inSignal = node.getPorts().getInputs().get(0).getSignal(); VIRNode inCodeIr = vcBuilder.getSignalCodeIr(inSignal); - VExpr inExpr = inCodeIr.resolveToExpr(vcBuilder); + inExpr = inCodeIr.resolveToExpr(vcBuilder); + } + + if (node.getPorts().getOutputs().size() == 1 + && node.getPorts().getOutputs().get(0).getBits() == inExpr.getSignal().getBits()) { + Port outPort = node.getPorts().getOutputs().get(0); + Signal outSignal = outPort.getSignal(); + + if (outSignal != null) { + inExpr.setSignal(outSignal); + vcBuilder.setCodeIrForSignal(outSignal, inExpr); + } + } else { inExpr = inExpr.resolveToIdExpr(vcBuilder); for (Port p : node.getPorts().getOutputs()) { @@ -61,23 +87,6 @@ public class SplitterVerilog extends VerilogElement { expr.setSignal(p.getSignal()); vcBuilder.setCodeIrForSignal(p.getSignal(), expr); } - } else { // Assumes one output signal - Port outPort = node.getPorts().getOutputs().get(0); - Signal outSignal = outPort.getSignal(); - - ArrayList exprList = new ArrayList<>(); - - for (Port p : node.getPorts().getInputs()) { - VIRNode inCodeIrNode = vcBuilder.getSignalCodeIr(p.getSignal()); - VExpr inExpr = inCodeIrNode.resolveToExpr(vcBuilder); - - exprList.add(0, inExpr); - } - VExpr expr = new VConcatExpr(exprList); - - expr.setSignal(outSignal); - vcBuilder.setCodeIrForSignal(outSignal, expr); } } - } diff --git a/src/main/java/de/neemann/digital/hdl/verilog/lib/VerilogFileTemplate.java b/src/main/java/de/neemann/digital/hdl/verilog/lib/VerilogFileTemplate.java index 0db0e11f1..98f6274b4 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog/lib/VerilogFileTemplate.java +++ b/src/main/java/de/neemann/digital/hdl/verilog/lib/VerilogFileTemplate.java @@ -161,7 +161,14 @@ public class VerilogFileTemplate extends VerilogElement { // ensures the usage of the correct default value key = findKey(keyName); } - genericMappings.add(new VGenericMapping(keyName, node.get(key).toString())); + Object keyVal = node.get(key); + String kvs; + if (keyVal instanceof Boolean) { + kvs = ((Boolean) keyVal)? "1" : "0"; + } else { + kvs = keyVal.toString(); + } + genericMappings.add(new VGenericMapping(keyName, kvs)); } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 1802a2f8d..d3ecaa846 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1103,6 +1103,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig? GHDL Pfad der ausführbaren ghdl-Datei. Nur wichtig, wenn ghdl zur Interpretation von VHDL-Code verwendet werden soll. + GHDL + Pfad der ausführbaren iverilog-Datei. Nur wichtig, wenn ghdl zur Interpretation von + Verilog-Code verwendet werden soll. Leitung eingefügt. Aus Zwischenablage eingefügt. diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 085cb3e66..5f59c6c6e 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -665,7 +665,7 @@ input B control input. inverted control input - + Line {0} : {1} Unterminated block comment @@ -1093,6 +1093,9 @@ GHDL Path to the executable ghdl file. Only necessary if you want to use ghdl to simulate components defined with vhdl. + iverilog + Path to the executable iverilog file. Only necessary if you want to use iverilog to simulate + components defined with verilog. Inserted wire. Insert from clipboard. @@ -1288,7 +1291,7 @@ Export to VHDL Exports the circuit to VHDL Export to Verilog - Exports the circuit to Verilog + Exports the circuit to Verilog Documentation Open {0} Error opening a PDF file! diff --git a/src/main/resources/verilog/DIG_RAMDualAccess.v b/src/main/resources/verilog/DIG_RAMDualAccess.v index d5ff9beec..dec00fc0f 100644 --- a/src/main/resources/verilog/DIG_RAMDualAccess.v +++ b/src/main/resources/verilog/DIG_RAMDualAccess.v @@ -12,8 +12,8 @@ generics[1] = "AddrBits"; input PORT_C, // Clock signal input PORT_ld, input [(AddrBits-1):0] PORT_1A, - input [(Bits-1):0] PORT_1D_in, input [(AddrBits-1):0] PORT_2A, + input [(Bits-1):0] PORT_1Din, input PORT_str, output [(Bits-1):0] PORT_1D, output [(Bits-1):0] PORT_2D @@ -25,7 +25,7 @@ generics[1] = "AddrBits"; always @ (posedge PORT_C) begin if (PORT_str) - memory[PORT_1A] <= PORT_1D_in; + memory[PORT_1A] <= PORT_1Din; end endmodule diff --git a/src/main/resources/verilog/DIG_RAMDualPort.v b/src/main/resources/verilog/DIG_RAMDualPort.v index 8e2bb8ccc..d1e9bd580 100644 --- a/src/main/resources/verilog/DIG_RAMDualPort.v +++ b/src/main/resources/verilog/DIG_RAMDualPort.v @@ -10,7 +10,7 @@ generics[1] = "AddrBits"; ) ( input [(AddrBits-1):0] PORT_A, - input [(Bits-1):0] PORT_D_in, + input [(Bits-1):0] PORT_Din, input PORT_str, input PORT_C, input PORT_ld, @@ -22,6 +22,6 @@ generics[1] = "AddrBits"; always @ (posedge PORT_C) begin if (PORT_str) - memory[PORT_A] <= PORT_D_in; + memory[PORT_A] <= PORT_Din; end endmodule diff --git a/src/main/resources/verilog/DIG_Reset.v b/src/main/resources/verilog/DIG_Reset.v new file mode 100644 index 000000000..72fcf4923 --- /dev/null +++ b/src/main/resources/verilog/DIG_Reset.v @@ -0,0 +1,13 @@ + +module +#( + parameter invertOutput = 0 +) +( + output PORT_Reset +); + // ToDo: how to deal with the reset pin? + assign PORT_Reset = invertOutput; +endmodule \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/hdl/verilog/TestInSimulator.java b/src/test/java/de/neemann/digital/hdl/verilog/TestInSimulator.java new file mode 100644 index 000000000..19617e791 --- /dev/null +++ b/src/test/java/de/neemann/digital/hdl/verilog/TestInSimulator.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018 Ivan Deras + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.hdl.verilog; + +import de.neemann.digital.core.ExceptionWithOrigin; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.extern.ProcessStarter; +import de.neemann.digital.draw.elements.PinException; +import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.hdl.model.HDLException; +import de.neemann.digital.hdl.printer.CodePrinter; +import de.neemann.digital.integration.FileScanner; +import de.neemann.digital.integration.Resources; +import de.neemann.digital.integration.ToBreakRunner; +import junit.framework.TestCase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +/** + * Test verilog files in icarus verilog simulator + */ +public class TestInSimulator extends TestCase { + private static final Logger LOGGER = LoggerFactory.getLogger(TestInSimulator.class); + private static String IVERILOG = System.getProperty("iverilog", ""); + private static String IVERILOG_DIR; + private static String VVP; + private static final boolean foundIVerilog = findIVerilogDir(); + + private int testBenches; + + public void testInSimulator() throws Exception { + File examples = new File(Resources.getRoot(), "/dig/test/vhdl"); + try { + int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples); + assertEquals(27, tested); + assertEquals(tested, testBenches); + } catch (FileScanner.SkipAllException e) { + // if iverilog is not installed its also ok + } + } + + public void testInSimulator2() throws Exception { + File examples = new File(Resources.getRoot(), "/dig/hdl"); + try { + int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples); + assertEquals(28, tested); + } catch (FileScanner.SkipAllException e) { + // if iverilog is not installed its also ok + } + } + + public void testDistributedInSimulator() throws Exception { + File examples = new File(Resources.getRoot(), "../../main/dig/vhdl"); + try { + int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples); + assertEquals(1, tested); + assertEquals(1, testBenches); + } catch (FileScanner.SkipAllException e) { + // if iverilog is not installed its also ok + } + } + + public void testProcessorInSimulator() throws Exception { + File file = new File(Resources.getRoot(), "../../main/dig/processor/VHDLExample.dig"); + try { + checkVerilogExport(file); + } catch (FileScanner.SkipAllException e) { + // if iverilog is not installed its also ok + } catch (Exception e) { + System.out.println(ExceptionWithOrigin.getOriginOf(e)); + throw e; + } + } + + private void checkVerilogExport(File file) throws PinException, NodeException, ElementNotFoundException, IOException, FileScanner.SkipAllException, HDLException { + ToBreakRunner br = new ToBreakRunner(file); + File dir = Files.createTempDirectory("digital_vhdl_" + getTime() + "_").toFile(); + try { + File sourceFile = new File(dir, file.getName().replace('.', '_') + ".v"); + CodePrinter out = new CodePrinter(sourceFile); + try (VerilogGenerator vgen = new VerilogGenerator(br.getLibrary(), out)) { + vgen.omitClockDividers().export(br.getCircuit()); + VerilogTestBenchCreator tb = vgen.getTestBenches(); + out.close(); + runIVerilog(sourceFile, tb.getTestFileWritten()); + } + } finally { + br.close(); + ProcessStarter.removeFolder(dir); + } + } + + private void runIVerilog(File sourceFile, ArrayList testFileWritten) throws IOException, FileScanner.SkipAllException, HDLException { + String ivlModuleDir = IVERILOG_DIR + File.separator + "lib" + File.separator + "ivl"; + for (File testbench : testFileWritten) { + String name = testbench.getName(); + String module = name.substring(0, name.length() - 2); + String testOutputName = module + ".out"; + + checkWarn(testbench, startProcess(sourceFile.getParentFile(), IVERILOG, "-tvvp", "-o" + testOutputName, sourceFile.getName(), name)); + + String result = startProcess(sourceFile.getParentFile(), VVP, "-M", ivlModuleDir, testOutputName); + if (result.contains("(assertion error)")) + throw new HDLException("test bench " + name + " failed:\n" + result); + checkWarn(testbench, result); + testBenches++; + } + } + + private void checkWarn(File file, String result) { + if (result.contains("warning")) { + System.out.println(file); + System.out.println(result); + } + } + + private String startProcess(File dir, String... args) throws IOException, FileScanner.SkipAllException { + try { + return ProcessStarter.start(dir, args); + } catch (ProcessStarter.CouldNotStartProcessException e) { + throw new FileScanner.SkipAllException("iverilog (https://github.com/steveicarus/iverilog) is not installed! Add iverilog binary to the system path or set system property 'iverilog' to iverilog binary"); + } + } + + private String getTime() { + DateFormat f = new SimpleDateFormat("YY-MM-dd_HH-mm_ss"); + return f.format(new Date()); + } + + private static boolean findIVerilogDir() { + Path ivp = null; + + if (!IVERILOG.isEmpty()) { + Path p = Paths.get(IVERILOG); + + if (Files.isExecutable(p)) { + ivp = p; + if (Files.isSymbolicLink(p)) { + try { + ivp = Files.readSymbolicLink(ivp); + } catch (IOException ex) { + LOGGER.info("I/O Exception: " + ex.getMessage()); + 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) { + LOGGER.info("I/O Exception: " + ex.getMessage()); + return false; + } + } + break; + } + } + } + + if (ivp != null) { + IVERILOG_DIR = ivp.getParent().getParent().toString(); + IVERILOG = ivp.getParent().resolve("iverilog").toString(); + VVP = ivp.getParent().resolve("vvp").toString(); + + return true; + } else { + return false; + } + } +}