refactoring of DataField and DataEditor

This commit is contained in:
hneemann 2016-08-20 18:19:53 +02:00
parent 967c9c88f0
commit ee6d7483ee
12 changed files with 127 additions and 111 deletions

View File

@ -197,7 +197,7 @@
<string>1,15</string>
</entry>
</elementAttributes>
<pos x="600" y="600"/>
<pos x="700" y="600"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
@ -312,12 +312,12 @@
<p2 x="720" y="440"/>
</wire>
<wire>
<p1 x="600" y="600"/>
<p1 x="700" y="600"/>
<p2 x="820" y="600"/>
</wire>
<wire>
<p1 x="540" y="600"/>
<p2 x="580" y="600"/>
<p2 x="680" y="600"/>
</wire>
<wire>
<p1 x="520" y="280"/>

View File

@ -14,11 +14,10 @@ public class DataField {
/***
* Simple default data field
*/
public static final DataField DEFAULT = new DataField(0, 8);
public static final DataField DEFAULT = new DataField(0);
private final int size;
private long[] data;
private final int bits;
private final transient ArrayList<DataListener> listeners = new ArrayList<>();
@ -26,16 +25,14 @@ public class DataField {
* Creates a new DataField
*
* @param size size
* @param bits number of bits
*/
public DataField(int size, int bits) {
this(new long[size], size, bits);
public DataField(int size) {
this(new long[size], size);
}
private DataField(long[] data, int size, int bits) {
private DataField(long[] data, int size) {
this.size = size;
this.data = data;
this.bits = bits;
}
/**
@ -44,10 +41,9 @@ public class DataField {
*
* @param dataField the data to use
* @param newSize new size
* @param bits number og bits
*/
public DataField(DataField dataField, int newSize, int bits) {
this(Arrays.copyOf(dataField.data, newSize), newSize, bits);
public DataField(DataField dataField, int newSize) {
this(Arrays.copyOf(dataField.data, newSize), newSize);
}
/**
@ -87,7 +83,6 @@ public class DataField {
}
size = pos;
}
bits = 16;
}
/**
@ -142,14 +137,7 @@ public class DataField {
if (pos == data.length)
return this;
else
return new DataField(Arrays.copyOf(data, pos), size, bits);
}
/**
* @return the number of bits
*/
public int getBits() {
return bits;
return new DataField(Arrays.copyOf(data, pos), size);
}
/**

View File

@ -1,9 +1,6 @@
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.*;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.ElementTypeDescription;
@ -36,13 +33,13 @@ public class RAMDualPort extends Node implements Element, RAMInterface {
private final DataField memory;
private final ObservableValue output;
protected final int addrBits;
protected final int bits;
protected ObservableValue addrIn;
protected ObservableValue dataIn;
protected ObservableValue strIn;
protected ObservableValue clkIn;
protected ObservableValue ldIn;
private final int addrBits;
private final int bits;
private ObservableValue addrIn;
private ObservableValue dataIn;
private ObservableValue strIn;
private ObservableValue clkIn;
private ObservableValue ldIn;
private int addr;
private boolean lastClk = false;
private boolean ld;
@ -57,7 +54,7 @@ public class RAMDualPort extends Node implements Element, RAMInterface {
bits = attr.get(Keys.BITS);
output = createOutput();
addrBits = attr.get(Keys.ADDR_BITS);
memory = new DataField(1 << addrBits, bits);
memory = new DataField(1 << addrBits);
}
/**
@ -71,11 +68,61 @@ public class RAMDualPort extends Node implements Element, RAMInterface {
@Override
public void setInputs(ObservableValues inputs) throws NodeException {
addrIn = inputs.get(0).checkBits(addrBits, this).addObserverToValue(this);
dataIn = inputs.get(1).checkBits(bits, this).addObserverToValue(this);
strIn = inputs.get(2).checkBits(1, this).addObserverToValue(this);
clkIn = inputs.get(3).checkBits(1, this).addObserverToValue(this);
ldIn = inputs.get(4).checkBits(1, this).addObserverToValue(this);
setAddrIn(inputs.get(0));
setDataIn(inputs.get(1));
setStrIn(inputs.get(2));
setClkIn(inputs.get(3));
setLdIn(inputs.get(4));
}
/**
* Sets the addrIn input value
*
* @param addrIn addrIn
* @throws BitsException BitsException
*/
protected void setAddrIn(ObservableValue addrIn) throws BitsException {
this.addrIn = addrIn.checkBits(addrBits, this).addObserverToValue(this);
}
/**
* Sets the dataIn input value
*
* @param dataIn dataIn
* @throws BitsException BitsException
*/
protected void setDataIn(ObservableValue dataIn) throws BitsException {
this.dataIn = dataIn.checkBits(bits, this).addObserverToValue(this);
}
/**
* Sets the strIn input value
*
* @param strIn strIn
* @throws BitsException BitsException
*/
protected void setStrIn(ObservableValue strIn) throws BitsException {
this.strIn = strIn.checkBits(1, this).addObserverToValue(this);
}
/**
* Sets the clkIn input value
*
* @param clkIn clkIn
* @throws BitsException BitsException
*/
protected void setClkIn(ObservableValue clkIn) throws BitsException {
this.clkIn = clkIn.checkBits(1, this).addObserverToValue(this);
}
/**
* Sets the ldIn input value
*
* @param ldIn ldIn
* @throws BitsException BitsException
*/
protected void setLdIn(ObservableValue ldIn) throws BitsException {
this.ldIn = ldIn.checkBits(1, this).addObserverToValue(this);
}
@Override

View File

@ -56,11 +56,11 @@ public class RAMSinglePort extends RAMDualPort {
@Override
public void setInputs(ObservableValues inputs) throws NodeException {
addrIn = inputs.get(0).checkBits(addrBits, this).addObserverToValue(this);
strIn = inputs.get(1).checkBits(1, this).addObserverToValue(this);
clkIn = inputs.get(2).checkBits(1, this).addObserverToValue(this);
ldIn = inputs.get(3).checkBits(1, this).addObserverToValue(this);
dataIn = inputs.get(4).checkBits(bits, this).addObserverToValue(this); // additional input to read the port
setAddrIn(inputs.get(0));
setStrIn(inputs.get(1));
setClkIn(inputs.get(2));
setLdIn(inputs.get(3));
setDataIn(inputs.get(4)); // additional input to read the port
}
}

View File

@ -2,6 +2,8 @@ package de.neemann.digital.draw.shapes;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.core.memory.DataField;
import de.neemann.digital.core.memory.RAMInterface;
@ -14,19 +16,24 @@ import java.awt.*;
/**
* The RAM shape
*
* @author hneemann
*/
public class RAMShape extends GenericShape {
private final int bits;
private final int size;
/**
* Creates a new instance
*
* @param name name of the element
* @param attr the label to use
* @param inputs the inputs
* @param outputs the outputs
* @param label the label to use
*/
public RAMShape(String name, PinDescriptions inputs, PinDescriptions outputs, String label) {
super(name, inputs, outputs, label, true);
public RAMShape(ElementAttributes attr, PinDescriptions inputs, PinDescriptions outputs) {
super("RAM", inputs, outputs, attr.getLabel(), true);
bits = attr.get(Keys.BITS);
size = 1 << attr.get(Keys.ADDR_BITS);
}
@Override
@ -36,7 +43,7 @@ public class RAMShape extends GenericShape {
public boolean clicked(CircuitComponent cc, Point pos, IOState ioState, Element element, Sync modelSync) {
if (element instanceof RAMInterface) {
DataField dataField = ((RAMInterface) element).getMemory();
new DataEditor(cc, dataField, modelSync).showDialog();
new DataEditor(cc, dataField, size, bits, true, modelSync).showDialog();
}
return false;
}

View File

@ -69,8 +69,8 @@ public final class ShapeFactory {
}
map.put(RAMDualPort.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape("RAM", RAMDualPort.DESCRIPTION.getInputDescription(attr), RAMDualPort.DESCRIPTION.getOutputDescriptions(attr), attr.getLabel()));
map.put(RAMSinglePort.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape("RAM", RAMSinglePort.DESCRIPTION.getInputDescription(attr), RAMSinglePort.DESCRIPTION.getOutputDescriptions(attr), attr.getLabel()));
map.put(RAMDualPort.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMDualPort.DESCRIPTION.getInputDescription(attr), RAMDualPort.DESCRIPTION.getOutputDescriptions(attr)));
map.put(RAMSinglePort.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMSinglePort.DESCRIPTION.getInputDescription(attr), RAMSinglePort.DESCRIPTION.getOutputDescriptions(attr)));
map.put(In.DESCRIPTION.getName(), InputShape::new);
map.put(Reset.DESCRIPTION.getName(), ResetShape::new);

View File

@ -1,7 +1,5 @@
package de.neemann.digital.gui.components;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.memory.DataField;
import de.neemann.digital.gui.sync.Sync;
import de.neemann.digital.lang.Lang;
@ -24,7 +22,7 @@ import java.util.ArrayList;
* @author hneemann
*/
public class DataEditor extends JDialog {
private final DataField dataField;
private final DataField localDataField;
private boolean ok = false;
/**
@ -33,71 +31,44 @@ public class DataEditor extends JDialog {
* @param parent the parent
* @param dataField the data to edit
*/
public DataEditor(JComponent parent, DataField dataField, Sync modelSync) {
this(parent, dataField, null, modelSync);
}
/**
* Creates a new instance
*
* @param parent the parent
* @param dataField the data to edit
* @param attr uset to get bit sizes
*/
public DataEditor(JComponent parent, DataField dataField, ElementAttributes attr, Sync modelSync) {
super(SwingUtilities.windowForComponent(parent), Lang.get("key_Data"), attr == null ? ModalityType.MODELESS : ModalityType.APPLICATION_MODAL);
public DataEditor(JComponent parent, DataField dataField, int size, int bits, boolean modelIsRunning, Sync modelSync) {
super(SwingUtilities.windowForComponent(parent), Lang.get("key_Data"), modelIsRunning ? ModalityType.MODELESS : ModalityType.APPLICATION_MODAL);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
int size;
int bits;
boolean register;
if (attr != null) {
bits = attr.getBits();
if (attr.contains(Keys.ADDR_BITS))
size = 1 << attr.get(Keys.ADDR_BITS);
else
size = 1 << attr.get(Keys.INPUT_COUNT);
this.dataField = new DataField(dataField, size, bits);
register = false;
} else {
this.dataField = dataField;
size = this.dataField.size();
bits = this.dataField.getBits();
register = true;
}
if (modelIsRunning)
localDataField = dataField;
else
localDataField = new DataField(dataField, size);
int cols = 16;
if (size <= 16) cols = 1;
else if (size <= 128) cols = 8;
MyTableModel dm = new MyTableModel(this.dataField, cols, modelSync);
MyTableModel dm = new MyTableModel(this.localDataField, cols, modelSync);
JTable table = new JTable(dm);
table.setDefaultRenderer(MyLong.class, new MyLongRenderer(bits));
getContentPane().add(new JScrollPane(table));
if (register) {
this.dataField.addListener(dm);
if (modelIsRunning) {
dataField.addListener(dm);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
DataEditor.this.dataField.removeListener(dm);
dataField.removeListener(dm);
}
});
} else {
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
buttons.add(new JButton(new AbstractAction(Lang.get("ok")) {
@Override
public void actionPerformed(ActionEvent e) {
ok = true;
dispose();
}
}));
getContentPane().add(buttons, BorderLayout.SOUTH);
}
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
buttons.add(new JButton(new AbstractAction(Lang.get("ok")) {
@Override
public void actionPerformed(ActionEvent e) {
ok = true;
dispose();
}
}));
getContentPane().add(buttons, BorderLayout.SOUTH);
setPreferredSize(new Dimension((cols + 1) * 50, getPreferredSize().height));
pack();
@ -108,8 +79,8 @@ public class DataEditor extends JDialog {
/**
* @return the data field
*/
public DataField getDataField() {
return dataField;
public DataField getModifiedDataField() {
return localDataField;
}
/**
@ -174,7 +145,7 @@ public class DataEditor extends JDialog {
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
modelSync.access(()->{
modelSync.access(() -> {
dataField.setData(rowIndex * cols + (columnIndex - 1), ((MyLong) aValue).getValue());
});
}

View File

@ -2,6 +2,7 @@ package de.neemann.digital.gui.components;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Key;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.Rotation;
import de.neemann.digital.core.io.IntFormat;
import de.neemann.digital.core.memory.DataField;
@ -236,9 +237,11 @@ public final class EditorFactory {
panel.add(new ToolTipAction(Lang.get("btn_edit")) {
@Override
public void actionPerformed(ActionEvent e) {
DataEditor de = new DataEditor(panel, data, attr, NoSync.INST);
int bits = attr.get(Keys.BITS);
int size = 1 << attr.get(Keys.ADDR_BITS);
DataEditor de = new DataEditor(panel, data, size, bits, false, NoSync.INST);
if (de.showDialog()) {
data = de.getDataField();
data = de.getModifiedDataField();
}
}
}.createJButton());

View File

@ -67,7 +67,7 @@ public class GraphicCard extends Node implements Element, RAMInterface {
width = attr.get(Keys.GRAPHIC_WIDTH);
height = attr.get(Keys.GRAPHIC_HEIGHT);
bankSize = width * height;
memory = new DataField(bankSize * 2, 8);
memory = new DataField(bankSize * 2);
dataOut = new ObservableValue("D", 16, true)
.setDescription(Lang.get("elem_RAMSinglePort_pin_d"))

View File

@ -10,7 +10,7 @@ import java.io.StringReader;
public class DataFieldTest extends TestCase {
public void testGetMinimized() throws Exception {
DataField data = new DataField(100, 8);
DataField data = new DataField(100);
data.setData(9, 1);
data = data.getMinimized();
assertEquals(1, data.getDataWord(9));
@ -19,7 +19,7 @@ public class DataFieldTest extends TestCase {
}
public void testGrow() throws Exception {
DataField data = new DataField(100, 8);
DataField data = new DataField(100);
data.setData(9, 1);
data = data.getMinimized();
assertEquals(1, data.getDataWord(9));

View File

@ -20,7 +20,7 @@ public class LUTTest extends TestCase {
ObservableValue c = new ObservableValue("c", 1);
Model model = new Model();
DataField data = new DataField(8, 8);
DataField data = new DataField(8);
data.setData(3, 1);
data.setData(7, 1);
LookUpTable out = model.add(new LookUpTable(

View File

@ -19,7 +19,7 @@ public class ROMTest extends TestCase {
ObservableValue sel = new ObservableValue("sel", 1);
Model model = new Model();
DataField data = new DataField(8, 8);
DataField data = new DataField(8);
data.setData(3, 17);
data.setData(7, 200);
ROM out = model.add(new ROM(