diff --git a/src/main/java/de/neemann/digital/core/memory/EEPROM.java b/src/main/java/de/neemann/digital/core/memory/EEPROM.java index 4e14d2a57..9b02cd47a 100644 --- a/src/main/java/de/neemann/digital/core/memory/EEPROM.java +++ b/src/main/java/de/neemann/digital/core/memory/EEPROM.java @@ -5,6 +5,11 @@ */ 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; @@ -15,7 +20,7 @@ import static de.neemann.digital.core.element.PinInfo.input; /** * A EEPROM module. */ -public class EEPROM extends RAMSinglePortSel implements ROMInterface { +public class EEPROM extends Node implements Element, RAMInterface, ROMInterface { /** * The EEPROMs {@link ElementTypeDescription} @@ -33,17 +38,129 @@ public class EEPROM extends RAMSinglePortSel implements ROMInterface { .addAttribute(Keys.INVERTER_CONFIG) .addAttribute(Keys.DATA); + private final int bits; + private final int addrBits; + private final int size; + private final String label; + private final ObservableValue dataOut; + private final boolean isProgramMemory; + private DataField memory; + private ObservableValue addrIn; + private ObservableValue csIn; + private ObservableValue weIn; + private ObservableValue oeIn; + private ObservableValue dataIn; + + private int readAddr; + private int writeAddr; + private boolean cs; + private boolean oe; + private boolean we; + private boolean lastWrite; + /** * Creates a new instance * * @param attr the elements attributes */ public EEPROM(ElementAttributes attr) { - super(attr); + super(true); + bits = attr.get(Keys.BITS); + addrBits = attr.get(Keys.ADDR_BITS); + size = 1 << addrBits; + memory = attr.get(Keys.DATA); + label = attr.getLabel(); + dataOut = new ObservableValue("D", bits) + .setToHighZ() + .setPinDescription(DESCRIPTION) + .setBidirectional(); + isProgramMemory = attr.get(Keys.IS_PROGRAM_MEMORY); } @Override - protected DataField createDataField(ElementAttributes attr, int size) { - return attr.get(Keys.DATA); + public void setInputs(ObservableValues inputs) throws NodeException { + addrIn = inputs.get(0).checkBits(addrBits, this).addObserverToValue(this); + csIn = inputs.get(1).checkBits(1, this).addObserverToValue(this); + weIn = inputs.get(2).checkBits(1, this).addObserverToValue(this); + oeIn = inputs.get(3).checkBits(1, this).addObserverToValue(this); + dataIn = inputs.get(4).checkBits(bits, this); + } + + @Override + public void readInputs() throws NodeException { + cs = csIn.getBool(); + if (cs) { + readAddr = (int) addrIn.getValue(); + oe = oeIn.getBool(); + } + + we = weIn.getBool(); + boolean write = cs && we; + if (write && !lastWrite) + writeAddr = (int) addrIn.getValue(); + + if (!write && lastWrite) { + long data = dataIn.getValue(); + memory.setData(writeAddr, data); + } + lastWrite = write; + } + + @Override + public void writeOutputs() throws NodeException { + if (cs && oe && !we) { + dataOut.setValue(memory.getDataWord(readAddr)); + } else { + dataOut.setToHighZ(); + } + } + + @Override + public ObservableValues getOutputs() { + return dataOut.asList(); + } + + @Override + public DataField getMemory() { + return memory; + } + + @Override + public String getLabel() { + return label; + } + + @Override + public int getSize() { + return size; + } + + @Override + public int getDataBits() { + return bits; + } + + @Override + public int getAddrBits() { + return addrBits; + } + + /** + * Sets the rams data + * + * @param data the data to set + */ + public void setData(DataField data) { + this.memory = data; + } + + @Override + public boolean isProgramMemory() { + return isProgramMemory; + } + + @Override + public void setProgramMemory(DataField dataField) { + memory.setDataFrom(dataField); } } diff --git a/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java b/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java index 8b75e5144..fdbb58284 100644 --- a/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java +++ b/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java @@ -5,12 +5,14 @@ */ package de.neemann.digital.core.memory; -import de.neemann.digital.core.*; +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; @@ -26,7 +28,7 @@ public class RAMSinglePortSel extends Node implements Element, RAMInterface { public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(RAMSinglePortSel.class, input("A"), input("CS"), - input("WE").setClock(), + input("WE"), input("OE")) .addAttribute(Keys.ROTATE) .addAttribute(Keys.BITS) @@ -48,12 +50,10 @@ public class RAMSinglePortSel extends Node implements Element, RAMInterface { private ObservableValue oeIn; private ObservableValue dataIn; - private int readAddr; - private int writeAddr; + private int addr; private boolean cs; private boolean oe; private boolean we; - private boolean lastWrite; /** * Creates a new instance @@ -65,7 +65,7 @@ public class RAMSinglePortSel extends Node implements Element, RAMInterface { bits = attr.get(Keys.BITS); addrBits = attr.get(Keys.ADDR_BITS); size = 1 << addrBits; - memory = createDataField(attr, size); + memory = new DataField(size); label = attr.getLabel(); dataOut = new ObservableValue("D", bits) .setToHighZ() @@ -74,57 +74,40 @@ public class RAMSinglePortSel extends Node implements Element, RAMInterface { isProgramMemory = attr.get(Keys.IS_PROGRAM_MEMORY); } - /** - * creates the data field to use - * - * @param attr the elements attributes - * @param size the size of the memory - * @return the memory to use - */ - protected DataField createDataField(ElementAttributes attr, int size) { - return new DataField(size); - } - @Override public void setInputs(ObservableValues inputs) throws NodeException { addrIn = inputs.get(0).checkBits(addrBits, this).addObserverToValue(this); csIn = inputs.get(1).checkBits(1, this).addObserverToValue(this); weIn = inputs.get(2).checkBits(1, this).addObserverToValue(this); oeIn = inputs.get(3).checkBits(1, this).addObserverToValue(this); - dataIn = inputs.get(4).checkBits(bits, this); + dataIn = inputs.get(4).checkBits(bits, this).addObserverToValue(this); } @Override public void readInputs() throws NodeException { cs = csIn.getBool(); if (cs) { - readAddr = (int) addrIn.getValue(); + addr = (int) addrIn.getValue(); oe = oeIn.getBool(); + we = weIn.getBool(); + if (we) { + long data = dataIn.getValue(); + memory.setData(addr, data); + } } - - we = weIn.getBool(); - boolean write = cs && we; - if (write && !lastWrite) - writeAddr = (int) addrIn.getValue(); - - if (!write && lastWrite) { - long data = dataIn.getValue(); - memory.setData(writeAddr, data); - } - lastWrite = write; } @Override public void writeOutputs() throws NodeException { if (cs && oe && !we) { - dataOut.setValue(memory.getDataWord(readAddr)); + dataOut.setValue(memory.getDataWord(addr)); } else { dataOut.setToHighZ(); } } @Override - public ObservableValues getOutputs() throws PinException { + public ObservableValues getOutputs() { return dataOut.asList(); } diff --git a/src/main/java/de/neemann/digital/gui/components/terminal/Terminal.java b/src/main/java/de/neemann/digital/gui/components/terminal/Terminal.java index edd699dca..900492205 100644 --- a/src/main/java/de/neemann/digital/gui/components/terminal/Terminal.java +++ b/src/main/java/de/neemann/digital/gui/components/terminal/Terminal.java @@ -16,11 +16,14 @@ import de.neemann.digital.core.element.Keys; import javax.swing.*; +import java.awt.*; + import static de.neemann.digital.core.element.PinInfo.input; /** */ public class Terminal extends Node implements Element { + private static final boolean HEADLESS = GraphicsEnvironment.isHeadless(); /** * The terminal description @@ -70,7 +73,7 @@ public class Terminal extends Node implements Element { boolean clockVal = clock.getBool(); if (!lastClock && clockVal && en.getBool()) { long value = data.getValue(); - if (value != 0) + if (value != 0 && !HEADLESS) SwingUtilities.invokeLater(() -> { if (terminalDialog == null || !terminalDialog.isVisible()) { terminalDialog = new TerminalDialog(getModel().getWindowPosManager().getMainFrame(), attr);