edacation 0.1.0
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.
- package/LICENSE.md +21 -0
- package/README.md +27 -0
- package/dist/cli/index.js +136 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/project/configuration.js +76 -0
- package/dist/project/configuration.js.map +1 -0
- package/dist/project/devices.js +327 -0
- package/dist/project/devices.js.map +1 -0
- package/dist/project/index.js +6 -0
- package/dist/project/index.js.map +1 -0
- package/dist/project/nextpnr.js +83 -0
- package/dist/project/nextpnr.js.map +1 -0
- package/dist/project/project.js +98 -0
- package/dist/project/project.js.map +1 -0
- package/dist/project/target.js +35 -0
- package/dist/project/target.js.map +1 -0
- package/dist/project/yosys.js +73 -0
- package/dist/project/yosys.js.map +1 -0
- package/dist/tool.js +14 -0
- package/dist/tool.js.map +1 -0
- package/dist/util.js +20 -0
- package/dist/util.js.map +1 -0
- package/package.json +49 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 EDAcation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# EDAcation
|
|
2
|
+
|
|
3
|
+
EDAcation is a learning environment for digital hardware design.
|
|
4
|
+
|
|
5
|
+
The following open source EDA tools are used:
|
|
6
|
+
- [Yosys](https://github.com/YosysHQ/yosys) - RTL synthesis
|
|
7
|
+
- [nextpnr](https://github.com/YosysHQ/nextpnr) - FPGA place and route
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
TODO
|
|
11
|
+
|
|
12
|
+
## Documentation
|
|
13
|
+
The documentation is available [here](docs/index.md).
|
|
14
|
+
|
|
15
|
+
## Contributing
|
|
16
|
+
See the [development documentation](docs/development.md). In the future more specific guidelines for contributing could be drafted.
|
|
17
|
+
|
|
18
|
+
## License
|
|
19
|
+
This project is available under the [MIT license](LICENSE.md). Note that some dependencies have different licenses.
|
|
20
|
+
|
|
21
|
+
## Other projects
|
|
22
|
+
EDAcation consists of several projects:
|
|
23
|
+
- [vscode-edacation](https://github.com/EDAcation/vscode-edacation) - VS Code extension
|
|
24
|
+
- [edacation](https://github.com/EDAcation/edacation) - Libary and CLI
|
|
25
|
+
- [yosys.js](https://github.com/EDAcation/yosys.js) - WebAssembly version of Yosys
|
|
26
|
+
- [nextpnr.js](https://github.com/EDAcation/nextpnr.js) - WebAssembly version of nextpnr
|
|
27
|
+
- [nextpnr-viewer](https://github.com/EDAcation/nextpnr-viewer) - FPGA viewer for nextpnr
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { readFile, writeFile, unlink, mkdir } from 'fs/promises';
|
|
3
|
+
import yargs from 'yargs/yargs';
|
|
4
|
+
import { hideBin } from 'yargs/helpers';
|
|
5
|
+
import { exists } from '../util';
|
|
6
|
+
import { Project, VENDORS, generateNextpnrWorker, generateYosysWorker } from '../project';
|
|
7
|
+
import { executeTool } from '../tool';
|
|
8
|
+
console.log('EDAcation CLI');
|
|
9
|
+
console.log();
|
|
10
|
+
const buildCommandArgs = (yargs) => {
|
|
11
|
+
return yargs
|
|
12
|
+
.positional('project', {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'EDA project file (e.g. "full-adder.edaproject")'
|
|
15
|
+
})
|
|
16
|
+
.positional('target', {
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'EDA target'
|
|
19
|
+
})
|
|
20
|
+
.option('execute', {
|
|
21
|
+
type: 'boolean',
|
|
22
|
+
description: 'Whether to execute the tool.',
|
|
23
|
+
default: true,
|
|
24
|
+
alias: 'x'
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
// Parse arguments
|
|
28
|
+
const argv = await yargs(hideBin(process.argv))
|
|
29
|
+
.scriptName('edacation')
|
|
30
|
+
.command('init <project>', 'Initialize EDA project', (yargs) => {
|
|
31
|
+
return yargs
|
|
32
|
+
.positional('project', {
|
|
33
|
+
type: 'string',
|
|
34
|
+
description: 'EDA project file (e.g. "full-adder.edaproject")'
|
|
35
|
+
})
|
|
36
|
+
.option('name', {
|
|
37
|
+
type: 'string',
|
|
38
|
+
description: 'Name of the project (e.g. "Full Adder")'
|
|
39
|
+
});
|
|
40
|
+
})
|
|
41
|
+
.command('yosys <project> <target>', 'Synthesize with Yosys', buildCommandArgs)
|
|
42
|
+
.command('nextpnr <project> <target>', 'Place and route with nextpnr', buildCommandArgs)
|
|
43
|
+
.demandCommand()
|
|
44
|
+
.recommendCommands()
|
|
45
|
+
.strict()
|
|
46
|
+
.help()
|
|
47
|
+
.parse();
|
|
48
|
+
const command = argv._[0];
|
|
49
|
+
// Validate project
|
|
50
|
+
const cwdPath = path.resolve(process.cwd());
|
|
51
|
+
let projectFile = argv.project;
|
|
52
|
+
let projectPath = path.join(cwdPath, projectFile);
|
|
53
|
+
if (command === 'init') {
|
|
54
|
+
if (!projectPath.endsWith('.edaproject')) {
|
|
55
|
+
projectFile = `${projectFile}.edaproject`;
|
|
56
|
+
projectPath = `${projectPath}.edaproject`;
|
|
57
|
+
}
|
|
58
|
+
if (await exists(projectPath)) {
|
|
59
|
+
console.error(`Project "${projectFile}" already exists in "${cwdPath}".`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
let name = argv.name;
|
|
63
|
+
if (!name) {
|
|
64
|
+
name = path.basename(projectPath);
|
|
65
|
+
name = name.substring(0, name.length - '.edaproject'.length);
|
|
66
|
+
}
|
|
67
|
+
const project = new Project(name);
|
|
68
|
+
await writeFile(projectPath, await Project.store(project));
|
|
69
|
+
console.log(`Created project "${name}" in "${projectPath}".`);
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
if (!(await exists(projectPath))) {
|
|
73
|
+
if (projectPath.endsWith('.edaproject')) {
|
|
74
|
+
console.error(`Project "${projectFile}" could not be found in "${cwdPath}".`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
projectPath = `${projectPath}.edaproject`;
|
|
79
|
+
if (!await exists(projectPath)) {
|
|
80
|
+
console.error(`Project "${projectFile}" or "${projectFile}.edaproject" could not be found in "${cwdPath}".`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const cwd = path.dirname(projectPath);
|
|
86
|
+
const shouldExecute = argv.execute;
|
|
87
|
+
const targetId = argv.target;
|
|
88
|
+
// Load project
|
|
89
|
+
const project = await Project.load(await readFile(projectPath));
|
|
90
|
+
const configuration = project.getConfiguration();
|
|
91
|
+
console.log(`Loaded project "${project.getName()}".`);
|
|
92
|
+
const targetNumber = parseInt(targetId);
|
|
93
|
+
const target = configuration.targets.find((target, index) => target.id === targetId || index + 1 === targetNumber);
|
|
94
|
+
if (!target) {
|
|
95
|
+
const targetsText = `${configuration.targets.map((target, index) => `${index + 1}. ${target.id} (${target.name})`).join('\n')}`;
|
|
96
|
+
console.error(`Target "${targetId}" does not exist.\n\nAvailable targets:\n${targetsText}`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
console.log(`Loaded target "${target.name}".`);
|
|
100
|
+
console.log();
|
|
101
|
+
console.log(`Vendor: ${VENDORS[target.vendor].name}`);
|
|
102
|
+
console.log(`Family: ${VENDORS[target.vendor].families[target.family].name}`);
|
|
103
|
+
console.log(`Device: ${VENDORS[target.vendor].families[target.family].devices[target.device].name}`);
|
|
104
|
+
console.log(`Package: ${VENDORS[target.vendor].packages[target.package]}`);
|
|
105
|
+
console.log();
|
|
106
|
+
// Create output directory if necessary
|
|
107
|
+
if (shouldExecute) {
|
|
108
|
+
const targetDirectory = path.join(cwd, target.directory ?? '.');
|
|
109
|
+
if (!await exists(targetDirectory)) {
|
|
110
|
+
await mkdir(targetDirectory, {
|
|
111
|
+
recursive: true
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (command === 'yosys') {
|
|
116
|
+
const workerOptions = generateYosysWorker(project, target.id);
|
|
117
|
+
console.log(workerOptions);
|
|
118
|
+
if (shouldExecute) {
|
|
119
|
+
const designFilePath = path.join(cwd, 'design.ys');
|
|
120
|
+
await writeFile(designFilePath, workerOptions.commands.concat(['']).join('\n'), { encoding: 'utf-8' });
|
|
121
|
+
await executeTool(workerOptions.tool, ['design.ys'], cwd);
|
|
122
|
+
await unlink(designFilePath);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (command === 'nextpnr') {
|
|
126
|
+
const workerOptions = generateNextpnrWorker(project, target.id);
|
|
127
|
+
console.log(workerOptions);
|
|
128
|
+
if (shouldExecute) {
|
|
129
|
+
await executeTool(workerOptions.tool, workerOptions.arguments, cwd);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
console.error(`Unknown command "${command}".`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const DEFAULT_CONFIGURATION = {
|
|
3
|
+
targets: [
|
|
4
|
+
{
|
|
5
|
+
id: 'default',
|
|
6
|
+
name: 'ECP5 - LFE5U-12 - caBGA381',
|
|
7
|
+
vendor: 'lattice',
|
|
8
|
+
family: 'ecp5',
|
|
9
|
+
device: 'lfe5u-12',
|
|
10
|
+
package: 'caBGA381'
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
};
|
|
14
|
+
const schemaValueList = z.object({
|
|
15
|
+
useGenerated: z.boolean().optional().default(true),
|
|
16
|
+
values: z.array(z.string()).optional().default([])
|
|
17
|
+
});
|
|
18
|
+
const schemaValueListTarget = schemaValueList.extend({
|
|
19
|
+
useDefault: z.boolean().optional().default(true)
|
|
20
|
+
});
|
|
21
|
+
const schemaWorker = z.object({
|
|
22
|
+
inputFiles: schemaValueList.optional(),
|
|
23
|
+
outputFiles: schemaValueList.optional()
|
|
24
|
+
});
|
|
25
|
+
const schemaWorkerTarget = z.object({
|
|
26
|
+
inputFiles: schemaValueListTarget.optional(),
|
|
27
|
+
outputFiles: schemaValueListTarget.optional()
|
|
28
|
+
});
|
|
29
|
+
const schemaYosysOptions = z.object({
|
|
30
|
+
optimize: z.boolean().optional()
|
|
31
|
+
});
|
|
32
|
+
const schemaYosys = z.object({
|
|
33
|
+
commands: schemaValueList.optional(),
|
|
34
|
+
options: schemaYosysOptions.optional()
|
|
35
|
+
});
|
|
36
|
+
const schemaYosysTarget = z.object({
|
|
37
|
+
commands: schemaValueListTarget.optional(),
|
|
38
|
+
options: schemaYosysOptions.optional()
|
|
39
|
+
});
|
|
40
|
+
const schemaNextpnrOptions = z.object({
|
|
41
|
+
placedSvg: z.boolean().optional(),
|
|
42
|
+
routedSvg: z.boolean().optional(),
|
|
43
|
+
routedJson: z.boolean().optional()
|
|
44
|
+
});
|
|
45
|
+
const schemaNextpnr = z.object({
|
|
46
|
+
arguments: schemaValueList.optional(),
|
|
47
|
+
options: schemaNextpnrOptions.optional()
|
|
48
|
+
});
|
|
49
|
+
const schemaNextpnrTarget = z.object({
|
|
50
|
+
arguments: schemaValueListTarget.optional(),
|
|
51
|
+
options: schemaNextpnrOptions.optional()
|
|
52
|
+
});
|
|
53
|
+
const schemaCombinedYosys = schemaWorker.merge(schemaYosys);
|
|
54
|
+
const schemaCombinedYosysTarget = schemaWorkerTarget.merge(schemaYosysTarget);
|
|
55
|
+
const schemaCombinedNextpnr = schemaWorker.merge(schemaNextpnr);
|
|
56
|
+
const schemaCombinedNextpnrTarget = schemaWorkerTarget.merge(schemaNextpnrTarget);
|
|
57
|
+
const schemaTargetDefaults = z.object({
|
|
58
|
+
yosys: schemaCombinedYosys.optional(),
|
|
59
|
+
nextpnr: schemaCombinedNextpnr.optional()
|
|
60
|
+
});
|
|
61
|
+
const schemaTarget = z.object({
|
|
62
|
+
id: z.string(),
|
|
63
|
+
name: z.string(),
|
|
64
|
+
vendor: z.string(),
|
|
65
|
+
family: z.string(),
|
|
66
|
+
device: z.string(),
|
|
67
|
+
package: z.string(),
|
|
68
|
+
directory: z.string().optional(),
|
|
69
|
+
yosys: schemaCombinedYosysTarget.optional(),
|
|
70
|
+
nextpnr: schemaCombinedNextpnrTarget.optional()
|
|
71
|
+
});
|
|
72
|
+
export const schemaProjectConfiguration = z.object({
|
|
73
|
+
defaults: schemaTargetDefaults.optional(),
|
|
74
|
+
targets: z.array(schemaTarget)
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=configuration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configuration.js","sourceRoot":"","sources":["../../src/project/configuration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
export const VENDORS = {
|
|
2
|
+
generic: {
|
|
3
|
+
name: 'Generic',
|
|
4
|
+
url: 'https://github.com/YosysHQ/nextpnr/blob/master/docs/generic.md',
|
|
5
|
+
packages: {
|
|
6
|
+
generic: 'Generic'
|
|
7
|
+
},
|
|
8
|
+
families: {
|
|
9
|
+
generic: {
|
|
10
|
+
name: 'Generic',
|
|
11
|
+
architecture: 'generic',
|
|
12
|
+
devices: {
|
|
13
|
+
generic: {
|
|
14
|
+
name: 'Generic',
|
|
15
|
+
device: 'generic',
|
|
16
|
+
packages: ['generic']
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
gowin: {
|
|
23
|
+
name: 'Gowin',
|
|
24
|
+
url: 'https://gowinsemi.com',
|
|
25
|
+
packages: {
|
|
26
|
+
LQ144: 'LQ144 (20 mm x 20 mm)',
|
|
27
|
+
QFN48: 'QFN48 (6 mm x 6 mm)',
|
|
28
|
+
QN48: 'QN48 (6 mm x 6 mm)',
|
|
29
|
+
QN48P: 'QN48P (6 mm x 6 mm)',
|
|
30
|
+
QN88: 'QN88 (10 mm x 10 mm)'
|
|
31
|
+
},
|
|
32
|
+
families: {
|
|
33
|
+
littlebee: {
|
|
34
|
+
name: 'LittleBee',
|
|
35
|
+
architecture: 'gowin',
|
|
36
|
+
url: 'https://www.gowinsemi.com/en/product/detail/46',
|
|
37
|
+
devices: {
|
|
38
|
+
'gw1n-1': {
|
|
39
|
+
name: 'GW1N-1',
|
|
40
|
+
device: 'GW1N-1',
|
|
41
|
+
// NOTE: other packages are also listed on the Gowin website, but nextpnr does not appear to support it for this device
|
|
42
|
+
packages: ['QN48']
|
|
43
|
+
},
|
|
44
|
+
// NOTE: GW1N-1P5 and GW1N-2 are also listed on the Gowin website, but nextpnr does not appear to support these devices
|
|
45
|
+
'gw1n-4': {
|
|
46
|
+
name: 'GW1N-4',
|
|
47
|
+
device: 'GW1N-4',
|
|
48
|
+
// NOTE: other packages are also listed on the Gowin website, but nextpnr does not appear to support it for this device
|
|
49
|
+
packages: ['LQ144']
|
|
50
|
+
},
|
|
51
|
+
// GW1N-9 is also listed on the Gowin website, but nextpnr does not appear to support this device
|
|
52
|
+
// GW1NR-1, GW1NR-2 and GW1NR-4 are also listed on the Gowin website, but nextpnr does not appear to support these devices
|
|
53
|
+
'gw1nr-9': {
|
|
54
|
+
name: 'GW1NR-9',
|
|
55
|
+
device: 'GW1NR-9',
|
|
56
|
+
// NOTE: other packages are also listed on the Gowin website, but nextpnr does not appear to support it for this device
|
|
57
|
+
packages: ['QN88']
|
|
58
|
+
},
|
|
59
|
+
// NOTE: GW1NS-2 is also listed on the Gowin website, but nextpnr does not appear to support this device
|
|
60
|
+
'gw1ns-2c': {
|
|
61
|
+
name: 'GW1NS-2C',
|
|
62
|
+
device: 'GW1NS-2C',
|
|
63
|
+
// NOTE: other packages are also listed on the Gowin website, but nextpnr does not appear to support it for this device
|
|
64
|
+
packages: ['QN48']
|
|
65
|
+
},
|
|
66
|
+
// NOTE: GW1NS-4 and GW1NS-4C are also listed on the Gowin website, but nextpnr does not appear to support these devices
|
|
67
|
+
'gw1nz-1': {
|
|
68
|
+
name: 'GW1NZ-1',
|
|
69
|
+
device: 'GW1NZ-1',
|
|
70
|
+
// NOTE: other packages are also listed on the Gowin website, but nextpnr does not appear to support it for this devi
|
|
71
|
+
packages: ['QFN48']
|
|
72
|
+
},
|
|
73
|
+
'gw1nsr-4c': {
|
|
74
|
+
name: 'GW1NSR-4C',
|
|
75
|
+
device: 'GW1NSR-4C',
|
|
76
|
+
// NOTE: other packages are also listed on the Gowin website, but nextpnr does not appear to support it for this device
|
|
77
|
+
packages: ['QN48P']
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
lattice: {
|
|
84
|
+
name: 'Lattice',
|
|
85
|
+
url: 'https://www.latticesemi.com',
|
|
86
|
+
packages: {
|
|
87
|
+
ASG256: 'ASG256 (9 x 9 mm)',
|
|
88
|
+
BBG484: 'BBG484 (19 x 19 mm)',
|
|
89
|
+
BFG484: 'BFG484 (23 x 23 mm)',
|
|
90
|
+
bg121: '121-ball caBGA (9 x 9 mm)',
|
|
91
|
+
'bg121:4k': '121-ball caBGA (9 x 9 mm)',
|
|
92
|
+
caBGA256: '256-ball caBGA (14 x 14 mm)',
|
|
93
|
+
caBGA381: '381-ball caBGA (17 x 17 mm)',
|
|
94
|
+
caBGA400: '400-ball caBGA (17 x 17 mm)',
|
|
95
|
+
caBGA554: '554-ball caBGA (23 x 23 mm)',
|
|
96
|
+
caBGA756: '756-ball caBGA (27 x 27 mm)',
|
|
97
|
+
cb81: '81-ball csBGA2 (5 x 5 mm)',
|
|
98
|
+
cb121: '121-ball csBGA (6 x 6 mm)',
|
|
99
|
+
cb132: '132-ball csBGA (8 x 8 mm)',
|
|
100
|
+
'cb132:4k': '132-ball csBGA (8 x 8 mm)',
|
|
101
|
+
CBG256: 'CBG256 (14 x 14 mm)',
|
|
102
|
+
cm36: '36-ball ucBGA (2.5 x 2.5 mm)',
|
|
103
|
+
cm49: '49-ball ucBGA (3 x 3 mm)',
|
|
104
|
+
cm81: '81-ball ucBGA (4 x 4 mm)',
|
|
105
|
+
'cm81:4k': '81-ball ucBGA (4 x 4 mm)',
|
|
106
|
+
cm121: '121-ball ucBGA (5 x 5 mm)',
|
|
107
|
+
'cm121:4k': '121-ball ucBGA (5 x 5 mm)',
|
|
108
|
+
cm225: '225-ball ucBGA (7 x 7 mm)',
|
|
109
|
+
'cm225:4k': '225-ball ucBGA (7 x 7 mm)',
|
|
110
|
+
ct121: '121-ball caBGA (9 x 9 mm)',
|
|
111
|
+
ct256: '256-ball caBGA (14 x 14 mm)',
|
|
112
|
+
csfBGA121: '121 csfBGA (6 x 6 mm)',
|
|
113
|
+
csfBGA285: '285 csfBGA (10 x 10 mm)',
|
|
114
|
+
csfBGA289: '289 csBGA (9.5 x 9.5 mm)',
|
|
115
|
+
LFG672: 'LFG672 (27 x 27 mm)',
|
|
116
|
+
QFN32: '32-pin QFN (5 x 5 mm)',
|
|
117
|
+
QFN48: '48-pin QFN (7 x 7 mm)',
|
|
118
|
+
QFN72: '72-pin QFN (10 x 10 mm)',
|
|
119
|
+
qn32: '32-pin QFN (5 x 5 mm)',
|
|
120
|
+
qn84: '84-pin QFNS (7 x 7 mm)',
|
|
121
|
+
swg16tr: '16-ball WLCSP (1.40 x 1.48 mm)',
|
|
122
|
+
tq144: '144-pin TQFP (20 x 20 mm)',
|
|
123
|
+
'tq144:4k': '144-pin TQFP (20 x 20 mm)',
|
|
124
|
+
TQFP100: '100-pin TQFP (14 x 14 mm)',
|
|
125
|
+
TQFP144: '144-pin TQFP (20 x 20 mm)',
|
|
126
|
+
vq100: '100-pin VQFP (14 x 14 mm)'
|
|
127
|
+
},
|
|
128
|
+
families: {
|
|
129
|
+
// 'certus-nx': {
|
|
130
|
+
// name: 'Certus-NX',
|
|
131
|
+
// architecture: 'nexus',
|
|
132
|
+
// url: 'https://www.latticesemi.com/Certus-NX',
|
|
133
|
+
// devices: {
|
|
134
|
+
// // NOTE: LFD2NX-17 is also listed on the Lattice website, but nextpnr does not appear to support this device
|
|
135
|
+
// 'lfd2nx-40': {
|
|
136
|
+
// name: 'LFD2NX-40',
|
|
137
|
+
// device: 'LFD2NX-40',
|
|
138
|
+
// // NOTE: csfBGA121 and caBGA196 are also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
139
|
+
// packages: ['caBGA256']
|
|
140
|
+
// }
|
|
141
|
+
// }
|
|
142
|
+
// },
|
|
143
|
+
// 'certuspro-nx': {
|
|
144
|
+
// name: 'CertusPro-NX',
|
|
145
|
+
// architecture: 'nexus',
|
|
146
|
+
// url: 'https://www.latticesemi.com/CertusPro-NX',
|
|
147
|
+
// devices: {
|
|
148
|
+
// // NOTE: LFCPNX-50 is also listed on the Lattice website, but nextpnr does not appear to support this device
|
|
149
|
+
// 'lfcpnx-100': {
|
|
150
|
+
// name: 'LFCPNX-100',
|
|
151
|
+
// device: 'LFCPNX-100',
|
|
152
|
+
// packages: ['ASG256', 'CBG256', 'BBG484', 'BFG484', 'LFG672']
|
|
153
|
+
// }
|
|
154
|
+
// }
|
|
155
|
+
// },
|
|
156
|
+
'crosslink-nx': {
|
|
157
|
+
name: 'CrossLink-NX',
|
|
158
|
+
architecture: 'nexus',
|
|
159
|
+
url: 'https://www.latticesemi.com/CrossLink-NX',
|
|
160
|
+
devices: {
|
|
161
|
+
'lifcl-17': {
|
|
162
|
+
name: 'LIFCL-17',
|
|
163
|
+
device: 'LIFCL-17',
|
|
164
|
+
packages: ['WLCSP72', 'QFN72', 'csfBGA121', 'caBGA256']
|
|
165
|
+
},
|
|
166
|
+
// NOTE: LIFCL-33 is also listed on the Lattice website, but nextpnr does not appear to support this device
|
|
167
|
+
'lifcl-40': {
|
|
168
|
+
name: 'LIFCL-40',
|
|
169
|
+
device: 'LIFCL-40',
|
|
170
|
+
packages: ['QFN72', 'csfBGA121', 'caBGA256', 'csfBGA289', 'caBGA400']
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
ecp5: {
|
|
175
|
+
name: 'ECP5 / ECP5-5G',
|
|
176
|
+
architecture: 'ecp5',
|
|
177
|
+
url: 'https://www.latticesemi.com/ECP5',
|
|
178
|
+
devices: {
|
|
179
|
+
'lfe5u-12': {
|
|
180
|
+
name: 'LFE5U-12',
|
|
181
|
+
device: '12k',
|
|
182
|
+
// NOTE: TQFP144 is also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
183
|
+
packages: ['csfBGA285', 'caBGA256', 'caBGA381']
|
|
184
|
+
},
|
|
185
|
+
'lfe5u-25': {
|
|
186
|
+
name: 'LFE5U-25',
|
|
187
|
+
device: '25k',
|
|
188
|
+
// NOTE: TQFP144 is also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
189
|
+
packages: ['csfBGA285', 'caBGA256', 'caBGA381']
|
|
190
|
+
},
|
|
191
|
+
'lfe5u-45': {
|
|
192
|
+
name: 'LFE5U-45',
|
|
193
|
+
device: '45k',
|
|
194
|
+
// NOTE: TQFP144 is also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
195
|
+
packages: ['csfBGA285', 'caBGA256', 'caBGA381', 'caBGA554']
|
|
196
|
+
},
|
|
197
|
+
'lfe5u-85': {
|
|
198
|
+
name: 'LFE5U-85',
|
|
199
|
+
device: '85k',
|
|
200
|
+
packages: ['csfBGA285', 'caBGA381', 'caBGA554', 'caBGA756']
|
|
201
|
+
},
|
|
202
|
+
'lfe5um-25': {
|
|
203
|
+
name: 'LFE5UM-25',
|
|
204
|
+
device: 'um-25k',
|
|
205
|
+
packages: ['csfBGA285', 'caBGA381']
|
|
206
|
+
},
|
|
207
|
+
'lfe5um-45': {
|
|
208
|
+
name: 'LFE5UM-45',
|
|
209
|
+
device: 'um-45k',
|
|
210
|
+
packages: ['csfBGA285', 'caBGA381', 'caBGA554']
|
|
211
|
+
},
|
|
212
|
+
'lfe5um-85': {
|
|
213
|
+
name: 'LFE5UM-85',
|
|
214
|
+
device: 'um-85k',
|
|
215
|
+
packages: ['csfBGA285', 'caBGA381', 'caBGA554', 'caBGA756']
|
|
216
|
+
},
|
|
217
|
+
'lfe5um5g-25': {
|
|
218
|
+
name: 'LFE5UM5G-25',
|
|
219
|
+
device: 'um5g-25k',
|
|
220
|
+
packages: ['csfBGA285', 'caBGA381']
|
|
221
|
+
},
|
|
222
|
+
'lfe5um5g-45': {
|
|
223
|
+
name: 'LFE5UM5G-45',
|
|
224
|
+
device: 'um5g-45k',
|
|
225
|
+
packages: ['csfBGA285', 'caBGA381', 'caBGA554']
|
|
226
|
+
},
|
|
227
|
+
'lfe5um5g-85': {
|
|
228
|
+
name: 'LFE5UM5G-85',
|
|
229
|
+
device: 'um5g-85k',
|
|
230
|
+
packages: ['csfBGA285', 'caBGA381', 'caBGA554', 'caBGA756']
|
|
231
|
+
}
|
|
232
|
+
// NOTE: ECP5 Automative Devices are also listed on the Lattice website, but nextpnr does not appear to support those devices
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
ice40: {
|
|
236
|
+
name: 'iCE40 LP/HX',
|
|
237
|
+
architecture: 'ice40',
|
|
238
|
+
url: 'https://www.latticesemi.com/iCE40',
|
|
239
|
+
devices: {
|
|
240
|
+
lp384: {
|
|
241
|
+
name: 'LP384',
|
|
242
|
+
device: 'lp384',
|
|
243
|
+
packages: ['cm36', 'cm49', 'qn32']
|
|
244
|
+
},
|
|
245
|
+
// NOTE: LP640 is also listed on the Lattice website, but nextpnr does not appear to support this device
|
|
246
|
+
lp1k: {
|
|
247
|
+
name: 'LP1K',
|
|
248
|
+
device: 'lp1k',
|
|
249
|
+
packages: ['swg16tr', 'cm36', 'cm49', 'cm81', 'cm121', 'qn84', 'cb81', 'cb121']
|
|
250
|
+
},
|
|
251
|
+
lp4k: {
|
|
252
|
+
name: 'LP4K',
|
|
253
|
+
device: 'lp8k',
|
|
254
|
+
packages: ['cm81:4k', 'cm121:4k', 'cm225:4k']
|
|
255
|
+
},
|
|
256
|
+
lp8k: {
|
|
257
|
+
name: 'LP8K',
|
|
258
|
+
device: 'lp8k',
|
|
259
|
+
packages: ['cm81', 'cm121', 'cm225']
|
|
260
|
+
},
|
|
261
|
+
hx1k: {
|
|
262
|
+
name: 'HX1K',
|
|
263
|
+
device: 'hx1k',
|
|
264
|
+
packages: ['cb132', 'vq100', 'tq144']
|
|
265
|
+
},
|
|
266
|
+
hx4k: {
|
|
267
|
+
name: 'HX4K',
|
|
268
|
+
device: 'hx8k',
|
|
269
|
+
packages: ['cb132:4k', 'tq144:4k', 'bg121:4k']
|
|
270
|
+
},
|
|
271
|
+
hx8k: {
|
|
272
|
+
name: 'HX8K',
|
|
273
|
+
device: 'hx8k',
|
|
274
|
+
packages: ['cm225', 'cb132', 'bg121', 'ct256']
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
machxo2: {
|
|
279
|
+
name: 'MachXO2',
|
|
280
|
+
architecture: 'machxo2',
|
|
281
|
+
url: 'https://www.latticesemi.com/MachXO2',
|
|
282
|
+
devices: {
|
|
283
|
+
'xo2-256': {
|
|
284
|
+
name: 'XO2-256',
|
|
285
|
+
device: '256',
|
|
286
|
+
// NOTE: other packages are also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
287
|
+
packages: ['QFN32']
|
|
288
|
+
},
|
|
289
|
+
'xo2-640': {
|
|
290
|
+
name: 'XO2-640',
|
|
291
|
+
device: '640',
|
|
292
|
+
// NOTE: other packages are also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
293
|
+
packages: ['QFN48']
|
|
294
|
+
},
|
|
295
|
+
// NOTE: XO2-640U is also listed on the Lattice website, but nextpnr does not appear to support this device
|
|
296
|
+
'xo2-1200': {
|
|
297
|
+
name: 'XO2-1200',
|
|
298
|
+
device: '1200',
|
|
299
|
+
// NOTE: other packages are also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
300
|
+
packages: ['QFN32']
|
|
301
|
+
},
|
|
302
|
+
// NOTE: XO2-1200U is also listed on the Lattice website, but nextpnr does not appear to support this device
|
|
303
|
+
'xo2-2000': {
|
|
304
|
+
name: 'XO2-2000',
|
|
305
|
+
device: '2000',
|
|
306
|
+
// NOTE: other packages are also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
307
|
+
packages: ['TQFP100']
|
|
308
|
+
},
|
|
309
|
+
// NOTE: XO2-2000U is also listed on the Lattice website, but nextpnr does not appear to support this device
|
|
310
|
+
'xo2-4000': {
|
|
311
|
+
name: 'XO2-4000',
|
|
312
|
+
device: '4000',
|
|
313
|
+
// NOTE: other packages are also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
314
|
+
packages: ['TQFP144']
|
|
315
|
+
},
|
|
316
|
+
'xo2-7000': {
|
|
317
|
+
name: 'XO2-7000',
|
|
318
|
+
device: '7000',
|
|
319
|
+
// NOTE: other packages are also listed on the Lattice website, but nextpnr does not appear to support it for this device
|
|
320
|
+
packages: ['TQFP144']
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
//# sourceMappingURL=devices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devices.js","sourceRoot":"","sources":["../../src/project/devices.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { VENDORS } from './devices';
|
|
2
|
+
import { getCombined, getOptions, getTarget, getTargetFile } from './target';
|
|
3
|
+
const DEFAULT_OPTIONS = {
|
|
4
|
+
placedSvg: true,
|
|
5
|
+
routedSvg: true,
|
|
6
|
+
routedJson: true
|
|
7
|
+
};
|
|
8
|
+
export const generateNextpnrWorker = (project, targetId) => {
|
|
9
|
+
const target = getTarget(project.getConfiguration(), targetId);
|
|
10
|
+
const options = getOptions(project.getConfiguration(), targetId, 'nextpnr', DEFAULT_OPTIONS);
|
|
11
|
+
const vendor = VENDORS[target.vendor];
|
|
12
|
+
const family = vendor.families[target.family];
|
|
13
|
+
const device = family.devices[target.device];
|
|
14
|
+
const generatedInputFiles = [
|
|
15
|
+
getTargetFile(target, `${family.architecture}.json`)
|
|
16
|
+
];
|
|
17
|
+
const generatedOutputFiles = [];
|
|
18
|
+
const generatedArgs = [];
|
|
19
|
+
switch (family.architecture) {
|
|
20
|
+
case 'ecp5': {
|
|
21
|
+
generatedArgs.push(`--${device.device}`);
|
|
22
|
+
generatedArgs.push('--package', target.package.toUpperCase());
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case 'generic': {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 'gowin': {
|
|
29
|
+
generatedArgs.push('--device', `${device.device.replace('-', '-UV')}${target.package}C5/I4`);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case 'ice40': {
|
|
33
|
+
generatedArgs.push(`--${device.device}`);
|
|
34
|
+
generatedArgs.push('--package', target.package);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case 'nexus': {
|
|
38
|
+
const packageLookup = {
|
|
39
|
+
WLCSP72: 'UWG72',
|
|
40
|
+
QFN72: 'SG72',
|
|
41
|
+
csfBGA121: 'MG121',
|
|
42
|
+
caBGA256: 'BG256',
|
|
43
|
+
csfBGA289: 'MG289',
|
|
44
|
+
caBGA400: 'BG400'
|
|
45
|
+
};
|
|
46
|
+
if (target.package in packageLookup) {
|
|
47
|
+
throw new Error(`Package "${target.package}" is currenty not supported.`);
|
|
48
|
+
}
|
|
49
|
+
generatedArgs.push('--device', `${device.device}-7${packageLookup[target.package]}C`);
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
default: {
|
|
53
|
+
throw new Error(`Architecture "${family.architecture}" is currently not supported.`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
generatedArgs.push('--json', generatedInputFiles[0]);
|
|
57
|
+
if (options.placedSvg) {
|
|
58
|
+
const file = getTargetFile(target, 'placed.svg');
|
|
59
|
+
generatedOutputFiles.push(file);
|
|
60
|
+
generatedArgs.push('--placed-svg', file);
|
|
61
|
+
}
|
|
62
|
+
if (options.routedSvg) {
|
|
63
|
+
const file = getTargetFile(target, 'routed.svg');
|
|
64
|
+
generatedOutputFiles.push(file);
|
|
65
|
+
generatedArgs.push('--routed-svg', file);
|
|
66
|
+
}
|
|
67
|
+
if (options.routedJson) {
|
|
68
|
+
const file = getTargetFile(target, 'routed.nextpnr.json');
|
|
69
|
+
generatedOutputFiles.push(file);
|
|
70
|
+
generatedArgs.push('--write', file);
|
|
71
|
+
}
|
|
72
|
+
const inputFiles = getCombined(project.getConfiguration(), targetId, 'nextpnr', 'inputFiles', generatedInputFiles);
|
|
73
|
+
const outputFiles = getCombined(project.getConfiguration(), targetId, 'nextpnr', 'outputFiles', generatedOutputFiles);
|
|
74
|
+
const tool = `nextpnr-${family.architecture}`;
|
|
75
|
+
const args = getCombined(project.getConfiguration(), targetId, 'nextpnr', 'arguments', generatedArgs);
|
|
76
|
+
return {
|
|
77
|
+
inputFiles,
|
|
78
|
+
outputFiles,
|
|
79
|
+
tool,
|
|
80
|
+
arguments: args
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=nextpnr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextpnr.js","sourceRoot":"","sources":["../../src/project/nextpnr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { decodeJSON, encodeJSON } from '../util';
|
|
2
|
+
import { DEFAULT_CONFIGURATION, schemaProjectConfiguration } from './configuration';
|
|
3
|
+
export class Project {
|
|
4
|
+
constructor(name, inputFiles = [], outputFiles = [], configuration = DEFAULT_CONFIGURATION) {
|
|
5
|
+
this.name = name;
|
|
6
|
+
this.inputFiles = inputFiles;
|
|
7
|
+
this.outputFiles = outputFiles;
|
|
8
|
+
const config = schemaProjectConfiguration.safeParse(configuration);
|
|
9
|
+
if (config.success) {
|
|
10
|
+
this.configuration = config.data;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
throw new Error(`Failed to parse project configuration: ${config.error}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
getName() {
|
|
17
|
+
return this.name;
|
|
18
|
+
}
|
|
19
|
+
getInputFiles() {
|
|
20
|
+
return this.inputFiles;
|
|
21
|
+
}
|
|
22
|
+
hasInputFile(filePath) {
|
|
23
|
+
return this.inputFiles.some((file) => file === filePath);
|
|
24
|
+
}
|
|
25
|
+
async addInputFiles(filePaths) {
|
|
26
|
+
for (const filePath of filePaths) {
|
|
27
|
+
if (!this.hasInputFile(filePath)) {
|
|
28
|
+
this.inputFiles.push(filePath);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
this.inputFiles.sort((a, b) => {
|
|
32
|
+
return a < b ? -1 : 1;
|
|
33
|
+
});
|
|
34
|
+
await this.save();
|
|
35
|
+
}
|
|
36
|
+
async removeInputFiles(filePaths) {
|
|
37
|
+
this.inputFiles = this.inputFiles.filter((file) => !filePaths.includes(file));
|
|
38
|
+
await this.save();
|
|
39
|
+
}
|
|
40
|
+
getOutputFiles() {
|
|
41
|
+
return this.outputFiles;
|
|
42
|
+
}
|
|
43
|
+
hasOutputFile(filePath) {
|
|
44
|
+
return this.outputFiles.some((file) => file === filePath);
|
|
45
|
+
}
|
|
46
|
+
async addOutputFiles(filePaths) {
|
|
47
|
+
for (const filePath of filePaths) {
|
|
48
|
+
if (!this.hasOutputFile(filePath)) {
|
|
49
|
+
this.outputFiles.push(filePath);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
this.outputFiles.sort((a, b) => {
|
|
53
|
+
return a < b ? -1 : 1;
|
|
54
|
+
});
|
|
55
|
+
await this.save();
|
|
56
|
+
}
|
|
57
|
+
async removeOutputFiles(filePaths) {
|
|
58
|
+
this.outputFiles = this.outputFiles.filter((file) => !filePaths.includes(file));
|
|
59
|
+
await this.save();
|
|
60
|
+
}
|
|
61
|
+
getConfiguration() {
|
|
62
|
+
return this.configuration;
|
|
63
|
+
}
|
|
64
|
+
updateConfiguration(configuration) {
|
|
65
|
+
this.configuration = {
|
|
66
|
+
...this.configuration,
|
|
67
|
+
...configuration
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async save() {
|
|
71
|
+
await Project.store(this);
|
|
72
|
+
}
|
|
73
|
+
static serialize(project) {
|
|
74
|
+
return {
|
|
75
|
+
name: project.name,
|
|
76
|
+
inputFiles: project.inputFiles,
|
|
77
|
+
outputFiles: project.outputFiles,
|
|
78
|
+
configuration: project.configuration
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
static deserialize(data) {
|
|
82
|
+
const name = data.name;
|
|
83
|
+
const inputFiles = data.inputFiles ?? [];
|
|
84
|
+
const outputFiles = data.outputFiles ?? [];
|
|
85
|
+
const configuration = data.configuration ?? {};
|
|
86
|
+
return new Project(name, inputFiles, outputFiles, configuration);
|
|
87
|
+
}
|
|
88
|
+
static async load(rawData) {
|
|
89
|
+
const data = decodeJSON(rawData);
|
|
90
|
+
const project = Project.deserialize(data);
|
|
91
|
+
return project;
|
|
92
|
+
}
|
|
93
|
+
static async store(project) {
|
|
94
|
+
const data = Project.serialize(project);
|
|
95
|
+
return encodeJSON(data, true);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/project/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
export const getTargetDefaults = (configuration) => {
|
|
3
|
+
return configuration.defaults ?? {};
|
|
4
|
+
};
|
|
5
|
+
export const getTarget = (configuration, targetId) => {
|
|
6
|
+
const target = configuration.targets.find((target) => target.id === targetId);
|
|
7
|
+
if (!target) {
|
|
8
|
+
throw new Error(`Target "${targetId}" could not be found.`);
|
|
9
|
+
}
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
export const getTargetFile = (target, file) => path.join(target.directory ?? '.', file);
|
|
13
|
+
export const getOptions = (configuration, targetId, workerId, defaultValues) => {
|
|
14
|
+
const targetDefaults = getTargetDefaults(configuration)[workerId];
|
|
15
|
+
const target = getTarget(configuration, targetId)[workerId];
|
|
16
|
+
const defaultConfig = targetDefaults ? targetDefaults.options : undefined;
|
|
17
|
+
const config = target ? target.options : undefined;
|
|
18
|
+
return {
|
|
19
|
+
...defaultValues,
|
|
20
|
+
...defaultConfig,
|
|
21
|
+
...config
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export const getCombined = (configuration, targetId, workerId, configId, generated) => {
|
|
25
|
+
const targetDefaults = getTargetDefaults(configuration)[workerId];
|
|
26
|
+
const target = getTarget(configuration, targetId)[workerId];
|
|
27
|
+
const defaultConfig = targetDefaults ? targetDefaults[configId] : undefined;
|
|
28
|
+
const config = target ? target[configId] : undefined;
|
|
29
|
+
return [
|
|
30
|
+
...(!config || config.useGenerated) ? generated : [],
|
|
31
|
+
...(!config || config.useDefault) && !!defaultConfig ? defaultConfig.values : [],
|
|
32
|
+
...(config ? config.values : [])
|
|
33
|
+
];
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../../src/project/target.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,aAAmC,EAA+B,EAAE;IAClG,OAAO,aAAa,CAAC,QAAQ,IAAI,EAAE,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,aAAmC,EAAE,QAAgB,EAAuB,EAAE;IACpG,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IAC9E,IAAI,CAAC,MAAM,EAAE;QACT,MAAM,IAAI,KAAK,CAAC,WAAW,QAAQ,uBAAuB,CAAC,CAAC;KAC/D;IACD,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAA2B,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,GAAG,EAAE,IAAI,CAAC,CAAC;AAOrH,MAAM,CAAC,MAAM,UAAU,GAAG,CACtB,aAAmC,EACnC,QAAgB,EAChB,QAAW,EACX,aAAmC,EACf,EAAE;IACtB,MAAM,cAAc,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE5D,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnD,OAAO;QACH,GAAG,aAAa;QAChB,GAAG,aAAa;QAChB,GAAG,MAAM;KACZ,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,aAAmC,EAAE,QAAgB,EAAE,QAAkB,EAAE,QAAgB,EAAE,SAAmB,EAAE,EAAE;IAC5I,MAAM,cAAc,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE5D,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAErD,OAAO;QACH,GAAG,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QACpD,GAAG,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;QAChF,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;KACnC,CAAC;AACN,CAAC,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { FILE_EXTENSIONS_VERILOG, FILE_EXTENSIONS_HDL } from '../util';
|
|
3
|
+
import { VENDORS } from './devices';
|
|
4
|
+
import { getCombined, getOptions, getTarget, getTargetFile } from './target';
|
|
5
|
+
const DEFAULT_OPTIONS = {
|
|
6
|
+
optimize: true
|
|
7
|
+
};
|
|
8
|
+
export const generateYosysWorker = (project, targetId) => {
|
|
9
|
+
const target = getTarget(project.getConfiguration(), targetId);
|
|
10
|
+
const options = getOptions(project.getConfiguration(), targetId, 'yosys', DEFAULT_OPTIONS);
|
|
11
|
+
const vendor = VENDORS[target.vendor];
|
|
12
|
+
const family = vendor.families[target.family];
|
|
13
|
+
const generatedInputFiles = project.getInputFiles().filter((inputFile) => FILE_EXTENSIONS_HDL.includes(path.extname(inputFile).substring(1)));
|
|
14
|
+
const generatedOutputFiles = [
|
|
15
|
+
getTargetFile(target, `${family.architecture}.json`)
|
|
16
|
+
];
|
|
17
|
+
const generatedCommands = [
|
|
18
|
+
...generatedInputFiles.map((file) => `read_verilog ${file}`),
|
|
19
|
+
'proc;'
|
|
20
|
+
];
|
|
21
|
+
if (options.optimize) {
|
|
22
|
+
generatedCommands.push('opt;');
|
|
23
|
+
}
|
|
24
|
+
if (family.architecture === 'generic') {
|
|
25
|
+
generatedCommands.push('synth;');
|
|
26
|
+
generatedCommands.push(`write_json ${generatedOutputFiles[0]};`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
generatedCommands.push(`synth_${family.architecture} -json ${generatedOutputFiles[0]};`);
|
|
30
|
+
}
|
|
31
|
+
const inputFiles = getCombined(project.getConfiguration(), targetId, 'yosys', 'inputFiles', generatedInputFiles);
|
|
32
|
+
const outputFiles = getCombined(project.getConfiguration(), targetId, 'yosys', 'outputFiles', generatedOutputFiles);
|
|
33
|
+
const tool = 'yosys';
|
|
34
|
+
const commands = getCombined(project.getConfiguration(), targetId, 'yosys', 'commands', generatedCommands);
|
|
35
|
+
return {
|
|
36
|
+
inputFiles,
|
|
37
|
+
outputFiles,
|
|
38
|
+
tool,
|
|
39
|
+
commands
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export const generateYosysRTLCommands = (inputFiles) => {
|
|
43
|
+
const verilogFiles = inputFiles.filter((file) => FILE_EXTENSIONS_VERILOG.includes(path.extname(file).substring(1)));
|
|
44
|
+
// Yosys commands taken from yosys2digitaljs (https://github.com/tilk/yosys2digitaljs/blob/1b4afeae61/src/index.ts#L1225)
|
|
45
|
+
return [
|
|
46
|
+
...verilogFiles.map((file) => `read_verilog ${file}`),
|
|
47
|
+
'hierarchy -auto-top',
|
|
48
|
+
'proc;',
|
|
49
|
+
'opt;',
|
|
50
|
+
'memory -nomap;',
|
|
51
|
+
'wreduce -memx;',
|
|
52
|
+
'opt -full;',
|
|
53
|
+
'write_json rtl.digitaljs.json',
|
|
54
|
+
''
|
|
55
|
+
];
|
|
56
|
+
};
|
|
57
|
+
export const generateYosysSynthCommands = (inputFiles) => {
|
|
58
|
+
const verilogFiles = inputFiles.filter((file) => FILE_EXTENSIONS_VERILOG.includes(path.extname(file).substring(1)));
|
|
59
|
+
return [
|
|
60
|
+
...verilogFiles.map((file) => `read_verilog ${file}`),
|
|
61
|
+
'proc;',
|
|
62
|
+
'opt;',
|
|
63
|
+
'synth -lut 4',
|
|
64
|
+
'write_json luts.digitaljs.json',
|
|
65
|
+
'design -reset',
|
|
66
|
+
...verilogFiles.map((file) => `read_verilog ${file}`),
|
|
67
|
+
'proc;',
|
|
68
|
+
'opt;',
|
|
69
|
+
'synth_ecp5 -json ecp5.json;',
|
|
70
|
+
''
|
|
71
|
+
];
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=yosys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yosys.js","sourceRoot":"","sources":["../../src/project/yosys.ts"],"names":[],"mappings":"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"}
|
package/dist/tool.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
export const executeTool = (tool, args, cwd) => new Promise((resolve, reject) => {
|
|
3
|
+
const p = spawn(tool, args, {
|
|
4
|
+
cwd,
|
|
5
|
+
stdio: ['pipe', 'inherit', 'inherit']
|
|
6
|
+
});
|
|
7
|
+
p.on('error', (err) => {
|
|
8
|
+
reject(err);
|
|
9
|
+
});
|
|
10
|
+
p.on('exit', () => {
|
|
11
|
+
resolve();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=tool.js.map
|
package/dist/tool.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,IAAc,EAAE,GAAW,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC5G,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE;QACxB,GAAG;QACH,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC;KACxC,CAAC,CAAC;IAEH,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAClB,MAAM,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACd,OAAO,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { access } from 'fs/promises';
|
|
2
|
+
export const exists = async (...args) => {
|
|
3
|
+
try {
|
|
4
|
+
await access(...args);
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
catch (err) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const textEncoder = new TextEncoder();
|
|
12
|
+
const textDecoder = new TextDecoder();
|
|
13
|
+
export const encodeText = (input) => textEncoder.encode(input.endsWith('\n') ? input : `${input}\n`);
|
|
14
|
+
export const encodeJSON = (input, pretty = false) => encodeText(JSON.stringify(input, undefined, pretty ? 4 : undefined));
|
|
15
|
+
export const decodeText = (input) => textDecoder.decode(input);
|
|
16
|
+
export const decodeJSON = (input) => JSON.parse(decodeText(input));
|
|
17
|
+
export const FILE_EXTENSIONS_VERILOG = ['v', 'vh', 'sv', 'svh'];
|
|
18
|
+
export const FILE_EXTENSIONS_VHDL = ['vhd'];
|
|
19
|
+
export const FILE_EXTENSIONS_HDL = [...FILE_EXTENSIONS_VERILOG, ...FILE_EXTENSIONS_VHDL];
|
|
20
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAInC,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,GAAG,IAA+B,EAAE,EAAE;IAC/D,IAAI;QACA,MAAM,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;KACf;IAAC,OAAO,GAAG,EAAE;QACV,OAAO,KAAK,CAAC;KAChB;AACL,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;AAC7G,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAc,EAAE,SAAkB,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAE5I,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAA2C,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACrG,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAA2C,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;AAEzG,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,uBAAuB,EAAE,GAAG,oBAAoB,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "edacation",
|
|
3
|
+
"description": "Library and CLI for interacting with Yosys and nextpnr.",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"contributors": [
|
|
7
|
+
"Danielle Huisman <danielle@huisman.me> (https://github.com/DanielleHuisman)"
|
|
8
|
+
],
|
|
9
|
+
"repository": "github:EDAcation/edacation",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"edacation",
|
|
12
|
+
"cli",
|
|
13
|
+
"yosys",
|
|
14
|
+
"nextpnr"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"systemd",
|
|
22
|
+
"LICENSE.md",
|
|
23
|
+
"README.md",
|
|
24
|
+
"package.json"
|
|
25
|
+
],
|
|
26
|
+
"bin": "./dist/cli/index.js",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"lint": "eslint",
|
|
29
|
+
"clean": "rm -rf dist",
|
|
30
|
+
"build": "yarn run clean && yarn run lint && tsc",
|
|
31
|
+
"prepublish": "yarn run build",
|
|
32
|
+
"dev": "node --loader ts-node/esm --experimental-specifier-resolution=node src/cli/index.ts"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@types/node": "^18.14.6",
|
|
36
|
+
"@types/yargs": "^17.0.22",
|
|
37
|
+
"yargs": "^17.7.1",
|
|
38
|
+
"zod": "^3.21.4"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
|
42
|
+
"@typescript-eslint/parser": "^5.54.0",
|
|
43
|
+
"eslint": "^8.35.0",
|
|
44
|
+
"eslint-config-google": "^0.14.0",
|
|
45
|
+
"eslint-plugin-import": "^2.27.5",
|
|
46
|
+
"ts-node": "^10.9.1",
|
|
47
|
+
"typescript": "^4.9.5"
|
|
48
|
+
}
|
|
49
|
+
}
|