accel.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. # Copyright (c) 2023 Victor Suarez Rovere <suarezvictor@gmail.com>
  2. # SPDX-License-Identifier: AGPL-3.0-only
  3. from litex.soc.interconnect import wishbone
  4. from litex.soc.interconnect.csr import *
  5. from litex.soc.integration.common import *
  6. from litex.soc.integration.soc_core import SoCMini
  7. from litex.soc.integration.builder import *
  8. from litex.soc.integration.soc import *
  9. from litedram.common import LiteDRAMNativePort
  10. from litex.build.generic_platform import *
  11. from litex.build.sim import SimPlatform
  12. class Accel(Module, AutoCSR):
  13. def __init__(self, name, arg_desc_layout, with_csr=True):
  14. self.name = name
  15. self.args = args = stream.Endpoint(arg_desc_layout)
  16. self.params = dict(
  17. # Clk / Rst.
  18. i_clock = ClockSignal("sys"),
  19. i_reset = ResetSignal("sys"), # Active High.
  20. # Run / Done
  21. i_in_run = args.valid,
  22. o_out_done = args.ready,
  23. )
  24. for arg, width in args.description.payload_layout:
  25. self.params["i_in_"+arg] = args.__getattr__(arg)
  26. if with_csr:
  27. self.add_csrs()
  28. def add_bus_arg(self, bus):
  29. adr = Signal(32);
  30. # Core instance.
  31. # -----------------
  32. self.params.update(dict(
  33. # Bus.
  34. o_out_bus_cyc = bus.cyc,
  35. o_out_bus_stb = bus.stb,
  36. o_out_bus_adr = adr,
  37. o_out_bus_we = bus.we,
  38. o_out_bus_dat_w = bus.dat_w,
  39. o_out_bus_sel = bus.sel,
  40. i_in_bus_ack = bus.ack,
  41. i_in_bus_dat_r = bus.dat_r,
  42. ))
  43. #FIXME: use dict
  44. if bus.data_width == 256:
  45. self.comb += bus.adr.eq(adr[5:])
  46. if bus.data_width == 128:
  47. self.comb += bus.adr.eq(adr[4:])
  48. if bus.data_width == 64:
  49. self.comb += bus.adr.eq(adr[3:])
  50. if bus.data_width == 32:
  51. self.comb += bus.adr.eq(adr[2:])
  52. def add_csrs(self):
  53. self.run = CSRStorage(reset=0)
  54. self.done = CSRStatus()
  55. self.comb += [
  56. self.args.valid.eq(self.run.storage),
  57. self.done.status.eq(self.args.ready),
  58. ]
  59. for arg, width in self.args.description.payload_layout:
  60. csr = CSRStorage(width, name=arg, reset=0)
  61. setattr(self, arg, csr)
  62. self.comb += getattr(self.args, arg).eq(csr.storage)
  63. def do_finalize(self):
  64. super().do_finalize()
  65. self.specials.coreinstance = Instance("M_"+self.name, **self.params)
  66. # Export builder -----------------------------------------------------------------------------------
  67. accel_io = [
  68. # Clk / Rst
  69. ("clk", 0, Pins(1)),
  70. ("rst", 1, Pins(1)),
  71. ]
  72. """
  73. #FIXME: does't work
  74. class AccelSoc(SoCMini):
  75. def __init__(self, core):
  76. platform = SimPlatform("Accel", accel_io)
  77. # CRG --------------------------------------------------------------------------------------
  78. self.submodules.crg = CRG(platform.request("clk"), platform.request("rst"))
  79. # SoCMini ----------------------------------------------------------------------------------
  80. SoCMini.__init__(self, platform, clk_freq=int(1e6), nterconnect_register=False)
  81. # Add core
  82. self.submodules.accelcore = core #there's need to make a submodule
  83. self.export_masterbus(core.dma_bus)
  84. def export_dram(self, port):
  85. # Expose DRAM native port
  86. self.platform.add_extension(get_native_user_port_ios("native_port", port.address_width, port.data_width))
  87. self.comb += connect_native_port(port, self.platform.request("native_port"))
  88. def export_masterbus(self, mbus):
  89. self.platform.add_extension(mbus.get_ios(mbus.name))
  90. wb_pads = self.platform.request(mbus.name)
  91. self.comb += mbus.connect_to_pads(wb_pads, mode="master")
  92. # SoC finalization -----------------------------------------------------------------------------
  93. def do_finalize(self):
  94. super().do_finalize()
  95. #export all slaves (including CSRs)
  96. for sname, bus in self.bus.slaves.items():
  97. ios = bus.get_ios(sname)
  98. self.platform.add_extension(ios)
  99. extpads = self.platform.request(sname)
  100. self.comb += bus.connect_to_pads(extpads, mode="slave")
  101. from litex.soc.integration.builder import Builder
  102. builder = Builder(self, output_dir=build_dir)
  103. builder.build(build_name=self.accelcore.name, run=False)
  104. """
  105. SDRAM_ACCESS_WIDTH = 128 #FIXME: should match glue code, and ideally matching sdram bus width (128-bit)
  106. class AccelImporterSoC(Module): #TODO: separate in base and derived class
  107. def __init__(self, corename, csr_base=0, busmaster_type="wishbone", debug=False):
  108. self.name = corename
  109. self.csr_base = csr_base
  110. self.mmap_s = s = wishbone.Interface() #CSR and others
  111. if busmaster_type == "wishbone":
  112. self.mmap_m = m = wishbone.Interface()
  113. if busmaster_type == "native":
  114. self.mmap_m = m = LiteDRAMNativePort("both", address_width=30, data_width=SDRAM_ACCESS_WIDTH)
  115. self.busmaster_type = busmaster_type
  116. if debug:
  117. self.sync += If(s.cyc & s.we,
  118. Display("Slave write at 0x%08X <= %d (ack %d)", s.adr, s.dat_w, s.ack))
  119. self.sync += If(s.cyc & ~s.we,
  120. Display("Slave read at 0x%08X => %d (ack %d)", s.adr, s.dat_r, s.ack))
  121. if busmaster_type == "wishbone":
  122. self.sync += If(m.cyc & m.we,
  123. Display("Master write at 0x%08X <= %d (ack %d)", m.adr, m.dat_w, m.ack))
  124. self.sync += If(m.cyc & ~m.we,
  125. Display("Master read at 0x%08X => %d (ack %d)", m.adr, m.dat_r, m.ack))
  126. if busmaster_type == "native":
  127. self.sync += If(m.wdata.valid & m.wdata.we,
  128. Display("Master native write at 0x%08X <= %d (ack %d)", m.cmd.addr, m.wdata.data, m.wdata.ready))
  129. self.sync += If(m.rdata.valid & m.rdata.ready,
  130. Display("Master native read at 0x%08X => %d (ack %d)", m.cmd.addr, m.rdata.data, m.rdata.valid))
  131. def instance_core(self, region):
  132. mmap_m = self.mmap_m
  133. mmap_s = self.mmap_s
  134. assert(mmap_s.data_width == 32)
  135. #normally maps 0x2000_0000 (CSR at CPU address 0x80000000) to 0 (generated soc CSR address)
  136. adr = Signal(30)
  137. self.comb += adr.eq(mmap_s.adr)
  138. self.comb += If((mmap_s.adr>=(region.origin//4)) & (mmap_s.adr<((region.origin+region.size)//4)),
  139. adr.eq(mmap_s.adr-(region.origin-self.csr_base)//4))
  140. params = dict(
  141. # Clk / Rst.
  142. i_clk = ClockSignal("sys"),
  143. i_rst = ResetSignal("sys"), # Active High.
  144. # MMAP slave
  145. i_mmap_s_adr = adr, #remapped address
  146. i_mmap_s_dat_w = mmap_s.dat_w,
  147. o_mmap_s_dat_r = mmap_s.dat_r,
  148. i_mmap_s_sel = mmap_s.sel,
  149. i_mmap_s_cyc = mmap_s.cyc,
  150. i_mmap_s_stb = mmap_s.stb,
  151. o_mmap_s_ack = mmap_s.ack,
  152. i_mmap_s_we = mmap_s.we,
  153. i_mmap_s_cti = mmap_s.cti,
  154. i_mmap_s_bte = mmap_s.bte,
  155. o_mmap_s_err = mmap_s.err,
  156. )
  157. # MMAP master
  158. if self.busmaster_type=="wishbone":
  159. params.update(dict(
  160. o_mmap_m_adr = mmap_m.adr,
  161. o_mmap_m_dat_w = mmap_m.dat_w,
  162. i_mmap_m_dat_r = mmap_m.dat_r,
  163. o_mmap_m_sel = mmap_m.sel,
  164. o_mmap_m_cyc = mmap_m.cyc,
  165. o_mmap_m_stb = mmap_m.stb,
  166. i_mmap_m_ack = mmap_m.ack,
  167. o_mmap_m_we = mmap_m.we,
  168. o_mmap_m_cti = mmap_m.cti,
  169. o_mmap_m_bte = mmap_m.bte,
  170. i_mmap_m_err = mmap_m.err,
  171. ))
  172. if self.busmaster_type=="native":
  173. params.update(dict(
  174. o_mmap_m_cmd_valid = mmap_m.cmd.valid,
  175. i_mmap_m_cmd_ready = mmap_m.cmd.ready,
  176. o_mmap_m_cmd_we = mmap_m.cmd.we,
  177. o_mmap_m_cmd_addr = mmap_m.cmd.addr,
  178. o_mmap_m_wdata_valid = mmap_m.wdata.valid,
  179. i_mmap_m_wdata_ready = mmap_m.wdata.ready,
  180. o_mmap_m_wdata_we = mmap_m.wdata.we,
  181. o_mmap_m_wdata_data = mmap_m.wdata.data,
  182. i_mmap_m_rdata_valid = mmap_m.rdata.valid,
  183. o_mmap_m_rdata_ready = mmap_m.rdata.ready,
  184. i_mmap_m_rdata_data = mmap_m.rdata.data,
  185. ))
  186. self.specials += Instance(self.name, **params)
  187. def connect_to_soc(self, soc):
  188. #master
  189. if self.busmaster_type == "wishbone":
  190. soc.bus.add_master(master=self.mmap_m)
  191. if self.busmaster_type == "native":
  192. soc.comb += self.mmap_m.connect(soc.sdram.crossbar.get_port(data_width=SDRAM_ACCESS_WIDTH))
  193. #slave
  194. region_name = self.name+"_region" #CSR base
  195. region = soc.bus.alloc_region(region_name, 0x1000, cached=False)
  196. soc.bus.add_slave(name=self.name+"_slave", slave=self.mmap_s, region=region)
  197. soc.add_constant(region_name, region.origin)
  198. soc.platform.add_source(self.name + ".v")
  199. self.instance_core(region)