WireEnd functionality split into ReadEnd and ReadWriteEnd
[Mograsim.git] / era.mi / src / era / mi / logic / components / Mux.java
1 package era.mi.logic.components;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Arrays;\r
5 import java.util.Collections;\r
6 import java.util.List;\r
7 \r
8 import era.mi.logic.wires.Wire;\r
9 import era.mi.logic.wires.Wire.ReadEnd;\r
10 import era.mi.logic.wires.Wire.ReadWriteEnd;\r
11 \r
12 /**\r
13  * Models a multiplexer. Takes an arbitrary amount of input {@link Wire}s, one of which, as determined by select, is put through to the\r
14  * output.\r
15  * \r
16  * @author Fabian Stemmler\r
17  *\r
18  */\r
19 public class Mux extends BasicComponent\r
20 {\r
21         private ReadEnd select;\r
22         private ReadWriteEnd out;\r
23         private ReadEnd[] inputs;\r
24         private final int outputSize;\r
25 \r
26         /**\r
27          * Input {@link Wire}s and out must be of uniform length\r
28          * \r
29          * @param out    Must be of uniform length with all inputs.\r
30          * @param select Indexes the input array which is to be mapped to the output. Must have enough bits to index all inputs.\r
31          * @param inputs One of these inputs is mapped to the output, depending on the select bits\r
32          */\r
33         public Mux(int processTime, ReadWriteEnd out, ReadEnd select, ReadEnd... inputs)\r
34         {\r
35                 super(processTime);\r
36                 outputSize = out.length();\r
37 \r
38                 this.inputs = inputs.clone();\r
39                 for (int i = 0; i < this.inputs.length; i++)\r
40                 {\r
41                         if (inputs[i].length() != outputSize)\r
42                                 throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");\r
43                         inputs[i].addObserver(this);\r
44                 }\r
45 \r
46                 this.select = select;\r
47                 select.addObserver(this);\r
48 \r
49                 int maxInputs = 1 << select.length();\r
50                 if (this.inputs.length > maxInputs)\r
51                         throw new IllegalArgumentException("There are more inputs (" + this.inputs.length + ") to the MUX than supported by "\r
52                                         + select.length() + " select bits (" + maxInputs + ").");\r
53 \r
54                 this.out = out;\r
55         }\r
56 \r
57         public ReadEnd getOut()\r
58         {\r
59                 return out;\r
60         }\r
61 \r
62         public ReadEnd getSelect()\r
63         {\r
64                 return select;\r
65         }\r
66 \r
67         @Override\r
68         public void compute()\r
69         {\r
70                 int selectValue;\r
71                 if (!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length)\r
72                 {\r
73                         out.clearSignals();\r
74                         return;\r
75                 }\r
76 \r
77                 ReadEnd active = inputs[selectValue];\r
78                 out.feedSignals(active.getValues());\r
79         }\r
80 \r
81         @Override\r
82         public List<ReadEnd> getAllInputs()\r
83         {\r
84                 ArrayList<ReadEnd> wires = new ArrayList<ReadEnd>(Arrays.asList(inputs));\r
85                 wires.add(select);\r
86                 return Collections.unmodifiableList(wires);\r
87         }\r
88 \r
89         @Override\r
90         public List<ReadWriteEnd> getAllOutputs()\r
91         {\r
92                 return List.of(out);\r
93         }\r
94 }\r