Skip to content

Commit 3725e58

Browse files
committed
[feature] - Add multiplexer
1 parent d646e82 commit 3725e58

17 files changed

+197
-4
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ npm-debug.log*
66
yarn-debug.log*
77
yarn-error.log*
88

9+
# Test coverage
10+
/coverage/
11+
912
# Optional npm cache directory
1013
.npm
1114

@@ -88,4 +91,4 @@ $RECYCLE.BIN/
8891
.TemporaryItems
8992
.Trashes
9093
.VolumeIcon.icns
91-
.com.apple.timemachine.donotpresent
94+
.com.apple.timemachine.donotpresent

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"build": "rollup -c",
99
"dev": "rollup -c -w",
1010
"start": "sirv public",
11-
"test:unit": "jest"
11+
"test:unit": "jest --collectCoverage"
1212
},
1313
"devDependencies": {
1414
"@babel/core": "^7.9.0",

src/components/adders/tests/full-adder.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { fullAdder } from "..";
22

33
describe("Adders - Full Adder", () => {
4+
test("default to output { sum: 0, carry: 0 }", () => {
5+
expect(fullAdder()).toStrictEqual({
6+
sum: 0b0,
7+
carry: 0b0,
8+
});
9+
});
10+
411
test("0 0 0 to output { sum: 0, carry: 0 }", () => {
512
expect(fullAdder(0b0, 0b0, 0b0)).toStrictEqual({
613
sum: 0b0,

src/components/adders/tests/half-adder.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { halfAdder } from "..";
22

33
describe("Adders - Half Adder", () => {
4+
test("default to output { sum: 0, carry: 0 }", () => {
5+
expect(halfAdder()).toStrictEqual({
6+
sum: 0b0,
7+
carry: 0b0,
8+
});
9+
});
10+
411
test("0 0 to output { sum: 0, carry: 0 }", () => {
512
expect(halfAdder(0b0, 0b0)).toStrictEqual({
613
sum: 0b0,

src/components/adders/tests/ripple-carry-adder.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import { defaultByte } from "../../../util/defaults";
22
import { rippleCarryAdder } from "..";
33

44
describe("Adders - Ripple Carry Adder", () => {
5+
test("default to output { sum: 00000000, carry: 0 }", () => {
6+
expect(rippleCarryAdder()).toStrictEqual({
7+
sum: defaultByte,
8+
carry: 0b0,
9+
});
10+
});
11+
512
test("00000000 + 00000000 to output { sum: 00000000, carry: 0 }", () => {
613
expect(rippleCarryAdder(defaultByte, defaultByte)).toStrictEqual({
714
sum: defaultByte,

src/components/gates/tests/and-gate.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import { andGate } from "..";
22

33
describe("Gates - AND", () => {
4+
test("defaults to 0", () => {
5+
expect(andGate()).toBe(0b0);
6+
});
7+
48
test("0 AND 0 to be 0", () => {
59
expect(andGate(0b0, 0b0)).toBe(0b0);
610
});
11+
712
test("0 AND 1 to be 0", () => {
813
expect(andGate(0b0, 0b1)).toBe(0b0);
914
});
15+
1016
test("1 AND 0 to be 0", () => {
1117
expect(andGate(0b1, 0b0)).toBe(0b0);
1218
});
19+
1320
test("1 AND 1 to be 1", () => {
1421
expect(andGate(0b1, 0b1)).toBe(0b1);
1522
});

src/components/gates/tests/not-gate.test.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { notGate } from "..";
22

33
describe("Gates - NOT", () => {
4+
test("defaults to 1", () => {
5+
expect(notGate()).toBe(0b1);
6+
});
7+
48
test("0 to become 1", () => {
59
expect(notGate(0b0)).toBe(0b1);
610
});
11+
712
test("1 to become 0", () => {
813
expect(notGate(0b1)).toBe(0b0);
914
});

src/components/gates/tests/or-gate.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import { orGate } from "..";
22

33
describe("Gates - OR", () => {
4+
test("defaults to 0", () => {
5+
expect(orGate()).toBe(0b0);
6+
});
7+
48
test("0 OR 0 to be 0", () => {
59
expect(orGate(0b0, 0b0)).toBe(0b0);
610
});
11+
712
test("0 OR 1 to be 1", () => {
813
expect(orGate(0b0, 0b1)).toBe(0b1);
914
});
15+
1016
test("1 OR 0 to be 1", () => {
1117
expect(orGate(0b1, 0b0)).toBe(0b1);
1218
});
19+
1320
test("1 OR 1 to be 1", () => {
1421
expect(orGate(0b1, 0b1)).toBe(0b1);
1522
});

src/components/gates/tests/xor-gate.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import { xorGate } from "..";
22

33
describe("Gates - XOR", () => {
4+
test("defaults to 0", () => {
5+
expect(xorGate()).toBe(0b0);
6+
});
7+
48
test("0 XOR 0 to be 0", () => {
59
expect(xorGate(0b0, 0b0)).toBe(0b0);
610
});
11+
712
test("0 XOR 1 to be 1", () => {
813
expect(xorGate(0b0, 0b1)).toBe(0b1);
914
});
15+
1016
test("1 XOR 0 to be 1", () => {
1117
expect(xorGate(0b1, 0b0)).toBe(0b1);
1218
});
19+
1320
test("1 XOR 1 to be 0", () => {
1421
expect(xorGate(0b1, 0b1)).toBe(0b0);
1522
});

src/components/latches/tests/and-or-latch.test.js

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ describe("Latches - AndOrLatch", () => {
66
expect(latch.output).toBe(0b0);
77
});
88

9+
test("default trigger outputs 0", () => {
10+
const latch = new AndOrLatch();
11+
latch.trigger();
12+
expect(latch.output).toBe(0b0);
13+
});
14+
915
test("Setting input to 1 outputs 1", () => {
1016
const latch = new AndOrLatch();
1117
latch.trigger(0b1, 0b0);

src/components/latches/tests/gated-latch.test.js

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ describe("Latches - GatedLatch", () => {
66
expect(latch.output).toBe(0b0);
77
});
88

9+
test("default trigger outputs 0", () => {
10+
const latch = new GatedLatch();
11+
latch.trigger();
12+
expect(latch.output).toBe(0b0);
13+
});
14+
915
test("Setting input to 1 outputs 0", () => {
1016
const latch = new GatedLatch();
1117
latch.trigger(0b1, 0b0);

src/components/registers/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { EightBitRegister } from "./eight-bit-register";
2+
export { MultiPlexer } from "./multiplexer";
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import "../../util/types";
2+
import { defaultByte, defaultBit } from "../../util/defaults";
3+
import { binaryArrayToDecimal } from "../../util/convert";
4+
import { GatedLatch } from "../latches";
5+
6+
const MatrixFactory = (rows, cols) => {
7+
return [...Array(rows)].map(() => Array(cols).fill(new GatedLatch()));
8+
};
9+
10+
export class MultiPlexer {
11+
constructor(rows = 16, cols = 16) {
12+
/** @type {GatedLatch[][]} */
13+
this.matrix = MatrixFactory(rows, cols);
14+
}
15+
16+
/**
17+
* Simulates an active intersection wire
18+
* @param {byte} address - The address of the latch to enable
19+
* @param {bit} data - The input/output data bit
20+
* @param {bit} writeEnabled - The shared writeEnabled bit
21+
* @param {bit} readEnabled - The shared readEnabled bit
22+
*/
23+
trigger(
24+
address = defaultByte,
25+
data = defaultBit,
26+
writeEnabled = defaultBit,
27+
readEnabled = defaultBit
28+
) {
29+
const [c3, c2, c1, c0, r3, r2, r1, r0] = address;
30+
const colAddress = binaryArrayToDecimal([c3, c2, c1, c0]);
31+
const rowAddress = binaryArrayToDecimal([r3, r2, r1, r0]);
32+
this.activeLatch = this.matrix[colAddress][rowAddress];
33+
34+
// In reality this would use an AND gate
35+
if (writeEnabled) {
36+
this.activeLatch.trigger(data, writeEnabled);
37+
}
38+
39+
// In reality this would use an AND gate
40+
if (readEnabled) {
41+
return this.activeLatch.output;
42+
}
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { MultiPlexer } from "..";
2+
3+
describe("Registers - Multiplexer", () => {
4+
test("new multiplexeris 16x16 matrix", () => {
5+
const multiplexer = new MultiPlexer();
6+
expect(multiplexer.matrix).toHaveLength(16);
7+
expect(multiplexer.matrix[0]).toHaveLength(16);
8+
expect(multiplexer.matrix[1]).toHaveLength(16);
9+
expect(multiplexer.matrix[15]).toHaveLength(16);
10+
});
11+
12+
test("The trigger can read/write to specific latches", () => {
13+
const multiplexer = new MultiPlexer();
14+
const address1 = [0b0, 0b0, 0b1, 0b0, 0b0, 0b1, 0b1, 0b1]; // col 2, row 7
15+
const address2 = [0b0, 0b1, 0b1, 0b0, 0b0, 0b0, 0b1, 0b1]; // col 5, row 3
16+
17+
const read = (addr) => {
18+
return multiplexer.trigger(addr, 0b0, 0b0, 0b1);
19+
};
20+
21+
const write = (addr, dataIn) => {
22+
multiplexer.trigger(addr, dataIn, 0b1, 0b0);
23+
};
24+
25+
// 1) can read address
26+
expect(read(address1)).toBe(0b0);
27+
28+
// 2) can write 1 to address
29+
write(address1, 0b1);
30+
expect(read(address1)).toBe(0b1);
31+
32+
// 3) Can remember values in different addresses
33+
expect(read(address2)).toBe(0b0);
34+
expect(read(address1)).toBe(0b1);
35+
});
36+
});

src/util/convert.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import "./types";
2+
3+
/**
4+
* Converts a byte to decimal
5+
* @param {byte | nibble} input
6+
*/
7+
export function binaryArrayToDecimal(input) {
8+
return parseInt(input.join(""), 2);
9+
}

src/util/defaults.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import "./types";
22

3-
/** @type {byte} */
3+
/** @type {0b0} */
44
export const defaultBit = 0b0;
55

6-
/** @type {byte} */
6+
/** @type {[0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b0]} */
77
export const defaultByte = [0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b0];

src/util/tests/convert.test.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { binaryArrayToDecimal } from "../convert";
2+
3+
describe("Util - Convert", () => {
4+
describe("binaryArrayToDecimal method", () => {
5+
test("converts a byte successfully (00000000)", () => {
6+
const input = [0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b0];
7+
const result = binaryArrayToDecimal(input);
8+
expect(result).toBe(0);
9+
});
10+
11+
test("converts a byte successfully (11111111)", () => {
12+
const input = [0b1, 0b1, 0b1, 0b1, 0b1, 0b1, 0b1, 0b1];
13+
const result = binaryArrayToDecimal(input);
14+
expect(result).toBe(255);
15+
});
16+
17+
test("converts a byte successfully (10101010)", () => {
18+
const input = [0b1, 0b0, 0b1, 0b0, 0b1, 0b0, 0b1, 0b0];
19+
const result = binaryArrayToDecimal(input);
20+
expect(result).toBe(170);
21+
});
22+
23+
test("converts a byte successfully (01010101)", () => {
24+
const input = [0b0, 0b1, 0b0, 0b1, 0b0, 0b1, 0b0, 0b1];
25+
const result = binaryArrayToDecimal(input);
26+
expect(result).toBe(85);
27+
});
28+
29+
test("converts a nibble successfully (0100)", () => {
30+
const input = [0b0, 0b1, 0b0, 0b0];
31+
const result = binaryArrayToDecimal(input);
32+
expect(result).toBe(4);
33+
});
34+
35+
test("converts a nibble successfully (1100)", () => {
36+
const input = [0b1, 0b1, 0b0, 0b0];
37+
const result = binaryArrayToDecimal(input);
38+
expect(result).toBe(12);
39+
});
40+
});
41+
});

0 commit comments

Comments
 (0)