Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,22 @@ ciel --version
# About the builds
In its current inception, ciel supports builds of **sky130** and **gf180mcu** PDKs using [Open-PDKs](https://github.com/rtimothyedwards/open_pdks), including the following libraries:

|sky130|gf180mcu|ihp-sg13g2|
|-|-|-|
|sky130_fd_io|gf180mcu_fd_io|sg13g2_io|
|sky130_fd_pr|gf180mcu_fd_pr|sg13g2_pr|
|sky130_fd_pr_reram|gf180mcu_fd_pr|sg13g2_pr|
|sky130_fd_sc_hd|gf180mcu_fd_sc_mcu7t5v0|sg13g2_stdcell|
|sky130_ml_xx_hd|gf180mcu_fd_sc_mcu9t5v0|-|
|sky130_fd_sc_hvl|gf180mcu_osu_sc_gp9t3v3|-|
|sky130_fd_sc_lp|gf180mcu_osu_sc_gp12t3v3|-|
|sky130_fd_sc_ls|-|-|
|sky130_fd_sc_ms|-|-|
|sky130_fd_sc_hs|-|-|
|sky130_sram_macros|gf180mcu_fd_ip_sram|sg13g2_sram|
|sky130|gf180mcu|ihp-sg13g2|ics55|
|-|-|-|-|
|sky130_fd_io|gf180mcu_fd_io|sg13g2_io|ICSIOA_N55_3P3_1P6M1TM|
|sky130_fd_pr|gf180mcu_fd_pr|sg13g2_pr|-|
|sky130_fd_pr_reram|gf180mcu_fd_pr|sg13g2_pr|-|
|sky130_fd_sc_hd|gf180mcu_fd_sc_mcu7t5v0|sg13g2_stdcell|ics55_LLSC_H7CR|
|sky130_ml_xx_hd|gf180mcu_fd_sc_mcu9t5v0|-|-|
|sky130_fd_sc_hvl|gf180mcu_osu_sc_gp9t3v3|-|ics55_LLSC_H7CH|
|sky130_fd_sc_lp|gf180mcu_osu_sc_gp12t3v3|-|ics55_LLSC_H7CL|
|sky130_fd_sc_ls|-|-|-|
|sky130_fd_sc_ms|-|-|-|
|sky130_fd_sc_hs|-|-|-|
|sky130_sram_macros|gf180mcu_fd_ip_sram|sg13g2_sram|-|

Builds for sky130 and gf180mcu are identified by their [**open_pdks**](https://github.com/rtimothyedwards/open_pdks) commit hashes. Builds for ihp-sg13g2 are identified by their [**IHP-Open-PDK**](https://github.com/ihp-gmbh/ihp-open-pdk) commit hashes.
Builds for ics55 are identified by their [**icesprout55-openpdk**](https://github.com/ckdur/icesprout55-openpdk) commit hashes.

# Usage
Ciel requires a so-called **PDK Root**. This PDK root can be anywhere on your computer, but by default it's the folder `~/.ciel` in your home directory. If you have the variable `PDK_ROOT` set, ciel will use that instead. You can also manually override both values by supplying the `--pdk-root` commandline argument.
Expand Down
172 changes: 172 additions & 0 deletions ciel/build/ics55.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Copyright 2026 Ckristian Duran
# Copyright 2022-2023 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import shutil
import subprocess
from datetime import datetime
from typing import Optional, List, Tuple, Dict
from concurrent.futures import ThreadPoolExecutor

from rich.console import Console
from rich.progress import Progress

from .git_multi_clone import GitMultiClone
from ..families import Family
from ..github import ics55_open_repo
from ..common import (
Version,
get_ciel_dir,
mkdirp,
)


def get_ics55(
version, build_directory, jobs=1, repo_path=None
) -> Tuple[str, Optional[str], Optional[str]]:
try:
console = Console()

if repo_path is None:
with Progress() as progress:
with ThreadPoolExecutor(max_workers=jobs) as executor:
gmc = GitMultiClone(build_directory, progress)
ics_future = executor.submit(
GitMultiClone.clone,
gmc,
ics55_open_repo.link,
version,
)
repo = ics_future.result()
current_task = progress.add_task("Updating submodules…", total=100)
repo.init_submodule(
callback=lambda x: progress.update(current_task, completed=x)
)
repo_path = repo.path
console.log(f"Done fetching {ics55_open_repo.name}.")
else:
console.log(f"Using ICS55 at {repo_path} unaltered.")

return repo_path

except subprocess.CalledProcessError as e:
print(e)
print(e.stderr)
exit(-1)


def build_ics(build_directory, ics55_path, log_dir):
# """Build"""
try:
shutil.rmtree(os.path.join(build_directory, "ics55"))
except FileNotFoundError:
pass

# Execute the install
console = Console()
def run_sh(script, log_to):
output_file = open(log_to, "w")
try:
subprocess.check_call(
["bash", "-c", script],
cwd=ics55_path,
stdout=output_file,
stderr=output_file,
stdin=open(os.devnull),
)
except subprocess.CalledProcessError as e:
console.log(
f"An error occurred while building the PDK. Check {log_to} for more information."
)
raise e

config_log = os.path.join(log_dir, "config.log")
console.log(f"Downloading and installing PDK. Logging into {config_log}")
run_sh("make openpdk", log_to=config_log)

shutil.copytree(
os.path.join(ics55_path, "ics55"),
os.path.join(build_directory, "ics55"),
ignore=lambda dir, files: (
files if ".git" in os.path.split(dir) else [".git", ".DS_Store"]
),
)


def install_ics(build_directory, pdk_root, version):
console = Console()
with console.status("Adding build to list of installed versions…"):
ics55_family = Family.by_name["ics55"]

version_directory = Version(version, "ics55").get_dir(pdk_root)
if (
os.path.exists(version_directory)
and len(os.listdir(version_directory)) != 0
):
backup_path = version_directory
it = 0
while os.path.exists(backup_path) and len(os.listdir(backup_path)) != 0:
it += 1
backup_path = Version(f"{version}.bk{it}", "ics55").get_dir(
pdk_root
)
console.log(
f"Build already found at {version_directory}, moving to {backup_path}…"
)
shutil.move(version_directory, backup_path)

console.log("Copying…")
mkdirp(version_directory)

for variant in ics55_family.variants:
variant_build_path = os.path.join(build_directory, variant)
variant_install_path = os.path.join(version_directory, variant)
if os.path.isdir(variant_build_path):
shutil.copytree(variant_build_path, variant_install_path)

console.log("Done.")


def build(
pdk_root: str,
version: str,
jobs: int = 1,
clear_build_artifacts: bool = True,
include_libraries: Optional[List[str]] = None,
using_repos: Optional[Dict[str, str]] = None,
):
console = Console()
if include_libraries is not None:
console.log(
"Note: all libraries will be acquired as part of the trivial PDK build."
)

if using_repos is None:
using_repos = {}

build_directory = os.path.join(
get_ciel_dir(pdk_root, "ics55"), "build", version
)
timestamp = datetime.now().strftime("build_ics55-%Y-%m-%d-%H-%M-%S")
log_dir = os.path.join(build_directory, "logs", timestamp)
mkdirp(log_dir)

console.log(f"Logging to '{log_dir}'…")

ics55_path = get_ics55(version, build_directory, jobs, using_repos.get("ics"))
build_ics(build_directory, ics55_path, log_dir)
install_ics(build_directory, pdk_root, version)

if clear_build_artifacts:
shutil.rmtree(build_directory)
13 changes: 12 additions & 1 deletion ciel/families.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from dataclasses import dataclass
from typing import Iterable, List, Dict, Optional, Set, ClassVar

from .github import RepoInfo, opdks_repo, ihp_repo
from .github import RepoInfo, opdks_repo, ihp_repo, ics55_open_repo


@dataclass
Expand Down Expand Up @@ -124,3 +124,14 @@ def resolve_libraries(
],
repo=ihp_repo,
)
Family.by_name["ics55"] = Family(
name="ics55",
variants=["ics55"],
all_libraries=[
"ics55_LLSC_H7CH",
"ics55_LLSC_H7CL",
"ics55_LLSC_H7CR",
"ICsprout_55LLULP1233_IO_251013",
],
repo=ics55_open_repo,
)
10 changes: 10 additions & 0 deletions ciel/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ def api(self):
os.getenv("IHP_REPO_NAME", "IHP-Open-PDK"),
)

ics55_repo = RepoInfo(
os.getenv("ICS_REPO_OWNER", "openecos-projects"),
os.getenv("ICS_REPO_NAME", "icsprout55-pdk"),
)

ics55_open_repo = RepoInfo(
os.getenv("ICS_REPO_OWNER", "ckdur"), # TODO: Once the PR passes, we should change this
os.getenv("ICS_REPO_NAME", "icsprout55-pdk"),
)


class GitHubSession(httpx.Client):
class Token(object):
Expand Down