From 2d6afd4c3b78d062c12fe9bd34b4b59a6013dba4 Mon Sep 17 00:00:00 2001 From: Matt Venn Date: Fri, 14 Oct 2022 16:44:45 +0200 Subject: [PATCH] initial commit --- .github/FUNDING.yml | 3 + .github/ISSUE_TEMPLATE/bug_report.md | 12 ++ .github/workflows/docs.yaml | 28 ++++ .github/workflows/gds.yaml | 223 +++++++++++++++++++++++++++ LICENSE | 201 ++++++++++++++++++++++++ Makefile | 10 ++ README.md | 33 ++++ info.yaml | 45 ++++++ requirements.txt | 5 + setup.py | 123 +++++++++++++++ src/cells.v | 96 ++++++++++++ src/config.tcl | 53 +++++++ src/pin_order.cfg | 9 ++ 13 files changed, 841 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/workflows/docs.yaml create mode 100644 .github/workflows/gds.yaml create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 info.yaml create mode 100644 requirements.txt create mode 100755 setup.py create mode 100644 src/cells.v create mode 100644 src/config.tcl create mode 100644 src/pin_order.cfg diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..44cd61f7 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +custom: ['https://zerotoasiccourse.com'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..783dd4fe --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,12 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: mattvenn + +--- + +**Link to your wokwi project** + +Please put a link to your wokwi project here. diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 00000000..e6845149 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,28 @@ +name: docs +# either manually started, or on a schedule +on: [ push, workflow_dispatch ] +permissions: + contents: write + pages: write + id-token: write +jobs: + docs: + # ubuntu + runs-on: ubuntu-latest + steps: + # need the repo checked out + - name: checkout repo + uses: actions/checkout@v2 + + # need python + - name: setup python + uses: actions/setup-python@v2 + with: + python-version: '3.7.7' + cache: 'pip' + - run: pip install -r requirements.txt + + # fetch the Verilog from Wokwi API + - name: fetch Verilog and build config + run: ./setup.py --check-docs + diff --git a/.github/workflows/gds.yaml b/.github/workflows/gds.yaml new file mode 100644 index 00000000..043c170c --- /dev/null +++ b/.github/workflows/gds.yaml @@ -0,0 +1,223 @@ +name: gds +# either manually started, or on a schedule +on: [ push, workflow_dispatch ] +permissions: + contents: write + pages: write + id-token: write +jobs: + gds: + env: + OPENLANE_TAG: 2022.07.02_01.38.08 + OPENLANE_IMAGE_NAME: efabless/openlane:$(OPENLANE_TAG) + OPENLANE_ROOT: /home/runner/openlane + PDK_ROOT: /home/runner/pdk + PDK: sky130B + + # ubuntu + runs-on: ubuntu-latest + steps: + # need the repo checked out + - name: checkout repo + uses: actions/checkout@v2 + + # build PDK and fetch OpenLane + - name: pdk & caravel + run: | + cd $HOME + git clone https://github.com/efabless/caravel_user_project.git -b mpw-7a + cd caravel_user_project + make setup + + # need python + - name: setup python + uses: actions/setup-python@v2 + with: + python-version: '3.7.7' + cache: 'pip' + - run: pip install -r requirements.txt + + # fetch the Verilog from Wokwi API + - name: fetch Verilog and build config + run: ./setup.py --create-user-config + + # run the 'harden' rule in the Makefile to use OpenLane to build the GDS + - name: make GDS + run: make harden + + # for debugging, show all the files + - name: show files + run: find runs/wokwi/results + + - name: add summary + run: | + python << EOF >> $GITHUB_STEP_SUMMARY + import csv + with open('runs/wokwi/reports/final_summary_report.csv') as f: + report = list(csv.DictReader(f))[0] + keys = ['OpenDP_Util', 'cell_count', 'wire_length', 'AND', 'DFF', 'NAND', 'NOR', 'OR', 'XOR', 'XNOR', 'MUX'] + print(f'| { "|".join(keys) } |') + print(f'| { "|".join(["-----"] * len(keys)) } |') + print(f'| { "|".join(report[k] for k in keys) } |') + EOF + + - name: populate src cache + uses: actions/cache@v2 + with: + path: src + key: ${{ runner.os }}-src-${{ github.run_id }} + + - name: populate runs cache + uses: actions/cache@v2 + with: + path: runs + key: ${{ runner.os }}-runs-${{ github.run_id }} + + svg: + needs: gds + runs-on: ubuntu-latest + steps: + - name: checkout repo + uses: actions/checkout@v2 + + - name: setup python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: restore runs cache + uses: actions/cache@v2 + with: + path: runs + key: ${{ runner.os }}-runs-${{ github.run_id }} + + - name: create svg + run: | + python -m pip install gdstk + python << EOF + import gdstk + import pathlib + + gds = sorted(pathlib.Path('runs').glob('wokwi/results/final/gds/*.gds')) + library = gdstk.read_gds(gds[-1]) + top_cells = library.top_level() + top_cells[0].write_svg('gds_render.svg') + EOF + + - name: populate svg cache + uses: actions/cache@v2 + with: + path: 'gds_render.svg' + key: ${{ runner.os }}-svg-${{ github.run_id }} + + viewer: + needs: gds + runs-on: ubuntu-latest + steps: + - name: checkout GDS2glTF repo + uses: actions/checkout@v2 + with: + repository: mbalestrini/GDS2glTF + + - name: checkout tinytapeout_gds_viewer repo + uses: actions/checkout@v2 + with: + repository: mbalestrini/tinytapeout_gds_viewer + path: viewer + + - name: setup python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: restore runs cache + uses: actions/cache@v2 + with: + path: runs + key: ${{ runner.os }}-runs-${{ github.run_id }} + + - name: gds2gltf + run: | + python -m pip install -r requirements.txt + cp runs/wokwi/results/final/gds/*.gds tinytapeout.gds + python3 gds2gltf.py tinytapeout.gds + cp tinytapeout.gds.gltf viewer/ + + - name: populate viewer cache + uses: actions/cache@v2 + with: + path: viewer + key: ${{ runner.os }}-viewer-${{ github.run_id }} + + artifact: + needs: + - gds + runs-on: ubuntu-latest + steps: + - name: restore src cache + uses: actions/cache@v2 + with: + path: src + key: ${{ runner.os }}-src-${{ github.run_id }} + + - name: restore runs cache + uses: actions/cache@v2 + with: + path: runs + key: ${{ runner.os }}-runs-${{ github.run_id }} + + - name: upload artifact + uses: actions/upload-artifact@v2 + with: + # path depends on the tag and the module name + name: GDS + path: | + src/* + runs/wokwi/results/final/* + runs/wokwi/reports/final_summary_report.csv + + pages: + needs: + - svg + - viewer + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + outputs: + page_url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: restore svg cache + uses: actions/cache@v2 + with: + path: 'gds_render.svg' + key: ${{ runner.os }}-svg-${{ github.run_id }} + - name: restore viewer cache + uses: actions/cache@v2 + with: + path: viewer + key: ${{ runner.os }}-viewer-${{ github.run_id }} + - name: Setup Pages + uses: actions/configure-pages@v2 + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: '.' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 + + preview: + needs: pages + runs-on: ubuntu-latest + steps: + - name: add gds preview + run: | + PAGE_URL=${{ needs.pages.outputs.page_url }} + PAGE_URL=$(echo "$PAGE_URL" | sed -e 's/\/$//') + cat << EOF >> $GITHUB_STEP_SUMMARY + # layout + ![svg]($PAGE_URL/gds_render.svg) + # viewer + [open preview]($PAGE_URL/viewer/tinytapeout.html) + EOF diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..7334a456 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +# needs PDK_ROOT and OPENLANE_ROOT, OPENLANE_IMAGE_NAME set by the action +harden: + docker run --rm \ + -v $(OPENLANE_ROOT):/openlane \ + -v $(PDK_ROOT):$(PDK_ROOT) \ + -v $(CURDIR):/work \ + -e PDK_ROOT=$(PDK_ROOT) \ + -u $(shell id -u $(USER)):$(shell id -g $(USER)) \ + $(OPENLANE_IMAGE_NAME) \ + /bin/bash -c "./flow.tcl -overwrite -design /work/src -run_path /work/runs -tag wokwi" diff --git a/README.md b/README.md new file mode 100644 index 00000000..f24c1437 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +![](../../workflows/gds/badge.svg) ![](../../workflows/docs/badge.svg) + +Go to https://tinytapeout.com for instructions! + +# How to change the Wokwi project + +Edit the [info.yaml](info.yaml) and change the wokwi_id to match your project. + +# What is this about? + +This repo is a template you can make a copy of for your own [ASIC](https://www.zerotoasiccourse.com/terminology/asic/) design using [Wokwi](https://wokwi.com/). + +When you edit the info.yaml to choose a different ID, the [GitHub Action](.github/workflows/gds.yaml) will fetch the digital netlist of your design from Wokwi. + +The design gets wrapped in some extra logic that builds a 'scan chain'. This is a way to put lots of designs onto one chip and still have access to them all. You can see [all of the technical details here](https://github.com/mattvenn/scan_wrapper). + +After that, the action uses the open source ASIC tool called [OpenLane](https://www.zerotoasiccourse.com/terminology/openlane/) to build the files needed to fabricate an ASIC. + +# What files get made? + +When the action is complete, you can [click here](https://github.com/mattvenn/wokwi-verilog-gds-test/actions) to see the latest build of your design. You need to download the zip file and take a look at the contents: + +* gds_render.svg - picture of your ASIC design +* gds.html - zoomable picture of your ASIC design +* runs/wokwi/reports/final_summary_report.csv - CSV file with lots of details about the design +* runs/wokwi/reports/synthesis/1-synthesis.stat.rpt.strategy4 - list of the [standard cells](https://www.zerotoasiccourse.com/terminology/standardcell/) used by your design +* runs/wokwi/results/final/gds/user_module.gds - the final [GDS](https://www.zerotoasiccourse.com/terminology/gds2/) file needed to make your design + +# What next? + +* Share your GDS on twitter, tag it #tinytapeout and [link me](https://twitter.com/matthewvenn)! +* [Submit it to be made](https://docs.google.com/forms/d/e/1FAIpQLSc3ZF0AHKD3LoZRSmKX5byl-0AzrSK8ADeh0DtkZQX0bbr16w/viewform?usp=sf_link) +* [Join the community](https://discord.gg/rPK2nSjxy8) diff --git a/info.yaml b/info.yaml new file mode 100644 index 00000000..e8446035 --- /dev/null +++ b/info.yaml @@ -0,0 +1,45 @@ +--- +# TinyTapeout project information +project: + wokwi_id: 339800239192932947 # If using wokwi, set this to your project's ID +# source_files: # If using an HDL, set wokwi_id as 0 and uncomment and list your source files here. Source files must be in ./src +# - file1.v +# - file2.v +# top_module: "" # put the name of your top module here, make it unique by prepending your github username + +# As everyone will have access to all designs, try to make it easy for someone new to your design to know what +# it does and how to operate it. +# +# Here is an example: https://github.com/mattvenn/tinytapeout_m_segments/blob/main/info.yaml +# +# This info will be automatically collected and used to make a datasheet for the chip. +documentation: + author: "" # Your name + title: "" # Project title + description: "" # Short description of what your project does + how_it_works: "" # Longer description of how the project works + how_to_test: "" # Instructions on how someone could test your project, include things like what buttons do what and how to set the clock if needed + external_hw: "" # Describe any external hardware needed + language: "wokwi" # other examples include Verilog, Amaranth, VHDL, etc + doc_link: "" # URL to longer form documentation, eg the README.md in your repository + clock_hz: 0 # Clock frequency in Hz (if required) + picture: "" # relative path to a picture in your repository + inputs: # a description of what the inputs do + - clock + - reset + - none + - none + - none + - none + - none + - none + outputs: + - segment a # a description of what the outputs do + - segment b + - segment c + - segment d + - segment e + - segment f + - segment g + - none + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..c5e23b4a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +gdstk +gdspy +pyclipper +mapbox_earcut +PyYAML diff --git a/setup.py b/setup.py new file mode 100755 index 00000000..86c7f31f --- /dev/null +++ b/setup.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +import requests +import argparse +import os +import yaml +import logging +import sys + + +def load_yaml(yaml_file): + with open(yaml_file, "r") as stream: + return (yaml.safe_load(stream)) + + +def write_user_config(module_name, sources): + filename = 'user_config.tcl' + with open(os.path.join('src', filename), 'w') as fh: + fh.write("set ::env(DESIGN_NAME) {}\n".format(module_name)) + fh.write('set ::env(VERILOG_FILES) "\\\n') + for line, source in enumerate(sources): + fh.write(" $::env(DESIGN_DIR)/" + source) + if line != len(sources) - 1: + fh.write('\\\n') + fh.write('"\n') + + +def get_project_source(yaml): + # wokwi_id must be an int or 0 + try: + wokwi_id = int(yaml['project']['wokwi_id']) + except ValueError: + logging.error("wokwi id must be an integer") + exit(1) + + # it's a wokwi project + if wokwi_id != 0: + url = "https://wokwi.com/api/projects/{}/verilog".format(wokwi_id) + logging.info("trying to download {}".format(url)) + r = requests.get(url) + if r.status_code != 200: + logging.warning("couldn't download {}".format(url)) + exit(1) + + # otherwise write it out + filename = "user_module_{}.v".format(wokwi_id) + with open(os.path.join('src', filename), 'wb') as fh: + fh.write(r.content) + return [filename, 'cells.v'] + + # else it's HDL, so check source files + else: + if 'source_files' not in yaml['project']: + logging.error("source files must be provided if wokiw_id is set to 0") + exit(1) + + source_files = yaml['project']['source_files'] + if source_files is None: + logging.error("must be more than 1 source file") + exit(1) + + if len(source_files) == 0: + logging.error("must be more than 1 source file") + exit(1) + + if not 'top_module' not in yaml['project']: + logging.error("must provide a top module name") + exit(1) + + return source_files + + +# documentation +def check_docs(yaml): + for key in ['author', 'title', 'description', 'how_it_works', 'how_to_test', 'language']: + if key not in yaml['documentation']: + logging.error("missing key {} in documentation".format(key)) + exit(1) + if yaml['documentation'][key] == "": + logging.error("missing value for {} in documentation".format(key)) + exit(1) + + +def get_top_module(yaml): + wokwi_id = int(yaml['project']['wokwi_id']) + if wokwi_id != 0: + return "user_module_{}".format(wokwi_id) + else: + return yaml['project']['top_module'] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="TT setup") + + parser.add_argument('--check-docs', help="check the documentation part of the yaml", action="store_const", const=True) + parser.add_argument('--create-user-config', help="create the user_config.tcl file with top module and source files", action="store_const", const=True) + parser.add_argument('--debug', help="debug logging", action="store_const", dest="loglevel", const=logging.DEBUG, default=logging.INFO) + parser.add_argument('--yaml', help="yaml file to load", default='info.yaml') + + 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) + + if args.check_docs: + logging.info("checking docs") + config = load_yaml(args.yaml) + check_docs(config) + + if args.create_user_config: + logging.info("creating include file") + config = load_yaml(args.yaml) + source_files = get_project_source(config) + top_module = get_top_module(config) + write_user_config(top_module, source_files) diff --git a/src/cells.v b/src/cells.v new file mode 100644 index 00000000..fb6db626 --- /dev/null +++ b/src/cells.v @@ -0,0 +1,96 @@ +`define default_netname none + +module buffer_cell ( + input wire in, + output wire out + ); + assign out = in; +endmodule + +module and_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a & b; +endmodule + +module or_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a | b; +endmodule + +module xor_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = a ^ b; +endmodule + +module nand_cell ( + input wire a, + input wire b, + output wire out + ); + + assign out = !(a&b); +endmodule + +module not_cell ( + input wire in, + output wire out + ); + + assign out = !in; +endmodule + +module mux_cell ( + input wire a, + input wire b, + input wire sel, + output wire out + ); + + assign out = sel ? b : a; +endmodule + +module dff_cell ( + input wire clk, + input wire d, + output reg q, + output wire notq + ); + + assign notq = !q; + always @(posedge clk) + q <= d; + +endmodule + +module dffsr_cell ( + input wire clk, + input wire d, + input wire s, + input wire r, + output reg q, + output wire notq + ); + + assign notq = !q; + + always @(posedge clk or posedge s or posedge r) begin + if (r) + q <= '0; + else if (s) + q <= '1; + else + q <= d; + end +endmodule diff --git a/src/config.tcl b/src/config.tcl new file mode 100644 index 00000000..f0fffadf --- /dev/null +++ b/src/config.tcl @@ -0,0 +1,53 @@ +# User config +set script_dir [file dirname [file normalize [info script]]] + +# read some user config that is written by the setup.py program. +# - the name of the module is defined +# - the list of source files +source $::env(DESIGN_DIR)/user_config.tcl + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +# allow use of specific sky130 cells +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# put all the pins on the left +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg + +# reduce wasted space +set ::env(TOP_MARGIN_MULT) 2 +set ::env(BOTTOM_MARGIN_MULT) 2 + +# absolute die size +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 90 120" +set ::env(FP_CORE_UTIL) 45 +set ::env(PL_BASIC_PLACEMENT) {1} + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +# use alternative efabless decap cells to solve LI density issue +set ::env(DECAP_CELL) "\ + sky130_fd_sc_hd__decap_3 \ + sky130_fd_sc_hd__decap_4 \ + sky130_fd_sc_hd__decap_6 \ + sky130_fd_sc_hd__decap_8 \ + sky130_ef_sc_hd__decap_12" + +# clock +set ::env(CLOCK_TREE_SYNTH) 0 +set ::env(CLOCK_PORT) "" + +# don't use power rings or met5 +set ::env(DESIGN_IS_CORE) 0 +set ::env(RT_MAX_LAYER) {met4} + +# connect to first digital rails +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] diff --git a/src/pin_order.cfg b/src/pin_order.cfg new file mode 100644 index 00000000..0b85c636 --- /dev/null +++ b/src/pin_order.cfg @@ -0,0 +1,9 @@ +#N + +#S + +#E + +#W +io_in.* +io_out.*