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> inputs;
private final ArrayList<HDLNet> listOfNets;
private final String description;
private ArrayList<HDLPort> ports;
private NetList netList;
private ArrayList<HDLNode> nodes;
@ -89,6 +90,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
nets = new HashMap<>();
listOfNets = new ArrayList<>();
netList = new NetList(circuit);
description = circuit.getAttributes().get(Keys.DESCRIPTION);
ArrayList<ClockInfo> clocks = new ArrayList<>();
@ -100,7 +102,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
getNetOfPin(v.getPins().get(0)),
HDLPort.Direction.OUT, // from inside the node this is an output because it defines a value
v.getElementAttributes().getBits())
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER));
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))
.setDescription(v.getElementAttributes().get(Keys.DESCRIPTION));
addInput(port);
if (v.equalsDescription(Clock.DESCRIPTION))
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)),
HDLPort.Direction.IN, // from inside the node this is an input because it reads the value to output
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))
handleSplitter(c.createNode(v, this));
else if (isRealElement(v))
@ -460,6 +464,20 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
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.
*

View File

@ -15,6 +15,8 @@ import java.io.IOException;
*/
public class HDLPort implements Printable, HasName {
private String description;
/**
* The ports direction
*/
@ -71,6 +73,31 @@ public class HDLPort implements Printable, HasName {
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
*/

View File

@ -18,6 +18,7 @@ public class CodePrinter implements Closeable {
private File file;
private int ident = 0;
private boolean newLine = true;
private int pos;
/**
* Creates a new instance
@ -139,7 +140,7 @@ public class CodePrinter implements Closeable {
*/
public CodePrinter print(char c) throws IOException {
if (newLine && c != '\n') {
int pos = ident * indentWidth;
pos = ident * indentWidth;
for (int i = 0; i < pos; i++)
out.write(' ');
newLine = false;
@ -148,6 +149,8 @@ public class CodePrinter implements Closeable {
out.write(c);
else
out.write(("" + c).getBytes(CHARSET));
pos++;
if (c == '\n') {
newLine = true;
eolIsWritten();
@ -191,4 +194,38 @@ public class CodePrinter implements Closeable {
public File getFile() {
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 {
private final String sep;
private final CodePrinter out;
private final String finalizerSeparator;
private boolean first = true;
private LineFinalizer lineFinalizer;
/**
* Creates a new instance
*
* @param out the print stream
* @param sep The separator
*/
public Separator(String sep) {
public Separator(CodePrinter out, String 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
*
* @param out the print stream
* @throws IOException IOException
*/
public void check(CodePrinter out) throws IOException {
public void check() throws IOException {
if (first)
first = false;
else
out.print(getSeperator());
else {
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() {
return sep;
public void printSeparator(CodePrinter out) throws IOException {
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

@ -27,7 +27,7 @@ public class VHDLCreator {
/**
* Creates a new instance
*
* @param out the output stream
* @param out the output stream
*/
VHDLCreator(CodePrinter out) {
this.out = out;
@ -104,6 +104,9 @@ public class VHDLCreator {
.println("USE ieee.numeric_std.all;")
.println();
if (circuit.hasDescription())
out.printComment("-- ", circuit.getDescription());
out.print("entity ").print(circuit.getHdlEntityName()).println(" is").inc();
writePorts(out, circuit);
out.dec();
@ -152,16 +155,19 @@ public class VHDLCreator {
public static void writePorts(CodePrinter out, HDLCircuit circuit) throws IOException {
out.println("port (").inc();
Separator sep = new Separator(";\n");
Separator sep = new Separator(out, ";\n");
for (HDLPort i : circuit.getInputs()) {
sep.check(out);
sep.check();
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()) {
sep.check(out);
sep.check();
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();
}
@ -204,16 +210,16 @@ public class VHDLCreator {
if (!(node instanceof HDLNodeCustom))
library.getEntity(node).writeGenericMap(out, node);
out.println("port map (").inc();
Separator sep = new Separator(",\n");
Separator sep = new Separator(out, ",\n");
for (HDLPort i : node.getInputs())
if (i.getNet() != null) {
sep.check(out);
sep.check();
out.print(i.getName()).print(" => ").print(i.getNet().getName());
}
for (HDLPort o : node.getOutputs())
if (o.getNet() != null) {
sep.check(out);
sep.check();
out.print(o.getName()).print(" => ").print(o.getNet().getName());
}
out.println(");").dec().dec();

View File

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

View File

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

View File

@ -23,6 +23,20 @@ public class CodePrinterStrTest extends TestCase {
.dec()
.println("test")
.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"?>
<circuit>
<version>1</version>
<attributes/>
<attributes>
<entry>
<string>Description</string>
<string>Simple test circuit
used to test comments.</string>
</entry>
</attributes>
<visualElements>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Description</string>
<string>first output</string>
</entry>
<entry>
<string>Label</string>
<string>S2</string>
@ -20,6 +30,11 @@
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Description</string>
<string>First input
This is a far longer text.</string>
</entry>
<entry>
<string>Label</string>
<string>S0</string>
@ -30,6 +45,10 @@
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Description</string>
<string>Second input</string>
</entry>
<entry>
<string>Label</string>
<string>S1</string>
@ -55,6 +74,11 @@
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Description</string>
<string>second output
also with a longer text</string>
</entry>
<entry>
<string>Label</string>
<string>S3</string>