edacation 0.5.1 → 0.6.1

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.
@@ -2,8 +2,6 @@ import type { NextpnrOptions, ProjectConfiguration, WorkerOptions, WorkerStep }
2
2
  import type { Project } from './project.js';
3
3
  export type NextpnrStep = WorkerStep;
4
4
  export type NextpnrWorkerOptions = WorkerOptions<NextpnrStep, NextpnrOptions>;
5
- export declare const getNextpnrDefaultOptions: (configuration: ProjectConfiguration) => NextpnrOptions;
6
- export declare const getNextpnrOptions: (configuration: ProjectConfiguration, targetId: string) => NextpnrOptions;
7
- export declare const generateNextpnrWorkerOptions: (configuration: ProjectConfiguration, targetId: string) => NextpnrWorkerOptions;
8
5
  export declare const parseNextpnrArguments: (args: string[]) => string[];
6
+ export declare const getNextpnrOptions: (configuration: ProjectConfiguration, targetId: string) => NextpnrOptions;
9
7
  export declare const getNextpnrWorkerOptions: (project: Project, targetId: string) => NextpnrWorkerOptions;
@@ -1,48 +1,64 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNextpnrWorkerOptions = exports.parseNextpnrArguments = exports.generateNextpnrWorkerOptions = exports.getNextpnrOptions = exports.getNextpnrDefaultOptions = void 0;
3
+ exports.getNextpnrWorkerOptions = exports.getNextpnrOptions = exports.parseNextpnrArguments = void 0;
4
4
  const string_args_parser_1 = require("string-args-parser");
5
5
  const devices_js_1 = require("./devices.js");
6
6
  const target_js_1 = require("./target.js");
7
7
  const DEFAULT_OPTIONS = {
8
8
  placedSvg: false,
9
9
  routedSvg: false,
10
- routedJson: true
10
+ routedJson: true,
11
+ pinConfigFile: undefined
11
12
  };
12
- const getNextpnrDefaultOptions = (configuration) => (0, target_js_1.getDefaultOptions)(configuration, 'nextpnr', DEFAULT_OPTIONS);
13
- exports.getNextpnrDefaultOptions = getNextpnrDefaultOptions;
13
+ const parseNextpnrArguments = (args) => args.flatMap((arg) => (0, string_args_parser_1.parseArgs)(arg));
14
+ exports.parseNextpnrArguments = parseNextpnrArguments;
14
15
  const getNextpnrOptions = (configuration, targetId) => (0, target_js_1.getOptions)(configuration, targetId, 'nextpnr', DEFAULT_OPTIONS);
15
16
  exports.getNextpnrOptions = getNextpnrOptions;
