Skip to content

Commit

Permalink
Report error when chip parts have a loop (#423)
Browse files Browse the repository at this point in the history
* Report error when chip parts have a loop
  • Loading branch information
netalondon authored Aug 14, 2024
1 parent 8c45a9f commit 5d89db0
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 7 deletions.
20 changes: 20 additions & 0 deletions simulator/src/chip/builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,26 @@ describe("Chip Builder", () => {
throw new Error(display(e.message ?? e.shortMessage ?? e));
}
});

it("returns error for part loop", async () => {
try {
const chip = unwrap(
HDL.parse(`CHIP Not {
IN in;
OUT out;
PARTS:
Nand(a=in, b=b, out=c);
Nand(a=in, b=c, out=b);
}`),
);
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 {
Expand Down
2 changes: 0 additions & 2 deletions simulator/src/chip/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,6 @@ class ChipBuilder {
.filter((pin) => this.chip.isClockedPin(pin)),
);

this.chip.sortParts();

// Reset clock order after wiring sub-pins
for (const part of this.chip.parts) {
part.subscribeToClock();
Expand Down
31 changes: 26 additions & 5 deletions simulator/src/chip/chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ export class Chip {
return Ok();
}

sortParts() {
// Returns whether the part connection graph has a loop
sortParts(): boolean {
const sorted: Chip[] = [];
const visited = new Set<Chip>();
const visiting = new Set<Chip>();
Expand All @@ -500,7 +501,7 @@ export class Chip {
sorted.push(node.part);
} else if (!visited.has(node.part)) {
if (visiting.has(node.part)) {
continue;
return true;
}
visiting.add(node.part);

Expand All @@ -522,6 +523,7 @@ export class Chip {
}

this.parts = sorted.reverse();
return false;
}

private findPin(from: string, minWidth?: number): Pin {
Expand Down Expand Up @@ -592,14 +594,23 @@ export class Chip {
chipPin = new OutSubBus(chipPin, to.start, to.width);
}

partPin.connect(chipPin);

if (!part.clockedPins.has(partPin.name)) {
const partToOuts = this.partToOuts.get(part) ?? new Set();
partToOuts.add(chipPin.name);
this.partToOuts.set(part, partToOuts);
}

const loop = this.sortParts();

if (loop) {
const partToOuts = this.partToOuts.get(part) ?? new Set();
partToOuts.delete(chipPin.name);
this.partToOuts.set(part, partToOuts);
return Err({ message: "Circular pin dependency", lhs: false });
} else {
partPin.connect(chipPin);
}

return Ok();
}

Expand Down Expand Up @@ -643,14 +654,24 @@ export class Chip {
partPin = new OutSubBus(partPin, from.start, from.width);
}
}
chipPin.connect(partPin);

if (!part.clockedPins.has(partPin.name)) {
const pinsToPart = this.insToPart.get(chipPin.name) ?? new Set();
pinsToPart.add(part);
this.insToPart.set(chipPin.name, pinsToPart);
}

const loop = this.sortParts();

if (loop) {
const pinsToPart = this.insToPart.get(chipPin.name) ?? new Set();
pinsToPart.delete(part);
this.insToPart.set(chipPin.name, pinsToPart);
return Err({ message: "Circular pin dependency", lhs: true });
} else {
chipPin.connect(partPin);
}

return Ok();
}

Expand Down

0 comments on commit 5d89db0

Please sign in to comment.