Skip to content

Commit

Permalink
Merge pull request #1582 from danilovesky/verilog-time-units
Browse files Browse the repository at this point in the history
Add time units and precision to Verilog export
  • Loading branch information
danilovesky committed Feb 27, 2024
2 parents a15738e + dcc7462 commit 56ced08
Show file tree
Hide file tree
Showing 21 changed files with 1,519 additions and 1,366 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion ci/export-circuit/vme-tm.circuit.js
Expand Up @@ -3,7 +3,7 @@ setConfigVar("CommonEditorSettings.exportHeaderStyle", "BRIEF");
we = load("vme-tm.circuit.work");

exportCircuitVerilog(we, "vme-tm.circuit.v");
exportCircuitVerilogAssign(we, "vme-assign.circuit.v");
exportCircuitSystemVerilogAssigns(we, "vme-assign.circuit.sv");

exportSvg(we, "vme-tm.circuit.svg");
exportPng(we, "vme-tm.circuit.png");
Expand Down
1 change: 1 addition & 0 deletions ci/help/exportHelp.txt.min
@@ -1,3 +1,4 @@
exportCircuitSystemVerilogAssigns(work, svFileName) - export the Circuit 'work' as a System Verilog (*.sv) file 'svFileName' with assign statements
exportCircuitVerilog(work, vFileName) - export the Circuit 'work' as a Verilog netlist (*.v) file 'vFileName'
exportDfsVerilog(work, vFileName) - export the DFS 'work' as a Verilog netlist (*.v) file 'vFileName'
exportDot(work, fileName) - export the model 'work' as a GraphViz (*.dot) file 'fileName'
Expand Down
1 change: 1 addition & 0 deletions ci/help/importHelp.txt.min
@@ -1,3 +1,4 @@
importCircuitSystemVerilogAssigns(svFileName, topModuleName) - import a Circuit 'topModuleName' (can be skipped for auto detection) with its dependencies from the given System Verilog (*.sv) file 'svFileName' and return its work
importCircuitVerilog(vFileName, topModuleName) - import a Circuit 'topModuleName' (can be skipped for auto detection) with its dependencies from the given Verilog netlist (*.v) file 'vFileName' and return its work
importFstSg(sgFileName) - import an FST from the State Graph (*.sg) file 'sgFileName' and return its work
importStgG(gFileName) - import an STG from the Signal Transition Graph (*.g) file 'gFileName' and return its work
Expand Down
Expand Up @@ -57,11 +57,15 @@ SKIP:
|
"/*" : WITHIN_COMMENT
|
<"`" (~["\r", "\n"])*>
<"`" (~["\r", "\n"])*> // Simulator directives, e.g. `timescale
|
<"#" ([ "0"-"9" ])* (["."])? ([ "0"-"9" ])+> // Simple delay
|
"#(" { delayNestingDepth = 1 ; } : WITHIN_DELAY // Complex delay
|
<"timeunit" (~[";"])* ";"> // System Verilog timeunit
|
<"timeprecision" (~[";"])* ";"> // System Verilog timeprecision
}

