blob: fba91324349ebec360675064582d126e375734b5 [file] [log] [blame]
emayecs14748312021-08-05 14:21:26 -04001#!/usr/bin/env python3
emayecs5966a532021-07-29 10:07:02 -04002
3# foundry_nodes.py ---
4#
5# This script runs in cloudV and discovers the set of foundry-
6# node names that are on the system and which support digital
7# synthesis. It returns the list of discovered nodes in JSON
8# data format (output to stdout).
9#
10# Note that as this runs on the cloudV server, it is written
11# in python 2.7 syntax
12
13from __future__ import print_function
14
15import os
16import re
17import sys
18import json
19import glob
20
21def print_usage():
22 print('Usage: foundry_nodes.py [all|<tag>]')
23
24if __name__ == '__main__':
25 arguments = []
26 for item in sys.argv[1:]:
27 arguments.append(item)
28
29 dolist = 'active'
30 if len(arguments) == 1:
31 dolist = arguments[0]
32 elif len(arguments) != 0:
33 print_usage()
34 sys.exit(0)
35
36 # Search the /ef/ tree and find all foundry name (root name of the
37 # directory above the foundry node name). If nothing is found,
38 # assume that this is the project name. If the project name
39 # is already set, then generate an error.
40
41 proclist = []
42
43 for procnode in glob.glob('/ef/tech/*/*/.ef-config/nodeinfo.json'):
44 try:
45 with open(procnode, 'r') as ifile:
46 process = json.load(ifile)
47 except:
48 pass
49 else:
50 nodename = process['node']
51 rootpath = os.path.split(procnode)[0]
52 techroot = os.path.realpath(rootpath + '/techdir')
53 qflowlist = glob.glob(techroot + '/libs.tech/qflow/' + nodename + '*.sh')
54
55
56 if 'status' in process:
57 status = process['status']
58 else:
59 # Default behavior is that nodes with "LEGACY" in the name
60 # are inactive, and all others are active.
61 if 'LEGACY' in nodename:
62 status = 'legacy'
63 else:
64 status = 'active'
65
66 # Do not record process nodes that do not match the status-match
67 # argument (unless the argument is "all").
68 if dolist != 'all':
69 if status != dolist:
70 continue
71
72 # Try to find available standard cell sets if they are not marked
73 # as an entry in the nodeinfo.json file. If they are an entry in nodeinfo.json,
74 # check if it is just a list of names. If so, look up each name entry and
75 # expand it into a dictionary. If it is already a dictionary, then just copy
76 # it to the output.
77 validcells = []
78 if 'stdcells' in process:
79 for name in process['stdcells'][:]:
80 if type(name) is not dict:
81 process['stdcells'].remove(name)
82 validcells.append(name)
83
84 stdcells = []
85 for qflowdefs in qflowlist:
86 stdcellname = os.path.split(qflowdefs)[1]
87 validname = os.path.splitext(stdcellname)[0]
88 if validcells == [] or validname in validcells:
89
90 stdcelldef = {}
91 stdcelldef['name'] = validname
92
93 # Read the qflow .sh file for the name of the preferred liberty format
94 # file and the name of the verilog file. Pull the path name from the
95 # verilog file since there may be other supporting files that need to
96 # be read from that path.
97
98 # Diagnostic
99 # print("Reading file " + qflowdefs, file=sys.stderr)
100 with open(qflowdefs, 'r') as ifile:
101 nodevars = ifile.read().splitlines()
102
103 try:
104 libline = next(item for item in nodevars if 'libertyfile' in item and item.strip()[0] != '#')
105 lfile = libline.split('=')[1].strip()
106 lfile = lfile.split()[0]
107 stdcelldef['libertyfile'] = lfile
108 except:
109 pass
110
111 try:
112 vlgline = next(item for item in nodevars if 'verilogfile' in item and item.strip()[0] != '#')
113 vfile = vlgline.split('=')[1].strip()
114 vfile = vfile.split()[0]
115 if os.path.exists(vfile):
116 stdcelldef['verilogpath'] = os.path.split(vfile)[0]
117 else:
118 print("Warning: bad verilogfile path " + vfile, file=sys.stderr)
119 except:
120 pass
121
122 stdcells.append(stdcelldef)
123
124 process['stdcells'] = stdcells
125 proclist.append(process)
126
127 if len(proclist) > 0:
128 json.dump(proclist, sys.stdout, indent=4)
129 else:
130 print("Error, no process nodes found!", file=sys.stderr)
131