improved label checking

This commit is contained in:
hneemann 2018-03-25 23:48:28 +02:00
parent 58c427b107
commit a1cdf04bae
11 changed files with 154 additions and 67 deletions

View File

@ -421,8 +421,9 @@ public class HDLCircuit implements Iterable<HDLNode>, 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<HDLNode>, HDLModel.BitProvider, Prin
n.rename(renaming);
hdlEntityName = renaming.checkName(hdlEntityName);
checkUnique(getPorts());
checkUnique(listOfNets);
}
private void checkUnique(Collection<? extends HasName> names) throws HDLException {
HashSet<String> 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);
}
}
/**

View File

@ -178,8 +178,9 @@ public class HDLModel implements Iterable<HDLCircuit> {
* 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);

View File

@ -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<HDLPort> 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;
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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.");

View File

@ -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<String> 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());
}
}

View File

@ -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<String> 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();
}
}

View File

@ -860,6 +860,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="err_monoflopRequiresOneClock">Wird ein Monoflop verwendet, muss es genau ein Taktelement geben!</string>
<string name="err_couldNotCreateElement_N">Konnte kein Element vom Typ "{0}" erzeugen!</string>
<string name="err_centralDefinedRomsAreNotSupported">Zentral definierte ROM-Inhalte werden nicht unterstützt!</string>
<string name="err_namesAreNotUnique_N">Der Name "{0}" ist nicht eindeutig!</string>
<string name="err_errorWritingDataToProcess">Es konnten keine Werte an den externen Prozess übergeben werden!</string>
<string name="err_errorReadingDataToProcess">Es konnten keine Werte vom externen Prozess gelesen werden!</string>

View File

@ -881,6 +881,7 @@
<string name="err_errorAnalysingCircuit_N">Error analysing the circuit: {0}</string>
<string name="err_romNeedsALabelToBeExported">Every ROM needs a unique label to be exported!</string>
<string name="err_counterNeedsMoreBits">The counter needs at least two bits.</string>
<string name="err_namesAreNotUnique_N">The name "{0}" is not unique!</string>
<string name="key_AddrBits">Address Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
<string name="key_AddrBits_tt">Number of address bits used.</string>

View File

@ -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("a<b"));
assertEquals("agrb", r.checkName("a>b"));
assertEquals("aeqb", r.checkName("a=b"));
}
}