Skip to content

Commit ab9880e

Browse files
committed
chore: refactor from tuples to bitwise
1 parent 3b9d8d9 commit ab9880e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1473
-1911
lines changed

.devcontainer/devcontainer.json

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
{
2-
"name": "Deno",
3-
"build": {
4-
"dockerfile": "Dockerfile"
5-
},
6-
"customizations": {
7-
"vscode": {
8-
"extensions": [
9-
"denoland.vscode-deno"
10-
]
11-
}
12-
}
13-
}
2+
"name": "Deno",
3+
"build": {
4+
"dockerfile": "Dockerfile"
5+
},
6+
"customizations": {
7+
"vscode": {
8+
"extensions": [
9+
"denoland.vscode-deno"
10+
]
11+
}
12+
},
13+
"features": {
14+
"ghcr.io/devcontainers/features/git:1": {}
15+
}
16+
}

add16/add16.test.ts

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,61 @@
11
import { assertEquals } from "jsr:@std/assert";
22
import add16 from "./add16.ts";
3-
import { BitTuple } from "../utility.ts";
43

5-
Deno.test("add16: adds two zero arrays", () => {
6-
const a: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
7-
const b: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
8-
assertEquals(add16(a, b), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4+
// 0 + 0 = 0
5+
Deno.test("add16: 0b0000000000000000 + 0b0000000000000000 = 0b0000000000000000", () => {
6+
assertEquals(
7+
add16(0b0000000000000000, 0b0000000000000000),
8+
0b0000000000000000,
9+
);
910
});
1011

11-
Deno.test("add16: adds one and zero", () => {
12-
const a: BitTuple<16> = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
13-
const b: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
14-
assertEquals(add16(a, b), [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
12+
// 1 + 1 = 2
13+
Deno.test("add16: 0b0000000000000001 + 0b0000000000000001 = 0b0000000000000010", () => {
14+
assertEquals(
15+
add16(0b0000000000000001, 0b0000000000000001),
16+
0b0000000000000010,
17+
);
1518
});
1619

17-
Deno.test("add16: adds two numbers without overflow", () => {
18-
const a: BitTuple<16> = [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 1+4+16+64 = 85
19-
const b: BitTuple<16> = [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]; // 2+8+32+128 = 170
20-
// 85 + 170 = 255 = [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0]
21-
assertEquals(add16(a, b), [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]);
20+
// 0b0000000000001010 + 0b0000000000000101 = 0b0000000000001111
21+
Deno.test("add16: 0b0000000000001010 + 0b0000000000000101 = 0b0000000000001111", () => {
22+
assertEquals(
23+
add16(0b0000000000001010, 0b0000000000000101),
24+
0b0000000000001111,
25+
);
2226
});
2327

24-
Deno.test("add16: adds two max arrays (overflow)", () => {
25-
const a: BitTuple<16> = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
26-
const b: BitTuple<16> = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
27-
// 65535 + 65535 = 131070, lower 16 bits: 1111111111111110
28-
assertEquals(add16(a, b), [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
28+
// 0b1111111111111111 + 0b0000000000000001 = 0b0000000000000000 (overflow)
29+
Deno.test("add16: 0b1111111111111111 + 0b0000000000000001 = 0b0000000000000000", () => {
30+
assertEquals(
31+
add16(0b1111111111111111, 0b0000000000000001),
32+
0b0000000000000000,
33+
);
2934
});
3035

31-
Deno.test("add16: adds with carry from lower to higher bits", () => {
32-
const a: BitTuple<16> = [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
33-
const b: BitTuple<16> = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
34-
// 15 + 1 = 16 = [0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0]
35-
assertEquals(add16(a, b), [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
36+
// 0b1010101010101010 + 0b0101010101010101 = 0b1111111111111111
37+
Deno.test("add16: 0b1010101010101010 + 0b0101010101010101 = 0b1111111111111111", () => {
38+
assertEquals(
39+
add16(0b1010101010101010, 0b0101010101010101),
40+
0b1111111111111111,
41+
);
3642
});
43+
44+
// 0b1111111111111111 + 0b1111111111111111 = 0b1111111111111110 (carry out ignored)
45+
Deno.test("add16: 0b1111111111111111 + 0b1111111111111111 = 0b1111111111111110", () => {
46+
assertEquals(
47+
add16(0b1111111111111111, 0b1111111111111111),
48+
0b1111111111111110,
49+
);
50+
});
51+
52+
// 0b1000000000000000 + 0b1000000000000000 = 0b0000000000000000 (overflow)
53+
Deno.test(
54+
"add16: 0b1000000000000000 + 0b1000000000000000 = 0b0000000000000000",
55+
() => {
56+
assertEquals(
57+
add16(0b1000000000000000, 0b1000000000000000),
58+
0b0000000000000000,
59+
);
60+
},
61+
);

add16/add16.ts

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,22 @@
1-
import type { BitTuple, bit } from "../utility.ts";
2-
import full_adder from "../full_adder/full_adder.ts";
1+
import { mask } from "../utility.ts";
32

43
/**
5-
* @module ADD16
4+
* Adds two numbers and returns the sum masked to the lowest 16 bits.
65
*
7-
* @param {BitTuple<16>} a - First 16-bit input tuple
8-
* @param {BitTuple<16>} b - Second 16-bit input tuple
9-
* @returns {BitTuple<16>} sum - 16-bit sum output tuple
6+
* Both input numbers are first masked to 16 bits, then added together.
7+
* The result is also masked to ensure the return value is a 16-bit number.
108
*
11-
* Input: a[16], b[16]
12-
* Output: sum[16]
13-
* Function: for i = 0..15, sum = a + b (binary addition, ignoring overflow)
9+
* @param {number} a - The first operand. Only the least significant 16 bits are used.
10+
* @param {number} b - The second operand. Only the least significant 16 bits are used.
11+
* @returns {number} The 16-bit masked sum of the two operands.
1412
*
15-
* The ADD16 module computes the bitwise sum of two 16-bit inputs, returning a 16-bit tuple representing the result.
13+
* @example
14+
* add16(0b0000000000000010, 0b0000000000000011); // 0b0000000000000101 (5)
15+
* add16(0xFFFF, 1); // 0x0000 (0), because (0xFFFF + 1) & 0xFFFF === 0
1616
*/
17+
export default function (a: number, b: number): number {
18+
const _a = mask(a);
19+
const _b = mask(b);
1720

18-
export default function (a: BitTuple<16>, b: BitTuple<16>): BitTuple<16> {
19-
const out = new Array<bit>(16).fill(0) as BitTuple<16>;
20-
21-
let carry: bit = 0;
22-
for (let i = 0; i < 16; i++) {
23-
const [_carry, sum] = full_adder(a[i], b[i], carry);
24-
25-
carry = _carry;
26-
out[i] = sum;
27-
}
28-
29-
return out;
21+
return mask(a + b);
3022
}

alu/alu.test.ts

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,83 @@
11
import { assertEquals } from "jsr:@std/assert";
2-
import alu from "./alu.ts";
3-
import type { BitTuple } from "../utility.ts";
4-
import type { AluControlBits } from "./alu.ts";
2+
import alu, { type AluControlBits } from "./alu.ts";
53

4+
// Helper for binary formatting (optional, for readable error messages)
5+
const bin16 = (n: number) => n.toString(2).padStart(16, "0");
6+
7+
// 0
68
Deno.test("ALU: computes 0", () => {
7-
const x: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
8-
const y: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
9+
const x = 0b0000000000000000;
10+
const y = 0b0000000000000000;
911
const control: AluControlBits = { zx: 1, nx: 0, zy: 1, ny: 0, f: 1, no: 0 };
1012
const result = alu(x, y, control);
11-
assertEquals(result.out, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
13+
assertEquals(result.out, 0b0000000000000000, bin16(result.out));
1214
assertEquals(result.zr, 1);
1315
assertEquals(result.ng, 0);
1416
});
1517

18+
// 1
1619
Deno.test("ALU: computes 1", () => {
17-
const x: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
18-
const y: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
20+
const x = 0b0000000000000000;
21+
const y = 0b0000000000000000;
1922
const control: AluControlBits = { zx: 1, nx: 1, zy: 1, ny: 1, f: 1, no: 1 };
2023
const result = alu(x, y, control);
21-
assertEquals(result.out, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
24+
assertEquals(result.out, 0b0000000000000001, bin16(result.out));
2225
assertEquals(result.zr, 0);
2326
assertEquals(result.ng, 0);
2427
});
2528

29+
// -1 (all bits set)
2630
Deno.test("ALU: computes -1", () => {
27-
const x: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
28-
const y: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
31+
const x = 0b0000000000000000;
32+
const y = 0b0000000000000000;
2933
const control: AluControlBits = { zx: 1, nx: 1, zy: 1, ny: 0, f: 1, no: 0 };
3034
const result = alu(x, y, control);
31-
assertEquals(result.out, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
35+
assertEquals(result.out, 0b1111111111111111, bin16(result.out));
3236
assertEquals(result.zr, 0);
3337
assertEquals(result.ng, 1);
3438
});
3539

40+
// Passes through x
3641
Deno.test("ALU: passes through x", () => {
37-
const x: BitTuple<16> = [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0];
38-
const y: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
42+
const x = 0b1010101000000000;
43+
const y = 0b0000000000000000;
3944
const control: AluControlBits = { zx: 0, nx: 0, zy: 1, ny: 0, f: 1, no: 0 };
4045
const result = alu(x, y, control);
41-
assertEquals(result.out, [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
46+
assertEquals(result.out, x, bin16(result.out));
4247
});
4348

49+
// Passes through y
4450
Deno.test("ALU: passes through y", () => {
45-
const x: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
46-
const y: BitTuple<16> = [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0];
51+
const x = 0b0000000000000000;
52+
const y = 0b0101010100000000;
4753
const control: AluControlBits = { zx: 1, nx: 0, zy: 0, ny: 0, f: 1, no: 0 };
4854
const result = alu(x, y, control);
49-
assertEquals(result.out, [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]);
55+
assertEquals(result.out, y, bin16(result.out));
5056
});
5157

58+
// Bitwise not x
5259
Deno.test("ALU: bitwise not x", () => {
53-
const x: BitTuple<16> = [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0];
54-
const y: BitTuple<16> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
60+
const x = 0b1010101000000000;
61+
const y = 0b0000000000000000;
5562
const control: AluControlBits = { zx: 0, nx: 1, zy: 1, ny: 0, f: 1, no: 0 };
5663
const result = alu(x, y, control);
57-
assertEquals(result.out, [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
64+
assertEquals(result.out, (~x) & 0xFFFF, bin16(result.out)); // 16-bit mask
5865
});
5966

67+
// Add x and y
6068
Deno.test("ALU: add x and y", () => {
61-
const x: BitTuple<16> = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 1
62-
const y: BitTuple<16> = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 3
69+
const x = 0b0000000000000001; // 1
70+
const y = 0b0000000000000011; // 3
6371
const control: AluControlBits = { zx: 0, nx: 0, zy: 0, ny: 0, f: 1, no: 0 };
6472
const result = alu(x, y, control);
65-
// 1 + 3 = 4 -> [0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0]
66-
assertEquals(result.out, [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
73+
assertEquals(result.out, 0b0000000000000100, bin16(result.out)); // 4
6774
});
6875

76+
// Bitwise and
6977
Deno.test("ALU: bitwise and", () => {
70-
const x: BitTuple<16> = [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0];
71-
const y: BitTuple<16> = [1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0];
78+
const x = 0b1010101000000000;
79+
const y = 0b1101010100000000;
7280
const control: AluControlBits = { zx: 0, nx: 0, zy: 0, ny: 0, f: 0, no: 0 };
7381
const result = alu(x, y, control);
74-
assertEquals(result.out, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
82+
assertEquals(result.out, x & y, bin16(result.out));
7583
});

alu/alu.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,30 @@ import not from "../not/not.ts";
55
import not16 from "../not16/not16.ts";
66
import or from "../or/or.ts";
77
import or8way from "../or8way/or8way.ts";
8-
import type { bit, BitTuple } from "../utility.ts";
8+
import { index, sliceBits } from "../utility.ts";
99

1010
export interface AluControlBits {
1111
/** Zero the x input if 1 */
12-
zx: bit;
12+
zx: number;
1313
/** Negate the x input if 1 */
14-
nx: bit;
14+
nx: number;
1515
/** Zero the y input if 1 */
16-
zy: bit;
16+
zy: number;
1717
/** Negate the y input if 1 */
18-
ny: bit;
18+
ny: number;
1919
/** Function code: 1 for Add, 0 for And */
20-
f: bit;
20+
f: number;
2121
/** Negate the output if 1 */
22-
no: bit;
22+
no: number;
2323
}
2424

2525
/**
2626
* @module ALU
2727
*
28-
* @param {BitTuple<16>} x - 16-bit input
29-
* @param {BitTuple<16>} y - 16-bit input
28+
* @param {number} x - 16-bit input (as a number; only the lowest 16 bits are used)
29+
* @param {number} y - 16-bit input (as a number; only the lowest 16 bits are used)
3030
* @param {AluControlBits} control_bits - Object containing all ALU control bits
31-
* @returns {{out: BitTuple<16>, zr: bit, ng: bit}}
31+
* @returns {{out: number, zr: 0|1, ng: 0|1}}
3232
*
3333
* | zx | nx | zy | ny | f | no | Output | Description |
3434
* |----|----|----|----|----|----|--------------|----------------------|
@@ -51,34 +51,32 @@ export interface AluControlBits {
5151
* | 0 | 0 | 0 | 0 | 0 | 0 | x & y | Bitwise and |
5252
* | 0 | 1 | 0 | 1 | 0 | 1 | x \| y | Bitwise or |
5353
*
54-
* The ALU computes a 16-bit output (out) and two status flags:
55-
* - zr: 1 if out == 0, else 0
56-
* - ng: 1 if out < 0 (in two's complement), else 0
54+
* The ALU computes a 16-bit output (`out`) and two status flags:
55+
* - `zr`: 1 if out == 0, else 0
56+
* - `ng`: 1 if out < 0 (in two's complement), else 0
5757
*/
5858

5959
export default function (
60-
x: BitTuple<16>,
61-
y: BitTuple<16>,
60+
x: number,
61+
y: number,
6262
{ zx, nx, zy, ny, f, no }: AluControlBits,
63-
): { ng: bit; out: BitTuple<16>; zr: bit } {
64-
const zero = new Array<bit>(16).fill(0) as BitTuple<16>;
65-
66-
if (zx) x = mux16(x, zero, zx);
63+
): { ng: number; out: number; zr: number } {
64+
if (zx) x = mux16(x, 0, zx);
6765
if (nx) x = not16(x);
68-
if (zy) y = mux16(y, zero, zy);
66+
if (zy) y = mux16(y, 0, zy);
6967
if (ny) y = not16(y);
7068

7169
const operation_result = f ? add16(x, y) : and16(x, y);
7270
const not_operation_result = not16(operation_result);
7371
const out = mux16(operation_result, not_operation_result, no);
7472

75-
const first_or = or8way(out.slice(0, 7) as BitTuple<8>);
76-
const second_or = or8way(out.slice(8) as BitTuple<8>);
73+
const first_or = or8way(sliceBits(out, 0, 7));
74+
const second_or = or8way(sliceBits(out, 8, 8));
7775
const last_or = or(first_or, second_or);
7876
const zr = not(last_or);
7977

8078
return {
81-
ng: out[15],
79+
ng: index(out, 15),
8280
out,
8381
zr,
8482
};

and/and.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import nand from "../nand/nand.ts";
2-
import type { bit } from "../utility.ts";
32
/**
43
* @module AND
54
*
6-
* @param {bit} a
7-
* @param {bit} b
8-
* @returns {bit}
5+
* @param {number} a
6+
* @param {number} b
7+
* @returns {number}
98
*
109
* | A | B | A AND B |
1110
* |---|---|:--------:|
@@ -14,7 +13,7 @@ import type { bit } from "../utility.ts";
1413
* | 1 | 0 | 0 |
1514
* | 1 | 1 | 1 |
1615
*/
17-
export default function (a: bit, b: bit): bit {
16+
export default function and(a: number, b: number): number {
1817
const w1 = nand(a, b);
1918
return nand(w1, w1);
2019
}

0 commit comments

Comments
 (0)