siliconcompiler 0.26.5__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.
- siliconcompiler/__init__.py +24 -0
- siliconcompiler/__main__.py +12 -0
- siliconcompiler/_common.py +49 -0
- siliconcompiler/_metadata.py +36 -0
- siliconcompiler/apps/__init__.py +0 -0
- siliconcompiler/apps/_common.py +76 -0
- siliconcompiler/apps/sc.py +92 -0
- siliconcompiler/apps/sc_dashboard.py +94 -0
- siliconcompiler/apps/sc_issue.py +178 -0
- siliconcompiler/apps/sc_remote.py +199 -0
- siliconcompiler/apps/sc_server.py +39 -0
- siliconcompiler/apps/sc_show.py +142 -0
- siliconcompiler/apps/smake.py +232 -0
- siliconcompiler/checklists/__init__.py +0 -0
- siliconcompiler/checklists/oh_tapeout.py +41 -0
- siliconcompiler/core.py +3221 -0
- siliconcompiler/data/RobotoMono/LICENSE.txt +202 -0
- siliconcompiler/data/RobotoMono/RobotoMono-Regular.ttf +0 -0
- siliconcompiler/data/heartbeat.v +18 -0
- siliconcompiler/data/logo.png +0 -0
- siliconcompiler/flowgraph.py +570 -0
- siliconcompiler/flows/__init__.py +0 -0
- siliconcompiler/flows/_common.py +67 -0
- siliconcompiler/flows/asicflow.py +180 -0
- siliconcompiler/flows/asictopflow.py +38 -0
- siliconcompiler/flows/dvflow.py +86 -0
- siliconcompiler/flows/fpgaflow.py +202 -0
- siliconcompiler/flows/generate_openroad_rcx.py +66 -0
- siliconcompiler/flows/lintflow.py +35 -0
- siliconcompiler/flows/screenshotflow.py +51 -0
- siliconcompiler/flows/showflow.py +59 -0
- siliconcompiler/flows/signoffflow.py +53 -0
- siliconcompiler/flows/synflow.py +128 -0
- siliconcompiler/fpgas/__init__.py +0 -0
- siliconcompiler/fpgas/lattice_ice40.py +42 -0
- siliconcompiler/fpgas/vpr_example.py +109 -0
- siliconcompiler/issue.py +300 -0
- siliconcompiler/libs/__init__.py +0 -0
- siliconcompiler/libs/asap7sc7p5t.py +8 -0
- siliconcompiler/libs/gf180mcu.py +8 -0
- siliconcompiler/libs/nangate45.py +8 -0
- siliconcompiler/libs/sky130hd.py +8 -0
- siliconcompiler/libs/sky130io.py +8 -0
- siliconcompiler/package.py +412 -0
- siliconcompiler/pdks/__init__.py +0 -0
- siliconcompiler/pdks/asap7.py +8 -0
- siliconcompiler/pdks/freepdk45.py +8 -0
- siliconcompiler/pdks/gf180.py +8 -0
- siliconcompiler/pdks/skywater130.py +8 -0
- siliconcompiler/remote/__init__.py +36 -0
- siliconcompiler/remote/client.py +891 -0
- siliconcompiler/remote/schema.py +106 -0
- siliconcompiler/remote/server.py +507 -0
- siliconcompiler/remote/server_schema/requests/cancel_job.json +51 -0
- siliconcompiler/remote/server_schema/requests/check_progress.json +61 -0
- siliconcompiler/remote/server_schema/requests/check_server.json +38 -0
- siliconcompiler/remote/server_schema/requests/delete_job.json +51 -0
- siliconcompiler/remote/server_schema/requests/get_results.json +48 -0
- siliconcompiler/remote/server_schema/requests/remote_run.json +40 -0
- siliconcompiler/remote/server_schema/responses/cancel_job.json +18 -0
- siliconcompiler/remote/server_schema/responses/check_progress.json +30 -0
- siliconcompiler/remote/server_schema/responses/check_server.json +32 -0
- siliconcompiler/remote/server_schema/responses/delete_job.json +18 -0
- siliconcompiler/remote/server_schema/responses/get_results.json +21 -0
- siliconcompiler/remote/server_schema/responses/remote_run.json +25 -0
- siliconcompiler/report/__init__.py +13 -0
- siliconcompiler/report/html_report.py +74 -0
- siliconcompiler/report/report.py +355 -0
- siliconcompiler/report/streamlit_report.py +137 -0
- siliconcompiler/report/streamlit_viewer.py +944 -0
- siliconcompiler/report/summary_image.py +117 -0
- siliconcompiler/report/summary_table.py +105 -0
- siliconcompiler/report/utils.py +163 -0
- siliconcompiler/scheduler/__init__.py +2092 -0
- siliconcompiler/scheduler/docker_runner.py +253 -0
- siliconcompiler/scheduler/run_node.py +138 -0
- siliconcompiler/scheduler/send_messages.py +178 -0
- siliconcompiler/scheduler/slurm.py +208 -0
- siliconcompiler/scheduler/validation/email_credentials.json +54 -0
- siliconcompiler/schema/__init__.py +7 -0
- siliconcompiler/schema/schema_cfg.py +4014 -0
- siliconcompiler/schema/schema_obj.py +1841 -0
- siliconcompiler/schema/utils.py +93 -0
- siliconcompiler/sphinx_ext/__init__.py +0 -0
- siliconcompiler/sphinx_ext/dynamicgen.py +1006 -0
- siliconcompiler/sphinx_ext/schemagen.py +221 -0
- siliconcompiler/sphinx_ext/utils.py +166 -0
- siliconcompiler/targets/__init__.py +0 -0
- siliconcompiler/targets/asap7_demo.py +68 -0
- siliconcompiler/targets/asic_demo.py +38 -0
- siliconcompiler/targets/fpgaflow_demo.py +47 -0
- siliconcompiler/targets/freepdk45_demo.py +59 -0
- siliconcompiler/targets/gf180_demo.py +77 -0
- siliconcompiler/targets/skywater130_demo.py +70 -0
- siliconcompiler/templates/email/general.j2 +66 -0
- siliconcompiler/templates/email/summary.j2 +43 -0
- siliconcompiler/templates/issue/README.txt +26 -0
- siliconcompiler/templates/issue/run.sh +6 -0
- siliconcompiler/templates/report/bootstrap.min.css +7 -0
- siliconcompiler/templates/report/bootstrap.min.js +7 -0
- siliconcompiler/templates/report/bootstrap_LICENSE.md +24 -0
- siliconcompiler/templates/report/sc_report.j2 +427 -0
- siliconcompiler/templates/slurm/run.sh +9 -0
- siliconcompiler/templates/tcl/manifest.tcl.j2 +137 -0
- siliconcompiler/tools/__init__.py +0 -0
- siliconcompiler/tools/_common/__init__.py +432 -0
- siliconcompiler/tools/_common/asic.py +115 -0
- siliconcompiler/tools/_common/sdc/sc_constraints.sdc +76 -0
- siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +63 -0
- siliconcompiler/tools/bambu/bambu.py +32 -0
- siliconcompiler/tools/bambu/convert.py +77 -0
- siliconcompiler/tools/bluespec/bluespec.py +40 -0
- siliconcompiler/tools/bluespec/convert.py +103 -0
- siliconcompiler/tools/builtin/_common.py +155 -0
- siliconcompiler/tools/builtin/builtin.py +26 -0
- siliconcompiler/tools/builtin/concatenate.py +85 -0
- siliconcompiler/tools/builtin/join.py +27 -0
- siliconcompiler/tools/builtin/maximum.py +46 -0
- siliconcompiler/tools/builtin/minimum.py +57 -0
- siliconcompiler/tools/builtin/mux.py +70 -0
- siliconcompiler/tools/builtin/nop.py +38 -0
- siliconcompiler/tools/builtin/verify.py +83 -0
- siliconcompiler/tools/chisel/SCDriver.scala +10 -0
- siliconcompiler/tools/chisel/build.sbt +27 -0
- siliconcompiler/tools/chisel/chisel.py +37 -0
- siliconcompiler/tools/chisel/convert.py +140 -0
- siliconcompiler/tools/execute/exec_input.py +41 -0
- siliconcompiler/tools/execute/execute.py +17 -0
- siliconcompiler/tools/genfasm/bitstream.py +61 -0
- siliconcompiler/tools/genfasm/genfasm.py +40 -0
- siliconcompiler/tools/ghdl/convert.py +87 -0
- siliconcompiler/tools/ghdl/ghdl.py +41 -0
- siliconcompiler/tools/icarus/compile.py +87 -0
- siliconcompiler/tools/icarus/icarus.py +36 -0
- siliconcompiler/tools/icepack/bitstream.py +20 -0
- siliconcompiler/tools/icepack/icepack.py +43 -0
- siliconcompiler/tools/klayout/export.py +117 -0
- siliconcompiler/tools/klayout/klayout.py +119 -0
- siliconcompiler/tools/klayout/klayout_export.py +205 -0
- siliconcompiler/tools/klayout/klayout_operations.py +363 -0
- siliconcompiler/tools/klayout/klayout_show.py +242 -0
- siliconcompiler/tools/klayout/klayout_utils.py +176 -0
- siliconcompiler/tools/klayout/operations.py +194 -0
- siliconcompiler/tools/klayout/screenshot.py +98 -0
- siliconcompiler/tools/klayout/show.py +101 -0
- siliconcompiler/tools/magic/drc.py +49 -0
- siliconcompiler/tools/magic/extspice.py +19 -0
- siliconcompiler/tools/magic/magic.py +85 -0
- siliconcompiler/tools/magic/sc_drc.tcl +96 -0
- siliconcompiler/tools/magic/sc_extspice.tcl +54 -0
- siliconcompiler/tools/magic/sc_magic.tcl +47 -0
- siliconcompiler/tools/montage/montage.py +30 -0
- siliconcompiler/tools/montage/tile.py +66 -0
- siliconcompiler/tools/netgen/count_lvs.py +132 -0
- siliconcompiler/tools/netgen/lvs.py +90 -0
- siliconcompiler/tools/netgen/netgen.py +36 -0
- siliconcompiler/tools/netgen/sc_lvs.tcl +46 -0
- siliconcompiler/tools/nextpnr/apr.py +24 -0
- siliconcompiler/tools/nextpnr/nextpnr.py +59 -0
- siliconcompiler/tools/openfpgaloader/openfpgaloader.py +39 -0
- siliconcompiler/tools/openroad/__init__.py +0 -0
- siliconcompiler/tools/openroad/cts.py +45 -0
- siliconcompiler/tools/openroad/dfm.py +66 -0
- siliconcompiler/tools/openroad/export.py +131 -0
- siliconcompiler/tools/openroad/floorplan.py +70 -0
- siliconcompiler/tools/openroad/openroad.py +977 -0
- siliconcompiler/tools/openroad/physyn.py +27 -0
- siliconcompiler/tools/openroad/place.py +41 -0
- siliconcompiler/tools/openroad/rcx_bench.py +95 -0
- siliconcompiler/tools/openroad/rcx_extract.py +34 -0
- siliconcompiler/tools/openroad/route.py +45 -0
- siliconcompiler/tools/openroad/screenshot.py +60 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +499 -0
- siliconcompiler/tools/openroad/scripts/sc_cts.tcl +64 -0
- siliconcompiler/tools/openroad/scripts/sc_dfm.tcl +20 -0
- siliconcompiler/tools/openroad/scripts/sc_export.tcl +98 -0
- siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +413 -0
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +158 -0
- siliconcompiler/tools/openroad/scripts/sc_physyn.tcl +7 -0
- siliconcompiler/tools/openroad/scripts/sc_place.tcl +84 -0
- siliconcompiler/tools/openroad/scripts/sc_procs.tcl +423 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +63 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx_bench.tcl +20 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx_extract.tcl +12 -0
- siliconcompiler/tools/openroad/scripts/sc_route.tcl +133 -0
- siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +21 -0
- siliconcompiler/tools/openroad/scripts/sc_write.tcl +5 -0
- siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +361 -0
- siliconcompiler/tools/openroad/show.py +94 -0
- siliconcompiler/tools/openroad/templates/pex.tcl +8 -0
- siliconcompiler/tools/opensta/__init__.py +101 -0
- siliconcompiler/tools/opensta/report_libraries.py +28 -0
- siliconcompiler/tools/opensta/scripts/sc_procs.tcl +47 -0
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +74 -0
- siliconcompiler/tools/opensta/scripts/sc_timing.tcl +268 -0
- siliconcompiler/tools/opensta/timing.py +214 -0
- siliconcompiler/tools/slang/__init__.py +49 -0
- siliconcompiler/tools/slang/lint.py +101 -0
- siliconcompiler/tools/surelog/__init__.py +123 -0
- siliconcompiler/tools/surelog/parse.py +183 -0
- siliconcompiler/tools/surelog/templates/output.v +7 -0
- siliconcompiler/tools/sv2v/convert.py +46 -0
- siliconcompiler/tools/sv2v/sv2v.py +37 -0
- siliconcompiler/tools/template/template.py +125 -0
- siliconcompiler/tools/verilator/compile.py +139 -0
- siliconcompiler/tools/verilator/lint.py +19 -0
- siliconcompiler/tools/verilator/parse.py +27 -0
- siliconcompiler/tools/verilator/verilator.py +172 -0
- siliconcompiler/tools/vivado/__init__.py +7 -0
- siliconcompiler/tools/vivado/bitstream.py +21 -0
- siliconcompiler/tools/vivado/place.py +21 -0
- siliconcompiler/tools/vivado/route.py +21 -0
- siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +6 -0
- siliconcompiler/tools/vivado/scripts/sc_place.tcl +2 -0
- siliconcompiler/tools/vivado/scripts/sc_route.tcl +4 -0
- siliconcompiler/tools/vivado/scripts/sc_run.tcl +45 -0
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +25 -0
- siliconcompiler/tools/vivado/syn_fpga.py +20 -0
- siliconcompiler/tools/vivado/vivado.py +147 -0
- siliconcompiler/tools/vpr/_json_constraint.py +63 -0
- siliconcompiler/tools/vpr/_xml_constraint.py +109 -0
- siliconcompiler/tools/vpr/place.py +137 -0
- siliconcompiler/tools/vpr/route.py +124 -0
- siliconcompiler/tools/vpr/screenshot.py +54 -0
- siliconcompiler/tools/vpr/show.py +88 -0
- siliconcompiler/tools/vpr/vpr.py +357 -0
- siliconcompiler/tools/xyce/xyce.py +36 -0
- siliconcompiler/tools/yosys/lec.py +56 -0
- siliconcompiler/tools/yosys/prepareLib.py +59 -0
- siliconcompiler/tools/yosys/sc_lec.tcl +84 -0
- siliconcompiler/tools/yosys/sc_syn.tcl +79 -0
- siliconcompiler/tools/yosys/syn_asic.py +565 -0
- siliconcompiler/tools/yosys/syn_asic.tcl +377 -0
- siliconcompiler/tools/yosys/syn_asic_fpga_shared.tcl +31 -0
- siliconcompiler/tools/yosys/syn_fpga.py +146 -0
- siliconcompiler/tools/yosys/syn_fpga.tcl +233 -0
- siliconcompiler/tools/yosys/syn_strategies.tcl +81 -0
- siliconcompiler/tools/yosys/techmaps/lcu_kogge_stone.v +39 -0
- siliconcompiler/tools/yosys/templates/abc.const +2 -0
- siliconcompiler/tools/yosys/yosys.py +147 -0
- siliconcompiler/units.py +259 -0
- siliconcompiler/use.py +177 -0
- siliconcompiler/utils/__init__.py +423 -0
- siliconcompiler/utils/asic.py +158 -0
- siliconcompiler/utils/showtools.py +25 -0
- siliconcompiler-0.26.5.dist-info/LICENSE +190 -0
- siliconcompiler-0.26.5.dist-info/METADATA +195 -0
- siliconcompiler-0.26.5.dist-info/RECORD +251 -0
- siliconcompiler-0.26.5.dist-info/WHEEL +5 -0
- siliconcompiler-0.26.5.dist-info/entry_points.txt +12 -0
- siliconcompiler-0.26.5.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import requests
|
|
3
|
+
import tarfile
|
|
4
|
+
import zipfile
|
|
5
|
+
from git import Repo, GitCommandError
|
|
6
|
+
from urllib.parse import urlparse
|
|
7
|
+
import importlib
|
|
8
|
+
import shutil
|
|
9
|
+
import re
|
|
10
|
+
from siliconcompiler import SiliconCompilerError
|
|
11
|
+
from siliconcompiler.utils import default_cache_dir, _resolve_env_vars
|
|
12
|
+
import json
|
|
13
|
+
from importlib.metadata import distributions, distribution
|
|
14
|
+
import functools
|
|
15
|
+
import fasteners
|
|
16
|
+
import time
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from io import BytesIO
|
|
19
|
+
|
|
20
|
+
from github import Github
|
|
21
|
+
import github.Auth
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_cache_path(chip):
|
|
25
|
+
cache_path = chip.get('option', 'cachedir')
|
|
26
|
+
if cache_path:
|
|
27
|
+
cache_path = chip.find_files('option', 'cachedir', missing_ok=True)
|
|
28
|
+
if not cache_path:
|
|
29
|
+
cache_path = os.path.join(chip.cwd, chip.get('option', 'cachedir'))
|
|
30
|
+
if not cache_path:
|
|
31
|
+
cache_path = default_cache_dir()
|
|
32
|
+
|
|
33
|
+
return cache_path
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _path(chip, package, download_handler):
|
|
37
|
+
if package in chip._packages:
|
|
38
|
+
return chip._packages[package]
|
|
39
|
+
|
|
40
|
+
# Initially try retrieving data source from schema
|
|
41
|
+
data = {}
|
|
42
|
+
data['path'] = chip.get('package', 'source', package, 'path')
|
|
43
|
+
data['ref'] = chip.get('package', 'source', package, 'ref')
|
|
44
|
+
if not data['path']:
|
|
45
|
+
raise SiliconCompilerError(
|
|
46
|
+
f'Could not find package source for {package} in schema. '
|
|
47
|
+
'You can use register_source() to add it.', chip=chip)
|
|
48
|
+
|
|
49
|
+
data['path'] = _resolve_env_vars(chip, data['path'])
|
|
50
|
+
|
|
51
|
+
url = urlparse(data['path'])
|
|
52
|
+
|
|
53
|
+
# check network drive for package data source
|
|
54
|
+
if data['path'].startswith('file://') or os.path.exists(data['path']):
|
|
55
|
+
path = os.path.abspath(data['path'].replace('file://', ''))
|
|
56
|
+
chip.logger.info(f'Found {package} data at {path}')
|
|
57
|
+
chip._packages[package] = path
|
|
58
|
+
return path
|
|
59
|
+
elif data['path'].startswith('python://'):
|
|
60
|
+
path = path_from_python(chip, url.netloc)
|
|
61
|
+
chip.logger.info(f'Found {package} data at {path}')
|
|
62
|
+
chip._packages[package] = path
|
|
63
|
+
return path
|
|
64
|
+
|
|
65
|
+
# location of the python package
|
|
66
|
+
cache_path = get_cache_path(chip)
|
|
67
|
+
if not os.path.exists(cache_path):
|
|
68
|
+
os.makedirs(cache_path, exist_ok=True)
|
|
69
|
+
project_id = f'{package}-{data.get("ref")}'
|
|
70
|
+
if url.scheme not in ['git', 'git+https', 'https', 'git+ssh', 'ssh'] or not project_id:
|
|
71
|
+
raise SiliconCompilerError(
|
|
72
|
+
f'Could not find data path in package {package}: {data["path"]}',
|
|
73
|
+
chip=chip)
|
|
74
|
+
|
|
75
|
+
data_path = os.path.join(cache_path, project_id)
|
|
76
|
+
|
|
77
|
+
if download_handler:
|
|
78
|
+
download_handler(chip,
|
|
79
|
+
package,
|
|
80
|
+
data,
|
|
81
|
+
url,
|
|
82
|
+
data_path,
|
|
83
|
+
os.path.join(cache_path, f'{project_id}.lock'))
|
|
84
|
+
|
|
85
|
+
if os.path.exists(data_path):
|
|
86
|
+
if package not in chip._packages:
|
|
87
|
+
chip.logger.info(f'Saved {package} data to {data_path}')
|
|
88
|
+
chip._packages[package] = data_path
|
|
89
|
+
return data_path
|
|
90
|
+
|
|
91
|
+
raise SiliconCompilerError(f'Extracting {package} data to {data_path} failed')
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def path(chip, package):
|
|
95
|
+
"""
|
|
96
|
+
Compute data source data path
|
|
97
|
+
Additionally cache data source data if possible
|
|
98
|
+
Parameters:
|
|
99
|
+
package (str): Name of the data source
|
|
100
|
+
Returns:
|
|
101
|
+
path: Location of data source on the local system
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
return _path(chip, package, __download_data)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def __download_data(chip, package, data, url, data_path, data_path_lock):
|
|
108
|
+
data_lock = fasteners.InterProcessLock(data_path_lock)
|
|
109
|
+
|
|
110
|
+
_aquire_data_lock(data_path, data_lock)
|
|
111
|
+
|
|
112
|
+
# check cached package data source
|
|
113
|
+
if os.path.exists(data_path):
|
|
114
|
+
chip.logger.info(f'Found cached {package} data at {data_path}')
|
|
115
|
+
if url.scheme in ['git', 'git+https', 'ssh', 'git+ssh']:
|
|
116
|
+
try:
|
|
117
|
+
repo = Repo(data_path)
|
|
118
|
+
if repo.untracked_files or repo.index.diff("HEAD"):
|
|
119
|
+
chip.logger.warning('The repo of the cached data is dirty.')
|
|
120
|
+
_release_data_lock(data_lock)
|
|
121
|
+
chip._packages[package] = data_path
|
|
122
|
+
return
|
|
123
|
+
except GitCommandError:
|
|
124
|
+
chip.logger.warning('Deleting corrupted cache data.')
|
|
125
|
+
shutil.rmtree(path)
|
|
126
|
+
else:
|
|
127
|
+
_release_data_lock(data_lock)
|
|
128
|
+
chip._packages[package] = data_path
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
# download package data source
|
|
132
|
+
if url.scheme in ['git', 'git+https', 'ssh', 'git+ssh']:
|
|
133
|
+
clone_synchronized(chip, package, data, data_path)
|
|
134
|
+
elif url.scheme == 'https':
|
|
135
|
+
extract_from_url(chip, package, data, data_path)
|
|
136
|
+
|
|
137
|
+
_release_data_lock(data_lock)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def __get_filebased_lock(data_lock):
|
|
141
|
+
base, _ = os.path.splitext(os.fsdecode(data_lock.path))
|
|
142
|
+
return Path(f'{base}.sc_lock')
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _aquire_data_lock(data_path, data_lock):
|
|
146
|
+
# Wait a maximum of 10 minutes for other processes to finish
|
|
147
|
+
max_seconds = 10 * 60
|
|
148
|
+
try:
|
|
149
|
+
if data_lock.acquire(timeout=max_seconds):
|
|
150
|
+
return
|
|
151
|
+
except RuntimeError:
|
|
152
|
+
# Fall back to file based locking method
|
|
153
|
+
lock_file = __get_filebased_lock(data_lock)
|
|
154
|
+
while (lock_file.exists()):
|
|
155
|
+
if max_seconds == 0:
|
|
156
|
+
raise SiliconCompilerError(f'Failed to access {data_path}.'
|
|
157
|
+
f'Lock {lock_file} still exists.')
|
|
158
|
+
time.sleep(1)
|
|
159
|
+
max_seconds -= 1
|
|
160
|
+
|
|
161
|
+
lock_file.touch()
|
|
162
|
+
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
raise SiliconCompilerError(f'Failed to access {data_path}. '
|
|
166
|
+
f'{data_lock.path} is still locked, if this is a mistake, '
|
|
167
|
+
'please delete it.')
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _release_data_lock(data_lock):
|
|
171
|
+
# Check if file based locking method was used
|
|
172
|
+
lock_file = __get_filebased_lock(data_lock)
|
|
173
|
+
if lock_file.exists():
|
|
174
|
+
lock_file.unlink(missing_ok=True)
|
|
175
|
+
return
|
|
176
|
+
|
|
177
|
+
data_lock.release()
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def clone_synchronized(chip, package, data, data_path):
|
|
181
|
+
url = urlparse(data['path'])
|
|
182
|
+
try:
|
|
183
|
+
clone_from_git(chip, package, data, data_path)
|
|
184
|
+
except GitCommandError as e:
|
|
185
|
+
if 'Permission denied' in repr(e):
|
|
186
|
+
if url.scheme in ['ssh', 'git+ssh']:
|
|
187
|
+
chip.logger.error('Failed to authenticate. Please setup your git ssh.')
|
|
188
|
+
elif url.scheme in ['git', 'git+https']:
|
|
189
|
+
chip.logger.error('Failed to authenticate. Please use a token or ssh.')
|
|
190
|
+
else:
|
|
191
|
+
raise e
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def clone_from_git(chip, package, data, repo_path):
|
|
195
|
+
url = urlparse(data['path'])
|
|
196
|
+
if url.scheme in ['git', 'git+https'] and url.username:
|
|
197
|
+
chip.logger.warning('Your token is in the data source path and will be stored in the '
|
|
198
|
+
'schema. If you do not want this set the env variable GIT_TOKEN '
|
|
199
|
+
'or use ssh for authentication.')
|
|
200
|
+
if url.scheme in ['git+ssh', 'ssh']:
|
|
201
|
+
chip.logger.info(f'Cloning {package} data from {url.netloc}:{url.path[1:]}')
|
|
202
|
+
# Git requires the format git@github.com:org/repo instead of git@github.com/org/repo
|
|
203
|
+
repo = Repo.clone_from(f'{url.netloc}:{url.path[1:]}',
|
|
204
|
+
repo_path,
|
|
205
|
+
recurse_submodules=True)
|
|
206
|
+
else:
|
|
207
|
+
if os.environ.get('GIT_TOKEN') and not url.username:
|
|
208
|
+
url = url._replace(netloc=f'{os.environ.get("GIT_TOKEN")}@{url.hostname}')
|
|
209
|
+
url = url._replace(scheme='https')
|
|
210
|
+
chip.logger.info(f'Cloning {package} data from {url.geturl()}')
|
|
211
|
+
repo = Repo.clone_from(url.geturl(), repo_path, recurse_submodules=True)
|
|
212
|
+
chip.logger.info(f'Checking out {data["ref"]}')
|
|
213
|
+
repo.git.checkout(data["ref"])
|
|
214
|
+
for submodule in repo.submodules:
|
|
215
|
+
submodule.update(init=True)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def extract_from_url(chip, package, data, data_path):
|
|
219
|
+
url = urlparse(data['path'])
|
|
220
|
+
data_url = data.get('path')
|
|
221
|
+
headers = {}
|
|
222
|
+
if os.environ.get('GIT_TOKEN') or url.username:
|
|
223
|
+
headers['Authorization'] = f'token {os.environ.get("GIT_TOKEN") or url.username}'
|
|
224
|
+
if "github" in data_url:
|
|
225
|
+
headers['Accept'] = 'application/octet-stream'
|
|
226
|
+
data_url = data['path']
|
|
227
|
+
if data_url.endswith('/'):
|
|
228
|
+
data_url = f"{data_url}{data['ref']}.tar.gz"
|
|
229
|
+
chip.logger.info(f'Downloading {package} data from {data_url}')
|
|
230
|
+
response = requests.get(data_url, stream=True, headers=headers)
|
|
231
|
+
if not response.ok:
|
|
232
|
+
raise SiliconCompilerError(f'Failed to download {package} data source.', chip=chip)
|
|
233
|
+
|
|
234
|
+
fileobj = BytesIO(response.content)
|
|
235
|
+
try:
|
|
236
|
+
with tarfile.open(fileobj=fileobj, mode='r|gz') as tar_ref:
|
|
237
|
+
tar_ref.extractall(path=data_path)
|
|
238
|
+
except tarfile.ReadError:
|
|
239
|
+
fileobj.seek(0)
|
|
240
|
+
# Try as zip
|
|
241
|
+
with zipfile.ZipFile(fileobj) as zip_ref:
|
|
242
|
+
zip_ref.extractall(path=data_path)
|
|
243
|
+
|
|
244
|
+
if 'github' in url.netloc and len(os.listdir(data_path)) == 1:
|
|
245
|
+
# Github inserts one folder at the highest level of the tar file
|
|
246
|
+
# this compensates for this behavior
|
|
247
|
+
gh_url = urlparse(data_url)
|
|
248
|
+
|
|
249
|
+
repo = gh_url.path.split('/')[2]
|
|
250
|
+
|
|
251
|
+
ref = gh_url.path.split('/')[-1]
|
|
252
|
+
if repo.endswith('.git'):
|
|
253
|
+
ref = data['ref']
|
|
254
|
+
elif ref.endswith('.tar.gz'):
|
|
255
|
+
ref = ref[0:-7]
|
|
256
|
+
elif ref.endswith('.tgz'):
|
|
257
|
+
ref = ref[0:-4]
|
|
258
|
+
else:
|
|
259
|
+
ref = ref.split('.')[0]
|
|
260
|
+
|
|
261
|
+
if ref.startswith('v'):
|
|
262
|
+
ref = ref[1:]
|
|
263
|
+
|
|
264
|
+
github_folder = f"{repo}-{ref}"
|
|
265
|
+
|
|
266
|
+
if github_folder in os.listdir(data_path):
|
|
267
|
+
# This moves all files one level up
|
|
268
|
+
git_path = os.path.join(data_path, github_folder)
|
|
269
|
+
for data_file in os.listdir(git_path):
|
|
270
|
+
shutil.move(os.path.join(git_path, data_file), data_path)
|
|
271
|
+
os.removedirs(git_path)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def path_from_python(chip, python_package, append_path=None):
|
|
275
|
+
try:
|
|
276
|
+
module = importlib.import_module(python_package)
|
|
277
|
+
except: # noqa E722
|
|
278
|
+
raise SiliconCompilerError(f'Failed to import {python_package}.', chip=chip)
|
|
279
|
+
|
|
280
|
+
python_path = os.path.dirname(module.__file__)
|
|
281
|
+
if append_path:
|
|
282
|
+
if isinstance(append_path, str):
|
|
283
|
+
append_path = [append_path]
|
|
284
|
+
python_path = os.path.join(python_path, *append_path)
|
|
285
|
+
|
|
286
|
+
python_path = os.path.abspath(python_path)
|
|
287
|
+
|
|
288
|
+
return python_path
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def is_python_module_editable(module_name):
|
|
292
|
+
dist_map = __get_python_module_mapping()
|
|
293
|
+
dist = dist_map[module_name][0]
|
|
294
|
+
|
|
295
|
+
is_editable = False
|
|
296
|
+
for f in distribution(dist).files:
|
|
297
|
+
if f.name == 'direct_url.json':
|
|
298
|
+
info = None
|
|
299
|
+
with open(f.locate(), 'r') as f:
|
|
300
|
+
info = json.load(f)
|
|
301
|
+
|
|
302
|
+
if "dir_info" in info:
|
|
303
|
+
is_editable = info["dir_info"].get("editable", False)
|
|
304
|
+
|
|
305
|
+
return is_editable
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def register_python_data_source(chip,
|
|
309
|
+
package_name,
|
|
310
|
+
python_module,
|
|
311
|
+
alternative_path,
|
|
312
|
+
alternative_ref=None,
|
|
313
|
+
python_module_path_append=None):
|
|
314
|
+
'''
|
|
315
|
+
Helper function to register a python module as data source with an alternative in case
|
|
316
|
+
the module is not installed in an editable state
|
|
317
|
+
'''
|
|
318
|
+
# check if installed in an editable state
|
|
319
|
+
if is_python_module_editable(python_module):
|
|
320
|
+
if python_module_path_append:
|
|
321
|
+
path = path_from_python(chip, python_module, append_path=python_module_path_append)
|
|
322
|
+
else:
|
|
323
|
+
path = f"python://{python_module}"
|
|
324
|
+
ref = None
|
|
325
|
+
else:
|
|
326
|
+
path = alternative_path
|
|
327
|
+
ref = alternative_ref
|
|
328
|
+
|
|
329
|
+
chip.register_source(name=package_name,
|
|
330
|
+
path=path,
|
|
331
|
+
ref=ref)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def register_private_github_data_source(chip,
|
|
335
|
+
package_name,
|
|
336
|
+
repository,
|
|
337
|
+
release,
|
|
338
|
+
artifact):
|
|
339
|
+
gh = Github(auth=github.Auth.Token(__get_github_auth_token(package_name)))
|
|
340
|
+
repo = gh.get_repo(repository)
|
|
341
|
+
|
|
342
|
+
if not release:
|
|
343
|
+
release = repo.get_latest_release().tag_name
|
|
344
|
+
|
|
345
|
+
url = None
|
|
346
|
+
for repo_release in repo.get_releases():
|
|
347
|
+
if repo_release.tag_name == release:
|
|
348
|
+
for asset in repo_release.assets:
|
|
349
|
+
if asset.name == artifact:
|
|
350
|
+
url = asset.url
|
|
351
|
+
|
|
352
|
+
if not url:
|
|
353
|
+
raise ValueError(f'Unable to find release asset: {repository}/{release}/{artifact}')
|
|
354
|
+
|
|
355
|
+
chip.register_source(
|
|
356
|
+
package_name,
|
|
357
|
+
path=url,
|
|
358
|
+
ref=release)
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def __get_github_auth_token(package_name):
|
|
362
|
+
token_name = package_name.upper()
|
|
363
|
+
for tok in ('#', '$', '&', '-', '=', '!', '/'):
|
|
364
|
+
token_name = token_name.replace(tok, '')
|
|
365
|
+
|
|
366
|
+
search_env = (
|
|
367
|
+
f'GITHUB_{token_name}_TOKEN',
|
|
368
|
+
'GITHUB_TOKEN',
|
|
369
|
+
'GIT_TOKEN'
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
token = None
|
|
373
|
+
for env in search_env:
|
|
374
|
+
token = os.environ.get(env, None)
|
|
375
|
+
|
|
376
|
+
if token:
|
|
377
|
+
break
|
|
378
|
+
|
|
379
|
+
if not token:
|
|
380
|
+
raise ValueError('Unable to determine authorization token for GitHub, '
|
|
381
|
+
f'please set one of the following environmental variables: {search_env}')
|
|
382
|
+
|
|
383
|
+
return token
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
@functools.lru_cache(maxsize=1)
|
|
387
|
+
def __get_python_module_mapping():
|
|
388
|
+
mapping = {}
|
|
389
|
+
|
|
390
|
+
for dist in distributions():
|
|
391
|
+
dist_name = None
|
|
392
|
+
if hasattr(dist, 'name'):
|
|
393
|
+
dist_name = dist.name
|
|
394
|
+
else:
|
|
395
|
+
metadata = dist.read_text('METADATA')
|
|
396
|
+
if metadata:
|
|
397
|
+
find_name = re.compile(r'Name: (.*)')
|
|
398
|
+
for data in metadata.splitlines():
|
|
399
|
+
group = find_name.findall(data)
|
|
400
|
+
if group:
|
|
401
|
+
dist_name = group[0]
|
|
402
|
+
break
|
|
403
|
+
|
|
404
|
+
if not dist_name:
|
|
405
|
+
continue
|
|
406
|
+
|
|
407
|
+
provides = dist.read_text('top_level.txt')
|
|
408
|
+
if provides:
|
|
409
|
+
for module in dist.read_text('top_level.txt').split():
|
|
410
|
+
mapping.setdefault(module, []).append(dist_name)
|
|
411
|
+
|
|
412
|
+
return mapping
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from siliconcompiler._common import NodeStatus as SCNodeStatus
|
|
2
|
+
|
|
3
|
+
# CLI entry banner autogenerated using pyfiglet.
|
|
4
|
+
# >> pyfiglet.figlet_format("SC Server")
|
|
5
|
+
banner = r'''
|
|
6
|
+
____ ____ ____
|
|
7
|
+
/ ___| / ___| / ___| ___ _ ____ _____ _ __
|
|
8
|
+
\___ \| | \___ \ / _ \ '__\ \ / / _ \ '__|
|
|
9
|
+
___) | |___ ___) | __/ | \ V / __/ |
|
|
10
|
+
|____/ \____| |____/ \___|_| \_/ \___|_|
|
|
11
|
+
'''
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NodeStatus(SCNodeStatus):
|
|
15
|
+
'''
|
|
16
|
+
Enum class to help ensure consistent status messages
|
|
17
|
+
'''
|
|
18
|
+
|
|
19
|
+
# special code for uploaded
|
|
20
|
+
UPLOADED = 'uploaded'
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class JobStatus():
|
|
24
|
+
'''
|
|
25
|
+
Enum class to help ensure consistent status messages
|
|
26
|
+
'''
|
|
27
|
+
|
|
28
|
+
RUNNING = "running"
|
|
29
|
+
|
|
30
|
+
COMPLETED = "completed"
|
|
31
|
+
FAILED = "failed"
|
|
32
|
+
CANCELED = "canceled"
|
|
33
|
+
REJECTED = "rejected"
|
|
34
|
+
TIMEOUT = "timeout"
|
|
35
|
+
|
|
36
|
+
UNKNOWN = "unknown"
|