Skip to content

Commit

Permalink
Several bug fixes and improvements (#192)
Browse files Browse the repository at this point in the history
* Don't recompile HDL code when switching between 2 builtin chips
* Allow comipling test seperately from hdl to not overrite builtin chips
* Add missing await for chip compilation
* Reset pin values after switching chip
* Omit visualization label for chips without visualizations
* Change builtin chip display to better reflect the book
* Fix inconsistent HDL templates
* Don't await useBuiltin inside switch toggle
* Correctly load the first project on startup
* Change "Visualizations" text to "Visualization"
* Enable decimal inputs
* Handle negative decimal inputs
* Disable eval button when decimal input is invalid
* Fix inconsistencies between chip names and file names
* Line order change
* Set some of the decimal fields to be unsigned according to function
* Fix builtin chip syntax
* Change invalid HDL error message
* Remove ALUNoStat
* Disable eval button when decimal input overflows
* Fix virtual scroll
* Add register visualization
* Add Nand and DFF as builtin only chips
* Add missing semicolons
* Hide internal pins for builtin only chips
* Fix DFF hdl interface & description
* Add Screen and Keyboard builtin chips
* Change keyboard output pins to update immediately
* Fix builtin RAM reset
* Fix true and false busses evaluation


Signed-off-by: Neta London <[email protected]>
  • Loading branch information
netalondon authored Oct 25, 2023
1 parent 42ad025 commit 611d235
Show file tree
Hide file tree
Showing 28 changed files with 502 additions and 121 deletions.
55 changes: 40 additions & 15 deletions components/src/chips/keyboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,43 @@ function keyPressToHackCharacter(keypress: KeyboardEvent): number {
return 0;
}

export const Keyboard = ({ keyboard }: { keyboard: KeyboardChip }) => {
export const Keyboard = ({
keyboard,
update,
}: {
keyboard: KeyboardChip;
update?: () => void;
}) => {
const [showPicker, setShowPicker] = useState(false);
const [bits, setBits] = useState(keyboard.out().busVoltage);
let currentKey = 0;

const setKey = useCallback(
(event: KeyboardEvent<HTMLInputElement>) => {
const key = keyPressToHackCharacter(event);
if (key === 0) {
return;
}
event.preventDefault();
keyboard.setKey(key);
setBits(keyboard.out().busVoltage);
setShowPicker(false);
},
[keyboard, setShowPicker, setBits]
);
const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
event.preventDefault();
const key = keyPressToHackCharacter(event);
if (key === currentKey) {
return;
}
setKey(key);
update?.();
};

const onKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {
currentKey = 0;
keyboard.clearKey();
update?.();
setBits(keyboard.out().busVoltage);
};

const setKey = (key: number) => {
if (key === 0) {
return;
}
keyboard.setKey(key);
setBits(keyboard.out().busVoltage);
currentKey = key;
// setShowPicker(false);
};

const changeKey = useCallback(() => {
setShowPicker(true);
Expand All @@ -75,7 +95,12 @@ export const Keyboard = ({ keyboard }: { keyboard: KeyboardChip }) => {
</div>
<div className="flex-1">
{showPicker ? (
<input ref={(e) => e?.focus()} type="text" onKeyDown={setKey} />
<input
ref={(e) => e?.focus()}
type="text"
onKeyDown={onKeyDown}
onKeyUp={onKeyUp}
/>
) : (
<button onClick={changeKey}>
{/* <Icon name="keyboard" /> */}
Expand Down
14 changes: 7 additions & 7 deletions components/src/chips/visualizations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { ALU } from "@nand2tetris/simulator/chip/builtins/index.js";
import {
PC,
VRegister,
Register,
} from "@nand2tetris/simulator/chip/builtins/sequential/bit.js";
import {
RAM,
Expand Down Expand Up @@ -41,7 +41,7 @@ export function getBuiltinVisualization(part: Chip): ReactElement | undefined {
}
}

export function makeVisualization(chip: Chip): ReactElement | undefined {
export function makeVisualization(chip: Chip, updateAction? : () => void): ReactElement | undefined {
if (chip instanceof ALU) {
return (
<ALUComponent
Expand All @@ -59,7 +59,7 @@ export function makeVisualization(chip: Chip): ReactElement | undefined {
/>
);
}
if (chip instanceof VRegister) {
if (chip instanceof Register) {
return (
<RegisterComponent
name={chip.name ?? `Chip ${chip.id}`}
Expand All @@ -71,7 +71,7 @@ export function makeVisualization(chip: Chip): ReactElement | undefined {
return <RegisterComponent name="PC" bits={chip.bits} />;
}
if (chip instanceof Keyboard) {
return <KeyboardComponent keyboard={chip} />;
return <KeyboardComponent keyboard={chip} update={updateAction} />;
}
if (chip instanceof Screen) {
return <ScreenComponent memory={chip.memory} />;
Expand Down Expand Up @@ -108,18 +108,18 @@ export function makeVisualization(chip: Chip): ReactElement | undefined {
}

const vis = [...chip.parts]
.map(makeVisualization)
.map((chip) => makeVisualization(chip, updateAction))
.filter((v) => v !== undefined);
return vis.length > 0 ? <>{vis}</> : undefined;
}

export function makeVisualizationsWithId(chip: {
parts: Chip[];
}): [string, ReactElement][] {
}, updateAction? : () => void): [string, ReactElement][] {
return [...chip.parts]
.map((part, i): [string, ReactElement | undefined] => [
`${part.id}_${i}`,
makeVisualization(part),
makeVisualization(part, updateAction),
])
.filter(([_, v]) => v !== undefined) as [string, ReactElement][];
}
48 changes: 48 additions & 0 deletions components/src/pin_display.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Ok, isOk } from "@davidsouther/jiffies/lib/esm/result.js";
import {
REGISTRY as BUILTIN_REGISTRY,
getBuiltinChip,
} from "@nand2tetris/simulator/chip/builtins/index.js";

export class ChipDisplayInfo {
signBehaviors: Map<string, boolean> = new Map();

public constructor(chipName: string, unsigned?: string[]) {
if (BUILTIN_REGISTRY.has(chipName)) {
const chip = getBuiltinChip(chipName);
if (isOk(chip)) {
const pins = Array.from(Ok(chip).ins.entries()).concat(
Array.from(Ok(chip).outs.entries())
);
for (const pin of pins) {
this.signBehaviors.set(
pin.name,
!unsigned || !unsigned.includes(pin.name)
);
}
}
}
}

public isSigned(pin: string) {
return this.signBehaviors.get(pin);
}
}

const UNSIGNED_PINS = new Map<string, string[]>([
["Mux4Way16", ["sel"]],
["Mux8Way16", ["sel"]],
["DMux4Way", ["sel"]],
["DMux8Way", ["sel"]],
["RAM8", ["address"]],
["RAM64", ["address"]],
["RAM512", ["address"]],
["RAM4K", ["address"]],
["RAM16K", ["address"]],
["Screen", ["address"]],
["Memory", ["address"]],
["CPU", ["addressM", "pc"]],
]);

export const getDisplayInfo = (chipName: string) =>
new ChipDisplayInfo(chipName, UNSIGNED_PINS.get(chipName));
Loading

0 comments on commit 611d235

Please sign in to comment.