19341e7e3Sxiaofeibao-xjtu#! /usr/bin/env python3 29341e7e3Sxiaofeibao-xjtu 39341e7e3Sxiaofeibao-xjtuimport argparse 49341e7e3Sxiaofeibao-xjtuimport os 59341e7e3Sxiaofeibao-xjtuimport re 69341e7e3Sxiaofeibao-xjtufrom datetime import date 79341e7e3Sxiaofeibao-xjtufrom shutil import copy, copytree 89341e7e3Sxiaofeibao-xjtu 99341e7e3Sxiaofeibao-xjtuimport xlsxwriter 109341e7e3Sxiaofeibao-xjtu 119341e7e3Sxiaofeibao-xjtu 129341e7e3Sxiaofeibao-xjtuclass VIO(object): 139341e7e3Sxiaofeibao-xjtu def __init__(self, info): 149341e7e3Sxiaofeibao-xjtu self.info = info 159341e7e3Sxiaofeibao-xjtu assert(self.info[0] in ["input", "output"]) 169341e7e3Sxiaofeibao-xjtu self.direction = self.info[0] 179341e7e3Sxiaofeibao-xjtu self.width = 0 if self.info[1] == "" else int(self.info[1].split(":")[0].replace("[", "")) 189341e7e3Sxiaofeibao-xjtu self.width += 1 199341e7e3Sxiaofeibao-xjtu self.name = self.info[2] 209341e7e3Sxiaofeibao-xjtu 219341e7e3Sxiaofeibao-xjtu def get_direction(self): 229341e7e3Sxiaofeibao-xjtu return self.direction 239341e7e3Sxiaofeibao-xjtu 249341e7e3Sxiaofeibao-xjtu def get_width(self): 259341e7e3Sxiaofeibao-xjtu return self.width 269341e7e3Sxiaofeibao-xjtu 279341e7e3Sxiaofeibao-xjtu def get_name(self): 289341e7e3Sxiaofeibao-xjtu return self.name 299341e7e3Sxiaofeibao-xjtu 309341e7e3Sxiaofeibao-xjtu def startswith(self, prefix): 319341e7e3Sxiaofeibao-xjtu return self.info[2].startswith(prefix) 329341e7e3Sxiaofeibao-xjtu 339341e7e3Sxiaofeibao-xjtu def __str__(self): 349341e7e3Sxiaofeibao-xjtu return " ".join(self.info) 359341e7e3Sxiaofeibao-xjtu 369341e7e3Sxiaofeibao-xjtu def __repr__(self): 379341e7e3Sxiaofeibao-xjtu return self.__str__() 389341e7e3Sxiaofeibao-xjtu 399341e7e3Sxiaofeibao-xjtu def __lt__(self, other): 409341e7e3Sxiaofeibao-xjtu return str(self) < str(other) 419341e7e3Sxiaofeibao-xjtu 429341e7e3Sxiaofeibao-xjtuclass VModule(object): 439341e7e3Sxiaofeibao-xjtu module_re = re.compile(r'^\s*module\s*(\w+)\s*(#\(?|)\s*(\(.*|)\s*$') 449341e7e3Sxiaofeibao-xjtu io_re = re.compile(r'^\s*(input|output)\s*(\[\s*\d+\s*:\s*\d+\s*\]|)\s*(\w+),?\s*$') 45*556c96d6Sxiaofeibao-xjtu submodule_re = re.compile(r'^\s*(\w+)\s*(#\(.*\)|)\s*(\w+)\s*\(\s*\)*\s*;*(|//.*)\s*$') 4620dd904fSxiaofeibao-xjtu # when instance submodule is multiline, it will endswith #( or ( , 4720dd904fSxiaofeibao-xjtu # we can only get the submodule's module name, and set instance name "multiline_instance" 4820dd904fSxiaofeibao-xjtu submodule_re_multiline = re.compile(r'^\s*(\w+)\s*#*\(\s*$') 499341e7e3Sxiaofeibao-xjtu difftest_module_re = re.compile(r'^ \w*Difftest\w+\s+\w+ \( //.*$') 509341e7e3Sxiaofeibao-xjtu 519341e7e3Sxiaofeibao-xjtu def __init__(self, name): 529341e7e3Sxiaofeibao-xjtu self.name = name 539341e7e3Sxiaofeibao-xjtu self.lines = [] 549341e7e3Sxiaofeibao-xjtu self.io = [] 559341e7e3Sxiaofeibao-xjtu self.submodule = dict() 569341e7e3Sxiaofeibao-xjtu self.instance = set() 579341e7e3Sxiaofeibao-xjtu self.in_difftest = False 589341e7e3Sxiaofeibao-xjtu 599341e7e3Sxiaofeibao-xjtu def add_line(self, line): 609341e7e3Sxiaofeibao-xjtu debug_dontCare = False 61623032efSxiaofeibao if "RenameTable" in self.name: 629341e7e3Sxiaofeibao-xjtu if line.strip().startswith("assign io_debug_rdata_"): 639341e7e3Sxiaofeibao-xjtu debug_dontCare = True 649341e7e3Sxiaofeibao-xjtu elif "SynRegfileSlice" in self.name: 659341e7e3Sxiaofeibao-xjtu if line.strip().startswith("assign io_debug_ports_"): 669341e7e3Sxiaofeibao-xjtu debug_dontCare = True 679341e7e3Sxiaofeibao-xjtu 689341e7e3Sxiaofeibao-xjtu # start of difftest module 699341e7e3Sxiaofeibao-xjtu difftest_match = self.difftest_module_re.match(line) 709341e7e3Sxiaofeibao-xjtu if difftest_match: 719341e7e3Sxiaofeibao-xjtu self.in_difftest = True 729341e7e3Sxiaofeibao-xjtu self.lines.append("`ifndef SYNTHESIS\n") 739341e7e3Sxiaofeibao-xjtu 749341e7e3Sxiaofeibao-xjtu if debug_dontCare: 759341e7e3Sxiaofeibao-xjtu self.lines.append("`ifndef SYNTHESIS\n") 769341e7e3Sxiaofeibao-xjtu self.lines.append(line) 779341e7e3Sxiaofeibao-xjtu if debug_dontCare: 789341e7e3Sxiaofeibao-xjtu self.lines.append("`else\n") 799341e7e3Sxiaofeibao-xjtu debug_dontCare_name = line.strip().split(" ")[1] 809341e7e3Sxiaofeibao-xjtu self.lines.append(f" assign {debug_dontCare_name} = 0;\n") 819341e7e3Sxiaofeibao-xjtu self.lines.append("`endif\n") 829341e7e3Sxiaofeibao-xjtu 839341e7e3Sxiaofeibao-xjtu # end of difftest module 849341e7e3Sxiaofeibao-xjtu if self.in_difftest and line.strip() == ");": 859341e7e3Sxiaofeibao-xjtu self.in_difftest = False 869341e7e3Sxiaofeibao-xjtu self.lines.append("`endif\n") 879341e7e3Sxiaofeibao-xjtu 889341e7e3Sxiaofeibao-xjtu if len(self.lines): 899341e7e3Sxiaofeibao-xjtu io_match = self.io_re.match(line) 909341e7e3Sxiaofeibao-xjtu if io_match: 919341e7e3Sxiaofeibao-xjtu this_io = VIO(tuple(map(lambda i: io_match.group(i), range(1, 4)))) 929341e7e3Sxiaofeibao-xjtu self.io.append(this_io) 9320dd904fSxiaofeibao-xjtu submodule_mutiline_match = self.submodule_re_multiline.match(line) 9420dd904fSxiaofeibao-xjtu submodule_match = self.submodule_re.match(line) or submodule_mutiline_match 9520dd904fSxiaofeibao-xjtu if submodule_mutiline_match: 9620dd904fSxiaofeibao-xjtu print('submodule_re_mutiline:') 9720dd904fSxiaofeibao-xjtu print(line) 989341e7e3Sxiaofeibao-xjtu if submodule_match: 999341e7e3Sxiaofeibao-xjtu this_submodule = submodule_match.group(1) 1009341e7e3Sxiaofeibao-xjtu if this_submodule != "module": 10120dd904fSxiaofeibao-xjtu print(self.name + " submodule_match:") 10220dd904fSxiaofeibao-xjtu print(this_submodule) 1039341e7e3Sxiaofeibao-xjtu self.add_submodule(this_submodule) 10420dd904fSxiaofeibao-xjtu if (submodule_mutiline_match): 10520dd904fSxiaofeibao-xjtu self.add_instance(this_submodule, "multiline_instance") 10620dd904fSxiaofeibao-xjtu else: 1079341e7e3Sxiaofeibao-xjtu self.add_instance(this_submodule, submodule_match.group(3)) 1089341e7e3Sxiaofeibao-xjtu 1099341e7e3Sxiaofeibao-xjtu def add_lines(self, lines): 1109341e7e3Sxiaofeibao-xjtu for line in lines: 1119341e7e3Sxiaofeibao-xjtu self.add_line(line) 1129341e7e3Sxiaofeibao-xjtu 1139341e7e3Sxiaofeibao-xjtu def get_name(self): 1149341e7e3Sxiaofeibao-xjtu return self.name 1159341e7e3Sxiaofeibao-xjtu 1169341e7e3Sxiaofeibao-xjtu def set_name(self, updated_name): 1179341e7e3Sxiaofeibao-xjtu for i, line in enumerate(self.lines): 1189341e7e3Sxiaofeibao-xjtu module_match = VModule.module_re.match(line) 1199341e7e3Sxiaofeibao-xjtu if module_match: 1209341e7e3Sxiaofeibao-xjtu print(f"Line Previously: {line.strip()}") 1219341e7e3Sxiaofeibao-xjtu updated_line = line.replace(self.name, updated_name) 1229341e7e3Sxiaofeibao-xjtu print(f"Line Updated: {updated_line.strip()}") 1239341e7e3Sxiaofeibao-xjtu self.lines[i] = updated_line 1249341e7e3Sxiaofeibao-xjtu break 1259341e7e3Sxiaofeibao-xjtu self.name = updated_name 1269341e7e3Sxiaofeibao-xjtu 1279341e7e3Sxiaofeibao-xjtu def get_lines(self): 1289341e7e3Sxiaofeibao-xjtu return self.lines + ["\n"] 1299341e7e3Sxiaofeibao-xjtu 1309341e7e3Sxiaofeibao-xjtu def get_io(self, prefix="", match=""): 1319341e7e3Sxiaofeibao-xjtu if match: 1329341e7e3Sxiaofeibao-xjtu r = re.compile(match) 1339341e7e3Sxiaofeibao-xjtu return list(filter(lambda x: r.match(str(x)), self.io)) 1349341e7e3Sxiaofeibao-xjtu else: 1359341e7e3Sxiaofeibao-xjtu return list(filter(lambda x: x.startswith(prefix), self.io)) 1369341e7e3Sxiaofeibao-xjtu 1379341e7e3Sxiaofeibao-xjtu def get_submodule(self): 1389341e7e3Sxiaofeibao-xjtu return self.submodule 1399341e7e3Sxiaofeibao-xjtu 1409341e7e3Sxiaofeibao-xjtu def get_instance(self): 1419341e7e3Sxiaofeibao-xjtu return self.instance 1429341e7e3Sxiaofeibao-xjtu 1439341e7e3Sxiaofeibao-xjtu def add_submodule(self, name): 1449341e7e3Sxiaofeibao-xjtu self.submodule[name] = self.submodule.get(name, 0) + 1 1459341e7e3Sxiaofeibao-xjtu 1469341e7e3Sxiaofeibao-xjtu def add_instance(self, name, instance_name): 1479341e7e3Sxiaofeibao-xjtu self.instance.add((name, instance_name)) 1489341e7e3Sxiaofeibao-xjtu 1499341e7e3Sxiaofeibao-xjtu def add_submodules(self, names): 1509341e7e3Sxiaofeibao-xjtu for name in names: 1519341e7e3Sxiaofeibao-xjtu self.add_submodule(name) 1529341e7e3Sxiaofeibao-xjtu 1539341e7e3Sxiaofeibao-xjtu def dump_io(self, prefix="", match=""): 1549341e7e3Sxiaofeibao-xjtu print("\n".join(map(lambda x: str(x), self.get_io(prefix, match)))) 1559341e7e3Sxiaofeibao-xjtu 1569341e7e3Sxiaofeibao-xjtu def get_mbist_type(self): 1579341e7e3Sxiaofeibao-xjtu r = re.compile(r'input.*mbist_(\w+)_(trim|sleep)_fuse.*') 1589341e7e3Sxiaofeibao-xjtu mbist_fuse_io = list(filter(lambda x: r.match(str(x)), self.io)) 1599341e7e3Sxiaofeibao-xjtu mbist_types = list(set(map(lambda io: io.get_name().split("_")[1], mbist_fuse_io))) 1609341e7e3Sxiaofeibao-xjtu assert(len(mbist_types) == 1) 1619341e7e3Sxiaofeibao-xjtu return mbist_types[0] 1629341e7e3Sxiaofeibao-xjtu 1639341e7e3Sxiaofeibao-xjtu def replace(self, s): 1649341e7e3Sxiaofeibao-xjtu self.lines = [s] 1659341e7e3Sxiaofeibao-xjtu 1669341e7e3Sxiaofeibao-xjtu def replace_with_macro(self, macro, s): 1679341e7e3Sxiaofeibao-xjtu replaced_lines = [] 1689341e7e3Sxiaofeibao-xjtu in_io, in_body = False, False 1699341e7e3Sxiaofeibao-xjtu for line in self.lines: 1709341e7e3Sxiaofeibao-xjtu if self.io_re.match(line): 1719341e7e3Sxiaofeibao-xjtu in_io = True 1729341e7e3Sxiaofeibao-xjtu replaced_lines.append(line) 1739341e7e3Sxiaofeibao-xjtu elif in_io: 1749341e7e3Sxiaofeibao-xjtu in_io = False 1759341e7e3Sxiaofeibao-xjtu in_body = True 1769341e7e3Sxiaofeibao-xjtu replaced_lines.append(line) # This is ");" 1779341e7e3Sxiaofeibao-xjtu replaced_lines.append(f"`ifdef {macro}\n") 1789341e7e3Sxiaofeibao-xjtu replaced_lines.append(s) 1799341e7e3Sxiaofeibao-xjtu replaced_lines.append(f"`else\n") 1809341e7e3Sxiaofeibao-xjtu elif in_body: 1819341e7e3Sxiaofeibao-xjtu if line.strip() == "endmodule": 1829341e7e3Sxiaofeibao-xjtu replaced_lines.append(f"`endif // {macro}\n") 1839341e7e3Sxiaofeibao-xjtu replaced_lines.append(line) 1849341e7e3Sxiaofeibao-xjtu else: 1859341e7e3Sxiaofeibao-xjtu replaced_lines.append(line) 1869341e7e3Sxiaofeibao-xjtu self.lines = replaced_lines 1879341e7e3Sxiaofeibao-xjtu 1889341e7e3Sxiaofeibao-xjtu def __str__(self): 1899341e7e3Sxiaofeibao-xjtu module_name = "Module {}: \n".format(self.name) 1909341e7e3Sxiaofeibao-xjtu module_io = "\n".join(map(lambda x: "\t" + str(x), self.io)) + "\n" 1919341e7e3Sxiaofeibao-xjtu return module_name + module_io 1929341e7e3Sxiaofeibao-xjtu 1939341e7e3Sxiaofeibao-xjtu def __repr__(self): 1949341e7e3Sxiaofeibao-xjtu return "{}".format(self.name) 1959341e7e3Sxiaofeibao-xjtu 1969341e7e3Sxiaofeibao-xjtu 1979341e7e3Sxiaofeibao-xjtuclass VCollection(object): 1989341e7e3Sxiaofeibao-xjtu def __init__(self): 1999341e7e3Sxiaofeibao-xjtu self.modules = [] 2009341e7e3Sxiaofeibao-xjtu self.ancestors = [] 2019341e7e3Sxiaofeibao-xjtu 2029341e7e3Sxiaofeibao-xjtu def load_modules(self, vfile): 2039341e7e3Sxiaofeibao-xjtu in_module = False 2049341e7e3Sxiaofeibao-xjtu current_module = None 2059341e7e3Sxiaofeibao-xjtu skipped_lines = [] 2069341e7e3Sxiaofeibao-xjtu with open(vfile) as f: 2079341e7e3Sxiaofeibao-xjtu print("Loading modules from {}...".format(vfile)) 2089341e7e3Sxiaofeibao-xjtu for i, line in enumerate(f): 2099341e7e3Sxiaofeibao-xjtu module_match = VModule.module_re.match(line) 2109341e7e3Sxiaofeibao-xjtu if module_match: 2119341e7e3Sxiaofeibao-xjtu module_name = module_match.group(1) 2129341e7e3Sxiaofeibao-xjtu if in_module or current_module is not None: 2139341e7e3Sxiaofeibao-xjtu print("Line {}: does not find endmodule for {}".format(i, current_module)) 2149341e7e3Sxiaofeibao-xjtu exit() 2159341e7e3Sxiaofeibao-xjtu current_module = VModule(module_name) 2169341e7e3Sxiaofeibao-xjtu for skip_line in skipped_lines: 2179341e7e3Sxiaofeibao-xjtu print("[WARNING]{}:{} is added to module {}:\n{}".format(vfile, i, module_name, skip_line), end="") 2189341e7e3Sxiaofeibao-xjtu current_module.add_line(skip_line) 2199341e7e3Sxiaofeibao-xjtu skipped_lines = [] 2209341e7e3Sxiaofeibao-xjtu in_module = True 2219341e7e3Sxiaofeibao-xjtu if not in_module or current_module is None: 2229341e7e3Sxiaofeibao-xjtu if line.strip() != "":# and not line.strip().startswith("//"): 2239341e7e3Sxiaofeibao-xjtu skipped_lines.append(line) 2249341e7e3Sxiaofeibao-xjtu continue 2259341e7e3Sxiaofeibao-xjtu current_module.add_line(line) 2269341e7e3Sxiaofeibao-xjtu if line.startswith("endmodule"): 2279341e7e3Sxiaofeibao-xjtu self.modules.append(current_module) 2289341e7e3Sxiaofeibao-xjtu current_module = None 2299341e7e3Sxiaofeibao-xjtu in_module = False 2309341e7e3Sxiaofeibao-xjtu 2319341e7e3Sxiaofeibao-xjtu def get_module_names(self): 2329341e7e3Sxiaofeibao-xjtu return list(map(lambda m: m.get_name(), self.modules)) 2339341e7e3Sxiaofeibao-xjtu 2349341e7e3Sxiaofeibao-xjtu def get_all_modules(self, match=""): 2359341e7e3Sxiaofeibao-xjtu if match: 2369341e7e3Sxiaofeibao-xjtu r = re.compile(match) 2379341e7e3Sxiaofeibao-xjtu return list(filter(lambda m: r.match(m.get_name()), self.modules)) 2389341e7e3Sxiaofeibao-xjtu else: 2399341e7e3Sxiaofeibao-xjtu return self.modules 2409341e7e3Sxiaofeibao-xjtu 2419341e7e3Sxiaofeibao-xjtu def get_module(self, name, negedge_modules=None, negedge_prefix=None, with_submodule=False, try_prefix=None, ignore_modules=None): 2429341e7e3Sxiaofeibao-xjtu if negedge_modules is None: 2439341e7e3Sxiaofeibao-xjtu negedge_modules = [] 2449341e7e3Sxiaofeibao-xjtu target = None 2459341e7e3Sxiaofeibao-xjtu for module in self.modules: 2469341e7e3Sxiaofeibao-xjtu if module.get_name() == name: 2479341e7e3Sxiaofeibao-xjtu target = module 2489341e7e3Sxiaofeibao-xjtu if target is None and try_prefix is not None: 2499341e7e3Sxiaofeibao-xjtu for module in self.modules: 2509341e7e3Sxiaofeibao-xjtu name_no_prefix = name[len(try_prefix):] 2519341e7e3Sxiaofeibao-xjtu if module.get_name() == name_no_prefix: 2529341e7e3Sxiaofeibao-xjtu target = module 2539341e7e3Sxiaofeibao-xjtu print(f"Replace {name_no_prefix} with modulename {name}. Please DOUBLE CHECK the verilog.") 2549341e7e3Sxiaofeibao-xjtu target.set_name(name) 2559341e7e3Sxiaofeibao-xjtu if target is None or not with_submodule: 2569341e7e3Sxiaofeibao-xjtu return target 2579341e7e3Sxiaofeibao-xjtu submodules = set() 2589341e7e3Sxiaofeibao-xjtu submodules.add(target) 2599341e7e3Sxiaofeibao-xjtu for submodule, instance in target.get_instance(): 2609341e7e3Sxiaofeibao-xjtu if ignore_modules is not None and submodule in ignore_modules: 2619341e7e3Sxiaofeibao-xjtu continue 2629341e7e3Sxiaofeibao-xjtu self.ancestors.append(instance) 2639341e7e3Sxiaofeibao-xjtu is_negedge_module = False 2649341e7e3Sxiaofeibao-xjtu if negedge_prefix is not None: 2659341e7e3Sxiaofeibao-xjtu if submodule.startswith(negedge_prefix): 2669341e7e3Sxiaofeibao-xjtu is_negedge_module = True 2679341e7e3Sxiaofeibao-xjtu elif try_prefix is not None and submodule.startswith(try_prefix + negedge_prefix): 2689341e7e3Sxiaofeibao-xjtu is_negedge_module = True 2699341e7e3Sxiaofeibao-xjtu if is_negedge_module: 2709341e7e3Sxiaofeibao-xjtu negedge_modules.append("/".join(self.ancestors)) 2719341e7e3Sxiaofeibao-xjtu result = self.get_module(submodule, negedge_modules, negedge_prefix, with_submodule=True, try_prefix=try_prefix, ignore_modules=ignore_modules) 2729341e7e3Sxiaofeibao-xjtu self.ancestors.pop() 2739341e7e3Sxiaofeibao-xjtu if result is None: 2749341e7e3Sxiaofeibao-xjtu print("Error: cannot find submodules of {} or the module itself".format(submodule)) 2759341e7e3Sxiaofeibao-xjtu return None 2769341e7e3Sxiaofeibao-xjtu submodules.update(result) 2779341e7e3Sxiaofeibao-xjtu return submodules 2789341e7e3Sxiaofeibao-xjtu 2799341e7e3Sxiaofeibao-xjtu def dump_to_file(self, name, output_dir, with_submodule=True, split=True, try_prefix=None, ignore_modules=None): 2809341e7e3Sxiaofeibao-xjtu print("Dump module {} to {}...".format(name, output_dir)) 2819341e7e3Sxiaofeibao-xjtu modules = self.get_module(name, with_submodule=with_submodule, try_prefix=try_prefix, ignore_modules=ignore_modules) 2829341e7e3Sxiaofeibao-xjtu if modules is None: 2839341e7e3Sxiaofeibao-xjtu print("does not find module", name) 2849341e7e3Sxiaofeibao-xjtu return False 2859341e7e3Sxiaofeibao-xjtu # print("All modules:", modules) 2869341e7e3Sxiaofeibao-xjtu if not with_submodule: 2879341e7e3Sxiaofeibao-xjtu modules = [modules] 2889341e7e3Sxiaofeibao-xjtu if not os.path.isdir(output_dir): 2899341e7e3Sxiaofeibao-xjtu os.makedirs(output_dir, exist_ok=True) 2909341e7e3Sxiaofeibao-xjtu if split: 2919341e7e3Sxiaofeibao-xjtu for module in modules: 2929341e7e3Sxiaofeibao-xjtu output_file = os.path.join(output_dir, module.get_name() + ".v") 2939341e7e3Sxiaofeibao-xjtu # print("write module", module.get_name(), "to", output_file) 2949341e7e3Sxiaofeibao-xjtu with open(output_file, "w") as f: 2959341e7e3Sxiaofeibao-xjtu f.writelines(module.get_lines()) 2969341e7e3Sxiaofeibao-xjtu else: 2979341e7e3Sxiaofeibao-xjtu output_file = os.path.join(output_dir, name + ".v") 2989341e7e3Sxiaofeibao-xjtu with open(output_file, "w") as f: 2999341e7e3Sxiaofeibao-xjtu for module in modules: 3009341e7e3Sxiaofeibao-xjtu f.writelines(module.get_lines()) 3019341e7e3Sxiaofeibao-xjtu return True 3029341e7e3Sxiaofeibao-xjtu 3039341e7e3Sxiaofeibao-xjtu def dump_negedge_modules_to_file(self, name, output_dir, with_submodule=True, try_prefix=None): 3049341e7e3Sxiaofeibao-xjtu print("Dump negedge module {} to {}...".format(name, output_dir)) 3059341e7e3Sxiaofeibao-xjtu negedge_modules = [] 3069341e7e3Sxiaofeibao-xjtu self.get_module(name, negedge_modules, "NegedgeDataModule_", with_submodule=with_submodule, try_prefix=try_prefix) 3079341e7e3Sxiaofeibao-xjtu negedge_modules_sort = [] 3089341e7e3Sxiaofeibao-xjtu for negedge in negedge_modules: 3099341e7e3Sxiaofeibao-xjtu re_degits = re.compile(r".*[0-9]$") 3109341e7e3Sxiaofeibao-xjtu if re_degits.match(negedge): 3119341e7e3Sxiaofeibao-xjtu negedge_module, num = negedge.rsplit("_", 1) 3129341e7e3Sxiaofeibao-xjtu else: 3139341e7e3Sxiaofeibao-xjtu negedge_module, num = negedge, -1 3149341e7e3Sxiaofeibao-xjtu negedge_modules_sort.append((negedge_module, int(num))) 3159341e7e3Sxiaofeibao-xjtu negedge_modules_sort.sort(key = lambda x : (x[0], x[1])) 3169341e7e3Sxiaofeibao-xjtu output_file = os.path.join(output_dir, "negedge_modules.txt") 3179341e7e3Sxiaofeibao-xjtu with open(output_file, "w")as f: 3189341e7e3Sxiaofeibao-xjtu f.write("set sregfile_list [list\n") 3199341e7e3Sxiaofeibao-xjtu for negedge_module, num in negedge_modules_sort: 3209341e7e3Sxiaofeibao-xjtu if num == -1: 3219341e7e3Sxiaofeibao-xjtu f.write("{}\n".format(negedge_module)) 3229341e7e3Sxiaofeibao-xjtu else: 3239341e7e3Sxiaofeibao-xjtu f.write("{}_{}\n".format(negedge_module, num)) 3249341e7e3Sxiaofeibao-xjtu f.write("]") 3259341e7e3Sxiaofeibao-xjtu 3269341e7e3Sxiaofeibao-xjtu def add_module(self, name, line): 3279341e7e3Sxiaofeibao-xjtu module = VModule(name) 3289341e7e3Sxiaofeibao-xjtu module.add_line(line) 3299341e7e3Sxiaofeibao-xjtu self.modules.append(module) 3309341e7e3Sxiaofeibao-xjtu return module 3319341e7e3Sxiaofeibao-xjtu 3329341e7e3Sxiaofeibao-xjtu def count_instances(self, top_name, name): 3339341e7e3Sxiaofeibao-xjtu if top_name == name: 3349341e7e3Sxiaofeibao-xjtu return 1 3359341e7e3Sxiaofeibao-xjtu count = 0 3369341e7e3Sxiaofeibao-xjtu top_module = self.get_module(top_name) 3379341e7e3Sxiaofeibao-xjtu if top_module is not None: 3389341e7e3Sxiaofeibao-xjtu for submodule in top_module.submodule: 3399341e7e3Sxiaofeibao-xjtu count += top_module.submodule[submodule] * self.count_instances(submodule, name) 3409341e7e3Sxiaofeibao-xjtu return count 3419341e7e3Sxiaofeibao-xjtu 3429341e7e3Sxiaofeibao-xjtudef check_data_module_template(collection): 3439341e7e3Sxiaofeibao-xjtu error_modules = [] 3449341e7e3Sxiaofeibao-xjtu field_re = re.compile(r'io_(w|r)data_(\d*)(_.*|)') 3459341e7e3Sxiaofeibao-xjtu modules = collection.get_all_modules(match="(Sync|Async)DataModuleTemplate.*") 3469341e7e3Sxiaofeibao-xjtu for module in modules: 3479341e7e3Sxiaofeibao-xjtu module_name = module.get_name() 3489341e7e3Sxiaofeibao-xjtu print("Checking", module_name, "...") 3499341e7e3Sxiaofeibao-xjtu wdata_all = sorted(module.get_io(match="input.*wdata.*")) 3509341e7e3Sxiaofeibao-xjtu rdata_all = sorted(module.get_io(match="output.*rdata.*")) 3519341e7e3Sxiaofeibao-xjtu wdata_pattern = set(map(lambda x: " ".join((str(x.get_width()), field_re.match(x.get_name()).group(3))), wdata_all)) 3529341e7e3Sxiaofeibao-xjtu rdata_pattern = set(map(lambda x: " ".join((str(x.get_width()), field_re.match(x.get_name()).group(3))), rdata_all)) 3539341e7e3Sxiaofeibao-xjtu if wdata_pattern != rdata_pattern: 3549341e7e3Sxiaofeibao-xjtu print("Errors:") 3559341e7e3Sxiaofeibao-xjtu print(" wdata only:", sorted(wdata_pattern - rdata_pattern, key=lambda x: x.split(" ")[1])) 3569341e7e3Sxiaofeibao-xjtu print(" rdata only:", sorted(rdata_pattern - wdata_pattern, key=lambda x: x.split(" ")[1])) 3579341e7e3Sxiaofeibao-xjtu print("In", str(module)) 3589341e7e3Sxiaofeibao-xjtu error_modules.append(module) 3599341e7e3Sxiaofeibao-xjtu return error_modules 3609341e7e3Sxiaofeibao-xjtu 3619341e7e3Sxiaofeibao-xjtudef create_verilog(files, top_module, config, try_prefix=None, ignore_modules=None): 3629341e7e3Sxiaofeibao-xjtu collection = VCollection() 3639341e7e3Sxiaofeibao-xjtu for f in files: 3649341e7e3Sxiaofeibao-xjtu collection.load_modules(f) 3659341e7e3Sxiaofeibao-xjtu today = date.today() 3669341e7e3Sxiaofeibao-xjtu directory = f'{top_module}-Release-{config}-{today.strftime("%b-%d-%Y")}' 3679341e7e3Sxiaofeibao-xjtu success = collection.dump_to_file(top_module, os.path.join(directory, top_module), try_prefix=try_prefix, ignore_modules=ignore_modules) 3689341e7e3Sxiaofeibao-xjtu collection.dump_negedge_modules_to_file(top_module, directory, try_prefix=try_prefix) 3699341e7e3Sxiaofeibao-xjtu if not success: 3709341e7e3Sxiaofeibao-xjtu return None, None 3719341e7e3Sxiaofeibao-xjtu return collection, os.path.realpath(directory) 3729341e7e3Sxiaofeibao-xjtu 3739341e7e3Sxiaofeibao-xjtudef get_files(build_path): 3749341e7e3Sxiaofeibao-xjtu files = [] 3759341e7e3Sxiaofeibao-xjtu for f in os.listdir(build_path): 3769341e7e3Sxiaofeibao-xjtu file_path = os.path.join(build_path, f) 3779341e7e3Sxiaofeibao-xjtu if f.endswith(".v") or f.endswith(".sv"): 3789341e7e3Sxiaofeibao-xjtu files.append(file_path) 3799341e7e3Sxiaofeibao-xjtu elif os.path.isdir(file_path): 3809341e7e3Sxiaofeibao-xjtu files += get_files(file_path) 3819341e7e3Sxiaofeibao-xjtu return files 3829341e7e3Sxiaofeibao-xjtu 3839341e7e3Sxiaofeibao-xjtudef create_filelist(filelist_name, out_dir, file_dirs=None, extra_lines=[]): 3849341e7e3Sxiaofeibao-xjtu if file_dirs is None: 3859341e7e3Sxiaofeibao-xjtu file_dirs = [filelist_name] 3869341e7e3Sxiaofeibao-xjtu filelist_entries = [] 3879341e7e3Sxiaofeibao-xjtu for file_dir in file_dirs: 3889341e7e3Sxiaofeibao-xjtu for filename in os.listdir(os.path.join(out_dir, file_dir)): 3899341e7e3Sxiaofeibao-xjtu if filename.endswith(".v") or filename.endswith(".sv"): 3909341e7e3Sxiaofeibao-xjtu # check whether it exists in previous directories 3919341e7e3Sxiaofeibao-xjtu # this infers an implicit priority between the file_dirs 3929341e7e3Sxiaofeibao-xjtu filelist_entry = os.path.join(file_dir, filename) 39320dd904fSxiaofeibao-xjtu if filelist_entry in filelist_entries: 39420dd904fSxiaofeibao-xjtu print(f'[warning]: {filelist_entry} is already in filelist_entries') 39520dd904fSxiaofeibao-xjtu else: 3969341e7e3Sxiaofeibao-xjtu filelist_entries.append(filelist_entry) 3979341e7e3Sxiaofeibao-xjtu with open(os.path.join(out_dir, f"{filelist_name}.f"), "w") as f: 3989341e7e3Sxiaofeibao-xjtu for entry in filelist_entries + extra_lines: 3999341e7e3Sxiaofeibao-xjtu f.write(f"{entry}\n") 4009341e7e3Sxiaofeibao-xjtu 4019341e7e3Sxiaofeibao-xjtu 4029341e7e3Sxiaofeibao-xjtuclass SRAMConfiguration(object): 4039341e7e3Sxiaofeibao-xjtu ARRAY_NAME = "sram_array_(\d)p(\d+)x(\d+)m(\d+)(_multicycle|)(_repair|)" 4049341e7e3Sxiaofeibao-xjtu 4059341e7e3Sxiaofeibao-xjtu SINGLE_PORT = 0 4069341e7e3Sxiaofeibao-xjtu SINGLE_PORT_MASK = 1 4079341e7e3Sxiaofeibao-xjtu DUAL_PORT = 2 4089341e7e3Sxiaofeibao-xjtu DUAL_PORT_MASK = 3 4099341e7e3Sxiaofeibao-xjtu 4109341e7e3Sxiaofeibao-xjtu def __init__(self): 4119341e7e3Sxiaofeibao-xjtu self.name = None 4129341e7e3Sxiaofeibao-xjtu self.depth = None 4139341e7e3Sxiaofeibao-xjtu self.width = None 4149341e7e3Sxiaofeibao-xjtu self.ports = None 4159341e7e3Sxiaofeibao-xjtu self.mask_gran = None 4169341e7e3Sxiaofeibao-xjtu self.has_multi_cycle = False 4179341e7e3Sxiaofeibao-xjtu self.has_repair = False 4189341e7e3Sxiaofeibao-xjtu 4199341e7e3Sxiaofeibao-xjtu def size(self): 4209341e7e3Sxiaofeibao-xjtu return self.depth * self.width 4219341e7e3Sxiaofeibao-xjtu 4229341e7e3Sxiaofeibao-xjtu def is_single_port(self): 4239341e7e3Sxiaofeibao-xjtu return self.ports == self.SINGLE_PORT or self.ports == self.SINGLE_PORT_MASK 4249341e7e3Sxiaofeibao-xjtu 4259341e7e3Sxiaofeibao-xjtu def mask_width(self): 4269341e7e3Sxiaofeibao-xjtu return self.width // self.mask_gran 4279341e7e3Sxiaofeibao-xjtu 4289341e7e3Sxiaofeibao-xjtu def match_module_name(self, module_name): 4299341e7e3Sxiaofeibao-xjtu sram_array_re = re.compile(self.ARRAY_NAME) 4309341e7e3Sxiaofeibao-xjtu module_name_match = sram_array_re.match(self.name) 4319341e7e3Sxiaofeibao-xjtu return module_name_match 4329341e7e3Sxiaofeibao-xjtu 4339341e7e3Sxiaofeibao-xjtu def from_module_name(self, module_name): 4349341e7e3Sxiaofeibao-xjtu self.name = module_name 4359341e7e3Sxiaofeibao-xjtu module_name_match = self.match_module_name(self.name) 4369341e7e3Sxiaofeibao-xjtu assert(module_name_match is not None) 4379341e7e3Sxiaofeibao-xjtu num_ports = int(module_name_match.group(1)) 4389341e7e3Sxiaofeibao-xjtu self.depth = int(module_name_match.group(2)) 4399341e7e3Sxiaofeibao-xjtu self.width = int(module_name_match.group(3)) 4409341e7e3Sxiaofeibao-xjtu self.mask_gran = int(module_name_match.group(4)) 4419341e7e3Sxiaofeibao-xjtu assert(self.width % self.mask_gran == 0) 4429341e7e3Sxiaofeibao-xjtu if num_ports == 1: 4439341e7e3Sxiaofeibao-xjtu self.ports = self.SINGLE_PORT if self.mask_width() == 1 else self.SINGLE_PORT_MASK 4449341e7e3Sxiaofeibao-xjtu else: 4459341e7e3Sxiaofeibao-xjtu self.ports = self.DUAL_PORT if self.mask_width() == 1 else self.DUAL_PORT_MASK 4469341e7e3Sxiaofeibao-xjtu self.has_multi_cycle = str(module_name_match.group(5)) != "" 4479341e7e3Sxiaofeibao-xjtu self.has_repair = str(module_name_match.group(6)) != "" 4489341e7e3Sxiaofeibao-xjtu 4499341e7e3Sxiaofeibao-xjtu def ports_s(self): 4509341e7e3Sxiaofeibao-xjtu s = { 4519341e7e3Sxiaofeibao-xjtu self.SINGLE_PORT: "rw", 4529341e7e3Sxiaofeibao-xjtu self.SINGLE_PORT_MASK: "mrw", 4539341e7e3Sxiaofeibao-xjtu self.DUAL_PORT: "write,read", 4549341e7e3Sxiaofeibao-xjtu self.DUAL_PORT_MASK: "mwrite,read" 4559341e7e3Sxiaofeibao-xjtu } 4569341e7e3Sxiaofeibao-xjtu return s[self.ports] 4579341e7e3Sxiaofeibao-xjtu 4589341e7e3Sxiaofeibao-xjtu def to_sram_conf_entry(self): 4599341e7e3Sxiaofeibao-xjtu all_info = ["name", self.name, "depth", self.depth, "width", self.width, "ports", self.ports_s()] 4609341e7e3Sxiaofeibao-xjtu if self.mask_gran < self.width: 4619341e7e3Sxiaofeibao-xjtu all_info += ["mask_gran", self.mask_gran] 4629341e7e3Sxiaofeibao-xjtu return " ".join(map(str, all_info)) 4639341e7e3Sxiaofeibao-xjtu 4649341e7e3Sxiaofeibao-xjtu def from_sram_conf_entry(self, line): 4659341e7e3Sxiaofeibao-xjtu items = line.strip().split(" ") 4669341e7e3Sxiaofeibao-xjtu self.name = items[1] 4679341e7e3Sxiaofeibao-xjtu if items[7] == "rw": 4689341e7e3Sxiaofeibao-xjtu ports = self.SINGLE_PORT 4699341e7e3Sxiaofeibao-xjtu elif items[7] == "mrw": 4709341e7e3Sxiaofeibao-xjtu ports = self.SINGLE_PORT_MASK 4719341e7e3Sxiaofeibao-xjtu elif items[7] == "write,read": 4729341e7e3Sxiaofeibao-xjtu ports = self.DUAL_PORT 4739341e7e3Sxiaofeibao-xjtu elif items[7] == "mwrite,read": 4749341e7e3Sxiaofeibao-xjtu ports = self.DUAL_PORT_MASK 4759341e7e3Sxiaofeibao-xjtu else: 4769341e7e3Sxiaofeibao-xjtu assert(0) 4779341e7e3Sxiaofeibao-xjtu depth = int(items[3]) 4789341e7e3Sxiaofeibao-xjtu width = int(items[5]) 4799341e7e3Sxiaofeibao-xjtu mask_gran = int(items[-1]) if len(items) > 8 else width 4809341e7e3Sxiaofeibao-xjtu matched_name = self.match_module_name(self.name) is not None 4819341e7e3Sxiaofeibao-xjtu if matched_name: 4829341e7e3Sxiaofeibao-xjtu self.from_module_name(self.name) 4839341e7e3Sxiaofeibao-xjtu assert(self.ports == ports) 4849341e7e3Sxiaofeibao-xjtu assert(self.depth == depth) 4859341e7e3Sxiaofeibao-xjtu assert(self.width == width) 4869341e7e3Sxiaofeibao-xjtu assert(self.mask_gran == mask_gran) 4879341e7e3Sxiaofeibao-xjtu else: 4889341e7e3Sxiaofeibao-xjtu self.ports = ports 4899341e7e3Sxiaofeibao-xjtu self.depth = depth 4909341e7e3Sxiaofeibao-xjtu self.width = width 4919341e7e3Sxiaofeibao-xjtu self.mask_gran = mask_gran 4929341e7e3Sxiaofeibao-xjtu 4939341e7e3Sxiaofeibao-xjtu def to_sram_xlsx_entry(self, num_instances): 4949341e7e3Sxiaofeibao-xjtu if self.is_single_port(): 4959341e7e3Sxiaofeibao-xjtu num_read_port = "shared 1" 4969341e7e3Sxiaofeibao-xjtu num_write_port = "shared 1" 4979341e7e3Sxiaofeibao-xjtu read_clk = "RW0_clk" 4989341e7e3Sxiaofeibao-xjtu write_clk = "RW0_clk" 4999341e7e3Sxiaofeibao-xjtu else: 5009341e7e3Sxiaofeibao-xjtu num_read_port = 1 5019341e7e3Sxiaofeibao-xjtu num_write_port = 1 5029341e7e3Sxiaofeibao-xjtu read_clk = "R0_clk" 5039341e7e3Sxiaofeibao-xjtu write_clk = "W0_clk" 5049341e7e3Sxiaofeibao-xjtu all_info = [self.name, num_instances, "SRAM", num_read_port, num_write_port, 0, 5059341e7e3Sxiaofeibao-xjtu self.depth, self.width, self.mask_gran, read_clk, write_clk, "N/A"] 5069341e7e3Sxiaofeibao-xjtu return all_info 5079341e7e3Sxiaofeibao-xjtu 5089341e7e3Sxiaofeibao-xjtu def get_foundry_sram_wrapper(self, mbist_type): 5099341e7e3Sxiaofeibao-xjtu wrapper_type = "RAMSP" if self.is_single_port() else "RF2P" 5109341e7e3Sxiaofeibao-xjtu wrapper_mask = "" if self.mask_width() == 1 else f"_M{self.mask_width()}" 5119341e7e3Sxiaofeibao-xjtu wrapper_module = f"{wrapper_type}_{self.depth}x{self.width}{wrapper_mask}_WRAP" 5129341e7e3Sxiaofeibao-xjtu wrapper_instance = "u_mem" 5139341e7e3Sxiaofeibao-xjtu foundry_ports = { 5149341e7e3Sxiaofeibao-xjtu "IP_RESET_B" : "mbist_IP_RESET_B", 5159341e7e3Sxiaofeibao-xjtu "PWR_MGMT_IN" : "mbist_PWR_MGNT_IN", 5169341e7e3Sxiaofeibao-xjtu "TRIM_FUSE_IN" : f"mbist_{mbist_type}_trim_fuse", 5179341e7e3Sxiaofeibao-xjtu "SLEEP_FUSE_IN" : f"mbist_{mbist_type}_sleep_fuse", 5189341e7e3Sxiaofeibao-xjtu "FSCAN_RAM_BYPSEL" : "mbist_bypsel", 5199341e7e3Sxiaofeibao-xjtu "FSCAN_RAM_WDIS_B" : "mbist_wdis_b", 5209341e7e3Sxiaofeibao-xjtu "FSCAN_RAM_RDIS_B" : "mbist_rdis_b", 5219341e7e3Sxiaofeibao-xjtu "FSCAN_RAM_INIT_EN" : "mbist_init_en", 5229341e7e3Sxiaofeibao-xjtu "FSCAN_RAM_INIT_VAL" : "mbist_init_val", 5239341e7e3Sxiaofeibao-xjtu "FSCAN_CLKUNGATE" : "mbist_clkungate", 5249341e7e3Sxiaofeibao-xjtu "OUTPUT_RESET" : "mbist_OUTPUT_RESET", 5259341e7e3Sxiaofeibao-xjtu "PWR_MGMT_OUT" : "mbist_PWR_MGNT_OUT" 5269341e7e3Sxiaofeibao-xjtu } 5279341e7e3Sxiaofeibao-xjtu if self.is_single_port(): 5289341e7e3Sxiaofeibao-xjtu foundry_ports["WRAPPER_CLK_EN"] = "mbist_WRAPPER_CLK_EN" 5299341e7e3Sxiaofeibao-xjtu else: 5309341e7e3Sxiaofeibao-xjtu foundry_ports["WRAPPER_WR_CLK_EN"] = "mbist_WRAPPER_WR_CLK_EN" 5319341e7e3Sxiaofeibao-xjtu foundry_ports["WRAPPER_RD_CLK_EN"] = "mbist_WRAPPER_RD_CLK_EN" 5329341e7e3Sxiaofeibao-xjtu if self.has_repair: 5339341e7e3Sxiaofeibao-xjtu foundry_ports["ROW_REPAIR_IN"] = "repair_rowRepair" 5349341e7e3Sxiaofeibao-xjtu foundry_ports["COL_REPAIR_IN"] = "repair_colRepair" 5359341e7e3Sxiaofeibao-xjtu foundry_ports["io_bisr_shift_en"] = "mbist_bisr_shift_en" 5369341e7e3Sxiaofeibao-xjtu foundry_ports["io_bisr_clock"] = "mbist_bisr_clock" 5379341e7e3Sxiaofeibao-xjtu foundry_ports["io_bisr_reset"] = "mbist_bisr_reset" 5389341e7e3Sxiaofeibao-xjtu foundry_ports["u_mem_bisr_inst_SI"] = "mbist_bisr_scan_in" 5399341e7e3Sxiaofeibao-xjtu foundry_ports["u_mem_bisr_inst_SO"] = "mbist_bisr_scan_out" 5409341e7e3Sxiaofeibao-xjtu if self.is_single_port(): 5419341e7e3Sxiaofeibao-xjtu func_ports = { 5429341e7e3Sxiaofeibao-xjtu "CK" : "RW0_clk", 5439341e7e3Sxiaofeibao-xjtu "A" : "RW0_addr", 5449341e7e3Sxiaofeibao-xjtu "WEN" : "RW0_en & RW0_wmode", 5459341e7e3Sxiaofeibao-xjtu "D" : "RW0_wdata", 5469341e7e3Sxiaofeibao-xjtu "REN" : "RW0_en & ~RW0_wmode", 5479341e7e3Sxiaofeibao-xjtu "Q" : "RW0_rdata" 5489341e7e3Sxiaofeibao-xjtu } 5499341e7e3Sxiaofeibao-xjtu if self.mask_width() > 1: 5509341e7e3Sxiaofeibao-xjtu func_ports["WM"] = "RW0_wmask" 5519341e7e3Sxiaofeibao-xjtu else: 5529341e7e3Sxiaofeibao-xjtu func_ports = { 5539341e7e3Sxiaofeibao-xjtu "WCK" : "W0_clk", 5549341e7e3Sxiaofeibao-xjtu "WA" : "W0_addr", 5559341e7e3Sxiaofeibao-xjtu "WEN" : "W0_en", 5569341e7e3Sxiaofeibao-xjtu "D" : "W0_data", 5579341e7e3Sxiaofeibao-xjtu "RCK" : "R0_clk", 5589341e7e3Sxiaofeibao-xjtu "RA" : "R0_addr", 5599341e7e3Sxiaofeibao-xjtu "REN" : "R0_en", 5609341e7e3Sxiaofeibao-xjtu "Q" : "R0_data" 5619341e7e3Sxiaofeibao-xjtu } 5629341e7e3Sxiaofeibao-xjtu if self.mask_width() > 1: 5639341e7e3Sxiaofeibao-xjtu func_ports["WM"] = "W0_mask" 5649341e7e3Sxiaofeibao-xjtu if self.width > 256: 5659341e7e3Sxiaofeibao-xjtu func_ports["MBIST_SELECTEDOH"] = "mbist_selectedOH" 5669341e7e3Sxiaofeibao-xjtu verilog_lines = [] 5679341e7e3Sxiaofeibao-xjtu verilog_lines.append(f" {wrapper_module} {wrapper_instance} (\n") 5689341e7e3Sxiaofeibao-xjtu connected_pins = [] 5699341e7e3Sxiaofeibao-xjtu for pin_name in func_ports: 5709341e7e3Sxiaofeibao-xjtu connected_pins.append(f".{pin_name}({func_ports[pin_name]})") 5719341e7e3Sxiaofeibao-xjtu for pin_name in foundry_ports: 5729341e7e3Sxiaofeibao-xjtu connected_pins.append(f".{pin_name}({foundry_ports[pin_name]})") 5739341e7e3Sxiaofeibao-xjtu verilog_lines.append(" " + ",\n ".join(connected_pins) + "\n") 5749341e7e3Sxiaofeibao-xjtu verilog_lines.append(" );\n") 5759341e7e3Sxiaofeibao-xjtu return wrapper_module, "".join(verilog_lines) 5769341e7e3Sxiaofeibao-xjtu 5779341e7e3Sxiaofeibao-xjtudef generate_sram_conf(collection, module_prefix, out_dir): 5789341e7e3Sxiaofeibao-xjtu if module_prefix is None: 5799341e7e3Sxiaofeibao-xjtu module_prefix = "" 5809341e7e3Sxiaofeibao-xjtu sram_conf = [] 5819341e7e3Sxiaofeibao-xjtu sram_array_name = module_prefix + SRAMConfiguration.ARRAY_NAME 5829341e7e3Sxiaofeibao-xjtu modules = collection.get_all_modules(match=sram_array_name) 5839341e7e3Sxiaofeibao-xjtu for module in modules: 5849341e7e3Sxiaofeibao-xjtu conf = SRAMConfiguration() 5859341e7e3Sxiaofeibao-xjtu conf.from_module_name(module.get_name()[len(module_prefix):]) 5869341e7e3Sxiaofeibao-xjtu sram_conf.append(conf) 5879341e7e3Sxiaofeibao-xjtu conf_path = os.path.join(out_dir, "sram_configuration.txt") 5889341e7e3Sxiaofeibao-xjtu with open(conf_path, "w") as f: 5899341e7e3Sxiaofeibao-xjtu for conf in sram_conf: 5909341e7e3Sxiaofeibao-xjtu f.write(conf.to_sram_conf_entry() + "\n") 5919341e7e3Sxiaofeibao-xjtu return conf_path 5929341e7e3Sxiaofeibao-xjtu 5939341e7e3Sxiaofeibao-xjtudef create_sram_xlsx(out_dir, collection, sram_conf, top_module, try_prefix=None): 5949341e7e3Sxiaofeibao-xjtu workbook = xlsxwriter.Workbook(os.path.join(out_dir, "sram_list.xlsx")) 5959341e7e3Sxiaofeibao-xjtu worksheet = workbook.add_worksheet() 5969341e7e3Sxiaofeibao-xjtu # Header for the list. Starting from row 5. 5979341e7e3Sxiaofeibao-xjtu row = 5 5989341e7e3Sxiaofeibao-xjtu columns = ["Array Instance Name", "# Instances", "Memory Type", 5999341e7e3Sxiaofeibao-xjtu "# Read Ports", "# Write Ports", "# CAM Ports", 6009341e7e3Sxiaofeibao-xjtu "Depth (Entries)", "Width (Bits)", "# Write Segments", 6019341e7e3Sxiaofeibao-xjtu "Read Clk Pin Names(s)", "Write Clk Pin Name(s)", "CAM Clk Pin Name" 6029341e7e3Sxiaofeibao-xjtu ] 6039341e7e3Sxiaofeibao-xjtu for col, column_name in enumerate(columns): 6049341e7e3Sxiaofeibao-xjtu worksheet.write(row, col, column_name) 6059341e7e3Sxiaofeibao-xjtu row += 1 6069341e7e3Sxiaofeibao-xjtu # Entries for the list. 6079341e7e3Sxiaofeibao-xjtu total_size = 0 6089341e7e3Sxiaofeibao-xjtu with open(sram_conf) as f: 6099341e7e3Sxiaofeibao-xjtu for line in f: 6109341e7e3Sxiaofeibao-xjtu conf = SRAMConfiguration() 6119341e7e3Sxiaofeibao-xjtu conf.from_sram_conf_entry(line) 6129341e7e3Sxiaofeibao-xjtu num_instances = collection.count_instances(top_module, conf.name) 6139341e7e3Sxiaofeibao-xjtu if num_instances == 0 and try_prefix is not None: 6149341e7e3Sxiaofeibao-xjtu try_prefix_name = f"{try_prefix}{conf.name}" 6159341e7e3Sxiaofeibao-xjtu num_instances = collection.count_instances(top_module, try_prefix_name) 6169341e7e3Sxiaofeibao-xjtu if num_instances != 0: 6179341e7e3Sxiaofeibao-xjtu conf.name = try_prefix_name 6189341e7e3Sxiaofeibao-xjtu all_info = conf.to_sram_xlsx_entry(num_instances) 6199341e7e3Sxiaofeibao-xjtu for col, info in enumerate(all_info): 6209341e7e3Sxiaofeibao-xjtu worksheet.write(row, col, info) 6219341e7e3Sxiaofeibao-xjtu row += 1 6229341e7e3Sxiaofeibao-xjtu total_size += conf.size() * num_instances 6239341e7e3Sxiaofeibao-xjtu # Total size of the SRAM in top of the sheet 6249341e7e3Sxiaofeibao-xjtu worksheet.write(0, 0, f"Total size: {total_size / (8 * 1024)} KiB") 6259341e7e3Sxiaofeibao-xjtu workbook.close() 6269341e7e3Sxiaofeibao-xjtu 6279341e7e3Sxiaofeibao-xjtudef create_extra_files(out_dir, build_path): 6289341e7e3Sxiaofeibao-xjtu extra_path = os.path.join(out_dir, "extra") 6299341e7e3Sxiaofeibao-xjtu copytree("/nfs/home/share/southlake/extra", extra_path) 6309341e7e3Sxiaofeibao-xjtu for f in os.listdir(build_path): 6319341e7e3Sxiaofeibao-xjtu file_path = os.path.join(build_path, f) 6329341e7e3Sxiaofeibao-xjtu if f.endswith(".csv"): 6339341e7e3Sxiaofeibao-xjtu copy(file_path, extra_path) 6349341e7e3Sxiaofeibao-xjtu 6359341e7e3Sxiaofeibao-xjtudef replace_sram(out_dir, sram_conf, top_module, module_prefix): 6369341e7e3Sxiaofeibao-xjtu replace_sram_dir = "memory_array" 6379341e7e3Sxiaofeibao-xjtu replace_sram_path = os.path.join(out_dir, replace_sram_dir) 6389341e7e3Sxiaofeibao-xjtu if not os.path.exists(replace_sram_path): 6399341e7e3Sxiaofeibao-xjtu os.mkdir(replace_sram_path) 6409341e7e3Sxiaofeibao-xjtu sram_wrapper_dir = "memory_wrapper" 6419341e7e3Sxiaofeibao-xjtu sram_wrapper_path = os.path.join(out_dir, sram_wrapper_dir) 6429341e7e3Sxiaofeibao-xjtu if not os.path.exists(sram_wrapper_path): 6439341e7e3Sxiaofeibao-xjtu os.mkdir(sram_wrapper_path) 6449341e7e3Sxiaofeibao-xjtu replaced_sram = [] 6459341e7e3Sxiaofeibao-xjtu with open(sram_conf) as f: 6469341e7e3Sxiaofeibao-xjtu for line in f: 6479341e7e3Sxiaofeibao-xjtu conf = SRAMConfiguration() 6489341e7e3Sxiaofeibao-xjtu conf.from_sram_conf_entry(line) 6499341e7e3Sxiaofeibao-xjtu sim_sram_module = VModule(conf.name) 6509341e7e3Sxiaofeibao-xjtu sim_sram_path = os.path.join(out_dir, top_module, f"{conf.name}.v") 6519341e7e3Sxiaofeibao-xjtu if not os.path.exists(sim_sram_path) and module_prefix is not None: 6529341e7e3Sxiaofeibao-xjtu sim_sram_path = os.path.join(out_dir, top_module, f"{module_prefix}{conf.name}.v") 6539341e7e3Sxiaofeibao-xjtu sim_sram_module.name = f"{module_prefix}{conf.name}" 6549341e7e3Sxiaofeibao-xjtu if not os.path.exists(sim_sram_path): 6559341e7e3Sxiaofeibao-xjtu print(f"SRAM Replace: does not find {sim_sram_path}. Skipped.") 6569341e7e3Sxiaofeibao-xjtu continue 6579341e7e3Sxiaofeibao-xjtu with open(sim_sram_path, "r") as sim_f: 6589341e7e3Sxiaofeibao-xjtu sim_sram_module.add_lines(sim_f.readlines()) 6599341e7e3Sxiaofeibao-xjtu mbist_type = sim_sram_module.get_mbist_type() 6609341e7e3Sxiaofeibao-xjtu wrapper, instantiation_v = conf.get_foundry_sram_wrapper(mbist_type) 6619341e7e3Sxiaofeibao-xjtu sim_sram_module.replace_with_macro("FOUNDRY_MEM", instantiation_v) 6629341e7e3Sxiaofeibao-xjtu output_file = os.path.join(replace_sram_path, f"{sim_sram_module.name}.v") 6639341e7e3Sxiaofeibao-xjtu with open(output_file, "w") as f: 6649341e7e3Sxiaofeibao-xjtu f.writelines(sim_sram_module.get_lines()) 6659341e7e3Sxiaofeibao-xjtu # uncomment the following lines to copy the provided memory wrapper 6669341e7e3Sxiaofeibao-xjtu # wrapper_dir = "/nfs/home/share/southlake/sram_replace/mem_wrap" 6679341e7e3Sxiaofeibao-xjtu # wrapper_path = os.path.join(wrapper_dir, f"{wrapper}.v") 6689341e7e3Sxiaofeibao-xjtu # copy(wrapper_path, os.path.join(sram_wrapper_path, f"{wrapper}.v")) 6699341e7e3Sxiaofeibao-xjtu replaced_sram.append(sim_sram_module.name) 6709341e7e3Sxiaofeibao-xjtu with open(os.path.join(out_dir, f"{sram_wrapper_dir}.f"), "w") as wrapper_f: 6719341e7e3Sxiaofeibao-xjtu wrapper_f.write("// FIXME: include your SRAM wrappers here\n") 6729341e7e3Sxiaofeibao-xjtu return replace_sram_dir, [f"-F {sram_wrapper_dir}.f"] 6739341e7e3Sxiaofeibao-xjtu 6749341e7e3Sxiaofeibao-xjtu 6759341e7e3Sxiaofeibao-xjtudef replace_mbist_scan_controller(out_dir): 6769341e7e3Sxiaofeibao-xjtu target_dir = "scan_mbist_ctrl" 6779341e7e3Sxiaofeibao-xjtu target_path = os.path.join(out_dir, target_dir) 6789341e7e3Sxiaofeibao-xjtu if not os.path.exists(target_path): 6799341e7e3Sxiaofeibao-xjtu os.mkdir(target_path) 6809341e7e3Sxiaofeibao-xjtu blackbox_src_dir = "/nfs/home/share/southlake/sram_replace/scan_mbist_ctrl_rpl_rtl" 6819341e7e3Sxiaofeibao-xjtu for filename in os.listdir(blackbox_src_dir): 6829341e7e3Sxiaofeibao-xjtu if filename.startswith("bosc_") and (filename.endswith(".v") or filename.endswith(".sv")): 6839341e7e3Sxiaofeibao-xjtu copy(os.path.join(blackbox_src_dir, filename), target_path) 6849341e7e3Sxiaofeibao-xjtu with open(os.path.join(out_dir, "dfx_blackbox.f"), "w") as wrapper_f: 6859341e7e3Sxiaofeibao-xjtu wrapper_f.write("// FIXME: include your blackbox mbist/scan controllers here\n") 6869341e7e3Sxiaofeibao-xjtu return target_dir, [f"-F dfx_blackbox.f"] 6879341e7e3Sxiaofeibao-xjtu 6889341e7e3Sxiaofeibao-xjtu 6899341e7e3Sxiaofeibao-xjtuif __name__ == "__main__": 6909341e7e3Sxiaofeibao-xjtu parser = argparse.ArgumentParser(description='Verilog parser for XS') 6919341e7e3Sxiaofeibao-xjtu parser.add_argument('top', type=str, help='top-level module') 6929341e7e3Sxiaofeibao-xjtu parser.add_argument('--xs-home', type=str, help='path to XS') 6939341e7e3Sxiaofeibao-xjtu parser.add_argument('--config', type=str, default="Unknown", help='XSConfig') 6949341e7e3Sxiaofeibao-xjtu parser.add_argument('--prefix', type=str, help='module prefix') 6959341e7e3Sxiaofeibao-xjtu parser.add_argument('--ignore', type=str, default="", help='ignore modules (and their submodules)') 6969341e7e3Sxiaofeibao-xjtu parser.add_argument('--include', type=str, help='include verilog from more directories') 6979341e7e3Sxiaofeibao-xjtu parser.add_argument('--no-filelist', action='store_true', help='do not create filelist') 6989341e7e3Sxiaofeibao-xjtu parser.add_argument('--no-sram-conf', action='store_true', help='do not create sram configuration file') 6999341e7e3Sxiaofeibao-xjtu parser.add_argument('--no-sram-xlsx', action='store_true', help='do not create sram configuration xlsx') 7009341e7e3Sxiaofeibao-xjtu parser.add_argument('--with-extra-files', action='store_true', help='copy extra files') # for southlake alone 7019341e7e3Sxiaofeibao-xjtu parser.add_argument('--sram-replace', action='store_true', help='replace SRAM libraries') 7029341e7e3Sxiaofeibao-xjtu parser.add_argument('--mbist-scan-replace', action='store_true', help='replace mbist and scan controllers') # for southlake alone 7039341e7e3Sxiaofeibao-xjtu 7049341e7e3Sxiaofeibao-xjtu args = parser.parse_args() 7059341e7e3Sxiaofeibao-xjtu 7069341e7e3Sxiaofeibao-xjtu xs_home = args.xs_home 7079341e7e3Sxiaofeibao-xjtu if xs_home is None: 7089341e7e3Sxiaofeibao-xjtu xs_home = os.path.realpath(os.getenv("NOOP_HOME")) 7099341e7e3Sxiaofeibao-xjtu assert(xs_home is not None) 7109341e7e3Sxiaofeibao-xjtu build_path = os.path.join(xs_home, "build") 7119341e7e3Sxiaofeibao-xjtu files = get_files(build_path) 7129341e7e3Sxiaofeibao-xjtu if args.include is not None: 7139341e7e3Sxiaofeibao-xjtu for inc_path in args.include.split(","): 7149341e7e3Sxiaofeibao-xjtu files += get_files(inc_path) 7159341e7e3Sxiaofeibao-xjtu 7169341e7e3Sxiaofeibao-xjtu top_module = args.top 7179341e7e3Sxiaofeibao-xjtu module_prefix = args.prefix 7189341e7e3Sxiaofeibao-xjtu config = args.config 7199341e7e3Sxiaofeibao-xjtu ignore_modules = list(filter(lambda x: x != "", args.ignore.split(","))) 7209341e7e3Sxiaofeibao-xjtu if module_prefix is not None: 7219341e7e3Sxiaofeibao-xjtu top_module = f"{module_prefix}{top_module}" 7229341e7e3Sxiaofeibao-xjtu ignore_modules += list(map(lambda x: module_prefix + x, ignore_modules)) 7239341e7e3Sxiaofeibao-xjtu 7249341e7e3Sxiaofeibao-xjtu print(f"Top-level Module: {top_module} with prefix {module_prefix}") 7259341e7e3Sxiaofeibao-xjtu print(f"Config: {config}") 7269341e7e3Sxiaofeibao-xjtu print(f"Ignored modules: {ignore_modules}") 7279341e7e3Sxiaofeibao-xjtu collection, out_dir = create_verilog(files, top_module, config, try_prefix=module_prefix, ignore_modules=ignore_modules) 7289341e7e3Sxiaofeibao-xjtu assert(collection) 7299341e7e3Sxiaofeibao-xjtu 7309341e7e3Sxiaofeibao-xjtu rtl_dirs = [top_module] 7319341e7e3Sxiaofeibao-xjtu extra_filelist_lines = [] 7329341e7e3Sxiaofeibao-xjtu if args.mbist_scan_replace: 7339341e7e3Sxiaofeibao-xjtu dfx_ctrl, extra_dfx_lines = replace_mbist_scan_controller(out_dir) 7349341e7e3Sxiaofeibao-xjtu rtl_dirs = [dfx_ctrl] + rtl_dirs 7359341e7e3Sxiaofeibao-xjtu extra_filelist_lines += extra_dfx_lines 7369341e7e3Sxiaofeibao-xjtu if not args.no_filelist: 7379341e7e3Sxiaofeibao-xjtu create_filelist(top_module, out_dir, rtl_dirs, extra_filelist_lines) 7389341e7e3Sxiaofeibao-xjtu if not args.no_sram_conf: 7399341e7e3Sxiaofeibao-xjtu sram_conf = generate_sram_conf(collection, module_prefix, out_dir) 7409341e7e3Sxiaofeibao-xjtu if not args.no_sram_xlsx: 7419341e7e3Sxiaofeibao-xjtu create_sram_xlsx(out_dir, collection, sram_conf, top_module, try_prefix=module_prefix) 7429341e7e3Sxiaofeibao-xjtu if args.sram_replace: 7439341e7e3Sxiaofeibao-xjtu sram_replace_dir, sram_extra_lines = replace_sram(out_dir, sram_conf, top_module, module_prefix) 7449341e7e3Sxiaofeibao-xjtu # We create another filelist for foundry-provided SRAMs 7459341e7e3Sxiaofeibao-xjtu if not args.no_filelist: 7469341e7e3Sxiaofeibao-xjtu rtl_dirs = [sram_replace_dir] + rtl_dirs 7479341e7e3Sxiaofeibao-xjtu extra_filelist_lines += sram_extra_lines 7489341e7e3Sxiaofeibao-xjtu create_filelist(f"{top_module}_with_foundry_sram", out_dir, rtl_dirs, extra_filelist_lines) 7499341e7e3Sxiaofeibao-xjtu if args.with_extra_files: 7509341e7e3Sxiaofeibao-xjtu create_extra_files(out_dir, build_path) 751