muxer is working with new template engine

This commit is contained in:
hneemann 2018-03-13 12:49:52 +01:00
parent b6e5b0ea7f
commit 70a1a8bc9d
9 changed files with 282 additions and 185 deletions

View File

@ -21,6 +21,9 @@ import de.neemann.gui.language.Language;
import java.awt.*; import java.awt.*;
import java.io.File; import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
/** /**
@ -28,6 +31,37 @@ import java.util.Locale;
*/ */
public final class Keys { public final class Keys {
private static final class InstanceHolder {
private static final HashMap<String, Key> INSTANCE = createMap();
private static HashMap<String, Key> createMap() {
HashMap<String, Key> map = new HashMap<>();
for (Field k : Keys.class.getDeclaredFields()) {
if (Modifier.isStatic(k.getModifiers()) && Key.class.isAssignableFrom(k.getType())) {
try {
Key key = (Key) k.get(null);
map.put(key.getKey(), key);
} catch (IllegalAccessException e) {
throw new RuntimeException("error accessing the Keys");
}
}
}
return map;
}
}
/**
* Returns the key of the given name.
* If key does not exist, nul is returned.
*
* @param name the name of the key
* @return the key or null
*/
public static Key getKeyByName(String name) {
return InstanceHolder.INSTANCE.get(name);
}
private Keys() { private Keys() {
} }

View File

@ -138,6 +138,7 @@ public class Parser {
return c -> ref.set(c, Expression.add(ref.get(c), 1)); return c -> ref.set(c, Expression.add(ref.get(c), 1));
} else if (isToken(OPEN)) { } else if (isToken(OPEN)) {
ArrayList<Expression> args = parseArgList(); ArrayList<Expression> args = parseArgList();
expect(SEMICOLON);
if (ref instanceof ReferenceToVar) { if (ref instanceof ReferenceToVar) {
return findFunctionStatement(((ReferenceToVar) ref).getName(), args); return findFunctionStatement(((ReferenceToVar) ref).getName(), args);
} else } else

View File

@ -11,9 +11,6 @@ import de.neemann.digital.core.element.Keys;
import de.neemann.digital.hdl.hgs.Context; import de.neemann.digital.hdl.hgs.Context;
import de.neemann.digital.hdl.hgs.EvalException; import de.neemann.digital.hdl.hgs.EvalException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
@ -22,20 +19,6 @@ import java.util.Map;
public class ReferenceToStruct implements Reference { public class ReferenceToStruct implements Reference {
private final Reference parent; private final Reference parent;
private final String name; private final String name;
private static final HashMap<String, Key> KEY_MAP = new HashMap<>();
static {
for (Field k : Keys.class.getDeclaredFields()) {
if (Modifier.isStatic(k.getModifiers()) && Key.class.isAssignableFrom(k.getType())) {
try {
Key key = (Key) k.get(null);
KEY_MAP.put(key.getKey(), key);
} catch (IllegalAccessException e) {
throw new RuntimeException("error accessing the Keys");
}
}
}
}
/** /**
* Creates a new struct access * Creates a new struct access
@ -63,7 +46,7 @@ public class ReferenceToStruct implements Reference {
if (m instanceof Map) if (m instanceof Map)
return ((Map) m).get(name); return ((Map) m).get(name);
else if (m instanceof ElementAttributes) { else if (m instanceof ElementAttributes) {
Key key = KEY_MAP.get(name); Key key = Keys.getKeyByName(name);
if (key == null) if (key == null)
throw new EvalException("invalid key: " + name); throw new EvalException("invalid key: " + name);
return ((ElementAttributes) m).get(key); return ((ElementAttributes) m).get(key);

View File

@ -5,6 +5,8 @@
*/ */
package de.neemann.digital.hdl.vhdl.lib; package de.neemann.digital.hdl.vhdl.lib;
import de.neemann.digital.core.element.Key;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.hdl.hgs.*;
import de.neemann.digital.hdl.hgs.function.FuncAdapter; import de.neemann.digital.hdl.hgs.function.FuncAdapter;
import de.neemann.digital.hdl.hgs.function.Function; import de.neemann.digital.hdl.hgs.function.Function;
@ -20,6 +22,7 @@ import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import static de.neemann.digital.hdl.vhdl.lib.VHDLEntitySimple.writePort; import static de.neemann.digital.hdl.vhdl.lib.VHDLEntitySimple.writePort;
@ -64,6 +67,21 @@ public class VHDLTemplate implements VHDLEntity {
c.setVar("portDecl", portDecl); c.setVar("portDecl", portDecl);
return null; return null;
} }
})
.addFunction("registerGeneric", new Function(1) {
@Override
public Object calcValue(Context c, ArrayList<Expression> args) throws EvalException {
List<String> generics;
if (c.contains("generics"))
generics = (List<String>) c.getVar("generics");
else {
generics = new ArrayList<>();
c.setVar("generics", generics);
}
String name = Expression.toString(args.get(0).value(c));
generics.add(name);
return null;
}
}); });
statements = p.parse(); statements = p.parse();
staticContext = p.getStaticContext(); staticContext = p.getStaticContext();
@ -80,7 +98,7 @@ public class VHDLTemplate implements VHDLEntity {
public void writeHeader(CodePrinter out, HDLNode node) throws IOException { public void writeHeader(CodePrinter out, HDLNode node) throws IOException {
try { try {
Entity e = getEntity(node); Entity e = getEntity(node);
out.print(e.code); out.print(e.getCode());
e.setWritten(true); e.setWritten(true);
} catch (EvalException e) { } catch (EvalException e) {
throw new IOException("error evaluating the template", e); throw new IOException("error evaluating the template", e);
@ -126,14 +144,32 @@ public class VHDLTemplate implements VHDLEntity {
} }
@Override @Override
public void writeArchitecture(CodePrinter out, HDLNode node) { public void writeGenericMap(CodePrinter out, HDLNode node) throws HDLException, IOException {
try {
final Entity e = getEntity(node);
if (e.getGenerics() != null) {
out.println("generic map (").inc();
Separator semic = new Separator(",\n");
for (String name : e.getGenerics()) {
Key key = Keys.getKeyByName(name);
if (key != null) {
semic.check(out);
out.print(name).print(" => ").print(node.get(key).toString());
} else
throw new HDLException("unknown generic key: " + name);
}
out.println(")").dec();
}
} catch (EvalException e) {
throw new IOException("error evaluating the template", e);
}
} }
@Override @Override
public void writeGenericMap(CodePrinter out, HDLNode node) { public void writeArchitecture(CodePrinter out, HDLNode node) {
} }
@Override @Override
public String getDescription(HDLNode node) { public String getDescription(HDLNode node) {
return null; return null;
@ -167,6 +203,7 @@ public class VHDLTemplate implements VHDLEntity {
private final String code; private final String code;
private final String portDecl; private final String portDecl;
private final String name; private final String name;
private final List<String> generics;
private boolean isWritten = false; private boolean isWritten = false;
private Entity(HDLNode node, String name) throws EvalException { private Entity(HDLNode node, String name) throws EvalException {
@ -179,6 +216,10 @@ public class VHDLTemplate implements VHDLEntity {
portDecl = c.getVar("portDecl").toString(); portDecl = c.getVar("portDecl").toString();
else else
portDecl = null; portDecl = null;
if (c.contains("generics"))
generics = (List<String>) c.getVar("generics");
else
generics = null;
} }
private String getCode() { private String getCode() {
@ -200,6 +241,10 @@ public class VHDLTemplate implements VHDLEntity {
private String getName() { private String getName() {
return name; return name;
} }
public List<String> getGenerics() {
return generics;
}
} }
private final static class FunctionType extends FuncAdapter { private final static class FunctionType extends FuncAdapter {

View File

@ -14,18 +14,21 @@ inputs=1<<elem.'Selector Bits';
if (elem.Bits=1) if (elem.Bits=1)
dataType=type(elem.Bits); dataType=type(elem.Bits);
else else
dataType="std_logic_vector ((bitCount-1) downto 0)"; dataType="std_logic_vector ((Bits-1) downto 0)";
?> ?>
entity <?=name?> is entity <?=name?> is
<? beginGenericPort()?> <? beginGenericPort();?>
<? if (elem.Bits>1) { ?>
generic ( Bits : integer ); <? registerGeneric("Bits");?>
<? } ?>
port ( port (
PORT_out: out <?=dataType?>; PORT_out: out <?=dataType?>;
PORT_sel: in <?=type(elem.'Selector Bits')?>; PORT_sel: in <?=type(elem.'Selector Bits')?>;
<? for (n=0;n<inputs;n++) { ?> <? for (n=0;n<inputs;n++) { ?>
PORT_in_<?=n?>: in <?=dataType if (n<inputs-1) print(";"); }?> ); PORT_in_<?=n?>: in <?=dataType if (n<inputs-1) print(";"); }?> );
<? endGenericPort()?> <? endGenericPort();?>
end <?=name?>; end <?=name?>;
architecture <?=name?>_arch of <?=name?> is architecture <?=name?>_arch of <?=name?> is
@ -34,6 +37,10 @@ begin
PORT_out <= PORT_out <=
<? for (n=0;n<inputs;n++) { ?> <? for (n=0;n<inputs;n++) { ?>
PORT_in_<?=n?> when <?=value(n, elem.'Selector Bits') ?>, PORT_in_<?=n?> when <?=value(n, elem.'Selector Bits') ?>,
<? } ?> <? }
<?=value(0, elem.Bits) ?> when others; if (elem.Bits>1)
print("(others => '0')");
else
print(value(0, elem.Bits));
?> when others;
end <?=name?>_arch; end <?=name?>_arch;

View File

@ -245,7 +245,7 @@ public class ParserTest extends TestCase {
public void testFunctionAsStatement() throws IOException, ParserException, EvalException { public void testFunctionAsStatement() throws IOException, ParserException, EvalException {
flag = 0; flag = 0;
Statement s = new Parser("a : in <? type(7) ?>;") Statement s = new Parser("a : in <? type(7); ?>;")
.addFunction("type", new FuncAdapter() { .addFunction("type", new FuncAdapter() {
@Override @Override
protected Object f(long n) { protected Object f(long n) {

View File

@ -10,6 +10,10 @@ import java.util.StringTokenizer;
public class TestHelper { public class TestHelper {
static public String removeCommentLines(String code) { static public String removeCommentLines(String code) {
return removeCommentLines(code, false);
}
static public String removeCommentLines(String code, boolean normalizeWhiteSpace) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
StringTokenizer st = new StringTokenizer(code, "\n"); StringTokenizer st = new StringTokenizer(code, "\n");
while (st.hasMoreTokens()) { while (st.hasMoreTokens()) {
@ -18,10 +22,29 @@ public class TestHelper {
if (!(testLine.length() == 0 || (testLine.length() >= 2 && testLine.startsWith("--")))) { if (!(testLine.length() == 0 || (testLine.length() >= 2 && testLine.startsWith("--")))) {
if (sb.length() > 0) if (sb.length() > 0)
sb.append("\n"); sb.append("\n");
if (normalizeWhiteSpace)
normalizeWhiteSpaces(sb, line);
else
sb.append(line); sb.append(line);
} }
} }
return sb.toString(); return sb.toString();
} }
private static void normalizeWhiteSpaces(StringBuilder sb, String line) {
boolean wasBlank = true;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (c == ' ' || c == '\t') {
wasBlank = true;
} else {
if (wasBlank) {
sb.append(' ');
wasBlank = false;
}
sb.append(c);
}
}
}
} }

View File

@ -126,9 +126,9 @@ public class TestInSimulator extends TestCase {
out.close(); out.close();
runGHDL(vhdlFile, tb.getTestFileWritten()); runGHDL(vhdlFile, tb.getTestFileWritten());
} }
ProcessStarter.removeFolder(dir);
} finally { } finally {
br.close(); br.close();
ProcessStarter.removeFolder(dir);
} }
} }

View File

@ -20,7 +20,8 @@ public class MultiplexerTest extends TestCase {
public void testSimple() throws IOException, ElementNotFoundException, PinException, NodeException { public void testSimple() throws IOException, ElementNotFoundException, PinException, NodeException {
ToBreakRunner br = new ToBreakRunner("dig/hdl/mux.dig"); ToBreakRunner br = new ToBreakRunner("dig/hdl/mux.dig");
String vhdl = new VHDLGenerator(br.getLibrary()).export(br.getCircuit()).toString(); String vhdl = new VHDLGenerator(br.getLibrary()).export(br.getCircuit()).toString();
assertEquals("LIBRARY ieee;\n" + assertEquals(TestHelper.removeCommentLines(
"LIBRARY ieee;\n" +
"USE ieee.std_logic_1164.all;\n" + "USE ieee.std_logic_1164.all;\n" +
"USE ieee.numeric_std.all;\n" + "USE ieee.numeric_std.all;\n" +
"entity main is\n" + "entity main is\n" +
@ -64,13 +65,14 @@ public class MultiplexerTest extends TestCase {
" PORT_in_0 when '0',\n" + " PORT_in_0 when '0',\n" +
" PORT_in_1 when '1',\n" + " PORT_in_1 when '1',\n" +
" '0' when others;\n" + " '0' when others;\n" +
"end MUX_GATE_1_arch;", TestHelper.removeCommentLines(vhdl)); "end MUX_GATE_1_arch;", true), TestHelper.removeCommentLines(vhdl, true));
} }
public void testSimple2() throws IOException, ElementNotFoundException, PinException, NodeException { public void testSimple2() throws IOException, ElementNotFoundException, PinException, NodeException {
ToBreakRunner br = new ToBreakRunner("dig/hdl/mux2.dig"); ToBreakRunner br = new ToBreakRunner("dig/hdl/mux2.dig");
String vhdl = new VHDLGenerator(br.getLibrary()).export(br.getCircuit()).toString(); String vhdl = new VHDLGenerator(br.getLibrary()).export(br.getCircuit()).toString();
assertEquals("LIBRARY ieee;\n" + assertEquals(TestHelper.removeCommentLines(
"LIBRARY ieee;\n" +
"USE ieee.std_logic_1164.all;\n" + "USE ieee.std_logic_1164.all;\n" +
"USE ieee.numeric_std.all;\n" + "USE ieee.numeric_std.all;\n" +
"entity main is\n" + "entity main is\n" +
@ -124,13 +126,14 @@ public class MultiplexerTest extends TestCase {
" PORT_in_2 when \"10\",\n" + " PORT_in_2 when \"10\",\n" +
" PORT_in_3 when \"11\",\n" + " PORT_in_3 when \"11\",\n" +
" '0' when others;\n" + " '0' when others;\n" +
"end MUX_GATE_2_arch;", TestHelper.removeCommentLines(vhdl)); "end MUX_GATE_2_arch;", true), TestHelper.removeCommentLines(vhdl, true));
} }
public void testSimple3() throws IOException, ElementNotFoundException, PinException, NodeException { public void testSimple3() throws IOException, ElementNotFoundException, PinException, NodeException {
ToBreakRunner br = new ToBreakRunner("dig/hdl/mux3.dig"); ToBreakRunner br = new ToBreakRunner("dig/hdl/mux3.dig");
String vhdl = new VHDLGenerator(br.getLibrary()).export(br.getCircuit()).toString(); String vhdl = new VHDLGenerator(br.getLibrary()).export(br.getCircuit()).toString();
assertEquals("LIBRARY ieee;\n" + assertEquals(TestHelper.removeCommentLines(
"LIBRARY ieee;\n" +
"USE ieee.std_logic_1164.all;\n" + "USE ieee.std_logic_1164.all;\n" +
"USE ieee.numeric_std.all;\n" + "USE ieee.numeric_std.all;\n" +
"entity main is\n" + "entity main is\n" +
@ -144,19 +147,20 @@ public class MultiplexerTest extends TestCase {
"end main;\n" + "end main;\n" +
"architecture main_arch of main is\n" + "architecture main_arch of main is\n" +
" component MUX_GATE_BUS_2\n" + " component MUX_GATE_BUS_2\n" +
" generic ( bitCount : integer );\n" + " generic ( Bits : integer );\n" +
" port (\n" + " port (\n" +
" PORT_out: out std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_sel: in std_logic_vector (1 downto 0);\n" + " PORT_sel: in std_logic_vector (1 downto 0);\n" +
" PORT_out: out std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_0: in std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_in_0: in std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_1: in std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_in_1: in std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_2: in std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_in_2: in std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_3: in std_logic_vector ((Bits-1) downto 0) );\n" +
" PORT_in_3: in std_logic_vector ( (bitCount-1) downto 0) );\n" +
" end component;\n" + " end component;\n" +
" signal S0: std_logic_vector (3 downto 0);\n" + " signal S0: std_logic_vector (3 downto 0);\n" +
"begin\n" + "begin\n" +
" gate0 : MUX_GATE_BUS_2\n" + " gate0 : MUX_GATE_BUS_2\n" +
" generic map ( bitCount => 4)\n" + " generic map (\n" +
" Bits => 4)\n" +
" port map (\n" + " port map (\n" +
" PORT_out => S0,\n" + " PORT_out => S0,\n" +
" PORT_sel => PORT_Sel,\n" + " PORT_sel => PORT_Sel,\n" +
@ -169,14 +173,14 @@ public class MultiplexerTest extends TestCase {
"LIBRARY ieee;\n" + "LIBRARY ieee;\n" +
"USE ieee.std_logic_1164.all;\n" + "USE ieee.std_logic_1164.all;\n" +
"entity MUX_GATE_BUS_2 is\n" + "entity MUX_GATE_BUS_2 is\n" +
" generic ( bitCount : integer );\n" + " generic ( Bits : integer );\n" +
" port (\n" + " port (\n" +
" PORT_out: out std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_sel: in std_logic_vector (1 downto 0);\n" + " PORT_sel: in std_logic_vector (1 downto 0);\n" +
" PORT_out: out std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_0: in std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_in_0: in std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_1: in std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_in_1: in std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_2: in std_logic_vector ((Bits-1) downto 0);\n" +
" PORT_in_2: in std_logic_vector ( (bitCount-1) downto 0);\n" + " PORT_in_3: in std_logic_vector ((Bits-1) downto 0) );\n" +
" PORT_in_3: in std_logic_vector ( (bitCount-1) downto 0) );\n" +
"end MUX_GATE_BUS_2;\n" + "end MUX_GATE_BUS_2;\n" +
"architecture MUX_GATE_BUS_2_arch of MUX_GATE_BUS_2 is\n" + "architecture MUX_GATE_BUS_2_arch of MUX_GATE_BUS_2 is\n" +
"begin\n" + "begin\n" +
@ -187,7 +191,7 @@ public class MultiplexerTest extends TestCase {
" PORT_in_2 when \"10\",\n" + " PORT_in_2 when \"10\",\n" +
" PORT_in_3 when \"11\",\n" + " PORT_in_3 when \"11\",\n" +
" (others => '0') when others;\n" + " (others => '0') when others;\n" +
"end MUX_GATE_BUS_2_arch;", TestHelper.removeCommentLines(vhdl)); "end MUX_GATE_BUS_2_arch;", true), TestHelper.removeCommentLines(vhdl, true));
} }
} }