From 5d03b9e38ae7e33cf7b8f9dfcdffc467b6f53209 Mon Sep 17 00:00:00 2001 From: hneemann Date: Thu, 15 Mar 2018 10:03:52 +0100 Subject: [PATCH] replaced ROMEntity by a template --- .../digital/core/memory/DataField.java | 10 +- .../core/memory/DataFieldConverter.java | 7 +- .../de/neemann/digital/hdl/hgs/Tokenizer.java | 36 +++++- .../neemann/digital/hdl/vhdl/VHDLLibrary.java | 3 - .../neemann/digital/hdl/vhdl/lib/ROMVHDL.java | 113 ------------------ src/main/resources/vhdl/DIG_ROM.tem | 46 +++++++ .../neemann/digital/hdl/vhdl/lib/ROMTest.java | 78 ++++++++++++ 7 files changed, 166 insertions(+), 127 deletions(-) delete mode 100644 src/main/java/de/neemann/digital/hdl/vhdl/lib/ROMVHDL.java create mode 100644 src/main/resources/vhdl/DIG_ROM.tem create mode 100644 src/test/java/de/neemann/digital/hdl/vhdl/lib/ROMTest.java diff --git a/src/main/java/de/neemann/digital/core/memory/DataField.java b/src/main/java/de/neemann/digital/core/memory/DataField.java index 5f2b3150c..97ae279c4 100644 --- a/src/main/java/de/neemann/digital/core/memory/DataField.java +++ b/src/main/java/de/neemann/digital/core/memory/DataField.java @@ -37,7 +37,13 @@ public class DataField implements HGSArray { this(new long[size], size); } - private DataField(long[] data, int size) { + /** + * Creates a new data field + * + * @param data the data + * @param size the size + */ + public DataField(long[] data, int size) { this.size = size; this.data = data; } @@ -232,7 +238,7 @@ public class DataField implements HGSArray { @Override public int hgsArraySize() { - return size; + return data.length; } @Override diff --git a/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java b/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java index b70bdfbd3..8e6b99860 100644 --- a/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java +++ b/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java @@ -12,6 +12,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import de.neemann.digital.core.Bits; +import java.util.Arrays; import java.util.StringTokenizer; /** @@ -70,14 +71,14 @@ public class DataFieldConverter implements Converter { try { // new type int size = Integer.parseInt(reader.getAttribute("size")); - DataField df = new DataField(size); + long[] data = new long[size]; StringTokenizer st = new StringTokenizer(reader.getValue(), ","); int i = 0; while (st.hasMoreTokens()) { - df.setData(i, Bits.decode(st.nextToken().trim(), 0, 16)); + data[i] = Bits.decode(st.nextToken().trim(), 0, 16); i++; } - return df; + return new DataField(Arrays.copyOf(data, i), size); } catch (Bits.NumberFormatException e) { throw new RuntimeException(e); } diff --git a/src/main/java/de/neemann/digital/hdl/hgs/Tokenizer.java b/src/main/java/de/neemann/digital/hdl/hgs/Tokenizer.java index 33c04897a..09fff1665 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/Tokenizer.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/Tokenizer.java @@ -184,12 +184,7 @@ class Tokenizer { break; case '"': token = Token.STRING; - builder.setLength(0); - while ((c = readChar()) != '"') { - builder.append((char) c); - if (c < 0) - throw new IOException("EOF detected while scanning a string"); - } + readString(); break; case '\'': token = Token.IDENT; @@ -224,6 +219,35 @@ class Tokenizer { } } + private void readString() throws IOException { + int c; + builder.setLength(0); + while ((c = readChar()) != '"') { + if (c == '\\') { + c = readChar(); + switch (c) { + case '\\': + c = '\\'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + default: + throw new IOException("not allowed in string: \\" + (char) c); + } + } + builder.append((char) c); + if (c < 0) + throw new IOException("EOF detected while scanning a string"); + } + } + private void readNumber(int c) throws IOException { token = Token.NUMBER; builder.setLength(0); diff --git a/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java b/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java index ccb0ade56..95e6566e0 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java @@ -8,7 +8,6 @@ package de.neemann.digital.hdl.vhdl; import de.neemann.digital.core.basic.*; import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.extern.External; -import de.neemann.digital.core.memory.ROM; import de.neemann.digital.hdl.model.HDLException; import de.neemann.digital.hdl.model.HDLNode; import de.neemann.digital.hdl.model.Port; @@ -60,8 +59,6 @@ public class VHDLLibrary { .put("inv", true))); put(External.DESCRIPTION, new ExternalVHDL()); - - put(ROM.DESCRIPTION, new ROMVHDL()); } private void put(ElementTypeDescription description, VHDLEntity entity) { diff --git a/src/main/java/de/neemann/digital/hdl/vhdl/lib/ROMVHDL.java b/src/main/java/de/neemann/digital/hdl/vhdl/lib/ROMVHDL.java deleted file mode 100644 index 74791e133..000000000 --- a/src/main/java/de/neemann/digital/hdl/vhdl/lib/ROMVHDL.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.vhdl.lib; - -import de.neemann.digital.core.element.Keys; -import de.neemann.digital.core.memory.ROM; -import de.neemann.digital.hdl.model.HDLConstant; -import de.neemann.digital.hdl.model.HDLException; -import de.neemann.digital.hdl.model.HDLNode; -import de.neemann.digital.hdl.model.Port; -import de.neemann.digital.hdl.printer.CodePrinter; -import de.neemann.digital.hdl.vhdl.Separator; -import de.neemann.digital.lang.Lang; - -import java.io.IOException; -import java.util.HashSet; - -/** - * Creates the code for a ROM - */ -public class ROMVHDL extends VHDLEntitySimple { - private HashSet nameSet = new HashSet<>(); - - /** - * Creates a new instance - */ - public ROMVHDL() { - super(ROM.DESCRIPTION); - } - - @Override - public String getName(HDLNode node) throws HDLException { - String name; - try { - name = "DIG_ROM_" + Port.getHDLName(node.get(Keys.LABEL)); - } catch (HDLException e) { - throw new HDLException(Lang.get("err_vhdlRomHasNoValidLabel")); - } - if (nameSet.contains(name)) - throw new HDLException(Lang.get("err_vhdlRomLabel_N_notUnique", node.get(Keys.LABEL))); - nameSet.add(name); - return name; - } - - @Override - public void writeHeader(CodePrinter out, HDLNode node) throws IOException { - super.writeHeader(out, node); - out.println("use IEEE.NUMERIC_STD.ALL;"); - } - - @Override - public boolean needsOutput(HDLNode node) { - return true; - } - - @Override - public void writeArchitecture(CodePrinter out, HDLNode node) throws IOException, HDLException { - long[] data = node.get(Keys.DATA).getMinimized().getData(); - - int dataBits = node.get(Keys.BITS); - int addrBits = node.get(Keys.ADDR_BITS); - - out.inc().print("type mem is array ( 0 to ") - .print(data.length - 1) - .print(") of std_logic_vector(") - .print(dataBits - 1) - .println(" downto 0);"); - - out.println("constant my_Rom : mem := (").inc(); - Separator sep = new Separator(", "); - int pos = 0; - for (int i = 0; i < data.length; i++) { - sep.check(out); - pos += 2; - - if (pos > 70) { - out.println(); - pos = 0; - } - - out.print(new HDLConstant(data[i], dataBits).vhdlValue()); - pos += 2 + dataBits; - } - out.dec().println(");"); - - out.dec().println("begin").inc(); - - out.print("process (PORT_A, PORT_sel)").eol(); - out.print("begin").inc().eol(); - - out.print("if PORT_sel='0' then").inc().eol(); - out.print("PORT_D <= (others => 'Z');").dec().eol(); - if (data.length < (1 << addrBits)) { - out.print("elsif PORT_A > "); - out.print(new HDLConstant(data.length - 1, addrBits).vhdlValue()); - out.print(" then").inc().eol(); - out.print("PORT_D <= (others => '0');").dec().eol(); - } - out.print("else").inc().eol(); - out.print("PORT_D <= my_rom(to_integer(unsigned(PORT_A)));").dec().eol(); - out.print("end if;").eol(); - - out.dec().print("end process;").dec().eol(); - } - - @Override - public boolean createsSignals(HDLNode node) { - return true; - } -} diff --git a/src/main/resources/vhdl/DIG_ROM.tem b/src/main/resources/vhdl/DIG_ROM.tem new file mode 100644 index 000000000..e0fd2dbcf --- /dev/null +++ b/src/main/resources/vhdl/DIG_ROM.tem @@ -0,0 +1,46 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; +use IEEE.NUMERIC_STD.ALL; + + +entity is + port ( + PORT_D: out ; + PORT_A: in ; + PORT_sel: in std_logic ); +end ; + +architecture _arch of is + type mem is array ( 0 to ) of ; + constant my_Rom : mem := ( + ); +begin + process (PORT_A, PORT_sel) + begin + if PORT_sel='0' then + PORT_D <= 1) {?>(others => 'Z')'Z'; + elsif PORT_A > then + PORT_D <= ; + else + PORT_D <= my_rom(to_integer(unsigned(PORT_A))); + end if; + end process; +end _arch; \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/hdl/vhdl/lib/ROMTest.java b/src/test/java/de/neemann/digital/hdl/vhdl/lib/ROMTest.java new file mode 100644 index 000000000..b8b59744e --- /dev/null +++ b/src/test/java/de/neemann/digital/hdl/vhdl/lib/ROMTest.java @@ -0,0 +1,78 @@ +/* + * 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.vhdl.lib; + +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.vhdl.TestHelper; +import de.neemann.digital.hdl.vhdl.VHDLGenerator; +import de.neemann.digital.integration.ToBreakRunner; +import junit.framework.TestCase; + +import java.io.IOException; + +public class ROMTest extends TestCase { + + public void testSimple() throws IOException, ElementNotFoundException, PinException, NodeException { + ToBreakRunner br = new ToBreakRunner("dig/test/vhdl/rom.dig"); + String vhdl = new VHDLGenerator(br.getLibrary()).export(br.getCircuit()).toString(); + assertEquals( + "LIBRARY ieee;\n" + + "USE ieee.std_logic_1164.all;\n" + + "USE ieee.numeric_std.all;\n" + + "entity main is\n" + + " port (\n" + + " PORT_O: out std_logic_vector (7 downto 0);\n" + + " PORT_A: in std_logic_vector (3 downto 0);\n" + + " PORT_en: in std_logic );\n" + + "end main;\n" + + "architecture main_arch of main is\n" + + " component DIG_ROM_ROM\n" + + " port (\n" + + " PORT_D: out std_logic_vector (7 downto 0);\n" + + " PORT_A: in std_logic_vector (3 downto 0);\n" + + " PORT_sel: in std_logic );\n" + + " end component;\n" + + " signal S0: std_logic_vector (7 downto 0);\n" + + "begin\n" + + " gate0 : DIG_ROM_ROM\n" + + " port map (\n" + + " PORT_D => S0,\n" + + " PORT_A => PORT_A,\n" + + " PORT_sel => PORT_en );\n" + + " PORT_O <= S0;\n" + + "end main_arch;\n" + + "LIBRARY ieee;\n" + + "USE ieee.std_logic_1164.all;\n" + + "use IEEE.NUMERIC_STD.ALL;\n" + + "entity DIG_ROM_ROM is\n" + + " port (\n" + + " PORT_D: out std_logic_vector (7 downto 0);\n" + + " PORT_A: in std_logic_vector (3 downto 0);\n" + + " PORT_sel: in std_logic );\n" + + "end DIG_ROM_ROM;\n" + + "architecture DIG_ROM_ROM_arch of DIG_ROM_ROM is\n" + + " type mem is array ( 0 to 13) of std_logic_vector (7 downto 0);\n" + + " constant my_Rom : mem := (\n" + + " \"00000011\", \"00000001\", \"00000000\", \"00000101\", \"00000111\", \"00000000\", \n" + + " \"00000000\", \"00000000\", \"00000000\", \"00000111\", \"00000000\", \"00000000\", \n" + + " \"00000000\", \"11111111\");\n" + + "begin\n" + + " process (PORT_A, PORT_sel)\n" + + " begin\n" + + " if PORT_sel='0' then\n" + + " PORT_D <= (others => 'Z');\n" + + " elsif PORT_A > \"1101\" then\n" + + " PORT_D <= (others => '0');\n" + + " else\n" + + " PORT_D <= my_rom(to_integer(unsigned(PORT_A)));\n" + + " end if;\n" + + " end process;\n" + + "end DIG_ROM_ROM_arch;", TestHelper.removeCommentLines(vhdl)); + } + +}