From 84efb79dd71a619718701e85ecb01c307333c285 Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Thu, 18 Sep 2025 11:29:07 +0300 Subject: [PATCH] feat(tt_tool): --create-tt-submission command --- .github/workflows/test-harden.yaml | 10 ++++++ project.py | 49 ++++++++++++++++++++++++++++++ tech.py | 3 ++ tt_tool.py | 11 ++++++- 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-harden.yaml b/.github/workflows/test-harden.yaml index a4591db..3aecc0a 100644 --- a/.github/workflows/test-harden.yaml +++ b/.github/workflows/test-harden.yaml @@ -70,6 +70,10 @@ jobs: working-directory: ${{ env.PROJECT_DIR }} run: python ./tt/tt_tool.py $TT_TOOL_ARGS --harden + - name: Create TT submission + working-directory: ${{ env.PROJECT_DIR }} + run: python ./tt/tt_tool.py $TT_TOOL_ARGS --create-tt-submission + - name: Print stats working-directory: ${{ env.PROJECT_DIR }} run: | @@ -84,6 +88,12 @@ jobs: with: name: gds-${{ matrix.pdk }} path: ${{ env.PROJECT_DIR }}/runs/wokwi + + - name: Upload TT submission + uses: actions/upload-artifact@v4 + with: + name: tt-submission-${{ matrix.pdk }} + path: ${{ env.PROJECT_DIR }}/tt_submission - name: Upload SVG render uses: actions/upload-artifact@v4 diff --git a/project.py b/project.py index 52fcaca..8e18b1c 100644 --- a/project.py +++ b/project.py @@ -12,6 +12,7 @@ import typing import cairosvg # type: ignore import chevron import gdstk # type: ignore +import klayout.db as pya import yaml from git.repo import Repo @@ -541,6 +542,54 @@ class Project: os.chdir(cwd) + def create_tt_submission(self): + top_module = self.get_macro_name() + logging.info(f"Creating TT submission for {top_module}") + tt_submission_dir = os.path.join(self.local_dir, "tt_submission") + shutil.rmtree(tt_submission_dir, ignore_errors=True) + stats_dir = os.path.join(tt_submission_dir, "stats") + os.makedirs(stats_dir, exist_ok=True) + run_dir = os.path.join(self.local_dir, "runs/wokwi") + final_dir = os.path.join(run_dir, "final") + + # Convert to OAS: + # strm2oas tt_submission/${TOP_MODULE}.gds tt_submission/${TOP_MODULE}.oas + oas_file = os.path.join("tt_submission", f"{top_module}.oas") + gds_file = os.path.join(final_dir, "gds", f"{top_module}.gds") + layout = pya.Layout() + layout.read(gds_file) + layout.write(oas_file) + + files_to_copy = [ + os.path.join(run_dir, "FLOW_VERSION"), + os.path.join(run_dir, "PDK_SOURCES"), + os.path.join(run_dir, "resolved.json"), + os.path.join(final_dir, "commit_id.json"), + os.path.join(final_dir, "gds", f"{top_module}.gds"), + os.path.join(final_dir, "lef", f"{top_module}.lef"), + *glob.glob(os.path.join(final_dir, "spef/*/*.spef")), + ] + for file in files_to_copy: + shutil.copyfile( + file, os.path.join(tt_submission_dir, os.path.basename(file)) + ) + + # GL netlist + gl_type = self.tech.netlist_type + gl_file = os.path.join(final_dir, gl_type, f"{top_module}.{gl_type}.v") + shutil.copyfile(gl_file, os.path.join(tt_submission_dir, f"{top_module}.v")) + + # Stats: + shutil.copyfile( + os.path.join(final_dir, "metrics.csv"), + os.path.join(stats_dir, "metrics.csv"), + ) + (yosys_synth_dir,) = glob.glob(os.path.join(run_dir, "*yosys-synthesis")) + shutil.copyfile( + os.path.join(yosys_synth_dir, "reports", "stat.rpt"), + os.path.join(stats_dir, "synthesis-stats.txt"), + ) + def create_fpga_bitstream(self, args): logging.info(f"Creating FPGA bitstream for {self}") diff --git a/tech.py b/tech.py index 964e83d..d1af1f3 100644 --- a/tech.py +++ b/tech.py @@ -17,6 +17,7 @@ class Tech(Protocol): librelane_pdk_args: str tt_corner: str cell_regexp: str + netlist_type: Literal["pnl", "nl"] """ These layers will be removed from the SVG render of the layout """ label_layers: List[Tuple[int, int]] @@ -41,6 +42,7 @@ class Sky130Tech(Tech): librelane_pdk_args = "" tt_corner = "nom_tt_025C_1v80" cell_regexp = r"sky130_(?P\S+)__(?P\S+)_(?P\d+)" + netlist_type = "pnl" label_layers = [ (64, 59), # pwell.label (64, 5), # nwell.label @@ -91,6 +93,7 @@ class IHPTech(Tech): librelane_pdk_args = "--manual-pdk --pdk ihp-sg13g2" tt_corner = "nom_typ_1p20V_25C" cell_regexp = r"sg13g2_(?P\S+)_(?P\d+)" + netlist_type = "nl" label_layers = [ (8, 1), # Metal1.label (8, 25), # Metal1.text diff --git a/tt_tool.py b/tt_tool.py index c479b3c..0c35763 100755 --- a/tt_tool.py +++ b/tt_tool.py @@ -91,7 +91,7 @@ if __name__ == "__main__": const=True, ) - # configure + # Hardening and submission parser.add_argument( "--create-user-config", help="create the user_config.json file with top module and source files", @@ -104,6 +104,12 @@ if __name__ == "__main__": action="store_const", const=True, ) + parser.add_argument( + "--create-tt-submission", + help="Copy the hardened design to the tt_submission directory", + action="store_const", + const=True, + ) # FPGA parser.add_argument( @@ -173,6 +179,9 @@ if __name__ == "__main__": if args.harden: project.harden() + if args.create_tt_submission: + project.create_tt_submission() + if args.create_pdf: project.create_pdf()