more consistent handling of int format in probe dialog, fixes #105

This commit is contained in:
hneemann 2018-01-14 11:51:31 +01:00
parent c41658ba55
commit edad475434
12 changed files with 91 additions and 12 deletions

View File

@ -88,7 +88,7 @@ public final class Bits {
/**
* Decodes a string to a long.
* Supports decimal, octal, hex and binary
* Supports decimal, octal, hex, binary and ascii
*
* @param str the string
* @return the long value
@ -139,6 +139,10 @@ public final class Bits {
p++;
if (p == str.length()) throw new NumberFormatException(str, p);
break;
case '\'':
p++;
if (p == str.length()) throw new NumberFormatException(str, p);
return str.charAt(p);
default:
if (wasZero) {
if (neg) throw new NumberFormatException(str, p);

View File

@ -1,5 +1,7 @@
package de.neemann.digital.core;
import de.neemann.digital.core.io.IntFormat;
/**
* A simple storage bean for signals
*/
@ -7,6 +9,7 @@ public final class Signal implements Comparable<Signal> {
private final String name;
private final ObservableValue value;
private final Setter setter;
private IntFormat format = IntFormat.def;
private String pinNumber;
private boolean isPin = false;
@ -53,6 +56,23 @@ public final class Signal implements Comparable<Signal> {
return this;
}
/**
* Sets the integer format to create a string
*
* @param format the format
* @return this for chained calls
*/
public Signal setFormat(IntFormat format) {
if (format != null) {
if (format == IntFormat.def && value.getBits() > 1)
this.format = IntFormat.hex;
else
this.format = format;
}
return this;
}
/**
* Gets the number of this pin.
*
@ -96,6 +116,13 @@ public final class Signal implements Comparable<Signal> {
return name;
}
/**
* @return the value in the spscified format
*/
public String getValueString() {
return format.editableFormat(value.getCopy());
}
/**
* Returns true if this signal is a valid signal.
* Valid means there is a name and the value is non null
@ -130,7 +157,8 @@ public final class Signal implements Comparable<Signal> {
* Has to modify the inner state and also has to update the outputs.
*
* @param value the value to set
* @param highZ true is value is in high z state
*/
void set(long value);
void set(long value, boolean highZ);
}
}

View File

