@tscircuit/core 0.0.2180 → 0.0.2181

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +290 -24
  2. package/dist/index.js +614 -11
  3. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -18,6 +18,8 @@ __export(components_exports, {
18
18
  AnalogAnalysisSimulation: () => AnalogAnalysisSimulation,
19
19
  AnalogDcOperatingPointSimulation: () => AnalogDcOperatingPointSimulation,
20
20
  AnalogDcSweepSimulation: () => AnalogDcSweepSimulation,
21
+ AnalogDigitalStimulus: () => AnalogDigitalStimulus,
22
+ AnalogEyeDiagram: () => AnalogEyeDiagram,
21
23
  AnalogSimulation: () => AnalogSimulation,
22
24
  AnalogSweepParameter: () => AnalogSweepParameter,
23
25
  AnalogTransientSimulation: () => AnalogTransientSimulation,
@@ -66,6 +68,7 @@ __export(components_exports, {
66
68
  Fuse: () => Fuse,
67
69
  Group: () => Group5,
68
70
  Hole: () => Hole,
71
+ IbisModel: () => IbisModel,
69
72
  Inductor: () => Inductor,
70
73
  Interconnect: () => Interconnect,
71
74
  Jumper: () => Jumper,
@@ -1751,6 +1754,11 @@ var renderPhaseIndexMap = new Map(
1751
1754
  var asyncPhaseDependencies = {
1752
1755
  InflateSubcircuitCircuitJson: ["RenderIsolatedSubcircuits"],
1753
1756
  ResolveFootprintPinLabels: ["PcbFootprintStringRender", "FetchPartFootprint"],
1757
+ SimulationRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
1758
+ SimulationSpiceEngineRender: [
1759
+ "PcbFootprintStringRender",
1760
+ "FetchPartFootprint"
1761
+ ],
1754
1762
  SchematicComponentRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
1755
1763
  SchematicPortRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
1756
1764
  SymbolContainerRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
@@ -20450,6 +20458,139 @@ function inflatePcbBoard(pcbBoard, inflatorContext) {
20450
20458
  return board;
20451
20459
  }
20452
20460
 
20461
+ // lib/components/primitive-components/Group/Subcircuit/inflators/inflateSimulation.ts
20462
+ import { getElementId } from "@tscircuit/circuit-json-util";
20463
+ var ibisSimulationTypes = [
20464
+ "simulation_ibis_model",
20465
+ "simulation_ibis_pin_state",
20466
+ "simulation_digital_stimulus",
20467
+ "simulation_eye_diagram"
20468
+ ];
20469
+ var simulationTypes = [
20470
+ "simulation_experiment",
20471
+ "simulation_voltage_probe",
20472
+ ...ibisSimulationTypes
20473
+ ];
20474
+ var InflatedSimulation = class extends PrimitiveComponent2 {
20475
+ constructor(inflationCtx) {
20476
+ super({});
20477
+ this.inflationCtx = inflationCtx;
20478
+ }
20479
+ inflationCtx;
20480
+ get config() {
20481
+ return { ...super.config, componentName: "InflatedSimulation" };
20482
+ }
20483
+ doInitialSimulationRender() {
20484
+ if (this.getInheritedProperty("analogSimulationDisabled")) return;
20485
+ restoreSimulationRecords(this.inflationCtx);
20486
+ }
20487
+ };
20488
+ function restoreSimulationRecords({
20489
+ injectionDb,
20490
+ subcircuit,
20491
+ groupsMap
20492
+ }) {
20493
+ const { db: db2 } = subcircuit.root;
20494
+ const eyes = injectionDb.simulation_eye_diagram.list();
20495
+ const experimentIds = new Set(
20496
+ [
20497
+ ...injectionDb.simulation_ibis_pin_state.list(),
20498
+ ...injectionDb.simulation_digital_stimulus.list(),
20499
+ ...eyes
20500
+ ].map((record) => record.simulation_experiment_id)
20501
+ );
20502
+ const probeIds = new Set(eyes.map((eye) => eye.simulation_voltage_probe_id));
20503
+ const restoredIds = /* @__PURE__ */ new Map();
20504
+ const remapId = (originalId, field) => {
20505
+ const restoredId = restoredIds.get(originalId);
20506
+ if (restoredId) return restoredId;
20507
+ let matchedId;
20508
+ if (field === "subcircuit_id") {
20509
+ const sourceGroup = injectionDb.source_group.list().find((group2) => group2.subcircuit_id === originalId);
20510
+ const group = sourceGroup && groupsMap?.get(sourceGroup.source_group_id);
20511
+ matchedId = group?.getSubcircuit().subcircuit_id ?? void 0;
20512
+ } else if (field === "source_component_id") {
20513
+ const original = injectionDb.source_component.get(originalId);
20514
+ const group = original?.source_group_id ? groupsMap?.get(original.source_group_id) : subcircuit;
20515
+ if (original && group?.source_group_id) {
20516
+ const components = db2.source_component.list({
20517
+ source_group_id: group.source_group_id,
20518
+ name: original.name
20519
+ });
20520
+ if (components.length === 1)
20521
+ matchedId = components[0].source_component_id;
20522
+ }
20523
+ } else if (field.endsWith("source_port_id")) {
20524
+ const original = injectionDb.source_port.get(originalId);
20525
+ if (original?.source_component_id) {
20526
+ const componentId = remapId(
20527
+ original.source_component_id,
20528
+ "source_component_id"
20529
+ );
20530
+ const ports = db2.source_port.list({ source_component_id: componentId }).filter(
20531
+ (port) => original.pin_number !== void 0 ? port.pin_number === original.pin_number : port.name === original.name
20532
+ );
20533
+ if (ports.length === 1) matchedId = ports[0].source_port_id;
20534
+ }
20535
+ } else if (field.endsWith("source_net_id")) {
20536
+ const original = injectionDb.source_net.get(originalId);
20537
+ if (original) {
20538
+ const nets = db2.source_net.list({
20539
+ name: original.name,
20540
+ subcircuit_id: original.subcircuit_id ? remapId(original.subcircuit_id, "subcircuit_id") : subcircuit.subcircuit_id
20541
+ });
20542
+ if (nets.length === 1) matchedId = nets[0].source_net_id;
20543
+ }
20544
+ }
20545
+ if (!matchedId) {
20546
+ throw new Error(
20547
+ `Cannot restore simulation records: unable to remap ${field} safely.`
20548
+ );
20549
+ }
20550
+ restoredIds.set(originalId, matchedId);
20551
+ return matchedId;
20552
+ };
20553
+ const remapReferences = (value, field) => {
20554
+ if (typeof value === "string" && field.endsWith("_id"))
20555
+ return remapId(value, field);
20556
+ if (Array.isArray(value))
20557
+ return value.map((entry) => remapReferences(entry, field));
20558
+ if (value && typeof value === "object") {
20559
+ return Object.fromEntries(
20560
+ Object.entries(value).map(([key, entry]) => [
20561
+ key,
20562
+ remapReferences(
20563
+ entry,
20564
+ field === "ibis_pin_name_to_source_port_id" ? "source_port_id" : key
20565
+ )
20566
+ ])
20567
+ );
20568
+ }
20569
+ return value;
20570
+ };
20571
+ for (const type of simulationTypes) {
20572
+ for (const record of injectionDb[type].list()) {
20573
+ if (record.type === "simulation_experiment" && !experimentIds.has(record.simulation_experiment_id) || record.type === "simulation_voltage_probe" && !probeIds.has(record.simulation_voltage_probe_id))
20574
+ continue;
20575
+ const primaryIdField = `${type}_id`;
20576
+ const fields = Object.fromEntries(
20577
+ Object.entries(record).filter(([key]) => key !== primaryIdField)
20578
+ );
20579
+ const restored = db2.insert(
20580
+ remapReferences(fields, "")
20581
+ );
20582
+ restoredIds.set(getElementId(record), getElementId(restored));
20583
+ }
20584
+ }
20585
+ }
20586
+ function inflateSimulation(inflationCtx) {
20587
+ if (!ibisSimulationTypes.some(
20588
+ (type) => inflationCtx.injectionDb[type].list().length > 0
20589
+ ))
20590
+ return;
20591
+ inflationCtx.subcircuit.add(new InflatedSimulation(inflationCtx));
20592
+ }
20593
+
20453
20594
  // lib/components/normal-components/Capacitor.ts
20454
20595
  import { capacitorProps, resolveManufacturerPartNumber as resolveManufacturerPartNumber4 } from "@tscircuit/props";
20455
20596
  import { formatSiUnit } from "format-si-unit";
@@ -85433,7 +85574,7 @@ var buildPowerPourPolygons = (problem) => {
85433
85574
  var getLayerColor = (layer) => layer === "top" ? "#c2453a" : layer === "bottom" ? "#5b7fd8" : "#c58b43";
85434
85575
 
85435
85576
  // node_modules/@tscircuit/implicit-copper-pour-solver/lib/prepare-circuit-json.ts
85436
- import { getElementId } from "@tscircuit/circuit-json-util";
85577
+ import { getElementId as getElementId2 } from "@tscircuit/circuit-json-util";
85437
85578
  import {
85438
85579
  getBoundFromCenteredRect,
85439
85580
  getBoundsFromPoints as getBoundsFromPoints8
@@ -85756,7 +85897,7 @@ var prepareCircuitJson = (input) => {
85756
85897
  );
85757
85898
  const netIndexByConnectivityNetwork = /* @__PURE__ */ new Map();
85758
85899
  const getConnectivityNetIndex = (element) => {
85759
- const elementId = getElementId(element);
85900
+ const elementId = getElementId2(element);
85760
85901
  const connectivityNetworkId = connectivityMap.getNetConnectedToId(elementId);
85761
85902
  if (connectivityNetworkId) {
85762
85903
  const connectedSourceNetIndexes = sourceNets.flatMap(
@@ -85797,7 +85938,7 @@ var prepareCircuitJson = (input) => {
85797
85938
  }
85798
85939
  const connectivityNetIndex = getConnectivityNetIndex(element);
85799
85940
  if (connectivityNetIndex !== void 0) return connectivityNetIndex;
85800
- const elementId = getElementId(element);
85941
+ const elementId = getElementId2(element);
85801
85942
  return getOrCreateImplicitNetIndex(
85802
85943
  `${element.type}:${elementId}`,
85803
85944
  elementId
@@ -118479,6 +118620,10 @@ function Group_doInitialSimulationSpiceEngineRender(group) {
118479
118620
  debug12("No simulation experiment found, skipping simulation");
118480
118621
  continue;
118481
118622
  }
118623
+ if (simulationExperiment.spice_engine === "pcb_spice" && (!spiceEngineMap.pcb_spice || isExternalIbisExperiment(root.db, simulationExperimentId))) {
118624
+ debug12("Skipping external pcb_spice experiment during rendering");
118625
+ continue;
118626
+ }
118482
118627
  const simulationScope = analogSimulation.getGroup() ?? group;
118483
118628
  const voltageProbes = simulationScope.selectAll("voltageprobe");
118484
118629
  const ammeters = simulationScope.selectAll("ammeter");
@@ -118687,6 +118832,10 @@ ${simulationRuns.map((simulationRun) => simulationRun.spiceString).join("\n")}`
118687
118832
  });
118688
118833
  }
118689
118834
  }
118835
+ function isExternalIbisExperiment(db2, simulationExperimentId) {
118836
+ const belongsToExperiment = (record) => record.simulation_experiment_id === simulationExperimentId;
118837
+ return db2.simulation_ibis_pin_state.list().some(belongsToExperiment) || db2.simulation_digital_stimulus.list().some(belongsToExperiment) || db2.simulation_eye_diagram.list().some(belongsToExperiment);
118838
+ }
118690
118839
 
118691
118840
  // lib/components/primitive-components/Group/Group_doInitialSourceAddConnectivityMapKey.ts
118692
118841
  import { ConnectivityMap as ConnectivityMap5 } from "circuit-json-to-connectivity-map";
@@ -119560,7 +119709,7 @@ var RoutingPhasePreparationError = class extends Error {
119560
119709
  var package_default = {
119561
119710
  name: "@tscircuit/core",
119562
119711
  type: "module",
119563
- version: "0.0.2179",
119712
+ version: "0.0.2180",
119564
119713
  types: "dist/index.d.ts",
119565
119714
  main: "dist/index.js",
119566
119715
  module: "dist/index.js",
@@ -119619,7 +119768,7 @@ var package_default = {
119619
119768
  "@tscircuit/miniflex": "^0.0.4",
119620
119769
  "@tscircuit/modelprinter": "^0.0.18",
119621
119770
  "@tscircuit/ngspice-spice-engine": "^0.0.20",
119622
- "@tscircuit/props": "^0.0.704",
119771
+ "@tscircuit/props": "^0.0.705",
119623
119772
  "@tscircuit/schematic-match-adapt": "^0.0.18",
119624
119773
  "@tscircuit/schematic-trace-solver": "https://jscdn.tscircuit.com/@tscircuit/schematic-trace-solver/0.0.230.tgz",
119625
119774
  "@tscircuit/solver-utils": "^0.0.16",
@@ -119635,7 +119784,7 @@ var package_default = {
119635
119784
  "bun-match-svg": "0.0.12",
119636
119785
  "calculate-elbow": "^0.0.12",
119637
119786
  "chokidar-cli": "^3.0.0",
119638
- "circuit-json": "^0.0.528",
119787
+ "circuit-json": "^0.0.529",
119639
119788
  "circuit-json-to-bpc": "^0.0.13",
119640
119789
  "circuit-json-to-connectivity-map": "^0.0.33",
119641
119790
  "circuit-json-to-gltf": "^0.0.151",
@@ -119702,8 +119851,8 @@ var package_default = {
119702
119851
  "jscad-fiber": "^0.0.88"
119703
119852
  },
119704
119853
  overrides: {
119705
- "@tscircuit/props": "^0.0.704",
119706
- "circuit-json": "^0.0.528",
119854
+ "@tscircuit/props": "^0.0.705",
119855
+ "circuit-json": "^0.0.529",
119707
119856
  "@tscircuit/cableprinter": "^0.0.6"
119708
119857
  }
119709
119858
  };
@@ -124079,6 +124228,7 @@ var inflateCircuitJson = (target, circuitJson, children) => {
124079
124228
  inflateSourceTrace(sourceTrace, inflationCtx);
124080
124229
  }
124081
124230
  inflateStandalonePcbPrimitives(inflationCtx);
124231
+ inflateSimulation(inflationCtx);
124082
124232
  };
124083
124233
 
124084
124234
  // lib/components/primitive-components/resolve-board-motor-mount.ts
@@ -134097,6 +134247,80 @@ var AnalogAnalysisSimulation = class extends PrimitiveComponent2 {
134097
134247
 
134098
134248
  // lib/components/primitive-components/AnalogTransientSimulation.ts
134099
134249
  import { analogTransientSimulationProps } from "@tscircuit/props";
134250
+
134251
+ // lib/utils/simulation/resolveExternalSimulation.ts
134252
+ function resolveExternalSimulationPort({
134253
+ declaration,
134254
+ selector
134255
+ }) {
134256
+ const ports = declaration.getSubcircuit().selectAll(selector).filter((port2) => port2.componentName === "Port");
134257
+ if (ports.length !== 1 || !ports[0].source_port_id) {
134258
+ throw new Error(
134259
+ `Simulation pin selector "${selector}" must identify exactly one physical source pin.`
134260
+ );
134261
+ }
134262
+ const port = ports[0];
134263
+ if (port.getSubcircuit() !== declaration.getSubcircuit()) {
134264
+ throw new Error(
134265
+ `Simulation pin "${selector}" must belong to the same subcircuit as its declaration.`
134266
+ );
134267
+ }
134268
+ return port;
134269
+ }
134270
+ function resolveExternalTransientSimulation({
134271
+ declaration,
134272
+ selector
134273
+ }) {
134274
+ const simulations = declaration.getSubcircuit().selectAll(selector).filter(
134275
+ (simulation3) => simulation3.componentName === "AnalogTransientSimulation"
134276
+ );
134277
+ if (simulations.length !== 1 || simulations[0].getSubcircuit() !== declaration.getSubcircuit()) {
134278
+ throw new Error(
134279
+ `Simulation selector "${selector}" must identify one transient in the same subcircuit.`
134280
+ );
134281
+ }
134282
+ const simulation2 = simulations[0];
134283
+ if (simulation2.getSpiceEngineName() !== "pcb_spice") {
134284
+ throw new Error(
134285
+ `Simulation "${selector}" requires spiceEngine="pcb_spice" for IBIS declarations.`
134286
+ );
134287
+ }
134288
+ simulation2.getOrCreateSimulationExperiment();
134289
+ return simulation2;
134290
+ }
134291
+
134292
+ // lib/components/primitive-components/AnalogTransientSimulation_validateIbisBindings.ts
134293
+ function AnalogTransientSimulation_validateIbisBindings(simulation2) {
134294
+ if (simulation2.getSpiceEngineName() !== "pcb_spice") return;
134295
+ const subcircuit = simulation2.getSubcircuit();
134296
+ const models = subcircuit.selectAll("ibismodel").filter(
134297
+ (model) => !model.shouldBeRemoved && model.getSubcircuit() === subcircuit
134298
+ ).map(
134299
+ (model) => simulation2.root.db.simulation_ibis_model.get(
134300
+ model.simulation_ibis_model_id
134301
+ )
134302
+ );
134303
+ for (const selector of Object.keys(
134304
+ simulation2._parsedProps.ibisPinStates ?? {}
134305
+ )) {
134306
+ const port = resolveExternalSimulationPort({
134307
+ declaration: simulation2,
134308
+ selector
134309
+ });
134310
+ const bindings = models.filter(
134311
+ (model) => Object.values(model.ibis_pin_name_to_source_port_id).includes(
134312
+ port.source_port_id
134313
+ )
134314
+ );
134315
+ if (bindings.length !== 1) {
134316
+ throw new Error(
134317
+ `Simulation "${simulation2._parsedProps.name ?? "transient"}" pin "${selector}" requires exactly one IBIS model binding in this subcircuit.`
134318
+ );
134319
+ }
134320
+ }
134321
+ }
134322
+
134323
+ // lib/components/primitive-components/AnalogTransientSimulation.ts
134100
134324
  var AnalogTransientSimulation = class extends AnalogAnalysisSimulation {
134101
134325
  get config() {
134102
134326
  return {
@@ -134104,17 +134328,389 @@ var AnalogTransientSimulation = class extends AnalogAnalysisSimulation {
134104
134328
  zodProps: analogTransientSimulationProps
134105
134329
  };
134106
134330
  }
134331
+ doInitialSimulationSpiceEngineRender() {
134332
+ if (this.getInheritedProperty("analogSimulationDisabled")) return;
134333
+ AnalogTransientSimulation_validateIbisBindings(this);
134334
+ }
134335
+ updateSimulationSpiceEngineRender() {
134336
+ this.doInitialSimulationSpiceEngineRender();
134337
+ }
134338
+ onPropsChange() {
134339
+ this._markDirty("SimulationRender");
134340
+ if (!this.simulation_experiment_id) return;
134341
+ const subcircuit = this.getSubcircuit();
134342
+ for (const declaration of [
134343
+ ...subcircuit.selectAll("analogdigitalstimulus"),
134344
+ ...subcircuit.selectAll("analogeyediagram")
134345
+ ]) {
134346
+ if (declaration.getSubcircuit() === subcircuit)
134347
+ declaration._markDirty("SimulationSpiceEngineRender");
134348
+ }
134349
+ }
134350
+ updateSimulationRender() {
134351
+ this.insertSimulationExperiment();
134352
+ }
134353
+ removeIbisPinStates() {
134354
+ for (const state of this.root.db.simulation_ibis_pin_state.list({
134355
+ simulation_experiment_id: this.simulation_experiment_id
134356
+ })) {
134357
+ this.root.db.simulation_ibis_pin_state.delete(
134358
+ state.simulation_ibis_pin_state_id
134359
+ );
134360
+ }
134361
+ }
134362
+ removeSimulationRender() {
134363
+ if (!this.simulation_experiment_id) return;
134364
+ this.removeIbisPinStates();
134365
+ this.root.db.simulation_experiment.delete(this.simulation_experiment_id);
134366
+ this.simulation_experiment_id = null;
134367
+ }
134107
134368
  insertSimulationExperiment() {
134108
134369
  const { db: db2 } = this.root;
134109
134370
  const { duration, name, startTime, timePerStep, spiceOptions } = this._parsedProps;
134110
- return db2.simulation_experiment.insert({
134371
+ const ibisPinStates = this.getInheritedProperty("analogSimulationDisabled") ? {} : this._parsedProps.ibisPinStates;
134372
+ const pins = Object.entries(ibisPinStates ?? {}).map(
134373
+ ([selector, state]) => {
134374
+ const pin = {
134375
+ source_port_id: resolveExternalSimulationPort({
134376
+ declaration: this,
134377
+ selector
134378
+ }).source_port_id,
134379
+ is_output: state.isOutput
134380
+ };
134381
+ if (state.isOutput)
134382
+ return { ...pin, is_output_enabled: state.isOutputEnabled };
134383
+ return pin;
134384
+ }
134385
+ );
134386
+ if (new Set(pins.map((pin) => pin.source_port_id)).size !== pins.length) {
134387
+ throw new Error(
134388
+ `Simulation "${name ?? "transient"}" assigns multiple states to the same physical pin.`
134389
+ );
134390
+ }
134391
+ const experimentProps = {
134111
134392
  name: name ?? "spice_transient_analysis",
134112
134393
  experiment_type: "spice_transient_analysis",
134113
134394
  end_time_ms: duration,
134114
134395
  start_time_ms: startTime,
134115
134396
  time_per_step: timePerStep,
134116
- spice_options: spiceOptions
134117
- });
134397
+ spice_options: spiceOptions,
134398
+ spice_engine: this.getSpiceEngineName(),
134399
+ subcircuit_id: this.getSubcircuit().subcircuit_id
134400
+ };
134401
+ const experiment = this.simulation_experiment_id ? db2.simulation_experiment.update(
134402
+ this.simulation_experiment_id,
134403
+ experimentProps
134404
+ ) : db2.simulation_experiment.insert(experimentProps);
134405
+ if (this.simulation_experiment_id) this.removeIbisPinStates();
134406
+ for (const pin of pins) {
134407
+ db2.simulation_ibis_pin_state.insert({
134408
+ simulation_experiment_id: experiment.simulation_experiment_id,
134409
+ ...pin
134410
+ });
134411
+ }
134412
+ return experiment;
134413
+ }
134414
+ };
134415
+
134416
+ // lib/components/primitive-components/AnalogDigitalStimulus.ts
134417
+ import { analogDigitalStimulusProps } from "@tscircuit/props";
134418
+
134419
+ // lib/components/primitive-components/AnalogDigitalStimulus_getSimulationDigitalStimulus.ts
134420
+ function AnalogDigitalStimulus_getSimulationDigitalStimulus(declaration) {
134421
+ const props = declaration._parsedProps;
134422
+ const simulation2 = resolveExternalTransientSimulation({
134423
+ declaration,
134424
+ selector: props.simulationRef
134425
+ });
134426
+ const port = resolveExternalSimulationPort({
134427
+ declaration,
134428
+ selector: props.sourcePinRef
134429
+ });
134430
+ const experiment = simulation2.getOrCreateSimulationExperiment();
134431
+ if (props.startTime >= experiment.end_time_ms)
134432
+ throw new Error(`Stimulus "${props.name}" starts outside its simulation.`);
134433
+ const pinState = declaration.root.db.simulation_ibis_pin_state.list({
134434
+ simulation_experiment_id: experiment.simulation_experiment_id
134435
+ }).find((state) => state.source_port_id === port.source_port_id);
134436
+ if (pinState?.is_output !== true || pinState.is_output_enabled !== true) {
134437
+ throw new Error(
134438
+ `Stimulus "${props.name}" must drive a pin declared as an enabled output in its simulation.`
134439
+ );
134440
+ }
134441
+ if (declaration.root.db.simulation_digital_stimulus.list({
134442
+ simulation_experiment_id: experiment.simulation_experiment_id
134443
+ }).some(
134444
+ (stimulus) => stimulus.simulation_digital_stimulus_id !== declaration.simulation_digital_stimulus_id && (stimulus.source_port_id === port.source_port_id || stimulus.name === props.name)
134445
+ )) {
134446
+ throw new Error(
134447
+ `Stimulus "${props.name}" duplicates a driven pin or stimulus name in this simulation.`
134448
+ );
134449
+ }
134450
+ return {
134451
+ type: "simulation_digital_stimulus",
134452
+ name: props.name,
134453
+ simulation_experiment_id: experiment.simulation_experiment_id,
134454
+ source_port_id: port.source_port_id,
134455
+ bit_duration_ms: props.bitDuration,
134456
+ start_time_ms: props.startTime,
134457
+ initial_state: props.initialState,
134458
+ inverted: props.inverted,
134459
+ transmission_pattern: {
134460
+ transmission_type: props.transmittedData.transmissionType,
134461
+ bits: props.transmittedData.bits,
134462
+ repeat: props.transmittedData.repeat
134463
+ }
134464
+ };
134465
+ }
134466
+
134467
+ // lib/components/primitive-components/AnalogDigitalStimulus.ts
134468
+ var AnalogDigitalStimulus = class extends PrimitiveComponent2 {
134469
+ simulation_digital_stimulus_id = null;
134470
+ get config() {
134471
+ return {
134472
+ componentName: "AnalogDigitalStimulus",
134473
+ zodProps: analogDigitalStimulusProps
134474
+ };
134475
+ }
134476
+ doInitialSimulationRender() {
134477
+ if (this.getInheritedProperty("analogSimulationDisabled")) return;
134478
+ const stimulus = AnalogDigitalStimulus_getSimulationDigitalStimulus(this);
134479
+ if (this.simulation_digital_stimulus_id)
134480
+ this.root.db.simulation_digital_stimulus.update(
134481
+ this.simulation_digital_stimulus_id,
134482
+ stimulus
134483
+ );
134484
+ else
134485
+ this.simulation_digital_stimulus_id = this.root.db.simulation_digital_stimulus.insert(
134486
+ stimulus
134487
+ ).simulation_digital_stimulus_id;
134488
+ }
134489
+ onPropsChange() {
134490
+ this._markDirty("SimulationSpiceEngineRender");
134491
+ }
134492
+ // Refresh traffic after every experiment has updated its pin states.
134493
+ updateSimulationSpiceEngineRender() {
134494
+ this.doInitialSimulationRender();
134495
+ }
134496
+ removeSimulationRender() {
134497
+ if (this.simulation_digital_stimulus_id)
134498
+ this.root.db.simulation_digital_stimulus.delete(
134499
+ this.simulation_digital_stimulus_id
134500
+ );
134501
+ this.simulation_digital_stimulus_id = null;
134502
+ }
134503
+ };
134504
+
134505
+ // lib/components/primitive-components/AnalogEyeDiagram.ts
134506
+ import { analogEyeDiagramProps } from "@tscircuit/props";
134507
+
134508
+ // lib/components/primitive-components/AnalogEyeDiagram_getSimulationEyeDiagram.ts
134509
+ function AnalogEyeDiagram_getSimulationEyeDiagram(declaration) {
134510
+ const props = declaration._parsedProps;
134511
+ const simulation2 = resolveExternalTransientSimulation({
134512
+ declaration,
134513
+ selector: props.simulationRef
134514
+ });
134515
+ const experiment = simulation2.getOrCreateSimulationExperiment();
134516
+ const probes = declaration.getSubcircuit().selectAll(props.probeRef).filter((probe2) => probe2.componentName === "VoltageProbe");
134517
+ if (probes.length !== 1 || probes[0].getSubcircuit() !== declaration.getSubcircuit()) {
134518
+ throw new Error(
134519
+ `Eye probe selector "${props.probeRef}" must identify one voltage probe in this subcircuit.`
134520
+ );
134521
+ }
134522
+ const probe = probes[0];
134523
+ if (!probe.simulation_voltage_probe_id) {
134524
+ throw new Error(
134525
+ `Eye probe "${props.probeRef}" did not render a voltage probe.`
134526
+ );
134527
+ }
134528
+ const start = props.startTime ?? experiment.start_time_ms ?? 0, end = props.endTime ?? experiment.end_time_ms;
134529
+ const firstBoundary = (start - props.timeOrigin) / props.unitInterval + 0.5;
134530
+ const lastBoundary = (end - props.timeOrigin) / props.unitInterval - 1.5;
134531
+ const roundingTolerance = 8 * Number.EPSILON * Math.max(1, Math.abs(firstBoundary), Math.abs(lastBoundary));
134532
+ if (start < (experiment.start_time_ms ?? 0) || end > experiment.end_time_ms || end <= start || Math.ceil(firstBoundary - roundingTolerance) > Math.floor(lastBoundary + roundingTolerance)) {
134533
+ throw new Error(
134534
+ `Eye "${props.name}" needs a gate within its simulation containing at least two bit intervals forming a complete two-UI eye window aligned to timeOrigin after recording starts.`
134535
+ );
134536
+ }
134537
+ return {
134538
+ type: "simulation_eye_diagram",
134539
+ name: props.name,
134540
+ simulation_experiment_id: experiment.simulation_experiment_id,
134541
+ simulation_voltage_probe_id: probe.simulation_voltage_probe_id,
134542
+ unit_interval_ms: props.unitInterval,
134543
+ time_origin_ms: props.timeOrigin,
134544
+ start_time_ms: start,
134545
+ end_time_ms: end
134546
+ };
134547
+ }
134548
+
134549
+ // lib/components/primitive-components/AnalogEyeDiagram.ts
134550
+ var AnalogEyeDiagram = class extends PrimitiveComponent2 {
134551
+ simulation_eye_diagram_id = null;
134552
+ get config() {
134553
+ return {
134554
+ componentName: "AnalogEyeDiagram",
134555
+ zodProps: analogEyeDiagramProps
134556
+ };
134557
+ }
134558
+ // Probes have finished SimulationRender before this phase, independent of JSX order.
134559
+ doInitialSimulationSpiceEngineRender() {
134560
+ if (this.getInheritedProperty("analogSimulationDisabled")) return;
134561
+ const eye = AnalogEyeDiagram_getSimulationEyeDiagram(this);
134562
+ if (this.simulation_eye_diagram_id)
134563
+ this.root.db.simulation_eye_diagram.update(
134564
+ this.simulation_eye_diagram_id,
134565
+ eye
134566
+ );
134567
+ else
134568
+ this.simulation_eye_diagram_id = this.root.db.simulation_eye_diagram.insert(
134569
+ eye
134570
+ ).simulation_eye_diagram_id;
134571
+ }
134572
+ onPropsChange() {
134573
+ this._markDirty("SimulationSpiceEngineRender");
134574
+ }
134575
+ updateSimulationSpiceEngineRender() {
134576
+ this.doInitialSimulationSpiceEngineRender();
134577
+ }
134578
+ removeSimulationSpiceEngineRender() {
134579
+ if (this.simulation_eye_diagram_id)
134580
+ this.root.db.simulation_eye_diagram.delete(
134581
+ this.simulation_eye_diagram_id
134582
+ );
134583
+ this.simulation_eye_diagram_id = null;
134584
+ }
134585
+ };
134586
+
134587
+ // lib/components/primitive-components/IbisModel.ts
134588
+ import { ibisModelProps } from "@tscircuit/props";
134589
+
134590
+ // lib/components/primitive-components/IbisModel_getSimulationIbisModel.ts
134591
+ function IbisModel_getSimulationIbisModel(declaration) {
134592
+ const props = declaration._parsedProps;
134593
+ const chips = declaration.getSubcircuit().selectAll(props.componentRef).filter((chip2) => chip2.source_component_id);
134594
+ if (chips.length !== 1 || chips[0].getSubcircuit() !== declaration.getSubcircuit()) {
134595
+ throw new Error(
134596
+ `IBIS component selector "${props.componentRef}" must identify one component in this subcircuit.`
134597
+ );
134598
+ }
134599
+ const chip = chips[0];
134600
+ if (declaration.root.db.simulation_ibis_model.list({
134601
+ source_component_id: chip.source_component_id
134602
+ }).some(
134603
+ (model) => model.simulation_ibis_model_id !== declaration.simulation_ibis_model_id
134604
+ )) {
134605
+ throw new Error(
134606
+ `Component "${props.componentRef}" already has an IBIS model.`
134607
+ );
134608
+ }
134609
+ const pinMap = Object.fromEntries(
134610
+ Object.entries(props.ibisPinNameToPortLabel).map(([pin, label]) => [
134611
+ pin,
134612
+ resolveExternalSimulationPort({
134613
+ declaration,
134614
+ selector: `${props.componentRef} > .${label}`
134615
+ }).source_port_id
134616
+ ])
134617
+ );
134618
+ const ibisPinNameBySourcePortId = /* @__PURE__ */ new Map();
134619
+ for (const [pin, sourcePortId] of Object.entries(pinMap)) {
134620
+ const previousPin = ibisPinNameBySourcePortId.get(sourcePortId);
134621
+ if (previousPin !== void 0) {
134622
+ throw new Error(
134623
+ `IBIS pins "${previousPin}" and "${pin}" on "${props.componentRef}" resolve to the same physical pin.`
134624
+ );
134625
+ }
134626
+ ibisPinNameBySourcePortId.set(sourcePortId, pin);
134627
+ }
134628
+ for (const pin of [
134629
+ ...Object.keys(props.ibisPinNameToReferencePortLabels ?? {}),
134630
+ ...Object.keys(props.ibisPinNameToModelName ?? {})
134631
+ ]) {
134632
+ if (!Object.hasOwn(props.ibisPinNameToPortLabel, pin)) {
134633
+ throw new Error(
134634
+ `IBIS pin "${pin}" is referenced but not present in ibisPinNameToPortLabel.`
134635
+ );
134636
+ }
134637
+ }
134638
+ let references;
134639
+ if (props.ibisPinNameToReferencePortLabels) {
134640
+ references = {};
134641
+ for (const [pin, pinReferences] of Object.entries(
134642
+ props.ibisPinNameToReferencePortLabels
134643
+ )) {
134644
+ references[pin] = {};
134645
+ for (const [role, sourcePortIdField] of [
134646
+ ["pullup", "pullup_reference_source_port_id"],
134647
+ ["pulldown", "pulldown_reference_source_port_id"],
134648
+ ["powerClamp", "power_clamp_reference_source_port_id"],
134649
+ ["groundClamp", "ground_clamp_reference_source_port_id"],
134650
+ ["external", "external_reference_source_port_id"]
134651
+ ]) {
134652
+ const label = pinReferences[role];
134653
+ if (label === void 0) continue;
134654
+ references[pin][sourcePortIdField] = resolveExternalSimulationPort({
134655
+ declaration,
134656
+ selector: `${props.componentRef} > .${label}`
134657
+ }).source_port_id;
134658
+ }
134659
+ }
134660
+ }
134661
+ return {
134662
+ type: "simulation_ibis_model",
134663
+ source_component_id: chip.source_component_id,
134664
+ ibis_model_asset: props.ibisModelAsset,
134665
+ ibis_component_name: props.ibisComponentName,
134666
+ model_value_corner: props.modelValueCorner,
134667
+ include_package_parasitics: props.includePackageParasitics,
134668
+ ibis_pin_name_to_model_name: props.ibisPinNameToModelName,
134669
+ ibis_pin_name_to_source_port_id: pinMap,
134670
+ ibis_pin_name_to_reference_source_port_ids: references
134671
+ };
134672
+ }
134673
+
134674
+ // lib/components/primitive-components/IbisModel.ts
134675
+ var IbisModel = class extends PrimitiveComponent2 {
134676
+ simulation_ibis_model_id = null;
134677
+ get config() {
134678
+ return { componentName: "IbisModel", zodProps: ibisModelProps };
134679
+ }
134680
+ onPropsChange() {
134681
+ this._markDirty("SimulationRender");
134682
+ }
134683
+ markIbisBindingsDirty() {
134684
+ const subcircuit = this.getSubcircuit();
134685
+ for (const simulation2 of subcircuit.selectAll(
134686
+ "analogtransientsimulation"
134687
+ )) {
134688
+ if (simulation2.getSubcircuit() === subcircuit)
134689
+ simulation2._markDirty("SimulationSpiceEngineRender");
134690
+ }
134691
+ }
134692
+ doInitialSimulationRender() {
134693
+ if (this.getInheritedProperty("analogSimulationDisabled")) return;
134694
+ const model = IbisModel_getSimulationIbisModel(this);
134695
+ if (this.simulation_ibis_model_id)
134696
+ this.root.db.simulation_ibis_model.update(
134697
+ this.simulation_ibis_model_id,
134698
+ model
134699
+ );
134700
+ else
134701
+ this.simulation_ibis_model_id = this.root.db.simulation_ibis_model.insert(
134702
+ model
134703
+ ).simulation_ibis_model_id;
134704
+ this.markIbisBindingsDirty();
134705
+ }
134706
+ updateSimulationRender() {
134707
+ this.doInitialSimulationRender();
134708
+ }
134709
+ removeSimulationRender() {
134710
+ if (this.simulation_ibis_model_id)
134711
+ this.root.db.simulation_ibis_model.delete(this.simulation_ibis_model_id);
134712
+ this.simulation_ibis_model_id = null;
134713
+ this.markIbisBindingsDirty();
134118
134714
  }
134119
134715
  };
134120
134716
 
@@ -136050,6 +136646,10 @@ var createNamespacedElement = (hostType) => {
136050
136646
 
136051
136647
  // lib/namespaced-elements/analog.ts
136052
136648
  var analog = {
136649
+ digitalstimulus: createNamespacedElement(
136650
+ "analogdigitalstimulus"
136651
+ ),
136652
+ eyediagram: createNamespacedElement("analogeyediagram"),
136053
136653
  transientsimulation: createNamespacedElement(
136054
136654
  "analogtransientsimulation"
136055
136655
  ),
@@ -136359,6 +136959,8 @@ export {
136359
136959
  AnalogAnalysisSimulation,
136360
136960
  AnalogDcOperatingPointSimulation,
136361
136961
  AnalogDcSweepSimulation,
136962
+ AnalogDigitalStimulus,
136963
+ AnalogEyeDiagram,
136362
136964
  AnalogSimulation,
136363
136965
  AnalogSweepParameter,
136364
136966
  AnalogTransientSimulation,
@@ -136408,6 +137010,7 @@ export {
136408
137010
  Fuse,
136409
137011
  Group5 as Group,
136410
137012
  Hole,
137013
+ IbisModel,
136411
137014
  Inductor,
136412
137015
  Interconnect,
136413
137016
  IsolatedCircuit,