mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-08 20:35:39 -04:00
First fully working implementation
This commit is contained in:
parent
00d8a2f845
commit
9c78909bdc
@ -150,7 +150,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, library);
|
||||
}
|
||||
|
||||
private void generify(ElementAttributes attr, Circuit circuit) throws IOException {
|
||||
|
@ -295,12 +295,24 @@ public class ElementAttributes implements HGSMap {
|
||||
return get(k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to the instance specific cache
|
||||
*
|
||||
* @param key key
|
||||
* @param value value
|
||||
*/
|
||||
public void putToCache(String key, Object value) {
|
||||
if (cache == null)
|
||||
cache = new HashMap<>();
|
||||
cache.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a value from the cache
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value
|
||||
*/
|
||||
public Object getFromCache(String key) {
|
||||
if (cache == null)
|
||||
return null;
|
||||
|
@ -831,7 +831,13 @@ public final class Keys {
|
||||
* Used to input statements to generify a circuit.
|
||||
*/
|
||||
public static final Key<String> GENERIC =
|
||||
new Key.LongString("generic").allowGroupEdit();
|
||||
new Key.LongString("generic").setLineNumbers(true).allowGroupEdit();
|
||||
|
||||
/**
|
||||
* Used to input statements to generify a circuit.
|
||||
*/
|
||||
public static final Key<String> GENERICLARGE =
|
||||
new Key.LongString("generic").setLineNumbers(true).setRows(20).allowGroupEdit();
|
||||
|
||||
/**
|
||||
* Circuit is generic
|
||||
|
@ -11,7 +11,6 @@ import de.neemann.digital.draw.graphics.*;
|
||||
import de.neemann.digital.draw.shapes.Shape;
|
||||
import de.neemann.digital.draw.shapes.*;
|
||||
import de.neemann.digital.gui.components.CircuitComponent;
|
||||
import de.neemann.digital.hdl.hgs.Context;
|
||||
import de.neemann.gui.Screen;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -226,6 +226,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
.add(new LibraryNode(Lang.get("lib_misc"))
|
||||
.add(TestCaseElement.DESCRIPTION)
|
||||
.add(GenericInitCode.DESCRIPTION)
|
||||
.add(GenericCode.DESCRIPTION)
|
||||
.add(DummyElement.RECTDESCRIPTION)
|
||||
.add(PowerSupply.DESCRIPTION)
|
||||
.add(BusSplitter.DESCRIPTION)
|
||||
@ -619,6 +620,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
*
|
||||
* @param file the file
|
||||
* @param circuit the circuit
|
||||
* @param library the library
|
||||
* @return the type description
|
||||
* @throws PinException PinException
|
||||
*/
|
||||
|
@ -35,7 +35,6 @@ public final class ElementTypeDescriptionCustom extends ElementTypeDescription {
|
||||
private final LibraryInterface library;
|
||||
private String description;
|
||||
private NetList netList;
|
||||
private boolean isCustom = true;
|
||||
private String declarationDefault;
|
||||
|
||||
/**
|
||||
@ -127,21 +126,6 @@ public final class ElementTypeDescriptionCustom extends ElementTypeDescription {
|
||||
return new ModelCreator(circuit, library, true, new NetList(netList, errorVisualElement), subName, depth, errorVisualElement);
|
||||
}
|
||||
|
||||
public boolean isCustom() {
|
||||
return isCustom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by element substitution to allow to mark custom circuits which replace a built-in
|
||||
* component to be not custom.
|
||||
*
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public ElementTypeDescriptionCustom isSubstitutedBuiltIn() {
|
||||
isCustom = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the generics field default value
|
||||
* @throws NodeException NodeException
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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.draw.library;
|
||||
|
||||
import de.neemann.digital.core.Model;
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.core.ObservableValues;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Allows to a generic init code to a circuit.
|
||||
*/
|
||||
public class GenericCode implements Element {
|
||||
/**
|
||||
* The GenericInitCodeElement description
|
||||
*/
|
||||
public static final ElementTypeDescription DESCRIPTION
|
||||
= new ElementTypeDescription(GenericCode.class)
|
||||
.addAttribute(Keys.GENERICLARGE)
|
||||
.supportsHDL();
|
||||
|
||||
/**
|
||||
* creates a new instance
|
||||
*
|
||||
* @param attributes the attributes
|
||||
*/
|
||||
public GenericCode(ElementAttributes attributes) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputs(ObservableValues inputs) throws NodeException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValues getOutputs() {
|
||||
return ObservableValues.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerNodes(Model model) {
|
||||
}
|
||||
}
|
@ -31,11 +31,13 @@ import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
|
||||
*/
|
||||
public class ResolveGenerics {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ResolveGenerics.class);
|
||||
private static final Context EMPTY_CONTEXT = new Context();
|
||||
|
||||
/**
|
||||
* Key uses to store the args for the generic circuits
|
||||
*/
|
||||
public static final String GEN_ARGS_KEY = "genArgs";
|
||||
private final HashMap<String, Statement> map;
|
||||
private final HashMap<Context, CircuitHolder> circuitMap;
|
||||
private final HashMap<Args, CircuitHolder> circuitMap;
|
||||
private final Circuit circuit;
|
||||
private final LibraryInterface library;
|
||||
|
||||
@ -61,23 +63,57 @@ public class ResolveGenerics {
|
||||
* @throws ElementNotFoundException ElementNotFoundException
|
||||
*/
|
||||
public CircuitHolder resolveCircuit(ElementAttributes attributes) throws NodeException, ElementNotFoundException {
|
||||
Context context = EMPTY_CONTEXT;
|
||||
if (attributes != null)
|
||||
context = (Context) attributes.getFromCache(GEN_ARGS_KEY);
|
||||
Args args;
|
||||
if (attributes == null)
|
||||
args = createArgsFromGenericBlock();
|
||||
else
|
||||
args = createArgsFromParentCircuitEmbedding(attributes);
|
||||
|
||||
CircuitHolder ch = circuitMap.get(context);
|
||||
CircuitHolder ch = circuitMap.get(args);
|
||||
if (ch == null) {
|
||||
ch = innerResolveCircuit(attributes);
|
||||
circuitMap.put(context, ch);
|
||||
ch = innerResolveCircuit(args);
|
||||
circuitMap.put(args, ch);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
public CircuitHolder innerResolveCircuit(ElementAttributes parentAttributes) throws NodeException, ElementNotFoundException {
|
||||
private Args createArgsFromParentCircuitEmbedding(ElementAttributes attributes) throws NodeException {
|
||||
Context context = (Context) attributes.getFromCache(GEN_ARGS_KEY);
|
||||
if (context == null) {
|
||||
String argsCode = attributes.get(Keys.GENERIC);
|
||||
try {
|
||||
Statement s = getStatement(argsCode);
|
||||
context = new Context();
|
||||
s.execute(context);
|
||||
} catch (HGSEvalException | ParserException | IOException e) {
|
||||
final NodeException ex = new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", null, argsCode), e);
|
||||
ex.setOrigin(circuit.getOrigin());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return new Args(context);
|
||||
}
|
||||
|
||||
private Args createArgsFromGenericBlock() throws NodeException {
|
||||
Context context = new Context();
|
||||
List<VisualElement> g = circuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION) && v.getElementAttributes().get(Keys.ENABLED));
|
||||
if (g.size() == 0)
|
||||
throw new NodeException(Lang.get("err_noGenericInitCode"));
|
||||
if (g.size() > 1)
|
||||
throw new NodeException(Lang.get("err_multipleGenericInitCodes"));
|
||||
String argsCode = g.get(0).getElementAttributes().get(Keys.GENERIC);
|
||||
try {
|
||||
getStatement(argsCode).execute(context);
|
||||
} catch (IOException | ParserException | HGSEvalException e) {
|
||||
throw new NodeException(Lang.get("err_inGenericInitCode"), e);
|
||||
}
|
||||
return new Args(context);
|
||||
}
|
||||
|
||||
private CircuitHolder innerResolveCircuit(Args args) throws NodeException, ElementNotFoundException {
|
||||
LOGGER.info("create concrete circuit based on " + circuit.getOrigin());
|
||||
final Circuit c = circuit.createDeepCopy();
|
||||
ArrayList<VisualElement> newComponents = new ArrayList<>();
|
||||
final Args args = createArgs(parentAttributes, c, newComponents);
|
||||
|
||||
for (VisualElement ve : c.getElements()) {
|
||||
ElementAttributes elementAttributes = ve.getElementAttributes();
|
||||
@ -125,40 +161,6 @@ public class ResolveGenerics {
|
||||
}
|
||||
}
|
||||
|
||||
private Args createArgs(ElementAttributes attributes, Circuit circuit, ArrayList<VisualElement> newComponents) throws NodeException {
|
||||
Context context;
|
||||
if (attributes != null) {
|
||||
context = (Context) attributes.getFromCache(GEN_ARGS_KEY);
|
||||
if (context == null) {
|
||||
String argsCode = attributes.get(Keys.GENERIC);
|
||||
try {
|
||||
Statement s = getStatement(argsCode);
|
||||
context = createContext(circuit, newComponents);
|
||||
s.execute(context);
|
||||
} catch (HGSEvalException | ParserException | IOException e) {
|
||||
final NodeException ex = new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", null, argsCode), e);
|
||||
ex.setOrigin(circuit.getOrigin());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context = createContext(circuit, newComponents);
|
||||
List<VisualElement> g = circuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION) && v.getElementAttributes().get(Keys.ENABLED));
|
||||
if (g.size() == 0)
|
||||
throw new NodeException(Lang.get("err_noGenericInitCode"));
|
||||
if (g.size() > 1)
|
||||
throw new NodeException(Lang.get("err_multipleGenericInitCodes"));
|
||||
String argsCode = g.get(0).getElementAttributes().get(Keys.GENERIC);
|
||||
try {
|
||||
getStatement(argsCode).execute(context);
|
||||
} catch (IOException | ParserException | HGSEvalException e) {
|
||||
throw new NodeException(Lang.get("err_inGenericInitCode"), e);
|
||||
}
|
||||
}
|
||||
|
||||
return new Args(context);
|
||||
}
|
||||
|
||||
private Statement getStatement(String code) throws IOException, ParserException {
|
||||
Statement genS = map.get(code);
|
||||
if (genS == null) {
|
||||
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.draw.shapes;
|
||||
|
||||
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.draw.elements.IOState;
|
||||
import de.neemann.digital.draw.elements.Pins;
|
||||
import de.neemann.digital.draw.graphics.Graphic;
|
||||
import de.neemann.digital.draw.graphics.Orientation;
|
||||
import de.neemann.digital.draw.graphics.Style;
|
||||
import de.neemann.digital.draw.graphics.Vector;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Simple text
|
||||
*/
|
||||
public class GenericCodeShape implements Shape {
|
||||
private static final Style STYLE = Style.NORMAL.deriveFontStyle(Style.NORMAL.getFontSize(), true);
|
||||
|
||||
private final ArrayList<String> text;
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param attr attributes
|
||||
* @param inputs the inputs
|
||||
* @param outputs the outputs
|
||||
*/
|
||||
public GenericCodeShape(ElementAttributes attr, PinDescriptions inputs, PinDescriptions outputs) {
|
||||
String gen = attr.get(Keys.GENERIC);
|
||||
text = new ArrayList<>();
|
||||
if (gen.isEmpty())
|
||||
text.add(Lang.get("elem_GenericCode"));
|
||||
else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < gen.length(); i++) {
|
||||
char c = gen.charAt(i);
|
||||
switch (c) {
|
||||
case ' ':
|
||||
sb.append("\u00A0");
|
||||
break;
|
||||
case '_':
|
||||
sb.append("\\_");
|
||||
break;
|
||||
case '^':
|
||||
sb.append("\\^");
|
||||
break;
|
||||
case '\n':
|
||||
text.add(sb.toString());
|
||||
sb.setLength(0);
|
||||
default:
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
if (sb.length() > 0)
|
||||
text.add(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pins getPins() {
|
||||
return new Pins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interactor applyStateMonitor(IOState ioState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic graphic, Style highLight) {
|
||||
Vector pos = new Vector(0, 0);
|
||||
final int dy = (STYLE.getFontSize() * 20) / 16;
|
||||
for (String s : text) {
|
||||
graphic.drawText(pos, s, Orientation.LEFTCENTER, STYLE);
|
||||
pos = pos.add(0, dy);
|
||||
}
|
||||
}
|
||||
}
|
@ -20,10 +20,7 @@ import de.neemann.digital.core.wiring.*;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.elements.Tunnel;
|
||||
import de.neemann.digital.draw.graphics.Style;
|
||||
import de.neemann.digital.draw.library.ElementLibrary;
|
||||
import de.neemann.digital.draw.library.ElementTypeDescriptionCustom;
|
||||
import de.neemann.digital.draw.library.GenericInitCode;
|
||||
import de.neemann.digital.draw.library.JarComponentManager;
|
||||
import de.neemann.digital.draw.library.*;
|
||||
import de.neemann.digital.draw.shapes.custom.CustomShape;
|
||||
import de.neemann.digital.draw.shapes.custom.CustomShapeDescription;
|
||||
import de.neemann.digital.draw.shapes.ieee.IEEEAndShape;
|
||||
@ -163,6 +160,7 @@ public final class ShapeFactory {
|
||||
map.put(DummyElement.RECTDESCRIPTION.getName(), RectShape::new);
|
||||
map.put(TestCaseElement.DESCRIPTION.getName(), TestCaseShape::new);
|
||||
map.put(GenericInitCode.DESCRIPTION.getName(), GenericInitCodeShape::new);
|
||||
map.put(GenericCode.DESCRIPTION.getName(), GenericCodeShape::new);
|
||||
map.put(AsyncSeq.DESCRIPTION.getName(), AsyncClockShape::new);
|
||||
|
||||
map.put(Diode.DESCRIPTION.getName(), DiodeShape::new);
|
||||
|
@ -1427,7 +1427,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
|
||||
|
||||
private ArrayList<Key> getAttributeList(VisualElement ve) throws ElementNotFoundException {
|
||||
ArrayList<Key> list = library.getElementType(ve.getElementName()).getAttributeList();
|
||||
if (getCircuit().getAttributes().get(Keys.IS_GENERIC) && !list.contains(Keys.GENERIC)) {
|
||||
if (getCircuit().getAttributes().get(Keys.IS_GENERIC) && !(list.contains(Keys.GENERIC) || list.contains(Keys.GENERICLARGE))) {
|
||||
list = new ArrayList<>(list);
|
||||
list.add(Keys.GENERIC);
|
||||
}
|
||||
|
@ -959,6 +959,10 @@
|
||||
können.
|
||||
Soll eine generische Schaltung direkt gestartet werden, muss eine solche Komponente vorhanden sein.
|
||||
</string>
|
||||
<string name="elem_GenericCode">Code</string>
|
||||
<string name="elem_GenericCode_tt">Code der ausgeführt wird, wenn eine generische Schaltung konkretisiert wird.
|
||||
Kann z.B. benutzt werden, um einer Schaltung Komponenten oder Leitungen hinzuzufügen.
|
||||
</string>
|
||||
|
||||
<string name="elem_AsyncSeq">Asynchrones Timing</string>
|
||||
<string name="elem_AsyncSeq_tt">Erlaubt die Konfiguration des Timings eines asynchronen Automaten wie z.B einer
|
||||
|
@ -938,6 +938,10 @@
|
||||
<string name="elem_GenericInitCode_tt">Code that is executed to start a generic circuit directly.
|
||||
If a generic circuit is to be started directly, such a component must be present.
|
||||
</string>
|
||||
<string name="elem_GenericCode">Code</string>
|
||||
<string name="elem_GenericCode_tt">Code that is executed when a generic circuit is made concrete.
|
||||
Can be used, for example, to add components or wires to a circuit.
|
||||
</string>
|
||||
|
||||
<string name="elem_AsyncSeq">Asynchronous Timing</string>
|
||||
<string name="elem_AsyncSeq_tt">Allows configuration of the timing of an asynchronous sequential circuit such as a
|
||||
|
@ -12,6 +12,7 @@ import de.neemann.digital.core.wiring.Clock;
|
||||
import de.neemann.digital.core.wiring.Splitter;
|
||||
import de.neemann.digital.draw.elements.Tunnel;
|
||||
import de.neemann.digital.draw.library.ElementLibrary;
|
||||
import de.neemann.digital.draw.library.GenericCode;
|
||||
import de.neemann.digital.draw.library.GenericInitCode;
|
||||
import de.neemann.digital.hdl.vhdl2.entities.VHDLTemplate;
|
||||
import de.neemann.digital.testing.TestCaseElement;
|
||||
@ -45,6 +46,7 @@ public class TestHDLExportFlag extends TestCase {
|
||||
|
||||
implicitSupported.add(TestCaseElement.DESCRIPTION);
|
||||
implicitSupported.add(GenericInitCode.DESCRIPTION);
|
||||
implicitSupported.add(GenericCode.DESCRIPTION);
|
||||
}
|
||||
|
||||
public void testHDLExportFlag() {
|
||||
|
@ -31,15 +31,8 @@ import static de.neemann.digital.draw.library.ResolveGenerics.GEN_ARGS_KEY;
|
||||
* Does not ensure that they work correctly if no tests are present in the circuit!
|
||||
*/
|
||||
public class TestExamples extends TestCase {
|
||||
|
||||
private int testCasesInFiles;
|
||||
|
||||
|
||||
public void testDebug() throws Exception {
|
||||
File f = new File("/home/hneemann/Dokumente/Java/digital/src/main/dig/generic/barrelShifter/TestBarrelShifter.dig");
|
||||
check(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the examples which are distributed
|
||||
*
|
||||
|
@ -697,6 +697,11 @@
|
||||
</elementAttributes>
|
||||
<pos x="420" y="1080"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>GenericCode</elementName>
|
||||
<elementAttributes/>
|
||||
<pos x="120" y="1120"/>
|
||||
</visualElement>
|
||||
</visualElements>
|
||||
<wires>
|
||||
<wire>
|
||||
|
Loading…
x
Reference in New Issue
Block a user