/ coreblocks / params / genparams.py
genparams.py
  1  from __future__ import annotations
  2  
  3  from amaranth.utils import ceil_log2, exact_log2
  4  
  5  from coreblocks.arch.isa import ISA, gen_isa_string
  6  from .icache_params import ICacheParameters
  7  from .vmem_params import VirtualMemoryParameters
  8  from .fu_params import extensions_supported
  9  from ..peripherals.wishbone import WishboneParameters
 10  from transactron.utils import DependentCache
 11  
 12  from typing import TYPE_CHECKING
 13  
 14  if TYPE_CHECKING:
 15      from .configurations import CoreConfiguration
 16  
 17  __all__ = ["GenParams"]
 18  
 19  
 20  class GenParams(DependentCache):
 21      def __init__(self, cfg: CoreConfiguration):
 22          super().__init__()
 23  
 24          self.func_units_config = cfg.func_units_config
 25  
 26          ext_partial, ext_full = extensions_supported(self.func_units_config, cfg.embedded, cfg.compressed, cfg.zcb)
 27          extensions = ext_partial if cfg.allow_partial_extensions else ext_full
 28          if not cfg.allow_partial_extensions and ext_partial != ext_full:
 29              raise RuntimeError(f"Extensions {ext_partial & ~ext_full!r} are only partially supported")
 30  
 31          extensions |= cfg._implied_extensions
 32          self.isa_str = gen_isa_string(extensions, cfg.xlen)
 33  
 34          self.isa = ISA(self.isa_str)
 35  
 36          self.pma = cfg.pma
 37  
 38          bytes_in_word = self.isa.xlen // 8
 39          bytes_in_word_log = exact_log2(bytes_in_word)
 40  
 41          max_phys_addr_bits = VirtualMemoryParameters.max_physical_address_bits(cfg.xlen, cfg.supported_vm_schemes)
 42          self.phys_addr_bits = cfg.phys_addr_bits if cfg.phys_addr_bits is not None else max_phys_addr_bits
 43          if self.phys_addr_bits < bytes_in_word_log:
 44              raise ValueError(
 45                  f"Physical address width ({self.phys_addr_bits}) " f"must be at least {bytes_in_word_log} bits"
 46              )
 47          if self.phys_addr_bits > max_phys_addr_bits:
 48              raise ValueError(
 49                  "Physical address width "
 50                  f"({self.phys_addr_bits}) exceeds maximum {max_phys_addr_bits} "
 51                  f"bits for XLEN={cfg.xlen}"
 52              )
 53  
 54          self.wb_params = WishboneParameters(
 55              data_width=self.isa.xlen,
 56              addr_width=self.phys_addr_bits - bytes_in_word_log,
 57          )
 58  
 59          self.vmem_params = VirtualMemoryParameters(
 60              xlen=cfg.xlen,
 61              supervisor_mode=cfg.supervisor_mode,
 62              asidlen=cfg.asidlen,
 63              supported_schemes=cfg.supported_vm_schemes,
 64          )
 65  
 66          self.icache_params = ICacheParameters(
 67              addr_width=self.phys_addr_bits,
 68              word_width=self.isa.xlen,
 69              fetch_block_bytes_log=cfg.fetch_block_bytes_log,
 70              num_of_ways=cfg.icache_ways,
 71              num_of_sets_bits=cfg.icache_sets_bits,
 72              line_bytes_log=cfg.icache_line_bytes_log,
 73              enable=cfg.icache_enable,
 74          )
 75  
 76          self.debug_signals_enabled = cfg.debug_signals
 77  
 78          # Verification temporally disabled
 79          # if not optypes_required_by_extensions(self.isa.extensions) <= optypes_supported(func_units_config):
 80          #     raise Exception(f"Functional unit configuration do not support all extension required by{isa_str}")
 81  
 82          self.max_rs_entries = 1
 83  
 84          for block in self.func_units_config:
 85              self.max_rs_entries = max(self.max_rs_entries, block.get_rs_entry_count())
 86  
 87          self.rs_number_bits = ceil_log2(len(self.func_units_config))
 88  
 89          self.phys_regs = 2**cfg.phys_regs_bits
 90          self.rob_entries = 2**cfg.rob_entries_bits
 91  
 92          self.phys_regs_bits = cfg.phys_regs_bits
 93          self.rob_entries_bits = cfg.rob_entries_bits
 94          self.max_rs_entries_bits = ceil_log2(self.max_rs_entries)
 95          self.start_pc = cfg.start_pc
 96  
 97          self.frontend_superscalarity = cfg.frontend_superscalarity
 98          self.announcement_superscalarity = cfg.announcement_superscalarity
 99          self.retirement_superscalarity = cfg.retirement_superscalarity
