Advertisement
Guest User

Untitled

a guest
Jan 17th, 2017
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.28 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # Written by Qusai Abu-Obaida
  3. # 17-Jan-2017
  4.  
  5. import argparse
  6. import os
  7. import re
  8. import pprint
  9.  
  10. from collections import defaultdict
  11.  
  12. cell_fail_list = {}
  13.  
  14.  
  15. class Transistor:
  16.     def __init__(self, transistor_name, drain, gate, source, transistor_type):
  17.         self.name = transistor_name
  18.         self.d = drain
  19.         self.g = gate
  20.         self.s = source
  21.         self.mos = transistor_type
  22.  
  23.  
  24. def get_transistors(cell_name):
  25.     """ Return drains and sources in a cell (list), ((drain/source) gate type) combinations with
  26.        transistors that share them(dict: {dgt/sgt: [trans1, trans2 ...}), branch point (list),
  27.        and transistors data (dict: {transistor: transistor(object)})
  28.    """
  29.     drains_and_sources = []
  30.     transistors_data = {}
  31.     dgt_dict = defaultdict(list)
  32.     sgt_dict = defaultdict(list)
  33.     try:
  34.         with open("%s/cells/%s/%s.lvs" % (relative_path, cell_name, cell_name)) as lvs_file:
  35.             for t in lvs_file:
  36.                 t = t.strip()
  37.                 if len(t) != 0 and t[0].isalpha():
  38.                     t = t.split()
  39.                     name = t[0]
  40.                     d = t[1]
  41.                     g = t[2]
  42.                     s = t[3]
  43.                     mos = t[4]
  44.                     drains_and_sources.append(s)
  45.                     drains_and_sources.append(d)
  46.                     if d != s:
  47.                         dgt = '%s %s %s' % (d, g, mos)
  48.                         sgt = '%s %s %s' % (s, g, mos)
  49.                         transistors_data[name] = Transistor(name, d, g, s, mos)
  50.                         dgt_dict[dgt].append(transistors_data[name])
  51.                         sgt_dict[sgt].append(transistors_data[name])
  52.  
  53.             branch_points = []
  54.             for n in drains_and_sources:
  55.                 if drains_and_sources.count(n) > 2 and n not in branch_points:
  56.                     branch_points.append(n)
  57.             for n in dgt_dict.keys():
  58.                 if len(dgt_dict[n]) == 1 or n.split()[2] == 'VBP':
  59.                     del dgt_dict[n]
  60.             for n in sgt_dict.keys():
  61.                 if len(sgt_dict[n]) == 1 or n.split()[2] == 'VBN':
  62.                     del sgt_dict[n]
  63.         return drains_and_sources, dgt_dict, sgt_dict, branch_points, transistors_data
  64.     except IOError:
  65.         cell_fail_list[cell_name] = "no lvs"
  66.  
  67.  
  68. def find_series(branch_head, cell_name):
  69.     """ Returns a list of transistors connected in series with a given branch point
  70.        and the name of the last transistor before encountering another branch point
  71.    """
  72.     current = branch_head
  73.     big_list = [current]
  74.     while True:
  75.         series = []
  76.         for t in get_transistors(cell_name)[4].values():
  77.             if t.mos == 'VBN':
  78.                 if current.s == t.d and current.s not in get_transistors(cell_name)[3]:
  79.                     series.append(t)
  80.             elif t.mos == 'VBP':
  81.                 if current.d == t.s and current.d not in get_transistors(cell_name)[3]:
  82.                     series.append(t)
  83.         if len(series) == 1:
  84.             big_list.append(series[0])
  85.             current = series[0]
  86.         else:
  87.             if len(big_list) == 0:
  88.                 big_list = [branch_head]
  89.             return [big_list, current]
  90.  
  91. # Parser
  92. parser = argparse.ArgumentParser()
  93. group = parser.add_mutually_exclusive_group(required=True)
  94. group.add_argument('-all', help="test all cells", action="store_true")
  95. group.add_argument('-list', help="test for provided list")
  96. parser.add_argument('-path', help="Review folder path", default=os.getcwd())
  97. args = parser.parse_args()
  98. # args is an object, ex: args.path = PATH
  99. relative_path = args.path
  100.  
  101.  
  102. def main():
  103.     """ Performs a structure test on all cells excluding flops, latches, CK cells, and fillers in their name and
  104.        determines whether they have a combed structure, then checks if that structure is announced in the name.
  105.        prints a dictionary: {cell: error)
  106.    """
  107.     combed = re.compile(r'_(cv)(\d+)')
  108.     exclude = re.compile(r'(^(f|l)[dsi])|(^ck)')
  109.     # regex that matches any occurrence of either _cv*_ or _v*_ in a cell's name
  110.  
  111.     def combed_cell(cell): return combed.search(cell)
  112.     if args.all:
  113.         try:
  114.             cell_list_names = {cell: combed_cell(cell) for cell in os.listdir(relative_path + "/cells") if
  115.                                not exclude.search(cell)}
  116.         except OSError:
  117.             print 'Did not find "cells" folder'
  118.             quit()
  119.     else:
  120.         try:
  121.             with open(args.list) as f:
  122.                 cell_list_names = {cell.strip(): combed_cell(cell) for cell in [line[:-1] for line in f] if
  123.                                    len(cell) != 0 and not exclude.search(cell)}
  124.         except IOError:
  125.             print "%s doesn't exist" % args.list
  126.             quit()
  127.     print "Testing %d cells..." % len(cell_list_names)
  128.     for cell in cell_list_names:
  129.         data = get_transistors(cell)
  130.         if not data:
  131.             continue
  132.         # data is [drains_and_sources, dgt_dict, sgt_dict, branch_points, transistors_data]
  133.         to_delete = []
  134.         for key in data[1]:
  135.             temporary_dict = defaultdict(list)
  136.             for branch_point in data[1][key]:
  137.                 series = find_series(branch_point, cell)
  138.                 for i in series[0]:
  139.                     temporary_dict[branch_point.name].append(i.g)
  140.                 temporary_dict[branch_point.name].append(series[1].s)
  141.                 # temporary_dict now contains the name of a branch point as key and it's value
  142.                 # is the gates of the transistors connected with in series and finally the last
  143.                 #  point before encountering another branch point
  144.             history = []
  145.             for head, tail in temporary_dict.items():
  146.                 if tail in history:
  147.                     to_delete.append(head)
  148.                 else:
  149.                     history.append(tail)
  150.             # This part appends to the "to_delete" list all the non unique items in temporary_dict
  151.         for key in data[2]:
  152.             temporary_dict = defaultdict(list)
  153.             for branch_point in data[2][key]:
  154.                 series = find_series(branch_point, cell)
  155.                 for i in series[0]:
  156.                     temporary_dict[branch_point.name].append(i.g)
  157.                 temporary_dict[branch_point.name].append(series[1].d)
  158.             history = []
  159.             for head, tail in temporary_dict.items():
  160.                 if tail in history:
  161.                     to_delete.append(head)
  162.                 else:
  163.                     history.append(tail)
  164.         final_list = []
  165.         for i in to_delete:
  166.             # exclude "fingers" of the same transistor ex: MP1 A B C VBN, MP1_2 A B C VBN
  167.             if len(find_series(data[4][i], cell)[0]) > 1:
  168.                 for u in find_series(data[4][i], cell)[0]:
  169.                     final_list.append(u.name)
  170.         if cell_list_names[cell] and len(final_list) == 0:
  171.             cell_fail_list[cell] = "Combed naming, uncombed structure"
  172.         elif not cell_list_names[cell] and len(final_list) != 0:
  173.             cell_fail_list[cell] = "Combed structure not announced" + str(final_list)
  174.     if cell_fail_list:
  175.         pprint.pprint(cell_fail_list)
  176.     else:
  177.         print("Pass")
  178.  
  179.  
  180. if __name__ == '__main__':
  181.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement