| # Copyright lowRISC contributors. | 
 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
 | # SPDX-License-Identifier: Apache-2.0 | 
 | """This contains a class which is used to help generate top level SW tests. | 
 |  | 
 | We maintain as a separate class rather than merge implementation with c.py, | 
 | because both serve different purposes and need to capture the information | 
 | differently. | 
 | """ | 
 |  | 
 | import logging as log | 
 | import sys | 
 | from typing import Dict | 
 |  | 
 | from reggen.ip_block import IpBlock | 
 |  | 
 | from .c import TopGenC | 
 | from .lib import Name | 
 |  | 
 |  | 
 | class TestPeripheral: | 
 |     """Captures a peripheral instance's attributes for use in SW tests. | 
 |  | 
 |     It encapsulates the settings for each peripheral's instance in the design. | 
 |     These settings are captured as identifiers that are already defined in | 
 |     other autogenerated / hand-edited sources such as top_{name}.h and the DIF | 
 |     headers, rather than hard-coded constants. This is done to ensure that a | 
 |     single source of truth is referenced in all of the tests. | 
 |     """ | 
 |     def __init__(self, name: str, inst_name: str, base_addr_name: str, | 
 |                  is_templated: bool): | 
 |         self.name = name | 
 |         self.inst_name = inst_name | 
 |         self.base_addr_name = base_addr_name | 
 |         self.is_templated = is_templated | 
 |  | 
 |  | 
 | class IrqTestPeripheral(TestPeripheral): | 
 |     """Captures a peripheral instance's attributes for use in IRQ test.""" | 
 |     def __init__(self, name: str, inst_name: str, base_addr_name: str, | 
 |                  is_templated: bool, plic_name: str, start_irq: str, | 
 |                  end_irq: str, plic_start_irq: str): | 
 |         super().__init__(name, inst_name, base_addr_name, is_templated) | 
 |         self.plic_name = plic_name | 
 |         self.start_irq = start_irq | 
 |         self.end_irq = end_irq | 
 |         self.plic_start_irq = plic_start_irq | 
 |  | 
 |  | 
 | class TopGenCTest(TopGenC): | 
 |     def __init__(self, top_info, name_to_block: Dict[str, IpBlock]): | 
 |         super().__init__(top_info, name_to_block) | 
 |  | 
 |         self.irq_peripherals = self._get_irq_peripherals() | 
 |  | 
 |     def _get_irq_peripherals(self): | 
 |         irq_peripherals = [] | 
 |         self.devices() | 
 |         for entry in self.top['module']: | 
 |             inst_name = entry['name'] | 
 |             if inst_name not in self.top["interrupt_module"]: | 
 |                 continue | 
 |  | 
 |             name = entry['type'] | 
 |             plic_name = (self._top_name + Name(["plic", "peripheral"]) + | 
 |                          Name.from_snake_case(inst_name)) | 
 |             plic_name = plic_name.as_c_enum() | 
 |  | 
 |             # Device regions may have multiple TL interfaces. Pick the region | 
 |             # associated with the 'core' interface. | 
 |             if_name = None if len( | 
 |                 self.device_regions[inst_name]) == 1 else 'core' | 
 |             try: | 
 |                 region = self.device_regions[inst_name][if_name] | 
 |             except KeyError: | 
 |                 log.error(f"The 'base_addrs' dict for {name} needs to have " | 
 |                           "one entry keyed with 'None' or 'core'.") | 
 |                 sys.exit(1) | 
 |  | 
 |             base_addr_name = region.base_addr_name().as_c_define() | 
 |             is_templated = 'attr' in entry and entry['attr'] == 'templated' | 
 |  | 
 |             plic_name = (self._top_name + Name(["plic", "peripheral"]) + | 
 |                          Name.from_snake_case(inst_name)) | 
 |             plic_name = plic_name.as_c_enum() | 
 |  | 
 |             start_irq = self.device_irqs[inst_name][0] | 
 |             end_irq = self.device_irqs[inst_name][-1] | 
 |             plic_start_irq = (self._top_name + Name(["plic", "irq", "id"]) + | 
 |                               Name.from_snake_case(start_irq)) | 
 |             plic_start_irq = plic_start_irq.as_c_enum() | 
 |  | 
 |             # Get DIF compliant, instance-agnostic IRQ names. | 
 |             start_irq = start_irq.replace(inst_name, f"dif_{name}_irq", 1) | 
 |             start_irq = Name.from_snake_case(start_irq).as_c_enum() | 
 |             end_irq = end_irq.replace(inst_name, f"dif_{name}_irq", 1) | 
 |             end_irq = Name.from_snake_case(end_irq).as_c_enum() | 
 |  | 
 |             irq_peripheral = IrqTestPeripheral(name, inst_name, base_addr_name, | 
 |                                                is_templated, plic_name, start_irq, | 
 |                                                end_irq, plic_start_irq) | 
 |             irq_peripherals.append(irq_peripheral) | 
 |  | 
 |         irq_peripherals.sort(key=lambda p: p.inst_name) | 
 |         return irq_peripherals |