mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-15 07:48:29 -04:00
splitter is working completely
This commit is contained in:
parent
1c7b0a0f9d
commit
ccc588735c
@ -104,4 +104,7 @@ public class ObservableValue extends Value {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int observerCount() {
|
||||||
|
return observers.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,18 +56,18 @@ public class Splitter implements Element {
|
|||||||
Port inPort = inPorts.getPort(i);
|
Port inPort = inPorts.getPort(i);
|
||||||
if (inPort.getBits() != inputs[i].getBits())
|
if (inPort.getBits() != inputs[i].getBits())
|
||||||
throw new BitsException("splitterBitsMismatch", inputs[i]);
|
throw new BitsException("splitterBitsMismatch", inputs[i]);
|
||||||
registerObserversFor(inPort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Port out : outPorts)
|
||||||
|
fillOutput(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerObserversFor(Port in) throws NodeException {
|
private void fillOutput(Port out) throws NodeException {
|
||||||
Observer observer = outPorts.getSingleTargetObserver(in, inputs, outputs);
|
for (Port in : inPorts) {
|
||||||
if (observer != null) {
|
if (in.getPos() + in.getBits() <= out.getPos() || out.getPos() + out.getBits() <= in.getPos())
|
||||||
inputs[in.number].addObserver(observer);
|
continue; // this input is not needed to fill out!!!
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Port out : outPorts) {
|
// out is filled completely by this single input value!
|
||||||
if (out.getPos() >= in.getPos() &&
|
if (out.getPos() >= in.getPos() &&
|
||||||
out.getPos() + out.getBits() <= in.getPos() + in.getBits()) {
|
out.getPos() + out.getBits() <= in.getPos() + in.getBits()) {
|
||||||
|
|
||||||
@ -80,7 +80,61 @@ public class Splitter implements Element {
|
|||||||
outValue.setValue(inValue.getValue() >> bitPos);
|
outValue.setValue(inValue.getValue() >> bitPos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
break; // done!! out is completely filled!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// complete in value needs to be copied to a part of the output
|
||||||
|
if (out.getPos() <= in.getPos() && in.getPos() + in.getBits() <= out.getPos() + out.getBits()) {
|
||||||
|
final int bitPos = in.getPos() - out.getPos();
|
||||||
|
final long mask = ~(((1L << in.bits) - 1) << bitPos);
|
||||||
|
final ObservableValue inValue = inputs[in.number];
|
||||||
|
final ObservableValue outValue = outputs[out.number];
|
||||||
|
inputs[in.number].addObserver(new Observer() {
|
||||||
|
@Override
|
||||||
|
public void hasChanged() {
|
||||||
|
long in = inValue.getValue();
|
||||||
|
long out = outValue.getValue();
|
||||||
|
outValue.setValue((out & mask) | (in << bitPos));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
continue; // done with this input, its completely copied to the output!
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this point is reached, a part of the input needs to be copied to a part of the output!
|
||||||
|
|
||||||
|
// upper part of input needs to be copied to the lower part of the output
|
||||||
|
if (in.getPos() < out.getPos()) {
|
||||||
|
final int bitsToCopy = in.getPos() + in.getBits() - out.getPos();
|
||||||
|
final long mask = ~((1L << bitsToCopy) - 1);
|
||||||
|
final int shift = out.getPos() - in.getPos();
|
||||||
|
final ObservableValue inValue = inputs[in.number];
|
||||||
|
final ObservableValue outValue = outputs[out.number];
|
||||||
|
inputs[in.number].addObserver(new Observer() {
|
||||||
|
@Override
|
||||||
|
public void hasChanged() {
|
||||||
|
long in = inValue.getValue();
|
||||||
|
long out = outValue.getValue();
|
||||||
|
outValue.setValue((out & mask) | (in >> shift));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lower part of input needs to be copied to the upper part of the output
|
||||||
|
final int bitsToCopy = out.getPos() + out.getBits() - in.getPos();
|
||||||
|
final int shift = in.getPos() - out.getPos();
|
||||||
|
final long mask = ~(((1L << bitsToCopy) - 1) << shift);
|
||||||
|
final ObservableValue inValue = inputs[in.number];
|
||||||
|
final ObservableValue outValue = outputs[out.number];
|
||||||
|
inputs[in.number].addObserver(new Observer() {
|
||||||
|
@Override
|
||||||
|
public void hasChanged() {
|
||||||
|
long in = inValue.getValue();
|
||||||
|
long out = outValue.getValue();
|
||||||
|
outValue.setValue((out & mask) | (in << shift));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,36 +192,6 @@ public class Splitter implements Element {
|
|||||||
return ports.get(i);
|
return ports.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if there is a single out target port for the input port
|
|
||||||
*
|
|
||||||
* @param inPort
|
|
||||||
* @param inputs
|
|
||||||
* @param outputs
|
|
||||||
*/
|
|
||||||
public Observer getSingleTargetObserver(Port inPort, ObservableValue[] inputs, ObservableValue[] outputs) {
|
|
||||||
int pos = inPort.getPos();
|
|
||||||
int bits = inPort.getBits();
|
|
||||||
|
|
||||||
for (Port outPort : ports) {
|
|
||||||
if (outPort.getPos() <= pos && pos + bits <= outPort.getPos() + outPort.getBits()) {
|
|
||||||
final int bitPos = pos - outPort.getPos();
|
|
||||||
final int mask = ~(((1 << inPort.bits) - 1) << bitPos);
|
|
||||||
final ObservableValue inValue = inputs[inPort.number];
|
|
||||||
final ObservableValue outValue = outputs[outPort.number];
|
|
||||||
return new Observer() {
|
|
||||||
@Override
|
|
||||||
public void hasChanged() {
|
|
||||||
long in = inValue.getValue();
|
|
||||||
long out = outValue.getValue();
|
|
||||||
outValue.setValue((out & mask) | (in << bitPos));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Port> iterator() {
|
public Iterator<Port> iterator() {
|
||||||
return ports.iterator();
|
return ports.iterator();
|
||||||
|
@ -215,6 +215,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
|
|||||||
model.init();
|
model.init();
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
new ErrorMessage("error creating model").addCause(e1).show(Main.this);
|
new ErrorMessage("error creating model").addCause(e1).show(Main.this);
|
||||||
|
circuitComponent.setModeAndReset(CircuitComponent.Mode.part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ public class SplitterTest1 extends TestCase {
|
|||||||
.set(AttributeKey.OutputSplit, "4"));
|
.set(AttributeKey.OutputSplit, "4"));
|
||||||
|
|
||||||
splitter.setInputs(a, b, c, d);
|
splitter.setInputs(a, b, c, d);
|
||||||
|
assertEquals(1, a.observerCount());
|
||||||
|
assertEquals(1, b.observerCount());
|
||||||
|
assertEquals(1, c.observerCount());
|
||||||
|
assertEquals(1, d.observerCount());
|
||||||
|
|
||||||
ObservableValue[] outputs = splitter.getOutputs();
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
assertEquals(1, outputs.length);
|
assertEquals(1, outputs.length);
|
||||||
@ -50,6 +54,10 @@ public class SplitterTest1 extends TestCase {
|
|||||||
.set(AttributeKey.OutputSplit, "16"));
|
.set(AttributeKey.OutputSplit, "16"));
|
||||||
|
|
||||||
splitter.setInputs(a, b, c, d);
|
splitter.setInputs(a, b, c, d);
|
||||||
|
assertEquals(1, a.observerCount());
|
||||||
|
assertEquals(1, b.observerCount());
|
||||||
|
assertEquals(1, c.observerCount());
|
||||||
|
assertEquals(1, d.observerCount());
|
||||||
|
|
||||||
ObservableValue[] outputs = splitter.getOutputs();
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
assertEquals(1, outputs.length);
|
assertEquals(1, outputs.length);
|
||||||
@ -77,6 +85,10 @@ public class SplitterTest1 extends TestCase {
|
|||||||
.set(AttributeKey.OutputSplit, "8,8"));
|
.set(AttributeKey.OutputSplit, "8,8"));
|
||||||
|
|
||||||
splitter.setInputs(a, b, c, d);
|
splitter.setInputs(a, b, c, d);
|
||||||
|
assertEquals(1, a.observerCount());
|
||||||
|
assertEquals(1, b.observerCount());
|
||||||
|
assertEquals(1, c.observerCount());
|
||||||
|
assertEquals(1, d.observerCount());
|
||||||
|
|
||||||
ObservableValue[] outputs = splitter.getOutputs();
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
assertEquals(2, outputs.length);
|
assertEquals(2, outputs.length);
|
||||||
|
@ -19,6 +19,7 @@ public class SplitterTest2 extends TestCase {
|
|||||||
.set(AttributeKey.OutputSplit, "1,1,1,1"));
|
.set(AttributeKey.OutputSplit, "1,1,1,1"));
|
||||||
|
|
||||||
splitter.setInputs(a);
|
splitter.setInputs(a);
|
||||||
|
assertEquals(4, a.observerCount());
|
||||||
|
|
||||||
ObservableValue[] outputs = splitter.getOutputs();
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
assertEquals(4, outputs.length);
|
assertEquals(4, outputs.length);
|
||||||
@ -40,6 +41,7 @@ public class SplitterTest2 extends TestCase {
|
|||||||
.set(AttributeKey.OutputSplit, "4,4,4,4"));
|
.set(AttributeKey.OutputSplit, "4,4,4,4"));
|
||||||
|
|
||||||
splitter.setInputs(a);
|
splitter.setInputs(a);
|
||||||
|
assertEquals(4, a.observerCount());
|
||||||
|
|
||||||
ObservableValue[] outputs = splitter.getOutputs();
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
assertEquals(4, outputs.length);
|
assertEquals(4, outputs.length);
|
||||||
@ -65,6 +67,8 @@ public class SplitterTest2 extends TestCase {
|
|||||||
.set(AttributeKey.OutputSplit, "4,4,4,4"));
|
.set(AttributeKey.OutputSplit, "4,4,4,4"));
|
||||||
|
|
||||||
splitter.setInputs(a, b);
|
splitter.setInputs(a, b);
|
||||||
|
assertEquals(2, a.observerCount());
|
||||||
|
assertEquals(2, b.observerCount());
|
||||||
|
|
||||||
ObservableValue[] outputs = splitter.getOutputs();
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
assertEquals(4, outputs.length);
|
assertEquals(4, outputs.length);
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package de.neemann.digital.core.wiring;
|
||||||
|
|
||||||
|
import de.neemann.digital.TestExecuter;
|
||||||
|
import de.neemann.digital.core.ObservableValue;
|
||||||
|
import de.neemann.digital.core.element.AttributeKey;
|
||||||
|
import de.neemann.digital.core.element.ElementAttributes;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hneemann
|
||||||
|
*/
|
||||||
|
public class SplitterTestMix extends TestCase {
|
||||||
|
|
||||||
|
public void test1() throws Exception {
|
||||||
|
ObservableValue a = new ObservableValue("a", 8);
|
||||||
|
ObservableValue b = new ObservableValue("b", 8);
|
||||||
|
|
||||||
|
Splitter splitter = new Splitter(new ElementAttributes()
|
||||||
|
.set(AttributeKey.InputSplit, "8,8")
|
||||||
|
.set(AttributeKey.OutputSplit, "4,12"));
|
||||||
|
|
||||||
|
splitter.setInputs(a, b);
|
||||||
|
assertEquals(2, a.observerCount());
|
||||||
|
assertEquals(1, b.observerCount());
|
||||||
|
|
||||||
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
|
assertEquals(2, outputs.length);
|
||||||
|
|
||||||
|
TestExecuter sc = new TestExecuter().setInputs(a, b).setOutputsOf(splitter);
|
||||||
|
sc.check(0x00, 0x00, 0x0, 0x000);
|
||||||
|
|
||||||
|
sc.check(0x01, 0x00, 0x1, 0x000);
|
||||||
|
sc.check(0x10, 0x00, 0x0, 0x001);
|
||||||
|
sc.check(0x00, 0x01, 0x0, 0x010);
|
||||||
|
sc.check(0x00, 0x10, 0x0, 0x100);
|
||||||
|
|
||||||
|
sc.check(0x0f, 0x00, 0xf, 0x000);
|
||||||
|
sc.check(0xf0, 0x00, 0x0, 0x00f);
|
||||||
|
sc.check(0x00, 0x0f, 0x0, 0x0f0);
|
||||||
|
sc.check(0x00, 0xf0, 0x0, 0xf00);
|
||||||
|
|
||||||
|
sc.check(0xc0, 0xab, 0x0, 0xabc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test2() throws Exception {
|
||||||
|
ObservableValue a = new ObservableValue("a", 8);
|
||||||
|
ObservableValue b = new ObservableValue("b", 8);
|
||||||
|
|
||||||
|
Splitter splitter = new Splitter(new ElementAttributes()
|
||||||
|
.set(AttributeKey.InputSplit, "8,8")
|
||||||
|
.set(AttributeKey.OutputSplit, "12,4"));
|
||||||
|
|
||||||
|
splitter.setInputs(a, b);
|
||||||
|
assertEquals(1, a.observerCount());
|
||||||
|
assertEquals(2, b.observerCount());
|
||||||
|
|
||||||
|
ObservableValue[] outputs = splitter.getOutputs();
|
||||||
|
assertEquals(2, outputs.length);
|
||||||
|
|
||||||
|
TestExecuter sc = new TestExecuter().setInputs(a, b).setOutputsOf(splitter);
|
||||||
|
sc.check(0x00, 0x00, 0x000, 0x0);
|
||||||
|
|
||||||
|
sc.check(0x01, 0x00, 0x001, 0x0);
|
||||||
|
sc.check(0x10, 0x00, 0x010, 0x0);
|
||||||
|
sc.check(0x00, 0x01, 0x100, 0x0);
|
||||||
|
sc.check(0x00, 0x10, 0x000, 0x1);
|
||||||
|
|
||||||
|
sc.check(0x0f, 0x00, 0x00f, 0x0);
|
||||||
|
sc.check(0xf0, 0x00, 0x0f0, 0x0);
|
||||||
|
sc.check(0x00, 0x0f, 0xf00, 0x0);
|
||||||
|
sc.check(0x00, 0xf0, 0x000, 0xf);
|
||||||
|
|
||||||
|
sc.check(0xbc, 0xda, 0xabc, 0xd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user