@ -77,7 +77,7 @@ abstract class FlipflopBit extends Node implements Element {
public void registerNodes(Model model) {
super.registerNodes(model);
if (isProbe)
model.addSignal(new Signal(label, q, v -> {
model.addSignal(new Signal(label, q, (v, z) -> {
out = v != 0;
q.setBool(out);
qn.setBool(!out);

View File

@ -104,7 +104,7 @@ public class FlipflopD extends Node implements Element {
public void registerNodes(Model model) {
super.registerNodes(model);
if (isProbe)
model.addSignal(new Signal(label, q, v -> {
model.addSignal(new Signal(label, q, (v, z) -> {
value = v;
q.setValue(value);
qn.setValue(~value);

View File

@ -39,6 +39,7 @@ public class In implements Element {
private final ObservableValue output;
private final String label;
private final String pinNumber;
private final IntFormat format;
private Model model;
/**
@ -53,6 +54,7 @@ public class In implements Element {
output = new ObservableValue("out", attributes.get(Keys.BITS), highZ).setPinDescription(DESCRIPTION).setPinNumber(pinNumber);
output.set(value.getValue(), value.isHighZ());
label = attributes.getCleanLabel();
format = attributes.get(Keys.INT_FORMAT);
}
@Override
@ -67,7 +69,9 @@ public class In implements Element {
@Override
public void registerNodes(Model model) {
model.addInput(new Signal(label, output, output::setValue).setPinNumber(pinNumber));
model.addInput(new Signal(label, output, output::set)
.setPinNumber(pinNumber)
.setFormat(format));
this.model = model;
}

View File

@ -60,6 +60,35 @@ public enum IntFormat {
}
}
/**
* Formats the value.
* Creates a string which can be parsed by {@link Bits#decode(String)}
*
* @param inValue the value to format
* @return the formatted value as a string
* @see Bits#decode(String)
*/
public String editableFormat(Value inValue) {
if (inValue.isHighZ())
return "?";
switch (this) {
case dec:
return Long.toString(inValue.getValue());
case decSigned:
return Long.toString(inValue.getValueSigned());
case hex:
return "0x" + toHex(inValue);
case bin:
return "0b" + toBin(inValue);
case ascii:
return "'" + (char) inValue.getValue() + "'";
default:
return inValue.getValueString();
}
}
private static String toHex(Value inValue) {
final int bits = inValue.getBits();
final int numChars = (bits - 1) / 4 + 1;

View File

@ -59,6 +59,7 @@ public class Out implements Element {
private final int[] bits;
private final String label;
private final String pinNumber;
private final IntFormat format;
private ObservableValue value;
/**
@ -70,6 +71,7 @@ public class Out implements Element {
bits = new int[]{attributes.getBits()};
label = attributes.getCleanLabel();
pinNumber = attributes.get(Keys.PINNUMBER);
format = attributes.get(Keys.INT_FORMAT);
}
/**
@ -81,6 +83,7 @@ public class Out implements Element {
this.bits = bits;
label = null;
pinNumber = "";
format = null;
}
@Override
@ -99,7 +102,9 @@ public class Out implements Element {
@Override
public void registerNodes(Model model) {
model.addOutput(new Signal(label, value).setPinNumber(pinNumber));
model.addOutput(new Signal(label, value)
.setPinNumber(pinNumber)
.setFormat(format));
}
private final static class SevenSegTypeDescription extends ElementTypeDescription {

View File

@ -25,6 +25,7 @@ public class Probe implements Element {
.addAttribute(Keys.INT_FORMAT);
private final String label;
private final IntFormat format;
private ObservableValue value;
/**
@ -34,6 +35,7 @@ public class Probe implements Element {
*/
public Probe(ElementAttributes attributes) {
label = attributes.get(Keys.LABEL);
format = attributes.get(Keys.INT_FORMAT);
}
@Override
@ -48,7 +50,7 @@ public class Probe implements Element {
@Override
public void registerNodes(Model model) {
model.addSignal(new Signal(label, value));
model.addSignal(new Signal(label, value).setFormat(format));
}
}

View File

@ -94,7 +94,7 @@ public class Counter extends Node implements Element {
public void registerNodes(Model model) {
super.registerNodes(model);
if (probe)
model.addSignal(new Signal(label, out, v -> {
model.addSignal(new Signal(label, out, (v, z) -> {
counter = v;
boolean o = (counter == maxValue) && enable.getBool();
out.setValue(counter);

View File

@ -78,7 +78,7 @@ public class Register extends Node implements Element {
public void registerNodes(Model model) {
super.registerNodes(model);
if (isProbe)
model.addSignal(new Signal(label, q, v -> {
model.addSignal(new Signal(label, q, (v, z) -> {
value = v;
q.setValue(value);
}));

View File

@ -175,7 +175,7 @@ public class ProbeDialog extends JDialog implements ModelStateObserverTyped {
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) return signals.get(rowIndex).getName();
else return signals.get(rowIndex).getValue().getValueString();
else return signals.get(rowIndex).getValueString();
}
@Override
@ -184,8 +184,13 @@ public class ProbeDialog extends JDialog implements ModelStateObserverTyped {
Signal.Setter s = signals.get(rowIndex).getSetter();
if (s != null)
try {
long value = Bits.decode(aValue.toString());
modelSync.access(() -> s.set(value));
final String str = aValue.toString();
if (str.equals("?") || str.equals("z") || str.equals("Z")) {
modelSync.access(() -> s.set(0, true));
} else {
long value = Bits.decode(str);
modelSync.access(() -> s.set(value, false));
}
circuitComponent.modelHasChanged();
} catch (Bits.NumberFormatException e) {
// do nothing in this case!

View File

@ -77,6 +77,8 @@ public class BitsTest extends TestCase {
assertEquals(0xFFFFFFFFFFFFFFFFL, Bits.decode("0xFFFFFFFFFFFFFFFF"));
assertEquals(0xFFFFFFFFFFFFFFFFL, Bits.decode("FFFFFFFFFFFFFFFF", 0, 16));
assertEquals(42, Bits.decode("'*'"));
}
public void testDecodeInvalid() {