ciel 0.21.0.dev0__py3-none-any.whl

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.
ciel/__init__.py ADDED
@@ -0,0 +1,29 @@
1
+ # Copyright 2022-2023 Efabless Corporation
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from .manage import (
15
+ VersionNotFound,
16
+ enable,
17
+ get,
18
+ fetch,
19
+ )
20
+ from .common import (
21
+ get_cielo_home,
22
+ Version,
23
+ )
24
+ from .families import Family
25
+ from .github import (
26
+ GitHubSession,
27
+ )
28
+ from .build import build
29
+ from .__version__ import __version__
ciel/__main__.py ADDED
@@ -0,0 +1,429 @@
1
+ # Copyright 2022-2023 Efabless Corporation
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import sys
15
+ import json
16
+ import httpx
17
+
18
+ import click
19
+ from rich.console import Console
20
+
21
+ from .__version__ import __version__
22
+ from .common import (
23
+ Version,
24
+ get_cielo_home,
25
+ resolve_version,
26
+ )
27
+ from .click_common import (
28
+ opt,
29
+ opt_build,
30
+ opt_push,
31
+ opt_pdk_root,
32
+ opt_token,
33
+ )
34
+ from .manage import (
35
+ print_installed_list,
36
+ print_remote_list,
37
+ enable,
38
+ fetch,
39
+ )
40
+ from .build import (
41
+ build_cmd,
42
+ push_cmd,
43
+ )
44
+
45
+
46
+ @click.command("output")
47
+ @opt_pdk_root
48
+ def output_cmd(pdk_root, pdk):
49
+ """Outputs the currently enabled PDK version.
50
+
51
+ If not outputting to a tty, the output is either the version string
52
+ unembellished, or, if no current version is enabled, an empty output with an
53
+ exit code of 1.
54
+ """
55
+
56
+ version = Version.get_current(pdk_root, pdk)
57
+ if sys.stdout.isatty():
58
+ if version is None:
59
+ print(f"No version of the PDK {pdk} is currently enabled at {pdk_root}.")
60
+ print(
61
+ "Invoke cielo --help for assistance installing and enabling versions."
62
+ )
63
+ exit(1)
64
+ else:
65
+ print(f"Installed: {pdk} v{version.name}")
66
+ print(
67
+ "Invoke cielo --help for assistance installing and enabling versions."
68
+ )
69
+ else:
70
+ if version is None:
71
+ exit(1)
72
+ else:
73
+ print(version.name, end="")
74
+
75
+
76
+ @click.command("prune")
77
+ @opt_pdk_root
78
+ @click.option(
79
+ "--yes",
80
+ is_flag=True,
81
+ callback=lambda c, _, v: not v and c.abort(),
82
+ expose_value=False,
83
+ prompt="Are you sure? This will delete all non-enabled versions of the PDK from your computer.",
84
+ )
85
+ def prune_cmd(pdk_root, pdk):
86
+ """Removes all PDKs other than, if it exists, the one currently in use."""
87
+ pdk_versions = Version.get_all_installed(pdk_root, pdk)
88
+ for version in pdk_versions:
89
+ if version.is_current(pdk_root):
90
+ continue
91
+ try:
92
+ version.uninstall(pdk_root)
93
+ print(f"Deleted {version}.")
94
+ except Exception as e:
95
+ print(f"Failed to delete {version}: {e}", file=sys.stderr)
96
+
97
+
98
+ @click.command("rm")
99
+ @opt_pdk_root
100
+ @click.option(
101
+ "--yes",
102
+ is_flag=True,
103
+ callback=lambda c, _, v: not v and c.abort(),
104
+ expose_value=False,
105
+ prompt="Are you sure? This will delete this version of the PDK from your computer.",
106
+ )
107
+ @click.argument("version", required=False)
108
+ def rm_cmd(pdk_root, pdk, version):
109
+ """Removes the PDK version specified."""
110
+ version_object = Version(version, pdk)
111
+ try:
112
+ version_object.uninstall(pdk_root)
113
+ print(f"Deleted {version}.")
114
+ except Exception as e:
115
+ print(f"Failed to delete: {e}", file=sys.stderr)
116
+ exit(1)
117
+
118
+
119
+ @click.command("ls")
120
+ @opt_token
121
+ @opt_pdk_root
122
+ def list_cmd(pdk_root, pdk):
123
+ """Lists PDK versions that are locally installed. JSON if not outputting to a tty."""
124
+
125
+ pdk_versions = Version.get_all_installed(pdk_root, pdk)
126
+
127
+ if sys.stdout.isatty():
128
+ console = Console()
129
+ print_installed_list(
130
+ pdk_root,
131
+ pdk,
132
+ console=console,
133
+ installed_list=pdk_versions,
134
+ )
135
+ else:
136
+ print(json.dumps([version.name for version in pdk_versions]), end="")
137
+
138
+
139
+ @click.command("ls-remote")
140
+ @opt_token
141
+ @opt_pdk_root
142
+ def list_remote_cmd(pdk_root, pdk):
143
+ """Lists PDK versions that are remotely available. JSON if not outputting to a tty."""
144
+
145
+ try:
146
+ all_versions = Version._from_github()
147
+ pdk_versions = all_versions.get(pdk) or []
148
+
149
+ if sys.stdout.isatty():
150
+ console = Console()
151
+ print_remote_list(pdk_root, pdk, console, pdk_versions)
152
+ else:
153
+ for version in pdk_versions:
154
+ print(version.name)
155
+ except httpx.HTTPStatusError as e:
156
+ if sys.stdout.isatty():
157
+ console = Console()
158
+ console.print(f"[red]Encountered an error when polling version list: {e}")
159
+ else:
160
+ print(f"Failed to get version list: {e}", file=sys.stderr)
161
+ sys.exit(-1)
162
+ except httpx.NetworkError as e:
163
+ if sys.stdout.isatty():
164
+ console = Console()
165
+ console.print(
166
+ "[red]You don't appear to be connected to the Internet. ls-remote cannot be used."
167
+ )
168
+ else:
169
+ print(f"Failed to connect to remote server: {e}", file=sys.stderr)
170
+ sys.exit(-1)
171
+
172
+
173
+ @click.command("path")
174
+ @opt_pdk_root
175
+ @click.argument("version", required=False)
176
+ def path_cmd(pdk_root, pdk, version):
177
+ """
178
+ Prints the path of the cielo PDK root.
179
+
180
+ If a version is provided over the commandline, it prints the path to this
181
+ version instead.
182
+ """
183
+ if version is not None:
184
+ version = Version(version, pdk)
185
+ print(version.get_dir(pdk_root), end="")
186
+ else:
187
+ print(get_cielo_home(pdk_root))
188
+
189
+
190
+ @click.command("enable")
191
+ @opt_token
192
+ @opt_pdk_root
193
+ @click.option(
194
+ "-f",
195
+ "--metadata-file",
196
+ "tool_metadata_file_path",
197
+ default=None,
198
+ help="Explicitly define a tool metadata file instead of searching for a metadata file",
199
+ )
200
+ @click.option(
201
+ "-l",
202
+ "--include-libraries",
203
+ multiple=True,
204
+ default=None,
205
+ help="Libraries to include. You can use -l multiple times to include multiple libraries. Pass 'all' to include all of them. A default of 'None' uses a default set for the particular PDK.",
206
+ )
207
+ @click.argument("version", required=False)
208
+ def enable_cmd(
209
+ pdk_root,
210
+ pdk,
211
+ tool_metadata_file_path,
212
+ version,
213
+ include_libraries,
214
+ ):
215
+ """
216
+ Activates a given installed PDK version.
217
+
218
+ Parameters: <version> (Optional)
219
+
220
+ If a version is not given, and you run this in the top level directory of
221
+ tools with a tool_metadata.yml file, for example OpenLane or DFFRAM,
222
+ the appropriate version will be enabled automatically.
223
+ """
224
+ if include_libraries == ():
225
+ include_libraries = None
226
+
227
+ console = Console()
228
+ try:
229
+ version = resolve_version(version, tool_metadata_file_path)
230
+ except Exception as e:
231
+ console.print(f"Could not determine open_pdks version: {e}")
232
+ exit(-1)
233
+
234
+ try:
235
+ enable(
236
+ pdk_root,
237
+ pdk,
238
+ version,
239
+ include_libraries=include_libraries,
240
+ output=console,
241
+ )
242
+ except Exception as e:
243
+ console.print(f"[red]{e}")
244
+ exit(-1)
245
+
246
+
247
+ @click.command("fetch")
248
+ @opt_token
249
+ @opt_pdk_root
250
+ @click.option(
251
+ "-f",
252
+ "--metadata-file",
253
+ "tool_metadata_file_path",
254
+ default=None,
255
+ help="Explicitly define a tool metadata file instead of searching for a metadata file",
256
+ )
257
+ @click.option(
258
+ "-l",
259
+ "--include-libraries",
260
+ multiple=True,
261
+ default=None,
262
+ help="Libraries to include. You can use -l multiple times to include multiple libraries. Pass 'all' to include all of them. A default of 'None' uses a default set for the particular PDK.",
263
+ )
264
+ @click.argument("version", required=False)
265
+ def fetch_cmd(
266
+ pdk_root,
267
+ pdk,
268
+ tool_metadata_file_path,
269
+ version,
270
+ include_libraries,
271
+ ):
272
+ """
273
+ Fetches a PDK to Cielo's store without setting it as the "enabled" version
274
+ in ``PDK_ROOT``.
275
+
276
+ Parameters: <version> (Optional)
277
+
278
+ If a version is not given, and you run this in the top level directory of
279
+ tools with a tool_metadata.yml file, for example OpenLane or DFFRAM,
280
+ the appropriate version will be enabled automatically.
281
+ """
282
+ if include_libraries == ():
283
+ include_libraries = None
284
+
285
+ console = Console()
286
+ try:
287
+ version = resolve_version(version, tool_metadata_file_path)
288
+ except Exception as e:
289
+ console.print(f"Could not determine open_pdks version: {e}")
290
+ exit(-1)
291
+
292
+ try:
293
+ version = fetch(
294
+ pdk_root=pdk_root,
295
+ pdk=pdk,
296
+ version=version,
297
+ include_libraries=include_libraries,
298
+ output=console,
299
+ )
300
+ print(version.get_dir(pdk_root), end="")
301
+
302
+ except Exception as e:
303
+ console.print(f"[red]{e}")
304
+ exit(-1)
305
+
306
+
307
+ @click.command("enable_or_build", hidden=True)
308
+ @opt_token
309
+ @opt_pdk_root
310
+ @opt_push
311
+ @opt_build
312
+ @opt("--also-push/--dont-push", default=False, help="Also push.")
313
+ @click.option(
314
+ "-f",
315
+ "--metadata-file",
316
+ "tool_metadata_file_path",
317
+ default=None,
318
+ help="Explicitly define a tool metadata file instead of searching for a metadata file",
319
+ )
320
+ @click.argument("version")
321
+ def enable_or_build_cmd(
322
+ include_libraries,
323
+ jobs,
324
+ pdk_root,
325
+ pdk,
326
+ owner,
327
+ repository,
328
+ pre,
329
+ clear_build_artifacts,
330
+ tool_metadata_file_path,
331
+ also_push,
332
+ version,
333
+ use_repo_at,
334
+ push_libraries,
335
+ ):
336
+ """
337
+ Attempts to activate a given PDK version. If the version is not found locally or remotely,
338
+ it will instead attempt to build said version.
339
+
340
+ Parameters: <version>
341
+ """
342
+ if include_libraries == ():
343
+ include_libraries = None
344
+ if push_libraries == ():
345
+ push_libraries = include_libraries
346
+
347
+ console = Console()
348
+ try:
349
+ version = resolve_version(version, tool_metadata_file_path)
350
+ except Exception as e:
351
+ console.print(f"Could not determine open_pdks version: {e}")
352
+ exit(-1)
353
+ try:
354
+ enable(
355
+ pdk_root=pdk_root,
356
+ pdk=pdk,
357
+ version=version,
358
+ build_if_not_found=True,
359
+ also_push=also_push,
360
+ build_kwargs={
361
+ "include_libraries": include_libraries,
362
+ "jobs": jobs,
363
+ "clear_build_artifacts": clear_build_artifacts,
364
+ "use_repo_at": use_repo_at,
365
+ },
366
+ push_kwargs={
367
+ "owner": owner,
368
+ "repository": repository,
369
+ "pre": pre,
370
+ "push_libraries": push_libraries,
371
+ },
372
+ include_libraries=include_libraries,
373
+ output=console,
374
+ )
375
+ except Exception as e:
376
+ console.print(f"[red]{e}")
377
+ exit(-1)
378
+
379
+
380
+ @click.group()
381
+ @click.version_option(
382
+ __version__,
383
+ message="""Cielo v%(version)s ©2022-2025 Efabless Corporation and Contributors
384
+
385
+ Licensed under the Apache License, Version 2.0 (the "License");
386
+ you may not use this program except in compliance with the License.
387
+ You may obtain a copy of the License at
388
+
389
+ http://www.apache.org/licenses/LICENSE-2.0
390
+
391
+ Unless required by applicable law or agreed to in writing, software
392
+ distributed under the License is distributed on an "AS IS" BASIS,
393
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
394
+ See the License for the specific language governing permissions and
395
+ limitations under the License.""",
396
+ )
397
+ def cli():
398
+ pass
399
+
400
+
401
+ cli.add_command(output_cmd)
402
+ cli.add_command(prune_cmd)
403
+ cli.add_command(rm_cmd)
404
+ cli.add_command(build_cmd)
405
+ cli.add_command(push_cmd)
406
+ cli.add_command(path_cmd)
407
+ cli.add_command(list_cmd)
408
+ cli.add_command(list_remote_cmd)
409
+ cli.add_command(enable_cmd)
410
+ cli.add_command(fetch_cmd)
411
+ cli.add_command(enable_or_build_cmd)
412
+
413
+ try:
414
+ import ssl # noqa: F401
415
+ except ModuleNotFoundError as e:
416
+ print(
417
+ f"Your version of Python 3 was not built with a required module: '{e.name}'",
418
+ file=sys.stderr,
419
+ )
420
+ print(
421
+ "Please install Python 3 with all (optional) dependencies using your operating system's package manager.",
422
+ file=sys.stderr,
423
+ )
424
+ print("This is a fatal error. Cielo will now quit.", file=sys.stderr)
425
+ exit(-1)
426
+
427
+
428
+ if __name__ == "__main__":
429
+ cli()
ciel/__version__.py ADDED
@@ -0,0 +1,44 @@
1
+ # Copyright 2023 Efabless Corporation
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import os
15
+ import importlib.metadata
16
+ import sys
17
+
18
+
19
+ def __get_version():
20
+ try:
21
+ return importlib.metadata.version(__package__ or __name__)
22
+ except importlib.metadata.PackageNotFoundError:
23
+ import re
24
+
25
+ rx = re.compile(r"version\s*=\s*\"([^\"]+)\"")
26
+ repo_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
27
+ pyproject_path = os.path.join(repo_directory, "pyproject.toml")
28
+ try:
29
+ match = rx.search(open(pyproject_path, encoding="utf8").read())
30
+ assert match is not None, "pyproject.toml found, but without a version"
31
+ return match[1]
32
+ except FileNotFoundError:
33
+ print(
34
+ f"Warning: Failed to extract version for {__package__}.",
35
+ file=sys.stderr,
36
+ )
37
+ return "UNKNOWN"
38
+
39
+
40
+ __version__ = __get_version()
41
+
42
+
43
+ if __name__ == "__main__":
44
+ print(__version__, end="")