Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 1 | # Copyright lowRISC contributors. |
| 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | # SPDX-License-Identifier: Apache-2.0 |
| 4 | |
| 5 | '''Code representing an IP block for reggen''' |
| 6 | |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 7 | from typing import Dict, List, Optional, Sequence, Set, Tuple |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 8 | |
| 9 | import hjson # type: ignore |
| 10 | |
| 11 | from .alert import Alert |
Rupert Swarbrick | 6c83129 | 2021-02-25 17:08:53 +0000 | [diff] [blame] | 12 | from .bus_interfaces import BusInterfaces |
Timothy Chen | 7c3de6e | 2021-07-19 16:46:45 -0700 | [diff] [blame] | 13 | from .clocking import Clocking, ClockingItem |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 14 | from .inter_signal import InterSignal |
Michael Schaffner | bd43036 | 2022-05-09 18:13:23 -0700 | [diff] [blame] | 15 | from .lib import (check_keys, check_name, check_int, check_bool, check_list) |
Philipp Wagner | 78194c8 | 2021-03-10 10:08:17 +0000 | [diff] [blame] | 16 | from .params import ReggenParams, LocalParam |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 17 | from .reg_block import RegBlock |
| 18 | from .signal import Signal |
Michael Schaffner | e8976ff | 2021-11-15 16:12:17 -0800 | [diff] [blame] | 19 | from .countermeasure import CounterMeasure |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 20 | |
| 21 | |
| 22 | REQUIRED_FIELDS = { |
| 23 | 'name': ['s', "name of the component"], |
Rupert Swarbrick | d0cbfad | 2021-06-29 17:04:51 +0100 | [diff] [blame] | 24 | 'clocking': ['l', "clocking for the device"], |
Rupert Swarbrick | 6c83129 | 2021-02-25 17:08:53 +0000 | [diff] [blame] | 25 | 'bus_interfaces': ['l', "bus interfaces for the device"], |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 26 | 'registers': [ |
| 27 | 'l', |
| 28 | "list of register definition groups and " |
| 29 | "offset control groups" |
| 30 | ] |
| 31 | } |
| 32 | |
| 33 | OPTIONAL_FIELDS = { |
| 34 | 'alert_list': ['lnw', "list of peripheral alerts"], |
| 35 | 'available_inout_list': ['lnw', "list of available peripheral inouts"], |
| 36 | 'available_input_list': ['lnw', "list of available peripheral inputs"], |
| 37 | 'available_output_list': ['lnw', "list of available peripheral outputs"], |
Rupert Swarbrick | da5ed15 | 2021-06-08 14:14:40 +0100 | [diff] [blame] | 38 | 'expose_reg_if': ['pb', 'if set, expose reg interface in reg2hw signal'], |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 39 | 'interrupt_list': ['lnw', "list of peripheral interrupts"], |
| 40 | 'inter_signal_list': ['l', "list of inter-module signals"], |
| 41 | 'no_auto_alert_regs': [ |
| 42 | 's', "Set to true to suppress automatic " |
| 43 | "generation of alert test registers. " |
| 44 | "Defaults to true if no alert_list is present. " |
| 45 | "Otherwise this defaults to false. " |
| 46 | ], |
| 47 | 'no_auto_intr_regs': [ |
| 48 | 's', "Set to true to suppress automatic " |
| 49 | "generation of interrupt registers. " |
| 50 | "Defaults to true if no interrupt_list is present. " |
| 51 | "Otherwise this defaults to false. " |
| 52 | ], |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 53 | 'param_list': ['lp', "list of parameters of the IP"], |
| 54 | 'regwidth': ['d', "width of registers in bits (default 32)"], |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 55 | 'reset_request_list': ['l', 'list of signals requesting reset'], |
| 56 | 'scan': ['pb', 'Indicates the module have `scanmode_i`'], |
Timothy Chen | 21e6a4f | 2021-04-30 03:47:01 -0700 | [diff] [blame] | 57 | 'scan_reset': ['pb', 'Indicates the module have `scan_rst_ni`'], |
| 58 | 'scan_en': ['pb', 'Indicates the module has `scan_en_i`'], |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 59 | 'SPDX-License-Identifier': [ |
| 60 | 's', "License ientifier (if using pure json) " |
| 61 | "Only use this if unable to put this " |
| 62 | "information in a comment at the top of the " |
| 63 | "file." |
| 64 | ], |
Michael Schaffner | e8976ff | 2021-11-15 16:12:17 -0800 | [diff] [blame] | 65 | 'wakeup_list': ['lnw', "list of peripheral wakeups"], |
| 66 | 'countermeasures': ["ln", "list of countermeasures in this block"] |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 70 | class IpBlock: |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 71 | def __init__(self, |
| 72 | name: str, |
| 73 | regwidth: int, |
Philipp Wagner | 78194c8 | 2021-03-10 10:08:17 +0000 | [diff] [blame] | 74 | params: ReggenParams, |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 75 | reg_blocks: Dict[Optional[str], RegBlock], |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 76 | interrupts: Sequence[Signal], |
| 77 | no_auto_intr: bool, |
| 78 | alerts: List[Alert], |
| 79 | no_auto_alert: bool, |
| 80 | scan: bool, |
| 81 | inter_signals: List[InterSignal], |
Rupert Swarbrick | 6c83129 | 2021-02-25 17:08:53 +0000 | [diff] [blame] | 82 | bus_interfaces: BusInterfaces, |
Rupert Swarbrick | d0cbfad | 2021-06-29 17:04:51 +0100 | [diff] [blame] | 83 | clocking: Clocking, |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 84 | xputs: Tuple[Sequence[Signal], |
| 85 | Sequence[Signal], |
| 86 | Sequence[Signal]], |
| 87 | wakeups: Sequence[Signal], |
| 88 | reset_requests: Sequence[Signal], |
Rupert Swarbrick | da5ed15 | 2021-06-08 14:14:40 +0100 | [diff] [blame] | 89 | expose_reg_if: bool, |
Timothy Chen | 21e6a4f | 2021-04-30 03:47:01 -0700 | [diff] [blame] | 90 | scan_reset: bool, |
Michael Schaffner | e8976ff | 2021-11-15 16:12:17 -0800 | [diff] [blame] | 91 | scan_en: bool, |
| 92 | countermeasures: List[CounterMeasure]): |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 93 | assert reg_blocks |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 94 | |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 95 | # Check that register blocks are in bijection with device interfaces |
| 96 | reg_block_names = reg_blocks.keys() |
| 97 | dev_if_names = [] # type: List[Optional[str]] |
| 98 | dev_if_names += bus_interfaces.named_devices |
| 99 | if bus_interfaces.has_unnamed_device: |
| 100 | dev_if_names.append(None) |
| 101 | assert set(reg_block_names) == set(dev_if_names) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 102 | |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 103 | self.name = name |
| 104 | self.regwidth = regwidth |
| 105 | self.reg_blocks = reg_blocks |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 106 | self.params = params |
| 107 | self.interrupts = interrupts |
| 108 | self.no_auto_intr = no_auto_intr |
| 109 | self.alerts = alerts |
| 110 | self.no_auto_alert = no_auto_alert |
| 111 | self.scan = scan |
| 112 | self.inter_signals = inter_signals |
Rupert Swarbrick | 6c83129 | 2021-02-25 17:08:53 +0000 | [diff] [blame] | 113 | self.bus_interfaces = bus_interfaces |
Rupert Swarbrick | d0cbfad | 2021-06-29 17:04:51 +0100 | [diff] [blame] | 114 | self.clocking = clocking |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 115 | self.xputs = xputs |
| 116 | self.wakeups = wakeups |
| 117 | self.reset_requests = reset_requests |
Rupert Swarbrick | da5ed15 | 2021-06-08 14:14:40 +0100 | [diff] [blame] | 118 | self.expose_reg_if = expose_reg_if |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 119 | self.scan_reset = scan_reset |
Timothy Chen | 21e6a4f | 2021-04-30 03:47:01 -0700 | [diff] [blame] | 120 | self.scan_en = scan_en |
Michael Schaffner | e8976ff | 2021-11-15 16:12:17 -0800 | [diff] [blame] | 121 | self.countermeasures = countermeasures |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 122 | |
| 123 | @staticmethod |
| 124 | def from_raw(param_defaults: List[Tuple[str, str]], |
| 125 | raw: object, |
| 126 | where: str) -> 'IpBlock': |
| 127 | |
| 128 | rd = check_keys(raw, 'block at ' + where, |
| 129 | list(REQUIRED_FIELDS.keys()), |
| 130 | list(OPTIONAL_FIELDS.keys())) |
| 131 | |
| 132 | name = check_name(rd['name'], 'name of block at ' + where) |
| 133 | |
| 134 | what = '{} block at {}'.format(name, where) |
| 135 | |
| 136 | r_regwidth = rd.get('regwidth') |
| 137 | if r_regwidth is None: |
| 138 | regwidth = 32 |
| 139 | else: |
| 140 | regwidth = check_int(r_regwidth, 'regwidth field of ' + what) |
| 141 | if regwidth <= 0: |
| 142 | raise ValueError('Invalid regwidth field for {}: ' |
| 143 | '{} is not positive.' |
| 144 | .format(what, regwidth)) |
| 145 | |
Philipp Wagner | 78194c8 | 2021-03-10 10:08:17 +0000 | [diff] [blame] | 146 | params = ReggenParams.from_raw('parameter list for ' + what, |
| 147 | rd.get('param_list', [])) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 148 | try: |
| 149 | params.apply_defaults(param_defaults) |
| 150 | except (ValueError, KeyError) as err: |
| 151 | raise ValueError('Failed to apply defaults to params: {}' |
| 152 | .format(err)) from None |
| 153 | |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 154 | init_block = RegBlock(regwidth, params) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 155 | |
| 156 | interrupts = Signal.from_raw_list('interrupt_list for block {}' |
| 157 | .format(name), |
| 158 | rd.get('interrupt_list', [])) |
| 159 | alerts = Alert.from_raw_list('alert_list for block {}' |
| 160 | .format(name), |
| 161 | rd.get('alert_list', [])) |
Michael Schaffner | 02bfd84 | 2021-12-23 09:07:02 -0800 | [diff] [blame] | 162 | known_cms = {} |
| 163 | raw_cms = rd.get('countermeasures', []) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 164 | |
Michael Schaffner | e8976ff | 2021-11-15 16:12:17 -0800 | [diff] [blame] | 165 | countermeasures = CounterMeasure.from_raw_list( |
| 166 | 'countermeasure list for block {}' |
Michael Schaffner | 02bfd84 | 2021-12-23 09:07:02 -0800 | [diff] [blame] | 167 | .format(name), raw_cms) |
| 168 | |
| 169 | # Ensure that the countermeasures are unique |
| 170 | for x in countermeasures: |
| 171 | if str(x) in known_cms: |
| 172 | raise RuntimeError(f"Duplicate countermeasure {str(x)}") |
| 173 | else: |
| 174 | known_cms.update({str(x): 1}) |
Michael Schaffner | e8976ff | 2021-11-15 16:12:17 -0800 | [diff] [blame] | 175 | |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 176 | no_auto_intr = check_bool(rd.get('no_auto_intr_regs', not interrupts), |
| 177 | 'no_auto_intr_regs field of ' + what) |
| 178 | |
| 179 | no_auto_alert = check_bool(rd.get('no_auto_alert_regs', not alerts), |
| 180 | 'no_auto_alert_regs field of ' + what) |
| 181 | |
| 182 | if interrupts and not no_auto_intr: |
| 183 | if interrupts[-1].bits.msb >= regwidth: |
| 184 | raise ValueError("Interrupt list for {} is too wide: " |
| 185 | "msb is {}, which doesn't fit with a " |
| 186 | "regwidth of {}." |
| 187 | .format(what, |
| 188 | interrupts[-1].bits.msb, regwidth)) |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 189 | init_block.make_intr_regs(interrupts) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 190 | |
| 191 | if alerts: |
| 192 | if not no_auto_alert: |
| 193 | if len(alerts) > regwidth: |
| 194 | raise ValueError("Interrupt list for {} is too wide: " |
| 195 | "{} alerts don't fit with a regwidth of {}." |
| 196 | .format(what, len(alerts), regwidth)) |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 197 | init_block.make_alert_regs(alerts) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 198 | |
| 199 | # Generate a NumAlerts parameter |
| 200 | existing_param = params.get('NumAlerts') |
| 201 | if existing_param is not None: |
| 202 | if ((not isinstance(existing_param, LocalParam) or |
| 203 | existing_param.param_type != 'int' or |
| 204 | existing_param.value != str(len(alerts)))): |
| 205 | raise ValueError('Conflicting definition of NumAlerts ' |
| 206 | 'parameter.') |
| 207 | else: |
| 208 | params.add(LocalParam(name='NumAlerts', |
| 209 | desc='Number of alerts', |
| 210 | param_type='int', |
| 211 | value=str(len(alerts)))) |
| 212 | |
| 213 | scan = check_bool(rd.get('scan', False), 'scan field of ' + what) |
| 214 | |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 215 | r_inter_signals = check_list(rd.get('inter_signal_list', []), |
| 216 | 'inter_signal_list field') |
| 217 | inter_signals = [ |
| 218 | InterSignal.from_raw('entry {} of the inter_signal_list field' |
| 219 | .format(idx + 1), |
| 220 | entry) |
| 221 | for idx, entry in enumerate(r_inter_signals) |
| 222 | ] |
| 223 | |
Rupert Swarbrick | 6c83129 | 2021-02-25 17:08:53 +0000 | [diff] [blame] | 224 | bus_interfaces = (BusInterfaces. |
| 225 | from_raw(rd['bus_interfaces'], |
| 226 | 'bus_interfaces field of ' + where)) |
| 227 | inter_signals += bus_interfaces.inter_signals() |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 228 | |
Rupert Swarbrick | d0cbfad | 2021-06-29 17:04:51 +0100 | [diff] [blame] | 229 | clocking = Clocking.from_raw(rd['clocking'], |
| 230 | 'clocking field of ' + what) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 231 | |
Timothy Chen | a49ceb6 | 2021-07-13 14:59:09 -0700 | [diff] [blame] | 232 | reg_blocks = RegBlock.build_blocks(init_block, rd['registers'], |
| 233 | bus_interfaces, |
| 234 | clocking) |
| 235 | |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 236 | xputs = ( |
| 237 | Signal.from_raw_list('available_inout_list for block ' + name, |
| 238 | rd.get('available_inout_list', [])), |
| 239 | Signal.from_raw_list('available_input_list for block ' + name, |
| 240 | rd.get('available_input_list', [])), |
| 241 | Signal.from_raw_list('available_output_list for block ' + name, |
| 242 | rd.get('available_output_list', [])) |
| 243 | ) |
| 244 | wakeups = Signal.from_raw_list('wakeup_list for block ' + name, |
| 245 | rd.get('wakeup_list', [])) |
| 246 | rst_reqs = Signal.from_raw_list('reset_request_list for block ' + name, |
| 247 | rd.get('reset_request_list', [])) |
| 248 | |
Rupert Swarbrick | da5ed15 | 2021-06-08 14:14:40 +0100 | [diff] [blame] | 249 | expose_reg_if = check_bool(rd.get('expose_reg_if', False), |
| 250 | 'expose_reg_if field of ' + what) |
| 251 | |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 252 | scan_reset = check_bool(rd.get('scan_reset', False), |
| 253 | 'scan_reset field of ' + what) |
| 254 | |
Timothy Chen | 21e6a4f | 2021-04-30 03:47:01 -0700 | [diff] [blame] | 255 | scan_en = check_bool(rd.get('scan_en', False), |
Rupert Swarbrick | ba0bd32 | 2021-06-07 16:30:20 +0100 | [diff] [blame] | 256 | 'scan_en field of ' + what) |
Timothy Chen | 21e6a4f | 2021-04-30 03:47:01 -0700 | [diff] [blame] | 257 | |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 258 | # Check that register blocks are in bijection with device interfaces |
| 259 | reg_block_names = reg_blocks.keys() |
| 260 | dev_if_names = [] # type: List[Optional[str]] |
| 261 | dev_if_names += bus_interfaces.named_devices |
| 262 | if bus_interfaces.has_unnamed_device: |
| 263 | dev_if_names.append(None) |
| 264 | if set(reg_block_names) != set(dev_if_names): |
| 265 | raise ValueError("IP block {} defines device interfaces, named {} " |
| 266 | "but its registers don't match (they are keyed " |
| 267 | "by {})." |
| 268 | .format(name, dev_if_names, |
| 269 | list(reg_block_names))) |
| 270 | |
| 271 | return IpBlock(name, regwidth, params, reg_blocks, |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 272 | interrupts, no_auto_intr, alerts, no_auto_alert, |
Michael Schaffner | bd43036 | 2022-05-09 18:13:23 -0700 | [diff] [blame] | 273 | scan, inter_signals, bus_interfaces, clocking, xputs, |
Michael Schaffner | e8976ff | 2021-11-15 16:12:17 -0800 | [diff] [blame] | 274 | wakeups, rst_reqs, expose_reg_if, scan_reset, scan_en, |
| 275 | countermeasures) |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 276 | |
| 277 | @staticmethod |
| 278 | def from_text(txt: str, |
| 279 | param_defaults: List[Tuple[str, str]], |
| 280 | where: str) -> 'IpBlock': |
| 281 | '''Load an IpBlock from an hjson description in txt''' |
| 282 | return IpBlock.from_raw(param_defaults, |
| 283 | hjson.loads(txt, use_decimal=True), |
| 284 | where) |
| 285 | |
| 286 | @staticmethod |
| 287 | def from_path(path: str, |
| 288 | param_defaults: List[Tuple[str, str]]) -> 'IpBlock': |
| 289 | '''Load an IpBlock from an hjson description in a file at path''' |
Srikrishna Iyer | 18b8ed9 | 2021-04-26 15:54:44 -0700 | [diff] [blame] | 290 | with open(path, 'r', encoding='utf-8') as handle: |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 291 | return IpBlock.from_text(handle.read(), param_defaults, |
| 292 | 'file at {!r}'.format(path)) |
| 293 | |
| 294 | def _asdict(self) -> Dict[str, object]: |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 295 | ret = { |
| 296 | 'name': self.name, |
| 297 | 'regwidth': self.regwidth |
| 298 | } |
| 299 | if len(self.reg_blocks) == 1 and None in self.reg_blocks: |
| 300 | ret['registers'] = self.reg_blocks[None].as_dicts() |
| 301 | else: |
| 302 | ret['registers'] = {k: v.as_dicts() |
| 303 | for k, v in self.reg_blocks.items()} |
| 304 | |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 305 | ret['param_list'] = self.params.as_dicts() |
| 306 | ret['interrupt_list'] = self.interrupts |
| 307 | ret['no_auto_intr_regs'] = self.no_auto_intr |
| 308 | ret['alert_list'] = self.alerts |
| 309 | ret['no_auto_alert_regs'] = self.no_auto_alert |
| 310 | ret['scan'] = self.scan |
| 311 | ret['inter_signal_list'] = self.inter_signals |
Rupert Swarbrick | 6c83129 | 2021-02-25 17:08:53 +0000 | [diff] [blame] | 312 | ret['bus_interfaces'] = self.bus_interfaces.as_dicts() |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 313 | |
Rupert Swarbrick | d0cbfad | 2021-06-29 17:04:51 +0100 | [diff] [blame] | 314 | ret['clocking'] = self.clocking.items |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 315 | |
| 316 | inouts, inputs, outputs = self.xputs |
| 317 | if inouts: |
| 318 | ret['available_inout_list'] = inouts |
| 319 | if inputs: |
| 320 | ret['available_input_list'] = inputs |
| 321 | if outputs: |
| 322 | ret['available_output_list'] = outputs |
| 323 | |
| 324 | if self.wakeups: |
| 325 | ret['wakeup_list'] = self.wakeups |
| 326 | if self.reset_requests: |
| 327 | ret['reset_request_list'] = self.reset_requests |
| 328 | |
| 329 | ret['scan_reset'] = self.scan_reset |
Timothy Chen | 21e6a4f | 2021-04-30 03:47:01 -0700 | [diff] [blame] | 330 | ret['scan_en'] = self.scan_en |
Rupert Swarbrick | 269bb3d | 2021-02-23 15:41:56 +0000 | [diff] [blame] | 331 | |
| 332 | return ret |
Rupert Swarbrick | 200d8b4 | 2021-03-08 12:32:11 +0000 | [diff] [blame] | 333 | |
| 334 | def get_rnames(self) -> Set[str]: |
| 335 | ret = set() # type: Set[str] |
| 336 | for rb in self.reg_blocks.values(): |
| 337 | ret = ret.union(set(rb.name_to_offset.keys())) |
| 338 | return ret |
Michael Schaffner | 74c4ff2 | 2021-03-30 15:43:46 -0700 | [diff] [blame] | 339 | |
Rupert Swarbrick | 0f6eeaf | 2021-05-28 15:24:14 +0100 | [diff] [blame] | 340 | def get_signals_as_list_of_dicts(self) -> List[Dict[str, object]]: |
Michael Schaffner | 74c4ff2 | 2021-03-30 15:43:46 -0700 | [diff] [blame] | 341 | '''Look up and return signal by name''' |
| 342 | result = [] |
| 343 | for iodir, xput in zip(('inout', 'input', 'output'), self.xputs): |
| 344 | for sig in xput: |
| 345 | result.append(sig.as_nwt_dict(iodir)) |
| 346 | return result |
| 347 | |
Rupert Swarbrick | 0f6eeaf | 2021-05-28 15:24:14 +0100 | [diff] [blame] | 348 | def get_signal_by_name_as_dict(self, name: str) -> Dict[str, object]: |
Michael Schaffner | 74c4ff2 | 2021-03-30 15:43:46 -0700 | [diff] [blame] | 349 | '''Look up and return signal by name''' |
| 350 | sig_list = self.get_signals_as_list_of_dicts() |
| 351 | for sig in sig_list: |
| 352 | if sig['name'] == name: |
| 353 | return sig |
| 354 | else: |
| 355 | raise ValueError("Signal {} does not exist in IP block {}" |
| 356 | .format(name, self.name)) |
Timothy Chen | 7c3de6e | 2021-07-19 16:46:45 -0700 | [diff] [blame] | 357 | |
| 358 | def has_shadowed_reg(self) -> bool: |
| 359 | '''Return boolean indication whether reg block contains shadowed registers''' |
| 360 | |
| 361 | for rb in self.reg_blocks.values(): |
| 362 | if rb.has_shadowed_reg(): |
| 363 | return True |
| 364 | |
| 365 | # if we are here, then no one has has a shadowed register |
| 366 | return False |
| 367 | |
| 368 | def get_primary_clock(self) -> ClockingItem: |
| 369 | '''Return primary clock of an block''' |
| 370 | |
| 371 | return self.clocking.primary |
Michael Schaffner | 9af3053 | 2022-01-13 20:25:55 -0800 | [diff] [blame] | 372 | |
| 373 | def check_cm_annotations(self, |
| 374 | rtl_names: Dict[str, List[Tuple[str, int]]], |
| 375 | where: str) -> None: |
| 376 | '''Check RTL annotations against countermeasure list of this block''' |
| 377 | |
| 378 | what = '{} block at {}'.format(self.name, where) |
| 379 | CounterMeasure.check_annotation_list(what, |
| 380 | rtl_names, |
| 381 | self.countermeasures) |