mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-17 00:44:40 -04:00
replaced ROMEntity by a template
This commit is contained in:
parent
0845698b38
commit
5d03b9e38a
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
46
src/main/resources/vhdl/DIG_ROM.tem
Normal file
46
src/main/resources/vhdl/DIG_ROM.tem
Normal 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;
|
78
src/test/java/de/neemann/digital/hdl/vhdl/lib/ROMTest.java
Normal file
78
src/test/java/de/neemann/digital/hdl/vhdl/lib/ROMTest.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user