mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-18 09:24:42 -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);
|
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.size = size;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
@ -232,7 +238,7 @@ public class DataField implements HGSArray {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hgsArraySize() {
|
public int hgsArraySize() {
|
||||||
return size;
|
return data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -12,6 +12,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
|||||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||||
import de.neemann.digital.core.Bits;
|
import de.neemann.digital.core.Bits;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,14 +71,14 @@ public class DataFieldConverter implements Converter {
|
|||||||
try {
|
try {
|
||||||
// new type
|
// new type
|
||||||
int size = Integer.parseInt(reader.getAttribute("size"));
|
int size = Integer.parseInt(reader.getAttribute("size"));
|
||||||
DataField df = new DataField(size);
|
long[] data = new long[size];
|
||||||
StringTokenizer st = new StringTokenizer(reader.getValue(), ",");
|
StringTokenizer st = new StringTokenizer(reader.getValue(), ",");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (st.hasMoreTokens()) {
|
while (st.hasMoreTokens()) {
|
||||||
df.setData(i, Bits.decode(st.nextToken().trim(), 0, 16));
|
data[i] = Bits.decode(st.nextToken().trim(), 0, 16);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return df;
|
return new DataField(Arrays.copyOf(data, i), size);
|
||||||
} catch (Bits.NumberFormatException e) {
|
} catch (Bits.NumberFormatException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -184,12 +184,7 @@ class Tokenizer {
|
|||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
token = Token.STRING;
|
token = Token.STRING;
|
||||||
builder.setLength(0);
|
readString();
|
||||||
while ((c = readChar()) != '"') {
|
|
||||||
builder.append((char) c);
|
|
||||||
if (c < 0)
|
|
||||||
throw new IOException("EOF detected while scanning a string");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
token = Token.IDENT;
|
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 {
|
private void readNumber(int c) throws IOException {
|
||||||
token = Token.NUMBER;
|
token = Token.NUMBER;
|
||||||
builder.setLength(0);
|
builder.setLength(0);
|
||||||
|
@ -8,7 +8,6 @@ package de.neemann.digital.hdl.vhdl;
|
|||||||
import de.neemann.digital.core.basic.*;
|
import de.neemann.digital.core.basic.*;
|
||||||
import de.neemann.digital.core.element.ElementTypeDescription;
|
import de.neemann.digital.core.element.ElementTypeDescription;
|
||||||
import de.neemann.digital.core.extern.External;
|
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.HDLException;
|
||||||
import de.neemann.digital.hdl.model.HDLNode;
|
import de.neemann.digital.hdl.model.HDLNode;
|
||||||
import de.neemann.digital.hdl.model.Port;
|
import de.neemann.digital.hdl.model.Port;
|
||||||
@ -60,8 +59,6 @@ public class VHDLLibrary {
|
|||||||
.put("inv", true)));
|
.put("inv", true)));
|
||||||
|
|
||||||
put(External.DESCRIPTION, new ExternalVHDL());
|
put(External.DESCRIPTION, new ExternalVHDL());
|
||||||
|
|
||||||
put(ROM.DESCRIPTION, new ROMVHDL());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void put(ElementTypeDescription description, VHDLEntity entity) {
|
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