blob: 3f322d6cc66c87eedb4f623983941ad38d5f8ca1 [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
4"""
Philipp Wagner14a3fee2019-11-21 10:07:02 +00005Register JSON validation
lowRISC Contributors802543a2019-08-31 12:12:56 +01006"""
7
8import logging as log
Rupert Swarbrick0f6eeaf2021-05-28 15:24:14 +01009from typing import Dict, List, Tuple, Union
lowRISC Contributors802543a2019-08-31 12:12:56 +010010
11
12# validating version of int(x, 0)
13# returns int value, error flag
14# if error flag is True value will be zero
Rupert Swarbrick0f6eeaf2021-05-28 15:24:14 +010015def check_int(x: Union[int, str],
16 err_prefix: str,
17 suppress_err_msg: bool = False) -> Tuple[int, bool]:
lowRISC Contributors802543a2019-08-31 12:12:56 +010018 if isinstance(x, int):
19 return x, False
20 if x[0] == '0' and len(x) > 2:
21 if x[1] in 'bB':
22 validch = '01'
23 elif x[1] in 'oO':
24 validch = '01234567'
25 elif x[1] in 'xX':
26 validch = '0123456789abcdefABCDEF'
27 else:
Michael Schaffner1b4744e2020-04-10 14:59:58 -070028 if not suppress_err_msg:
29 log.error(err_prefix +
30 ": int must start digit, 0b, 0B, 0o, 0O, 0x or 0X")
lowRISC Contributors802543a2019-08-31 12:12:56 +010031 return 0, True
32 for c in x[2:]:
Eunchan Kim0bd75662020-04-24 10:21:18 -070033 if c not in validch:
Michael Schaffner1b4744e2020-04-10 14:59:58 -070034 if not suppress_err_msg:
35 log.error(err_prefix + ": Bad character " + c + " in " + x)
lowRISC Contributors802543a2019-08-31 12:12:56 +010036 return 0, True
37 else:
38 if not x.isdecimal():
Michael Schaffner1b4744e2020-04-10 14:59:58 -070039 if not suppress_err_msg:
40 log.error(err_prefix + ": Number not valid int " + x)
41 return 0, True
lowRISC Contributors802543a2019-08-31 12:12:56 +010042 return int(x, 0), False
43
44
Rupert Swarbrick0f6eeaf2021-05-28 15:24:14 +010045def check_bool(x: Union[bool, str], err_prefix: str) -> Tuple[bool, bool]:
lowRISC Contributors802543a2019-08-31 12:12:56 +010046 """check_bool checks if input 'x' is one of the list:
47 "true", "false"
48
49 It returns value as Bool type and Error condition.
50 """
51 if isinstance(x, bool):
52 # if Bool returns as it is
53 return x, False
54 if not x.lower() in ["true", "false"]:
55 log.error(err_prefix + ": Bad field value " + x)
56 return False, True
57 else:
58 return (x.lower() == "true"), False
59
60
Rupert Swarbrick0f6eeaf2021-05-28 15:24:14 +010061def check_ln(obj: Dict[str, object],
62 x: str,
63 withwidth: bool,
64 err_prefix: str) -> int:
lowRISC Contributors802543a2019-08-31 12:12:56 +010065 error = 0
Rupert Swarbrick0f6eeaf2021-05-28 15:24:14 +010066 entry = obj[x]
67 if not isinstance(entry, list):
lowRISC Contributors802543a2019-08-31 12:12:56 +010068 log.error(err_prefix + ' element ' + x + ' not a list')
69 return 1
Rupert Swarbrick0f6eeaf2021-05-28 15:24:14 +010070
71 for y in entry:
lowRISC Contributors802543a2019-08-31 12:12:56 +010072 error += check_keys(y, ln_required, ln_optional if withwidth else {},
73 {}, err_prefix + ' element ' + x)
74 if withwidth:
75 if 'width' in y:
76 w, err = check_int(y['width'], err_prefix + ' width in ' + x)
77 if err:
78 error += 1
79 w = 1
80 else:
81 w = 1
82 y['width'] = str(w)
83
84 return error
85
86
Rupert Swarbrick0f6eeaf2021-05-28 15:24:14 +010087def check_keys(obj: Dict[str, object],
88 required_keys: Dict[str, List[str]],
89 optional_keys: Dict[str, List[str]],
90 added_keys: Dict[str, List[str]],
91 err_prefix: str) -> int:
lowRISC Contributors802543a2019-08-31 12:12:56 +010092 error = 0
93 for x in required_keys:
Eunchan Kim0bd75662020-04-24 10:21:18 -070094 if x not in obj:
lowRISC Contributors802543a2019-08-31 12:12:56 +010095 error += 1
96 log.error(err_prefix + " missing required key " + x)
97 for x in obj:
Rupert Swarbrickc02b52f2020-10-07 15:34:16 +010098 type = None
lowRISC Contributors802543a2019-08-31 12:12:56 +010099 if x in required_keys:
100 type = required_keys[x][0]
101 elif x in optional_keys:
102 type = optional_keys[x][0]
Eunchan Kim0bd75662020-04-24 10:21:18 -0700103 elif x not in added_keys:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100104 log.warning(err_prefix + " contains extra key " + x)
Rupert Swarbrickc02b52f2020-10-07 15:34:16 +0100105 if type is not None:
106 if type[:2] == 'ln':
107 error += check_ln(obj, x, type == 'lnw', err_prefix)
Eunchan Kimc4873f32019-09-25 12:46:12 -0700108
lowRISC Contributors802543a2019-08-31 12:12:56 +0100109 return error
110
111
lowRISC Contributors802543a2019-08-31 12:12:56 +0100112val_types = {
113 'd': ["int", "integer (binary 0b, octal 0o, decimal, hex 0x)"],
114 'x': ["xint", "x for undefined otherwise int"],
115 'b': [
Eunchan Kim0bd75662020-04-24 10:21:18 -0700116 "bitrange", "bit number as decimal integer, "
117 "or bit-range as decimal integers msb:lsb"
lowRISC Contributors802543a2019-08-31 12:12:56 +0100118 ],
119 'l': ["list", "comma separated list enclosed in `[]`"],
Eunchan Kim0bd75662020-04-24 10:21:18 -0700120 'ln': [
121 "name list", 'comma separated list enclosed in `[]` of '
122 'one or more groups that have just name and dscr keys.'
123 ' e.g. `{ name: "name", desc: "description"}`'
124 ],
lowRISC Contributors802543a2019-08-31 12:12:56 +0100125 'lnw': ["name list+", 'name list that optionally contains a width'],
Eunchan Kimc4873f32019-09-25 12:46:12 -0700126 'lp': ["parameter list", 'parameter list having default value optionally'],
lowRISC Contributors802543a2019-08-31 12:12:56 +0100127 'g': ["group", "comma separated group of key:value enclosed in `{}`"],
Eunchan Kim0bd75662020-04-24 10:21:18 -0700128 'lg': [
129 "list of group", "comma separated group of key:value enclosed in `{}`"
130 " the second entry of the list is the sub group format"
131 ],
lowRISC Contributors802543a2019-08-31 12:12:56 +0100132 's': ["string", "string, typically short"],
Eunchan Kim0bd75662020-04-24 10:21:18 -0700133 't': [
134 "text", "string, may be multi-line enclosed in `'''` "
135 "may use `**bold**`, `*italic*` or `!!Reg` markup"
136 ],
lowRISC Contributors802543a2019-08-31 12:12:56 +0100137 'T': ["tuple", "tuple enclosed in ()"],
Philipp Wagner14a3fee2019-11-21 10:07:02 +0000138 'pi': ["python int", "Native Python type int (generated)"],
139 'pb': ["python Bool", "Native Python type Bool (generated)"],
140 'pl': ["python list", "Native Python type list (generated)"],
141 'pe': ["python enum", "Native Python type enum (generated)"]
lowRISC Contributors802543a2019-08-31 12:12:56 +0100142}
143
lowRISC Contributors802543a2019-08-31 12:12:56 +0100144# ln type has list of groups with only name and description
145# (was called "subunit" in cfg_validate)
146ln_required = {
147 'name': ['s', "name of the item"],
148 'desc': ['s', "description of the item"],
149}
150ln_optional = {
151 'width': ['d', "bit width of the item (if not 1)"],
152}
153
154# Registers list may have embedded keys
Eunchan Kim0bd75662020-04-24 10:21:18 -0700155list_optone = {
156 'reserved': ['d', "number of registers to reserve space for"],
157 'skipto': ['d', "set next register offset to value"],
Eunchan Kim0bd75662020-04-24 10:21:18 -0700158 'window': [
159 'g', "group defining an address range "
160 "for something other than standard registers"
161 ],
162 'multireg':
163 ['g', "group defining registers generated "
164 "from a base instance."]
165}
lowRISC Contributors802543a2019-08-31 12:12:56 +0100166
lowRISC Contributors802543a2019-08-31 12:12:56 +0100167key_use = {'r': "required", 'o': "optional", 'a': "added by tool"}