From 33309dfb9e8e1fb9f9ad8eb10cd8126fadb8507f Mon Sep 17 00:00:00 2001 From: Neta London Date: Thu, 11 Jul 2024 09:24:35 +0300 Subject: [PATCH] Check for looping wires when building chip --- simulator/src/chip/builder.test.ts | 19 ++++++++++++++++ simulator/src/chip/builder.ts | 36 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/simulator/src/chip/builder.test.ts b/simulator/src/chip/builder.test.ts index 73352051d..f926dfc35 100644 --- a/simulator/src/chip/builder.test.ts +++ b/simulator/src/chip/builder.test.ts @@ -172,6 +172,25 @@ describe("Chip Builder", () => { throw new Error(display(e.message ?? e.shortMessage ?? e)); } }); + + it("returns error for wire loop", async () => { + try { + const chip = unwrap( + HDL.parse(`CHIP Not { + IN in; + OUT out; + PARTS: + Nand(a=in, b=myNand, out=myNand); + }`), + ); + const foo = await build(chip); + expect(foo).toBeErr(); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (e: any) { + throw new Error(display(e.message ?? e.shortMessage ?? e)); + } + }); }); const USE_COPY_HDL = `CHIP UseCopy { diff --git a/simulator/src/chip/builder.ts b/simulator/src/chip/builder.ts index 01973774f..5a7878bb6 100644 --- a/simulator/src/chip/builder.ts +++ b/simulator/src/chip/builder.ts @@ -263,7 +263,43 @@ class ChipBuilder { return Ok(); } + private checkLoops( + part: Part, + partChip: Chip, + ): Result { + const ins = new Set(); + const outs = new Set(); + + let loop: string | undefined = undefined; + for (const { lhs, rhs } of part.wires) { + if (partChip.isInPin(lhs.pin)) { + if (outs.has(rhs.pin)) { + loop = rhs.pin; + break; + } else { + ins.add(rhs.pin); + } + } else if (partChip.isOutPin(lhs.pin)) { + if (ins.has(rhs.pin)) { + loop = rhs.pin; + break; + } else { + outs.add(rhs.pin); + } + } + } + if (loop) { + return Err(createError(`Looping wire ${loop}`, part.span)); + } + return Ok(); + } + private wirePart(part: Part, partChip: Chip): Result { + const result = this.checkLoops(part, partChip); + if (isErr(result)) { + return result; + } + const connections: Connection[] = []; this.inPins.clear(); for (const { lhs, rhs } of part.wires) {