replaced ROMEntity by a template

This commit is contained in:
hneemann 2018-03-15 10:03:52 +01:00
parent 0845698b38
commit 5d03b9e38a
7 changed files with 166 additions and 127 deletions

View File

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

View File

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

View File

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

View File

@ -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) {

View File

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

View File

@ -0,0 +1,46 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.ALL;
<?
entityName="DIG_ROM_"+elem.Label;
?>
entity <?=entityName?> is
port (
PORT_D: out <?=type(elem.Bits)?>;
PORT_A: in <?=type(elem.AddrBits)?>;
PORT_sel: in std_logic );
end <?=entityName?>;
architecture <?=entityName?>_arch of <?=entityName?> is
type mem is array ( 0 to <?=sizeOf(elem.Data)-1?>) of <?=type(elem.Bits)?>;
constant my_Rom : mem := (
<?
len=sizeOf(elem.Data);
col=0;
for (i=0;i<len;i++) {
print(value(elem.Data[i],elem.Bits));
if (i<len-1) {
print(", ");
}
col++
if (col=6) {
col=0;
print("\n ");
}
}
?>);
begin
process (PORT_A, PORT_sel)
begin
if PORT_sel='0' then
PORT_D <= <? if (elem.Bits>1) {?>(others => 'Z')<? } else {?>'Z'<? } ?>;
elsif PORT_A > <?=value(sizeOf(elem.Data)-1,elem.AddrBits)?> then
PORT_D <= <?=zero(elem.Bits)?>;
else
PORT_D <= my_rom(to_integer(unsigned(PORT_A)));
end if;
end process;
end <?=entityName?>_arch;

View File

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