/ extract_rules.py
extract_rules.py
  1  #!/usr/bin/env python3
  2  """Script to extract the rules from PDK files"""
  3  # SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-or-later OR CERN-OHL-S-2.0+ OR Apache-2.0
  4  # Currently this is manual extraction for a signal TSMC 0.18um
  5  # Plan is to update this is the future to make it generic and driven
  6  # by an input file.
  7  
  8  import yaml
  9  
 10  from pdkmaster import AssuraContext
 11  
 12  print("TSMC_CM018RF")
 13  
 14  with open("tf_yaml/TSMC_CM018RF_TechFile.yaml") as f:
 15      tf = yaml.load(f, Loader=yaml.FullLoader)
 16  with open("assura_yaml/TSMC_CM018RF_DRC.yaml") as f:
 17      drc = yaml.load(f, Loader=yaml.FullLoader)
 18  with open("assura_yaml/TSMC_CM018RF_Antenna.yaml") as f:
 19      antenna = yaml.load(f, Loader=yaml.FullLoader)
 20  # TODO: LVS and PEX
 21  
 22  for expr in tf["TechFile"]:
 23      for key, value in expr.items():
 24          if key == "constraintGroups":
 25              tf_foundry = value["foundry"]
 26  
 27  print("Techfile foundry constraints specified:")
 28  for key in tf_foundry.keys():
 29      if key != "override":
 30          print("\t{}".format(key))
 31  
 32  
 33  def _cond2str(expr):
 34      if isinstance(expr, list):
 35          return "("+" ".join(_cond2str(item) for item in expr)+")"
 36      elif isinstance(expr, dict):
 37          assert len(expr) == 1
 38          for key, args in expr.items():
 39              return key+_cond2str(args)
 40      else:
 41          return str(expr)
 42  
 43  class AssuraDRC(dict):
 44      def extract_checks(self, value, *, condstr=""):
 45          for expr in value:
 46              if isinstance(expr, dict):
 47                  for key, value in expr.items():
 48                      if key == "if":
 49                          condstr2 = _cond2str(value["cond"])
 50                          if len(condstr) > 0:
 51                              condstr2 = condstr+"&&"+condstr2
 52                          self.extract_checks(
 53                              value=value["then"]["statements"],
 54                              condstr=condstr2,
 55                          )
 56                          if "else" in value:
 57                              condstr2 = "!"+_cond2str(value["cond"])
 58                              if len(condstr) > 0:
 59                                  condstr2 = condstr+"&&"+condstr2
 60                              self.extract_checks(
 61                                  value=value["else"]["statements"],
 62                                  condstr=condstr2,
 63                              )
 64                      elif key in ("drc", "errorLayer", "offGrid"):
 65                          self.add_check(condstr, key, value)
 66  
 67      def add_check(self, condstr, checktype, check):
 68          try:
 69              conddata = self[condstr]
 70          except KeyError:
 71              self[condstr] = conddata = {}
 72  
 73          try:
 74              conddata[checktype].append(check)
 75          except KeyError:
 76              conddata[checktype] = [check]
 77  
 78      def print_checks(self):
 79          keys = list(self.keys())
 80          keys.sort()
 81  
 82          for key in keys:
 83              print("{}:".format("Unconditioned" if key == "" else key))
 84              for checktype, checks in self[key].items():
 85                  print("  {}:".format(checktype))
 86                  for check in checks:
 87                      print("    {}".format(check))
 88  
 89      def get_sigs(self):
 90          sigs = {}
 91          for _, checktypes in self.items():
 92              for checktype, checks in checktypes.items():
 93                  if checktype not in ("drc", "errorLayer", "offGrid"):
 94                      continue
 95                  checksigs = set(tuple(type(expr) for expr in check) for check in checks)
 96                  if checktype in sigs:
 97                      sigs[checktype].update(checksigs)
 98                  else:
 99                      sigs[checktype] = checksigs
100  
101          return sigs
102  
103  # assura_drc = AssuraDRC()
104  # for expr in drc["SkillFile"]:
105  #     if isinstance(expr, dict):
106  #         for key, value in expr.items():
107  #             if key == "drcExtractRules":
108  #                 assura_drc.extract_checks(value["statements"])
109  
110  # #assura_drc.print_checks()
111  # print("drc signatures:")
112  # for checktype, sigs in assura_drc.get_sigs().items():
113  #     print("  {}:".format(checktype))
114  #     for sig in sigs:
115  #         print("    {}".format(sig))
116  
117  context = AssuraContext()
118  ret = context.interpret(expr=drc["AssuraFile"], isstatements=True)
119  
120  print("Assura DRC executed:")
121  print("  Returned: {}".format(ret))
122  print("  Procedures:")
123  for name in context.procedures:
124      print("    {}".format(name))
125  print("  Variables:")
126  for name, value in context.variables.items():
127      print("    {}: {}".format(name, value))
128  print("  Called: {}".format(context.called))