forked from BerkeleyLab/Bedrock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcollect_clients.py
112 lines (100 loc) · 3.82 KB
/
collect_clients.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# Parses one Verilog file per client, and creates rtefi_preblob.vh
# that will define the instantiation and I/O port routing of the final
# rtefi_blob.v.
#
# The fundamental bug with this program is that it's
# based on text patterns, not semantics.
# At least it doesn't use magic comments!
from sys import argv
import re
xlist = []
params = []
def handle_port(plist, x2list, ptype, name, ix):
special_list = {'clk': 1, 'len_c': 1, 'idata': 1,
'raw_l': 1, 'raw_s': 1, 'odata': 1}
ename = name
if name not in special_list:
ename = "p%d_%s" % (ix, name)
# print("adding to x2list: %s, %s" % (ptype, ename))
x2list += [(ptype, ename)]
if name == "raw_l" or name == "raw_s":
ename = "%s[%d]" % (name, ix-1)
if name == "odata":
ename = "%s_p%d" % (name, ix)
plist += [".%s(%s)" % (name, ename)]
def map_params(ix, spec, params):
# print("// map_params(%d, %s ..)" % (ix, spec))
prefix = "p%d_" % ix
# Define a function to be used as repl argument to re.sub()
# Ideally we'd not try to process the leading input / output string
def param_replace(matchobj):
m = matchobj.group(0)
# print(m)
return prefix+m if m in params else m
ss = re.sub(r'([a-zA-Z]\w*)', param_replace, spec)
# print("// After: %s" % ss)
return ss
# regexps for I/O ports, with and without a specified width
# It would be cool if we could also propagate comments
# associated with ports and parameters.
PORT_N = r'^\s*,?(input|output|inout)\s+(signed)?\s*(\[[^]]+\])\s*(\w+)'
PORT_0 = r'^\s*,?(input|output|inout)\s+(signed)?\s*(\w+)'
PARAM = r'^\s*,?parameter\s+(\w+)\s*=\s*(\d+)'
def file_grab(fname, ix):
plist = []
x2list = []
global xlist
global params
param_map = []
param_set = [".n_lat(n_lat)"]
with open(fname, 'r') as f:
for li in f.read().split('\n'):
if li == "":
continue
# print(l)
m = re.search(PORT_N, li)
if m:
ll = [m.group(jx) for jx in [1, 2, 3]]
p = " ".join([x if x is not None else "" for x in ll])
handle_port(plist, x2list, p, m.group(4), ix)
m = re.search(PORT_0, li)
if m:
ll = [m.group(jx) for jx in [1, 2]]
p = " ".join([x if x is not None else "" for x in ll])
handle_port(plist, x2list, p, m.group(3), ix)
m = re.search(PARAM, li)
if m and m.group(1) != "n_lat":
pn = m.group(1)
pv = m.group(2)
params += ["parameter p%d_%s = %s;" % (ix, pn, pv)]
param_set += [".%s(p%d_%s)" % (pn, ix, pn)]
param_map += [pn]
for p_spec, p_name in x2list:
p_spec2 = map_params(ix, p_spec, param_map)
xlist += ['\t%s %s,' % (p_spec2, p_name)]
# Generate the module name from the file name;
# directories and .v suffixes aren't kept.
# print("// Finalizing %s" % fname)
# print(plist)
mod_name = fname.split('/')[-1]
mod_name = mod_name.split('.')[0]
param_sets = ", ".join(param_set)
ss = "%s #(%s) p%d_client(" % (mod_name, param_sets, ix)
ss += ", ".join(plist)
ss += ");"
return ss
ss = []
n_used = len(argv)-1
print("// This Verilog include file was machine-generated by {}".format(__file__))
for ix, fname in enumerate(argv[1:]):
print("// %d %s" % (ix+1, fname))
ss += [file_grab(fname, ix+1)]
print("// filling in unused UDP ports starting at %d" % (n_used+1))
for ix in range(n_used+1, 8):
ss += ["assign odata_p%d = 8'h%2x;" % (ix, 48+ix)]
print("`define BLOB_INSTANCES \\")
print("\\\n".join(ss))
print("`define BLOB_PORTS \\")
print("\\\n".join(xlist))
print("`define BLOB_PARAMS \\")
print("\\\n".join(params))