added comments to vhdl output

This commit is contained in:
hneemann 2018-03-26 14:03:33 +02:00
parent 5179b720ae
commit 7890ec22f2
11 changed files with 357 additions and 32 deletions

View File

@ -43,6 +43,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
private final ArrayList<HDLPort> outputs; private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> inputs; private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLNet> listOfNets; private final ArrayList<HDLNet> listOfNets;
private final String description;
private ArrayList<HDLPort> ports; private ArrayList<HDLPort> ports;
private NetList netList; private NetList netList;
private ArrayList<HDLNode> nodes; private ArrayList<HDLNode> nodes;
@ -89,6 +90,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
nets = new HashMap<>(); nets = new HashMap<>();
listOfNets = new ArrayList<>(); listOfNets = new ArrayList<>();
netList = new NetList(circuit); netList = new NetList(circuit);
description = circuit.getAttributes().get(Keys.DESCRIPTION);
ArrayList<ClockInfo> clocks = new ArrayList<>(); ArrayList<ClockInfo> clocks = new ArrayList<>();
@ -100,7 +102,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
getNetOfPin(v.getPins().get(0)), getNetOfPin(v.getPins().get(0)),
HDLPort.Direction.OUT, // from inside the node this is an output because it defines a value HDLPort.Direction.OUT, // from inside the node this is an output because it defines a value
v.getElementAttributes().getBits()) v.getElementAttributes().getBits())
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER)); .setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))
.setDescription(v.getElementAttributes().get(Keys.DESCRIPTION));
addInput(port); addInput(port);
if (v.equalsDescription(Clock.DESCRIPTION)) if (v.equalsDescription(Clock.DESCRIPTION))
clocks.add(new ClockInfo(port, v.getElementAttributes().get(Keys.FREQUENCY))); clocks.add(new ClockInfo(port, v.getElementAttributes().get(Keys.FREQUENCY)));
@ -110,7 +113,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
getNetOfPin(v.getPins().get(0)), getNetOfPin(v.getPins().get(0)),
HDLPort.Direction.IN, // from inside the node this is an input because it reads the value to output HDLPort.Direction.IN, // from inside the node this is an input because it reads the value to output
v.getElementAttributes().getBits()) v.getElementAttributes().getBits())
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))); .setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))
.setDescription(v.getElementAttributes().get(Keys.DESCRIPTION)));
else if (v.equalsDescription(Splitter.DESCRIPTION)) else if (v.equalsDescription(Splitter.DESCRIPTION))
handleSplitter(c.createNode(v, this)); handleSplitter(c.createNode(v, this));
else if (isRealElement(v)) else if (isRealElement(v))
@ -460,6 +464,20 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
return hdlEntityName; return hdlEntityName;
} }
/**
* @return the description of this circuit
*/
public String getDescription() {
return description;
}
/**
* @return true if the circuit has a description
*/
public boolean hasDescription() {
return description != null && description.trim().length() > 0;
}
/** /**
* Integrates a clock node. * Integrates a clock node.
* *

View File

@ -15,6 +15,8 @@ import java.io.IOException;
*/ */
public class HDLPort implements Printable, HasName { public class HDLPort implements Printable, HasName {
private String description;
/** /**
* The ports direction * The ports direction
*/ */
@ -71,6 +73,31 @@ public class HDLPort implements Printable, HasName {
return this; return this;
} }
/**
* Sets the description of this port.
*
* @param description the description
* @return this for chained calls
*/
public HDLPort setDescription(String description) {
this.description = description;
return this;
}
/**
* @return the ports description.
*/
public String getDescription() {
return description;
}
/**
* @return true if this port has a description
*/
public boolean hasDescription() {
return description != null && description.trim().length() > 0;
}
/** /**
* @return the net of this port * @return the net of this port
*/ */

View File

@ -18,6 +18,7 @@ public class CodePrinter implements Closeable {
private File file; private File file;
private int ident = 0; private int ident = 0;
private boolean newLine = true; private boolean newLine = true;
private int pos;
/** /**
* Creates a new instance * Creates a new instance
@ -139,7 +140,7 @@ public class CodePrinter implements Closeable {
*/ */
public CodePrinter print(char c) throws IOException { public CodePrinter print(char c) throws IOException {
if (newLine && c != '\n') { if (newLine && c != '\n') {
int pos = ident * indentWidth; pos = ident * indentWidth;
for (int i = 0; i < pos; i++) for (int i = 0; i < pos; i++)
out.write(' '); out.write(' ');
newLine = false; newLine = false;
@ -148,6 +149,8 @@ public class CodePrinter implements Closeable {
out.write(c); out.write(c);
else else
out.write(("" + c).getBytes(CHARSET)); out.write(("" + c).getBytes(CHARSET));
pos++;
if (c == '\n') { if (c == '\n') {
newLine = true; newLine = true;
eolIsWritten(); eolIsWritten();
@ -191,4 +194,38 @@ public class CodePrinter implements Closeable {
public File getFile() { public File getFile() {
return file; return file;
} }
/**
* Pronts a comment to the target file
*
* @param singleLineComment the string which opens a single line comment (-- in VHDL)
* @param comment the comment to print
* @return this for chained calls
* @throws IOException IOException
*/
public CodePrinter printComment(String singleLineComment, String comment) throws IOException {
if (comment == null || comment.length() == 0)
return this;
int startPos = pos;
if (newLine)
startPos = ident * indentWidth;
print(singleLineComment);
for (int i = 0; i < comment.length(); i++) {
char c = comment.charAt(i);
print(c);
if (c == '\n') {
int spaceCount = startPos - ident * indentWidth;
for (int j = 0; j < spaceCount; j++)
print(' ');
print(singleLineComment);
}
}
println();
return this;
}
} }

View File

@ -14,34 +14,88 @@ import java.io.IOException;
*/ */
public class Separator { public class Separator {
private final String sep; private final String sep;
private final CodePrinter out;
private final String finalizerSeparator;
private boolean first = true; private boolean first = true;
private LineFinalizer lineFinalizer;
/** /**
* Creates a new instance * Creates a new instance
* *
* @param out the print stream
* @param sep The separator * @param sep The separator
*/ */
public Separator(String sep) { public Separator(CodePrinter out, String sep) {
this.sep = sep; this.sep = sep;
this.out = out;
if (sep.length() > 0 && sep.charAt(sep.length() - 1) == '\n')
finalizerSeparator = sep.substring(0, sep.length() - 1);
else
finalizerSeparator = sep;
} }
/** /**
* Inserts the separator * Inserts the separator
* *
* @param out the print stream
* @throws IOException IOException * @throws IOException IOException
*/ */
public void check(CodePrinter out) throws IOException { public void check() throws IOException {
if (first) if (first)
first = false; first = false;
else else {
out.print(getSeperator()); if (lineFinalizer == null)
printSeparator(out);
else {
out.print(finalizerSeparator);
lineFinalizer.finalizeLine(out);
lineFinalizer = null;
}
}
} }
/** /**
* @return the separator * prints the separator
*
* @param out the print stream
* @throws IOException IOException
*/ */
public String getSeperator() { public void printSeparator(CodePrinter out) throws IOException {
return sep; out.print(sep);
}
/**
* Sets the line finalizer
* This finalizer is only used once at the next line ending.
*
* @param lineFinalizer thi file finalizer
*/
public void setLineFinalizer(LineFinalizer lineFinalizer) {
this.lineFinalizer = lineFinalizer;
}
/**
* Closes this Separator.
* If there is a pending line separator, it's printed.
*
* @throws IOException IOException
*/
public void close() throws IOException {
if (lineFinalizer != null)
lineFinalizer.finalizeLine(out);
}
/**
* If there is a finalizer, this finalizer method is called
* instead of calling printSeparator.
* A finerlizer is used only one time.
*/
public interface LineFinalizer {
/**
* Prints the line ending
*
* @param out the stream to print to
* @throws IOException IOException
*/
void finalizeLine(CodePrinter out) throws IOException;
} }
} }

View File

@ -104,6 +104,9 @@ public class VHDLCreator {
.println("USE ieee.numeric_std.all;") .println("USE ieee.numeric_std.all;")
.println(); .println();
if (circuit.hasDescription())
out.printComment("-- ", circuit.getDescription());
out.print("entity ").print(circuit.getHdlEntityName()).println(" is").inc(); out.print("entity ").print(circuit.getHdlEntityName()).println(" is").inc();
writePorts(out, circuit); writePorts(out, circuit);
out.dec(); out.dec();
@ -152,16 +155,19 @@ public class VHDLCreator {
public static void writePorts(CodePrinter out, HDLCircuit circuit) throws IOException { public static void writePorts(CodePrinter out, HDLCircuit circuit) throws IOException {
out.println("port (").inc(); out.println("port (").inc();
Separator sep = new Separator(";\n"); Separator sep = new Separator(out, ";\n");
for (HDLPort i : circuit.getInputs()) { for (HDLPort i : circuit.getInputs()) {
sep.check(out); sep.check();
out.print(i.getName()).print(": in ").print(getType(i.getBits())); out.print(i.getName()).print(": in ").print(getType(i.getBits()));
if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", i.getDescription()));
} }
for (HDLPort o : circuit.getOutputs()) { for (HDLPort o : circuit.getOutputs()) {
sep.check(out); sep.check();
out.print(o.getName()).print(": out ").print(getType(o.getBits())); out.print(o.getName()).print(": out ").print(getType(o.getBits()));
if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", o.getDescription()));
} }
sep.close();
out.println(");").dec(); out.println(");").dec();
} }
@ -204,16 +210,16 @@ public class VHDLCreator {
if (!(node instanceof HDLNodeCustom)) if (!(node instanceof HDLNodeCustom))
library.getEntity(node).writeGenericMap(out, node); library.getEntity(node).writeGenericMap(out, node);
out.println("port map (").inc(); out.println("port map (").inc();
Separator sep = new Separator(",\n"); Separator sep = new Separator(out, ",\n");
for (HDLPort i : node.getInputs()) for (HDLPort i : node.getInputs())
if (i.getNet() != null) { if (i.getNet() != null) {
sep.check(out); sep.check();
out.print(i.getName()).print(" => ").print(i.getNet().getName()); out.print(i.getName()).print(" => ").print(i.getNet().getName());
} }
for (HDLPort o : node.getOutputs()) for (HDLPort o : node.getOutputs())
if (o.getNet() != null) { if (o.getNet() != null) {
sep.check(out); sep.check();
out.print(o.getName()).print(" => ").print(o.getNet().getName()); out.print(o.getName()).print(" => ").print(o.getNet().getName());
} }
out.println(");").dec().dec(); out.println(");").dec().dec();

View File

@ -116,13 +116,13 @@ public class VHDLTestBenchCreator {
out.dec().println("begin").inc(); out.dec().println("begin").inc();
out.println("main_0 : main port map (").inc(); out.println("main_0 : main port map (").inc();
Separator comma = new Separator(",\n"); Separator comma = new Separator(out, ",\n");
for (HDLPort p : main.getInputs()) { for (HDLPort p : main.getInputs()) {
comma.check(out); comma.check();
out.print(p.getName() + " => " + p.getName()); out.print(p.getName() + " => " + p.getName());
} }
for (HDLPort p : main.getOutputs()) { for (HDLPort p : main.getOutputs()) {
comma.check(out); comma.check();
out.print(p.getName() + " => " + p.getName()); out.print(p.getName() + " => " + p.getName());
} }
out.println(" );").dec(); out.println(" );").dec();
@ -225,10 +225,10 @@ public class VHDLTestBenchCreator {
private LineListenerVHDL(CodePrinter out, ArrayList<HDLPort> dataOrder) { private LineListenerVHDL(CodePrinter out, ArrayList<HDLPort> dataOrder) {
this.out = out; this.out = out;
this.dataOrder = dataOrder; this.dataOrder = dataOrder;
lineSep = new Separator("") { lineSep = new Separator(out, "") {
@Override @Override
public String getSeperator() { public void printSeparator(CodePrinter out) throws IOException {
return ", -- i=" + (line++) + "\n"; out.print(", -- i=").print((line++)).print("\n");
} }
}; };
} }
@ -241,12 +241,12 @@ public class VHDLTestBenchCreator {
if (v.getType() == Value.Type.CLOCK) if (v.getType() == Value.Type.CLOCK)
containsClock = true; containsClock = true;
if (containsClock) { if (containsClock) {
lineSep.check(out); lineSep.check();
writeValues(values, true, 0); writeValues(values, true, 0);
lineSep.check(out); lineSep.check();
writeValues(values, true, 1); writeValues(values, true, 1);
} }
lineSep.check(out); lineSep.check();
writeValues(values, false, 0); writeValues(values, false, 0);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -255,9 +255,9 @@ public class VHDLTestBenchCreator {
private void writeValues(Value[] values, boolean isClock, int clock) throws IOException { private void writeValues(Value[] values, boolean isClock, int clock) throws IOException {
out.print("("); out.print("(");
Separator sep = new Separator(", "); Separator sep = new Separator(out, ", ");
for (int i = 0; i < values.length; i++) { for (int i = 0; i < values.length; i++) {
sep.check(out); sep.check();
Value val = values[i]; Value val = values[i];
int bits = dataOrder.get(i).getBits(); int bits = dataOrder.get(i).getBits();
switch (val.getType()) { switch (val.getType()) {

View File

@ -74,9 +74,9 @@ public class VHDLTemplate implements VHDLEntity {
final Entity e = getEntity(node); final Entity e = getEntity(node);
if (!e.getGenerics().isEmpty()) { if (!e.getGenerics().isEmpty()) {
out.println("generic map (").inc(); out.println("generic map (").inc();
Separator semic = new Separator(",\n"); Separator semic = new Separator(out, ",\n");
for (VHDLTemplateFunctions.Generic gen : e.getGenerics()) { for (VHDLTemplateFunctions.Generic gen : e.getGenerics()) {
semic.check(out); semic.check();
final Object value = node.getElementAttributes().hgsMapGet(gen.getName()); final Object value = node.getElementAttributes().hgsMapGet(gen.getName());
out.print(gen.getName()).print(" => ").print(gen.format(value)); out.print(gen.getName()).print(" => ").print(gen.format(value));
} }

View File

@ -23,6 +23,20 @@ public class CodePrinterStrTest extends TestCase {
.dec() .dec()
.println("test") .println("test")
.toString()); .toString());
assertEquals("test;\n" +
" -- Hello\n" +
" -- World\n" +
" -- Long text\n" +
"test",new CodePrinterStr()
.println("test;")
.printComment(" -- ","Hello\nWorld\nLong text").print("test").toString());
assertEquals("test; -- Hello\n" +
" -- World\n" +
" -- Long text\n" +
"test",new CodePrinterStr()
.print("test;")
.printComment(" -- ","Hello\nWorld\nLong text").print("test").toString());
} }
} }

View File

@ -0,0 +1,62 @@
/*
* 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.hdl.vhdl2;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.draw.elements.PinException;
import de.neemann.digital.draw.library.ElementNotFoundException;
import de.neemann.digital.hdl.hgs.HGSEvalException;
import de.neemann.digital.hdl.model2.HDLCircuit;
import de.neemann.digital.hdl.model2.HDLException;
import de.neemann.digital.hdl.model2.HDLModel;
import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.integration.ToBreakRunner;
import junit.framework.TestCase;
import java.io.IOException;
public class DescriptionTest extends TestCase {
public void testDescription() throws PinException, NodeException, ElementNotFoundException, IOException, HDLException, HGSEvalException {
ToBreakRunner br = new ToBreakRunner("dig/hdl/model2/naming.dig");
HDLCircuit circuit = new HDLCircuit(
br.getCircuit(),
"main"
, new HDLModel(br.getLibrary()),
null)
.mergeConstants()
.mergeExpressions()
.nameNets();
CodePrinterStr out = new CodePrinterStr();
new VHDLCreator(out).printHDLCircuit(circuit);
assertEquals("\n" +
"LIBRARY ieee;\n" +
"USE ieee.std_logic_1164.all;\n" +
"USE ieee.numeric_std.all;\n" +
"\n" +
"-- Simple test circuit\n" +
"-- used to test comments.\n"+
"entity main is\n" +
" port (\n" +
" S0: in std_logic; -- First input\n" +
" -- This is a far longer text.\n" +
" S1: in std_logic; -- Second input\n" +
" S2: out std_logic; -- first output\n" +
" S3: out std_logic -- second output\n" +
" -- also with a longer text\n" +
" );\n" +
"end main;\n" +
"\n" +
"architecture Behavioral of main is\n" +
" signal s4: std_logic;\n" +
"begin\n" +
" s4 <= NOT (S0 OR S1);\n" +
" S2 <= (S0 XOR s4);\n" +
" S3 <= (s4 XOR S1);\n" +
"end Behavioral;\n", out.toString());
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2017 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.hdl.vhdl2;
import de.neemann.digital.hdl.printer.CodePrinterStr;
import junit.framework.TestCase;
import java.io.IOException;
public class SeparatorTest extends TestCase {
public void testSeparator() throws IOException {
CodePrinterStr out = new CodePrinterStr();
out.println("open (").inc();
Separator sep = new Separator(out, ",\n");
for (int i = 0; i < 4; i++) {
sep.check();
out.print("item").print(i);
}
out.println(")").dec();
out.print("close");
assertEquals("open (\n" +
" item0,\n" +
" item1,\n" +
" item2,\n" +
" item3)\n" +
"close", out.toString());
}
public void testSeparator2() throws IOException {
CodePrinterStr out = new CodePrinterStr();
out.println("open (").inc();
Separator sep = new Separator(out, ",\n");
for (int i = 0; i < 4; i++) {
sep.check();
out.print("item").print(i);
String ic = "item" + i + " comment";
sep.setLineFinalizer(o -> o.printComment(" \\\\ ", ic));
}
sep.close();
out.println(")").dec();
out.print("close");
assertEquals("open (\n" +
" item0, \\\\ item0 comment\n" +
" item1, \\\\ item1 comment\n" +
" item2, \\\\ item2 comment\n" +
" item3 \\\\ item3 comment\n" +
" )\n" +
"close", out.toString());
}
public void testSeparator3() throws IOException {
CodePrinterStr out = new CodePrinterStr();
out.println("open (").inc();
Separator sep = new Separator(out, ",");
for (int i = 0; i < 4; i++) {
sep.check();
out.print("item").print(i);
if ((i&1)==0) {
String ic = "item" + i + " comment";
sep.setLineFinalizer(o -> o.printComment(" \\\\ ", ic));
}
}
sep.close();
out.println(")").dec();
out.print("close");
assertEquals("open (\n" +
" item0, \\\\ item0 comment\n" +
" item1,item2, \\\\ item2 comment\n" +
" item3)\n" +
"close", out.toString());
}
}

View File

@ -1,11 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<circuit> <circuit>
<version>1</version> <version>1</version>
<attributes/> <attributes>
<entry>
<string>Description</string>
<string>Simple test circuit
used to test comments.</string>
</entry>
</attributes>
<visualElements> <visualElements>
<visualElement> <visualElement>
<elementName>Out</elementName> <elementName>Out</elementName>
<elementAttributes> <elementAttributes>
<entry>
<string>Description</string>
<string>first output</string>
</entry>
<entry> <entry>
<string>Label</string> <string>Label</string>
<string>S2</string> <string>S2</string>
@ -20,6 +30,11 @@
<visualElement> <visualElement>
<elementName>In</elementName> <elementName>In</elementName>
<elementAttributes> <elementAttributes>
<entry>
<string>Description</string>
<string>First input
This is a far longer text.</string>
</entry>
<entry> <entry>
<string>Label</string> <string>Label</string>
<string>S0</string> <string>S0</string>
@ -30,6 +45,10 @@
<visualElement> <visualElement>
<elementName>In</elementName> <elementName>In</elementName>
<elementAttributes> <elementAttributes>
<entry>
<string>Description</string>
<string>Second input</string>
</entry>
<entry> <entry>
<string>Label</string> <string>Label</string>
<string>S1</string> <string>S1</string>
@ -55,6 +74,11 @@
<visualElement> <visualElement>
<elementName>Out</elementName> <elementName>Out</elementName>
<elementAttributes> <elementAttributes>
<entry>
<string>Description</string>
<string>second output
also with a longer text</string>
</entry>
<entry> <entry>
<string>Label</string> <string>Label</string>
<string>S3</string> <string>S3</string>