3 # This file is Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr>
4 # This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
5 # This file is Copyright (c) 2017 Pierre-Olivier Vauboin <po@lambdaconcept>
12 from litex
.build
.generic_platform
import *
13 from litex
.build
.sim
import SimPlatform
14 from litex
.build
.sim
.config
import SimConfig
16 from litex
.soc
.integration
.common
import *
17 from litex
.soc
.integration
.soc_sdram
import *
18 from litex
.soc
.integration
.builder
import *
19 from litex
.soc
.integration
.soc
import *
21 from litedram
import modules
as litedram_modules
22 from litedram
.common
import *
23 from litedram
.phy
.model
import SDRAMPHYModel
25 from liteeth
.phy
.model
import LiteEthPHYModel
26 from liteeth
.mac
import LiteEthMAC
27 from liteeth
.core
.arp
import LiteEthARP
28 from liteeth
.core
.ip
import LiteEthIP
29 from liteeth
.core
.udp
import LiteEthUDP
30 from liteeth
.core
.icmp
import LiteEthICMP
31 from liteeth
.core
import LiteEthUDPIPCore
32 from liteeth
.frontend
.etherbone
import LiteEthEtherbone
33 from liteeth
.common
import *
35 from litescope
import LiteScopeAnalyzer
37 # IOs ----------------------------------------------------------------------------------------------
40 ("sys_clk", 0, Pins(1)),
41 ("sys_rst", 0, Pins(1)),
43 Subsignal("source_valid", Pins(1)),
44 Subsignal("source_ready", Pins(1)),
45 Subsignal("source_data", Pins(8)),
47 Subsignal("sink_valid", Pins(1)),
48 Subsignal("sink_ready", Pins(1)),
49 Subsignal("sink_data", Pins(8)),
52 Subsignal("tx", Pins(1)),
53 Subsignal("rx", Pins(1)),
56 Subsignal("source_valid", Pins(1)),
57 Subsignal("source_ready", Pins(1)),
58 Subsignal("source_data", Pins(8)),
60 Subsignal("sink_valid", Pins(1)),
61 Subsignal("sink_ready", Pins(1)),
62 Subsignal("sink_data", Pins(8)),
66 # Platform -----------------------------------------------------------------------------------------
68 class Platform(SimPlatform
):
70 SimPlatform
.__init
__(self
, "SIM", _io
)
72 # DFI PHY model settings ---------------------------------------------------------------------------
74 sdram_module_nphases
= {
83 def get_sdram_phy_settings(memtype
, data_width
, clk_freq
):
84 nphases
= sdram_module_nphases
[memtype
]
87 # Settings from gensdrphy
96 elif memtype
in ["DDR", "LPDDR"]:
97 # Settings from s6ddrphy
106 elif memtype
in ["DDR2", "DDR3"]:
107 # Settings from s7ddrphy
108 tck
= 2/(2*nphases
*clk_freq
)
110 cl
, cwl
= get_cl_cw(memtype
, tck
)
111 cl_sys_latency
= get_sys_latency(nphases
, cl
)
112 cwl
= cwl
+ cmd_latency
113 cwl_sys_latency
= get_sys_latency(nphases
, cwl
)
114 rdcmdphase
, rdphase
= get_sys_phases(nphases
, cl_sys_latency
, cl
)
115 wrcmdphase
, wrphase
= get_sys_phases(nphases
, cwl_sys_latency
, cwl
)
116 read_latency
= 2 + cl_sys_latency
+ 2 + 3
117 write_latency
= cwl_sys_latency
118 elif memtype
== "DDR4":
119 # Settings from usddrphy
120 tck
= 2/(2*nphases
*clk_freq
)
122 cl
, cwl
= get_cl_cw(memtype
, tck
)
123 cl_sys_latency
= get_sys_latency(nphases
, cl
)
124 cwl
= cwl
+ cmd_latency
125 cwl_sys_latency
= get_sys_latency(nphases
, cwl
)
126 rdcmdphase
, rdphase
= get_sys_phases(nphases
, cl_sys_latency
, cl
)
127 wrcmdphase
, wrphase
= get_sys_phases(nphases
, cwl_sys_latency
, cwl
)
128 read_latency
= 2 + cl_sys_latency
+ 1 + 3
129 write_latency
= cwl_sys_latency
131 sdram_phy_settings
= {
135 "rdcmdphase": rdcmdphase
,
136 "wrcmdphase": wrcmdphase
,
139 "read_latency": read_latency
,
140 "write_latency": write_latency
,
144 phytype
= "SDRAMPHYModel",
146 databits
= data_width
,
147 dfi_databits
= data_width
if memtype
== "SDR" else 2*data_width
,
148 **sdram_phy_settings
,
151 # Simulation SoC -----------------------------------------------------------------------------------
153 class SimSoC(SoCSDRAM
):
155 "ethmac": 0xb0000000,
157 mem_map
.update(SoCSDRAM
.mem_map
)
161 with_ethernet
= False,
162 with_etherbone
= False,
163 etherbone_mac_address
= 0x10e2d5000001,
164 etherbone_ip_address
= "192.168.1.51",
165 with_analyzer
= False,
166 sdram_module
= "MT48LC16M16",
168 sdram_data_width
= 32,
169 sdram_spd_data
= None,
172 platform
= Platform()
173 sys_clk_freq
= int(1e6
)
175 # SoCSDRAM ---------------------------------------------------------------------------------
176 SoCSDRAM
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
177 ident
= "LiteX Simulation", ident_version
=True,
180 # CRG --------------------------------------------------------------------------------------
181 self
.submodules
.crg
= CRG(platform
.request("sys_clk"))
183 # SDRAM ------------------------------------------------------------------------------------
185 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
186 if sdram_spd_data
is None:
187 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
188 sdram_rate
= "1:{}".format(sdram_module_nphases
[sdram_module_cls
.memtype
])
189 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
191 sdram_module
= litedram_modules
.SDRAMModule
.from_spd_data(sdram_spd_data
, sdram_clk_freq
)
192 phy_settings
= get_sdram_phy_settings(
193 memtype
= sdram_module
.memtype
,
194 data_width
= sdram_data_width
,
195 clk_freq
= sdram_clk_freq
)
196 self
.submodules
.sdrphy
= SDRAMPHYModel(
197 module
= sdram_module
,
198 settings
= phy_settings
,
199 clk_freq
= sdram_clk_freq
,
200 verbosity
= sdram_verbosity
,
204 sdram_module
.geom_settings
,
205 sdram_module
.timing_settings
)
206 # Reduce memtest size for simulation speedup
207 self
.add_constant("MEMTEST_DATA_SIZE", 8*1024)
208 self
.add_constant("MEMTEST_ADDR_SIZE", 8*1024)
210 #assert not (with_ethernet and with_etherbone)
212 if with_ethernet
and with_etherbone
:
214 etherbone_ip_address
= convert_ip(etherbone_ip_address
)
216 self
.submodules
.ethphy
= LiteEthPHYModel(self
.platform
.request("eth", 0))
217 self
.add_csr("ethphy")
219 self
.submodules
.ethmac
= LiteEthMAC(phy
=self
.ethphy
, dw
=dw
,
220 interface
= "hybrid",
221 endianness
= self
.cpu
.endianness
,
222 hw_mac
= etherbone_mac_address
)
225 self
.add_memory_region("ethmac", self
.mem_map
["ethmac"], 0x2000, type="io")
226 self
.add_wb_slave(self
.mem_regions
["ethmac"].origin
, self
.ethmac
.bus
, 0x2000)
227 self
.add_csr("ethmac")
228 self
.add_interrupt("ethmac")
230 self
.submodules
.arp
= LiteEthARP(self
.ethmac
, etherbone_mac_address
, etherbone_ip_address
, sys_clk_freq
, dw
=dw
)
231 self
.submodules
.ip
= LiteEthIP(self
.ethmac
, etherbone_mac_address
, etherbone_ip_address
, self
.arp
.table
, dw
=dw
)
232 self
.submodules
.icmp
= LiteEthICMP(self
.ip
, etherbone_ip_address
, dw
=dw
)
233 self
.submodules
.udp
= LiteEthUDP(self
.ip
, etherbone_ip_address
, dw
=dw
)
235 self
.submodules
.etherbone
= LiteEthEtherbone(self
.udp
, 1234, mode
="master")
236 self
.add_wb_master(self
.etherbone
.wishbone
.bus
)
238 # Ethernet ---------------------------------------------------------------------------------
241 self
.submodules
.ethphy
= LiteEthPHYModel(self
.platform
.request("eth", 0))
242 self
.add_csr("ethphy")
244 ethmac
= LiteEthMAC(phy
=self
.ethphy
, dw
=32,
245 interface
= "wishbone",
246 endianness
= self
.cpu
.endianness
)
248 ethmac
= ClockDomainsRenamer({"eth_tx": "ethphy_eth_tx", "eth_rx": "ethphy_eth_rx"})(ethmac
)
249 self
.submodules
.ethmac
= ethmac
250 self
.add_memory_region("ethmac", self
.mem_map
["ethmac"], 0x2000, type="io")
251 self
.add_wb_slave(self
.mem_regions
["ethmac"].origin
, self
.ethmac
.bus
, 0x2000)
252 self
.add_csr("ethmac")
253 self
.add_interrupt("ethmac")
255 # Etherbone --------------------------------------------------------------------------------
258 self
.submodules
.ethphy
= LiteEthPHYModel(self
.platform
.request("eth", 0)) # FIXME
259 self
.add_csr("ethphy")
261 ethcore
= LiteEthUDPIPCore(self
.ethphy
,
262 mac_address
= etherbone_mac_address
,
263 ip_address
= etherbone_ip_address
,
264 clk_freq
= sys_clk_freq
)
265 self
.submodules
.ethcore
= ethcore
267 self
.submodules
.etherbone
= LiteEthEtherbone(self
.ethcore
.udp
, 1234, mode
="master")
268 self
.add_wb_master(self
.etherbone
.wishbone
.bus
)
270 # Analyzer ---------------------------------------------------------------------------------
276 self
.submodules
.analyzer
= LiteScopeAnalyzer(analyzer_signals
, 512)
277 self
.add_csr("analyzer")
279 # Build --------------------------------------------------------------------------------------------
282 parser
= argparse
.ArgumentParser(description
="Generic LiteX SoC Simulation")
284 soc_sdram_args(parser
)
285 parser
.add_argument("--threads", default
=1, help="Set number of threads (default=1)")
286 parser
.add_argument("--rom-init", default
=None, help="rom_init file")
287 parser
.add_argument("--ram-init", default
=None, help="ram_init file")
288 parser
.add_argument("--with-sdram", action
="store_true", help="Enable SDRAM support")
289 parser
.add_argument("--sdram-module", default
="MT48LC16M16", help="Select SDRAM chip")
290 parser
.add_argument("--sdram-data-width", default
=32, help="Set SDRAM chip data width")
291 parser
.add_argument("--sdram-init", default
=None, help="SDRAM init file")
292 parser
.add_argument("--sdram-from-spd-data", default
=None, help="Generate SDRAM module based on SPD data from file")
293 parser
.add_argument("--sdram-verbosity", default
=0, help="Set SDRAM checker verbosity")
294 parser
.add_argument("--with-ethernet", action
="store_true", help="Enable Ethernet support")
295 parser
.add_argument("--with-etherbone", action
="store_true", help="Enable Etherbone support")
296 parser
.add_argument("--local-ip", default
="192.168.1.50", help="Local IP address of SoC (default=192.168.1.50)")
297 parser
.add_argument("--remote-ip", default
="192.168.1.100", help="Remote IP address of TFTP server (default=192.168.1.100)")
298 parser
.add_argument("--with-analyzer", action
="store_true", help="Enable Analyzer support")
299 parser
.add_argument("--trace", action
="store_true", help="Enable Tracing")
300 parser
.add_argument("--trace-fst", action
="store_true", help="Enable FST tracing (default=VCD)")
301 parser
.add_argument("--trace-start", default
=0, help="Cycle to start tracing")
302 parser
.add_argument("--trace-end", default
=-1, help="Cycle to end tracing")
303 parser
.add_argument("--opt-level", default
="O3", help="Compilation optimization level")
304 args
= parser
.parse_args()
306 soc_kwargs
= soc_sdram_argdict(args
)
307 builder_kwargs
= builder_argdict(args
)
309 sim_config
= SimConfig(default_clk
="sys_clk")
310 sim_config
.add_module("serial2console", "serial")
312 # Configuration --------------------------------------------------------------------------------
314 cpu_endianness
= "little"
315 if "cpu_type" in soc_kwargs
:
316 if soc_kwargs
["cpu_type"] in ["mor1kx", "lm32"]:
317 cpu_endianness
= "big"
318 soc_kwargs
["uart_name"] = "sim"
320 soc_kwargs
["integrated_rom_init"] = get_mem_data(args
.rom_init
, cpu_endianness
)
321 if not args
.with_sdram
:
322 soc_kwargs
["integrated_main_ram_size"] = 0x10000000 # 256 MB
323 if args
.ram_init
is not None:
324 soc_kwargs
["integrated_main_ram_init"] = get_mem_data(args
.ram_init
, cpu_endianness
)
326 assert args
.ram_init
is None
327 soc_kwargs
["integrated_main_ram_size"] = 0x0
328 soc_kwargs
["sdram_module"] = args
.sdram_module
329 soc_kwargs
["sdram_data_width"] = int(args
.sdram_data_width
)
330 soc_kwargs
["sdram_verbosity"] = int(args
.sdram_verbosity
)
331 if args
.sdram_from_spd_data
:
332 with
open(args
.sdram_from_spd_data
, "rb") as f
:
333 soc_kwargs
["sdram_spd_data"] = [int(b
) for b
in f
.read()]
335 if args
.with_ethernet
or args
.with_etherbone
:
336 sim_config
.add_module("ethernet", "eth", args
={"interface": "tap0", "ip": args
.remote_ip
})
338 # SoC ------------------------------------------------------------------------------------------
340 with_sdram
= args
.with_sdram
,
341 with_ethernet
= args
.with_ethernet
,
342 with_etherbone
= args
.with_etherbone
,
343 with_analyzer
= args
.with_analyzer
,
344 sdram_init
= [] if args
.sdram_init
is None else get_mem_data(args
.sdram_init
, cpu_endianness
),
346 if args
.ram_init
is not None:
347 soc
.add_constant("ROM_BOOT_ADDRESS", 0x40000000)
348 if args
.with_ethernet
:
350 soc
.add_constant("LOCALIP{}".format(i
+1), int(args
.local_ip
.split(".")[i
]))
352 soc
.add_constant("REMOTEIP{}".format(i
+1), int(args
.remote_ip
.split(".")[i
]))
354 # Build/Run ------------------------------------------------------------------------------------
355 builder_kwargs
["csr_csv"] = "csr.csv"
356 builder
= Builder(soc
, **builder_kwargs
)
357 vns
= builder
.build(run
=False, threads
=args
.threads
, sim_config
=sim_config
,
358 opt_level
= args
.opt_level
,
360 trace_fst
= args
.trace_fst
,
361 trace_start
= int(args
.trace_start
),
362 trace_end
= int(args
.trace_end
))
363 if args
.with_analyzer
:
364 soc
.analyzer
.export_csv(vns
, "analyzer.csv")
365 builder
.build(build
=False, threads
=args
.threads
, sim_config
=sim_config
,
366 opt_level
= args
.opt_level
,
368 trace_fst
= args
.trace
,
369 trace_start
= int(args
.trace_start
),
370 trace_end
= int(args
.trace_end
)
373 if __name__
== "__main__":