Skip to content

Commit abed992

Browse files
committed
feat: sequential chips
1 parent 75be655 commit abed992

File tree

23 files changed

+1482
-300
lines changed

23 files changed

+1482
-300
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.vscode

bit/bit.test.ts

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,62 @@
11
import { assertEquals } from "jsr:@std/assert";
2-
import Bit from "./bit.ts";
3-
import clock from "../clock/clock.ts"; // Adjust as needed
2+
import Bit from "./bit.ts"; // Adjust the import as needed
43

54
Deno.test("Bit: outputs 0 initially", () => {
6-
const bit = Bit();
7-
assertEquals(bit(0, 0), 0);
8-
assertEquals(bit(1, 0), 0);
5+
const bit = Bit(0, 0);
6+
assertEquals(bit.value, 0);
97
});
108

119
Deno.test("Bit: loads and stores a 1", () => {
12-
const bit = Bit();
13-
assertEquals(bit(1, 1), 0); // Set input=1, load=1, output still 0
14-
clock.tick();
15-
clock.tock();
16-
assertEquals(bit(0, 0), 1); // Output updates to 1
10+
const bit = Bit(0, 0);
11+
assertEquals(bit.value, 0);
12+
13+
bit.in = 1;
14+
bit.load = 1;
15+
bit.tick();
16+
bit.tock();
17+
18+
assertEquals(bit.value, 1);
1719
});
1820

1921
Deno.test("Bit: holds value when load is 0", () => {
20-
const bit = Bit();
21-
bit(1, 1); // Prepare to store 1
22-
clock.tick();
23-
clock.tock();
24-
assertEquals(bit(0, 0), 1); // Output is 1
25-
26-
bit(0, 0); // load=0, input=0, should not change
27-
clock.tick();
28-
clock.tock();
29-
assertEquals(bit(0, 0), 1); // Output still 1
22+
const bit = Bit(0, 0);
23+
24+
bit.in = 1;
25+
bit.load = 1;
26+
bit.tick();
27+
bit.tock();
28+
assertEquals(bit.value, 1);
29+
30+
bit.in = 0;
31+
bit.load = 0;
32+
bit.tick();
33+
bit.tock();
34+
assertEquals(bit.value, 1); // Should still hold the previous value
3035
});
3136

3237
Deno.test("Bit: can reset to 0 when load is 1", () => {
33-
const bit = Bit();
34-
bit(1, 1);
35-
clock.tick();
36-
clock.tock();
37-
assertEquals(bit(0, 0), 1);
38-
39-
bit(0, 1); // load=1, input=0, should store 0
40-
clock.tick();
41-
clock.tock();
42-
assertEquals(bit(0, 0), 0);
38+
const bit = Bit(0, 0);
39+
40+
bit.in = 1;
41+
bit.load = 1;
42+
bit.tick();
43+
bit.tock();
44+
assertEquals(bit.value, 1);
45+
46+
bit.in = 0;
47+
bit.load = 1;
48+
bit.tick();
49+
bit.tock();
50+
assertEquals(bit.value, 0);
4351
});
4452

4553
Deno.test("Bit: does not change output until tock", () => {
46-
const bit = Bit();
47-
bit(1, 1);
48-
clock.tick();
49-
assertEquals(bit(0, 0), 0); // Output not updated yet
50-
clock.tock();
51-
assertEquals(bit(0, 0), 1); // Output updated after tock
54+
const bit = Bit(0, 0);
55+
56+
bit.in = 1;
57+
bit.load = 1;
58+
bit.tick();
59+
assertEquals(bit.value, 0); // Output not updated yet
60+
bit.tock();
61+
assertEquals(bit.value, 1); // Output updated after tock
5262
});

bit/bit.ts

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,56 @@
11
import dff from "../dff/dff.ts";
22
import type { bit } from "../utility.ts";
33

