Improvements in the ModelComponentToVerilogConverter:
[Mograsim.git] / plugins / net.mograsim.logic.model.verilog / src / net / mograsim / logic / model / verilog / model / VerilogComponentImplementation.java
index fe33694..a7a9de2 100644 (file)
@@ -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<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()
@@ -60,19 +48,9 @@ public class VerilogComponentImplementation
                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()
@@ -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;
        }