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