mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-19 01:44:44 -04:00
adds a bit extender, see #76
This commit is contained in:
parent
4053826889
commit
d12fb1dfed
@ -22,10 +22,12 @@ public class Observable {
|
||||
* Adds an observer to this observable.
|
||||
*
|
||||
* @param observer the observer to add
|
||||
* @return observer the observer to add
|
||||
*/
|
||||
public void addObserver(Observer observer) {
|
||||
public Observer addObserver(Observer observer) {
|
||||
if (observer != null)
|
||||
observers.add(observer);
|
||||
return observer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,68 @@
|
||||
package de.neemann.digital.core.arithmetic;
|
||||
|
||||
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;
|
||||
import de.neemann.digital.core.element.Keys;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import static de.neemann.digital.core.element.PinInfo.input;
|
||||
|
||||
/**
|
||||
* Sign extension component
|
||||
*/
|
||||
public class BitExtender implements Element {
|
||||
|
||||
/**
|
||||
* Description of the sign extend component.
|
||||
*/
|
||||
public static final ElementTypeDescription DESCRIPTION
|
||||
= new ElementTypeDescription(BitExtender.class, input("in"))
|
||||
.addAttribute(Keys.ROTATE)
|
||||
.addAttribute(Keys.LABEL)
|
||||
.addAttribute(Keys.OUTPUT_BITS);
|
||||
|
||||
private final ObservableValue out;
|
||||
private final int outBits;
|
||||
|
||||
/**
|
||||
* creates a new instance
|
||||
*
|
||||
* @param attr the components attributes
|
||||
*/
|
||||
public BitExtender(ElementAttributes attr) {
|
||||
outBits = attr.get(Keys.OUTPUT_BITS);
|
||||
out = new ObservableValue("out", outBits).setPinDescription(DESCRIPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputs(ObservableValues inputs) throws NodeException {
|
||||
final ObservableValue in = inputs.get(0);
|
||||
final int inBits = in.getBits();
|
||||
if (inBits >= outBits)
|
||||
throw new NodeException(Lang.get("err_notMoreOutBitsThanInBits"));
|
||||
|
||||
final int signMask = 1 << (inBits - 1);
|
||||
final int extendMask = ~((1 << inBits) - 1);
|
||||
|
||||
in.addObserver(() -> {
|
||||
long inValue = in.getValue();
|
||||
if ((inValue & signMask) == 0)
|
||||
out.setValue(inValue);
|
||||
else
|
||||
out.setValue(inValue | extendMask);
|
||||
}).hasChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValues getOutputs() throws PinException {
|
||||
return out.asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerNodes(Model model) {
|
||||
// has no nodes! Is just wiring
|
||||
}
|
||||
}
|
@ -31,6 +31,12 @@ public final class Keys {
|
||||
public static final Key.KeyBits BITS
|
||||
= new Key.KeyBits("Bits", 1);
|
||||
|
||||
/**
|
||||
* output bits of sign extender
|
||||
*/
|
||||
public static final Key.KeyBits OUTPUT_BITS
|
||||
= new Key.KeyBits("outputBits", 16);
|
||||
|
||||
/**
|
||||
* number of inputs in simple gates like And and Or
|
||||
*/
|
||||
|
@ -156,6 +156,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
.add(BarrelShifter.DESCRIPTION)
|
||||
.add(Comparator.DESCRIPTION)
|
||||
.add(Neg.DESCRIPTION)
|
||||
.add(BitExtender.DESCRIPTION)
|
||||
.add(BitCount.DESCRIPTION))
|
||||
.add(new LibraryNode(Lang.get("lib_switching"))
|
||||
//.add(Diode.DESCRIPTION) // see class DiodeTest for further information
|
||||
|
@ -476,6 +476,13 @@
|
||||
<string name="elem_Neg_pin_in">Eingang des Datenworts, welches im 2-er Komplement negiert werden soll.</string>
|
||||
<string name="elem_Neg_pin_out">Gibt das Ergebnis der Negation im 2-er Komplement zurück.</string>
|
||||
<string name="elem_Neg_tt">Ein Baustein für die Negation von Datenworten im 2-er Komplement.</string>
|
||||
<string name="elem_BitExtender">Biterweiterung</string>
|
||||
<string name="elem_BitExtender_tt">Erweitert die Bitanzahl eines vorzeichenbehafteten Eingangswertes unter
|
||||
Erhalt des Vorzeichens.</string>
|
||||
<string name="elem_BitExtender_pin_in">Einganswert.
|
||||
Die Eingangsbitzahl muss kleiner sein als die Ausgangsbitzahl!</string>
|
||||
<string name="elem_BitExtender_pin_out">Vorzeichenrichtig erweiterter Eingangswert.
|
||||
Die Eingangsbitzahl muss kleiner sein als die Ausgangsbitzahl!</string>
|
||||
<string name="elem_BitCount">Bitzähler</string>
|
||||
<string name="elem_BitCount_tt">Gibt die Anzahl der 1-Bits im Eingangswert aus.</string>
|
||||
<string name="elem_BitCount_pin_in">Die 1-Bits in diesem Datenwort werden gezählt.</string>
|
||||
@ -717,6 +724,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="err_noMainFoundInManifest">Das Manifest enthält keinen Main-Class-Eintrag!</string>
|
||||
<string name="err_mainClass_N_NotFound">Die Klasse {0} wurde nicht gefunden!</string>
|
||||
<string name="err_couldNotInitializeMainClass_N">Es konnte keine Instanz der Klasse {0} erzeugt werden!</string>
|
||||
<string name="err_notMoreOutBitsThanInBits">Es muss mehr Eingangsbits als Ausgangsbits geben!</string>
|
||||
|
||||
<string name="key_AddrBits">Adress-Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
|
||||
<string name="key_AddrBits_tt">Anzahl der Adress-Bits die verwendet werden.</string>
|
||||
@ -896,6 +904,8 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="key_showWireBits">Zeigt die Anzahl der Leitungen auf einem Bus</string>
|
||||
<string name="key_showWireBits_tt">Zeigt die Anzahl der Leitungen eines Bus an. ACHTUNG: Dieser Wert wird nur beim
|
||||
Start der Simulation aktualisiert.</string>
|
||||
<string name="key_outputBits">Anzahl Ausgangsbits</string><!-- BitExtender -->
|
||||
<string name="key_outputBits_tt">Die Anzahl der Ausgangsbits muss größer sein als die Anzahl der Eingangsbits.</string>
|
||||
|
||||
<string name="mod_insertWire">Leitung eingefügt.</string>
|
||||
<string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string>
|
||||
|
@ -480,6 +480,12 @@
|
||||
<string name="elem_Neg_tt">Negation in the 2th complement</string>
|
||||
<string name="elem_Neg_pin_in">Input of the data word to be negated in 2th complement</string>
|
||||
<string name="elem_Neg_pin_out">Returns the result of the negation in 2th complement.</string>
|
||||
<string name="elem_BitExtender">SignExtend</string>
|
||||
<string name="elem_BitExtender_tt">Increases the bit width of a signed value keeping the values sign.</string>
|
||||
<string name="elem_BitExtender_pin_in">Input value.
|
||||
The input bit width must be smaller than the output bit width!</string>
|
||||
<string name="elem_BitExtender_pin_out">Extended input value.
|
||||
The input bit width must be smaller than the output bit width!</string>
|
||||
<string name="elem_BitCount">Bit counter</string>
|
||||
<string name="elem_BitCount_tt">Returns the number of 1-bits in the input value.</string>
|
||||
<string name="elem_BitCount_pin_in">The input which 1-bits are counted.</string>
|
||||
@ -715,6 +721,7 @@ The names of the variables may not be unique.</string>
|
||||
<string name="err_noMainFoundInManifest">The manifest does not contain a Main-Class entry!</string>
|
||||
<string name="err_mainClass_N_NotFound">Could not find the class {0}!</string>
|
||||
<string name="err_couldNotInitializeMainClass_N">Could not create an instance of the class {0}!</string>
|
||||
<string name="err_notMoreOutBitsThanInBits">There must be more input bits than output bits!</string>
|
||||
|
||||
<string name="key_AddrBits">Address Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
|
||||
<string name="key_AddrBits_tt">Number of address bits used.</string>
|
||||
@ -890,6 +897,8 @@ The names of the variables may not be unique.</string>
|
||||
<string name="key_jarPath_tt">A jar file containing additional components implemented in java.</string>
|
||||
<string name="key_showWireBits">Shows the number of wires on a bus.</string>
|
||||
<string name="key_showWireBits_tt">CAUTION: The value is only updated when the simulation starts.</string>
|
||||
<string name="key_outputBits">Output Bit Width</string><!-- BitExtender -->
|
||||
<string name="key_outputBits_tt">The number of output bits must be greater than the number of input bits.</string>
|
||||
|
||||
<string name="mod_insertWire">Inserted wire.</string>
|
||||
<string name="mod_insertCopied">Insert from clipboard.</string>
|
||||
|
@ -0,0 +1,60 @@
|
||||
package de.neemann.digital.core.arithmetic;
|
||||
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.core.ObservableValue;
|
||||
import de.neemann.digital.core.element.ElementAttributes;
|
||||
import de.neemann.digital.core.element.Keys;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class BitExtenderTest extends TestCase {
|
||||
|
||||
public void testSignExtend() throws Exception {
|
||||
ObservableValue in = new ObservableValue("in", 4);
|
||||
|
||||
BitExtender bitExtender = new BitExtender(new ElementAttributes().set(Keys.OUTPUT_BITS, 8));
|
||||
bitExtender.setInputs(in.asList());
|
||||
assertEquals(1, bitExtender.getOutputs().size());
|
||||
ObservableValue out = bitExtender.getOutputs().get(0);
|
||||
|
||||
check(in, out, 0, 0);
|
||||
check(in, out, 1, 1);
|
||||
check(in, out, 7, 7);
|
||||
check(in, out, 8, -8);
|
||||
check(in, out, 9, -7);
|
||||
check(in, out, -1, -1);
|
||||
check(in, out, -2, -2);
|
||||
}
|
||||
|
||||
public void testSignExtendInit() throws Exception {
|
||||
ObservableValue in = new ObservableValue("in", 4).setValue(1);
|
||||
|
||||
BitExtender bitExtender = new BitExtender(new ElementAttributes().set(Keys.OUTPUT_BITS, 8));
|
||||
bitExtender.setInputs(in.asList());
|
||||
|
||||
assertEquals(1, bitExtender.getOutputs().get(0).getValue());
|
||||
}
|
||||
|
||||
|
||||
private void check(ObservableValue in, ObservableValue out, int inVal, int outVal) {
|
||||
in.setValue(inVal);
|
||||
assertEquals(outVal, (byte) out.getValue());
|
||||
}
|
||||
|
||||
public void testSignExtendError() throws Exception {
|
||||
try {
|
||||
ObservableValue in = new ObservableValue("in", 4);
|
||||
new BitExtender(new ElementAttributes().set(Keys.OUTPUT_BITS, 4)).setInputs(in.asList());
|
||||
fail();
|
||||
} catch (NodeException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testSignExtendError2() throws Exception {
|
||||
try {
|
||||
ObservableValue in = new ObservableValue("in", 5);
|
||||
new BitExtender(new ElementAttributes().set(Keys.OUTPUT_BITS, 4)).setInputs(in.asList());
|
||||
fail();
|
||||
} catch (NodeException e) {
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user