fe336948d17f465f293aaeb39c49da3e6e3248f1
[Mograsim.git] / plugins / net.mograsim.logic.model.verilog / src / net / mograsim / logic / model / verilog / model / VerilogComponentImplementation.java
1 package net.mograsim.logic.model.verilog.model;
2
3 import java.util.ArrayList;
4 import java.util.HashSet;
5 import java.util.List;
6 import java.util.Objects;
7 import java.util.Set;
8 import java.util.stream.Collectors;
9
10 import net.mograsim.logic.model.verilog.model.Signal.Type;
11
12 public class VerilogComponentImplementation
13 {
14         private final VerilogComponentDeclaration declaration;
15         private final Set<Wire> internalWires;
16         private final Set<Assign> assigns;
17         private final Set<ComponentReference> subcomponents;
18
19         public VerilogComponentImplementation(VerilogComponentDeclaration declaration, Set<Wire> internalWires, Set<Assign> assigns,
20                         Set<ComponentReference> subcomponents)
21         {
22                 this.declaration = Objects.requireNonNull(declaration);
23                 this.internalWires = Set.copyOf(internalWires);
24                 this.assigns = Set.copyOf(assigns);
25                 this.subcomponents = Set.copyOf(subcomponents);
26
27                 check();
28         }
29
30         private void check()
31         {
32                 Set<Signal> allSignals = new HashSet<>();
33                 allSignals.addAll(declaration.getIOPorts());
34                 allSignals.addAll(internalWires);
35
36                 Set<String> usedNames = declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toCollection(HashSet::new));
37
38                 for (Wire wire : internalWires)
39                         if (!usedNames.add(wire.getName()))
40                                 throw new IllegalArgumentException("Name occurs twice: " + wire.getName());
41
42                 for (Assign assign : assigns)
43                         if (!allSignals.contains(assign.getSource()) || !allSignals.contains(assign.getTarget()))
44                                 throw new IllegalArgumentException("Referenced an unknown signal: " + assign.getSource());
45
46                 for (ComponentReference subcomponent : subcomponents)
47                         if (!usedNames.add(subcomponent.getName()))
48                                 throw new IllegalArgumentException("Name occurs twice: " + subcomponent.getName());
49                         else if (!subcomponent.getArguments().stream().filter(s -> s.getType() != Type.CONSTANT).allMatch(allSignals::contains))
50                         {
51                                 List<Signal> unknownSignals = new ArrayList<>(subcomponent.getArguments());
52                                 unknownSignals.removeAll(allSignals);
53                                 // we know this list contains at least one element
54                                 throw new IllegalArgumentException("Assigning a signal not in the component: " + unknownSignals.get(0));
55                         }
56         }
57
58         public VerilogComponentDeclaration getDeclaration()
59         {
60                 return declaration;
61         }
62
63         public Set<Wire> getInternalWires()
64         {
65                 return internalWires;
66         }
67
68         public Set<Assign> getAssigns()
69         {
70                 return assigns;
71         }
72
73         public Set<ComponentReference> getSubcomponents()
74         {
75                 return subcomponents;
76         }
77
78         public String toVerilogCode()
79         {
80                 StringBuilder sb = new StringBuilder();
81
82                 sb.append("module " + declaration.getID());
83                 sb.append(declaration.getIOPorts().stream().map(IOPort::toDeclarationVerilogCode).collect(Collectors.joining(", ", "(", ")")));
84                 sb.append(";\n\n");
85
86                 for (Wire wire : internalWires)
87                         sb.append(wire.toDeclarationVerilogCode() + "\n");
88                 if (!internalWires.isEmpty())
89                         sb.append("\n");
90
91                 for (Assign assign : assigns)
92                         sb.append(assign.toVerilogCode() + "\n");
93                 if (!assigns.isEmpty())
94                         sb.append("\n");
95
96                 for (ComponentReference subcomponent : subcomponents)
97                         sb.append(subcomponent.toVerilogCode() + "\n");
98                 if (!subcomponents.isEmpty())
99                         sb.append("\n");
100
101                 sb.append("endmodule\n");
102
103                 return sb.toString();
104         }
105
106         @Override
107         public String toString()
108         {
109                 return "Implementation[" + declaration.getID() + "]";
110         }
111
112         @Override
113         public int hashCode()
114         {
115                 final int prime = 31;
116                 int result = 1;
117                 result = prime * result + ((assigns == null) ? 0 : assigns.hashCode());
118                 result = prime * result + ((declaration == null) ? 0 : declaration.hashCode());
119                 result = prime * result + ((internalWires == null) ? 0 : internalWires.hashCode());
120                 result = prime * result + ((subcomponents == null) ? 0 : subcomponents.hashCode());
121                 return result;
122         }
123
124         @Override
125         public boolean equals(Object obj)
126         {
127                 if (this == obj)
128                         return true;
129                 if (obj == null)
130                         return false;
131                 if (getClass() != obj.getClass())
132                         return false;
133                 VerilogComponentImplementation other = (VerilogComponentImplementation) obj;
134                 if (assigns == null)
135                 {
136                         if (other.assigns != null)
137                                 return false;
138                 } else if (!assigns.equals(other.assigns))
139                         return false;
140                 if (declaration == null)
141                 {
142                         if (other.declaration != null)
143                                 return false;
144                 } else if (!declaration.equals(other.declaration))
145                         return false;
146                 if (internalWires == null)
147                 {
148                         if (other.internalWires != null)
149                                 return false;
150                 } else if (!internalWires.equals(other.internalWires))
151                         return false;
152                 if (subcomponents == null)
153                 {
154                         if (other.subcomponents != null)
155                                 return false;
156                 } else if (!subcomponents.equals(other.subcomponents))
157                         return false;
158                 return true;
159         }
160 }