mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-17 08:55:05 -04:00
adds a pseudo random number generator, see #598
This commit is contained in:
parent
b96714d61c
commit
2dab02e0c5
@ -144,7 +144,7 @@ public class SubstituteLibrary implements LibraryInterface {
|
||||
c.getAttributes().set(Keys.IS_GENERIC, false);
|
||||
generify(attr, c);
|
||||
|
||||
return ElementLibrary.createCustomDescription(new File(filename), c, library).isSubstitutedBuiltIn();
|
||||
return ElementLibrary.createCustomDescription(new File(filename), c).isSubstitutedBuiltIn();
|
||||
}
|
||||
|
||||
private void generify(ElementAttributes attr, Circuit circuit) throws IOException {
|
||||
|
97
src/main/java/de/neemann/digital/core/arithmetic/PRNG.java
Normal file
97
src/main/java/de/neemann/digital/core/arithmetic/PRNG.java
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Helmut Neemann.
|
||||
* Use of this source code is governed by the GPL v3 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
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 java.util.Random;
|
||||
|
||||
import static de.neemann.digital.core.element.PinInfo.input;
|
||||
|
||||
/**
|
||||
* Creates a random number using the Java Random class.
|
||||
*/
|
||||
public class PRNG extends Node implements Element {
|
||||
|
||||
/**
|
||||
* The element type description
|
||||
*/
|
||||
public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(PRNG.class,
|
||||
input("S"),
|
||||
input("se"),
|
||||
input("ne"),
|
||||
input("C").setClock())
|
||||
.addAttribute(Keys.ROTATE)
|
||||
.addAttribute(Keys.BITS)
|
||||
.addAttribute(Keys.LABEL);
|
||||
|
||||
private final ObservableValue output;
|
||||
private final int bits;
|
||||
private final long mask;
|
||||
private final Random random;
|
||||
private ObservableValue seedVal;
|
||||
private ObservableValue setVal;
|
||||
private ObservableValue nextVal;
|
||||
private ObservableValue clockVal;
|
||||
private boolean lastClock;
|
||||
private long value;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param attributes the elements attributes
|
||||
*/
|
||||
public PRNG(ElementAttributes attributes) {
|
||||
bits = attributes.get(Keys.BITS);
|
||||
output = new ObservableValue("R", bits).setPinDescription(DESCRIPTION);
|
||||
// Let Java set the initial seed so that different values are generated each simulation,
|
||||
// unless a specific seed is set by the user later on.
|
||||
random = new Random();
|
||||
mask = Bits.mask(bits);
|
||||
value = random.nextLong() & mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readInputs() throws NodeException {
|
||||
boolean clock = clockVal.getBool();
|
||||
|
||||
if (clock && !lastClock) {
|
||||
// First update seed
|
||||
if (setVal.getBool())
|
||||
random.setSeed(seedVal.getValue());
|
||||
|
||||
// Then value. This keeps the component well defined in case both 'set' and 'next' inputs are set.
|
||||
if (nextVal.getBool())
|
||||
value = random.nextLong() & mask;
|
||||
}
|
||||
|
||||
lastClock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeOutputs() throws NodeException {
|
||||
output.setValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputs(ObservableValues inputs) throws NodeException {
|
||||
// Note: could separate bit count for seed input & value output
|
||||
seedVal = inputs.get(0).checkBits(bits, this);
|
||||
setVal = inputs.get(1).checkBits(1, this);
|
||||
nextVal = inputs.get(2).checkBits(1, this);
|
||||
clockVal = inputs.get(3).addObserverToValue(this).checkBits(1, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValues getOutputs() {
|
||||
return output.asList();
|
||||
}
|
||||
|
||||
}
|
@ -89,9 +89,9 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
private final HashSet<String> isProgrammable = new HashSet<>();
|
||||
private final ArrayList<LibraryListener> listeners = new ArrayList<>();
|
||||
private final LibraryNode root;
|
||||
private final ElementLibraryFolder custom;
|
||||
private JarComponentManager jarComponentManager;
|
||||
private ShapeFactory shapeFactory;
|
||||
private ElementLibraryFolder custom;
|
||||
private File rootLibraryPath;
|
||||
private Exception exception;
|
||||
private long lastRescanTime;
|
||||
@ -197,7 +197,8 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
.add(ROM.DESCRIPTION)
|
||||
.add(ROMDualPort.DESCRIPTION)
|
||||
.add(Counter.DESCRIPTION)
|
||||
.add(CounterPreset.DESCRIPTION))
|
||||
.add(CounterPreset.DESCRIPTION)
|
||||
.add(PRNG.DESCRIPTION))
|
||||
.add(new LibraryNode(Lang.get("lib_arithmetic"))
|
||||
.add(Add.DESCRIPTION)
|
||||
.add(Sub.DESCRIPTION)
|
||||
@ -588,7 +589,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
throw new IOException(Lang.get("err_couldNotFindIncludedFile_N0", file));
|
||||
}
|
||||
|
||||
ElementTypeDescriptionCustom description = createCustomDescription(file, circuit, this);
|
||||
ElementTypeDescriptionCustom description = createCustomDescription(file, circuit);
|
||||
description.setShortName(createShortName(file.getName(), circuit.getAttributes().getLabel()));
|
||||
|
||||
String descriptionText = Lang.evalMultilingualContent(circuit.getAttributes().get(Keys.DESCRIPTION));
|
||||
@ -620,11 +621,10 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
*
|
||||
* @param file the file
|
||||
* @param circuit the circuit
|
||||
* @param library the used library
|
||||
* @return the type description
|
||||
* @throws PinException PinException
|
||||
*/
|
||||
public static ElementTypeDescriptionCustom createCustomDescription(File file, Circuit circuit, ElementLibrary library) throws PinException {
|
||||
public static ElementTypeDescriptionCustom createCustomDescription(File file, Circuit circuit) throws PinException {
|
||||
ElementTypeDescriptionCustom d = new ElementTypeDescriptionCustom(file, circuit);
|
||||
d.setElementFactory(attributes -> new CustomElement(d));
|
||||
return d;
|
||||
|
@ -375,7 +375,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
file = new File(name);
|
||||
try {
|
||||
ElementTypeDescriptionCustom description =
|
||||
ElementLibrary.createCustomDescription(file, circuit, library);
|
||||
ElementLibrary.createCustomDescription(file, circuit);
|
||||
description.setShortName(name);
|
||||
description.setDescription(Lang.evalMultilingualContent(circuit.getAttributes().get(Keys.DESCRIPTION)));
|
||||
new ElementHelpDialog(Main.this, description, circuit.getAttributes()).setVisible(true);
|
||||
|
@ -844,6 +844,19 @@
|
||||
<string name="elem_BitCount_pin_in">Die 1-Bits in diesem Datenwort werden gezählt.</string>
|
||||
<string name="elem_BitCount_pin_out">Ausgang mit der Anzahl der gezählten 1-Bits.</string>
|
||||
|
||||
<string name="elem_PRNG">Zufallszahlengenerator</string>
|
||||
<string name="elem_PRNG_tt">Kann verwendet werden um Zufallszahlen zu erzeugen.
|
||||
Beim Starten der Simulation wird der Generator neu initialisiert, so dass bei jedem Start eine neue
|
||||
Pseudozufallszahlenfolge erzeugt wird.
|
||||
Der Generator kann in der laufenden Simulation mit einem definierten SEED-Wert initialisiert werden,
|
||||
um eine definierte Pseudozufallszahlenfolge erzeugen zu lassen.
|
||||
</string>
|
||||
<string name="elem_PRNG_short">PRNG</string>
|
||||
<string name="elem_PRNG_pin_S">Startwert des Generators</string>
|
||||
<string name="elem_PRNG_pin_se">Wenn gesetzt wird der Zufallsszahlengenerator bei der nächsten steigenden Taktflanke mit dem neuen Startwert reinitialisiert.</string>
|
||||
<string name="elem_PRNG_pin_ne">Wenn gesetzt wird bei der nächsten steigenden Taktflanke eine neue Zufallsszahl ausgegeben.</string>
|
||||
<string name="elem_PRNG_pin_C">Der Takteingang.</string>
|
||||
<string name="elem_PRNG_pin_R">Ausgabe der Pseudozufallszahl.</string>
|
||||
|
||||
<!-- Schalter -->
|
||||
|
||||
|
@ -819,6 +819,19 @@
|
||||
<string name="elem_BitCount_pin_in">The input which 1-bits are counted.</string>
|
||||
<string name="elem_BitCount_pin_out">Outputs the number of 1-bits.</string>
|
||||
|
||||
<string name="elem_PRNG">Random Nnumber Generator</string>
|
||||
<string name="elem_PRNG_tt">Can be used to generate random numbers.
|
||||
When the simulation is started, the generator is reinitialized so that a new pseudo-random number
|
||||
sequence is generated at each start.
|
||||
The generator can be initialized in the running simulation with a defined seed value to generate
|
||||
a defined pseudo-random number sequence.
|
||||
</string>
|
||||
<string name="elem_PRNG_short">PRNG</string>
|
||||
<string name="elem_PRNG_pin_S">New seed value of the generator.</string>
|
||||
<string name="elem_PRNG_pin_se">If set, the random number generator is reinitialized with the new seed value at the next rising clock edge.</string>
|
||||
<string name="elem_PRNG_pin_ne">If set, a new random number is output at the next rising clock edge.</string>
|
||||
<string name="elem_PRNG_pin_C">The clock input.</string>
|
||||
<string name="elem_PRNG_pin_R">Output of the pseudorandom number.</string>
|
||||
|
||||
<!-- Switches -->
|
||||
|
||||
|
@ -50,8 +50,8 @@ public class TestExamples extends TestCase {
|
||||
*/
|
||||
public void testTestExamples() throws Exception {
|
||||
File examples = new File(Resources.getRoot(), "/dig/test");
|
||||
assertEquals(198, new FileScanner(this::check).scan(examples));
|
||||
assertEquals(187, testCasesInFiles);
|
||||
assertEquals(199, new FileScanner(this::check).scan(examples));
|
||||
assertEquals(188, testCasesInFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -687,6 +687,16 @@
|
||||
<elementAttributes/>
|
||||
<pos x="820" y="940"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>PRNG</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="420" y="1080"/>
|
||||
</visualElement>
|
||||
</visualElements>
|
||||
<wires>
|
||||
<wire>
|
||||
@ -737,6 +747,10 @@
|
||||
<p1 x="700" y="520"/>
|
||||
<p2 x="800" y="520"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="1160"/>
|
||||
<p2 x="420" y="1160"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="240" y="780"/>
|
||||
<p2 x="260" y="780"/>
|
||||
@ -1053,6 +1067,10 @@
|
||||
<p1 x="220" y="1080"/>
|
||||
<p2 x="240" y="1080"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="380" y="1080"/>
|
||||
<p2 x="420" y="1080"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="240" y="1080"/>
|
||||
<p2 x="260" y="1080"/>
|
||||
@ -1169,6 +1187,10 @@
|
||||
<p1 x="240" y="1100"/>
|
||||
<p2 x="260" y="1100"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="1100"/>
|
||||
<p2 x="420" y="1100"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="600" y="720"/>
|
||||
<p2 x="680" y="720"/>
|
||||
@ -1385,6 +1407,10 @@
|
||||
<p1 x="1160" y="500"/>
|
||||
<p2 x="1200" y="500"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="1140"/>
|
||||
<p2 x="420" y="1140"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="1080" y="760"/>
|
||||
<p2 x="1100" y="760"/>
|
||||
@ -1681,10 +1707,22 @@
|
||||
<p1 x="400" y="960"/>
|
||||
<p2 x="400" y="1020"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="1020"/>
|
||||
<p2 x="400" y="1100"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="580"/>
|
||||
<p2 x="400" y="780"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="1100"/>
|
||||
<p2 x="400" y="1140"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="1140"/>
|
||||
<p2 x="400" y="1160"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="220"/>
|
||||
<p2 x="400" y="260"/>
|
||||
@ -2125,6 +2163,10 @@
|
||||
<p1 x="380" y="820"/>
|
||||
<p2 x="380" y="920"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="380" y="920"/>
|
||||
<p2 x="380" y="1080"/>
|
||||
</wire>
|
||||
</wires>
|
||||
<measurementOrdering/>
|
||||
</circuit>
|
144
src/test/resources/dig/test/prng.dig
Normal file
144
src/test/resources/dig/test/prng.dig
Normal file
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<circuit>
|
||||
<version>1</version>
|
||||
<attributes/>
|
||||
<visualElements>
|
||||
<visualElement>
|
||||
<elementName>PRNG</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="460" y="180"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Clock</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>C</string>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="280" y="260"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Const</elementName>
|
||||
<elementAttributes/>
|
||||
<pos x="440" y="240"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>JK_FF</elementName>
|
||||
<elementAttributes/>
|
||||
<pos x="340" y="180"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Ground</elementName>
|
||||
<elementAttributes/>
|
||||
<pos x="320" y="240"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>VDD</elementName>
|
||||
<elementAttributes/>
|
||||
<pos x="320" y="160"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Const</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="440" y="180"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Out</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>Y</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="560" y="220"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Testcase</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Testdata</string>
|
||||
<testData>
|
||||
<dataString>C Y
|
||||
c 0xd8
|
||||
c 0x92
|
||||
c 0xf0
|
||||
c 0xdd
|
||||
c 0x68
|
||||
c 0x12
|
||||
c 0x7e
|
||||
c 0xe4
|
||||
c 0xfc
|
||||
</dataString>
|
||||
</testData>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="360" y="320"/>
|
||||
</visualElement>
|
||||
</visualElements>
|
||||
<wires>
|
||||
<wire>
|
||||
<p1 x="440" y="240"/>
|
||||
<p2 x="460" y="240"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="280" y="260"/>
|
||||
<p2 x="300" y="260"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="300" y="260"/>
|
||||
<p2 x="460" y="260"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="320" y="180"/>
|
||||
<p2 x="340" y="180"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="440" y="180"/>
|
||||
<p2 x="460" y="180"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="300" y="200"/>
|
||||
<p2 x="340" y="200"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="200"/>
|
||||
<p2 x="460" y="200"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="320" y="220"/>
|
||||
<p2 x="340" y="220"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="520" y="220"/>
|
||||
<p2 x="560" y="220"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="320" y="220"/>
|
||||
<p2 x="320" y="240"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="320" y="160"/>
|
||||
<p2 x="320" y="180"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="300" y="200"/>
|
||||
<p2 x="300" y="260"/>
|
||||
</wire>
|
||||
</wires>
|
||||
<measurementOrdering/>
|
||||
</circuit>
|
Loading…
x
Reference in New Issue
Block a user