/ coreblocks / socks / socks.py
socks.py
 1  from amaranth import *
 2  from amaranth.lib.wiring import Component, In, Out, connect, flipped
 3  
 4  from coreblocks.arch.isa_consts import InterruptCauseNumber
 5  from coreblocks.core import Core
 6  from coreblocks.params import GenParams
 7  from coreblocks.peripherals.wishbone import WishboneInterface, WishboneMuxer
 8  from coreblocks.priv.traps.interrupt_controller import ISA_RESERVED_INTERRUPTS
 9  from coreblocks.socks.clint import ClintPeriph
10  from coreblocks.socks.peripheral import bus_in_periph_range
11  
12  CLINT_BASE = 0xE1000000
13  
14  # This is a temporary wrapper solution to provide external memory-mapped components, required to run Linux.
15  # It is intended to be only usable with LiteX, that uses a simple core-facing interface and Wishbone bus
16  # (and is currenty the only supported integration).
17  # TODO: Replace this with a proper bus-agnostic (and multicore?) soultion at a later stage.
18  
19  
20  class Socks(Component):
21      wb_instr: WishboneInterface
22      wb_data: WishboneInterface
23      interrupts: Signal
24  
25      def __init__(self, core: Core, core_gen_params: GenParams):
26          super().__init__(
27              {
28                  "wb_instr": Out(WishboneInterface(core_gen_params.wb_params).signature),
29                  "wb_data": Out(WishboneInterface(core_gen_params.wb_params).signature),
30                  "interrupts": In(ISA_RESERVED_INTERRUPTS + core_gen_params.interrupt_custom_count),
31              }
32          )
33  
34          self.clint = ClintPeriph(base_addr=CLINT_BASE, wb_params=core_gen_params.wb_params)
35  
36          self.core = core
37          self.core_gen_params = core_gen_params
38  
39      def elaborate(self, platform):
40          m = Module()
41  
42          muxer_ssel = Signal(2)
43          periph_muxer = WishboneMuxer(self.core_gen_params.wb_params, 2, muxer_ssel)
44          periph_bus = self.clint.bus  # only one peripheral for now
45  
46          connect(m, self.core.wb_instr, flipped(self.wb_instr))
47  
48          connect(m, self.core.wb_data, periph_muxer.master_wb)
49          connect(m, periph_muxer.slaves[0], flipped(self.wb_data))
50  
51          connect(m, periph_muxer.slaves[1], periph_bus)
52  
53          clint_addr = Signal()
54          m.d.comb += clint_addr.eq(bus_in_periph_range(self.core.wb_data, self.clint))
55          m.d.comb += muxer_ssel.eq(Cat(~clint_addr, clint_addr))
56  
57          m.submodules.clint = self.clint
58          m.submodules.periph_muxer = periph_muxer
59  
60          m.submodules.core = self.core
61  
62          m.d.comb += self.core.interrupts[InterruptCauseNumber.MEI].eq(self.interrupts[InterruptCauseNumber.MEI])
63          m.d.comb += self.core.interrupts[InterruptCauseNumber.MTI].eq(self.clint.mtip)
64          m.d.comb += self.core.interrupts[InterruptCauseNumber.MSI].eq(self.clint.msip)
65          m.d.comb += self.core.interrupts[ISA_RESERVED_INTERRUPTS:].eq(self.interrupts[ISA_RESERVED_INTERRUPTS:])
66  
67          return m