blob: fa1f8de8f82f8dbcd1981408bc81ceb9f6ea9b21 [file] [log] [blame]
Eunchan Kim632c6f72019-09-30 11:11:51 -07001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4
5import logging as log
6from copy import deepcopy
7from pathlib import Path
8import hjson
9
10import re
11
12
13def is_ipcfg(ip: Path) -> bool: # return bool
14 log.info("IP Path: %s" % repr(ip))
15 ip_name = ip.parents[1].name
16 hjson_name = ip.name
17
18 log.info("IP Name(%s) and HJSON name (%s)" % (ip_name, hjson_name))
19
20 if ip_name + ".hjson" == hjson_name or ip_name + "_reg.hjson" == hjson_name:
21 return True
22 return False
23
24
25def search_ips(ip_path): # return list of config files
Philipp Wagner14a3fee2019-11-21 10:07:02 +000026 # list the every Hjson file
Tobias Wölfel4c5fbec2019-10-23 12:43:17 +020027 p = ip_path.glob('*/data/*.hjson')
Eunchan Kim632c6f72019-09-30 11:11:51 -070028
Tobias Wölfel4c5fbec2019-10-23 12:43:17 +020029 # filter only ip_name/data/ip_name{_reg|''}.hjson
Eunchan Kim632c6f72019-09-30 11:11:51 -070030 ips = [x for x in p if is_ipcfg(x)]
31
32 log.info("Filtered-in IP files: %s" % repr(ips))
33 return ips
34
35
36def is_xbarcfg(xbar_obj):
37 if "type" in xbar_obj and xbar_obj["type"] == "xbar":
38 return True
39
40 return False
41
42
43def get_hjsonobj_xbars(xbar_path):
Philipp Wagner14a3fee2019-11-21 10:07:02 +000044 """ Search crossbars Hjson files from given path.
Eunchan Kim632c6f72019-09-30 11:11:51 -070045
Philipp Wagner14a3fee2019-11-21 10:07:02 +000046 Search every Hjson in the directory and check Hjson type.
Eunchan Kim632c6f72019-09-30 11:11:51 -070047 It could be type: "top" or type: "xbar"
48 returns [(name, obj), ... ]
49 """
50 p = xbar_path.glob('*.hjson')
51 try:
52 xbar_objs = [hjson.load(x.open('r'), use_decimal=True) for x in p]
53 except ValueError:
54 raise Systemexit(sys.exc_info()[1])
55
56 xbar_objs = [x for x in xbar_objs if is_xbarcfg(x)]
57
58 return xbar_objs
59
60
61def get_module_by_name(top, name):
62 """Search in top["module"] by name
63 """
64 module = None
65 for m in top["module"]:
66 if m["name"] == name:
67 module = m
68 break
69
70 return module
71
72
73def get_signal_by_name(module, name):
74 """Return the signal struct with the type input/output/inout
75 """
76 result = None
77 for s in module["available_input_list"] + module[
78 "available_output_list"] + module["available_inout_list"]:
79 if s["name"] == name:
80 result = s
81 break
82
83 return result
84
85
86def add_prefix_to_signal(signal, prefix):
87 """Add prefix to module signal format { name: "sig_name", width: NN }
88 """
89 result = deepcopy(signal)
90
91 if not "name" in signal:
92 raise SystemExit("signal {} doesn't have name field".format(signal))
93
94 result["name"] = prefix + "_" + signal["name"]
95
96 return result
97
98
99def get_ms_name(name):
100 """Split module_name.signal_name to module_name , signal_name
101 """
102
103 tokens = name.split('.')
104
105 if len(tokens) == 0:
106 raise SystemExit("This to be catched in validate.py")
107
108 module = tokens[0]
109 signal = None
110 if len(tokens) == 2:
111 signal = tokens[1]
112
113 return module, signal
114
115
116def parse_pad_field(padstr):
117 """Parse PadName[NN...NN] or PadName[NN] or just PadName
118 """
119 match = re.match(r'^([A-Za-z0-9_]+)(\[([0-9]+)(\.\.([0-9]+))?\]|)', padstr)
120 return match.group(1), match.group(3), match.group(5)
121
122
123def get_pad_list(padstr):
124 pads = []
125
126 pad, first, last = parse_pad_field(padstr)
127 if first is None:
128 first = 0
129 last = 0
130 elif last is None:
131 last = first
132 first = int(first, 0)
133 last = int(last, 0)
134 width = first - last + 1
135
136 for p in range(first, last + 1):
137 pads.append({"name": pad, "index": p})
138
139 return pads
Eunchan Kim436d2242019-10-29 17:25:51 -0700140
141
142# Template functions
143def ljust(x, width):
144 return "{:<{width}}".format(x, width=width)
145
146
147def bitarray(d, width):
148 """Print Systemverilog bit array
149
150 @param d the bit width of the signal
151 @param width max character width of the signal group
152
153 For instance, if width is 4, the max d value in the signal group could be
154 9999. If d is 2, then this function pads 3 spaces at the end of the bit
155 slice.
156
157 "[1:0] " <- d:=2, width=4
158 "[9999:0]" <- max d-1 value
159
160 If d is 1, it means array slice isn't necessary. So it returns empty spaces
161 """
162
163 if d <= 0:
164 log.error("lib.bitarray: Given value {} is smaller than 1".format(d))
165 raise ValueError
166 if d == 1:
167 return " " * (width + 4) # [x:0] needs 4 more space than char_width
168
169 out = "[{}:0]".format(d - 1)
170 return out + (" " * (width - len(str(d))))
171
172
173def parameterize(text):
174 """Return the value wrapping with quote if not integer nor bits
175 """
176 if re.match('(\d+\'[hdb]\s*[0-9a-f_A-F]+|[0-9]+)', text) == None:
177 return "\"{}\"".format(text)
178
179 return text