100          max_superscalarity = max(self.frontend_superscalarity, self.retirement_superscalarity)
101          if max_superscalarity & (max_superscalarity - 1) != 0:
102              raise ValueError("Maximum of frontend and retirement superscalarity must be a power of 2")
103  
104          self.checkpoint_count = cfg.checkpoint_count
105          self.tag_bits = cfg.tag_bits
106          assert cfg.checkpoint_count < 2**cfg.tag_bits
107  
108          self.min_instr_width_bytes = 2 if cfg.compressed or cfg.zcb else 4
109          self.min_instr_width_bytes_log = exact_log2(self.min_instr_width_bytes)
110  
111          self.fetch_block_bytes_log = cfg.fetch_block_bytes_log
112          if self.fetch_block_bytes_log < bytes_in_word_log:
113              raise ValueError("Fetch block must be not smaller than the machine word.")
114          self.fetch_block_bytes = 2**self.fetch_block_bytes_log
115          self.fetch_width = 2**cfg.fetch_block_bytes_log // self.min_instr_width_bytes
116          self.fetch_width_log = exact_log2(self.fetch_width)
117  
118          self.instr_buffer_size = cfg.instr_buffer_size
119          self.extra_verification = cfg.extra_verification
120  
121          self.interrupt_custom_count = cfg.interrupt_custom_count
122          self.interrupt_custom_edge_trig_mask = cfg.interrupt_custom_edge_trig_mask
123  
124          self.user_mode = cfg.user_mode
125          self.supervisor_mode = cfg.supervisor_mode
126          self.hpm_counters_count = cfg.hpm_counters_count
127  
128          if self.hpm_counters_count < 0 or self.hpm_counters_count > 29:
129              raise ValueError("HPM counters count must be in range [0, 29]")
130  
131          # TODO: remove when HPM counters are implemented
132          if self.hpm_counters_count > 0:
133              raise NotImplementedError("HPM counters are currently not implemented")
134  
135          if self.supervisor_mode and not self.user_mode:
136              raise ValueError("Supervisor mode support requires user mode support")
137  
138          self.pmp_register_count = cfg.pmp_register_count
139          if self.pmp_register_count not in [0, 16, 64]:
140              raise ValueError("PMP register count must be 0, 16, or 64")
141  
142          if cfg.pmp_grain_log < 2:
143              raise ValueError("pmp_grain_log must be >= 2 (minimum 4-byte granularity)")
144  
145          self.pmp_grain = cfg.pmp_grain_log - 2  # G parameter from RISC-V spec
146          self.pmp_grain_bytes = 2**cfg.pmp_grain_log
147          if self.pmp_register_count > 0 and self.icache_params.enable:
148              if self.pmp_grain_bytes < self.icache_params.line_size_bytes:
149                  raise ValueError("PMP grain size must be >= cache line size")
150  
151          self._toolchain_isa_str = gen_isa_string(extensions, cfg.xlen, skip_internal=True)
152  
153          self._generate_test_hardware = cfg._generate_test_hardware
154  
155          self.marchid = cfg.marchid
156          self.mimpid = cfg.mimpid
157  
158          self.multiport_memory_type = cfg.multiport_memory_type