From: Daniel Kirschten Date: Sun, 13 Dec 2020 18:32:15 +0000 (+0100) Subject: Improvements in the ModelComponentToVerilogConverter: X-Git-Url: https://mograsim.net/gitweb/?p=Mograsim.git;a=commitdiff_plain;h=c6087221c312e76ad07cf75da61c735278ab8634 Improvements in the ModelComponentToVerilogConverter: +Internally connected pins are now supported +WireCrossPoints are now supported (without external definitions) Refined the Verilog model --- diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogComponentDeclarationMapping.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogComponentDeclarationMapping.java index 808ac51f..b05e152b 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogComponentDeclarationMapping.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogComponentDeclarationMapping.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import com.google.gson.JsonElement; @@ -20,6 +21,7 @@ public class ModelComponentToVerilogComponentDeclarationMapping private final VerilogComponentDeclaration verilogComponentDeclaration; private final Set pinMapping; + private final Set> internallyConnectedPins; private final Map prePinMapping; private final Map outPinMapping; private final Map resPinMapping; @@ -35,6 +37,7 @@ public class ModelComponentToVerilogComponentDeclarationMapping this.reversePinMapping = checkAndCalculateReversePinMapping(); + this.internallyConnectedPins = calculateInternallyConnectedPins(); this.prePinMapping = filterPinMapping(Type.PRE); this.outPinMapping = filterPinMapping(Type.OUT); this.resPinMapping = filterPinMapping(Type.RES); @@ -67,6 +70,11 @@ public class ModelComponentToVerilogComponentDeclarationMapping return reverseMapping; } + private Set> calculateInternallyConnectedPins() + { + return pinMapping.stream().map(VerilogEmulatedModelPin::getPinbits).collect(Collectors.toUnmodifiableSet()); + } + private Map filterPinMapping(Type filteredType) { Map result = new HashMap<>(); @@ -92,6 +100,11 @@ public class ModelComponentToVerilogComponentDeclarationMapping return verilogComponentDeclaration; } + public Set> getInternallyConnectedPins() + { + return internallyConnectedPins; + } + public Set getPinMapping() { return pinMapping; @@ -123,6 +136,7 @@ public class ModelComponentToVerilogComponentDeclarationMapping final int prime = 31; int result = 1; result = prime * result + ((modelComponentID == null) ? 0 : modelComponentID.hashCode()); + result = prime * result + ((modelComponentParams == null) ? 0 : modelComponentParams.hashCode()); result = prime * result + ((pinMapping == null) ? 0 : pinMapping.hashCode()); result = prime * result + ((verilogComponentDeclaration == null) ? 0 : verilogComponentDeclaration.hashCode()); return result; @@ -144,6 +158,12 @@ public class ModelComponentToVerilogComponentDeclarationMapping return false; } else if (!modelComponentID.equals(other.modelComponentID)) return false; + if (modelComponentParams == null) + { + if (other.modelComponentParams != null) + return false; + } else if (!modelComponentParams.equals(other.modelComponentParams)) + return false; if (pinMapping == null) { if (other.pinMapping != null) diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java index b7e87723..673018ed 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/ModelComponentToVerilogConverter.java @@ -20,22 +20,26 @@ import net.mograsim.logic.model.model.components.ModelComponent; import net.mograsim.logic.model.model.components.atomic.ModelSplitter; import net.mograsim.logic.model.model.components.submodels.SubmodelComponent; import net.mograsim.logic.model.model.wires.ModelWire; +import net.mograsim.logic.model.model.wires.ModelWireCrossPoint; import net.mograsim.logic.model.model.wires.Pin; import net.mograsim.logic.model.serializing.IdentifyParams; import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type; -import net.mograsim.logic.model.verilog.helper.IdentifierGenerator; -import net.mograsim.logic.model.verilog.helper.UnionFind; -import net.mograsim.logic.model.verilog.model.Assign; -import net.mograsim.logic.model.verilog.model.ComponentReference; -import net.mograsim.logic.model.verilog.model.Constant; -import net.mograsim.logic.model.verilog.model.IOPort; -import net.mograsim.logic.model.verilog.model.Input; -import net.mograsim.logic.model.verilog.model.NamedSignal; -import net.mograsim.logic.model.verilog.model.Output; -import net.mograsim.logic.model.verilog.model.Signal; import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration; import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation; -import net.mograsim.logic.model.verilog.model.Wire; +import net.mograsim.logic.model.verilog.model.expressions.SignalReference; +import net.mograsim.logic.model.verilog.model.signals.Constant; +import net.mograsim.logic.model.verilog.model.signals.IOPort; +import net.mograsim.logic.model.verilog.model.signals.Input; +import net.mograsim.logic.model.verilog.model.signals.NamedSignal; +import net.mograsim.logic.model.verilog.model.signals.Output; +import net.mograsim.logic.model.verilog.model.signals.Signal; +import net.mograsim.logic.model.verilog.model.signals.Wire; +import net.mograsim.logic.model.verilog.model.statements.Assign; +import net.mograsim.logic.model.verilog.model.statements.ComponentReference; +import net.mograsim.logic.model.verilog.model.statements.Statement; +import net.mograsim.logic.model.verilog.model.statements.WireDeclaration; +import net.mograsim.logic.model.verilog.utils.IdentifierGenerator; +import net.mograsim.logic.model.verilog.utils.UnionFind; public class ModelComponentToVerilogConverter { @@ -60,30 +64,42 @@ public class ModelComponentToVerilogConverter private void convert(ModelComponent modelComponent) { + // these are handled elsewhere + if (modelComponent instanceof ModelSplitter || modelComponent instanceof ModelWireCrossPoint) + return; + String modelID = modelComponent.getIDForSerializing(new IdentifyParams()); JsonElement params = modelComponent.getParamsForSerializingJSON(new IdentifyParams()); if (componentMappingsPerModelIDPerParams.getOrDefault(modelID, Map.of()).containsKey(params)) // we already converted that component, or it was specified externally return; - if (!(modelComponent instanceof SubmodelComponent)) + String verilogID = verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params)); + + // TODO don't rely on instanceof + if (modelComponent instanceof SubmodelComponent) + convertSubmodelComponent((SubmodelComponent) modelComponent, modelID, params, verilogID); + else throw new IllegalArgumentException( "Can only convert SubmodelComponents, tried to convert " + modelID + " with params " + params); - SubmodelComponent modelComponentC = (SubmodelComponent) modelComponent; + } + + private void convertSubmodelComponent(SubmodelComponent modelComponent, String modelID, JsonElement params, String verilogID) + { + for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) + if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) + convert(subcomponent); - UnionFind connectedPins = findConnectedPins(modelComponentC); + UnionFind connectedPins = findConnectedPins(modelComponent); - ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponentC, connectedPins, modelID, params); + ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponent, connectedPins, modelID, params, + verilogID); componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, mapping); - for (ModelComponent subcomponent : modelComponentC.submodel.getComponentsByName().values()) - if (!(subcomponent instanceof ModelSplitter) && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) - convert(subcomponent); - - verilogComponents.add(mapImplementation(modelComponentC, connectedPins, mapping)); + verilogComponents.add(mapImplementation(modelComponent, connectedPins, mapping)); } - private static UnionFind findConnectedPins(SubmodelComponent modelComponent) + private UnionFind findConnectedPins(SubmodelComponent modelComponent) { UnionFind connectedPins = new UnionFind<>(); for (ModelWire w : modelComponent.submodel.getWiresByName().values()) @@ -96,15 +112,19 @@ public class ModelComponentToVerilogConverter ModelSplitter splitter = (ModelSplitter) subcomponent; for (int bit = 0; bit < splitter.logicWidth; bit++) connectedPins.union(new PinBit(splitter.getInputPin(), bit), new PinBit(splitter.getOutputPin(bit), 0)); + } else if (!(subcomponent instanceof ModelWireCrossPoint) + && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) + { + ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = getComponentMapping(subcomponent); + for (Set connected : subcomponentMapping.getInternallyConnectedPins()) + connectedPins.unionAll(connected.stream().map(p -> p.toPinBit(subcomponent)).collect(Collectors.toList())); } - // TODO connected pins of subcomponents - return connectedPins; } - private ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent, - UnionFind connectedPins, String modelID, JsonElement params) + private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent, + UnionFind connectedPins, String modelID, JsonElement params, String verilogID) { // TODO this is probably slow Map representantMapping = new HashMap<>(); @@ -117,8 +137,7 @@ public class ModelComponentToVerilogConverter connectedPinsByName.union(pinnamebit, representative); } - return generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params, - verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params))); + return generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params, verilogID); } public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent, @@ -191,34 +210,28 @@ public class ModelComponentToVerilogConverter Map currentPreSignals = new HashMap<>(); Map finalOutSignals = new HashMap<>(); Map resSignals = new HashMap<>(); - for (Pin submodelPin : modelComponent.getSubmodelPins().values()) - for (int bit = 0; bit < submodelPin.logicWidth; bit++) - { - PinBit pinbit = new PinBit(submodelPin, bit); - PinNameBit pinnamebit = pinbit.toPinNameBit(); - PinBit root = connectedPins.find(pinbit); - resSignals.put(root, declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort()); - finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort()); - Signal prePort = declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort(); - Signal previousPrePort = currentPreSignals.put(root, prePort); - assert previousPrePort != null && !previousPrePort.equals(prePort); - } + for (Set connectedPinGroup : declarationMapping.getInternallyConnectedPins()) + { + PinNameBit pinnamebit = connectedPinGroup.iterator().next(); + PinBit root = connectedPins.find(pinnamebit.toSubmodelPinBit(modelComponent)); + resSignals.put(root, declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort()); + finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort()); + currentPreSignals.put(root, declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort()); + } IdentifierGenerator idGen = new IdentifierGenerator( declarationMapping.getVerilogComponentDeclaration().getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()), ModelComponentToVerilogConverter::sanitizeVerilogID); - Set internalWires = new HashSet<>(); - Set subcomponents = new HashSet<>(); + List statements = new ArrayList<>(); for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values()) { // TODO do we really want to use instanceof? - if (subcomponent instanceof ModelSplitter || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) + if (subcomponent instanceof ModelSplitter || subcomponent instanceof ModelWireCrossPoint + || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)) continue; String subcomponentVerilogName = idGen.generateID(subcomponent.getName()); - ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams - .get(subcomponent.getIDForSerializing(new IdentifyParams())) - .get(subcomponent.getParamsForSerializingJSON(new IdentifyParams())); + ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = getComponentMapping(subcomponent); int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size(); List arguments = new ArrayList<>(parameterCount); for (int i = 0; i < parameterCount; i++) @@ -229,7 +242,7 @@ public class ModelComponentToVerilogConverter PinBit pinbit = new PinBit(pin, bit); PinBit root = connectedPins.find(pinbit); Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2); - internalWires.add(outSignal); + statements.add(new WireDeclaration(outSignal)); Signal preSignal = currentPreSignals.put(root, outSignal); Signal resSignal = resSignals.get(root); if (resSignal == null) @@ -237,7 +250,7 @@ public class ModelComponentToVerilogConverter preSignal = new Constant(BitVector.of(Bit.ZERO, 2)); Wire resWire = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit + "_res"), 2); resSignal = resWire; - internalWires.add(resWire); + statements.add(new WireDeclaration(resWire)); finalOutSignals.put(root, resWire); resSignals.put(root, resWire); } @@ -246,16 +259,21 @@ public class ModelComponentToVerilogConverter arguments.set(subcomponentMapping.getOutPinMapping().get(pinnamebit).getPortIndex(), outSignal); arguments.set(subcomponentMapping.getResPinMapping().get(pinnamebit).getPortIndex(), resSignal); } - subcomponents + statements .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments)); } - Set assigns = new HashSet<>(); for (Entry e : finalOutSignals.entrySet()) - assigns.add(new Assign(currentPreSignals.get(e.getKey()), e.getValue())); + statements.add(new Assign(e.getValue(), new SignalReference(currentPreSignals.get(e.getKey())))); + + return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), statements); + } - return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), internalWires, assigns, - subcomponents); + private ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component) + { + ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams + .get(component.getIDForSerializing(new IdentifyParams())).get(component.getParamsForSerializingJSON(new IdentifyParams())); + return subcomponentMapping; } private Set getVerilogComponents() diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/PinNameBit.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/PinNameBit.java index 461aa02d..1a61e08e 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/PinNameBit.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/PinNameBit.java @@ -2,6 +2,9 @@ package net.mograsim.logic.model.verilog.converter; import java.util.Objects; +import net.mograsim.logic.model.model.components.ModelComponent; +import net.mograsim.logic.model.model.components.submodels.SubmodelComponent; + public class PinNameBit { private final String name; @@ -31,6 +34,16 @@ public class PinNameBit return bit; } + public PinBit toPinBit(ModelComponent pinParent) + { + return new PinBit(pinParent.getPin(name), bit); + } + + public PinBit toSubmodelPinBit(SubmodelComponent submodelComponent) + { + return new PinBit(submodelComponent.getSubmodelPin(name), bit); + } + @Override public String toString() { diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/VerilogEmulatedModelPin.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/VerilogEmulatedModelPin.java index b27b4853..feccad13 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/VerilogEmulatedModelPin.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/converter/VerilogEmulatedModelPin.java @@ -3,8 +3,8 @@ package net.mograsim.logic.model.verilog.converter; import java.util.Objects; import java.util.Set; -import net.mograsim.logic.model.verilog.model.IOPort; -import net.mograsim.logic.model.verilog.model.Signal; +import net.mograsim.logic.model.verilog.model.signals.IOPort; +import net.mograsim.logic.model.verilog.model.signals.Signal; public class VerilogEmulatedModelPin { diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/helper/IdentifierGenerator.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/helper/IdentifierGenerator.java deleted file mode 100644 index b247f25b..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/helper/IdentifierGenerator.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.mograsim.logic.model.verilog.helper; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Function; - -public class IdentifierGenerator -{ - private final Function sanitizer; - private final Set usedIdentifiers; - - public IdentifierGenerator() - { - this(Function.identity()); - } - - public IdentifierGenerator(Function sanitizer) - { - this.usedIdentifiers = new HashSet<>(); - this.sanitizer = sanitizer; - } - - public IdentifierGenerator(Collection forbiddenIDs) - { - this(forbiddenIDs, Function.identity()); - } - - public IdentifierGenerator(Collection forbiddenIDs, Function sanitizer) - { - this.usedIdentifiers = new HashSet<>(forbiddenIDs); - this.sanitizer = sanitizer; - } - - public String generateID(String hint) - { - String sanitized = sanitizer.apply(hint); - if (usedIdentifiers.add(sanitized)) - return sanitized; - - String idBase = sanitized.isEmpty() ? "_" : sanitized; - for (int i = 0;; i++) - if (usedIdentifiers.add(idBase + i)) - return idBase + i; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/helper/UnionFind.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/helper/UnionFind.java deleted file mode 100644 index 1a97ba29..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/helper/UnionFind.java +++ /dev/null @@ -1,73 +0,0 @@ -package net.mograsim.logic.model.verilog.helper; - -import java.util.HashMap; -import java.util.Map; - -public class UnionFind -{ - private final Map> elements; - - public UnionFind() - { - this.elements = new HashMap<>(); - } - - public UnionFindElement getElement(E e) - { - return elements.computeIfAbsent(e, UnionFindElement::new); - } - - public E find(E e) - { - return find(getElement(e)).getE(); - } - - public static UnionFindElement find(UnionFindElement elem) - { - if (elem == elem.parent) - return elem; - return elem.parent = find(elem.parent); - } - - public E union(E e1, E e2) - { - return union(getElement(e1), getElement(e2)).getE(); - } - - public static UnionFindElement union(UnionFindElement e1, UnionFindElement e2) - { - UnionFindElement e1Root = find(e1); - UnionFindElement e2Root = find(e2); - - if (e1Root == e2Root) - return e1Root; - - if (e1Root.rank < e2Root.rank) - return e1Root.parent = e2Root; - else if (e1Root.rank > e2Root.rank) - return e2Root.parent = e1Root; - else - { - e2Root.rank++; - return e1Root.parent = e2Root; - } - } - - public static class UnionFindElement - { - private final E e; - private UnionFindElement parent; - private int rank; - - private UnionFindElement(E e) - { - this.e = e; - this.parent = this; - } - - public E getE() - { - return e; - } - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Assign.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Assign.java deleted file mode 100644 index 1c58dc6e..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Assign.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -import java.util.Objects; - -public class Assign -{ - private final Signal source; - private final NamedSignal target; - - public Assign(Signal source, NamedSignal target) - { - this.source = Objects.requireNonNull(source); - this.target = Objects.requireNonNull(target); - - check(); - } - - private void check() - { - if (source.getWidth() != target.getWidth()) - throw new IllegalArgumentException("Signal widthes don't match"); - } - - public Signal getSource() - { - return source; - } - - public Signal getTarget() - { - return target; - } - - public String toVerilogCode() - { - return "assign " + target.toReferenceVerilogCode() + " = " + source.toReferenceVerilogCode() + ";"; - } - - @Override - public String toString() - { - return target.getName() + " = " + source.toReferenceVerilogCode(); - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((source == null) ? 0 : source.hashCode()); - result = prime * result + ((target == null) ? 0 : target.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Assign other = (Assign) obj; - if (source == null) - { - if (other.source != null) - return false; - } else if (!source.equals(other.source)) - return false; - if (target == null) - { - if (other.target != null) - return false; - } else if (!target.equals(other.target)) - return false; - return true; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/ComponentReference.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/ComponentReference.java deleted file mode 100644 index 0ef29aac..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/ComponentReference.java +++ /dev/null @@ -1,108 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -public class ComponentReference -{ - private final String name; - private final VerilogComponentDeclaration referencedComponent; - private final List arguments; - - public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List arguments) - { - this.name = Objects.requireNonNull(name); - this.referencedComponent = Objects.requireNonNull(referencedComponent); - this.arguments = List.copyOf(arguments); - - check(); - } - - private void check() - { - List ioPorts = referencedComponent.getIOPorts(); - if (ioPorts.size() != arguments.size()) - throw new IllegalArgumentException( - "Incorrect nubmer of arguments given: " + arguments.size() + ", but should be " + ioPorts.size()); - - for (int i = 0; i < ioPorts.size(); i++) - if (ioPorts.get(i).getWidth() != arguments.get(i).getWidth()) - throw new IllegalArgumentException("Argument #" + i + "(" + ioPorts.get(i) + "): Incorrect width: " - + arguments.get(i).getWidth() + ", but shoud be " + ioPorts.get(i).getWidth()); - } - - public String getName() - { - return name; - } - - public VerilogComponentDeclaration getReferencedComponent() - { - return referencedComponent; - } - - public List getArguments() - { - return arguments; - } - - public String toVerilogCode() - { - StringBuilder sb = new StringBuilder(); - - sb.append(referencedComponent.getID() + " " + name); - sb.append(arguments.stream().map(Signal::toReferenceVerilogCode).collect(Collectors.joining(", ", "(", ")"))); - sb.append(";"); - - return sb.toString(); - } - - @Override - public String toString() - { - return name + "[" + referencedComponent.getID() + "]"; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((arguments == null) ? 0 : arguments.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((referencedComponent == null) ? 0 : referencedComponent.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ComponentReference other = (ComponentReference) obj; - if (arguments == null) - { - if (other.arguments != null) - return false; - } else if (!arguments.equals(other.arguments)) - return false; - if (name == null) - { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (referencedComponent == null) - { - if (other.referencedComponent != null) - return false; - } else if (!referencedComponent.equals(other.referencedComponent)) - return false; - return true; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Constant.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Constant.java deleted file mode 100644 index 8820d391..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Constant.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -import net.mograsim.logic.core.types.BitVector; - -public class Constant extends Signal -{ - private final BitVector constant; - - public Constant(BitVector constant) - { - super(Type.CONSTANT, constant.length()); - this.constant = constant; - - check(); - } - - private void check() - { - if (!constant.isBinary()) - throw new IllegalArgumentException("Constant is not binary: " + constant); - } - - public BitVector getConstant() - { - return constant; - } - - @Override - public String toReferenceVerilogCode() - { - return getWidth() + "'b" + constant.toBitstring(); - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((constant == null) ? 0 : constant.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - Constant other = (Constant) obj; - if (constant == null) - { - if (other.constant != null) - return false; - } else if (!constant.equals(other.constant)) - return false; - return true; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/IOPort.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/IOPort.java deleted file mode 100644 index af9b9408..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/IOPort.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -public abstract class IOPort extends NamedSignal -{ - public IOPort(Type type, String name, int width) - { - super(type, name, width); - } - - public abstract String toDeclarationVerilogCode(); -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Input.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Input.java deleted file mode 100644 index d3393278..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Input.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -public class Input extends IOPort -{ - public Input(String name, int width) - { - super(Type.IO_INPUT, name, width); - } - - @Override - public String toDeclarationVerilogCode() - { - return "input [" + getWidth() + ":0] " + getName(); - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/NamedSignal.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/NamedSignal.java deleted file mode 100644 index 531cd6d0..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/NamedSignal.java +++ /dev/null @@ -1,59 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -import java.util.Objects; - -public abstract class NamedSignal extends Signal -{ - private final String name; - - public NamedSignal(Type type, String name, int width) - { - super(type, width); - this.name = Objects.requireNonNull(name); - } - - public String getName() - { - return name; - } - - @Override - public String toReferenceVerilogCode() - { - return name; - } - - @Override - public String toString() - { - return name + "[" + getWidth() + "]"; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - NamedSignal other = (NamedSignal) obj; - if (name == null) - { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Output.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Output.java deleted file mode 100644 index fc8c704d..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Output.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -public class Output extends IOPort -{ - public Output(String name, int width) - { - super(Type.IO_OUTPUT, name, width); - } - - @Override - public String toDeclarationVerilogCode() - { - return "output [" + getWidth() + ":0] " + getName(); - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Signal.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Signal.java deleted file mode 100644 index 44f72497..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Signal.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -import java.util.Objects; - -public abstract class Signal -{ - private final Type type; - private final int width; - - public Signal(Type type, int width) - { - this.type = Objects.requireNonNull(type); - this.width = width; - - check(); - } - - private void check() - { - if (width <= 0) - throw new IllegalArgumentException("Signal width is negative: " + width); - } - - public Type getType() - { - return type; - } - - public int getWidth() - { - return width; - } - - public abstract String toReferenceVerilogCode(); - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + width; - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Signal other = (Signal) obj; - if (type != other.type) - return false; - if (width != other.width) - return false; - return true; - } - - public static enum Type - { - WIRE, IO_INPUT, IO_OUTPUT, CONSTANT; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentDeclaration.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentDeclaration.java index bd5b0181..ef6430a7 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentDeclaration.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentDeclaration.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import net.mograsim.logic.model.verilog.model.signals.IOPort; + public class VerilogComponentDeclaration { private final String id; diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentImplementation.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentImplementation.java index fe336948..a7a9de29 100644 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentImplementation.java +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/VerilogComponentImplementation.java @@ -1,58 +1,46 @@ package net.mograsim.logic.model.verilog.model; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import net.mograsim.logic.model.verilog.model.Signal.Type; +import net.mograsim.logic.model.verilog.model.signals.IOPort; +import net.mograsim.logic.model.verilog.model.signals.Signal; +import net.mograsim.logic.model.verilog.model.statements.Statement; public class VerilogComponentImplementation { private final VerilogComponentDeclaration declaration; - private final Set internalWires; - private final Set assigns; - private final Set subcomponents; + private final List statements; - public VerilogComponentImplementation(VerilogComponentDeclaration declaration, Set internalWires, Set assigns, - Set subcomponents) + public VerilogComponentImplementation(VerilogComponentDeclaration declaration, List statements) { this.declaration = Objects.requireNonNull(declaration); - this.internalWires = Set.copyOf(internalWires); - this.assigns = Set.copyOf(assigns); - this.subcomponents = Set.copyOf(subcomponents); + this.statements = List.copyOf(statements); check(); } private void check() { + Set usedNames = declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toCollection(HashSet::new)); + + for (Statement statement : statements) + for (String definedName : statement.getDefinedNames()) + if (!usedNames.add(definedName)) + throw new IllegalArgumentException("Name occurs twice: " + definedName); + Set allSignals = new HashSet<>(); allSignals.addAll(declaration.getIOPorts()); - allSignals.addAll(internalWires); + statements.stream().map(Statement::getDefinedSignals).forEach(allSignals::addAll); - Set usedNames = declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toCollection(HashSet::new)); - - for (Wire wire : internalWires) - if (!usedNames.add(wire.getName())) - throw new IllegalArgumentException("Name occurs twice: " + wire.getName()); - - for (Assign assign : assigns) - if (!allSignals.contains(assign.getSource()) || !allSignals.contains(assign.getTarget())) - throw new IllegalArgumentException("Referenced an unknown signal: " + assign.getSource()); - - for (ComponentReference subcomponent : subcomponents) - if (!usedNames.add(subcomponent.getName())) - throw new IllegalArgumentException("Name occurs twice: " + subcomponent.getName()); - else if (!subcomponent.getArguments().stream().filter(s -> s.getType() != Type.CONSTANT).allMatch(allSignals::contains)) - { - List unknownSignals = new ArrayList<>(subcomponent.getArguments()); - unknownSignals.removeAll(allSignals); - // we know this list contains at least one element - throw new IllegalArgumentException("Assigning a signal not in the component: " + unknownSignals.get(0)); - } + // do two passes, a signal may be referenced before it is defined + for (Statement statement : statements) + if (!allSignals.containsAll(statement.getReferencedSignals())) + throw new IllegalArgumentException("Referenced an unknown signal: " + + statement.getReferencedSignals().stream().filter(s -> !allSignals.contains(s)).findAny().get()); } public VerilogComponentDeclaration getDeclaration() @@ -60,19 +48,9 @@ public class VerilogComponentImplementation return declaration; } - public Set getInternalWires() - { - return internalWires; - } - - public Set getAssigns() - { - return assigns; - } - - public Set getSubcomponents() + public List getStatements() { - return subcomponents; + return statements; } public String toVerilogCode() @@ -83,19 +61,9 @@ public class VerilogComponentImplementation sb.append(declaration.getIOPorts().stream().map(IOPort::toDeclarationVerilogCode).collect(Collectors.joining(", ", "(", ")"))); sb.append(";\n\n"); - for (Wire wire : internalWires) - sb.append(wire.toDeclarationVerilogCode() + "\n"); - if (!internalWires.isEmpty()) - sb.append("\n"); - - for (Assign assign : assigns) - sb.append(assign.toVerilogCode() + "\n"); - if (!assigns.isEmpty()) - sb.append("\n"); - - for (ComponentReference subcomponent : subcomponents) - sb.append(subcomponent.toVerilogCode() + "\n"); - if (!subcomponents.isEmpty()) + for (Statement statement : statements) + sb.append(statement.toVerilogCode() + "\n"); + if (!statements.isEmpty()) sb.append("\n"); sb.append("endmodule\n"); @@ -114,10 +82,8 @@ public class VerilogComponentImplementation { final int prime = 31; int result = 1; - result = prime * result + ((assigns == null) ? 0 : assigns.hashCode()); result = prime * result + ((declaration == null) ? 0 : declaration.hashCode()); - result = prime * result + ((internalWires == null) ? 0 : internalWires.hashCode()); - result = prime * result + ((subcomponents == null) ? 0 : subcomponents.hashCode()); + result = prime * result + ((statements == null) ? 0 : statements.hashCode()); return result; } @@ -131,29 +97,17 @@ public class VerilogComponentImplementation if (getClass() != obj.getClass()) return false; VerilogComponentImplementation other = (VerilogComponentImplementation) obj; - if (assigns == null) - { - if (other.assigns != null) - return false; - } else if (!assigns.equals(other.assigns)) - return false; if (declaration == null) { if (other.declaration != null) return false; } else if (!declaration.equals(other.declaration)) return false; - if (internalWires == null) - { - if (other.internalWires != null) - return false; - } else if (!internalWires.equals(other.internalWires)) - return false; - if (subcomponents == null) + if (statements == null) { - if (other.subcomponents != null) + if (other.statements != null) return false; - } else if (!subcomponents.equals(other.subcomponents)) + } else if (!statements.equals(other.statements)) return false; return true; } diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Wire.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Wire.java deleted file mode 100644 index 31e51fb7..00000000 --- a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/Wire.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.mograsim.logic.model.verilog.model; - -public class Wire extends NamedSignal -{ - public Wire(String name, int width) - { - super(Type.WIRE, name, width); - } - - public String toDeclarationVerilogCode() - { - return "wire [" + getWidth() + ":0] " + getName() + ";"; - } -} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Expression.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Expression.java new file mode 100644 index 00000000..b5fa9b37 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/Expression.java @@ -0,0 +1,24 @@ +package net.mograsim.logic.model.verilog.model.expressions; + +import java.util.Set; + +import net.mograsim.logic.model.verilog.model.signals.Signal; + +public abstract class Expression +{ + private final int width; + + public Expression(int width) + { + this.width = width; + } + + public int getWidth() + { + return width; + } + + public abstract String toVerilogCode(); + + public abstract Set getReferencedSignals(); +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/SignalReference.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/SignalReference.java new file mode 100644 index 00000000..7f553b95 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/expressions/SignalReference.java @@ -0,0 +1,29 @@ +package net.mograsim.logic.model.verilog.model.expressions; + +import java.util.Objects; +import java.util.Set; + +import net.mograsim.logic.model.verilog.model.signals.Signal; + +public class SignalReference extends Expression +{ + private final Signal referencedSignal; + + public SignalReference(Signal referencedSignal) + { + super(referencedSignal.getWidth()); + this.referencedSignal = Objects.requireNonNull(referencedSignal); + } + + @Override + public String toVerilogCode() + { + return referencedSignal.toReferenceVerilogCode(); + } + + @Override + public Set getReferencedSignals() + { + return Set.of(referencedSignal); + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Constant.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Constant.java new file mode 100644 index 00000000..46150b9f --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Constant.java @@ -0,0 +1,61 @@ +package net.mograsim.logic.model.verilog.model.signals; + +import net.mograsim.logic.core.types.BitVector; + +public class Constant extends Signal +{ + private final BitVector constant; + + public Constant(BitVector constant) + { + super(Type.CONSTANT, constant.length()); + this.constant = constant; + + check(); + } + + private void check() + { + if (!constant.isBinary()) + throw new IllegalArgumentException("Constant is not binary: " + constant); + } + + public BitVector getConstant() + { + return constant; + } + + @Override + public String toReferenceVerilogCode() + { + return getWidth() + "'b" + constant.toBitstring(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((constant == null) ? 0 : constant.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + Constant other = (Constant) obj; + if (constant == null) + { + if (other.constant != null) + return false; + } else if (!constant.equals(other.constant)) + return false; + return true; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/IOPort.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/IOPort.java new file mode 100644 index 00000000..7d573bb1 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/IOPort.java @@ -0,0 +1,11 @@ +package net.mograsim.logic.model.verilog.model.signals; + +public abstract class IOPort extends NamedSignal +{ + public IOPort(Type type, String name, int width) + { + super(type, name, width); + } + + public abstract String toDeclarationVerilogCode(); +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Input.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Input.java new file mode 100644 index 00000000..f80f8085 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Input.java @@ -0,0 +1,15 @@ +package net.mograsim.logic.model.verilog.model.signals; + +public class Input extends IOPort +{ + public Input(String name, int width) + { + super(Type.IO_INPUT, name, width); + } + + @Override + public String toDeclarationVerilogCode() + { + return "input [" + getWidth() + ":0] " + getName(); + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/NamedSignal.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/NamedSignal.java new file mode 100644 index 00000000..9fae34b6 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/NamedSignal.java @@ -0,0 +1,59 @@ +package net.mograsim.logic.model.verilog.model.signals; + +import java.util.Objects; + +public abstract class NamedSignal extends Signal +{ + private final String name; + + public NamedSignal(Type type, String name, int width) + { + super(type, width); + this.name = Objects.requireNonNull(name); + } + + public String getName() + { + return name; + } + + @Override + public String toReferenceVerilogCode() + { + return name; + } + + @Override + public String toString() + { + return name + "[" + getWidth() + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + NamedSignal other = (NamedSignal) obj; + if (name == null) + { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Output.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Output.java new file mode 100644 index 00000000..0cea00b7 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Output.java @@ -0,0 +1,15 @@ +package net.mograsim.logic.model.verilog.model.signals; + +public class Output extends IOPort +{ + public Output(String name, int width) + { + super(Type.IO_OUTPUT, name, width); + } + + @Override + public String toDeclarationVerilogCode() + { + return "output [" + getWidth() + ":0] " + getName(); + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Signal.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Signal.java new file mode 100644 index 00000000..e825cede --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Signal.java @@ -0,0 +1,67 @@ +package net.mograsim.logic.model.verilog.model.signals; + +import java.util.Objects; + +public abstract class Signal +{ + private final Type type; + private final int width; + + public Signal(Type type, int width) + { + this.type = Objects.requireNonNull(type); + this.width = width; + + check(); + } + + private void check() + { + if (width <= 0) + throw new IllegalArgumentException("Signal width is negative: " + width); + } + + public Type getType() + { + return type; + } + + public int getWidth() + { + return width; + } + + public abstract String toReferenceVerilogCode(); + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + width; + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Signal other = (Signal) obj; + if (type != other.type) + return false; + if (width != other.width) + return false; + return true; + } + + public static enum Type + { + WIRE, IO_INPUT, IO_OUTPUT, CONSTANT; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Wire.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Wire.java new file mode 100644 index 00000000..b6d331cc --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/signals/Wire.java @@ -0,0 +1,14 @@ +package net.mograsim.logic.model.verilog.model.signals; + +public class Wire extends NamedSignal +{ + public Wire(String name, int width) + { + super(Type.WIRE, name, width); + } + + public String toDeclarationVerilogCode() + { + return "wire [" + getWidth() + ":0] " + getName() + ";"; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Assign.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Assign.java new file mode 100644 index 00000000..e6036f04 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Assign.java @@ -0,0 +1,104 @@ +package net.mograsim.logic.model.verilog.model.statements; + +import java.util.Objects; +import java.util.Set; + +import net.mograsim.logic.model.verilog.model.expressions.Expression; +import net.mograsim.logic.model.verilog.model.signals.NamedSignal; +import net.mograsim.logic.model.verilog.model.signals.Signal; +import net.mograsim.logic.model.verilog.utils.CollectionsUtils; + +public class Assign extends Statement +{ + private final NamedSignal target; + private final Expression source; + + public Assign(NamedSignal target, Expression source) + { + this.target = Objects.requireNonNull(target); + this.source = Objects.requireNonNull(source); + + check(); + } + + private void check() + { + if (source.getWidth() != target.getWidth()) + throw new IllegalArgumentException("Signal widthes don't match"); + } + + public Signal getTarget() + { + return target; + } + + public Expression getSource() + { + return source; + } + + @Override + public String toVerilogCode() + { + return "assign " + target.toReferenceVerilogCode() + " = " + source.toVerilogCode() + ";"; + } + + @Override + public Set getDefinedNames() + { + return Set.of(); + } + + @Override + public Set getDefinedSignals() + { + return Set.of(); + } + + @Override + public Set getReferencedSignals() + { + return CollectionsUtils.union(Set.of(target), source.getReferencedSignals()); + } + + @Override + public String toString() + { + return target.getName() + " = " + source; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((source == null) ? 0 : source.hashCode()); + result = prime * result + ((target == null) ? 0 : target.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Assign other = (Assign) obj; + if (source == null) + { + if (other.source != null) + return false; + } else if (!source.equals(other.source)) + return false; + if (target == null) + { + if (other.target != null) + return false; + } else if (!target.equals(other.target)) + return false; + return true; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/ComponentReference.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/ComponentReference.java new file mode 100644 index 00000000..f676661a --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/ComponentReference.java @@ -0,0 +1,132 @@ +package net.mograsim.logic.model.verilog.model.statements; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration; +import net.mograsim.logic.model.verilog.model.signals.IOPort; +import net.mograsim.logic.model.verilog.model.signals.Signal; + +public class ComponentReference extends Statement +{ + private final String name; + private final VerilogComponentDeclaration referencedComponent; + private final List arguments; + + public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List arguments) + { + this.name = Objects.requireNonNull(name); + this.referencedComponent = Objects.requireNonNull(referencedComponent); + this.arguments = List.copyOf(arguments); + + check(); + } + + private void check() + { + List ioPorts = referencedComponent.getIOPorts(); + if (ioPorts.size() != arguments.size()) + throw new IllegalArgumentException( + "Incorrect nubmer of arguments given: " + arguments.size() + ", but should be " + ioPorts.size()); + + for (int i = 0; i < ioPorts.size(); i++) + if (ioPorts.get(i).getWidth() != arguments.get(i).getWidth()) + throw new IllegalArgumentException("Argument #" + i + "(" + ioPorts.get(i) + "): Incorrect width: " + + arguments.get(i).getWidth() + ", but shoud be " + ioPorts.get(i).getWidth()); + } + + public String getName() + { + return name; + } + + public VerilogComponentDeclaration getReferencedComponent() + { + return referencedComponent; + } + + public List getArguments() + { + return arguments; + } + + @Override + public String toVerilogCode() + { + StringBuilder sb = new StringBuilder(); + + sb.append(referencedComponent.getID() + " " + name); + sb.append(arguments.stream().map(Signal::toReferenceVerilogCode).collect(Collectors.joining(", ", "(", ")"))); + sb.append(";"); + + return sb.toString(); + } + + @Override + public Set getDefinedNames() + { + return Set.of(name); + } + + @Override + public Set getDefinedSignals() + { + return Set.of(); + } + + @Override + public Set getReferencedSignals() + { + return Set.copyOf(arguments); + } + + @Override + public String toString() + { + return name + "[" + referencedComponent.getID() + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((arguments == null) ? 0 : arguments.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((referencedComponent == null) ? 0 : referencedComponent.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ComponentReference other = (ComponentReference) obj; + if (arguments == null) + { + if (other.arguments != null) + return false; + } else if (!arguments.equals(other.arguments)) + return false; + if (name == null) + { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (referencedComponent == null) + { + if (other.referencedComponent != null) + return false; + } else if (!referencedComponent.equals(other.referencedComponent)) + return false; + return true; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Statement.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Statement.java new file mode 100644 index 00000000..2f95ebe7 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/Statement.java @@ -0,0 +1,16 @@ +package net.mograsim.logic.model.verilog.model.statements; + +import java.util.Set; + +import net.mograsim.logic.model.verilog.model.signals.Signal; + +public abstract class Statement +{ + public abstract String toVerilogCode(); + + public abstract Set getDefinedNames(); + + public abstract Set getDefinedSignals(); + + public abstract Set getReferencedSignals(); +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/WireDeclaration.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/WireDeclaration.java new file mode 100644 index 00000000..4d949b48 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/model/statements/WireDeclaration.java @@ -0,0 +1,80 @@ +package net.mograsim.logic.model.verilog.model.statements; + +import java.util.Objects; +import java.util.Set; + +import net.mograsim.logic.model.verilog.model.signals.Signal; +import net.mograsim.logic.model.verilog.model.signals.Wire; + +public class WireDeclaration extends Statement +{ + private final Wire wire; + + public WireDeclaration(Wire wire) + { + this.wire = Objects.requireNonNull(wire); + } + + public Wire getWire() + { + return wire; + } + + @Override + public String toVerilogCode() + { + return wire.toDeclarationVerilogCode(); + } + + @Override + public Set getDefinedNames() + { + return Set.of(wire.getName()); + } + + @Override + public Set getDefinedSignals() + { + return Set.of(wire); + } + + @Override + public Set getReferencedSignals() + { + return Set.of(); + } + + @Override + public String toString() + { + return "decl[" + wire.toString() + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((wire == null) ? 0 : wire.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + WireDeclaration other = (WireDeclaration) obj; + if (wire == null) + { + if (other.wire != null) + return false; + } else if (!wire.equals(other.wire)) + return false; + return true; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/CollectionsUtils.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/CollectionsUtils.java new file mode 100644 index 00000000..6d118c35 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/CollectionsUtils.java @@ -0,0 +1,19 @@ +package net.mograsim.logic.model.verilog.utils; + +import java.util.HashSet; +import java.util.Set; + +public class CollectionsUtils +{ + private CollectionsUtils() + { + } + + public static Set union(Set a, Set b) + { + Set union = new HashSet<>(); + union.addAll(a); + union.addAll(b); + return Set.copyOf(union); + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/IdentifierGenerator.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/IdentifierGenerator.java new file mode 100644 index 00000000..b35d8a62 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/IdentifierGenerator.java @@ -0,0 +1,46 @@ +package net.mograsim.logic.model.verilog.utils; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Function; + +public class IdentifierGenerator +{ + private final Function sanitizer; + private final Set usedIdentifiers; + + public IdentifierGenerator() + { + this(Function.identity()); + } + + public IdentifierGenerator(Function sanitizer) + { + this.usedIdentifiers = new HashSet<>(); + this.sanitizer = sanitizer; + } + + public IdentifierGenerator(Collection forbiddenIDs) + { + this(forbiddenIDs, Function.identity()); + } + + public IdentifierGenerator(Collection forbiddenIDs, Function sanitizer) + { + this.usedIdentifiers = new HashSet<>(forbiddenIDs); + this.sanitizer = sanitizer; + } + + public String generateID(String hint) + { + String sanitized = sanitizer.apply(hint); + if (usedIdentifiers.add(sanitized)) + return sanitized; + + String idBase = sanitized.isEmpty() ? "_" : sanitized; + for (int i = 0;; i++) + if (usedIdentifiers.add(idBase + i)) + return idBase + i; + } +} diff --git a/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/UnionFind.java b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/UnionFind.java new file mode 100644 index 00000000..c78f1ee1 --- /dev/null +++ b/plugins/net.mograsim.logic.model.verilog/src/net/mograsim/logic/model/verilog/utils/UnionFind.java @@ -0,0 +1,103 @@ +package net.mograsim.logic.model.verilog.utils; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class UnionFind +{ + private final Map> elements; + + public UnionFind() + { + this.elements = new HashMap<>(); + } + + public UnionFindElement getElement(E e) + { + return elements.computeIfAbsent(e, UnionFindElement::new); + } + + public E find(E e) + { + return find(getElement(e)).getE(); + } + + public static UnionFindElement find(UnionFindElement elem) + { + if (elem == elem.parent) + return elem; + return elem.parent = find(elem.parent); + } + + public E union(E e1, E e2) + { + return union(getElement(e1), getElement(e2)).getE(); + } + + public static UnionFindElement union(UnionFindElement e1, UnionFindElement e2) + { + UnionFindElement e1Root = find(e1); + UnionFindElement e2Root = find(e2); + + if (e1Root == e2Root) + return e1Root; + + if (e1Root.rank < e2Root.rank) + return e1Root.parent = e2Root; + else if (e1Root.rank > e2Root.rank) + return e2Root.parent = e1Root; + else + { + e2Root.rank++; + return e1Root.parent = e2Root; + } + } + + public E unionAll(Collection es) + { + Iterator it = es.iterator(); + if (!it.hasNext()) + return null; + + UnionFindElement representant = getElement(it.next()); + + while (it.hasNext()) + representant = union(representant, getElement(it.next())); + + return representant.getE(); + } + + public static UnionFindElement unionAll2(Collection> es) + { + Iterator> it = es.iterator(); + if (!it.hasNext()) + return null; + + UnionFindElement representant = it.next(); + + while (it.hasNext()) + representant = union(representant, it.next()); + + return representant; + } + + public static class UnionFindElement + { + private final E e; + private UnionFindElement parent; + private int rank; + + private UnionFindElement(E e) + { + this.e = e; + this.parent = this; + } + + public E getE() + { + return e; + } + } +} diff --git a/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java b/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java index 08712a0d..a2e46d9b 100644 --- a/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java +++ b/tests/net.mograsim.logic.model.verilog.tests/src/net/mograsim/logic/model/verilog/examples/ExportAm2900.java @@ -27,15 +27,14 @@ import net.mograsim.logic.model.model.components.atomic.ModelNandGate; import net.mograsim.logic.model.model.components.atomic.ModelTextComponent; import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer; import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer.ModelTriStateBufferParams; -import net.mograsim.logic.model.model.wires.ModelWireCrossPoint; import net.mograsim.logic.model.serializing.IdentifyParams; import net.mograsim.logic.model.serializing.IndirectModelComponentCreator; import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping; import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter; -import net.mograsim.logic.model.verilog.helper.UnionFind; -import net.mograsim.logic.model.verilog.model.IOPort; import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration; import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation; +import net.mograsim.logic.model.verilog.model.signals.IOPort; +import net.mograsim.logic.model.verilog.utils.UnionFind; public class ExportAm2900 { @@ -76,12 +75,6 @@ public class ExportAm2900 new ModelTriStateBuffer(model, new ModelTriStateBufferParams(12, Orientation.DOWN)), // new ModelTriStateBuffer(model, new ModelTriStateBufferParams(16, Orientation.LEFT)), // new ModelTriStateBuffer(model, new ModelTriStateBufferParams(16, Orientation.RIGHT_ALT)), // - new ModelWireCrossPoint(model, 1), // - new ModelWireCrossPoint(model, 2), // - new ModelWireCrossPoint(model, 4), // - new ModelWireCrossPoint(model, 9), // - new ModelWireCrossPoint(model, 12), // - new ModelWireCrossPoint(model, 16), // new ModelClock(model, new ModelClockParams(7000, Orientation.RIGHT)), // new ModelTextComponent(model, "A bus"), // new ModelTextComponent(model, "MPM addr"), //