diff --git a/src/main/java/de/neemann/digital/draw/library/ElementTypeDescriptionCustom.java b/src/main/java/de/neemann/digital/draw/library/ElementTypeDescriptionCustom.java index 786ea641b..bdd251c33 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementTypeDescriptionCustom.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementTypeDescriptionCustom.java @@ -18,11 +18,15 @@ import de.neemann.digital.draw.model.ModelCreator; import de.neemann.digital.draw.model.NetList; import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.hdl.hgs.function.Function; +import de.neemann.digital.hdl.hgs.refs.Reference; +import de.neemann.digital.hdl.hgs.refs.ReferenceToStruct; +import de.neemann.digital.hdl.hgs.refs.ReferenceToVar; import de.neemann.digital.lang.Lang; import java.io.File; import java.io.IOException; import java.util.HashMap; +import java.util.TreeSet; /** * The description of a nested element. @@ -36,6 +40,7 @@ public final class ElementTypeDescriptionCustom extends ElementTypeDescription { private String description; private NetList netList; private boolean isCustom = true; + private String declarationDefault; /** * Creates a new element @@ -53,7 +58,7 @@ public final class ElementTypeDescriptionCustom extends ElementTypeDescription { addAttribute(Keys.ROTATE); addAttribute(Keys.LABEL); addAttribute(Keys.SHAPE_TYPE); - if (circuit.getAttributes().get(Keys.IS_GENERIC)) + if (isGeneric()) addAttribute(Keys.GENERIC); } @@ -118,7 +123,7 @@ public final class ElementTypeDescriptionCustom extends ElementTypeDescription { if (depth > MAX_DEPTH) throw new NodeException(Lang.get("err_recursiveNestingAt_N0", circuit.getOrigin())); - if (circuit.getAttributes().get(Keys.IS_GENERIC)) { + if (isGeneric()) { try { Context args; if (containingVisualElement != null) { @@ -201,4 +206,51 @@ public final class ElementTypeDescriptionCustom extends ElementTypeDescription { isCustom = false; return this; } + + /** + * @return the generics field default value + */ + public String getDeclarationDefault() { + if (declarationDefault == null) + declarationDefault = createDeclarationDefault(); + return declarationDefault; + } + + private String createDeclarationDefault() { + TreeSet nameSet = new TreeSet<>(); + for (VisualElement ve : circuit.getElements()) { + String gen = ve.getElementAttributes().get(Keys.GENERIC).trim(); + try { + if (!gen.isEmpty()) { + Parser p = new Parser(gen); + p.enableRefReadCollection(); + p.parse(false); + for (Reference r : p.getRefsRead()) { + if (r instanceof ReferenceToStruct) { + ReferenceToStruct st = (ReferenceToStruct) r; + if (st.getParent() instanceof ReferenceToVar) { + ReferenceToVar var = (ReferenceToVar) st.getParent(); + if (var.getName().equals("args")) { + nameSet.add(st.getName()); + } + } + } + } + } + } catch (ParserException | IOException e) { + return ""; + } + } + StringBuilder sb = new StringBuilder(); + for (String name : nameSet) + sb.append(name).append(" := ;\n"); + return sb.toString(); + } + + /** + * @return true if the circuit is generic + */ + public boolean isGeneric() { + return circuit.getAttributes().get(Keys.IS_GENERIC); + } } 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 b74fa95e8..2f3bc8a24 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -1023,10 +1023,19 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib try { ArrayList list = getAttributeList(element); if (list.size() > 0) { + ElementTypeDescription elementType = library.getElementType(element.getElementName()); + + if (elementType instanceof ElementTypeDescriptionCustom) { + ElementTypeDescriptionCustom customDescr = (ElementTypeDescriptionCustom) elementType; + if (customDescr.isGeneric()) { + if (element.getElementAttributes().get(Keys.GENERIC).isEmpty()) + element.getElementAttributes().set(Keys.GENERIC, customDescr.getDeclarationDefault()); + } + } + Point p = new Point(e.getX(), e.getY()); SwingUtilities.convertPointToScreen(p, CircuitComponent.this); AttributeDialog attributeDialog = new AttributeDialog(parent, p, list, element.getElementAttributes()).setVisualElement(element); - ElementTypeDescription elementType = library.getElementType(element.getElementName()); if (elementType instanceof ElementTypeDescriptionCustom) { attributeDialog.addButton(Lang.get("attr_openCircuitLabel"), new ToolTipAction(Lang.get("attr_openCircuit")) { @Override 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 5c62c3599..03bac503d 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/Parser.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/Parser.java @@ -5,6 +5,7 @@ */ package de.neemann.digital.hdl.hgs; +import de.neemann.digital.builder.tt2.TT2Exporter; import de.neemann.digital.core.Bits; import de.neemann.digital.hdl.hgs.function.FirstClassFunction; import de.neemann.digital.hdl.hgs.function.FirstClassFunctionCall; @@ -55,6 +56,7 @@ public class Parser { } + private ArrayList refRead; private final Tokenizer tok; private Context staticContext; @@ -78,6 +80,20 @@ public class Parser { staticContext = new Context(); } + /** + * If called all read references are collected. + */ + public void enableRefReadCollection() { + refRead = new ArrayList<>(); + } + + /** + * @return returns the references read + */ + public ArrayList getRefsRead() { + return refRead; + } + private Statement lino(Statement statement) { if (statement instanceof StatementWithLine) return statement; @@ -517,6 +533,8 @@ public class Parser { case IDENT: String name = tok.getIdent(); Reference r = parseReference(name); + if (refRead != null) + refRead.add(r); return r::get; case NUMBER: long num = convToLong(tok.getIdent()); diff --git a/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToStruct.java b/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToStruct.java index cedf2935d..17c101bd5 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToStruct.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToStruct.java @@ -53,4 +53,17 @@ public class ReferenceToStruct implements Reference { return value; } + /** + * @return the parent reference + */ + public Reference getParent() { + return parent; + } + + /** + * @return the struct field name + */ + public String getName() { + return name; + } } diff --git a/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToVar.java b/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToVar.java index a8e45926e..8ba8f4ffd 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToVar.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/refs/ReferenceToVar.java @@ -42,4 +42,11 @@ public class ReferenceToVar implements Reference { public Object get(Context context) throws HGSEvalException { return context.getVar(name); } + + /** + * @return the var name + */ + public String getName() { + return name; + } } diff --git a/src/test/resources/dig/test/generics/mainMem.dig b/src/test/resources/dig/test/generics/mainMem.dig index 4494fc432..107545923 100644 --- a/src/test/resources/dig/test/generics/mainMem.dig +++ b/src/test/resources/dig/test/generics/mainMem.dig @@ -15,7 +15,7 @@ 16 - + In @@ -80,8 +80,11 @@ end loop # read data loop(n,1<<8) -C 0 (n) 0 (n+2) -end loop +0 0 (n) 0 (n+2) +end loop + +0 0 (1<<8) 0 (2) + @@ -92,8 +95,8 @@ end loop generic - bits:=int(16); -addr:=8; + dataBits := 16; +addrBits := 8; @@ -105,8 +108,8 @@ addr:=8; - - + + @@ -116,6 +119,10 @@ addr:=8; + + + + @@ -140,6 +147,10 @@ addr:=8; + + + + diff --git a/src/test/resources/dig/test/generics/memLeaf.dig b/src/test/resources/dig/test/generics/memLeaf.dig index 34ea4e024..b327bf6fa 100644 --- a/src/test/resources/dig/test/generics/memLeaf.dig +++ b/src/test/resources/dig/test/generics/memLeaf.dig @@ -13,7 +13,7 @@ generic - this.Bits=args.bits; + this.Bits=int(args.dataBits); @@ -23,7 +23,7 @@ generic - this.Bits=args.bits; + this.Bits=int(args.dataBits); @@ -33,7 +33,7 @@ generic - this.Bits=args.bits; + this.Bits=int(args.dataBits); diff --git a/src/test/resources/dig/test/generics/memNode.dig b/src/test/resources/dig/test/generics/memNode.dig index 6994fd7ae..dc3f52011 100644 --- a/src/test/resources/dig/test/generics/memNode.dig +++ b/src/test/resources/dig/test/generics/memNode.dig @@ -68,7 +68,7 @@ generic if (isPresent(args)) { - this.Bits=args.bits; + this.Bits=int(args.dataBits); } @@ -106,12 +106,12 @@ generic if (isPresent(args)) { - if (args.addr<2) { + if (args.addrBits<2) { panic("at least two address bits are necessary!"); } - this.'Input Splitting'=""+args.addr; - this.'Output Splitting'=(args.addr-1)+",1"; + this.'Input Splitting'=""+args.addrBits; + this.'Output Splitting'=(args.addrBits-1)+",1"; } @@ -123,13 +123,13 @@ generic if (isPresent(args)) { - export bits:=args.bits; - export addr:=args.addr-1; - if (args.addr>2) { + export dataBits:=args.dataBits; + export addrBits:=args.addrBits-1; + if (args.addrBits>2) { setCircuit("memNode.dig"); } } else { - export bits:=int(1); + export dataBits:=int(1); } @@ -141,13 +141,13 @@ generic if (isPresent(args)) { - export bits:=args.bits; - export addr:=args.addr-1; - if (args.addr>2) { + export dataBits:=args.dataBits; + export addrBits:=args.addrBits-1; + if (args.addrBits>2) { setCircuit("memNode.dig"); } } else { - export bits:=int(1); + export dataBits:=int(1); } @@ -161,14 +161,14 @@ - + - + @@ -185,10 +185,10 @@ - + - + @@ -212,7 +212,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -244,7 +244,7 @@ - + @@ -268,25 +268,25 @@ - - + + + + + + + + + + + + + + - - - - - - - - - - - - \ No newline at end of file