4-
export default function (): (_in: bit, load: bit) => bit {
5-
const _dff = dff();
6-
7-
/**
8-
* @module Bit
9-
*
10-
* @param {bit} in - 1-bit input value
11-
* @param {bit} load - 1-bit load signal (1: store input, 0: keep current)
12-
* @returns {object} out - Bit interface with getter for output and setters for input/load
13-
*
14-
* Input: in (bit), load (bit)
15-
* Output: out (bit)
16-
* Function:
17-
* If load == 1, stores `in` on next clock cycle.
18-
* If load == 0, preserves previous value.
19-
*
20-
* The Bit chip is a 1-bit register built from a DFF.
21-
*/
4+
/**
5+
* @module Bit
6+
*
7+
* @param {bit} in - 1-bit input value
8+
* @param {bit} load - 1-bit load signal (1: store input, 0: keep current)
9+
* @returns {object} out - Bit interface with getter for output and setters for input/load
10+
*
11+
* Input: in (bit), load (bit)
12+
* Output: out (bit)
13+
* Function:
14+
* If load == 1, stores `in` on next clock cycle.
15+
* If load == 0, preserves previous value.
16+
*
17+
* The Bit chip is a 1-bit register built from a DFF.
18+
*/
19+
interface Bit {
20+
value: bit;
21+
in: bit;
22+
load: bit;
23+
tick: () => void;
24+
tock: () => void;
25+
}
2226

23-
return function (_in: bit, load: bit): bit {
24-
if (load) {
25-
_dff.value = _in;
26-
}
27+
export default function (_in: bit = 0, load: bit = 0): Bit {
28+
const _dff = dff();
29+
let __in: bit = _in;
30+
let _load: bit = load;
2731

28-
return _dff.value;
32+
return {
33+
get in() {
34+
return __in;
35+
},
36+
set in(val: bit) {
37+
__in = val;
38+
},
39+
get load() {
40+
return _load;
41+
},
42+
set load(val: bit) {
43+
_load = val;
44+
},
45+
get value() {
46+
return _dff.value;
47+
},
48+
tick() {
49+
if (_load) _dff.value = __in;
50+
_dff.tick();
51+
},
52+
tock() {
53+
_dff.tock();
54+
},
2955
};
3056
}

clock/clock.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@r2/hack",
3-
"version": "0.13.0",
3+
"version": "0.14.0",
44
"license": "MIT",
55
"exports": {
66
".": "./main.ts"

dff/dff.test.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { assertEquals } from "jsr:@std/assert";
22
import DFF from "./dff.ts";
3-
import clock from "../clock/clock.ts";
43

54
Deno.test("DFF: outputs 0 initially", () => {
65
const dff = DFF();
@@ -17,21 +16,21 @@ Deno.test("DFF: latches input on tick and updates output on tock", () => {
1716
assertEquals(dff.value, 0);
1817

1918
// Tick: sample input
20-
clock.tick();
19+
dff.tick();
2120

2221
// Output should still be 0 before tock
2322
assertEquals(dff.value, 0);
2423

2524
// Tock: output updates to previous input
26-
clock.tock();
25+
dff.tock();
2726
assertEquals(dff.value, 1);
2827

2928
// Change input to 0, output remains 1 until next tick/tock
3029
dff.value = 0;
3130
assertEquals(dff.value, 1);
32-
clock.tick();
31+
dff.tick();
3332
assertEquals(dff.value, 1);
34-
clock.tock();
33+
dff.tock();
3534
assertEquals(dff.value, 0);
3635
});
3736

@@ -40,19 +39,19 @@ Deno.test("DFF: handles multiple cycles", () => {
4039

4140
// Cycle 1: input 1
4241
dff.value = 1;
43-
clock.tick();
44-
clock.tock();
42+
dff.tick();
43+
dff.tock();
4544
assertEquals(dff.value, 1);
4645

4746
// Cycle 2: input 0
4847
dff.value = 0;
49-
clock.tick();
50-
clock.tock();
48+
dff.tick();
49+
dff.tock();
5150
assertEquals(dff.value, 0);
5251

5352
// Cycle 3: input 1
5453
dff.value = 1;
55-
clock.tick();
56-
clock.tock();
54+
dff.tick();
55+
dff.tock();
5756
assertEquals(dff.value, 1);
5857
});

dff/dff.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import clock from "../clock/clock.ts";
21
import type { bit } from "../utility.ts";
32

43
/**
@@ -17,28 +16,32 @@ import type { bit } from "../utility.ts";
1716
* It updates its output in sync with the system clock's tick/tock phases.
1817
*/
1918

20-
export default function (): Record<string, bit> {
19+
interface DFF {
20+
value: bit;
21+
tick: () => void;
22+
tock: () => void;
23+
}
24+
25+
export default function (): DFF {
2126
let output: bit = 0;
2227
let next: bit = 0;
2328
let input: bit = 0;
2429

25-
const obj = {
30+
return {
2631
get value() {
2732
return output;
2833
},
2934

3035
set value(newVal: bit) {
3136
input = newVal;
3237
},
33-
};
34-
35-
clock.addEventListener("tick", () => {
36-
next = input;
37-
});
3838

39-
clock.addEventListener("tock", () => {
40-
output = next;
41-
});
39+
tick() {
40+
next = input;
41+
},
4242

43-
return obj;
43+
tock() {
44+
output = next;
45+
},
46+
};
4447
}

main.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,11 @@ export { default as dff } from "./dff/dff.ts";
2222
export { default as bit } from "./bit/bit.ts";
2323
export { default as register } from "./register/register.ts";
2424
export { default as ram8 } from "./ram8/ram8.ts"
25+
export { default as ram64 } from "./ram64/ram64.ts"
26+
export { default as ram512 } from "./ram512/ram512.ts"
27+
export { default as ram4k } from "./ram4k/ram4k.ts"
28+
export { default as ram16k } from "./ram16k/ram16k.ts"
29+
export { default as pc } from "./pc/pc.ts"
30+
2531

2632
export * from "./utility.ts";

0 commit comments

Comments
 (0)