diff --git a/src/main/dig/generic/barrelShifter/barrelShifter.dig b/src/main/dig/generic/barrelShifter/barrelShifter.dig index f7b639d3c..351b7c010 100644 --- a/src/main/dig/generic/barrelShifter/barrelShifter.dig +++ b/src/main/dig/generic/barrelShifter/barrelShifter.dig @@ -81,20 +81,20 @@ generic if (args.direction="right") { - export circuit:="shift-fixed-right-inc.dig"; - } else { - if (args.direction="arith") { - export circuit:="shift-fixed-arith-right-inc.dig"; - } else { - if (args.direction="left") { - export circuit:="shift-fixed-left-inc.dig"; - } else { - panic("only \"left\", \"right\" or \"arith\" is allowed as direction, not \""+args.direction+"\"!"); - } - } - } + export circuit:="shift-fixed-right-inc.dig"; +} else { + if (args.direction="arith") { + export circuit:="shift-fixed-arith-right-inc.dig"; + } else { + if (args.direction="left") { + export circuit:="shift-fixed-left-inc.dig"; + } else { + panic("only \"left\", \"right\" or \"arith\" is allowed as direction, not \""+args.direction+"\"!"); + } + } +} - export shiftBits:=bitsNeededFor(args.dataBits-1); +shiftBits:=bitsNeededFor(args.dataBits-1); diff --git a/src/main/dig/generic/barrelShifter/shift-inc.dig b/src/main/dig/generic/barrelShifter/shift-inc.dig index a96a8b2b0..be976891f 100644 --- a/src/main/dig/generic/barrelShifter/shift-inc.dig +++ b/src/main/dig/generic/barrelShifter/shift-inc.dig @@ -13,7 +13,7 @@ generic - export shift := 1<<(args.shiftBits-1); + shift := 1<<(args.shiftBits-1); setCircuit(args.circuit); @@ -87,8 +87,8 @@ setCircuit(args.circuit); generic if (args.shiftBits=2) { - export shift := 1; - setCircuit(args.circuit); + export shift := 1; + setCircuit(args.circuit); } else { export shiftBits := args.shiftBits-1; } diff --git a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java index ffaba3fcb..d8b4da9ca 100644 --- a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java +++ b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java @@ -12,10 +12,12 @@ import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.hdl.hgs.function.Function; +import de.neemann.digital.hdl.hgs.function.InnerFunction; import de.neemann.digital.lang.Lang; import java.io.IOException; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -25,6 +27,7 @@ import java.util.Objects; public class ResolveGenerics { private final HashMap map; + private LibraryInterface library; /** * Creates a new instance @@ -44,6 +47,7 @@ public class ResolveGenerics { * @throws ElementNotFoundException ElementNotFoundException */ public CircuitHolder resolveCircuit(VisualElement visualElement, Circuit circuit, LibraryInterface library) throws NodeException, ElementNotFoundException { + this.library = library; final Args args = createArgs(visualElement, circuit); Circuit c = circuit.createDeepCopy(); @@ -53,18 +57,17 @@ public class ResolveGenerics { if (!gen.isEmpty()) { boolean isCustom = library.getElementType(ve.getElementName(), ve.getElementAttributes()).isCustom(); Statement genS = getStatement(gen); + Context mod = new Context(); if (isCustom) { - Context mod = new Context() - .declareVar("args", args) + mod.declareVar("args", args) .declareFunc("setCircuit", new SetCircuitFunc(ve)); genS.execute(mod); - ve.setGenericArgs(mod); } else { - Context mod = new Context() - .declareVar("args", args) + mod.declareVar("args", args) .declareVar("this", new SubstituteLibrary.AllowSetAttributes(ve.getElementAttributes())); genS.execute(mod); } + ve.setGenericArgs(mod); } } catch (HGSEvalException | ParserException | IOException e) { final NodeException ex = new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", ve, gen), e); @@ -158,7 +161,7 @@ public class ResolveGenerics { /** * Holds the circuit and the args that created that circuit. */ - public static final class CircuitHolder { + public final class CircuitHolder { private final Circuit circuit; private final Args args; @@ -180,6 +183,70 @@ public class ResolveGenerics { public Args getArgs() { return args; } + + /** + * Converts a circuit that is only suitable for creating a model + * to a circuit that can also be edited and saved. + * + * @return this for chained calls + */ + public CircuitHolder cleanupConcreteCircuit() { + for (VisualElement gic : circuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION))) + circuit.delete(gic); + for (VisualElement v : circuit.getElements()) { + try { + boolean isCustom = library.getElementType(v.getElementName(), v.getElementAttributes()).isCustom(); + if (isCustom) + v.getElementAttributes().set(Keys.GENERIC, createGenericCode(v.getGenericArgs())); + else + v.getElementAttributes().set(Keys.GENERIC, ""); + } catch (ElementNotFoundException e) { + // can not happen + e.printStackTrace(); + } + v.setGenericArgs(null); + } + + circuit.getAttributes().set(Keys.IS_GENERIC, false); + + return this; + } + } + + private static String createGenericCode(Context args) { + StringBuilder sb = new StringBuilder(); + HashSet contentSet = new HashSet<>(); + addVal(sb, "", args, contentSet); + return sb.toString(); + } + + private static void addVal(StringBuilder sb, String key, Object val, HashSet contentSet) { + if (contentSet.contains(key)) + return; + + if (val instanceof InnerFunction) + return; + + if (val instanceof Context) { + Context c = (Context) val; + for (String k : c.getKeySet()) { + Object v = c.hgsMapGet(k); + if (!(v instanceof Args)) + addVal(sb, k, v, contentSet); + } + for (String k : c.getKeySet()) { + Object v = c.hgsMapGet(k); + if (v instanceof Args) + addVal(sb, k, ((Args) v).args, contentSet); + } + return; + } + + contentSet.add(key); + if (val instanceof String) + sb.append(key).append(":=\"").append(val).append("\";\n"); + else + sb.append(key).append(":=").append(val).append(";\n"); } private static final class SetCircuitFunc extends Function { diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index b138f6dc1..28515e558 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -1158,14 +1158,15 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib try { attributeDialog.fireOk(); ElementAttributes modified = attributeDialog.getModifiedAttributes(); - if (modified != null && !isLocked()) { + if (modified != null && !isLocked() && !modified.equals(element.getElementAttributes())) { Modification mod = new ModifyAttributes(element, modified); modify(checkNetRename(element, modified, mod)); } - Circuit concreteCircuit = new ResolveGenerics().resolveCircuit(element, getCircuit(), library).getCircuit(); - for (VisualElement gic : concreteCircuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION))) - concreteCircuit.delete(gic); - concreteCircuit.getAttributes().set(Keys.IS_GENERIC, false); + + Circuit concreteCircuit = new ResolveGenerics() + .resolveCircuit(element, getCircuit(), library) + .cleanupConcreteCircuit() + .getCircuit(); new Main.MainBuilder() .setParent(parent) diff --git a/src/main/java/de/neemann/digital/hdl/hgs/Context.java b/src/main/java/de/neemann/digital/hdl/hgs/Context.java index e44cf1b57..a563c0371 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/Context.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/Context.java @@ -281,6 +281,13 @@ public class Context implements HGSMap { return map.get(key); } + /** + * @return the set of all contained values + */ + public HashSet getKeySet() { + return new HashSet<>(map.keySet()); + } + private static final class FunctionPrint extends InnerFunction { private FunctionPrint() { super(-1); diff --git a/src/main/java/de/neemann/digital/hdl/hgs/Parser.java b/src/main/java/de/neemann/digital/hdl/hgs/Parser.java index 9c0896369..2c24b4f84 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/Parser.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/Parser.java @@ -637,14 +637,14 @@ public class Parser { } } - private static class StructLiteral implements Expression { + private static final class StructLiteral implements Expression { private final HashMap map; private StructLiteral() { map = new HashMap<>(); } - public void add(String key, Expression exp) { + private void add(String key, Expression exp) { map.put(key, exp); }