diff --git a/.github/workflows/test-precheck.yaml b/.github/workflows/test-precheck.yaml index 044ffcd..8007452 100644 --- a/.github/workflows/test-precheck.yaml +++ b/.github/workflows/test-precheck.yaml @@ -27,7 +27,7 @@ jobs: run: pip install -r requirements.txt - name: Install Sky130 PDK - uses: TinyTapeout/volare-action@v2 + uses: TinyTapeout/ciel-action@v1 with: pdk_name: sky130 pdk_version: ${{ env.PDK_VERSION }} diff --git a/precheck/precheck.py b/precheck/precheck.py index c0b7ce6..394f650 100644 --- a/precheck/precheck.py +++ b/precheck/precheck.py @@ -293,9 +293,9 @@ def main(): else: raise PrecheckFailure("Layout file extension is neither .gds nor .gds.br") - if args.tech not in tech_names: - raise PrecheckFailure(f"Invalid tech: {args.tech}") tech = args.tech + if tech not in tech_names: + raise PrecheckFailure(f"Invalid tech: {tech}") yaml_dir = os.path.dirname(args.gds) while not os.path.exists(f"{yaml_dir}/info.yaml"): @@ -336,22 +336,22 @@ def main(): { "name": "Magic DRC", "check": lambda: magic_drc(gds_file, top_module), - "tech": "sky130", + "tech": "sky130A", }, { "name": "KLayout FEOL", "check": lambda: klayout_drc(gds_file, "feol"), - "tech": "sky130", + "tech": "sky130A", }, { "name": "KLayout BEOL", "check": lambda: klayout_drc(gds_file, "beol"), - "tech": "sky130", + "tech": "sky130A", }, { "name": "KLayout offgrid", "check": lambda: klayout_drc(gds_file, "offgrid"), - "tech": "sky130", + "tech": "sky130A", }, { "name": "KLayout pin label overlapping drawing", @@ -381,7 +381,7 @@ def main(): { "name": "Power pin check", "check": lambda: power_pin_check(verilog_file, lef_file, uses_3v3), - "tech": "sky130", + "tech": "sky130A", }, {"name": "Layer check", "check": lambda: layer_check(gds_file, tech)}, {"name": "Cell name check", "check": lambda: cell_name_check(gds_file)}, diff --git a/precheck/tech_data.py b/precheck/tech_data.py index 2366343..031c0eb 100644 --- a/precheck/tech_data.py +++ b/precheck/tech_data.py @@ -1,5 +1,5 @@ # fmt: off -valid_layers_sky130 = { +valid_layers_sky130A = { (10, 0), (11, 0), (11, 20), (11, 44), (17, 0), (18, 20), (20, 0), (21, 0), (22, 0), (22, 20), (22, 21), (22, 22), (22, 23), (22, 24), (23, 0), (23, 28), (25, 0), (25, 42), (25, 43), (25, 44), (26, 20), (26, 21), (26, 22), (27, 0), @@ -176,24 +176,24 @@ valid_layers_ihp_sg13g2 = [ ] # layers used for the analog pin check -layer_map_sky130 = { +layer_map_sky130A = { "met4": (71, 20), "via3": (70, 44), } -def analog_pin_pos_sky130(pin_number: int, uses_3v3: bool): +def analog_pin_pos_sky130A(pin_number: int, uses_3v3: bool): return 151.81 - 19.32 * pin_number - (15.64 if uses_3v3 else 0) -valid_layers = {"sky130": valid_layers_sky130, "ihp-sg13g2": valid_layers_ihp_sg13g2} -layer_map = {"sky130": layer_map_sky130} -analog_pin_pos = {"sky130": analog_pin_pos_sky130} -lyp_filename = {"sky130": "sky130A.lyp", "ihp-sg13g2": "sg13g2.lyp"} +valid_layers = {"sky130A": valid_layers_sky130A, "ihp-sg13g2": valid_layers_ihp_sg13g2} +layer_map = {"sky130A": layer_map_sky130A} +analog_pin_pos = {"sky130A": analog_pin_pos_sky130A} +lyp_filename = {"sky130A": "sky130A.lyp", "ihp-sg13g2": "sg13g2.lyp"} # TODO: read layer numbers from lyp file valid_lef_port_layers = { - "sky130": { + "sky130A": { "met1.pin": (68, 16), "met2.pin": (69, 16), "met3.pin": (70, 16), @@ -208,7 +208,7 @@ valid_lef_port_layers = { }, } forbidden_layers = { - "sky130": ["met5.drawing", "met5.pin", "met5.label"], + "sky130A": ["met5.drawing", "met5.pin", "met5.label"], "ihp-sg13g2": [ "TopMetal1.drawing", "TopMetal1.pin", @@ -219,8 +219,8 @@ forbidden_layers = { ], } power_pins_layer = { - "sky130": "met4", + "sky130A": "met4", "ihp-sg13g2": "Metal5", } -tech_names = ["sky130", "ihp-sg13g2"] +tech_names = ["sky130A", "ihp-sg13g2"] diff --git a/precheck/test_precheck.py b/precheck/test_precheck.py index 36f63d2..6e043b8 100644 --- a/precheck/test_precheck.py +++ b/precheck/test_precheck.py @@ -477,14 +477,14 @@ def test_klayout_beol_fail(gds_fail_met1_poly: str): def test_klayout_checks_pass(gds_valid: str): - precheck.klayout_checks(gds_valid, "TEST_valid", "sky130") + precheck.klayout_checks(gds_valid, "TEST_valid", "sky130A") def test_klayout_checks_fail_metal5(gds_fail_metal5_poly: str): with pytest.raises( precheck.PrecheckFailure, match=r"Forbidden layer met5\.drawing found in .+" ): - precheck.klayout_checks(gds_fail_metal5_poly, "TEST_met5_error", "sky130") + precheck.klayout_checks(gds_fail_metal5_poly, "TEST_met5_error", "sky130A") def test_klayout_checks_fail_pr_boundary(gds_no_pr_boundary: str): @@ -492,7 +492,7 @@ def test_klayout_checks_fail_pr_boundary(gds_no_pr_boundary: str): precheck.PrecheckFailure, match=r"prBoundary.boundary \(235/4\) layer not found in .+", ): - precheck.klayout_checks(gds_no_pr_boundary, "TEST_no_prboundary", "sky130") + precheck.klayout_checks(gds_no_pr_boundary, "TEST_no_prboundary", "sky130A") def test_klayout_top_module_name(gds_invalid_macro_name: str): @@ -501,7 +501,7 @@ def test_klayout_top_module_name(gds_invalid_macro_name: str): match="Top macro name mismatch: expected TEST_invalid_macro_name, got wrong_name", ): precheck.klayout_checks( - gds_invalid_macro_name, "TEST_invalid_macro_name", "sky130" + gds_invalid_macro_name, "TEST_invalid_macro_name", "sky130A" ) @@ -516,7 +516,7 @@ def test_klayout_zero_area_drc_fail(gds_zero_area: str): def test_shapes_outside_area(gds_shapes_outside_area: str): with pytest.raises(precheck.PrecheckFailure, match="Shapes outside project area"): - precheck.boundary_check(gds_shapes_outside_area, "sky130") + precheck.boundary_check(gds_shapes_outside_area, "sky130A") def test_wrong_power_pins_1(verilog_lef_wrong_power_pins: tuple[str, str]): @@ -533,7 +533,7 @@ def test_wrong_power_pins_2(verilog_lef_wrong_power_pins: tuple[str, str]): def test_invalid_layer(gds_invalid_layer: str): with pytest.raises(precheck.PrecheckFailure, match="Invalid layers in GDS"): - precheck.layer_check(gds_invalid_layer, "sky130") + precheck.layer_check(gds_invalid_layer, "sky130A") def test_invalid_cell_name(gds_invalid_cell_name: str): @@ -560,7 +560,7 @@ def test_pin_analog_example(gds_lef_analog_example: tuple[str, str]): "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_example", False, - "sky130", + "sky130A", ) @@ -572,7 +572,7 @@ def test_pin_analog_power_compat(gds_lef_analog_power_compat: tuple[str, str]): "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_power_compat", False, - "sky130", + "sky130A", ) @@ -588,7 +588,7 @@ def test_pin_analog_wrong_vgnd(gds_lef_analog_wrong_vgnd: tuple[str, str]): "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_wrong_vgnd", False, - "sky130", + "sky130A", ) @@ -604,7 +604,7 @@ def test_pin_analog_overlapping_vgnd(gds_lef_analog_overlapping_vgnd: tuple[str, "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_overlapping_vgnd", False, - "sky130", + "sky130A", ) @@ -616,7 +616,7 @@ def test_pin_analog_compound_vgnd(gds_lef_analog_compound_vgnd: tuple[str, str]) "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_compound_vgnd", False, - "sky130", + "sky130A", ) @@ -628,7 +628,7 @@ def test_pin_analog_example_3v3(gds_lef_analog_example_3v3: tuple[str, str]): "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_example_3v3", True, - "sky130", + "sky130A", ) @@ -644,7 +644,7 @@ def test_pin_analog_3v3_mismatch1(gds_lef_analog_example: tuple[str, str]): "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_example", True, - "sky130", + "sky130A", ) @@ -660,14 +660,14 @@ def test_pin_analog_3v3_mismatch2(gds_lef_analog_example_3v3: tuple[str, str]): "../tech/sky130A/def/analog/tt_analog_1x2.def", "TEST_analog_example_3v3", False, - "sky130", + "sky130A", ) def test_analog_exact_pins(gds_lef_analog_pin_example: tuple[str, str]): gds_file, lef_file = gds_lef_analog_pin_example precheck.analog_pin_check( - gds_file, "sky130", True, False, 2, {"ua[0]": "x", "ua[1]": "x"} + gds_file, "sky130A", True, False, 2, {"ua[0]": "x", "ua[1]": "x"} ) @@ -678,7 +678,7 @@ def test_analog_less_pins(gds_lef_analog_pin_example: tuple[str, str]): match="Analog pin `ua\\[1\\]` is connected to some metal but `analog_pins` is set to 1 .*", ): precheck.analog_pin_check( - gds_file, "sky130", True, False, 1, {"ua[0]": "x", "ua[1]": "x"} + gds_file, "sky130A", True, False, 1, {"ua[0]": "x", "ua[1]": "x"} ) @@ -689,7 +689,7 @@ def test_analog_more_pins(gds_lef_analog_pin_example: tuple[str, str]): match="Analog pin `ua\\[2\\]` is not connected to any adjacent metal but `analog_pins` is set to 3 .*", ): precheck.analog_pin_check( - gds_file, "sky130", True, False, 3, {"ua[0]": "x", "ua[1]": "x"} + gds_file, "sky130A", True, False, 3, {"ua[0]": "x", "ua[1]": "x"} ) @@ -699,7 +699,7 @@ def test_analog_less_ua_entries(gds_lef_analog_pin_example: tuple[str, str]): precheck.PrecheckFailure, match="Analog pin `ua\\[1\\]` is connected to some metal but the description of `ua\\[1\\]` .*", ): - precheck.analog_pin_check(gds_file, "sky130", True, False, 2, {"ua[0]": "x"}) + precheck.analog_pin_check(gds_file, "sky130A", True, False, 2, {"ua[0]": "x"}) def test_analog_more_ua_entries(gds_lef_analog_pin_example: tuple[str, str]): @@ -710,7 +710,7 @@ def test_analog_more_ua_entries(gds_lef_analog_pin_example: tuple[str, str]): ): precheck.analog_pin_check( gds_file, - "sky130", + "sky130A", True, False, 2,