mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-12 22:36:02 -04:00
added comments to vhdl output
This commit is contained in:
parent
5179b720ae
commit
7890ec22f2
@ -43,6 +43,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
|
||||
private final ArrayList<HDLPort> outputs;
|
||||
private final ArrayList<HDLPort> inputs;
|
||||
private final ArrayList<HDLNet> listOfNets;
|
||||
private final String description;
|
||||
private ArrayList<HDLPort> ports;
|
||||
private NetList netList;
|
||||
private ArrayList<HDLNode> nodes;
|
||||
@ -89,6 +90,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
|
||||
nets = new HashMap<>();
|
||||
listOfNets = new ArrayList<>();
|
||||
netList = new NetList(circuit);
|
||||
description = circuit.getAttributes().get(Keys.DESCRIPTION);
|
||||
|
||||
ArrayList<ClockInfo> clocks = new ArrayList<>();
|
||||
|
||||
@ -100,7 +102,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
|
||||
getNetOfPin(v.getPins().get(0)),
|
||||
HDLPort.Direction.OUT, // from inside the node this is an output because it defines a value
|
||||
v.getElementAttributes().getBits())
|
||||
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER));
|
||||
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))
|
||||
.setDescription(v.getElementAttributes().get(Keys.DESCRIPTION));
|
||||
addInput(port);
|
||||
if (v.equalsDescription(Clock.DESCRIPTION))
|
||||
clocks.add(new ClockInfo(port, v.getElementAttributes().get(Keys.FREQUENCY)));
|
||||
@ -110,7 +113,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
|
||||
getNetOfPin(v.getPins().get(0)),
|
||||
HDLPort.Direction.IN, // from inside the node this is an input because it reads the value to output
|
||||
v.getElementAttributes().getBits())
|
||||
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER)));
|
||||
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))
|
||||
.setDescription(v.getElementAttributes().get(Keys.DESCRIPTION)));
|
||||
else if (v.equalsDescription(Splitter.DESCRIPTION))
|
||||
handleSplitter(c.createNode(v, this));
|
||||
else if (isRealElement(v))
|
||||
@ -460,6 +464,20 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
|
||||
return hdlEntityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description of this circuit
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the circuit has a description
|
||||
*/
|
||||
public boolean hasDescription() {
|
||||
return description != null && description.trim().length() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Integrates a clock node.
|
||||
*
|
||||
|
@ -15,6 +15,8 @@ import java.io.IOException;
|
||||
*/
|
||||
public class HDLPort implements Printable, HasName {
|
||||
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* The ports direction
|
||||
*/
|
||||
@ -71,6 +73,31 @@ public class HDLPort implements Printable, HasName {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this port.
|
||||
*
|
||||
* @param description the description
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public HDLPort setDescription(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ports description.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this port has a description
|
||||
*/
|
||||
public boolean hasDescription() {
|
||||
return description != null && description.trim().length() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the net of this port
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@ public class CodePrinter implements Closeable {
|
||||
private File file;
|
||||
private int ident = 0;
|
||||
private boolean newLine = true;
|
||||
private int pos;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
@ -139,7 +140,7 @@ public class CodePrinter implements Closeable {
|
||||
*/
|
||||
public CodePrinter print(char c) throws IOException {
|
||||
if (newLine && c != '\n') {
|
||||
int pos = ident * indentWidth;
|
||||
pos = ident * indentWidth;
|
||||
for (int i = 0; i < pos; i++)
|
||||
out.write(' ');
|
||||
newLine = false;
|
||||
@ -148,6 +149,8 @@ public class CodePrinter implements Closeable {
|
||||
out.write(c);
|
||||
else
|
||||
out.write(("" + c).getBytes(CHARSET));
|
||||
pos++;
|
||||
|
||||
if (c == '\n') {
|
||||
newLine = true;
|
||||
eolIsWritten();
|
||||
@ -191,4 +194,38 @@ public class CodePrinter implements Closeable {
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pronts a comment to the target file
|
||||
*
|
||||
* @param singleLineComment the string which opens a single line comment (-- in VHDL)
|
||||
* @param comment the comment to print
|
||||
* @return this for chained calls
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public CodePrinter printComment(String singleLineComment, String comment) throws IOException {
|
||||
if (comment == null || comment.length() == 0)
|
||||
return this;
|
||||
|
||||
|
||||
int startPos = pos;
|
||||
if (newLine)
|
||||
startPos = ident * indentWidth;
|
||||
|
||||
print(singleLineComment);
|
||||
for (int i = 0; i < comment.length(); i++) {
|
||||
char c = comment.charAt(i);
|
||||
print(c);
|
||||
if (c == '\n') {
|
||||
int spaceCount = startPos - ident * indentWidth;
|
||||
for (int j = 0; j < spaceCount; j++)
|
||||
print(' ');
|
||||
print(singleLineComment);
|
||||
}
|
||||
}
|
||||
println();
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -14,34 +14,88 @@ import java.io.IOException;
|
||||
*/
|
||||
public class Separator {
|
||||
private final String sep;
|
||||
private final CodePrinter out;
|
||||
private final String finalizerSeparator;
|
||||
private boolean first = true;
|
||||
private LineFinalizer lineFinalizer;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param out the print stream
|
||||
* @param sep The separator
|
||||
*/
|
||||
public Separator(String sep) {
|
||||
public Separator(CodePrinter out, String sep) {
|
||||
this.sep = sep;
|
||||
this.out = out;
|
||||
if (sep.length() > 0 && sep.charAt(sep.length() - 1) == '\n')
|
||||
finalizerSeparator = sep.substring(0, sep.length() - 1);
|
||||
else
|
||||
finalizerSeparator = sep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the separator
|
||||
*
|
||||
* @param out the print stream
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public void check(CodePrinter out) throws IOException {
|
||||
public void check() throws IOException {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
out.print(getSeperator());
|
||||
else {
|
||||
if (lineFinalizer == null)
|
||||
printSeparator(out);
|
||||
else {
|
||||
out.print(finalizerSeparator);
|
||||
lineFinalizer.finalizeLine(out);
|
||||
lineFinalizer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the separator
|
||||
* prints the separator
|
||||
*
|
||||
* @param out the print stream
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public String getSeperator() {
|
||||
return sep;
|
||||
public void printSeparator(CodePrinter out) throws IOException {
|
||||
out.print(sep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the line finalizer
|
||||
* This finalizer is only used once at the next line ending.
|
||||
*
|
||||
* @param lineFinalizer thi file finalizer
|
||||
*/
|
||||
public void setLineFinalizer(LineFinalizer lineFinalizer) {
|
||||
this.lineFinalizer = lineFinalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this Separator.
|
||||
* If there is a pending line separator, it's printed.
|
||||
*
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (lineFinalizer != null)
|
||||
lineFinalizer.finalizeLine(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a finalizer, this finalizer method is called
|
||||
* instead of calling printSeparator.
|
||||
* A finerlizer is used only one time.
|
||||
*/
|
||||
public interface LineFinalizer {
|
||||
/**
|
||||
* Prints the line ending
|
||||
*
|
||||
* @param out the stream to print to
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
void finalizeLine(CodePrinter out) throws IOException;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class VHDLCreator {
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param out the output stream
|
||||
* @param out the output stream
|
||||
*/
|
||||
VHDLCreator(CodePrinter out) {
|
||||
this.out = out;
|
||||
@ -104,6 +104,9 @@ public class VHDLCreator {
|
||||
.println("USE ieee.numeric_std.all;")
|
||||
.println();
|
||||
|
||||
if (circuit.hasDescription())
|
||||
out.printComment("-- ", circuit.getDescription());
|
||||
|
||||
out.print("entity ").print(circuit.getHdlEntityName()).println(" is").inc();
|
||||
writePorts(out, circuit);
|
||||
out.dec();
|
||||
@ -152,16 +155,19 @@ public class VHDLCreator {
|
||||
public static void writePorts(CodePrinter out, HDLCircuit circuit) throws IOException {
|
||||
out.println("port (").inc();
|
||||
|
||||
Separator sep = new Separator(";\n");
|
||||
Separator sep = new Separator(out, ";\n");
|
||||
|
||||
for (HDLPort i : circuit.getInputs()) {
|
||||
sep.check(out);
|
||||
sep.check();
|
||||
out.print(i.getName()).print(": in ").print(getType(i.getBits()));
|
||||
if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", i.getDescription()));
|
||||
}
|
||||
for (HDLPort o : circuit.getOutputs()) {
|
||||
sep.check(out);
|
||||
sep.check();
|
||||
out.print(o.getName()).print(": out ").print(getType(o.getBits()));
|
||||
if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", o.getDescription()));
|
||||
}
|
||||
sep.close();
|
||||
out.println(");").dec();
|
||||
}
|
||||
|
||||
@ -204,16 +210,16 @@ public class VHDLCreator {
|
||||
if (!(node instanceof HDLNodeCustom))
|
||||
library.getEntity(node).writeGenericMap(out, node);
|
||||
out.println("port map (").inc();
|
||||
Separator sep = new Separator(",\n");
|
||||
Separator sep = new Separator(out, ",\n");
|
||||
for (HDLPort i : node.getInputs())
|
||||
if (i.getNet() != null) {
|
||||
sep.check(out);
|
||||
sep.check();
|
||||
out.print(i.getName()).print(" => ").print(i.getNet().getName());
|
||||
}
|
||||
|
||||
for (HDLPort o : node.getOutputs())
|
||||
if (o.getNet() != null) {
|
||||
sep.check(out);
|
||||
sep.check();
|
||||
out.print(o.getName()).print(" => ").print(o.getNet().getName());
|
||||
}
|
||||
out.println(");").dec().dec();
|
||||
|
@ -116,13 +116,13 @@ public class VHDLTestBenchCreator {
|
||||
out.dec().println("begin").inc();
|
||||
|
||||
out.println("main_0 : main port map (").inc();
|
||||
Separator comma = new Separator(",\n");
|
||||
Separator comma = new Separator(out, ",\n");
|
||||
for (HDLPort p : main.getInputs()) {
|
||||
comma.check(out);
|
||||
comma.check();
|
||||
out.print(p.getName() + " => " + p.getName());
|
||||
}
|
||||
for (HDLPort p : main.getOutputs()) {
|
||||
comma.check(out);
|
||||
comma.check();
|
||||
out.print(p.getName() + " => " + p.getName());
|
||||
}
|
||||
out.println(" );").dec();
|
||||
@ -225,10 +225,10 @@ public class VHDLTestBenchCreator {
|
||||
private LineListenerVHDL(CodePrinter out, ArrayList<HDLPort> dataOrder) {
|
||||
this.out = out;
|
||||
this.dataOrder = dataOrder;
|
||||
lineSep = new Separator("") {
|
||||
lineSep = new Separator(out, "") {
|
||||
@Override
|
||||
public String getSeperator() {
|
||||
return ", -- i=" + (line++) + "\n";
|
||||
public void printSeparator(CodePrinter out) throws IOException {
|
||||
out.print(", -- i=").print((line++)).print("\n");
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -241,12 +241,12 @@ public class VHDLTestBenchCreator {
|
||||
if (v.getType() == Value.Type.CLOCK)
|
||||
containsClock = true;
|
||||
if (containsClock) {
|
||||
lineSep.check(out);
|
||||
lineSep.check();
|
||||
writeValues(values, true, 0);
|
||||
lineSep.check(out);
|
||||
lineSep.check();
|
||||
writeValues(values, true, 1);
|
||||
}
|
||||
lineSep.check(out);
|
||||
lineSep.check();
|
||||
writeValues(values, false, 0);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -255,9 +255,9 @@ public class VHDLTestBenchCreator {
|
||||
|
||||
private void writeValues(Value[] values, boolean isClock, int clock) throws IOException {
|
||||
out.print("(");
|
||||
Separator sep = new Separator(", ");
|
||||
Separator sep = new Separator(out, ", ");
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
sep.check(out);
|
||||
sep.check();
|
||||
Value val = values[i];
|
||||
int bits = dataOrder.get(i).getBits();
|
||||
switch (val.getType()) {
|
||||
|
@ -74,9 +74,9 @@ public class VHDLTemplate implements VHDLEntity {
|
||||
final Entity e = getEntity(node);
|
||||
if (!e.getGenerics().isEmpty()) {
|
||||
out.println("generic map (").inc();
|
||||
Separator semic = new Separator(",\n");
|
||||
Separator semic = new Separator(out, ",\n");
|
||||
for (VHDLTemplateFunctions.Generic gen : e.getGenerics()) {
|
||||
semic.check(out);
|
||||
semic.check();
|
||||
final Object value = node.getElementAttributes().hgsMapGet(gen.getName());
|
||||
out.print(gen.getName()).print(" => ").print(gen.format(value));
|
||||
}
|
||||
|
@ -23,6 +23,20 @@ public class CodePrinterStrTest extends TestCase {
|
||||
.dec()
|
||||
.println("test")
|
||||
.toString());
|
||||
|
||||
assertEquals("test;\n" +
|
||||
" -- Hello\n" +
|
||||
" -- World\n" +
|
||||
" -- Long text\n" +
|
||||
"test",new CodePrinterStr()
|
||||
.println("test;")
|
||||
.printComment(" -- ","Hello\nWorld\nLong text").print("test").toString());
|
||||
assertEquals("test; -- Hello\n" +
|
||||
" -- World\n" +
|
||||
" -- Long text\n" +
|
||||
"test",new CodePrinterStr()
|
||||
.print("test;")
|
||||
.printComment(" -- ","Hello\nWorld\nLong text").print("test").toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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.hdl.vhdl2;
|
||||
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||
import de.neemann.digital.hdl.hgs.HGSEvalException;
|
||||
import de.neemann.digital.hdl.model2.HDLCircuit;
|
||||
import de.neemann.digital.hdl.model2.HDLException;
|
||||
import de.neemann.digital.hdl.model2.HDLModel;
|
||||
import de.neemann.digital.hdl.printer.CodePrinterStr;
|
||||
import de.neemann.digital.integration.ToBreakRunner;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DescriptionTest extends TestCase {
|
||||
|
||||
public void testDescription() throws PinException, NodeException, ElementNotFoundException, IOException, HDLException, HGSEvalException {
|
||||
ToBreakRunner br = new ToBreakRunner("dig/hdl/model2/naming.dig");
|
||||
HDLCircuit circuit = new HDLCircuit(
|
||||
br.getCircuit(),
|
||||
"main"
|
||||
, new HDLModel(br.getLibrary()),
|
||||
null)
|
||||
.mergeConstants()
|
||||
.mergeExpressions()
|
||||
.nameNets();
|
||||
CodePrinterStr out = new CodePrinterStr();
|
||||
new VHDLCreator(out).printHDLCircuit(circuit);
|
||||
|
||||
assertEquals("\n" +
|
||||
"LIBRARY ieee;\n" +
|
||||
"USE ieee.std_logic_1164.all;\n" +
|
||||
"USE ieee.numeric_std.all;\n" +
|
||||
"\n" +
|
||||
"-- Simple test circuit\n" +
|
||||
"-- used to test comments.\n"+
|
||||
"entity main is\n" +
|
||||
" port (\n" +
|
||||
" S0: in std_logic; -- First input\n" +
|
||||
" -- This is a far longer text.\n" +
|
||||
" S1: in std_logic; -- Second input\n" +
|
||||
" S2: out std_logic; -- first output\n" +
|
||||
" S3: out std_logic -- second output\n" +
|
||||
" -- also with a longer text\n" +
|
||||
" );\n" +
|
||||
"end main;\n" +
|
||||
"\n" +
|
||||
"architecture Behavioral of main is\n" +
|
||||
" signal s4: std_logic;\n" +
|
||||
"begin\n" +
|
||||
" s4 <= NOT (S0 OR S1);\n" +
|
||||
" S2 <= (S0 XOR s4);\n" +
|
||||
" S3 <= (s4 XOR S1);\n" +
|
||||
"end Behavioral;\n", out.toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.hdl.vhdl2;
|
||||
|
||||
import de.neemann.digital.hdl.printer.CodePrinterStr;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SeparatorTest extends TestCase {
|
||||
|
||||
public void testSeparator() throws IOException {
|
||||
CodePrinterStr out = new CodePrinterStr();
|
||||
|
||||
out.println("open (").inc();
|
||||
Separator sep = new Separator(out, ",\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sep.check();
|
||||
out.print("item").print(i);
|
||||
}
|
||||
out.println(")").dec();
|
||||
out.print("close");
|
||||
|
||||
assertEquals("open (\n" +
|
||||
" item0,\n" +
|
||||
" item1,\n" +
|
||||
" item2,\n" +
|
||||
" item3)\n" +
|
||||
"close", out.toString());
|
||||
}
|
||||
|
||||
public void testSeparator2() throws IOException {
|
||||
CodePrinterStr out = new CodePrinterStr();
|
||||
|
||||
out.println("open (").inc();
|
||||
Separator sep = new Separator(out, ",\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sep.check();
|
||||
out.print("item").print(i);
|
||||
String ic = "item" + i + " comment";
|
||||
sep.setLineFinalizer(o -> o.printComment(" \\\\ ", ic));
|
||||
}
|
||||
sep.close();
|
||||
out.println(")").dec();
|
||||
out.print("close");
|
||||
|
||||
assertEquals("open (\n" +
|
||||
" item0, \\\\ item0 comment\n" +
|
||||
" item1, \\\\ item1 comment\n" +
|
||||
" item2, \\\\ item2 comment\n" +
|
||||
" item3 \\\\ item3 comment\n" +
|
||||
" )\n" +
|
||||
"close", out.toString());
|
||||
}
|
||||
|
||||
public void testSeparator3() throws IOException {
|
||||
CodePrinterStr out = new CodePrinterStr();
|
||||
|
||||
out.println("open (").inc();
|
||||
Separator sep = new Separator(out, ",");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sep.check();
|
||||
out.print("item").print(i);
|
||||
if ((i&1)==0) {
|
||||
String ic = "item" + i + " comment";
|
||||
sep.setLineFinalizer(o -> o.printComment(" \\\\ ", ic));
|
||||
}
|
||||
}
|
||||
sep.close();
|
||||
out.println(")").dec();
|
||||
out.print("close");
|
||||
|
||||
assertEquals("open (\n" +
|
||||
" item0, \\\\ item0 comment\n" +
|
||||
" item1,item2, \\\\ item2 comment\n" +
|
||||
" item3)\n" +
|
||||
"close", out.toString());
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<circuit>
|
||||
<version>1</version>
|
||||
<attributes/>
|
||||
<attributes>
|
||||
<entry>
|
||||
<string>Description</string>
|
||||
<string>Simple test circuit
|
||||
used to test comments.</string>
|
||||
</entry>
|
||||
</attributes>
|
||||
<visualElements>
|
||||
<visualElement>
|
||||
<elementName>Out</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Description</string>
|
||||
<string>first output</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>S2</string>
|
||||
@ -20,6 +30,11 @@
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Description</string>
|
||||
<string>First input
|
||||
This is a far longer text.</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>S0</string>
|
||||
@ -30,6 +45,10 @@
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Description</string>
|
||||
<string>Second input</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>S1</string>
|
||||
@ -55,6 +74,11 @@
|
||||
<visualElement>
|
||||
<elementName>Out</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Description</string>
|
||||
<string>second output
|
||||
also with a longer text</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>S3</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user