16
- const generateNextpnrWorkerOptions = (configuration, targetId) => {
17
+ const getNextpnrWorkerOptions = (project, targetId) => {
18
+ const configuration = project.getConfiguration();
17
19
  const target = (0, target_js_1.getTarget)(configuration, targetId);
18
20
  const options = (0, exports.getNextpnrOptions)(configuration, targetId);
19
21
  const vendor = devices_js_1.VENDORS[target.vendor];
20
22
  const family = vendor.families[target.family];
21
23
  const device = family.devices[target.device];
22
- const inputFiles = [(0, target_js_1.getTargetFile)(target, `${family.architecture}.json`)];
23
- const outputFiles = [];
24
+ // Input files
25
+ const generatedInputFiles = [`${family.architecture}.json`].map(f => (0, target_js_1.getTargetFile)(target, f));
26
+ const inputFiles = (0, target_js_1.getCombined)(configuration, targetId, 'nextpnr', 'inputFiles', generatedInputFiles).filter((f) => !!f);
27
+ // Tool
24
28
  const tool = `nextpnr-${family.architecture}`;
25
- const args = [];
29
+ // Output files / args
30
+ const generatedOutputFiles = [];
31
+ const generatedArgs = [];
26
32
  switch (family.architecture) {
27
33
  case 'ecp5': {
28
- args.push(`--${device.device}`);
29
- args.push('--package', target.package.toUpperCase());
34
+ generatedArgs.push(`--${device.device}`);
35
+ generatedArgs.push('--package', target.package.toUpperCase());
36
+ if (options.pinConfigFile) {
37
+ generatedArgs.push('--lpf', options.pinConfigFile);
38
+ }
39
+ // Write bitstream file
40
+ const file = (0, target_js_1.getTargetFile)(target, `${family.architecture}.config`);
41
+ generatedOutputFiles.push(file);
42
+ generatedArgs.push('--textcfg', file);
30
43
  break;
31
44
  }
32
45
  case 'generic': {
33
46
  break;
34
47
  }
35
48
  case 'gowin': {
36
- args.push('--device', `${device.device.replace('-', '-UV')}${target.package}C5/I4`);
49
+ generatedArgs.push('--device', `${device.device.replace('-', '-UV')}${target.package}C5/I4`);
37
50
  break;
38
51
  }
39
52
  case 'ice40': {
40
- args.push(`--${device.device}`);
41
- args.push('--package', target.package);
42
- // Write ASC file by default
53
+ generatedArgs.push(`--${device.device}`);
54
+ generatedArgs.push('--package', target.package);
55
+ if (options.pinConfigFile) {
56
+ generatedArgs.push('--pcf', options.pinConfigFile);
57
+ }
58
+ // Write ASC file
43
59
  const file = (0, target_js_1.getTargetFile)(target, `${family.architecture}.asc`);
44
- outputFiles.push(file);
45
- args.push('--asc', `${family.architecture}.asc`);
60
+ generatedOutputFiles.push(file);
61
+ generatedArgs.push('--asc', file);
46
62
  break;
47
63
  }
48
64
  case 'nexus': {
@@ -58,29 +74,31 @@ const generateNextpnrWorkerOptions = (configuration, targetId) => {
58
74
  if (!devPackage) {
59
75
  throw new Error(`Package "${target.package}" is currenty not supported.`);
60
76
  }
61
- args.push('--device', `${device.device}-7${devPackage}C`);
77
+ generatedArgs.push('--device', `${device.device}-7${devPackage}C`);
62
78
  break;
63
79
  }
64
80
  default: {
65
81
  throw new Error(`Architecture "${family.architecture}" is currently not supported.`);
66
82
  }
67
83
  }
68
- args.push('--json', inputFiles[0]);
84
+ generatedArgs.push('--json', inputFiles[0]);
69
85
  if (options.placedSvg) {
70
86
  const file = (0, target_js_1.getTargetFile)(target, 'placed.svg');
71
- outputFiles.push(file);
72
- args.push('--placed-svg', file);
87
+ generatedOutputFiles.push(file);
88
+ generatedArgs.push('--placed-svg', file);
73
89
  }
74
90
  if (options.routedSvg) {
75
91
  const file = (0, target_js_1.getTargetFile)(target, 'routed.svg');
76
- outputFiles.push(file);
77
- args.push('--routed-svg', file);
92
+ generatedOutputFiles.push(file);
93
+ generatedArgs.push('--routed-svg', file);
78
94
  }
79
95
  if (options.routedJson) {
80
96
  const file = (0, target_js_1.getTargetFile)(target, 'routed.nextpnr.json');
81
- outputFiles.push(file);
82
- args.push('--write', file);
97
+ generatedOutputFiles.push(file);
98
+ generatedArgs.push('--write', file);
83
99
  }
100
+ const outputFiles = (0, target_js_1.getCombined)(configuration, targetId, 'nextpnr', 'outputFiles', generatedOutputFiles).filter((f) => !!f);
101
+ const args = (0, target_js_1.getCombined)(configuration, targetId, 'nextpnr', 'arguments', generatedArgs, exports.parseNextpnrArguments);
84
102
  return {
85
103
  inputFiles,
86
104
  outputFiles,
@@ -88,33 +106,12 @@ const generateNextpnrWorkerOptions = (configuration, targetId) => {
88
106
  options,
89
107
  steps: [
90
108
  {
109
+ id: 'pnr',
91
110
  tool,
92
111
  arguments: args
93
112
  }
94
113
  ]
95
114
  };
96
115
  };
97
- exports.generateNextpnrWorkerOptions = generateNextpnrWorkerOptions;
98
- const parseNextpnrArguments = (args) => args.flatMap((arg) => (0, string_args_parser_1.parseArgs)(arg));
99
- exports.parseNextpnrArguments = parseNextpnrArguments;
100
- const getNextpnrWorkerOptions = (project, targetId) => {
101
- const generated = (0, exports.generateNextpnrWorkerOptions)(project.getConfiguration(), targetId);
102
- const inputFiles = (0, target_js_1.getCombined)(project.getConfiguration(), targetId, 'nextpnr', 'inputFiles', generated.inputFiles).filter((f) => !!f);
103
- const outputFiles = (0, target_js_1.getCombined)(project.getConfiguration(), targetId, 'nextpnr', 'outputFiles', generated.outputFiles).filter((f) => !!f);
104
- const target = generated.target;
105
- const options = generated.options;
106
- const steps = generated.steps.map((step) => {
107
- const tool = step.tool;
108
- const args = (0, target_js_1.getCombined)(project.getConfiguration(), targetId, 'nextpnr', 'arguments', step.arguments, exports.parseNextpnrArguments);
109
- return { tool, arguments: args };
110
- });
111
- return {
112
- inputFiles,
113
- outputFiles,
114
- target,
115
- options,
116
- steps
117
- };
118
- };
119
116
  exports.getNextpnrWorkerOptions = getNextpnrWorkerOptions;
120
117
  //# sourceMappingURL=nextpnr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nextpnr.js","sourceRoot":"","sources":["../../src/project/nextpnr.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nextpnr.js","sourceRoot":"","sources":["../../src/project/nextpnr.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@ export type ProjectEvent = 'meta' | 'inputFiles' | 'outputFiles' | 'configuratio
9
9
  type EventCallback = (project: Project, events: ProjectEvent[]) => void;
10
10
  export interface ProjectInputFileState {
11
11
  path: string;
12
- type: 'design' | 'testbench';
12
+ type: 'design' | 'testbench' | 'pinconfig';
13
13
  }
14
14
  export declare class ProjectInputFile {
15
15
  private _project;
@@ -52,6 +52,9 @@ export declare class ProjectTarget {
52
52
  set id(newId: string);
53
53
  get name(): string;
54
54
  set name(newName: string);
55
+ get isActive(): boolean;
56
+ setActive(): void;
57
+ getFile(...parts: string[]): string;
55
58
  get vendorId(): string;
56
59
  get availableVendors(): Record<string, Vendor>;
57
60
  get vendor(): Vendor | undefined;
@@ -70,7 +73,7 @@ export declare class ProjectTarget {
70
73
  setPackage(packageId: string): void;
71
74
  get config(): TargetConfiguration;
72
75
  setConfig<P extends PathArray<TargetConfiguration>>(path: P, value: PathArrayValue<TargetConfiguration, P>): void;
73
- getEffectiveOptions<W extends WorkerId>(workerId: WorkerId): TargetOptionTypes[W];
76
+ getEffectiveOptions<W extends WorkerId>(workerId: W): TargetOptionTypes[W];
74
77
  getEffectiveTextConfig(workerId: WorkerId, configId: string, generated: string[], parse?: (values: string[]) => string[]): string[];
75
78
  update(updates: Partial<TargetConfiguration>): void;
76
79
  serialize(): TargetConfiguration;
@@ -110,11 +113,16 @@ export declare class Project {
110
113
  removeOutputFiles(filePaths: string[]): void;
111
114
  expireOutputFiles(): void;
112
115
  setTopLevelModule(targetId: string, module: string): void;
113
- setTestbenchPath(targetId: string, testbenchPath?: string): void;
116
+ setActiveTestbenchPath(targetId: string, testbenchPath?: string): void;
117
+ getActiveTestbenchPath(targetId: string): string | undefined;
118
+ setActivePinConfigPath(targetId: string, pinConfigPath?: string): void;
119
+ getActivePinConfigPath(targetId: string): string | undefined;
114
120
  setInputFileType(filePath: string, type: ProjectInputFile['type']): void;
115
121
  getTargets(): ProjectTarget[];
116
122
  hasTarget(id: string): boolean;
117
123
  getTarget(id: string): ProjectTarget | null;
124
+ getActiveTarget(): ProjectTarget | null;
125
+ setActiveTarget(id: string | null): void;
118
126
  addTarget(id?: string, config?: Omit<TargetConfiguration, 'id'>): ProjectTarget;
119
127
  removeTarget(id: string): void;
120
128
  updateTarget(id: string, updates: Partial<TargetConfiguration>): void;
@@ -138,7 +146,17 @@ export declare class Project {
138
146
  values: string[];
139
147
  useDefault: boolean;
140
148
  } | undefined;
141
- commands?: {
149
+ synthPrepareCommands?: {
150
+ useGenerated: boolean;
151
+ values: string[];
152
+ useDefault: boolean;
153
+ } | undefined;
154
+ synthCommands?: {
155
+ useGenerated: boolean;
156
+ values: string[];
157
+ useDefault: boolean;
158
+ } | undefined;
159
+ rtlCommands?: {
142
160
  useGenerated: boolean;
143
161
  values: string[];
144
162
  useDefault: boolean;
@@ -168,6 +186,7 @@ export declare class Project {
168
186
  placedSvg?: boolean | undefined;
169
187
  routedSvg?: boolean | undefined;
170
188
  routedJson?: boolean | undefined;
189
+ pinConfigFile?: string | undefined;
171
190
  } | undefined;
172
191
  } | undefined;
173
192
  iverilog?: {
@@ -190,6 +209,31 @@ export declare class Project {
190
209
  testbenchFile?: string | undefined;
191
210
  } | undefined;
192
211
  } | undefined;
212
+ flasher?: {
213
+ inputFiles?: {
214
+ useGenerated: boolean;
215
+ values: string[];
216
+ useDefault: boolean;
217
+ } | undefined;
218
+ outputFiles?: {
219
+ useGenerated: boolean;
220
+ values: string[];
221
+ useDefault: boolean;
222
+ } | undefined;
223
+ packerArguments?: {
224
+ useGenerated: boolean;
225
+ values: string[];
226
+ useDefault: boolean;
227
+ } | undefined;
228
+ flasherArguments?: {
229
+ useGenerated: boolean;
230
+ values: string[];
231
+ useDefault: boolean;
232
+ } | undefined;
233
+ options?: {
234
+ board?: string | undefined;
235
+ } | undefined;
236
+ } | undefined;
193
237
  }[];
194
238
  defaults?: {
195
239
  yosys?: {
@@ -201,7 +245,15 @@ export declare class Project {
201
245
  useGenerated: boolean;
202
246
  values: string[];
203
247
  } | undefined;
204
- commands?: {
248
+ synthPrepareCommands?: {
249
+ useGenerated: boolean;
250
+ values: string[];
251
+ } | undefined;
252
+ synthCommands?: {
253
+ useGenerated: boolean;
254
+ values: string[];
255
+ } | undefined;
256
+ rtlCommands?: {
205
257
  useGenerated: boolean;
206
258
  values: string[];
207
259
  } | undefined;
@@ -227,6 +279,7 @@ export declare class Project {
227
279
  placedSvg?: boolean | undefined;
228
280
  routedSvg?: boolean | undefined;
229
281
  routedJson?: boolean | undefined;
282
+ pinConfigFile?: string | undefined;
230
283
  } | undefined;
231
284
  } | undefined;
232
285
  iverilog?: {
@@ -246,7 +299,29 @@ export declare class Project {
246
299
  testbenchFile?: string | undefined;
247
300
  } | undefined;
248
301
  } | undefined;
302
+ flasher?: {
303
+ inputFiles?: {
304
+ useGenerated: boolean;
305
+ values: string[];
306
+ } | undefined;
307
+ outputFiles?: {
308
+ useGenerated: boolean;
309
+ values: string[];
310
+ } | undefined;
311
+ packerArguments?: {
312
+ useGenerated: boolean;
313
+ values: string[];
314
+ } | undefined;
315
+ flasherArguments?: {
316
+ useGenerated: boolean;
317
+ values: string[];
318
+ } | undefined;
319
+ options?: {
320
+ board?: string | undefined;
321
+ } | undefined;
322
+ } | undefined;
249
323
  } | undefined;
324
+ activeTargetId?: string | undefined;
250
325
  };
251
326
  updateConfiguration(configuration: Partial<ProjectConfiguration>): void;
252
327
  protected importFromProject(other: Project, doTriggerEvent?: boolean): void;
@@ -255,7 +330,12 @@ export declare class Project {
255
330
  triggerConfigurationChanged(): void;
256
331
  protected emitEvents(...events: ProjectEvent[]): void;
257
332
  protected batchEvents<T>(func: () => T, ...events: ProjectEvent[]): T;
333
+ protected ignoreEvents<T>(func: () => T): T;
258
334
  protected static emitsEvents(...events: ProjectEvent[]): <T>(_target: object, _propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
335
+ protected makeCorrections(): boolean;
336
+ private correctTestbenchPath;
337
+ private correctPinconfigPaths;
338
+ correctActiveTarget(): boolean;
259
339
  static serialize(project: Project): ProjectState;
260
340
  static deserialize(data: ProjectState, ..._args: unknown[]): Project;
261
341
  static loadFromData(rawData: Uint8Array): Project;
@@ -8,15 +8,39 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.Project = exports.ProjectTarget = exports.ProjectOutputFile = exports.ProjectInputFile = void 0;
16
+ const path_1 = __importDefault(require("path"));
13
17
  const util_js_1 = require("../util.js");
14
18
  const configuration_js_1 = require("./configuration.js");
15
19
  const devices_js_1 = require("./devices.js");
20
+ const flasher_js_1 = require("./flasher.js");
16
21
  const iverilog_js_1 = require("./iverilog.js");
17
22
  const nextpnr_js_1 = require("./nextpnr.js");
18
23
  const target_js_1 = require("./target.js");
19
24
  const yosys_js_1 = require("./yosys.js");
25
+ const guessInputFileType = (filePath) => {
26
+ // *_tb.<hdl_ext> -> testbench
27
+ // *.<pin_cfg_ext> -> pinconfig
28
+ // default: design
29
+ const baseName = filePath.split('/').pop() ?? filePath;
30
+ const lowerBase = baseName.toLowerCase();
31
+ const ext = lowerBase.split('.').pop() ?? '';
32
+ const hdlExts = util_js_1.FILE_EXTENSIONS_HDL.map(e => e.toLowerCase());
33
+ const pincfgExts = util_js_1.FILE_EXTENSIONS_PINCFG.map(e => e.toLowerCase());
34
+ if (hdlExts.some(e => lowerBase.endsWith(`_tb.${e}`)))
35
+ return 'testbench';
36
+ if (pincfgExts.includes(ext))
37
+ return 'pinconfig';
38
+ return 'design';
39
+ };
40
+ // Fallback clone to handle Proxy objects (structuredClone throws DataCloneError on Proxy)
41
+ const safeStructuredClone = (value) => {
42
+ return JSON.parse(JSON.stringify(value));
43
+ };
20
44
  class ProjectInputFile {
21
45
  constructor(_project, _path, _type) {
22
46
  this._project = _project;
@@ -134,6 +158,18 @@ class ProjectTarget {
134
158
  this._data.name = newName;
135
159
  this._project.triggerConfigurationChanged();
136
160
  }
161
+ get isActive() {
162
+ const activeTarget = this._project.getActiveTarget();
163
+ return activeTarget?.id === this.id;
164
+ }
165
+ setActive() {
166
+ if (this.isActive)
167
+ return;
168
+ this._project.setActiveTarget(this.id);
169
+ }
170
+ getFile(...parts) {
171
+ return (0, target_js_1.getTargetFile)(this.config, path_1.default.join(...parts));
172
+ }
137
173
  get vendorId() {
138
174
  return this._data.vendor;
139
175
  }
@@ -251,6 +287,8 @@ class ProjectTarget {
251
287
  return (0, nextpnr_js_1.getNextpnrOptions)(this._project.getConfiguration(), this.id);
252
288
  else if (workerId === 'iverilog')
253
289
  return (0, iverilog_js_1.getIVerilogOptions)(this._project.getConfiguration(), this.id);
290
+ else if (workerId === 'flasher')
291
+ return (0, flasher_js_1.getFlasherOptions)(this._project.getConfiguration(), this.id);
254
292
  throw new Error(`Worker ID "${String(workerId)}" is not supported.`);
255
293
  }
256
294
  getEffectiveTextConfig(workerId, configId, generated, parse = target_js_1.defaultParse) {
@@ -263,7 +301,7 @@ class ProjectTarget {
263
301
  }
264
302
  this._data.id = updates.id;
265
303
  }
266
- Object.assign(this._data, structuredClone(updates));
304
+ Object.assign(this._data, safeStructuredClone(updates));
267
305
  this._project.triggerConfigurationChanged();
268
306
  }
269
307
  serialize() {
@@ -308,7 +346,8 @@ class Project {
308
346
  addInputFiles(files) {
309
347
  for (const file of files) {
310
348
  if (!this.hasInputFile(file.path)) {
311
- const inputFile = new ProjectInputFile(this, file.path, file.type ?? 'design');
349
+ const fileType = file.type ?? guessInputFileType(file.path);
350
+ const inputFile = new ProjectInputFile(this, file.path, fileType);
312
351
  this.inputFiles.push(inputFile);
313
352
  }
314
353
  }
@@ -376,7 +415,7 @@ class Project {
376
415
  cfg.yosys.options = {};
377
416
  cfg.yosys.options.topLevelModule = module;
378
417
  }
379
- setTestbenchPath(targetId, testbenchPath) {
418
+ setActiveTestbenchPath(targetId, testbenchPath) {
380
419
  const testbenchFiles = this.getInputFiles()
381
420
  .filter((file) => file.type === 'testbench')
382
421
  .map((file) => file.path);
@@ -385,12 +424,30 @@ class Project {
385
424
  const target = this.getTarget(targetId);
386
425
  if (!target)
387
426
  throw new Error(`Target "${targetId}" does not exist!`);
388
- const cfg = target.config;
389
- if (!cfg.iverilog)
390
- cfg.iverilog = {};
391
- if (!cfg.iverilog.options)
392
- cfg.iverilog.options = {};
393
- cfg.iverilog.options.testbenchFile = testbenchPath;
427
+ target.setConfig(['iverilog', 'options', 'testbenchFile'], testbenchPath);
428
+ }
429
+ getActiveTestbenchPath(targetId) {
430
+ const target = this.getTarget(targetId);
431
+ if (!target)
432
+ throw new Error(`Target "${targetId}" does not exist!`);
433
+ return target.getEffectiveOptions('iverilog').testbenchFile;
434
+ }
435
+ setActivePinConfigPath(targetId, pinConfigPath) {
436
+ const pinConfigFiles = this.getInputFiles()
437
+ .filter((file) => file.type === 'pinconfig')
438
+ .map((file) => file.path);
439
+ if (pinConfigPath && !pinConfigFiles.includes(pinConfigPath))
440
+ throw new Error(`Pin config file ${pinConfigPath} is not marked as such!`);
441
+ const target = this.getTarget(targetId);
442
+ if (!target)
443
+ throw new Error(`Target "${targetId}" does not exist!`);
444
+ target.setConfig(['nextpnr', 'options', 'pinConfigFile'], pinConfigPath);
445
+ }
446
+ getActivePinConfigPath(targetId) {
447
+ const target = this.getTarget(targetId);
448
+ if (!target)
449
+ throw new Error(`Target "${targetId}" does not exist!`);
450
+ return target.getEffectiveOptions('nextpnr').pinConfigFile;
394
451
  }
395
452
  setInputFileType(filePath, type) {
396
453
  const file = this.getInputFile(filePath);
@@ -410,6 +467,17 @@ class Project {
410
467
  const t = this.configuration.targets.find(t => t.id === id);
411
468
  return t ? new ProjectTarget(this, t) : null;
412
469
  }
470
+ getActiveTarget() {
471
+ if (!this.configuration.activeTargetId)
472
+ return null;
473
+ return this.getTarget(this.configuration.activeTargetId);
474
+ }
475
+ setActiveTarget(id) {
476
+ if (id !== null && !this.hasTarget(id)) {
477
+ throw new Error(`Target with ID "${id}" does not exist!`);
478
+ }
479
+ this.configuration.activeTargetId = id ?? undefined;
480
+ }
413
481
  addTarget(id, config) {
414
482
  if (!id) {
415
483
  // Generate a unique ID
@@ -422,7 +490,7 @@ class Project {
422
490
  throw new Error(`Target with ID "${id}" already exists!`);
423
491
  }
424
492
  const newTargetObj = {
425
- ...structuredClone(config || configuration_js_1.DEFAULT_TARGET),
493
+ ...safeStructuredClone(config || configuration_js_1.DEFAULT_TARGET),
426
494
  id
427
495
  };
428
496
  this.configuration.targets.push(newTargetObj);
@@ -464,7 +532,7 @@ class Project {
464
532
  this.name = other.getName();
465
533
  this.inputFiles = other.getInputFiles().map((file) => file.copy(this));
466
534
  this.outputFiles = other.getOutputFiles().map((file) => file.copy(this));
467
- this.configuration = structuredClone(other.getConfiguration());
535
+ this.configuration = safeStructuredClone(other.getConfiguration());
468
536
  if (doTriggerEvent)
469
537
  this.emitEvents('inputFiles', 'outputFiles', 'configuration', 'meta');
470
538
  }
@@ -487,6 +555,11 @@ class Project {
487
555
  // Do not emit events when batching
488
556
  if (this.batchCounter > 0)
489
557
  return;
558
+ // Make any corrections needed,
559
+ // and add 'configuration' event if any corrections were made
560
+ const didCorrect = this.makeCorrections();
561
+ if (didCorrect)
562
+ this.batchedEvents.add('configuration');
490
563
  // Emit new + batched events
491
564
  if (this.eventCallback)
492
565
  this.eventCallback(this, Array.from(this.batchedEvents));
@@ -499,6 +572,14 @@ class Project {
499
572
  this.emitEvents(...events);
500
573
  return res;
501
574
  }
575
+ ignoreEvents(func) {
576
+ // raise batch counter to ignore events,
577
+ // but don't actually emit them later
578
+ this.batchCounter += 1;
579
+ const res = func();
580
+ this.batchCounter -= 1;
581
+ return res;
582
+ }
502
583
  static emitsEvents(...events) {
503
584
  return function decorator(_target, _propertyKey, descriptor) {
504
585
  const originalMethod = descriptor.value;
@@ -511,6 +592,73 @@ class Project {
511
592
  return descriptor;
512
593
  };
513
594
  }
595
+ makeCorrections() {
596
+ return this.ignoreEvents(() => {
597
+ let didChange = false;
598
+ didChange = this.correctTestbenchPath() || didChange;
599
+ didChange = this.correctPinconfigPaths() || didChange;
600
+ didChange = this.correctActiveTarget() || didChange;
601
+ return didChange;
602
+ });
603
+ }
604
+ correctTestbenchPath() {
605
+ const testbenches = this.getInputFiles()
606
+ .filter((file) => file.type == 'testbench')
607
+ .map((file) => file.path);
608
+ let didChange = false;
609
+ for (const target of this.getTargets()) {
610
+ const tbPath = target.getEffectiveOptions('iverilog').testbenchFile;
611
+ if (tbPath && testbenches.includes(tbPath)) {
612
+ // testbench is configured and correct
613
+ continue;
614
+ }
615
+ else if (!tbPath && testbenches.length === 0) {
616
+ // no path configured but also no testbenches present, so ok
617
+ continue;
618
+ }
619
+ const newTb = testbenches.length === 0 ? undefined : testbenches[0];
620
+ this.setActiveTestbenchPath(target.id, newTb);
621
+ didChange = true;
622
+ }
623
+ return didChange;
624
+ }
625
+ correctPinconfigPaths() {
626
+ const pinconfigs = this.getInputFiles()
627
+ .filter((file) => file.type == 'pinconfig')
628
+ .map((file) => file.path);
629
+ let didChange = false;
630
+ for (const target of this.getTargets()) {
631
+ const pcPath = target.getEffectiveOptions('nextpnr').pinConfigFile;
632
+ if (pcPath && pinconfigs.includes(pcPath)) {
633
+ // pinconfig is configured and correct
634
+ continue;
635
+ }
636
+ else if (!pcPath && pinconfigs.length === 0) {
637
+ // no path configured but also no testbenches present, so ok
638
+ continue;
639
+ }
640
+ const newPc = pinconfigs.length === 0 ? undefined : pinconfigs[0];
641
+ this.setActivePinConfigPath(target.id, newPc);
642
+ didChange = true;
643
+ }
644
+ return didChange;
645
+ }
646
+ correctActiveTarget() {
647
+ const activeTarget = this.getActiveTarget();
648
+ if (activeTarget)
649
+ return false; // active target exists, so ok
650
+ const activeTargetId = this.configuration.activeTargetId;
651
+ if (activeTargetId && this.hasTarget(activeTargetId))
652
+ return false; // active target ID is valid, so ok
653
+ // No active target or invalid active target ID, so set to first target (if any)
654
+ if (this.configuration.targets.length > 0) {
655
+ this.configuration.activeTargetId = this.configuration.targets[0].id;
656
+ }
657
+ else {
658
+ this.configuration.activeTargetId = undefined;
659
+ }
660
+ return true;
661
+ }
514
662
  static serialize(project) {
515
663
  return {
516
664
  name: project.name,
@@ -584,13 +732,25 @@ __decorate([
584
732
  __metadata("design:type", Function),
585
733
  __metadata("design:paramtypes", [String, String]),
586
734
  __metadata("design:returntype", void 0)
587
- ], Project.prototype, "setTestbenchPath", null);
735
+ ], Project.prototype, "setActiveTestbenchPath", null);
736
+ __decorate([
737
+ Project.emitsEvents('configuration'),
738
+ __metadata("design:type", Function),
739
+ __metadata("design:paramtypes", [String, String]),
740
+ __metadata("design:returntype", void 0)
741
+ ], Project.prototype, "setActivePinConfigPath", null);
588
742
  __decorate([
589
743
  Project.emitsEvents('inputFiles'),
590
744
  __metadata("design:type", Function),
591
745
  __metadata("design:paramtypes", [String, Object]),
592
746
  __metadata("design:returntype", void 0)
593
747
  ], Project.prototype, "setInputFileType", null);
748
+ __decorate([
749
+ Project.emitsEvents('configuration'),
750
+ __metadata("design:type", Function),
751
+ __metadata("design:paramtypes", [Object]),
752
+ __metadata("design:returntype", void 0)
753
+ ], Project.prototype, "setActiveTarget", null);
594
754
  __decorate([
595
755
  Project.emitsEvents('configuration'),
596
756
  __metadata("design:type", Function),