Tim Edwards | 956e302 | 2021-05-27 20:43:26 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
| 3 | #-------------------------------------------------------------------- |
| 4 | # Add the special ID layers for the bipolar transistors which tell |
| 5 | # the extraction engine in magic to extract the device model that |
| 6 | # is specific to the device size. There is no such GDS layer, so it |
| 7 | # can only be added after the fact. |
| 8 | #-------------------------------------------------------------------- |
| 9 | |
| 10 | import os |
| 11 | import re |
| 12 | import sys |
| 13 | |
| 14 | magpath = 'sky130A/libs.ref/sky130_fd_pr/mag' |
| 15 | |
| 16 | if len(sys.argv) > 1: |
| 17 | magpath = sys.argv[1] |
| 18 | |
| 19 | baserex = re.compile('<< [np]base >>') |
| 20 | |
| 21 | # Note that the list of NPNs is not comprehensive. However, at the |
| 22 | # moment only 5 special layers and 5 special models are defined in |
| 23 | # the magic techfile and in the device generator. Adding more must |
| 24 | # start with the magic techfile, as the layers must be defined before |
| 25 | # this script can be run. |
| 26 | |
| 27 | devlist = ['sky130_fd_pr__rf_pnp_05v5_W0p68L0p68', |
| 28 | 'sky130_fd_pr__rf_pnp_05v5_W3p40L3p40', |
| 29 | 'sky130_fd_pr__rf_npn_11v0_W1p00L1p00', |
| 30 | 'sky130_fd_pr__rf_npn_05v5_W1p00L1p00', |
| 31 | 'sky130_fd_pr__rf_npn_05v5_W1p00L2p00'] |
| 32 | |
| 33 | typelist = ['pnp0p68', |
| 34 | 'pnp3p40', |
| 35 | 'npn11p0', |
| 36 | 'npn1p00', |
| 37 | 'npn2p00'] |
| 38 | |
| 39 | #-------------------------------------------------------------------- |
| 40 | |
| 41 | for idx, device in enumerate(devlist): |
| 42 | infile_name = magpath + '/' + device + '.mag' |
| 43 | outfile_name = magpath + '/temp.mag' |
| 44 | |
| 45 | if not os.path.exists(infile_name): |
| 46 | print('Error: Cannot find file ' + infile_name) |
| 47 | continue |
| 48 | |
| 49 | print('Adding special ID layer to device ' + device + ' layout') |
| 50 | |
| 51 | type = typelist[idx] |
| 52 | is_baserect = False |
| 53 | infile = open(infile_name, 'r') |
| 54 | outfile = open(outfile_name, 'w') |
| 55 | line_number = 0 |
| 56 | replaced_something = False |
| 57 | |
| 58 | for line in infile: |
| 59 | line_number += 1 |
| 60 | |
| 61 | if is_baserect: |
| 62 | # Repeat the same rectangle as for the bipolar base layer, |
| 63 | # using the ID type layer |
| 64 | outfile.write(line) |
| 65 | outfile.write('<< ' + type + ' >>\n') |
| 66 | replaced_something = True |
| 67 | is_baserect = False |
| 68 | else: |
| 69 | bmatch = baserex.match(line) |
| 70 | if bmatch: |
| 71 | is_baserect = True |
| 72 | |
| 73 | outfile.write(line) |
| 74 | |
| 75 | infile.close() |
| 76 | outfile.close() |
| 77 | |
| 78 | if replaced_something: |
| 79 | print("Something was replaced in '{}'".format(infile_name)) |
| 80 | os.rename(outfile_name, infile_name) |
| 81 | else: |
| 82 | print("Nothing was replaced in '{}'.".format(infile_name)) |
| 83 | os.remove(outfile_name) |
| 84 | |