components work
This commit is contained in:
parent
cbc416da46
commit
e8c8609217
@ -29,10 +29,10 @@ export class Board {
|
|||||||
|
|
||||||
private wireCachedState = new Map<Wire, ir.State>();
|
private wireCachedState = new Map<Wire, ir.State>();
|
||||||
|
|
||||||
constructor() {}
|
constructor(private repo: ComponentRepo) {}
|
||||||
|
|
||||||
static withExample(repo: ComponentRepo): Board {
|
static withExample(repo: ComponentRepo): Board {
|
||||||
const board = new Board();
|
const board = new Board(repo);
|
||||||
board.placeComponent(repo.get("input"), v2(100, 100));
|
board.placeComponent(repo.get("input"), v2(100, 100));
|
||||||
board.placeComponent(repo.get("input"), v2(100, 200));
|
board.placeComponent(repo.get("input"), v2(100, 200));
|
||||||
board.placeComponent(repo.get("and"), v2(300, 150));
|
board.placeComponent(repo.get("and"), v2(300, 150));
|
||||||
@ -52,13 +52,10 @@ export class Board {
|
|||||||
return board;
|
return board;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromSerialized(
|
static fromSerialized(data: ser.Board, repo: ComponentRepo): Board {
|
||||||
data: ser.Board,
|
const board = new Board(repo);
|
||||||
kindMap: Map<string, ComponentKind>,
|
|
||||||
): Board {
|
|
||||||
const board = new Board();
|
|
||||||
board.components = data.components.map((c) =>
|
board.components = data.components.map((c) =>
|
||||||
Component.fromSerialized(c, kindMap),
|
Component.fromSerialized(c, repo.defs),
|
||||||
);
|
);
|
||||||
board.joints = data.joints.map((j) => Joint.fromSerialized(j));
|
board.joints = data.joints.map((j) => Joint.fromSerialized(j));
|
||||||
board.wires = data.wires.map((w) =>
|
board.wires = data.wires.map((w) =>
|
||||||
@ -318,12 +315,20 @@ export class Board {
|
|||||||
|
|
||||||
simulate(inputStates: Map<Component, boolean>) {
|
simulate(inputStates: Map<Component, boolean>) {
|
||||||
console.log("Lowering to IR");
|
console.log("Lowering to IR");
|
||||||
const comp = this.toIr();
|
const comps = new Map<string, ir.Component>();
|
||||||
|
const comp = this.toIr("<main>", comps);
|
||||||
console.log("Before optimizing");
|
console.log("Before optimizing");
|
||||||
|
for (const [_label, comp] of comps) {
|
||||||
|
console.log(...new ir.ComponentPrinter().stringifyToConsole(comp));
|
||||||
|
}
|
||||||
console.log(...new ir.ComponentPrinter().stringifyToConsole(comp));
|
console.log(...new ir.ComponentPrinter().stringifyToConsole(comp));
|
||||||
|
|
||||||
|
for (const [_label, comp] of comps) {
|
||||||
|
new ir.ComponentOptimizer(comp, []).optimizeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
const replacedStates: [ir.State, ir.State][] = [];
|
const replacedStates: [ir.State, ir.State][] = [];
|
||||||
new ir.ComponentOptimizer(comp, replacedStates).optimize();
|
new ir.ComponentOptimizer(comp, replacedStates).optimizeMain();
|
||||||
|
|
||||||
for (const [oldState, newState] of replacedStates) {
|
for (const [oldState, newState] of replacedStates) {
|
||||||
this.stateWireMap
|
this.stateWireMap
|
||||||
@ -333,6 +338,9 @@ export class Board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log("After optimizing");
|
console.log("After optimizing");
|
||||||
|
for (const [_label, comp] of comps) {
|
||||||
|
console.log(...new ir.ComponentPrinter().stringifyToConsole(comp));
|
||||||
|
}
|
||||||
console.log(...new ir.ComponentPrinter().stringifyToConsole(comp));
|
console.log(...new ir.ComponentPrinter().stringifyToConsole(comp));
|
||||||
|
|
||||||
const inputs = this.inputArray(inputStates);
|
const inputs = this.inputArray(inputStates);
|
||||||
@ -357,7 +365,7 @@ export class Board {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toIr(): ir.Component {
|
toIr(label: string, comps: Map<string, ir.Component>): ir.Component {
|
||||||
for (const comp of this.components) {
|
for (const comp of this.components) {
|
||||||
comp.markedWiresConnected = [];
|
comp.markedWiresConnected = [];
|
||||||
}
|
}
|
||||||
@ -384,7 +392,7 @@ export class Board {
|
|||||||
outputIdcs.set(output, i);
|
outputIdcs.set(output, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
const b = new ir.ComponentBuilder(inputs.length, outputs.length, "main");
|
const b = new ir.ComponentBuilder(inputs.length, outputs.length, label);
|
||||||
|
|
||||||
this.stateWireMap.clear();
|
this.stateWireMap.clear();
|
||||||
const wireStates = new Map<Wire, ir.State>();
|
const wireStates = new Map<Wire, ir.State>();
|
||||||
@ -429,14 +437,32 @@ export class Board {
|
|||||||
return b.makeBinary("And", inputStmt(0), inputStmt(1));
|
return b.makeBinary("And", inputStmt(0), inputStmt(1));
|
||||||
case "or":
|
case "or":
|
||||||
return b.makeBinary("Or", inputStmt(0), inputStmt(1));
|
return b.makeBinary("Or", inputStmt(0), inputStmt(1));
|
||||||
default:
|
default: {
|
||||||
throw new Error("not implemented");
|
const savedBoard = this.repo.getSavedBoard(comp.kind.label);
|
||||||
|
if (!savedBoard) {
|
||||||
|
throw new Error(`no component '${comp.kind.label}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const label = comp.kind.label;
|
||||||
|
const board = Board.fromSerialized(savedBoard, this.repo);
|
||||||
|
|
||||||
|
const ir = comps.get(label) ?? board.toIr(label, comps);
|
||||||
|
comps.set(label, ir);
|
||||||
|
|
||||||
|
return b.makeCall(
|
||||||
|
ir,
|
||||||
|
comp.kind.inputs.map((_, i) => inputStmt(i)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
for (const [wire, connection] of comp.markedWiresConnected) {
|
for (const [wire, connection] of comp.markedWiresConnected) {
|
||||||
if (connection.tag === "OutputPin") {
|
if (connection.tag === "OutputPin") {
|
||||||
b.makeSetState(wireStates.get(wire)!, stmt);
|
b.makeSetState(
|
||||||
|
wireStates.get(wire)!,
|
||||||
|
stmt.kind.tag === "Call" ? b.makeElem(stmt, connection.i) : stmt,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -491,6 +517,7 @@ export interface BoardVisitor {
|
|||||||
|
|
||||||
export class ComponentRepo {
|
export class ComponentRepo {
|
||||||
public defs = new Map<string, ComponentKind>();
|
public defs = new Map<string, ComponentKind>();
|
||||||
|
private savedBoards = new Map<string, ser.Board>();
|
||||||
|
|
||||||
static withDefaults(): ComponentRepo {
|
static withDefaults(): ComponentRepo {
|
||||||
const repo = new ComponentRepo();
|
const repo = new ComponentRepo();
|
||||||
@ -507,12 +534,14 @@ export class ComponentRepo {
|
|||||||
repo.defs = new Map(
|
repo.defs = new Map(
|
||||||
data.defs.map((e) => [e[0], ComponentKind.fromSerialized(e[1])]),
|
data.defs.map((e) => [e[0], ComponentKind.fromSerialized(e[1])]),
|
||||||
);
|
);
|
||||||
|
repo.savedBoards = new Map(data.savedBoards);
|
||||||
return repo;
|
return repo;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize(): ser.ComponentRepo {
|
serialize(): ser.ComponentRepo {
|
||||||
return {
|
return {
|
||||||
defs: [...this.defs.entries()].map((e) => [e[0], e[1].serialize()]),
|
defs: [...this.defs.entries()].map((e) => [e[0], e[1].serialize()]),
|
||||||
|
savedBoards: [...this.savedBoards],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,6 +560,14 @@ export class ComponentRepo {
|
|||||||
}
|
}
|
||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addSavedBoard(ident: string, savedBoard: ser.Board) {
|
||||||
|
this.savedBoards.set(ident, savedBoard);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSavedBoard(ident: string): ser.Board | null {
|
||||||
|
return this.savedBoards.get(ident) ?? null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Component {
|
export class Component {
|
||||||
|
|||||||
@ -74,6 +74,8 @@ export class Editor {
|
|||||||
}
|
}
|
||||||
case "SelectTab": {
|
case "SelectTab": {
|
||||||
this.switchTab(ev.idx);
|
this.switchTab(ev.idx);
|
||||||
|
this.events.send({ tag: "SimulateRequest" });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "CloseComponent": {
|
case "CloseComponent": {
|
||||||
@ -89,7 +91,7 @@ export class Editor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "SimulateRequest": {
|
case "SimulateRequest": {
|
||||||
// this.runSimulation();
|
this.runSimulation();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "SaveRequest": {
|
case "SaveRequest": {
|
||||||
@ -146,7 +148,6 @@ export class Editor {
|
|||||||
|
|
||||||
runSimulation() {
|
runSimulation() {
|
||||||
this.board.simulate(this.inputStates);
|
this.board.simulate(this.inputStates);
|
||||||
this.events.send({ tag: "RenderRequest" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSelectTool(tool: string) {
|
private onSelectTool(tool: string) {
|
||||||
|
|||||||
@ -10,7 +10,6 @@ export class Project {
|
|||||||
private events: EventBus,
|
private events: EventBus,
|
||||||
private boardEditors: BoardEditor[],
|
private boardEditors: BoardEditor[],
|
||||||
public componentRepo: ComponentRepo,
|
public componentRepo: ComponentRepo,
|
||||||
private savedBoards: Map<string, ser.Board>,
|
|
||||||
) {
|
) {
|
||||||
this.current = boardEditors[this.selectedIdx];
|
this.current = boardEditors[this.selectedIdx];
|
||||||
}
|
}
|
||||||
@ -34,7 +33,6 @@ export class Project {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
repo,
|
repo,
|
||||||
new Map(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,13 +44,10 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
console.log("Saving");
|
// console.log("Saving");
|
||||||
const data = this.serialize();
|
const data = this.serialize();
|
||||||
globalThis.localStorage.setItem(
|
globalThis.localStorage.setItem("nandsim", JSON.stringify(data));
|
||||||
"nandsim",
|
// console.log(data);
|
||||||
JSON.stringify(this.serialize()),
|
|
||||||
);
|
|
||||||
console.log(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static fromSerialized(data: ser.Project, events: EventBus): Project {
|
private static fromSerialized(data: ser.Project, events: EventBus): Project {
|
||||||
@ -62,11 +57,10 @@ export class Project {
|
|||||||
data.boardEditors.map(
|
data.boardEditors.map(
|
||||||
(data): BoardEditor => ({
|
(data): BoardEditor => ({
|
||||||
name: data.name,
|
name: data.name,
|
||||||
board: Board.fromSerialized(data.board, repo.defs),
|
board: Board.fromSerialized(data.board, repo),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
repo,
|
repo,
|
||||||
new Map(data.savedBoards),
|
|
||||||
);
|
);
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
@ -82,7 +76,6 @@ export class Project {
|
|||||||
),
|
),
|
||||||
currentBoardEditorIdx: this.selectedIdx,
|
currentBoardEditorIdx: this.selectedIdx,
|
||||||
componentRepo,
|
componentRepo,
|
||||||
savedBoards: [...this.savedBoards],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +96,7 @@ export class Project {
|
|||||||
newTab(): number {
|
newTab(): number {
|
||||||
this.boardEditors.push({
|
this.boardEditors.push({
|
||||||
name: `(Unnamed ${this.boardEditors.length})`,
|
name: `(Unnamed ${this.boardEditors.length})`,
|
||||||
board: new Board(),
|
board: new Board(this.componentRepo),
|
||||||
});
|
});
|
||||||
this.events.send({ tag: "ShowSelectedTab", idx: this.selectedIdx });
|
this.events.send({ tag: "ShowSelectedTab", idx: this.selectedIdx });
|
||||||
return this.boardEditors.length - 1;
|
return this.boardEditors.length - 1;
|
||||||
@ -114,11 +107,11 @@ export class Project {
|
|||||||
this.current = this.boardEditors[this.selectedIdx];
|
this.current = this.boardEditors[this.selectedIdx];
|
||||||
this.events.send({ tag: "ShowSelectedTab", idx: this.selectedIdx });
|
this.events.send({ tag: "ShowSelectedTab", idx: this.selectedIdx });
|
||||||
this.events.send({ tag: "ShowSelectedTool", tool: this.current.name });
|
this.events.send({ tag: "ShowSelectedTool", tool: this.current.name });
|
||||||
|
this.events.send({ tag: "SaveRequest" });
|
||||||
}
|
}
|
||||||
|
|
||||||
closeTab(): number {
|
closeTab(): number {
|
||||||
const [removed] = this.boardEditors.splice(this.selectedIdx, 1);
|
const [_removed] = this.boardEditors.splice(this.selectedIdx, 1);
|
||||||
this.savedBoards.set(removed.name, removed.board.serialize());
|
|
||||||
this.events.send({ tag: "SaveRequest" });
|
this.events.send({ tag: "SaveRequest" });
|
||||||
|
|
||||||
if (this.boardEditors.length === 0) {
|
if (this.boardEditors.length === 0) {
|
||||||
@ -138,7 +131,13 @@ export class Project {
|
|||||||
this.current.name,
|
this.current.name,
|
||||||
this.current.board.toComponentKind(this.current.name),
|
this.current.board.toComponentKind(this.current.name),
|
||||||
);
|
);
|
||||||
|
this.componentRepo.addSavedBoard(
|
||||||
|
this.current.name,
|
||||||
|
this.current.board.serialize(),
|
||||||
|
);
|
||||||
|
|
||||||
this.events.send({ tag: "ShowSelectedTool", tool: this.current.name });
|
this.events.send({ tag: "ShowSelectedTool", tool: this.current.name });
|
||||||
|
this.events.send({ tag: "SaveRequest" });
|
||||||
}
|
}
|
||||||
|
|
||||||
tabWithTool(name: string): number {
|
tabWithTool(name: string): number {
|
||||||
@ -148,12 +147,12 @@ export class Project {
|
|||||||
return foundIdx;
|
return foundIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
const saved = this.savedBoards.get(name);
|
const saved = this.componentRepo.getSavedBoard(name);
|
||||||
if (!saved) throw new Error(`cannot open '${name}'`);
|
if (!saved) throw new Error(`cannot open '${name}'`);
|
||||||
|
|
||||||
this.boardEditors.push({
|
this.boardEditors.push({
|
||||||
name: name,
|
name: name,
|
||||||
board: Board.fromSerialized(saved, this.componentRepo.defs),
|
board: Board.fromSerialized(saved, this.componentRepo),
|
||||||
});
|
});
|
||||||
this.events.send({ tag: "ShowSelectedTab", idx: this.selectedIdx });
|
this.events.send({ tag: "ShowSelectedTab", idx: this.selectedIdx });
|
||||||
return this.boardEditors.length - 1;
|
return this.boardEditors.length - 1;
|
||||||
|
|||||||
@ -29,8 +29,10 @@ export class Stmt {
|
|||||||
case "And":
|
case "And":
|
||||||
case "Or":
|
case "Or":
|
||||||
return [k.lhs, k.rhs];
|
return [k.lhs, k.rhs];
|
||||||
case "Component":
|
case "Call":
|
||||||
return [...k.inputs];
|
return [...k.inputs];
|
||||||
|
case "Elem":
|
||||||
|
return [k.src];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,10 +55,11 @@ export class Stmt {
|
|||||||
if (k.lhs === oldStmt) k.lhs = newStmt;
|
if (k.lhs === oldStmt) k.lhs = newStmt;
|
||||||
if (k.rhs === oldStmt) k.rhs = newStmt;
|
if (k.rhs === oldStmt) k.rhs = newStmt;
|
||||||
break;
|
break;
|
||||||
case "Component":
|
case "Call":
|
||||||
k.inputs = k.inputs.map((stmt) =>
|
k.inputs = k.inputs.map((stmt) => (stmt === oldStmt ? newStmt : stmt));
|
||||||
stmt === oldStmt ? newStmt : oldStmt,
|
break;
|
||||||
);
|
case "Elem":
|
||||||
|
if (k.src === oldStmt) k.src = newStmt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,7 +85,8 @@ export type StmtKind =
|
|||||||
| { tag: "SetState"; state: State; src: Stmt }
|
| { tag: "SetState"; state: State; src: Stmt }
|
||||||
| { tag: "Not"; op: Stmt }
|
| { tag: "Not"; op: Stmt }
|
||||||
| { tag: "And" | "Or"; lhs: Stmt; rhs: Stmt }
|
| { tag: "And" | "Or"; lhs: Stmt; rhs: Stmt }
|
||||||
| { tag: "Component"; comp: Component; inputs: Stmt[]; outputs: Stmt[] };
|
| { tag: "Call"; comp: Component; inputs: Stmt[] }
|
||||||
|
| { tag: "Elem"; src: Stmt; i: number };
|
||||||
|
|
||||||
export class State {}
|
export class State {}
|
||||||
|
|
||||||
@ -123,6 +127,12 @@ export class ComponentBuilder {
|
|||||||
makeBinary(tag: "And" | "Or", lhs: Stmt, rhs: Stmt): Stmt {
|
makeBinary(tag: "And" | "Or", lhs: Stmt, rhs: Stmt): Stmt {
|
||||||
return this.makeStmt({ tag, lhs, rhs });
|
return this.makeStmt({ tag, lhs, rhs });
|
||||||
}
|
}
|
||||||
|
makeCall(comp: Component, inputs: Stmt[]): Stmt {
|
||||||
|
return this.makeStmt({ tag: "Call", comp, inputs });
|
||||||
|
}
|
||||||
|
makeElem(src: Stmt, i: number): Stmt {
|
||||||
|
return this.makeStmt({ tag: "Elem", src, i });
|
||||||
|
}
|
||||||
|
|
||||||
private makeStmt(kind: StmtKind): Stmt {
|
private makeStmt(kind: StmtKind): Stmt {
|
||||||
const stmt = new Stmt(kind);
|
const stmt = new Stmt(kind);
|
||||||
@ -186,7 +196,15 @@ export class ComponentOptimizer {
|
|||||||
private replacedStates: [State, State][],
|
private replacedStates: [State, State][],
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
optimize() {
|
optimizeMain() {
|
||||||
|
this.optimizeWithOptions(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
optimizeComponent() {
|
||||||
|
this.optimizeWithOptions(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private optimizeWithOptions(removeUnusedStates: boolean) {
|
||||||
const score = () => this.comp.stmts.length * 100 + this.comp.states.length;
|
const score = () => this.comp.stmts.length * 100 + this.comp.states.length;
|
||||||
|
|
||||||
let scoreBefore: number;
|
let scoreBefore: number;
|
||||||
@ -199,6 +217,9 @@ export class ComponentOptimizer {
|
|||||||
this.collapseStates();
|
this.collapseStates();
|
||||||
this.eliminateUnusedStates();
|
this.eliminateUnusedStates();
|
||||||
this.eliminateRedundantSetState();
|
this.eliminateRedundantSetState();
|
||||||
|
if (removeUnusedStates) {
|
||||||
|
this.eliminateIndependentSetState();
|
||||||
|
}
|
||||||
} while (score() !== scoreBefore);
|
} while (score() !== scoreBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,6 +330,28 @@ export class ComponentOptimizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eliminateIndependentSetState() {
|
||||||
|
const mut = new StmtsMutater(this.comp, this.replacedStates);
|
||||||
|
|
||||||
|
const usedStates = new Set<State>();
|
||||||
|
for (const stmt of mut) {
|
||||||
|
const k = stmt.kind;
|
||||||
|
switch (k.tag) {
|
||||||
|
case "GetState":
|
||||||
|
usedStates.add(k.state);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const stmt of [...mut]) {
|
||||||
|
if (stmt.kind.tag === "SetState" && !usedStates.has(stmt.kind.state)) {
|
||||||
|
mut.removeStmt(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private indexMap(): Map<Stmt, number> {
|
private indexMap(): Map<Stmt, number> {
|
||||||
return new Map(this.comp.stmts.map((stmt, i) => [stmt, i]));
|
return new Map(this.comp.stmts.map((stmt, i) => [stmt, i]));
|
||||||
}
|
}
|
||||||
@ -355,7 +398,7 @@ export class ComponentPrinter {
|
|||||||
"\\c(color: #d44949; font-weight: bold)$&\\c",
|
"\\c(color: #d44949; font-weight: bold)$&\\c",
|
||||||
)
|
)
|
||||||
.replaceAll(
|
.replaceAll(
|
||||||
/(?:Null)|(?:Input)|(?:Output)|(?:GetState)|(?:SetState)|(?:Not)|(?:And)|(?:Or)|(?:Component)/g,
|
/(?:Null)|(?:Input)|(?:Output)|(?:GetState)|(?:SetState)|(?:Not)|(?:And)|(?:Or)|(?:Call)|(?:Elem)/g,
|
||||||
"\\c(color: orange)$&\\c",
|
"\\c(color: orange)$&\\c",
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -407,8 +450,10 @@ export class ComponentPrinter {
|
|||||||
case "And":
|
case "And":
|
||||||
case "Or":
|
case "Or":
|
||||||
return `${stmtId(stmt)} = ${k.tag} ${stmtId(k.lhs)}, ${stmtId(k.rhs)}`;
|
return `${stmtId(stmt)} = ${k.tag} ${stmtId(k.lhs)}, ${stmtId(k.rhs)}`;
|
||||||
case "Component":
|
case "Call":
|
||||||
return `Component <...>`;
|
return `${stmtId(stmt)} = Call ${k.comp.label} (${k.inputs.map((s) => stmtId(s)).join(", ")})`;
|
||||||
|
case "Elem":
|
||||||
|
return `${stmtId(stmt)} = Elem ${stmtId(k.src)}, ${k.i}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ export type Project = {
|
|||||||
boardEditors: BoardEditor[];
|
boardEditors: BoardEditor[];
|
||||||
currentBoardEditorIdx: number;
|
currentBoardEditorIdx: number;
|
||||||
componentRepo: ComponentRepo;
|
componentRepo: ComponentRepo;
|
||||||
savedBoards: [string, Board][];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BoardEditor = {
|
export type BoardEditor = {
|
||||||
@ -37,6 +36,7 @@ export type WireConnection =
|
|||||||
|
|
||||||
export type ComponentRepo = {
|
export type ComponentRepo = {
|
||||||
defs: [string, ComponentKind][];
|
defs: [string, ComponentKind][];
|
||||||
|
savedBoards: [string, Board][];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ComponentKind = {
|
export type ComponentKind = {
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export class Sim {
|
|||||||
const regs = new Array<boolean>(comp.stmts.length).fill(false);
|
const regs = new Array<boolean>(comp.stmts.length).fill(false);
|
||||||
|
|
||||||
const stateDependents = new Map<ir.State, number>();
|
const stateDependents = new Map<ir.State, number>();
|
||||||
|
const callOutput = new Map<ir.Stmt, boolean[]>();
|
||||||
|
|
||||||
const operation = <Ops extends ir.Stmt[]>(
|
const operation = <Ops extends ir.Stmt[]>(
|
||||||
action: (...ops: boolean[]) => boolean,
|
action: (...ops: boolean[]) => boolean,
|
||||||
@ -65,8 +66,25 @@ export class Sim {
|
|||||||
case "Or":
|
case "Or":
|
||||||
regs[i] = operation((a, b) => a || b, k.lhs, k.rhs);
|
regs[i] = operation((a, b) => a || b, k.lhs, k.rhs);
|
||||||
break;
|
break;
|
||||||
case "Component":
|
case "Call": {
|
||||||
throw new Error("not implemented");
|
const outputs = new Array<boolean>(k.comp.outputs).fill(false);
|
||||||
|
new Sim(
|
||||||
|
k.comp,
|
||||||
|
k.inputs.map((stmt) => regs[stmtIdcs.get(stmt)!]),
|
||||||
|
outputs,
|
||||||
|
this.state,
|
||||||
|
).simulate();
|
||||||
|
callOutput.set(stmt, outputs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Elem": {
|
||||||
|
const outputs = callOutput.get(k.src);
|
||||||
|
if (!outputs) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
regs[i] = outputs[k.i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log("Sim:", i, stmt.kind.tag, inputs, outputs, this.state);
|
// console.log("Sim:", i, stmt.kind.tag, inputs, outputs, this.state);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user