import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
import com.google.gson.JsonElement;
private final VerilogComponentDeclaration verilogComponentDeclaration;
private final Set<VerilogEmulatedModelPin> pinMapping;
+ private final Set<Set<PinNameBit>> internallyConnectedPins;
private final Map<PinNameBit, VerilogEmulatedModelPin> prePinMapping;
private final Map<PinNameBit, VerilogEmulatedModelPin> outPinMapping;
private final Map<PinNameBit, VerilogEmulatedModelPin> resPinMapping;
this.reversePinMapping = checkAndCalculateReversePinMapping();
+ this.internallyConnectedPins = calculateInternallyConnectedPins();
this.prePinMapping = filterPinMapping(Type.PRE);
this.outPinMapping = filterPinMapping(Type.OUT);
this.resPinMapping = filterPinMapping(Type.RES);
return reverseMapping;
}
+ private Set<Set<PinNameBit>> calculateInternallyConnectedPins()
+ {
+ return pinMapping.stream().map(VerilogEmulatedModelPin::getPinbits).collect(Collectors.toUnmodifiableSet());
+ }
+
private Map<PinNameBit, VerilogEmulatedModelPin> filterPinMapping(Type filteredType)
{
Map<PinNameBit, VerilogEmulatedModelPin> result = new HashMap<>();
return verilogComponentDeclaration;
}
+ public Set<Set<PinNameBit>> getInternallyConnectedPins()
+ {
+ return internallyConnectedPins;
+ }
+
public Set<VerilogEmulatedModelPin> getPinMapping()
{
return pinMapping;
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;
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)
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
{
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<PinBit> connectedPins = findConnectedPins(modelComponentC);
+ UnionFind<PinBit> 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<PinBit> findConnectedPins(SubmodelComponent modelComponent)
+ private UnionFind<PinBit> findConnectedPins(SubmodelComponent modelComponent)
{
UnionFind<PinBit> connectedPins = new UnionFind<>();
for (ModelWire w : modelComponent.submodel.getWiresByName().values())
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<PinNameBit> 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<PinBit> connectedPins, String modelID, JsonElement params)
+ private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent,
+ UnionFind<PinBit> connectedPins, String modelID, JsonElement params, String verilogID)
{
// TODO this is probably slow
Map<PinBit, PinNameBit> representantMapping = new HashMap<>();
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,
Map<PinBit, Signal> currentPreSignals = new HashMap<>();
Map<PinBit, NamedSignal> finalOutSignals = new HashMap<>();
Map<PinBit, NamedSignal> 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<PinNameBit> 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<Wire> internalWires = new HashSet<>();
- Set<ComponentReference> subcomponents = new HashSet<>();
+ List<Statement> 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<Signal> arguments = new ArrayList<>(parameterCount);
for (int i = 0; i < parameterCount; i++)
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)
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);
}
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<Assign> assigns = new HashSet<>();
for (Entry<PinBit, NamedSignal> 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<VerilogComponentImplementation> getVerilogComponents()
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;
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()
{
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
{
+++ /dev/null
-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<String, String> sanitizer;
- private final Set<String> usedIdentifiers;
-
- public IdentifierGenerator()
- {
- this(Function.identity());
- }
-
- public IdentifierGenerator(Function<String, String> sanitizer)
- {
- this.usedIdentifiers = new HashSet<>();
- this.sanitizer = sanitizer;
- }
-
- public IdentifierGenerator(Collection<String> forbiddenIDs)
- {
- this(forbiddenIDs, Function.identity());
- }
-
- public IdentifierGenerator(Collection<String> forbiddenIDs, Function<String, String> 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;
- }
-}
+++ /dev/null
-package net.mograsim.logic.model.verilog.helper;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class UnionFind<E>
-{
- private final Map<E, UnionFindElement<E>> elements;
-
- public UnionFind()
- {
- this.elements = new HashMap<>();
- }
-
- public UnionFindElement<E> getElement(E e)
- {
- return elements.computeIfAbsent(e, UnionFindElement::new);
- }
-
- public E find(E e)
- {
- return find(getElement(e)).getE();
- }
-
- public static <E> UnionFindElement<E> find(UnionFindElement<E> 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 <E> UnionFindElement<E> union(UnionFindElement<E> e1, UnionFindElement<E> e2)
- {
- UnionFindElement<E> e1Root = find(e1);
- UnionFindElement<E> 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<E>
- {
- private final E e;
- private UnionFindElement<E> parent;
- private int rank;
-
- private UnionFindElement(E e)
- {
- this.e = e;
- this.parent = this;
- }
-
- public E getE()
- {
- return e;
- }
- }
-}
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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<Signal> arguments;
-
- public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List<Signal> arguments)
- {
- this.name = Objects.requireNonNull(name);
- this.referencedComponent = Objects.requireNonNull(referencedComponent);
- this.arguments = List.copyOf(arguments);
-
- check();
- }
-
- private void check()
- {
- List<IOPort> 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<Signal> 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;
- }
-}
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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();
-}
+++ /dev/null
-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();
- }
-}
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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();
- }
-}
+++ /dev/null
-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;
- }
-}
import java.util.Objects;
import java.util.Set;
+import net.mograsim.logic.model.verilog.model.signals.IOPort;
+
public class VerilogComponentDeclaration
{
private final String id;
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<Wire> internalWires;
- private final Set<Assign> assigns;
- private final Set<ComponentReference> subcomponents;
+ private final List<Statement> statements;
- public VerilogComponentImplementation(VerilogComponentDeclaration declaration, Set<Wire> internalWires, Set<Assign> assigns,
- Set<ComponentReference> subcomponents)
+ public VerilogComponentImplementation(VerilogComponentDeclaration declaration, List<Statement> 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<String> 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<Signal> allSignals = new HashSet<>();
allSignals.addAll(declaration.getIOPorts());
- allSignals.addAll(internalWires);
+ statements.stream().map(Statement::getDefinedSignals).forEach(allSignals::addAll);
- Set<String> 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<Signal> 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()
return declaration;
}
- public Set<Wire> getInternalWires()
- {
- return internalWires;
- }
-
- public Set<Assign> getAssigns()
- {
- return assigns;
- }
-
- public Set<ComponentReference> getSubcomponents()
+ public List<Statement> getStatements()
{
- return subcomponents;
+ return statements;
}
public String toVerilogCode()
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");
{
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;
}
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;
}
+++ /dev/null
-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() + ";";
- }
-}
--- /dev/null
+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<Signal> getReferencedSignals();
+}
--- /dev/null
+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<Signal> getReferencedSignals()
+ {
+ return Set.of(referencedSignal);
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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();
+}
--- /dev/null
+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();
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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();
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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() + ";";
+ }
+}
--- /dev/null
+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<String> getDefinedNames()
+ {
+ return Set.of();
+ }
+
+ @Override
+ public Set<Signal> getDefinedSignals()
+ {
+ return Set.of();
+ }
+
+ @Override
+ public Set<Signal> 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;
+ }
+}
--- /dev/null
+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<Signal> arguments;
+
+ public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List<Signal> arguments)
+ {
+ this.name = Objects.requireNonNull(name);
+ this.referencedComponent = Objects.requireNonNull(referencedComponent);
+ this.arguments = List.copyOf(arguments);
+
+ check();
+ }
+
+ private void check()
+ {
+ List<IOPort> 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<Signal> 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<String> getDefinedNames()
+ {
+ return Set.of(name);
+ }
+
+ @Override
+ public Set<Signal> getDefinedSignals()
+ {
+ return Set.of();
+ }
+
+ @Override
+ public Set<Signal> 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;
+ }
+}
--- /dev/null
+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<String> getDefinedNames();
+
+ public abstract Set<Signal> getDefinedSignals();
+
+ public abstract Set<Signal> getReferencedSignals();
+}
--- /dev/null
+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<String> getDefinedNames()
+ {
+ return Set.of(wire.getName());
+ }
+
+ @Override
+ public Set<Signal> getDefinedSignals()
+ {
+ return Set.of(wire);
+ }
+
+ @Override
+ public Set<Signal> 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;
+ }
+}
--- /dev/null
+package net.mograsim.logic.model.verilog.utils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class CollectionsUtils
+{
+ private CollectionsUtils()
+ {
+ }
+
+ public static <E> Set<E> union(Set<E> a, Set<E> b)
+ {
+ Set<E> union = new HashSet<>();
+ union.addAll(a);
+ union.addAll(b);
+ return Set.copyOf(union);
+ }
+}
--- /dev/null
+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<String, String> sanitizer;
+ private final Set<String> usedIdentifiers;
+
+ public IdentifierGenerator()
+ {
+ this(Function.identity());
+ }
+
+ public IdentifierGenerator(Function<String, String> sanitizer)
+ {
+ this.usedIdentifiers = new HashSet<>();
+ this.sanitizer = sanitizer;
+ }
+
+ public IdentifierGenerator(Collection<String> forbiddenIDs)
+ {
+ this(forbiddenIDs, Function.identity());
+ }
+
+ public IdentifierGenerator(Collection<String> forbiddenIDs, Function<String, String> 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;
+ }
+}
--- /dev/null
+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<E>
+{
+ private final Map<E, UnionFindElement<E>> elements;
+
+ public UnionFind()
+ {
+ this.elements = new HashMap<>();
+ }
+
+ public UnionFindElement<E> getElement(E e)
+ {
+ return elements.computeIfAbsent(e, UnionFindElement::new);
+ }
+
+ public E find(E e)
+ {
+ return find(getElement(e)).getE();
+ }
+
+ public static <E> UnionFindElement<E> find(UnionFindElement<E> 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 <E> UnionFindElement<E> union(UnionFindElement<E> e1, UnionFindElement<E> e2)
+ {
+ UnionFindElement<E> e1Root = find(e1);
+ UnionFindElement<E> 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<E> es)
+ {
+ Iterator<E> it = es.iterator();
+ if (!it.hasNext())
+ return null;
+
+ UnionFindElement<E> representant = getElement(it.next());
+
+ while (it.hasNext())
+ representant = union(representant, getElement(it.next()));
+
+ return representant.getE();
+ }
+
+ public static <E> UnionFindElement<E> unionAll2(Collection<UnionFindElement<E>> es)
+ {
+ Iterator<UnionFindElement<E>> it = es.iterator();
+ if (!it.hasNext())
+ return null;
+
+ UnionFindElement<E> representant = it.next();
+
+ while (it.hasNext())
+ representant = union(representant, it.next());
+
+ return representant;
+ }
+
+ public static class UnionFindElement<E>
+ {
+ private final E e;
+ private UnionFindElement<E> parent;
+ private int rank;
+
+ private UnionFindElement(E e)
+ {
+ this.e = e;
+ this.parent = this;
+ }
+
+ public E getE()
+ {
+ return e;
+ }
+ }
+}
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
{
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"), //