4c33dbb72208669517e6df5c0274b4a2a20aca18
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_core
import *
18 from litex
.soc
.integration
.soc_sdram
import *
19 from litex
.soc
.integration
.builder
import *
20 from litex
.soc
.integration
.soc
import *
21 from litex
.soc
.cores
.bitbang
import *
22 from litex
.soc
.cores
.cpu
import CPUS
24 from litedram
import modules
as litedram_modules
25 from litedram
.modules
import parse_spd_hexdump
26 from litedram
.common
import *
27 from litedram
.phy
.model
import SDRAMPHYModel
29 from liteeth
.phy
.model
import LiteEthPHYModel
30 from liteeth
.mac
import LiteEthMAC
31 from liteeth
.core
.arp
import LiteEthARP
32 from liteeth
.core
.ip
import LiteEthIP
33 from liteeth
.core
.udp
import LiteEthUDP
34 from liteeth
.core
.icmp
import LiteEthICMP
35 from liteeth
.core
import LiteEthUDPIPCore
36 from liteeth
.frontend
.etherbone
import LiteEthEtherbone
37 from liteeth
.common
import *
39 from litescope
import LiteScopeAnalyzer
41 # IOs ----------------------------------------------------------------------------------------------
44 ("sys_clk", 0, Pins(1)),
45 ("sys_rst", 0, Pins(1)),
47 Subsignal("source_valid", Pins(1)),
48 Subsignal("source_ready", Pins(1)),
49 Subsignal("source_data", Pins(8)),
51 Subsignal("sink_valid", Pins(1)),
52 Subsignal("sink_ready", Pins(1)),
53 Subsignal("sink_data", Pins(8)),
56 Subsignal("tx", Pins(1)),
57 Subsignal("rx", Pins(1)),
60 Subsignal("source_valid", Pins(1)),
61 Subsignal("source_ready", Pins(1)),
62 Subsignal("source_data", Pins(8)),
64 Subsignal("sink_valid", Pins(1)),
65 Subsignal("sink_ready", Pins(1)),
66 Subsignal("sink_data", Pins(8)),
69 Subsignal("scl", Pins(1)),
70 Subsignal("sda_out", Pins(1)),
71 Subsignal("sda_in", Pins(1)),
75 # Platform -----------------------------------------------------------------------------------------
77 class Platform(SimPlatform
):
79 SimPlatform
.__init
__(self
, "SIM", _io
)
81 # DFI PHY model settings ---------------------------------------------------------------------------
83 sdram_module_nphases
= {
92 def get_sdram_phy_settings(memtype
, data_width
, clk_freq
):
93 nphases
= sdram_module_nphases
[memtype
]
96 # Settings from gensdrphy
105 elif memtype
in ["DDR", "LPDDR"]:
106 # Settings from s6ddrphy
115 elif memtype
in ["DDR2", "DDR3"]:
116 # Settings from s7ddrphy
117 tck
= 2/(2*nphases
*clk_freq
)
119 cl
, cwl
= get_cl_cw(memtype
, tck
)
120 cl_sys_latency
= get_sys_latency(nphases
, cl
)
121 cwl
= cwl
+ cmd_latency
122 cwl_sys_latency
= get_sys_latency(nphases
, cwl
)
123 rdcmdphase
, rdphase
= get_sys_phases(nphases
, cl_sys_latency
, cl
)
124 wrcmdphase
, wrphase
= get_sys_phases(nphases
, cwl_sys_latency
, cwl
)
125 read_latency
= 2 + cl_sys_latency
+ 2 + 3
126 write_latency
= cwl_sys_latency
127 elif memtype
== "DDR4":
128 # Settings from usddrphy
129 tck
= 2/(2*nphases
*clk_freq
)
131 cl
, cwl
= get_cl_cw(memtype
, tck
)
132 cl_sys_latency
= get_sys_latency(nphases
, cl
)
133 cwl
= cwl
+ cmd_latency
134 cwl_sys_latency
= get_sys_latency(nphases
, cwl
)
135 rdcmdphase
, rdphase
= get_sys_phases(nphases
, cl_sys_latency
, cl
)
136 wrcmdphase
, wrphase
= get_sys_phases(nphases
, cwl_sys_latency
, cwl
)
137 read_latency
= 2 + cl_sys_latency
+ 1 + 3
138 write_latency
= cwl_sys_latency
140 sdram_phy_settings
= {
144 "rdcmdphase": rdcmdphase
,
145 "wrcmdphase": wrcmdphase
,
148 "read_latency": read_latency
,
149 "write_latency": write_latency
,
153 phytype
= "SDRAMPHYModel",
155 databits
= data_width
,
156 dfi_databits
= data_width
if memtype
== "SDR" else 2*data_width
,
157 **sdram_phy_settings
,
160 # Simulation SoC -----------------------------------------------------------------------------------
162 class SimSoC(SoCCore
):
164 "ethmac": 0xb0000000,
166 mem_map
.update(SoCCore
.mem_map
)
170 with_ethernet
= False,
171 with_etherbone
= False,
172 etherbone_mac_address
= 0x10e2d5000001,
173 etherbone_ip_address
= "192.168.1.51",
174 with_analyzer
= False,
175 sdram_module
= "MT48LC16M16",
177 sdram_data_width
= 32,
178 sdram_spd_data
= None,
183 platform
= Platform()
184 sys_clk_freq
= int(1e6
)
186 # SoCCore ----------------------------------------------------------------------------------
187 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
188 ident
= "LiteX Simulation",
189 ident_version
= True,
192 # CRG --------------------------------------------------------------------------------------
193 self
.submodules
.crg
= CRG(platform
.request("sys_clk"))
195 # SDRAM ------------------------------------------------------------------------------------
197 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
198 if sdram_spd_data
is None:
199 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
200 sdram_rate
= "1:{}".format(sdram_module_nphases
[sdram_module_cls
.memtype
])
201 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
203 sdram_module
= litedram_modules
.SDRAMModule
.from_spd_data(sdram_spd_data
, sdram_clk_freq
)
204 phy_settings
= get_sdram_phy_settings(
205 memtype
= sdram_module
.memtype
,
206 data_width
= sdram_data_width
,
207 clk_freq
= sdram_clk_freq
)
208 self
.submodules
.sdrphy
= SDRAMPHYModel(
209 module
= sdram_module
,
210 settings
= phy_settings
,
211 clk_freq
= sdram_clk_freq
,
212 verbosity
= sdram_verbosity
,
214 self
.add_sdram("sdram",
216 module
= sdram_module
,
217 origin
= self
.mem_map
["main_ram"],
218 size
= kwargs
.get("max_sdram_size", 0x40000000),
219 l2_cache_size
= kwargs
.get("l2_size", 8192),
220 l2_cache_min_data_width
= kwargs
.get("min_l2_data_width", 128),
221 l2_cache_reverse
= False
223 # Reduce memtest size for simulation speedup
224 self
.add_constant("MEMTEST_DATA_SIZE", 8*1024)
225 self
.add_constant("MEMTEST_ADDR_SIZE", 8*1024)
227 #assert not (with_ethernet and with_etherbone)
229 if with_ethernet
and with_etherbone
:
230 etherbone_ip_address
= convert_ip(etherbone_ip_address
)
232 self
.submodules
.ethphy
= LiteEthPHYModel(self
.platform
.request("eth", 0))
233 self
.add_csr("ethphy")
235 self
.submodules
.ethmac
= LiteEthMAC(phy
=self
.ethphy
, dw
=8,
236 interface
= "hybrid",
237 endianness
= self
.cpu
.endianness
,
238 hw_mac
= etherbone_mac_address
)
241 self
.add_memory_region("ethmac", self
.mem_map
["ethmac"], 0x2000, type="io")
242 self
.add_wb_slave(self
.mem_regions
["ethmac"].origin
, self
.ethmac
.bus
, 0x2000)
243 self
.add_csr("ethmac")
244 self
.add_interrupt("ethmac")
246 self
.submodules
.arp
= LiteEthARP(self
.ethmac
, etherbone_mac_address
, etherbone_ip_address
, sys_clk_freq
, dw
=8)
247 self
.submodules
.ip
= LiteEthIP(self
.ethmac
, etherbone_mac_address
, etherbone_ip_address
, self
.arp
.table
, dw
=8)
248 self
.submodules
.icmp
= LiteEthICMP(self
.ip
, etherbone_ip_address
, dw
=8)
249 self
.submodules
.udp
= LiteEthUDP(self
.ip
, etherbone_ip_address
, dw
=8)
251 self
.submodules
.etherbone
= LiteEthEtherbone(self
.udp
, 1234, mode
="master")
252 self
.add_wb_master(self
.etherbone
.wishbone
.bus
)
254 # Ethernet ---------------------------------------------------------------------------------
257 self
.submodules
.ethphy
= LiteEthPHYModel(self
.platform
.request("eth", 0))
258 self
.add_csr("ethphy")
260 ethmac
= LiteEthMAC(phy
=self
.ethphy
, dw
=32,
261 interface
= "wishbone",
262 endianness
= self
.cpu
.endianness
)
264 ethmac
= ClockDomainsRenamer({"eth_tx": "ethphy_eth_tx", "eth_rx": "ethphy_eth_rx"})(ethmac
)
265 self
.submodules
.ethmac
= ethmac
266 self
.add_memory_region("ethmac", self
.mem_map
["ethmac"], 0x2000, type="io")
267 self
.add_wb_slave(self
.mem_regions
["ethmac"].origin
, self
.ethmac
.bus
, 0x2000)
268 self
.add_csr("ethmac")
269 self
.add_interrupt("ethmac")
271 # Etherbone --------------------------------------------------------------------------------
274 self
.submodules
.ethphy
= LiteEthPHYModel(self
.platform
.request("eth", 0)) # FIXME
275 self
.add_csr("ethphy")
277 ethcore
= LiteEthUDPIPCore(self
.ethphy
,
278 mac_address
= etherbone_mac_address
,
279 ip_address
= etherbone_ip_address
,
280 clk_freq
= sys_clk_freq
)
281 self
.submodules
.ethcore
= ethcore
283 self
.submodules
.etherbone
= LiteEthEtherbone(self
.ethcore
.udp
, 1234, mode
="master")
284 self
.add_wb_master(self
.etherbone
.wishbone
.bus
)
286 # Analyzer ---------------------------------------------------------------------------------
298 self
.submodules
.analyzer
= LiteScopeAnalyzer(analyzer_signals
,
300 clock_domain
= "sys",
301 csr_csv
= "analyzer.csv")
302 self
.add_csr("analyzer")
304 # I2C --------------------------------------------------------------------------------------
306 pads
= platform
.request("i2c", 0)
307 self
.submodules
.i2c
= I2CMasterSim(pads
)
310 # SDCard -----------------------------------------------------------------------------------
312 self
.add_sdcard("sdcard", use_emulator
=True)
314 # Build --------------------------------------------------------------------------------------------
317 parser
= argparse
.ArgumentParser(description
="Generic LiteX SoC Simulation")
319 soc_sdram_args(parser
)
320 parser
.add_argument("--threads", default
=1, help="Set number of threads (default=1)")
321 parser
.add_argument("--rom-init", default
=None, help="rom_init file")
322 parser
.add_argument("--ram-init", default
=None, help="ram_init file")
323 parser
.add_argument("--with-sdram", action
="store_true", help="Enable SDRAM support")
324 parser
.add_argument("--sdram-module", default
="MT48LC16M16", help="Select SDRAM chip")
325 parser
.add_argument("--sdram-data-width", default
=32, help="Set SDRAM chip data width")
326 parser
.add_argument("--sdram-init", default
=None, help="SDRAM init file")
327 parser
.add_argument("--sdram-from-spd-dump", default
=None, help="Generate SDRAM module based on data from SPD EEPROM dump")
328 parser
.add_argument("--sdram-verbosity", default
=0, help="Set SDRAM checker verbosity")
329 parser
.add_argument("--with-ethernet", action
="store_true", help="Enable Ethernet support")
330 parser
.add_argument("--with-etherbone", action
="store_true", help="Enable Etherbone support")
331 parser
.add_argument("--local-ip", default
="192.168.1.50", help="Local IP address of SoC (default=192.168.1.50)")
332 parser
.add_argument("--remote-ip", default
="192.168.1.100", help="Remote IP address of TFTP server (default=192.168.1.100)")
333 parser
.add_argument("--with-analyzer", action
="store_true", help="Enable Analyzer support")
334 parser
.add_argument("--with-i2c", action
="store_true", help="Enable I2C support")
335 parser
.add_argument("--with-sdcard", action
="store_true", help="Enable SDCard support")
336 parser
.add_argument("--trace", action
="store_true", help="Enable Tracing")
337 parser
.add_argument("--trace-fst", action
="store_true", help="Enable FST tracing (default=VCD)")
338 parser
.add_argument("--trace-start", default
=0, help="Cycle to start tracing")
339 parser
.add_argument("--trace-end", default
=-1, help="Cycle to end tracing")
340 parser
.add_argument("--opt-level", default
="O3", help="Compilation optimization level")
341 args
= parser
.parse_args()
343 soc_kwargs
= soc_sdram_argdict(args
)
344 builder_kwargs
= builder_argdict(args
)
346 sim_config
= SimConfig(default_clk
="sys_clk")
348 # Configuration --------------------------------------------------------------------------------
350 cpu
= CPUS
[soc_kwargs
.get("cpu_type", "vexriscv")]
351 if soc_kwargs
["uart_name"] == "serial":
352 soc_kwargs
["uart_name"] = "sim"
353 sim_config
.add_module("serial2console", "serial")
355 soc_kwargs
["integrated_rom_init"] = get_mem_data(args
.rom_init
, cpu
.endianness
)
356 if not args
.with_sdram
:
357 soc_kwargs
["integrated_main_ram_size"] = 0x10000000 # 256 MB
358 if args
.ram_init
is not None:
359 soc_kwargs
["integrated_main_ram_init"] = get_mem_data(args
.ram_init
, cpu
.endianness
)
361 assert args
.ram_init
is None
362 soc_kwargs
["integrated_main_ram_size"] = 0x0
363 soc_kwargs
["sdram_module"] = args
.sdram_module
364 soc_kwargs
["sdram_data_width"] = int(args
.sdram_data_width
)
365 soc_kwargs
["sdram_verbosity"] = int(args
.sdram_verbosity
)
366 if args
.sdram_from_spd_dump
:
367 soc_kwargs
["sdram_spd_data"] = parse_spd_hexdump(args
.sdram_from_spd_dump
)
369 if args
.with_ethernet
or args
.with_etherbone
:
370 sim_config
.add_module("ethernet", "eth", args
={"interface": "tap0", "ip": args
.remote_ip
})
373 sim_config
.add_module("spdeeprom", "i2c")
375 # SoC ------------------------------------------------------------------------------------------
377 with_sdram
= args
.with_sdram
,
378 with_ethernet
= args
.with_ethernet
,
379 with_etherbone
= args
.with_etherbone
,
380 with_analyzer
= args
.with_analyzer
,
381 with_i2c
= args
.with_i2c
,
382 with_sdcard
= args
.with_sdcard
,
383 sdram_init
= [] if args
.sdram_init
is None else get_mem_data(args
.sdram_init
, cpu
.endianness
),
385 if args
.ram_init
is not None:
386 soc
.add_constant("ROM_BOOT_ADDRESS", 0x40000000)
387 if args
.with_ethernet
:
389 soc
.add_constant("LOCALIP{}".format(i
+1), int(args
.local_ip
.split(".")[i
]))
391 soc
.add_constant("REMOTEIP{}".format(i
+1), int(args
.remote_ip
.split(".")[i
]))
393 # Build/Run ------------------------------------------------------------------------------------
394 builder_kwargs
["csr_csv"] = "csr.csv"
395 builder
= Builder(soc
, **builder_kwargs
)
396 vns
= builder
.build(run
=False, threads
=args
.threads
, sim_config
=sim_config
,
397 opt_level
= args
.opt_level
,
399 trace_fst
= args
.trace_fst
,
400 trace_start
= int(args
.trace_start
),
401 trace_end
= int(args
.trace_end
))
402 if args
.with_analyzer
:
403 soc
.analyzer
.export_csv(vns
, "analyzer.csv")
404 builder
.build(build
=False, threads
=args
.threads
, sim_config
=sim_config
,
405 opt_level
= args
.opt_level
,
407 trace_fst
= args
.trace
,
408 trace_start
= int(args
.trace_start
),
409 trace_end
= int(args
.trace_end
)
412 if __name__
== "__main__":