simplified the new masked ram

This commit is contained in:
hneemann 2019-01-23 20:59:01 +01:00
parent 0cea738d74
commit b4f6c804b7
6 changed files with 165 additions and 143 deletions

View File

@ -167,15 +167,11 @@ public class RAMDualPort extends Node implements Element, RAMInterface {
addr = (int) addrIn.getValue();
if (str)
writeDataToMemory(addr, data);
memory.setData(addr, data);
lastClk = clk;
}
void writeDataToMemory(int addr, long data) {
memory.setData(addr, data);
}
@Override
public void writeOutputs() throws NodeException {
if (ld) {

View File

@ -5,19 +5,22 @@
*/
package de.neemann.digital.core.memory;
import de.neemann.digital.core.Node;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.ObservableValues;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.draw.elements.PinException;
import static de.neemann.digital.core.element.PinInfo.input;
/**
* A memory which allows to overwrite single bytes.
*/
public class RAMDualPortMasked extends RAMDualPort {
public class RAMDualPortMasked extends Node implements Element, RAMInterface {
private static final long[] MASK_TABLE = new long[256];
@ -41,17 +44,27 @@ public class RAMDualPortMasked extends RAMDualPort {
input("A"),
input("Din"),
input("str"),
input("C").setClock(),
input("ld"),
input("mask"))
input("C").setClock())
.addAttribute(Keys.ROTATE)
.addAttribute(Keys.BITS)
.addAttribute(Keys.ADDR_BITS)
.addAttribute(Keys.IS_PROGRAM_MEMORY)
.addAttribute(Keys.LABEL);
private DataField memory;
private final ObservableValue output;
private final int addrBits;
private final int bits;
private final String label;
private final int size;
private final boolean isProgramMemory;
private final int maskBits;
private ObservableValue maskVal;
private ObservableValue addrIn;
private ObservableValue dataIn;
private ObservableValue clkIn;
private boolean lastClk = false;
private long outputVal;
/**
* Creates a new instance
@ -59,25 +72,95 @@ public class RAMDualPortMasked extends RAMDualPort {
* @param attr the elements attributes
*/
public RAMDualPortMasked(ElementAttributes attr) {
super(attr);
super(true);
bits = attr.get(Keys.BITS);
output = new ObservableValue("D", bits).setPinDescription(DESCRIPTION);
addrBits = attr.get(Keys.ADDR_BITS);
size = 1 << addrBits;
memory = new DataField(size);
label = attr.getCleanLabel();
isProgramMemory = attr.get(Keys.IS_PROGRAM_MEMORY);
maskBits = Math.min(8, (getDataBits() - 1) / 8 + 1);
}
@Override
public void setInputs(ObservableValues inputs) throws NodeException {
super.setInputs(inputs);
maskVal = inputs.get(5).checkBits(maskBits, this).addObserverToValue(this);
addrIn = inputs.get(0).checkBits(addrBits, this);
dataIn = inputs.get(1).checkBits(bits, this);
maskVal = inputs.get(2).checkBits(maskBits, this);
clkIn = inputs.get(3).checkBits(1, this).addObserverToValue(this);
}
@Override
void writeDataToMemory(int addr, long data) {
public void readInputs() throws NodeException {
boolean clk = clkIn.getBool();
if (!lastClk && clk) {
int addr = (int) addrIn.getValue();
outputVal = memory.getDataWord(addr);
int maskVal = (int) this.maskVal.getValue();
if (maskVal != 0) {
long wData = dataIn.getValue();
writeDataToMemory(addr, wData, maskVal);
}
}
lastClk = clk;
}
private void writeDataToMemory(int addr, long data, int maskVal) {
DataField memory = getMemory();
long old = memory.getDataWord(addr);
long mask = MASK_TABLE[(int) maskVal.getValue()];
long mask = MASK_TABLE[maskVal];
data = data & mask;
old = old & ~mask;
memory.setData(addr, data | old);
}
@Override
public void writeOutputs() throws NodeException {
output.setValue(outputVal);
}
@Override
public ObservableValues getOutputs() throws PinException {
return output.asList();
}
@Override
public DataField getMemory() {
return memory;
}
@Override
public String getLabel() {
return label;
}
@Override
public int getSize() {
return size;
}
@Override
public int getAddrBits() {
return addrBits;
}
@Override
public boolean isProgramMemory() {
return isProgramMemory;
}
@Override
public void setProgramMemory(DataField dataField) {
memory.setDataFrom(dataField);
}
@Override
public int getDataBits() {
return bits;
}
}

View File

@ -483,17 +483,16 @@
<string name="elem_RAMDualPortMasked_tt">Ein RAM Modul mit getrennten Daten-Anschlüssen für Lesen und Schreiben.
Es gibt einen Eingang für das Beschreiben und einen Ausgang für das Auslesen der gespeicherten Daten.
Zusätzlich wird das Überschreigen einzelner Bytes ermöglicht. Auf diese Weise kann z.B. in einem 32
Bit Speicher ein einzelnes Byte überschrieben werden.
Bit Speicher ein einzelnes Byte überschrieben werden. Dieser RAM-Baustein aktualisiert seinen Ausgang
nur bei einer steigenden Flanke an der Clock. Das erlaubt die Verwendung von Block-RAM in einem FPGA.
</string>
<string name="elem_RAMDualPortMasked_pin_A">Die Adresse, an der gelesen bzw. geschrieben wird.</string>
<string name="elem_RAMDualPortMasked_pin_C">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
<string name="elem_RAMDualPortMasked_pin_C">Der Takt. A rising edge activates storing and reading.</string>
<string name="elem_RAMDualPortMasked_pin_Din">Die Daten, die gespeichert werden sollen.</string>
<string name="elem_RAMDualPortMasked_pin_D">Ausgabe der gespeicherten Daten.</string>
<string name="elem_RAMDualPortMasked_pin_ld">Ist diese Leitung high, wird der Ausgang aktiviert, und die Daten liegen dort an.</string>
<string name="elem_RAMDualPortMasked_pin_str">Ist diese Leitung high, wird das Datenwort gespeichert, wenn der Takt ansteigt.</string>
<string name="elem_RAMDualPortMasked_pin_mask">Setzt die Schreibmaske. In dieser Maske steht jewels ein Bit für ein
<string name="elem_RAMDualPortMasked_pin_str">Setzt die Schreibmaske. In dieser Maske steht jewels ein Bit für ein
Byte im Speicher, welches überschrieben werden kann. Soll also das zweite Byte im Speicherwort überschrieben werden,
muss auch das zweite Bit in der Maske gesetzt sein.
muss auch das zweite Bit in der Maske gesetzt sein. Ist kein Bit gesetzt, wird nicht gespeichert.
</string>
<string name="elem_EEPROMDualPort">EEPROM, getrennte Ports</string>

View File

@ -486,19 +486,19 @@
<string name="elem_RAMDualPortMasked">RAM, separated ports, byte access</string>
<string name="elem_RAMDualPortMasked_short">RAM</string>
<string name="elem_RAMDualPortMasked_tt">A RAM module with separate inputs for storing and output for reading the stored data.
In addition, individual bytes can be overwritten. In this way, for example, a single byte can be overwritten in a 32-bit memory.
<string name="elem_RAMDualPortMasked_tt">A RAM module with separate inputs for storing and output for reading the
stored data. In addition, individual bytes can be overwritten. In this way, for example, a single byte can be
overwritten in a 32-bit memory. This RAM only updates its output on a rising edge of the clock input.
This allows the usage of Block RAM on an FPGA.
</string>
<string name="elem_RAMDualPortMasked_pin_A">The address to read from or write to.</string>
<string name="elem_RAMDualPortMasked_pin_C">Clock input</string>
<string name="elem_RAMDualPortMasked_pin_Din">The data to be stored in the RAM.</string>
<string name="elem_RAMDualPortMasked_pin_D">The data output pin</string>
<string name="elem_RAMDualPortMasked_pin_ld">If this input is high the output is activated and the data is visible at the output.</string>
<string name="elem_RAMDualPortMasked_pin_str">If this input is high and when the clock becomes high, the the data is stored.</string>
<string name="elem_RAMDualPortMasked_pin_mask">Sets the write mask. In this mask there is one bit for each byte in the memory,
<string name="elem_RAMDualPortMasked_pin_str">Sets the write mask. In this mask there is one bit for each byte in the memory,
which can be overwritten. If the second byte in the memory word is to be overwritten, the second bit in
the mask must also be set.</string>
the mask must also be set. If no bit is set, no data is stored.
</string>
<string name="elem_EEPROMDualPort">EEPROM, separated Ports</string>
<string name="elem_EEPROMDualPort_short">EEPROM</string>
<string name="elem_EEPROMDualPort_tt">A EEPROM module with separate inputs for storing and output for reading the stored data.</string>

View File

@ -29,7 +29,7 @@
<int>32</int>
</entry>
</elementAttributes>
<pos x="500" y="240"/>
<pos x="500" y="220"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
@ -43,7 +43,7 @@
<int>8</int>
</entry>
</elementAttributes>
<pos x="260" y="180"/>
<pos x="280" y="180"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
@ -59,16 +59,6 @@
</elementAttributes>
<pos x="380" y="200"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>str</string>
</entry>
</elementAttributes>
<pos x="260" y="220"/>
</visualElement>
<visualElement>
<elementName>Clock</elementName>
<elementAttributes>
@ -79,16 +69,6 @@
</elementAttributes>
<pos x="380" y="260"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>ld</string>
</entry>
</elementAttributes>
<pos x="260" y="280"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
@ -101,7 +81,7 @@
<int>4</int>
</entry>
</elementAttributes>
<pos x="380" y="300"/>
<pos x="280" y="240"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
@ -109,55 +89,55 @@
<entry>
<string>Testdata</string>
<testData>
<dataString>C A Din str ld mask D
<dataString>C A Din mask D
# no write at all, mask is zero
C 0 0xffffffff 1 0 0b0000 x
0 0 0 0 1 0b0000 0
C 0 0xffffffff 0b0000 x
0 0 0 0b0000 0
# write bytes
C 0 0xffffffff 1 0 0b0001 x
0 0 0 0 1 0b0000 0xff
C 0 0xffffffff 0b0001 x
C 0 0 0b0000 0xff
C 0 0xffffff00 1 0 0b0010 x
0 0 0 0 1 0b0000 0xffff
C 0 0xffffff00 0b0010 x
C 0 0 0b0000 0xffff
C 0 0xffff0000 1 0 0b0100 x
0 0 0 0 1 0b0000 0xffffff
C 0 0xffff0000 0b0100 x
C 0 0 0b0000 0xffffff
C 0 0xff000000 1 0 0b1000 x
0 0 0 0 1 0b0000 0xffffffff
C 0 0xff000000 0b1000 x
C 0 0 0b0000 0xffffffff
# write 16 bit words
C 1 0xffff 1 0 0b0011 x
0 1 0 0 1 0b0000 0xffff
C 1 0xffff 0b0011 x
C 1 0 0b0000 0xffff
C 1 0xffff0000 1 0 0b1100 x
0 1 0 0 1 0b0000 0xffffffff
C 1 0xffff0000 0b1100 x
C 1 0 0b0000 0xffffffff
C 1 0xaaaa00 1 0 0b0110 x
0 1 0 0 1 0b0000 0xffaaaaff
C 1 0xaaaa00 0b0110 x
C 1 0 0b0000 0xffaaaaff
# write 32 bit words
C 2 0xffffffff 1 0 0b1111 x
0 2 0 0 1 0b0000 0xffffffff
C 2 0xffffffff 0b1111 x
C 2 0 0b0000 0xffffffff
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="320" y="340"/>
<pos x="320" y="320"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="460" y="240"/>
<p2 x="500" y="240"/>
<p1 x="280" y="240"/>
<p2 x="400" y="240"/>
</wire>
<wire>
<p1 x="260" y="180"/>
<p1 x="280" y="180"/>
<p2 x="400" y="180"/>
</wire>
<wire>
@ -169,16 +149,8 @@ C 2 0xffffffff 1 0 0b1111 x
<p2 x="400" y="200"/>
</wire>
<wire>
<p1 x="260" y="280"/>
<p2 x="400" y="280"/>
</wire>
<wire>
<p1 x="260" y="220"/>
<p2 x="400" y="220"/>
</wire>
<wire>
<p1 x="380" y="300"/>
<p2 x="400" y="300"/>
<p1 x="460" y="220"/>
<p2 x="500" y="220"/>
</wire>
</wires>
</circuit>

View File

@ -29,7 +29,7 @@
<int>64</int>
</entry>
</elementAttributes>
<pos x="500" y="240"/>
<pos x="500" y="220"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
@ -43,7 +43,7 @@
<int>8</int>
</entry>
</elementAttributes>
<pos x="260" y="180"/>
<pos x="280" y="180"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
@ -59,16 +59,6 @@
</elementAttributes>
<pos x="380" y="200"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>str</string>
</entry>
</elementAttributes>
<pos x="260" y="220"/>
</visualElement>
<visualElement>
<elementName>Clock</elementName>
<elementAttributes>
@ -79,16 +69,6 @@
</elementAttributes>
<pos x="380" y="260"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>ld</string>
</entry>
</elementAttributes>
<pos x="260" y="280"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
@ -101,7 +81,7 @@
<int>8</int>
</entry>
</elementAttributes>
<pos x="380" y="300"/>
<pos x="280" y="240"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
@ -109,59 +89,59 @@
<entry>
<string>Testdata</string>
<testData>
<dataString>C A Din str ld mask D
<dataString>C A Din mask D
# no write at all, mask is zero
C 0 0xffffffffffffffff 1 0 0b00000000 x
0 0 0 0 1 0b00000000 0
C 0 0xffffffffffffffff 0b00000000 x
C 0 0 0b00000000 0
# write bytes
C 0 0xffffffffffffffff 1 0 0b00000001 x
0 0 0 0 1 0b00000000 0xff
C 0 0xffffffffffffffff 0b00000001 x
C 0 0 0b00000000 0xff
C 0 0xffffffffffffff00 1 0 0b00000010 x
0 0 0 0 1 0b00000000 0xffff
C 0 0xffffffffffffff00 0b00000010 x
C 0 0 0b00000000 0xffff
C 0 0xffffffffffff0000 1 0 0b00000100 x
0 0 0 0 1 0b00000000 0xffffff
C 0 0xffffffffffff0000 0b00000100 x
C 0 0 0b00000000 0xffffff
C 0 0xffffffffff000000 1 0 0b00001000 x
0 0 0 0 1 0b00000000 0xffffffff
C 0 0xffffffffff000000 0b00001000 x
C 0 0 0b00000000 0xffffffff
C 0 0xffffffff00000000 1 0 0b00010000 x
0 0 0 0 1 0b00000000 0xffffffffff
C 0 0xffffffff00000000 0b00010000 x
C 0 0 0b00000000 0xffffffffff
C 0 0xffffff0000000000 1 0 0b00100000 x
0 0 0 0 1 0b00000000 0xffffffffffff
C 0 0xffffff0000000000 0b00100000 x
C 0 0 0b00000000 0xffffffffffff
C 0 0xffff000000000000 1 0 0b01000000 x
0 0 0 0 1 0b00000000 0xffffffffffffff
C 0 0xffff000000000000 0b01000000 x
C 0 0 0b00000000 0xffffffffffffff
C 0 0xff00000000000000 1 0 0b10000000 x
0 0 0 0 1 0b00000000 0xffffffffffffffff
C 0 0xff00000000000000 0b10000000 x
C 0 0 0b00000000 0xffffffffffffffff
# write 32 bit words
C 1 0xffffffff 1 0 0b00001111 x
0 1 0 0 1 0b00000000 0xffffffff
C 1 0xffffffff 0b00001111 x
C 1 0 0b00000000 0xffffffff
C 1 0xaaaaaaaa00000000 1 0 0b11110000 x
0 1 0 0 1 0b00000000 0xaaaaaaaaffffffff
C 1 0xaaaaaaaa00000000 0b11110000 x
C 1 0 0b00000000 0xaaaaaaaaffffffff
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="300" y="340"/>
<pos x="320" y="320"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="460" y="240"/>
<p2 x="500" y="240"/>
<p1 x="280" y="240"/>
<p2 x="400" y="240"/>
</wire>
<wire>
<p1 x="260" y="180"/>
<p1 x="280" y="180"/>
<p2 x="400" y="180"/>
</wire>
<wire>
@ -173,16 +153,8 @@ C 1 0xaaaaaaaa00000000 1 0 0b11110000 x
<p2 x="400" y="200"/>
</wire>
<wire>
<p1 x="260" y="280"/>
<p2 x="400" y="280"/>
</wire>
<wire>
<p1 x="260" y="220"/>
<p2 x="400" y="220"/>
</wire>
<wire>
<p1 x="380" y="300"/>
<p2 x="400" y="300"/>
<p1 x="460" y="220"/>
<p2 x="500" y="220"/>
</wire>
</wires>
</circuit>