mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-17 00:44:40 -04:00
- Added automated testing for the verilog exporter.
- Added missing elements (Reset and Demultiplexer) to the verilog exporter. - Added missing functionality in the splitter verilog exporter element. - Some small BUG fixes.
This commit is contained in:
parent
f5805a1717
commit
f8f5d6ae07
@ -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"));
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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");
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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<Port> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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<VExpr> 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<VExpr> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1103,6 +1103,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="key_ghdlPath">GHDL</string>
|
||||
<string name="key_ghdlPath_tt">Pfad der ausführbaren ghdl-Datei. Nur wichtig, wenn ghdl zur Interpretation von
|
||||
VHDL-Code verwendet werden soll.</string>
|
||||
<string name="key_iverilogPath">GHDL</string>
|
||||
<string name="key_iverilogPath_tt">Pfad der ausführbaren iverilog-Datei. Nur wichtig, wenn ghdl zur Interpretation von
|
||||
Verilog-Code verwendet werden soll.</string>
|
||||
|
||||
<string name="mod_insertWire">Leitung eingefügt.</string>
|
||||
<string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string>
|
||||
|
@ -1093,6 +1093,9 @@
|
||||
<string name="key_ghdlPath">GHDL</string>
|
||||
<string name="key_ghdlPath_tt">Path to the executable ghdl file. Only necessary if you want to use ghdl to simulate
|
||||
components defined with vhdl.</string>
|
||||
<string name="key_iverilogPath">iverilog</string>
|
||||
<string name="key_iverilogPath_tt">Path to the executable iverilog file. Only necessary if you want to use iverilog to simulate
|
||||
components defined with verilog.</string>
|
||||
|
||||
<string name="mod_insertWire">Inserted wire.</string>
|
||||
<string name="mod_insertCopied">Insert from clipboard.</string>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
13
src/main/resources/verilog/DIG_Reset.v
Normal file
13
src/main/resources/verilog/DIG_Reset.v
Normal file
@ -0,0 +1,13 @@
|
||||
<?
|
||||
generics[0] = "invertOutput";
|
||||
?>
|
||||
module <?= elem.name ?>
|
||||
#(
|
||||
parameter invertOutput = 0
|
||||
)
|
||||
(
|
||||
output PORT_Reset
|
||||
);
|
||||
// ToDo: how to deal with the reset pin?
|
||||
assign PORT_Reset = invertOutput;
|
||||
endmodule
|
@ -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<File> 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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user