blob: 157dd761791c59e7faa0ec121432d8a92aa284e3 [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
Eunchan Kim632c6f72019-09-30 11:11:51 -07004import logging as log
Timothy Chen80bd8aa2019-10-04 15:57:11 -07005from enum import Enum
Eunchan Kim6a4b49e2020-02-18 10:33:39 -08006from collections import OrderedDict
lowRISC Contributors802543a2019-08-31 12:12:56 +01007
Timothy Chen0550d692020-04-20 17:19:35 -07008from reggen.validate import check_keys
Timothy Chen80bd8aa2019-10-04 15:57:11 -07009
Eunchan Kim632c6f72019-09-30 11:11:51 -070010# For the reference
11# val_types = {
12# 'd': ["int", "integer (binary 0b, octal 0o, decimal, hex 0x)"],
13# 'x': ["xint", "x for undefined otherwise int"],
14# 'b': [
15# "bitrange", "bit number as decimal integer, \
16# or bit-range as decimal integers msb:lsb"
17# ],
18# 'l': ["list", "comma separated list enclosed in `[]`"],
19# 'ln': ["name list", 'comma separated list enclosed in `[]` of '\
20# 'one or more groups that have just name and dscr keys.'\
21# ' e.g. `{ name: "name", desc: "description"}`'],
22# 'lnw': ["name list+", 'name list that optionally contains a width'],
23# 'lp': ["parameter list", 'parameter list having default value optionally'],
24# 'g': ["group", "comma separated group of key:value enclosed in `{}`"],
25# 's': ["string", "string, typically short"],
26# 't': ["text", "string, may be multi-line enclosed in `'''` "\
27# "may use `**bold**`, `*italic*` or `!!Reg` markup"],
28# 'T': ["tuple", "tuple enclosed in ()"],
Philipp Wagner14a3fee2019-11-21 10:07:02 +000029# 'pi': ["python int", "Native Python type int (generated)"],
30# 'pb': ["python Bool", "Native Python type Bool (generated)"],
31# 'pl': ["python list", "Native Python type list (generated)"],
32# 'pe': ["python enum", "Native Python type enum (generated)"]
Eunchan Kim632c6f72019-09-30 11:11:51 -070033# }
34
35# Required/optional field in top hjson
36top_required = {
37 'name': ['s', 'Top name'],
38 'type': ['s', 'type of hjson. Shall be "top" always'],
Timothy Chen0550d692020-04-20 17:19:35 -070039 'clocks': ['g', 'group of clock properties'],
40 'resets': ['l', 'list of resets'],
Eunchan Kim632c6f72019-09-30 11:11:51 -070041 'module': ['l', 'list of modules to instantiate'],
42 'memory': [
43 'l', 'list of memories. At least one memory is needed to run \
44 the software'
45 ],
46 'debug_mem_base_addr':
47 ['d', 'Base address of RV_DM. Planned to move to \
48module'],
49 'xbar': ['l', 'List of the xbar used in the top'],
50}
51
52top_optional = {
Eunchan Kim1cf66af2020-04-30 11:31:53 -070053 'interrupt_module': ['l', 'list of the modules that connects to rv_plic'],
Eunchan Kim632c6f72019-09-30 11:11:51 -070054 'interrupt': ['lnw', 'interrupts (generated)'],
Eunchan Kim1cf66af2020-04-30 11:31:53 -070055 'alert_module':
Eunchan Kim6a4b49e2020-02-18 10:33:39 -080056 ['l', 'list of the modules that connects to alert_handler'],
Michael Schaffner666dde12019-10-25 11:57:54 -070057 'alert': ['lnw', 'alerts (generated)'],
58 'alert_async': ['l', 'async alerts (generated)'],
Eunchan Kim632c6f72019-09-30 11:11:51 -070059 'pinmux': ['g', 'pinmux definition if doesn\'t exist, tool uses defaults'],
60 'padctrl':
61 ['g', 'PADS instantiation, if doesn\'t exist, tool creates direct output'],
Eunchan Kim91b58ba2020-04-07 08:19:54 -070062 'inter_module': ['g', 'define the signal connections between the modules'],
Eunchan Kim1cf66af2020-04-30 11:31:53 -070063 'num_cores': ['pn', "number of computing units"],
64 'datawidth': ['pn', "default data width"],
Eunchan Kim632c6f72019-09-30 11:11:51 -070065}
66
67top_added = {}
68
69pinmux_required = {}
70pinmux_optional = {
Eunchan Kim529134b2020-04-24 09:51:06 -070071 'num_mio': [
72 'd', 'Number of Multiplexed IOs'
73 ' If padctrl is used, this value will be replaced with #pads'
74 ' - #DIO'
75 ],
Eunchan Kim436d2242019-10-29 17:25:51 -070076 'dio_modules': ['l', 'List of Dedicated IOs.'],
77 'mio_modules': ['l', 'List of Multiplexed IPs/IOs'],
78 'nc_modules': ['l', 'List of NotConnected IOs'],
Eunchan Kim632c6f72019-09-30 11:11:51 -070079}
80pinmux_added = {
81 'inputs': ['l', 'Full list of SoC inputs, `module_name.sig_name`'],
82 'outputs': ['l', 'Full list of SoC outputs, `module_name.sig_name`'],
83}
84
85padctrl_required = {}
86padctrl_optional = {
87 'pads': ['l', 'List of pads'],
88 'attr_default': ['l', 'List of the attribute']
89}
90padctrl_added = {}
91
Timothy Chen33b3b9d2020-05-08 10:14:17 -070092clock_srcs_required = {
93 'name': ['s', 'name of clock group'],
Timothy Chena4cc10d2020-05-08 16:06:20 -070094 'aon': ['s', 'yes, no. aon attribute of a clock'],
Timothy Chen33b3b9d2020-05-08 10:14:17 -070095 'freq': ['s', 'frequency of clock in Hz'],
96}
97
Timothy Chenfa851de2020-08-27 17:10:37 -070098clock_srcs_optional = {
99 'derived': ['s', 'whether clock is derived'],
100 'params': ['s', 'extra clock parameters']
101}
102
Timothy Chenb63f3b82020-06-30 17:10:57 -0700103derived_clock_srcs_required = {
104 'name': ['s', 'name of clock group'],
105 'aon': ['s', 'yes, no. aon attribute of a clock'],
106 'freq': ['s', 'frequency of clock in Hz'],
107 'src': ['s', 'source clock'],
108 'div': ['d', 'ratio between source clock and derived clock'],
109}
110
Timothy Chen0550d692020-04-20 17:19:35 -0700111clock_groups_required = {
112 'name': ['s', 'name of clock group'],
Timothy Chenf56c1b52020-04-28 17:00:43 -0700113 'src': ['s', 'yes, no. This clock group is directly from source'],
Timothy Chen0550d692020-04-20 17:19:35 -0700114 'sw_cg': ['s', 'yes, no, hint. Software clock gate attributes'],
115}
116clock_groups_optional = {
117 'unique': ['s', 'whether clocks in the group are unique'],
118 'clocks': ['g', 'groups of clock name to source'],
119}
120clock_groups_added = {}
121
Timothy Chen1daf5822020-10-26 17:28:15 -0700122eflash_required = {
123 'banks': ['d', 'number of flash banks'],
124 'pages_per_bank': ['d', 'number of data pages per flash bank'],
125 'clock_srcs': ['g', 'clock connections'],
126 'clock_group': ['s', 'associated clock attribute group'],
127 'reset_connections': ['g', 'reset connections'],
128 'type': ['s', 'type of memory'],
129 'base_addr': ['s', 'strarting hex address of memory'],
130 'swaccess': ['s', 'software accessibility'],
131 'inter_signal_list': ['lg', 'intersignal list']
132}
133
134eflash_optional = {}
135
136eflash_added = {}
137
Eunchan Kim632c6f72019-09-30 11:11:51 -0700138
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700139class TargetType(Enum):
140 MODULE = "module"
141 XBAR = "xbar"
142
143
144class Target:
145 """Target class informs the checkers if we are validating a module or xbar
146 """
147
148 # The type of this target
149 target_type = ""
150
151 # The key to search against
152 key = ""
153
154 def __init__(self, target_type):
155 self.target_type = target_type
156 if target_type == TargetType.MODULE:
157 self.key = "type"
158 else:
159 self.key = "name"
160
161
Timothy Chen1daf5822020-10-26 17:28:15 -0700162class Flash:
163 """Flash class contains information regarding parameter defaults.
164 For now, only expose banks / pages_per_bank for user configuration.
165 For now, also enforce power of 2 requiremnt.
166 """
167 max_banks = 4
168 max_pages_per_bank = 1024
169
170 def __init__(self, banks, pages_per_bank):
171 self.banks = banks
172 self.pages_per_bank = pages_per_bank
173 self.words_per_page = 128
174 self.data_width = 64
175 self.metadata_width = 12
176 self.info_types = 2
177 self.infos_per_bank = [4, 4]
178
179 def is_pow2(self, n):
180 return (n != 0) and (n & (n - 1) == 0)
181
182 def check_values(self):
183 pow2_check = self.is_pow2(self.banks) and self.is_pow2(self.pages_per_bank)
184 limit_check = (self.banks <= Flash.max_banks) \
185 and (self.pages_per_bank <= Flash.max_pages_per_bank)
186
187 return pow2_check and limit_check
188
189 def calc_size(self):
190 word_bytes = self.data_width / 8
191 bytes_per_page = word_bytes * self.words_per_page
192 bytes_per_bank = bytes_per_page * self.pages_per_bank
193 return bytes_per_bank * self.banks
194
195 def populate(self, mem):
196 mem['words_per_page'] = self.words_per_page
197 mem['data_width'] = self.data_width
198 mem['metadata_width'] = self.metadata_width
199 mem['info_types'] = self.info_types
200 mem['infos_per_bank'] = self.infos_per_bank
201 mem['size'] = hex(int(self.calc_size()))
202
203
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700204# Check to see if each module/xbar defined in top.hjson exists as ip/xbar.hjson
205# Also check to make sure there are not multiple definitions of ip/xbar.hjson for each
206# top level definition
207# If it does, return a dictionary of instance names to index in ip/xbarobjs
208def check_target(top, objs, tgtobj):
209 error = 0
Eunchan Kim6a4b49e2020-02-18 10:33:39 -0800210 idxs = OrderedDict()
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700211
212 for i in range(len(objs)):
213 log.info("%d Order is %s" % (i, objs[i]['name'].lower()))
214
215 tgt_type = tgtobj.target_type.value
216 inst_key = tgtobj.key
217
218 for cfg in top[tgt_type]:
219 cfg_name = cfg['name'].lower()
220 log.info("Checking target %s %s" % (tgt_type, cfg_name))
221 tgt_def = [o for o in objs if cfg[inst_key] == o['name'].lower()]
222 error += check_def(tgt_def, cfg_name)
223 if error:
224 log.error("Target existence check failed")
225 break
226 else:
227 idxs[cfg_name] = objs.index(tgt_def[0])
228
229 log.info("Current state %s" % idxs)
230 return error, idxs
231
232
Eunchan Kim632c6f72019-09-30 11:11:51 -0700233def check_padctrl(top, prefix):
234 error = check_keys(top["padctrl"], padctrl_required, padctrl_optional,
235 padctrl_added, prefix + " PadControl")
236 return error
237
238
239def check_pinmux(top, prefix):
240 return 0
241
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700242
Timothy Chen0550d692020-04-20 17:19:35 -0700243# check for inconsistent clock group definitions
244def check_clock_groups(top):
245
246 # default empty assignment
247 if "groups" not in top['clocks']:
248 top['clocks']['groups'] = []
249
250 error = 0
251 for group in top['clocks']['groups']:
252 error = check_keys(group, clock_groups_required, clock_groups_optional,
253 clock_groups_added, "Clock Groups")
254
255 # Check sw_cg values are valid
256 if group['sw_cg'] not in ['yes', 'no', 'hint']:
Eunchan Kim529134b2020-04-24 09:51:06 -0700257 log.error("Incorrect attribute for sw_cg: {}".format(
258 group['sw_cg']))
Timothy Chen0550d692020-04-20 17:19:35 -0700259 error += 1
260
Timothy Chenf56c1b52020-04-28 17:00:43 -0700261 # Check combination of src and sw are valid
Timothy Chena4cc10d2020-05-08 16:06:20 -0700262 if group['src'] == 'yes' and group['sw_cg'] != 'no':
Timothy Chenf56c1b52020-04-28 17:00:43 -0700263 log.error("Invalid combination of src and sw_cg: {} and {}".format(
264 group['src'], group['sw_cg']))
265 error += 1
266
Timothy Chen0550d692020-04-20 17:19:35 -0700267 # Check combination of sw_cg and unique are valid
268 unique = group['unique'] if 'unique' in group else 'no'
269 if group['sw_cg'] == 'no' and unique != 'no':
Eunchan Kim529134b2020-04-24 09:51:06 -0700270 log.error(
271 "Incorrect attribute combination. When sw_cg is no, unique must be no"
272 )
Timothy Chen0550d692020-04-20 17:19:35 -0700273 error += 1
274
275 if error:
276 break
277
278 return error
279
Eunchan Kim529134b2020-04-24 09:51:06 -0700280
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700281def check_clocks_resets(top, ipobjs, ip_idxs, xbarobjs, xbar_idxs):
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700282
Timothy Chenb63f3b82020-06-30 17:10:57 -0700283 error = 0
284
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700285 # check clock fields are all there
Timothy Chenb63f3b82020-06-30 17:10:57 -0700286 ext_srcs = []
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700287 for src in top['clocks']['srcs']:
Timothy Chenfa851de2020-08-27 17:10:37 -0700288 check_keys(src, clock_srcs_required, clock_srcs_optional, {}, "Clock source")
Timothy Chenb63f3b82020-06-30 17:10:57 -0700289 ext_srcs.append(src['name'])
290
291 # check derived clock sources
292 log.info("Collected clocks are {}".format(ext_srcs))
293 for src in top['clocks']['derived_srcs']:
294 check_keys(src, derived_clock_srcs_required, {}, {}, "Derived clocks")
295 try:
296 ext_srcs.index(src['src'])
297 except Exception:
298 error += 1
299 log.error("{} is not a valid src for {}".format(src['src'], src['name']))
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700300
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700301 # all defined clock/reset nets
Timothy Chenc6233932020-08-19 15:34:07 -0700302 reset_nets = [reset['name'] for reset in top['resets']['nodes']]
Timothy Chenb63f3b82020-06-30 17:10:57 -0700303 clock_srcs = [clock['name'] for clock in top['clocks']['srcs'] +
304 top['clocks']['derived_srcs']]
Eunchan Kim632c6f72019-09-30 11:11:51 -0700305
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700306 # Check clock/reset port connection for all IPs
Timothy Chen3193b002019-10-04 16:56:05 -0700307 for ipcfg in top['module']:
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700308 ipcfg_name = ipcfg['name'].lower()
309 log.info("Checking clock/resets for %s" % ipcfg_name)
310 error += validate_reset(ipcfg, ipobjs[ip_idxs[ipcfg_name]], reset_nets)
Timothy Chen0550d692020-04-20 17:19:35 -0700311 error += validate_clock(ipcfg, ipobjs[ip_idxs[ipcfg_name]], clock_srcs)
Timothy Chen3193b002019-10-04 16:56:05 -0700312
313 if error:
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700314 log.error("module clock/reset checking failed")
Timothy Chen3193b002019-10-04 16:56:05 -0700315 break
316
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700317 # Check clock/reset port connection for all xbars
Timothy Chen3193b002019-10-04 16:56:05 -0700318 for xbarcfg in top['xbar']:
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700319 xbarcfg_name = xbarcfg['name'].lower()
320 log.info("Checking clock/resets for xbar %s" % xbarcfg_name)
321 error += validate_reset(xbarcfg, xbarobjs[xbar_idxs[xbarcfg_name]],
322 reset_nets, "xbar")
323 error += validate_clock(xbarcfg, xbarobjs[xbar_idxs[xbarcfg_name]],
Timothy Chen0550d692020-04-20 17:19:35 -0700324 clock_srcs, "xbar")
Timothy Chen3193b002019-10-04 16:56:05 -0700325
326 if error:
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700327 log.error("xbar clock/reset checking failed")
Timothy Chen3193b002019-10-04 16:56:05 -0700328 break
329
330 return error
331
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700332
333def check_def(inst_def, name):
Timothy Chen3193b002019-10-04 16:56:05 -0700334 error = 0
335 if not inst_def:
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700336 log.error("Could not find %s.hjson" % name)
Timothy Chen3193b002019-10-04 16:56:05 -0700337 error += 1
338
339 if len(inst_def) > 1:
340 log.error("Duplicate %s.hjson" % name)
341 error += 1
342
343 return error
344
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700345
Timothy Chen3193b002019-10-04 16:56:05 -0700346# Checks the following
347# For each defined reset connection in top*.hjson, there exists a defined port at the destination
348# and defined reset net
349# There are the same number of defined connections as there are ports
350def validate_reset(top, inst, reset_nets, prefix=""):
351 # Gather inst port list
352 error = 0
353 inst_port_list = []
354 if 'reset_primary' not in inst.keys():
355 log.info("%s %s does not have a reset_primary defined, default used" %
356 (prefix, inst['name']))
357 inst_port_list.append("rst_ni")
358 else:
359 inst_port_list.append(inst['reset_primary'])
360
361 if 'other_reset_list' in inst.keys():
362 inst_port_list.extend(inst['other_reset_list'])
363 log.info("%s %s resets are %s" %
364 (prefix, inst['name'].lower(), inst_port_list))
365
366 if len(top['reset_connections'].keys()) != len(inst_port_list):
367 error += 1
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700368 log.error("%s %s mismatched number of reset ports and nets" %
Timothy Chen3193b002019-10-04 16:56:05 -0700369 (prefix, inst['name']))
370
371 missing_port = [
372 port for port in top['reset_connections'].keys()
373 if port not in inst_port_list
374 ]
375
376 if missing_port:
377 error += 1
378 log.error("%s %s Following reset ports do not exist:" %
379 (prefix, inst['name']))
380 [log.error("%s" % port) for port in missing_port]
381
382 missing_net = [
383 net for port, net in top['reset_connections'].items()
384 if net not in reset_nets
385 ]
386
387 if missing_net:
388 error += 1
389 log.error("%s %s Following reset nets do not exist:" %
390 (prefix, inst['name']))
391 [log.error("%s" % net) for net in missing_net]
392
393 return error
394
395
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700396# Checks the following
Timothy Chen0550d692020-04-20 17:19:35 -0700397# For each defined clock_src in top*.hjson, there exists a defined port at the destination
398# and defined clock source
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700399# There are the same number of defined connections as there are ports
Timothy Chen0550d692020-04-20 17:19:35 -0700400def validate_clock(top, inst, clock_srcs, prefix=""):
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700401 # Gather inst port list
402 error = 0
403 inst_port_list = []
404 if 'clock_primary' not in inst.keys():
405 log.info("%s %s does not have a clock_primary defined, default used" %
406 (prefix, inst['name']))
407 inst_port_list.append("clk_i")
408 else:
409 inst_port_list.append(inst['clock_primary'])
410
411 if 'other_clock_list' in inst.keys():
412 inst_port_list.extend(inst['other_clock_list'])
413 log.info("%s %s clocks are %s" %
414 (prefix, inst['name'].lower(), inst_port_list))
415
Timothy Chen0550d692020-04-20 17:19:35 -0700416 if len(top['clock_srcs'].keys()) != len(inst_port_list):
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700417 error += 1
418 log.error("%s %s mismatched number of clock ports and nets" %
419 (prefix, inst['name']))
420
421 missing_port = [
Eunchan Kim529134b2020-04-24 09:51:06 -0700422 port for port in top['clock_srcs'].keys() if port not in inst_port_list
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700423 ]
424
425 if missing_port:
426 error += 1
427 log.error("%s %s Following clock ports do not exist:" %
428 (prefix, inst['name']))
429 [log.error("%s" % port) for port in missing_port]
430
431 missing_net = [
Eunchan Kim529134b2020-04-24 09:51:06 -0700432 net for port, net in top['clock_srcs'].items() if net not in clock_srcs
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700433 ]
434
435 if missing_net:
436 error += 1
437 log.error("%s %s Following clock nets do not exist:" %
438 (prefix, inst['name']))
439 [log.error("%s" % net) for net in missing_net]
440
441 return error
442
443
Timothy Chen1daf5822020-10-26 17:28:15 -0700444def check_flash(top):
445 error = 0
446
447 for mem in top['memory']:
448 if mem['type'] == "eflash":
449 error = check_keys(mem, eflash_required, eflash_optional,
450 eflash_added, "Eflash")
451
452 flash = Flash(mem['banks'], mem['pages_per_bank'])
453 error += 1 if not flash.check_values() else 0
454
455 if error:
456 log.error("Flash check failed")
457 else:
458 flash.populate(mem)
459
460 return error
461
462
Timothy Chen3193b002019-10-04 16:56:05 -0700463def validate_top(top, ipobjs, xbarobjs):
lowRISC Contributors802543a2019-08-31 12:12:56 +0100464 # return as it is for now
Eunchan Kim632c6f72019-09-30 11:11:51 -0700465 error = check_keys(top, top_required, top_optional, top_added, "top")
466
467 if error != 0:
468 log.error("Top HJSON has top level errors. Aborting")
469 return top, error
470
471 component = top['name']
472
Eunchan Kim529134b2020-04-24 09:51:06 -0700473 # MODULE check
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700474 err, ip_idxs = check_target(top, ipobjs, Target(TargetType.MODULE))
475 error += err
476
Eunchan Kim529134b2020-04-24 09:51:06 -0700477 # XBAR check
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700478 err, xbar_idxs = check_target(top, xbarobjs, Target(TargetType.XBAR))
479 error += err
Eunchan Kim632c6f72019-09-30 11:11:51 -0700480
Eunchan Kim529134b2020-04-24 09:51:06 -0700481 # MEMORY check
Timothy Chen1daf5822020-10-26 17:28:15 -0700482 error += check_flash(top)
Eunchan Kim632c6f72019-09-30 11:11:51 -0700483
Eunchan Kim529134b2020-04-24 09:51:06 -0700484 # Clock / Reset check
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700485 error += check_clocks_resets(top, ipobjs, ip_idxs, xbarobjs, xbar_idxs)
486
Eunchan Kim529134b2020-04-24 09:51:06 -0700487 # Clock group check
Timothy Chen0550d692020-04-20 17:19:35 -0700488 error += check_clock_groups(top)
489
Eunchan Kim529134b2020-04-24 09:51:06 -0700490 # RV_PLIC check
Eunchan Kim632c6f72019-09-30 11:11:51 -0700491
Eunchan Kim529134b2020-04-24 09:51:06 -0700492 # PINMUX & PADS check
493 if "padctrl" not in top:
Eunchan Kim632c6f72019-09-30 11:11:51 -0700494 log.warning("padsctrl field doesn't exist in top. Skipping pads \
495 generation. Top input/output are directly connected from \
496 peripherals.")
497 # Pads configuration check
498 else:
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700499 error += check_padctrl(top, component)
Eunchan Kim632c6f72019-09-30 11:11:51 -0700500
Eunchan Kim529134b2020-04-24 09:51:06 -0700501 if "pinmux" not in top:
Eunchan Kim632c6f72019-09-30 11:11:51 -0700502 log.warning("Top {} has no 'pinmux' field. Please consider specifying \
503 pinmux and pads configuration")
Eunchan Kim6a4b49e2020-02-18 10:33:39 -0800504 top["pinmux"] = OrderedDict()
Eunchan Kim632c6f72019-09-30 11:11:51 -0700505 # checking pinmux after pads as dio connects to PAD
506
507 error += check_pinmux(top, component)
508
Eunchan Kim632c6f72019-09-30 11:11:51 -0700509 return top, error