/ coreblocks / core.py
core.py
  1  from amaranth import *
  2  from amaranth.lib.wiring import Component, flipped, connect, In, Out
  3  from transactron import Transaction
  4  from transactron.lib.allocators import PriorityEncoderAllocator
  5  
  6  from transactron.utils.dependencies import DependencyContext
  7  from coreblocks.priv.traps.instr_counter import CoreInstructionCounter
  8  from coreblocks.func_blocks.interface.func_blocks_unifier import FuncBlocksUnifier
  9  from coreblocks.priv.traps.interrupt_controller import ISA_RESERVED_INTERRUPTS, InternalInterruptController
 10  from transactron.core import TModule, Method, def_method
 11  from transactron.lib import CrossbarConnectTrans
 12  from coreblocks.interface.layouts import *
 13  from coreblocks.interface.keys import (
 14      CSRInstancesKey,
 15      CommonBusDataKey,
 16  )
 17  from coreblocks.params.genparams import GenParams
 18  from coreblocks.core_structs.crat import CheckpointRAT
 19  from coreblocks.core_structs.rat import RRAT
 20  from coreblocks.core_structs.rob import ReorderBuffer
 21  from coreblocks.core_structs.rf import RegisterFile
 22  from coreblocks.func_blocks.instruction_metrics import InstructionMetrics
 23  from coreblocks.priv.csr.csr_instances import CSRInstances
 24  from coreblocks.frontend.frontend import CoreFrontend
 25  from coreblocks.priv.traps.exception import ExceptionInformationRegister
 26  from coreblocks.scheduler.scheduler import Scheduler
 27  from coreblocks.backend.announcement import ResultAnnouncement
 28  from coreblocks.backend.retirement import Retirement
 29  from coreblocks.peripherals.bus_adapter import WishboneMasterAdapter
 30  from coreblocks.peripherals.wishbone import WishboneMaster, WishboneInterface
 31  from transactron.lib.metrics import HwMetricsEnabledKey, TaggedCounter
 32  
 33  __all__ = ["Core"]
 34  
 35  
 36  class Core(Component):
 37      wb_instr: WishboneInterface
 38      wb_data: WishboneInterface
 39      interrupts: Signal
 40  
 41      def __init__(self, *, gen_params: GenParams):
 42          super().__init__(
 43              {
 44                  "wb_instr": Out(WishboneInterface(gen_params.wb_params).signature),
 45                  "wb_data": Out(WishboneInterface(gen_params.wb_params).signature),
 46                  "interrupts": In(ISA_RESERVED_INTERRUPTS + gen_params.interrupt_custom_count),
 47              }
 48          )
 49  
 50          self.gen_params = gen_params
 51  
 52          self.dm = DependencyContext.get()
 53          if self.gen_params.debug_signals_enabled:
 54              self.dm.add_dependency(HwMetricsEnabledKey(), True)
 55  
 56          self.wb_master_instr = WishboneMaster(self.gen_params.wb_params, "instr")
 57          self.wb_master_data = WishboneMaster(self.gen_params.wb_params, "data")
 58  
 59          self.bus_master_instr_adapter = WishboneMasterAdapter(self.wb_master_instr)
 60          self.bus_master_data_adapter = WishboneMasterAdapter(self.wb_master_data)
 61          self.dm.add_dependency(CommonBusDataKey(), self.bus_master_data_adapter)
 62  
 63          self.frontend = CoreFrontend(gen_params=self.gen_params, instr_bus=self.bus_master_instr_adapter)
 64  
 65          self.rf_allocator = PriorityEncoderAllocator(
 66              gen_params.phys_regs, gen_params.frontend_superscalarity, init=2**gen_params.phys_regs - 2
 67          )
 68  
 69          self.CRAT = CheckpointRAT(gen_params=self.gen_params)
 70          self.RRAT = RRAT(gen_params=self.gen_params)
 71          self.RF = RegisterFile(
 72              gen_params=self.gen_params,
 73              read_ports=2 * self.gen_params.frontend_superscalarity,
 74              write_ports=self.gen_params.announcement_superscalarity,
 75              free_ports=1,
 76          )
 77          self.ROB = ReorderBuffer(
 78              gen_params=self.gen_params, mark_done_ports=self.gen_params.announcement_superscalarity
 79          )
 80  
 81          self.retirement = Retirement(self.gen_params)
 82  
 83          self.exception_information_register = ExceptionInformationRegister(
 84              self.gen_params,
 85              rob_get_indices=self.ROB.get_indices,
 86              fetch_stall_exception=self.frontend.stall,
 87          )
 88  
 89          self.func_blocks_unifier = FuncBlocksUnifier(
 90              gen_params=gen_params,
 91              blocks=gen_params.func_units_config,
 92          )
 93  
 94          self.csr_instances = CSRInstances(self.gen_params)
 95          self.dm.add_dependency(CSRInstancesKey(), self.csr_instances)
 96  
 97          self.interrupt_controller = InternalInterruptController(self.gen_params)
 98  
 99          self.announcement_counter = TaggedCounter(
100              "backend.announcement.announcement_count",
101              "Number of instruction results announced in one cycle",
102              tags=range(gen_params.announcement_superscalarity + 1),
103          )
104  
105      def elaborate(self, platform):
106          m = TModule()
107  
108          m.submodules += [self.announcement_counter]
109  
110          connect(m.top_module, flipped(self.wb_instr), self.wb_master_instr.wb_master)
111          connect(m.top_module, flipped(self.wb_data), self.wb_master_data.wb_master)
112  
113          m.submodules.wb_master_instr = self.wb_master_instr
114          m.submodules.wb_master_data = self.wb_master_data
115  
116          m.submodules.bus_master_instr_adapter = self.bus_master_instr_adapter
117          m.submodules.bus_master_data_adapter = self.bus_master_data_adapter
118  
119          m.submodules.frontend = self.frontend
120  
121          m.submodules.rf_allocator = rf_allocator = self.rf_allocator
122          m.submodules.CRAT = crat = self.CRAT
123          m.submodules.RRAT = rrat = self.RRAT
124          m.submodules.RF = rf = self.RF
125          m.submodules.rob = rob = self.ROB
126  
127          m.submodules.csr_instances = self.csr_instances
128          m.submodules.interrupt_controller = self.interrupt_controller
129          m.d.comb += self.interrupt_controller.internal_report_level.eq(self.interrupts[0:16])
130          m.d.comb += self.interrupt_controller.custom_report.eq(self.interrupts[16:])
131  
132          m.submodules.core_counter = core_counter = CoreInstructionCounter(self.gen_params)
133  
134          m.submodules.instruction_metrics = InstructionMetrics()
135  
136          get_instr = Method.like(self.frontend.consume_instr)
137  
138          @def_method(m, get_instr)
139          def _():
140              ret = self.frontend.consume_instr(m)
141              core_counter.increment(m, ret.count)
142              return ret
143  
144          m.submodules.scheduler = scheduler = Scheduler(gen_params=self.gen_params)
145          scheduler.get_instr.provide(get_instr)
146          scheduler.get_free_reg.provide(rf_allocator.alloc)
147          scheduler.crat_commit_checkpoint.provide(crat.commit_checkpoint)
148          scheduler.crat_rename.provide(crat.rename)
149          scheduler.crat_tag.provide(crat.tag)
150          scheduler.crat_active_tags.provide(crat.get_active_tags)
151          scheduler.rob_put.provide(rob.put)
152          scheduler.rf_read_req.provide(rf.read_req)
153          scheduler.rf_read_resp.provide(rf.read_resp)
154          for i, block in enumerate(self.func_blocks_unifier.rs_blocks):
155              scheduler.rs_select[i].provide(block.select)
156              scheduler.rs_insert[i].provide(block.insert)
157  
158          m.submodules.exception_information_register = self.exception_information_register
159  
160          announce_result: list[Method] = []
161          for i in range(self.gen_params.announcement_superscalarity):
162              m.submodules[f"announcement_{i}"] = announcement = ResultAnnouncement(gen_params=self.gen_params)
163              announcement.rob_mark_done.provide(self.ROB.mark_done[i])
164              announcement.rs_update.provide(self.func_blocks_unifier.update[i])
165              announcement.rf_write_val.provide(self.RF.write[i])
166              announce_result.append(announcement.push_result)
167  
168          with Transaction().body(m):
169              self.announcement_counter.incr(m, tag=sum(method.run for method in announce_result))
170  
171          m.submodules.announcement_connector = CrossbarConnectTrans.create(
172              self.func_blocks_unifier.get_result, announce_result
173          )
174  
175          m.submodules.retirement = retirement = self.retirement
176          retirement.rob_peek.provide(rob.peek)
177          retirement.rob_retire.provide(rob.retire)
178          retirement.r_rat_commit.provide(rrat.commit[0])
179          retirement.r_rat_peek.provide(rrat.peek[0])
180          retirement.free_rf_put.provide(rf_allocator.free[0])
181          retirement.rf_free.provide(rf.free[0])
182          retirement.exception_cause_get.provide(self.exception_information_register.get)
183          retirement.exception_cause_clear.provide(self.exception_information_register.clear)
184          retirement.c_rat_restore.provide(crat.flush_restore)
185          retirement.fetch_continue.provide(self.frontend.resume_from_exception)
186          retirement.instr_decrement.provide(core_counter.decrement)
187          retirement.trap_entry.provide(self.interrupt_controller.entry)
188          retirement.async_interrupt_cause.provide(self.interrupt_controller.interrupt_cause)
189          retirement.checkpoint_get_active_tags.provide(crat.get_active_tags)
190          retirement.checkpoint_tag_free.provide(crat.free_tag)
191  
192          m.submodules.func_blocks_unifier = self.func_blocks_unifier
193  
194          return m