Improvements in the ModelComponentToVerilogConverter:
[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.HashSet;
4 import java.util.List;
5 import java.util.Objects;
6 import java.util.Set;
7 import java.util.stream.Collectors;
8
9 import net.mograsim.logic.model.verilog.model.signals.IOPort;
10 import net.mograsim.logic.model.verilog.model.signals.Signal;
11 import net.mograsim.logic.model.verilog.model.statements.Statement;
12
13 public class VerilogComponentImplementation
14 {
15         private final VerilogComponentDeclaration declaration;
16         private final List<Statement> statements;
17
18         public VerilogComponentImplementation(VerilogComponentDeclaration declaration, List<Statement> statements)
19         {
20                 this.declaration = Objects.requireNonNull(declaration);
21                 this.statements = List.copyOf(statements);
22
23                 check();
24         }
25
26         private void check()
27         {
28                 Set<String> usedNames = declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toCollection(HashSet::new));
29
30                 for (Statement statement : statements)
31                         for (String definedName : statement.getDefinedNames())
32                                 if (!usedNames.add(definedName))
33                                         throw new IllegalArgumentException("Name occurs twice: " + definedName);
34
35                 Set<Signal> allSignals = new HashSet<>();
36                 allSignals.addAll(declaration.getIOPorts());
37                 statements.stream().map(Statement::getDefinedSignals).forEach(allSignals::addAll);
38
39                 // do two passes, a signal may be referenced before it is defined
40                 for (Statement statement : statements)
41                         if (!allSignals.containsAll(statement.getReferencedSignals()))
42                                 throw new IllegalArgumentException("Referenced an unknown signal: "
43                                                 + statement.getReferencedSignals().stream().filter(s -> !allSignals.contains(s)).findAny().get());
44         }
45
46         public VerilogComponentDeclaration getDeclaration()
47         {
48                 return declaration;
49         }
50
51         public List<Statement> getStatements()
52         {
53                 return statements;
54         }
55
56         public String toVerilogCode()
57         {
58                 StringBuilder sb = new StringBuilder();
59
60                 sb.append("module " + declaration.getID());
61                 sb.append(declaration.getIOPorts().stream().map(IOPort::toDeclarationVerilogCode).collect(Collectors.joining(", ", "(", ")")));
62                 sb.append(";\n\n");
63
64                 for (Statement statement : statements)
65                         sb.append(statement.toVerilogCode() + "\n");
66                 if (!statements.isEmpty())
67                         sb.append("\n");
68
69                 sb.append("endmodule\n");
70
71                 return sb.toString();
72         }
73
74         @Override
75         public String toString()
76         {
77                 return "Implementation[" + declaration.getID() + "]";
78         }
79
80         @Override
81         public int hashCode()
82         {
83                 final int prime = 31;
84                 int result = 1;
85                 result = prime * result + ((declaration == null) ? 0 : declaration.hashCode());
86                 result = prime * result + ((statements == null) ? 0 : statements.hashCode());
87                 return result;
88         }
89
90         @Override
91         public boolean equals(Object obj)
92         {
93                 if (this == obj)
94                         return true;
95                 if (obj == null)
96                         return false;
97                 if (getClass() != obj.getClass())
98                         return false;
99                 VerilogComponentImplementation other = (VerilogComponentImplementation) obj;
100                 if (declaration == null)
101                 {
102                         if (other.declaration != null)
103                                 return false;
104                 } else if (!declaration.equals(other.declaration))
105                         return false;
106                 if (statements == null)
107                 {
108                         if (other.statements != null)
109                                 return false;
110                 } else if (!statements.equals(other.statements))
111                         return false;
112                 return true;
113         }
114 }