<WITHIN_COMMENT> SKIP: { "*/" : DEFAULT }
Expand Down
25 changes: 18 additions & 7 deletions workcraft/CircuitPlugin/res/scripts/circuit-file.js
Expand Up @@ -3,12 +3,23 @@ framework.addJavaScriptHelp("importCircuitVerilog", "vFileName, topModuleName",

function importCircuitVerilog(vFileName, topModuleName) {
if (!vFileName.endsWith(".v")) {
throw("Verilog netlist file '" + vFileName + "' has incorrect extension, as '.v' is expected");
throw("Verilog file '" + vFileName + "' has incorrect extension, as '.v' is expected");
}
return (topModuleName == undefined) ? framework.importWork(vFileName)
: framework.importWork(vFileName, topModuleName);
}

framework.addJavaScriptHelp("importCircuitSystemVerilogAssigns", "svFileName, topModuleName",
"import a Circuit 'topModuleName' (can be skipped for auto detection) with its dependencies from the given System Verilog (*.sv) file 'svFileName' and return its work");

function importCircuitSystemVerilogAssigns(svFileName, topModuleName) {
if (!svFileName.endsWith(".sv")) {
throw("System Verilog file '" + svFileName + "' has incorrect extension, as '.sv' is expected");
}
return (topModuleName == undefined) ? framework.importWork(svFileName)
: framework.importWork(svFileName, topModuleName);
}


framework.addJavaScriptHelp("exportCircuitVerilog", "work, vFileName",
"export the Circuit 'work' as a Verilog netlist (*.v) file 'vFileName'");
Expand All @@ -21,12 +32,12 @@ function exportCircuitVerilog(work, vFileName) {
}


framework.addJavaScriptHelp("exportCircuitVerilogAssigns", "work, vFileName",
"export the Circuit 'work' as a Verilog assigns (*.v) file 'vFileName'");
framework.addJavaScriptHelp("exportCircuitSystemVerilogAssigns", "work, svFileName",
"export the Circuit 'work' as a System Verilog (*.sv) file 'svFileName' with assign statements");

function exportCircuitVerilogAssign(work, vFileName) {
if (!vFileName.endsWith(".v")) {
throw("Verilog file '" + vFileName + "' has incorrect extension, as '.v' is expected");
function exportCircuitSystemVerilogAssigns(work, svFileName) {
if (!svFileName.endsWith(".sv")) {
throw("System Verilog file '" + svFileName + "' has incorrect extension, as '.sv' is expected");
}
framework.exportWork(work, vFileName, 'VERILOG ASSIGNS');
framework.exportWork(work, svFileName, 'SYSTEM VERILOG ASSIGNS');
}
Expand Up @@ -22,7 +22,7 @@ public VisualCircuitDescriptor getVisualModelDescriptor() {

@Override
public Version getCompatibilityVersion() {
return new Version(3, 2, 0, Version.Status.RELEASE);
return new Version(3, 5, 0, Version.Status.RELEASE);
}

}
Expand Up @@ -6,10 +6,7 @@
import org.workcraft.plugins.Plugin;
import org.workcraft.plugins.PluginManager;
import org.workcraft.plugins.circuit.commands.*;
import org.workcraft.plugins.circuit.interop.GenlibImporter;
import org.workcraft.plugins.circuit.interop.VerilogAssignExporter;
import org.workcraft.plugins.circuit.interop.VerilogImporter;
import org.workcraft.plugins.circuit.interop.VerilogNetlistExporter;
import org.workcraft.plugins.circuit.interop.*;
import org.workcraft.plugins.circuit.serialisation.FunctionDeserialiser;
import org.workcraft.plugins.circuit.serialisation.FunctionSerialiser;
import org.workcraft.utils.ScriptableCommandUtils;
Expand Down Expand Up @@ -37,8 +34,9 @@ private void initPluginManager() {
pm.registerSettings(CircuitSettings.class);

pm.registerExporter(VerilogNetlistExporter.class);
pm.registerExporter(VerilogAssignExporter.class);
pm.registerExporter(SystemVerilogAssignExporter.class);
pm.registerImporter(VerilogImporter.class);
pm.registerImporter(SystemVerilogImporter.class);
pm.registerImporter(GenlibImporter.class);

// Circuit layout settings and commands
Expand Down
Expand Up @@ -28,14 +28,22 @@
import java.util.regex.Pattern;

public class CircuitSettings extends AbstractModelSettings {

public static final Map<String, String> PREDEFINED_DELAY_PARAMETERS = new LinkedHashMap<>();

static {
PREDEFINED_DELAY_PARAMETERS.put("", "No delay");
PREDEFINED_DELAY_PARAMETERS.put("1", "One unit delay (should be defined using `timescale)");
PREDEFINED_DELAY_PARAMETERS.put("1", "One unit delay (time unit and precision should be defined)");
PREDEFINED_DELAY_PARAMETERS.put("(1ps * $urandom_range(40, 90))", "Random delay between 40ps and 90ps");
}

public static final Map<String, String> PREDEFINED_TIMESCALE_PARAMETERS = new LinkedHashMap<>();

static {
PREDEFINED_TIMESCALE_PARAMETERS.put("", "No delay");
PREDEFINED_TIMESCALE_PARAMETERS.put("1ns / 1ps", "1ns per unit with 1ps precision");
}

public static final String GATE_LIBRARY_TITLE = "Gate library for technology mapping";

private static final Pattern MUTEX_DATA_PATTERN = Pattern.compile(
Expand Down Expand Up @@ -93,6 +101,7 @@ public class CircuitSettings extends AbstractModelSettings {
private static final String keyImportSubstitutionLibrary = prefix + ".importSubstitutionLibrary";
private static final String keyInvertImportSubstitutionRules = prefix + ".invertImportSubstitutionRules";
private static final String keyVerilogAssignDelay = prefix + ".verilogAssignDelay";
private static final String keyVerilogTimescale = prefix + ".verilogTimescale";
private static final String keyBusSuffix = prefix + ".busSuffix";
private static final String keyDissolveSingletonBus = prefix + ".dissolveSingletonBus";
private static final String keyAcceptInoutPort = prefix + ".acceptInoutPort";
Expand Down Expand Up @@ -146,6 +155,7 @@ public class CircuitSettings extends AbstractModelSettings {
private static final String defaultImportSubstitutionLibrary = "";
private static final boolean defaultInvertImportSubstitutionRules = true;
private static final String defaultVerilogAssignDelay = "1";
private static final String defaultVerilogTimescale = "";
private static final String defaultBusSuffix = "__" + BUS_INDEX_PLACEHOLDER;
private static final boolean defaultDissolveSingletonBus = true;
private static final boolean defaultAcceptInoutPort = true;
Expand Down Expand Up @@ -199,6 +209,7 @@ public class CircuitSettings extends AbstractModelSettings {
private static String importSubstitutionLibrary = defaultImportSubstitutionLibrary;
private static boolean invertImportSubstitutionRules = defaultInvertImportSubstitutionRules;
private static String verilogAssignDelay = defaultVerilogAssignDelay;
private static String verilogTimescale = defaultVerilogTimescale;
private static String busSuffix = defaultBusSuffix;
private static boolean dissolveSingletonBus = defaultDissolveSingletonBus;
private static boolean acceptInoutPort = defaultAcceptInoutPort;
Expand Down Expand Up @@ -362,6 +373,16 @@ public Map<String, String> getChoice() {
}
});

properties.add(new PropertyDeclaration<>(String.class,
PropertyHelper.BULLET_PREFIX + "Verilog time unit / precision (empty to suppress)",
CircuitSettings::setVerilogTimescale,
CircuitSettings::getVerilogTimescale) {
@Override
public Map<String, String> getChoice() {
return PREDEFINED_TIMESCALE_PARAMETERS;
}
});

properties.add(new PropertyDeclaration<>(String.class,
PropertyHelper.BULLET_PREFIX + "Bus split/merge suffix on Verilog import/export ("
+ BUS_INDEX_PLACEHOLDER + " denotes index)",
Expand Down Expand Up @@ -543,6 +564,7 @@ public void load(Config config) {
setImportSubstitutionLibrary(config.getString(keyImportSubstitutionLibrary, defaultImportSubstitutionLibrary));
setInvertImportSubstitutionRules(config.getBoolean(keyInvertImportSubstitutionRules, defaultInvertImportSubstitutionRules));
setVerilogAssignDelay(config.getString(keyVerilogAssignDelay, defaultVerilogAssignDelay));
setVerilogTimescale(config.getString(keyVerilogTimescale, defaultVerilogTimescale));
setBusSuffix(config.getString(keyBusSuffix, defaultBusSuffix));
setDissolveSingletonBus(config.getBoolean(keyDissolveSingletonBus, defaultDissolveSingletonBus));
setAcceptInoutPort(config.getBoolean(keyAcceptInoutPort, defaultAcceptInoutPort));
Expand Down Expand Up @@ -596,6 +618,7 @@ public void save(Config config) {
config.set(keyImportSubstitutionLibrary, getImportSubstitutionLibrary());
config.setBoolean(keyInvertImportSubstitutionRules, getInvertImportSubstitutionRules());
config.set(keyVerilogAssignDelay, getVerilogAssignDelay());
config.set(keyVerilogTimescale, getVerilogTimescale());
config.set(keyBusSuffix, getBusSuffix());
config.setBoolean(keyDissolveSingletonBus, getDissolveSingletonBus());
config.setBoolean(keyAcceptInoutPort, getAcceptInoutPort());
Expand Down Expand Up @@ -801,6 +824,17 @@ public static void setVerilogAssignDelay(String value) {
}
}

public static String getVerilogTimescale() {
return verilogTimescale;
}

public static void setVerilogTimescale(String value) {
if (value == null) {
value = "";
}
verilogTimescale = value.trim();
}

public static String getBusSuffix() {
return busSuffix;
}
Expand Down
Expand Up @@ -11,6 +11,7 @@
import org.workcraft.plugins.circuit.tools.StateDecoration;
import org.workcraft.plugins.circuit.utils.CircuitUtils;
import org.workcraft.serialisation.NoAutoSerialisation;
import org.workcraft.types.Pair;
import org.workcraft.utils.ColorUtils;

import java.awt.*;
Expand Down Expand Up @@ -318,8 +319,9 @@ public Font getFanoutFont() {
}

protected void cacheFanoutRenderedText(DrawRequest r) {
int fanout = CircuitUtils.calcFanout((VisualCircuit) r.getModel(), this);
cacheFanoutRenderedText(Integer.toString(fanout), getFanoutFont());
Pair<Integer, Boolean> fanout = CircuitUtils.calcFanout((VisualCircuit) r.getModel(), this);
String fanoutText = fanout.getFirst() + (fanout.getSecond() ? "+" : "");
cacheFanoutRenderedText(fanoutText, getFanoutFont());
}

protected void cacheFanoutRenderedText(String text, Font font) {
Expand Down
Expand Up @@ -37,6 +37,8 @@ public abstract class AbstractVerilogExporter implements Exporter {
private static final String KEYWORD_ENDMODULE = "endmodule";
private static final String KEYWORD_ASSIGN = "assign";
private static final String KEYWORD_ASSIGN_DELAY = "#";
private static final String KEYWORD_TIMESCALE = "`timescale";
private static final String KEYWORD_TIMEUNIT = "timeunit";

private final Queue<Pair<File, Circuit>> refinementCircuits = new LinkedList<>();

Expand All @@ -57,6 +59,12 @@ public void serialise(Model model, OutputStream out) {
File file = getCurrentFile();
writer.write(ExportUtils.getExportHeader("Verilog netlist", "//", moduleName, file, getFormat()));
refinementCircuits.clear();
if (!getFormat().useSystemVerilogSyntax()) {
String timescale = CircuitSettings.getVerilogTimescale();
if ((timescale != null) && !timescale.isEmpty()) {
writer.write(KEYWORD_TIMESCALE + ' ' + timescale + "\n\n");
}
}
writeCircuit(writer, circuit, moduleName);
writeRefinementCircuits(writer);
writer.close();
Expand All @@ -74,7 +82,7 @@ private void writeCircuit(PrintWriter writer, Circuit circuit, String moduleName
}
CircuitSignalInfo circuitInfo = new CircuitSignalInfo(circuit);
writeHeader(writer, circuitInfo, moduleName);
writeInstances(writer, circuitInfo, getFormat());
writeInstances(writer, circuitInfo);
writeInitialState(writer, circuitInfo);
writer.write(KEYWORD_ENDMODULE);
writer.write('\n');
Expand Down Expand Up @@ -142,6 +150,12 @@ private void writeHeader(PrintWriter writer, CircuitSignalInfo circuitInfo, Stri
Set<VerilogBus> wireBuses = extractSignalBuses(wires, circuitInfo);
writeSignalDefinitions(writer, KEYWORD_WIRE, wires, wireBuses);
writer.write('\n');
if (getFormat().useSystemVerilogSyntax()) {
String timescale = CircuitSettings.getVerilogTimescale();
if ((timescale != null) && !timescale.isEmpty()) {
writer.write(" " + KEYWORD_TIMEUNIT + ' ' + timescale + ";\n\n");
}
}
}

private void adjustBuses(Set<String> inputs, Set<String> outputs, Set<String> wires,
Expand Down Expand Up @@ -212,8 +226,8 @@ private void writeSignalDefinitions(PrintWriter writer, String keyword, Set<Stri
}
}

private void writeInstances(PrintWriter writer, CircuitSignalInfo circuitInfo, VerilogFormat format) {
boolean useAssignments = format.useAssignOnly();
private void writeInstances(PrintWriter writer, CircuitSignalInfo circuitInfo) {
boolean useAssignments = getFormat().useAssignOnly();
// Write assign statements
boolean hasAssignments = false;
for (FunctionComponent component : circuitInfo.getCircuit().getFunctionComponents()) {
Expand Down

0 comments on commit 56ced08

Please sign in to comment.