From a1cdf04baebadb589a010e8308aceae1b7960d80 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 25 Mar 2018 23:48:28 +0200 Subject: [PATCH] improved label checking --- .../digital/hdl/model2/HDLCircuit.java | 17 +++- .../neemann/digital/hdl/model2/HDLModel.java | 3 +- .../de/neemann/digital/hdl/model2/HDLNet.java | 6 +- .../neemann/digital/hdl/model2/HDLPort.java | 6 +- .../neemann/digital/hdl/model2/HasName.java | 16 ++++ .../digital/hdl/vhdl2/VHDLGenerator.java | 18 +--- .../digital/hdl/vhdl2/VHDLKeywords.java | 40 --------- .../digital/hdl/vhdl2/VHDLRenaming.java | 86 +++++++++++++++++++ src/main/resources/lang/lang_de.xml | 1 + src/main/resources/lang/lang_en.xml | 1 + .../digital/hdl/vhdl2/VHDLRenamingTest.java | 27 ++++++ 11 files changed, 154 insertions(+), 67 deletions(-) create mode 100644 src/main/java/de/neemann/digital/hdl/model2/HasName.java delete mode 100644 src/main/java/de/neemann/digital/hdl/vhdl2/VHDLKeywords.java create mode 100644 src/main/java/de/neemann/digital/hdl/vhdl2/VHDLRenaming.java create mode 100644 src/test/java/de/neemann/digital/hdl/vhdl2/VHDLRenamingTest.java diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java index ce2a817ed..87b2b06e0 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java @@ -421,8 +421,9 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin * Renames the names in this model to satisfy constrains of the final target language. * * @param renaming the renaming algorithm + * @throws HDLException HDLException */ - public void rename(HDLModel.Renaming renaming) { + public void rename(HDLModel.Renaming renaming) throws HDLException { for (HDLPort p : outputs) p.rename(renaming); for (HDLPort p : inputs) @@ -434,6 +435,20 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin n.rename(renaming); hdlEntityName = renaming.checkName(hdlEntityName); + + checkUnique(getPorts()); + checkUnique(listOfNets); + } + + private void checkUnique(Collection names) throws HDLException { + HashSet set = new HashSet<>(); + for (HasName hn : names) { + String name = hn.getName(); + if (set.contains(name)) + throw new HDLException(Lang.get("err_namesAreNotUnique_N", name)); + else + set.add(name); + } } /** diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java index bc70ed685..63c172498 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java @@ -178,8 +178,9 @@ public class HDLModel implements Iterable { * Renames the signals in this model * * @param renaming the renaming algorithm + * @throws HDLException HDLException */ - public void rename(Renaming renaming) { + public void renameLabels(Renaming renaming) throws HDLException { this.renaming = new RenameSingleCheck(renaming); for (HDLCircuit c : circuitMap.values()) c.rename(this.renaming); diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java b/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java index 4f992407e..a4eb44199 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java @@ -14,7 +14,7 @@ import java.util.ArrayList; * Represents a net. * A net can have only one input and several outputs. */ -public class HDLNet implements Printable { +public class HDLNet implements Printable, HasName { private String name; private ArrayList inputs; private HDLPort output; @@ -89,9 +89,7 @@ public class HDLNet implements Printable { out.print(name).print("->").print(inputs.size()); } - /** - * @return the name of the net - */ + @Override public String getName() { return name; } diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java b/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java index 78c25599d..6b943a752 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java @@ -13,7 +13,7 @@ import java.io.IOException; /** * A port */ -public class HDLPort implements Printable { +public class HDLPort implements Printable, HasName { /** * The ports direction @@ -92,9 +92,7 @@ public class HDLPort implements Printable { net.addPort(this); } - /** - * @return the name of this port - */ + @Override public String getName() { return name; } diff --git a/src/main/java/de/neemann/digital/hdl/model2/HasName.java b/src/main/java/de/neemann/digital/hdl/model2/HasName.java new file mode 100644 index 000000000..66da1cf3a --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/HasName.java @@ -0,0 +1,16 @@ +/* + * 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.model2; + +/** + * Implemented by classes the needs unique names + */ +public interface HasName { + /** + * @return the name + */ + String getName(); +} diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java index 222c7d926..71bf2debf 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java @@ -83,23 +83,7 @@ public class VHDLGenerator implements Closeable { .mergeExpressions() .nameNets(); - model.rename(name -> { - if (VHDLKeywords.isKeyword(name)) - return "p_" + name; - else { - if (Character.isDigit(name.charAt(0))) - name = "n" + name; - return name - .replace('.', '_') - .replace(',', '_') - .replace('-', '_') - .replace("\u00AC", "not") - .replace("~", "not") - .replace("=", "eq") - .replace("<", "le") - .replace(">", "gr"); - } - }); + model.renameLabels(new VHDLRenaming()); out.println("-- generated by Digital. Don't modify this file!"); out.println("-- Any changes will be lost if this file is regenerated."); diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLKeywords.java b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLKeywords.java deleted file mode 100644 index 149ea72d0..000000000 --- a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLKeywords.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 java.util.Collections; -import java.util.HashSet; - -/** - * List of vhdl keywords - */ -public final class VHDLKeywords { - private static final HashSet KEYWORDS = new HashSet<>(); - - static { - Collections.addAll(KEYWORDS, - "abs", "access", "after", "alias", "all", "and", "architecture", "array", "assert", - "attribute", "begin", "block", "body", "buffer", "bus", "case", "component", "configuration", - "constant", "disconnect", "downto", "else", "elsif", "end", "entity", "exit", "file", - "for", "function", "generate", "generic", "group", "guarded", "if", "impure", "in", - "inertial", "inout", "is", "label", "library", "linkage", "literal", "loop", - "map", "mod", "nand", "new", "next", "nor", "not", "null", "of", - "on", "open", "or", "others", "out", "package", "port", "postponed", "procedure", - "process", "pure", "range", "record", "register", "reject", "rem", "report", "return", - "rol", "ror", "select", "severity", "signal", "shared", "sla", "sll", "sra", - "srl", "subtype", "then", "to", "transport", "type", "unaffected", "units", "until", - "use", "variable", "wait", "when", "while", "with", "xnor", "xor"); - } - - private VHDLKeywords() { - } - - static boolean isKeyword(String str) { - return KEYWORDS.contains(str.toLowerCase()); - } -} - - diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLRenaming.java b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLRenaming.java new file mode 100644 index 000000000..7bba56b2d --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLRenaming.java @@ -0,0 +1,86 @@ +/* + * 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.hdl.model2.HDLModel; + +import java.util.Collections; +import java.util.HashSet; + +/** + * Renames the labels to valid VHDL names. + */ +public class VHDLRenaming implements HDLModel.Renaming { + + private static final HashSet KEYWORDS = new HashSet<>(); + + static { + Collections.addAll(KEYWORDS, + "abs", "access", "after", "alias", "all", "and", "architecture", "array", "assert", + "attribute", "begin", "block", "body", "buffer", "bus", "case", "component", "configuration", + "constant", "disconnect", "downto", "else", "elsif", "end", "entity", "exit", "file", + "for", "function", "generate", "generic", "group", "guarded", "if", "impure", "in", + "inertial", "inout", "is", "label", "library", "linkage", "literal", "loop", + "map", "mod", "nand", "new", "next", "nor", "not", "null", "of", + "on", "open", "or", "others", "out", "package", "port", "postponed", "procedure", + "process", "pure", "range", "record", "register", "reject", "rem", "report", "return", + "rol", "ror", "select", "severity", "signal", "shared", "sla", "sll", "sra", + "srl", "subtype", "then", "to", "transport", "type", "unaffected", "units", "until", + "use", "variable", "wait", "when", "while", "with", "xnor", "xor"); + } + + + @Override + public String checkName(String name) { + if (isKeyword(name)) + return "p_" + name; + else { + if (Character.isDigit(name.charAt(0))) + name = "n" + name; + return cleanName(name); + } + } + + private boolean isKeyword(String str) { + return KEYWORDS.contains(str.toLowerCase()); + } + + private String cleanName(String name) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) + sb.append(c); + else { + switch (c) { + case '~': + case '\u00AC': + sb.append("not"); + break; + case '=': + sb.append("eq"); + break; + case '<': + sb.append("le"); + break; + case '>': + sb.append("gr"); + break; + default: + if (sb.length() > 0 && sb.charAt(sb.length() - 1) != '_') + sb.append("_"); + } + } + } + + while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '_') + sb.setLength(sb.length() - 1); + + return sb.toString(); + } + + +} diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index fee25a90d..d54eb707b 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -860,6 +860,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Wird ein Monoflop verwendet, muss es genau ein Taktelement geben! Konnte kein Element vom Typ "{0}" erzeugen! Zentral definierte ROM-Inhalte werden nicht unterstützt! + Der Name "{0}" ist nicht eindeutig! Es konnten keine Werte an den externen Prozess übergeben werden! Es konnten keine Werte vom externen Prozess gelesen werden! diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 1b927a126..ce4f4457b 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -881,6 +881,7 @@ Error analysing the circuit: {0} Every ROM needs a unique label to be exported! The counter needs at least two bits. + The name "{0}" is not unique! Address Bits Number of address bits used. diff --git a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLRenamingTest.java b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLRenamingTest.java new file mode 100644 index 000000000..1334556a1 --- /dev/null +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLRenamingTest.java @@ -0,0 +1,27 @@ +/* + * 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 junit.framework.TestCase; + +public class VHDLRenamingTest extends TestCase { + + public void testCheckName() { + VHDLRenaming r = new VHDLRenaming(); + assertEquals("a", r.checkName("a")); + assertEquals("n0a", r.checkName("0a")); + assertEquals("p_in", r.checkName("in")); + assertEquals("a_u_in", r.checkName("a&u(in")); + assertEquals("a_in", r.checkName("a&ü(in")); + assertEquals("a_o_o", r.checkName("a\"o\"o")); + assertEquals("o", r.checkName("\"o\"")); + assertEquals("o", r.checkName("_o_")); + assertEquals("notQ", r.checkName("~Q")); + assertEquals("aleb", r.checkName("ab")); + assertEquals("aeqb", r.checkName("a=b")); + } +} \ No newline at end of file