Skip to content

Commit

Permalink
Enforce equal bus widths (#223)
Browse files Browse the repository at this point in the history
  • Loading branch information
netalondon authored Feb 5, 2024
1 parent 0680c88 commit 12b6931
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 3 deletions.
34 changes: 34 additions & 0 deletions simulator/src/chip/builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,40 @@ describe("Chip Builder", () => {
foo.eval();
expect(foo.out("b").busVoltage).toBe(0);
});

it("returns error for mismatching input width", async () => {
try {
const chip = unwrap(
HDL.parse(`CHIP Foo {
IN in[3]; OUT out;
PARTS: Or8Way(in=in, out=out);
}`)
);
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));
}
});

it("returns error for mismatching output width", async () => {
try {
const chip = unwrap(
HDL.parse(`CHIP Foo {
IN in; OUT out[5];
PARTS: Not(in=in, out=out);
}`)
);
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
63 changes: 60 additions & 3 deletions simulator/src/chip/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ export async function build(
interface InternalPin {
isDefined: boolean;
firstUse: Span;
width?: number;
}

interface Wire {
chip: Chip;
lhs: PinParts;
rhs: PinParts;
}

function isConstant(pinName: string): boolean {
Expand All @@ -104,6 +111,20 @@ function isConstant(pinName: string): boolean {
);
}

function getSubBusWidth(pin: PinParts): number | undefined {
if (pin.start != undefined && pin.end != undefined) {
return pin.end - pin.start + 1;
}
return undefined;
}

function display(pin: PinParts): string {
if (pin.start != undefined && pin.end != undefined) {
return `${pin.pin}[${pin.start}..${pin.end}]`;
}
return pin.pin;
}

function createWire(lhs: PinParts, rhs: PinParts): Connection {
return {
to: {
Expand Down Expand Up @@ -172,6 +193,7 @@ class ChipBuilder {
private internalPins: Map<string, InternalPin> = new Map();
private inPins: Map<string, Set<number>> = new Map();
private outPins: Map<string, Set<number>> = new Map();
private wires: Wire[] = [];

constructor(parts: HdlParse, fs?: FileSystem, name?: string) {
this.parts = parts;
Expand Down Expand Up @@ -229,7 +251,12 @@ class ChipBuilder {
return result;
}
}
const result = this.validateInternalPins();
let result = this.validateInternalPins();
if (isErr(result)) {
return result;
}
// We need to check this at the end because during wiring we might not know the width of some internal pins
result = this.validateWireWidths();
if (isErr(result)) {
return result;
}
Expand Down Expand Up @@ -266,7 +293,7 @@ class ChipBuilder {
return result;
}
} else if (partChip.isOutPin(lhs.pin)) {
const result = this.validateOutputWire(rhs);
const result = this.validateOutputWire(partChip, lhs, rhs);
if (isErr(result)) {
return result;
}
Expand All @@ -276,6 +303,9 @@ class ChipBuilder {
span: lhs.span,
});
}
if (!isConstant(rhs.pin)) {
this.wires.push({ chip: partChip, lhs, rhs });
}
return Ok();
}

Expand Down Expand Up @@ -316,7 +346,11 @@ class ChipBuilder {
return Ok();
}

private validateOutputWire(rhs: PinParts): Result<void, CompilationError> {
private validateOutputWire(
partChip: Chip,
lhs: PinParts,
rhs: PinParts
): Result<void, CompilationError> {
let result = this.validateWriteTarget(rhs);
if (isErr(result)) {
return result;
Expand All @@ -337,10 +371,12 @@ class ChipBuilder {
}
// track internal pin creation to detect undefined pins
const pinData = this.internalPins.get(rhs.pin);
const width = getSubBusWidth(lhs) ?? partChip.get(lhs.pin)?.width;
if (pinData == undefined) {
this.internalPins.set(rhs.pin, {
isDefined: true,
firstUse: rhs.span,
width,
});
} else {
if (pinData.isDefined) {
Expand All @@ -350,6 +386,7 @@ class ChipBuilder {
});
}
pinData.isDefined = true;
pinData.width = width;
}
}
return Ok();
Expand Down Expand Up @@ -402,4 +439,24 @@ class ChipBuilder {
}
return Ok();
}

private validateWireWidths(): Result<void, CompilationError> {
for (const wire of this.wires) {
const lhsWidth =
getSubBusWidth(wire.lhs) ?? wire.chip.get(wire.lhs.pin)?.width;
const rhsWidth =
getSubBusWidth(wire.rhs) ??
this.chip.get(wire.rhs.pin)?.width ??
this.internalPins.get(wire.rhs.pin)?.width;
if (lhsWidth != rhsWidth) {
return Err({
message: `Different bus widths: ${display(
wire.lhs
)}(${lhsWidth}) and ${display(wire.rhs)}(${rhsWidth})`,
span: wire.lhs.span,
});
}
}
return Ok();
}
}

0 comments on commit 12b6931

Please sign in to comment.