1 /*
2  * Copyright (c) 2016 Helmut Neemann
3  * Use of this source code is governed by the GPL v3 license
4  * that can be found in the LICENSE file.
5  */
6 package de.neemann.digital.builder.circuit;
7 
8 import de.neemann.digital.TestExecuter;
9 import de.neemann.digital.analyse.ModelAnalyser;
10 import de.neemann.digital.analyse.TruthTable;
11 import de.neemann.digital.analyse.expression.Constant;
12 import de.neemann.digital.analyse.expression.Expression;
13 import de.neemann.digital.analyse.expression.NamedExpression;
14 import de.neemann.digital.analyse.expression.Variable;
15 import de.neemann.digital.analyse.parser.ParseException;
16 import de.neemann.digital.analyse.parser.Parser;
17 import de.neemann.digital.builder.BuilderException;
18 import de.neemann.digital.core.NodeException;
19 import de.neemann.digital.core.element.Keys;
20 import de.neemann.digital.core.io.Const;
21 import de.neemann.digital.core.io.In;
22 import de.neemann.digital.core.io.Out;
23 import de.neemann.digital.core.memory.LookUpTable;
24 import de.neemann.digital.draw.elements.Circuit;
25 import de.neemann.digital.draw.elements.PinException;
26 import de.neemann.digital.draw.elements.Tunnel;
27 import de.neemann.digital.draw.elements.VisualElement;
28 import de.neemann.digital.draw.library.ElementLibrary;
29 import de.neemann.digital.draw.library.ElementNotFoundException;
30 import de.neemann.digital.draw.model.ModelCreator;
31 import de.neemann.digital.draw.shapes.ShapeFactory;
32 import de.neemann.digital.gui.components.table.BuilderExpressionCreator;
33 import de.neemann.digital.gui.components.table.ExpressionCreator;
34 import de.neemann.digital.gui.components.table.ExpressionListenerStore;
35 import de.neemann.digital.integration.ToBreakRunner;
36 import junit.framework.TestCase;
37 
38 import java.io.IOException;
39 import java.util.ArrayList;
40 import java.util.List;
41 
42 import static de.neemann.digital.analyse.expression.Not.not;
43 import static de.neemann.digital.analyse.expression.Operation.and;
44 import static de.neemann.digital.analyse.expression.Operation.or;
45 
46 /**
47  *
48  */
49 public class CircuitBuilderTest extends TestCase {
50 
testBuilderCombinatorial()51     public void testBuilderCombinatorial() throws Exception {
52 
53         Variable a = new Variable("a");
54         Variable b = new Variable("b");
55 
56         // xor
57         Expression y = and(or(a, b), not(and(a, b)));
58 
59         ElementLibrary library = new ElementLibrary();
60         Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
61                 .addCombinatorial("y", y)
62                 .createCircuit();
63 
64         ModelCreator m = new ModelCreator(circuit, library);
65 
66         TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
67         te.check(0, 0, 0);
68         te.check(0, 1, 1);
69         te.check(1, 0, 1);
70         te.check(1, 1, 0);
71     }
72 
testBuilderSequential()73     public void testBuilderSequential() throws Exception {
74         Variable y0 = new Variable("Y_0");
75         Variable y1 = new Variable("Y_1");
76 
77         // counter
78         Expression y0s = not(y0);
79         Expression y1s = or(and(not(y0), y1), and(y0, not(y1)));
80 
81         ElementLibrary library = new ElementLibrary();
82         Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
83                 .addSequential("Y_0", y0s)
84                 .addSequential("Y_1", y1s)
85                 .createCircuit();
86 
87         ModelCreator m = new ModelCreator(circuit, library);
88         TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
89         te.check(0, 0);
90         te.checkC(1, 0);
91         te.checkC(0, 1);
92         te.checkC(1, 1);
93         te.checkC(0, 0);
94     }
95 
testBuilderSequentialLUT()96     public void testBuilderSequentialLUT() throws Exception {
97         Variable y0 = new Variable("Y_0");
98         Variable y1 = new Variable("Y_1");
99         Variable y2 = new Variable("Y_2");
100 
101         // counter
102         Expression y0s = not(y0);
103         Expression y1s = or(and(not(y0), y1), and(y0, not(y1)));
104         Expression y2s = or(and(y0, y1, not(y2)), and(not(y0), y2), and(not(y1), y2));
105 
106         ElementLibrary library = new ElementLibrary();
107         Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
108                 .setUseLUTs(true)
109                 .addSequential("Y_0", y0s)
110                 .addSequential("Y_1", y1s)
111                 .addSequential("Y_2", y2s)
112                 .createCircuit();
113 
114         final ArrayList<VisualElement> el = circuit.getElements();
115         assertEquals(19, el.size());
116         assertEquals(1, el.stream().filter(visualElement -> visualElement.equalsDescription(LookUpTable.DESCRIPTION)).count());
117 
118         ModelCreator m = new ModelCreator(circuit, library);
119         TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
120         te.check(0, 0, 0);
121         te.checkC(1, 0, 0);
122         te.checkC(0, 1, 0);
123         te.checkC(1, 1, 0);
124         te.checkC(0, 0, 1);
125         te.checkC(1, 0, 1);
126         te.checkC(0, 1, 1);
127         te.checkC(1, 1, 1);
128         te.checkC(0, 0, 0);
129     }
130 
testBuilderSequentialJK_JequalsK()131     public void testBuilderSequentialJK_JequalsK() throws Exception {
132         Variable y0 = new Variable("Y_0");
133         Variable y1 = new Variable("Y_1");
134 
135         // counter
136         Expression y0s = not(y0);
137         Expression y1s = or(and(not(y0), y1), and(y0, not(y1)));
138 
139         ElementLibrary library = new ElementLibrary();
140         Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
141                 .setUseJK(true)
142                 .addSequential("Y_0", y0s)
143                 .addSequential("Y_1", y1s)
144                 .createCircuit();
145 
146         ModelCreator m = new ModelCreator(circuit, library);
147         TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
148         te.check(0, 0);
149         te.checkC(1, 0);
150         te.checkC(0, 1);
151         te.checkC(1, 1);
152         te.checkC(0, 0);
153     }
154 
testBuilderSequentialJK()155     public void testBuilderSequentialJK() throws Exception {
156         Variable y0 = new Variable("Y_0");
157         Variable y1 = new Variable("Y_1");
158 
159         // counter
160         Expression y0s = not(y0);
161         Expression y1s = or(not(y0), not(y1));
162 
163         ElementLibrary library = new ElementLibrary();
164         Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
165                 .setUseJK(true)
166                 .addSequential("Y_0", y0s)
167                 .addSequential("Y_1", y1s)
168                 .createCircuit();
169 
170         ModelCreator m = new ModelCreator(circuit, library);
171         TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
172         te.check(0, 0);
173         te.checkC(1, 1);
174         te.checkC(0, 0);
175         te.checkC(1, 1);
176         te.checkC(0, 0);
177     }
178 
testBuilderSequentialConstant()179     public void testBuilderSequentialConstant() throws Exception {
180         ElementLibrary library = new ElementLibrary();
181         Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
182                 .addSequential("Y_0", Constant.ONE)
183                 .addSequential("Y_1", Constant.ZERO)
184                 .createCircuit();
185 
186         final ArrayList<VisualElement> el = circuit.getElements();
187         assertEquals(8, el.size());
188         assertEquals(4, el.stream().filter(visualElement -> visualElement.equalsDescription(Tunnel.DESCRIPTION)).count());
189         assertEquals(2, el.stream().filter(visualElement -> visualElement.equalsDescription(Const.DESCRIPTION)).count());
190         assertEquals(2, el.stream().filter(visualElement -> visualElement.equalsDescription(Out.DESCRIPTION)).count());
191     }
192 
testBuilderSequentialConstantJK()193     public void testBuilderSequentialConstantJK() throws Exception {
194         ElementLibrary library = new ElementLibrary();
195         Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
196                 .setUseJK(true)
197                 .addSequential("Y_0", Constant.ONE)
198                 .addSequential("Y_1", Constant.ZERO)
199                 .createCircuit();
200 
201         final ArrayList<VisualElement> el = circuit.getElements();
202         assertEquals(8, el.size());
203         assertEquals(4, el.stream().filter(visualElement -> visualElement.equalsDescription(Tunnel.DESCRIPTION)).count());
204         assertEquals(2, el.stream().filter(visualElement -> visualElement.equalsDescription(Const.DESCRIPTION)).count());
205         assertEquals(2, el.stream().filter(visualElement -> visualElement.equalsDescription(Out.DESCRIPTION)).count());
206     }
207 
testBus()208     public void testBus() throws Exception {
209         final ToBreakRunner runner = new ToBreakRunner("dig/circuitBuilder/busTest.dig", false);
210         // create truth table incl. ModelAnalyzerInfo
211         TruthTable tt = new ModelAnalyser(runner.getModel()).analyse();
212 
213         assertEquals(8, tt.getVars().size());
214         assertEquals(8, tt.getResultCount());
215 
216         // create expressions based on truth table
217         ExpressionListenerStore expr = new ExpressionListenerStore(null);
218         new ExpressionCreator(tt).create(expr);
219 
220         // build a new circuit
221         CircuitBuilder circuitBuilder = new CircuitBuilder(runner.getLibrary().getShapeFactory(), tt.getVars())
222                 .setModelAnalyzerInfo(tt.getModelAnalyzerInfo());
223         new BuilderExpressionCreator(circuitBuilder).create(expr);
224         Circuit circuit = circuitBuilder.createCircuit();
225 
226         // check
227         List<VisualElement> in = circuit.getElements(v -> v.equalsDescription(In.DESCRIPTION));
228         assertEquals(2, in.size());
229         checkPin(in.get(0), "A", "1,2,3,4");
230         checkPin(in.get(1), "B", "5,6,7,8");
231 
232         List<VisualElement> out = circuit.getElements(v -> v.equalsDescription(Out.DESCRIPTION));
233         assertEquals(2, out.size());
234         checkPin(out.get(0), "S", "9,10,11,12");
235         checkPin(out.get(1), "U", "13,14,15,16");
236     }
237 
checkPin(VisualElement e, String label, String pins)238     private void checkPin(VisualElement e, String label, String pins) {
239         assertEquals(label, e.getElementAttributes().getLabel());
240         assertEquals(4, e.getElementAttributes().getBits());
241         assertEquals(pins, e.getElementAttributes().get(Keys.PINNUMBER));
242     }
243 
testIsXor()244     public void testIsXor() {
245         assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 0, 0}));
246         assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 0, 1}));
247         assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 1, 0}));
248         assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 1, 1}));
249         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 0, 0}));
250         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 0, 1}));
251         assertTrue(CircuitBuilder.isXor(new long[]{0, 1, 1, 0}));
252         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 1}));
253         assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 0, 0}));
254         assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 0, 1}));
255         assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 1, 0}));
256         assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 1, 1}));
257         assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 0, 0}));
258         assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 0, 1}));
259         assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 1, 0}));
260         assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 1, 1}));
261 
262         assertTrue(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 0, 0, 1}));
263         assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 1, 0, 1, 0, 0, 1}));
264         assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 1, 0, 1, 0, 0, 1}));
265         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 0, 0, 1, 0, 0, 1}));
266         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 1, 1, 0, 0, 1}));
267         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 0, 0, 0, 1}));
268         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 1, 0, 1}));
269         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 0, 1, 1}));
270         assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 0, 0, 0}));
271     }
272 
testIsXNor()273     public void testIsXNor() {
274         assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 0, 0}));
275         assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 0, 1}));
276         assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 1, 0}));
277         assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 1, 1}));
278         assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 0, 0}));
279         assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 0, 1}));
280         assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 1, 0}));
281         assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 1, 1}));
282         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 0}));
283         assertTrue(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1}));
284         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 1, 0}));
285         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 1, 1}));
286         assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 0, 0}));
287         assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 0, 1}));
288         assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 1, 0}));
289         assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 1, 1}));
290 
291         assertTrue(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 1, 1, 0}));
292         assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 0, 1, 0, 1, 1, 0}));
293         assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 0, 1, 0, 1, 1, 0}));
294         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 1, 1, 0, 1, 1, 0}));
295         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 0, 0, 1, 1, 0}));
296         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 1, 1, 1, 0}));
297         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 0, 1, 0}));
298         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 1, 0, 0}));
299         assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 1, 1, 1}));
300 
301     }
302 
testLocalVar()303     public void testLocalVar() throws IOException, ParseException, BuilderException, ElementNotFoundException, PinException, NodeException {
304         ArrayList<Expression> expList = new Parser("let a1=a+b;\nlet a2=c+d;\nlet y=a1^a2").parse();
305         ElementLibrary library = new ElementLibrary();
306         CircuitBuilder circuitBuilder = new CircuitBuilder(new ShapeFactory(library)).setResolveLocalVars(true);
307         for (Expression exp : expList) {
308             assertTrue(exp instanceof NamedExpression);
309             NamedExpression ne = (NamedExpression) exp;
310             circuitBuilder.addCombinatorial(ne.getName(), ne.getExpression());
311         }
312         Circuit circuit = circuitBuilder.createCircuit();
313         List<VisualElement> outs = circuit.getElements(v -> v.equalsDescription(Out.DESCRIPTION));
314         assertEquals(1, outs.size());
315         assertEquals("y", outs.get(0).getElementAttributes().getLabel());
316         List<VisualElement> tunnels = circuit.getElements(v -> v.equalsDescription(Tunnel.DESCRIPTION));
317         assertEquals(4, tunnels.size());
318 
319         ModelCreator m = new ModelCreator(circuit, library);
320         TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
321         te.check(0, 0, 0, 0, 0);
322         te.check(0, 0, 0, 1, 1);
323         te.check(0, 0, 1, 0, 1);
324         te.check(0, 0, 1, 1, 1);
325         te.check(0, 1, 0, 0, 1);
326         te.check(0, 1, 0, 1, 0);
327         te.check(0, 1, 1, 0, 0);
328         te.check(0, 1, 1, 1, 0);
329         te.check(1, 0, 0, 0, 1);
330         te.check(1, 0, 0, 1, 0);
331         te.check(1, 0, 1, 0, 0);
332         te.check(1, 0, 1, 1, 0);
333         te.check(1, 1, 0, 0, 1);
334         te.check(1, 1, 0, 1, 0);
335         te.check(1, 1, 1, 0, 0);
336         te.check(1, 1, 1, 1, 0);
337     }
338 }
339