mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-02 20:26:10 +01:00
cleanup: remove legacy code
This commit is contained in:
-101
@@ -1,101 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import discord
|
||||
import yaml
|
||||
|
||||
TOKEN = os.environ["DISCORD_TOKEN"]
|
||||
TARG = os.environ["TARGET_SERVER"]
|
||||
ROLE_ID = os.environ["ROLE_ID"]
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.members = True
|
||||
|
||||
client = discord.Client(intents=intents)
|
||||
exit_code = 0
|
||||
|
||||
|
||||
@client.event
|
||||
async def on_ready():
|
||||
global exit_code
|
||||
try:
|
||||
print(f"{client.user} has connected to Discord!")
|
||||
server = None
|
||||
for g in client.guilds:
|
||||
if g.name == TARG:
|
||||
server = g
|
||||
break
|
||||
if server is None:
|
||||
print(f"Error: Bot is not in a server named {TARG}")
|
||||
exit_code = 1
|
||||
await client.close()
|
||||
|
||||
role = server.get_role(int(ROLE_ID))
|
||||
if not role:
|
||||
print("Error: requested role does not exist on server!")
|
||||
exit_code = 1
|
||||
await client.close()
|
||||
|
||||
participants = []
|
||||
for project in os.listdir("./projects"):
|
||||
info_file = os.path.join("projects", project, "info.yaml")
|
||||
if not os.path.exists(info_file):
|
||||
print(f"info.yaml does not exist for project {project}. Skipping.")
|
||||
else:
|
||||
try:
|
||||
stream = open(info_file, "r")
|
||||
data = yaml.load(stream, Loader=yaml.FullLoader)
|
||||
stream.close()
|
||||
if "discord" in data["documentation"]:
|
||||
dname = data["documentation"]["discord"]
|
||||
if len(dname):
|
||||
if "#" in dname:
|
||||
dname = dname.split("#")[0]
|
||||
# print(f'adding {dname}')
|
||||
participants.append(dname)
|
||||
else:
|
||||
print(
|
||||
f"Project {project} has no discord username listed. Skipping."
|
||||
)
|
||||
except Exception as ex:
|
||||
print(f"Error parsing info.yaml for project {project}. Skipping.")
|
||||
print(f"Error was: {ex}")
|
||||
|
||||
members = []
|
||||
for p in participants:
|
||||
for m in server.members:
|
||||
if m.name == p:
|
||||
members.append(m)
|
||||
break
|
||||
if m.global_name == p:
|
||||
members.append(m)
|
||||
break
|
||||
else:
|
||||
print(f"{p} not found in members")
|
||||
|
||||
new_role_members = []
|
||||
for m in members:
|
||||
if len([d for d in m.roles if d.id == role.id]) == 0:
|
||||
print(f"Giving the role to {m.name}")
|
||||
new_role_members.append(m.name)
|
||||
await m.add_roles(
|
||||
role, reason="Automatic role assignment by GitHub actions pipeline."
|
||||
)
|
||||
else:
|
||||
print(f"{m.name} already has role")
|
||||
|
||||
print("All done!")
|
||||
print("gave new role to:")
|
||||
print("@" + " @".join(new_role_members))
|
||||
await client.close()
|
||||
except Exception as ex:
|
||||
print("Exception was thrown!")
|
||||
print(ex)
|
||||
exit_code = 1
|
||||
await client.close()
|
||||
|
||||
|
||||
client.run(TOKEN)
|
||||
sys.exit(exit_code)
|
||||
@@ -1,27 +0,0 @@
|
||||
# Usage:
|
||||
# klayout -b -r gds_compare.py -rd gds1=file1.gds -rd gds2=file2.gds
|
||||
|
||||
import sys
|
||||
|
||||
import pya
|
||||
|
||||
|
||||
def compare_gds(file1, file2):
|
||||
diff = pya.LayoutDiff()
|
||||
|
||||
# Load the layouts
|
||||
layout1 = pya.Layout()
|
||||
layout1.read(file1)
|
||||
|
||||
layout2 = pya.Layout()
|
||||
layout2.read(file2)
|
||||
|
||||
# Check if the layouts are identical
|
||||
return diff.compare(layout1, layout2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if compare_gds(gds1, gds2): # noqa: F821
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(-1)
|
||||
@@ -1,6 +1,5 @@
|
||||
import math
|
||||
import os
|
||||
import shutil
|
||||
from typing import Any, Dict
|
||||
|
||||
import mistune
|
||||
@@ -53,28 +52,3 @@ class ImagePathRewriterRenderer(MarkdownRenderer):
|
||||
def rewrite_image_paths(source: str, prefix: str) -> str:
|
||||
markdown = mistune.create_markdown(renderer=ImagePathRewriterRenderer(prefix))
|
||||
return unescape_braces(str(markdown(source)))
|
||||
|
||||
|
||||
class WebsiteImagePathRewriterRenderer(MarkdownRenderer):
|
||||
def __init__(self, source_dir: str, target_dir: str):
|
||||
super().__init__()
|
||||
self.source_dir = source_dir
|
||||
self.target_dir = target_dir
|
||||
|
||||
def image(self, token, state):
|
||||
url = token["attrs"]["url"]
|
||||
if "%7B" in url:
|
||||
pass
|
||||
elif ".." in url:
|
||||
url = ""
|
||||
elif "://" not in url and not url.startswith("/"):
|
||||
filename = os.path.basename(url)
|
||||
if url.startswith("/"):
|
||||
url = "../" + url[1:]
|
||||
shutil.copyfile(
|
||||
os.path.join(self.source_dir, url),
|
||||
os.path.join(self.target_dir, filename),
|
||||
)
|
||||
url = f"images/{filename}"
|
||||
token["attrs"]["url"] = url
|
||||
return super().image(token, state)
|
||||
|
||||
-250
@@ -1,250 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import csv
|
||||
import datetime
|
||||
import glob
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
import git
|
||||
|
||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
|
||||
PROJECTS_DIR = os.path.join(ROOT, "projects")
|
||||
REHARDEN_DIR = os.path.join(ROOT, "reharden")
|
||||
|
||||
|
||||
def load_metrics(path):
|
||||
try:
|
||||
with open(os.path.join(path, "runs/wokwi/reports/metrics.csv")) as fh:
|
||||
metrics = next(csv.DictReader(fh))
|
||||
return metrics
|
||||
except FileNotFoundError:
|
||||
logging.warning(f"no metrics found for {path}")
|
||||
return None
|
||||
|
||||
|
||||
# get cell count from synth report
|
||||
def get_cell_count_from_synth(path):
|
||||
num_cells = 0
|
||||
try:
|
||||
yosys_report = (
|
||||
f"{path}/runs/wokwi/reports/synthesis/1-synthesis.AREA_0.stat.rpt"
|
||||
)
|
||||
with open(yosys_report) as fh:
|
||||
for line in fh.readlines():
|
||||
m = re.search(r"Number of cells:\s+(\d+)", line)
|
||||
if m is not None:
|
||||
num_cells = int(m.group(1))
|
||||
|
||||
except IndexError:
|
||||
logging.warning(f"couldn't open yosys cell report for cell checking {path}")
|
||||
return 0
|
||||
except FileNotFoundError:
|
||||
logging.warning(f"no cell count found for {path}")
|
||||
return 0
|
||||
|
||||
return num_cells
|
||||
|
||||
|
||||
def get_cell_counts_from_gl(path):
|
||||
cell_count = {}
|
||||
total = 0
|
||||
|
||||
try:
|
||||
gl_path = glob.glob(
|
||||
os.path.join(path, "runs/wokwi/results/final/verilog/gl/*.nl.v")
|
||||
)[0]
|
||||
except IndexError:
|
||||
logging.warning("no gl cell count found")
|
||||
return 0
|
||||
with open(gl_path) as fh:
|
||||
for line in fh.readlines():
|
||||
m = re.search(r"sky130_(\S+)__(\S+)_(\d+)", line)
|
||||
if m is not None:
|
||||
total += 1
|
||||
cell_lib = m.group(1)
|
||||
cell_name = m.group(2)
|
||||
cell_drive = m.group(3)
|
||||
assert cell_lib in ["fd_sc_hd", "ef_sc_hd"]
|
||||
assert int(cell_drive) > 0
|
||||
try:
|
||||
cell_count[cell_name] += 1
|
||||
except KeyError:
|
||||
cell_count[cell_name] = 1
|
||||
return cell_count
|
||||
|
||||
|
||||
def build_metrics(shuttle_index):
|
||||
total_seconds = 0
|
||||
total_wire_length = 0
|
||||
total_wires_count = 0
|
||||
total_physical_cells = 0
|
||||
max_cells = 0
|
||||
min_cells = 1000
|
||||
max_cell_project = None
|
||||
max_util = 0
|
||||
min_util = 100
|
||||
max_util_project = None
|
||||
|
||||
for project in shuttle_index["projects"]:
|
||||
macro: str = project["macro"]
|
||||
repo_dir = os.path.join(REHARDEN_DIR, macro)
|
||||
metrics = load_metrics(repo_dir)
|
||||
if metrics is None:
|
||||
continue
|
||||
|
||||
try:
|
||||
dt = datetime.datetime.strptime(metrics["total_runtime"][:-3], "%Hh%Mm%Ss")
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
delt = datetime.timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second)
|
||||
total_seconds += delt.total_seconds()
|
||||
|
||||
total_wire_length += int(metrics["wire_length"])
|
||||
total_wires_count += int(metrics["wires_count"])
|
||||
util = float(metrics["OpenDP_Util"])
|
||||
num_cells = get_cell_count_from_synth(repo_dir)
|
||||
total_physical_cells += num_cells
|
||||
|
||||
if num_cells > max_cells:
|
||||
max_cells = num_cells
|
||||
max_cell_project = project
|
||||
if num_cells < min_cells:
|
||||
min_cells = num_cells
|
||||
|
||||
if util > max_util:
|
||||
max_util = util
|
||||
max_util_project = project
|
||||
if util < min_util:
|
||||
min_util = util
|
||||
|
||||
logging.info(f"build time for all projects {total_seconds / 3600} hrs")
|
||||
logging.info(f"total wire length {total_wire_length} um")
|
||||
logging.info(f"total cells {total_physical_cells}")
|
||||
logging.info(f"max cells {max_cells} for project {max_cell_project}")
|
||||
logging.info(f"min cells {min_cells}")
|
||||
logging.info(f"max util {max_util} for project {max_util_project}")
|
||||
logging.info(f"min util {min_util}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="TT reharden tool")
|
||||
parser.add_argument(
|
||||
"--debug",
|
||||
help="debug logging",
|
||||
action="store_const",
|
||||
dest="loglevel",
|
||||
const=logging.DEBUG,
|
||||
default=logging.INFO,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--clone", help="clone the repos", action="store_const", const=True
|
||||
)
|
||||
parser.add_argument(
|
||||
"--harden", help="harden the projects", action="store_const", const=True
|
||||
)
|
||||
parser.add_argument("--start-from", help="start from", type=int, default=0)
|
||||
parser.add_argument("--end-at", help="end at", type=int, default=100000)
|
||||
parser.add_argument("--build-metrics", action="store_const", const=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# setup log
|
||||
log_format = logging.Formatter(
|
||||
"%(asctime)s - %(module)-10s - %(levelname)-8s - %(message)s"
|
||||
)
|
||||
# configure the client logging
|
||||
log = logging.getLogger("")
|
||||
# has to be set to debug as is the root logger
|
||||
log.setLevel(args.loglevel)
|
||||
|
||||
# create console handler and set level to info
|
||||
ch = logging.StreamHandler(sys.stdout)
|
||||
# create formatter for console
|
||||
ch.setFormatter(log_format)
|
||||
log.addHandler(ch)
|
||||
|
||||
shuttle_index = json.load(open("shuttle_index.json"))
|
||||
differences: List[str] = []
|
||||
for number, project in enumerate(shuttle_index["projects"]):
|
||||
if number < args.start_from:
|
||||
continue
|
||||
if number > args.end_at:
|
||||
continue
|
||||
|
||||
repo = project["repo"]
|
||||
commit = project["commit"]
|
||||
macro = project["macro"]
|
||||
repo_dir = os.path.join(REHARDEN_DIR, macro)
|
||||
|
||||
if macro == "tt_um_chip_rom":
|
||||
logging.info(f"[{number :03}] skipping chip ROM")
|
||||
continue
|
||||
|
||||
if "analog_pins" in project:
|
||||
logging.info(f"[{number :03}] skipping analog project {macro}")
|
||||
continue
|
||||
|
||||
if args.clone:
|
||||
if not os.path.exists(repo_dir):
|
||||
logging.info(f"cloning {number :03} {repo}")
|
||||
git.Repo.clone_from(repo, repo_dir)
|
||||
cloned_repo = git.Repo(repo_dir)
|
||||
cloned_repo.git.submodule("update", "--init")
|
||||
cloned_repo.git.checkout(commit)
|
||||
else:
|
||||
cloned_repo = git.Repo(repo_dir)
|
||||
if commit != cloned_repo.commit().hexsha:
|
||||
logging.info(f"updating {number :03} {repo} to commit {commit}")
|
||||
cloned_repo.git.fetch("origin")
|
||||
cloned_repo.git.checkout(commit)
|
||||
cloned_repo.git.submodule("update", "--init")
|
||||
|
||||
# get tt tools setup.
|
||||
# can't run tt from another directory because gitpython fails
|
||||
# can't run symlinked because openlane fails
|
||||
# simple copy won't work because of tt is a submodule and not a standalone repo.
|
||||
tt_tools_path = os.path.join(repo_dir, "tt")
|
||||
if not os.path.exists(tt_tools_path):
|
||||
logging.info(f"cloning tt to {tt_tools_path}")
|
||||
git.Repo.clone_from("tt", tt_tools_path, depth=1)
|
||||
|
||||
if args.harden:
|
||||
logging.info(f"hardening {number :03} {repo_dir}")
|
||||
cwd = os.getcwd()
|
||||
os.chdir(repo_dir)
|
||||
new_gds = f"runs/wokwi/results/final/gds/{macro}.gds"
|
||||
prev_commit = None
|
||||
if os.path.isfile("commit.txt"):
|
||||
with open("commit.txt", "r") as f:
|
||||
prev_commit = f.read().strip()
|
||||
if not os.path.exists(new_gds) or prev_commit != commit:
|
||||
os.system(f"tt/tt_tool.py --create-user-config > reharden.log")
|
||||
res = os.system(f"tt/tt_tool.py --harden --debug >> reharden.log")
|
||||
if res != 0:
|
||||
logging.warning(f"failed to harden {macro}")
|
||||
else:
|
||||
with open("commit.txt", "w") as f:
|
||||
f.write(commit)
|
||||
orig_gds = os.path.join(PROJECTS_DIR, f"{macro}/{macro}.gds")
|
||||
logging.info(f"Comparing {orig_gds} with {new_gds}")
|
||||
res = os.system(
|
||||
f"klayout -b -r tt/gds_compare.py -rd 'gds1={orig_gds}' -rd 'gds2={new_gds}'"
|
||||
)
|
||||
if res != 0:
|
||||
logging.warning(f"GDS compare failed for {macro}")
|
||||
differences.append(macro)
|
||||
os.chdir(cwd)
|
||||
|
||||
if args.harden:
|
||||
print(f"Found total of {len(differences)} different projects: ")
|
||||
for diff in differences:
|
||||
print("- ", diff)
|
||||
|
||||
if args.build_metrics:
|
||||
build_metrics(shuttle_index)
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
img = Image.open("pics/tinytapeout.png").convert("RGBA")
|
||||
overlay = Image.new("RGBA", img.size, (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(overlay)
|
||||
font = ImageFont.truetype("/usr/share/fonts/dejavu/DejaVuSans.ttf", 30)
|
||||
|
||||
# coordinate mapping
|
||||
xmap = ((88, 272), (2676, 1646)) # two pairs of (chip x coord, picture x coord)
|
||||
ymap = ((95, 1879), (3240, 213)) # two pairs of (chip y coord, picture y coord)
|
||||
xshift, yshift = 40, -43 # text position relative to macro origin
|
||||
|
||||
for line in open("openlane/user_project_wrapper/macro.cfg"):
|
||||
macro, x, y, orient = line.split()
|
||||
if macro == "scan_controller":
|
||||
continue
|
||||
elif macro.startswith("scanchain_"):
|
||||
continue
|
||||
name, num = macro.rsplit("_", 1)
|
||||
num, x, y = int(num), int(x), int(y)
|
||||
x = int(
|
||||
(x - xmap[0][0]) / (xmap[1][0] - xmap[0][0]) * (xmap[1][1] - xmap[0][1])
|
||||
+ xmap[0][1]
|
||||
)
|
||||
y = int(
|
||||
(y - ymap[0][0]) / (ymap[1][0] - ymap[0][0]) * (ymap[1][1] - ymap[0][1])
|
||||
+ ymap[0][1]
|
||||
)
|
||||
x += xshift
|
||||
y += yshift
|
||||
msg = str(num)
|
||||
w, h = draw.textsize(msg, font=font)
|
||||
draw.text((x - w / 2, y - h / 2), msg, fill=(0, 0, 0, 255), font=font)
|
||||
|
||||
combined = Image.alpha_composite(img, overlay).convert("RGB")
|
||||
combined.save("pics/tinytapeout_numbered.png")
|
||||
Reference in New Issue
Block a user