ceb8f664d01fa349e8b83c62cc95ddb07ef28dc2
[gram.git] / gram / test / test_soc.py
1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
2
3 import random
4 import unittest
5
6 from nmigen import *
7 from nmigen.asserts import Assert, Assume
8 from nmigen_soc import wishbone, memory
9 from nmigen.lib.cdc import ResetSynchronizer
10
11 from lambdasoc.periph import Peripheral
12 from lambdasoc.soc.base import SoC
13
14 from gram.common import *
15 from gram.core import gramCore
16 from gram.phy.fakephy import FakePHY, SDRAM_VERBOSE_STD, SDRAM_VERBOSE_DBG
17 from gram.modules import MT41K256M16
18 from gram.frontend.wishbone import gramWishbone
19
20 from gram.core.multiplexer import _AntiStarvation
21 from gram.test.utils import *
22
23
24 class DDR3SoC(SoC, Elaboratable):
25 def __init__(self, *, clk_freq, dramcore_addr,
26 ddr_addr):
27 self._decoder = wishbone.Decoder(addr_width=30, data_width=32, granularity=8,
28 features={"cti", "bte"})
29
30 self.bus = wishbone.Interface(addr_width=30, data_width=32, granularity=8)
31
32 tck = 2/(2*2*100e6)
33 nphases = 2
34 databits = 16
35 nranks = 1
36 addressbits = 14
37 bankbits = 3
38 cl, cwl = get_cl_cw("DDR3", tck)
39 cl_sys_latency = get_sys_latency(nphases, cl)
40 cwl_sys_latency = get_sys_latency(nphases, cwl)
41 rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
42 wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
43 physettings = PhySettings(
44 phytype="ECP5DDRPHY",
45 memtype="DDR3",
46 databits=databits,
47 dfi_databits=4*databits,
48 nranks=nranks,
49 nphases=nphases,
50 rdphase=rdphase,
51 wrphase=wrphase,
52 rdcmdphase=rdcmdphase,
53 wrcmdphase=wrcmdphase,
54 cl=cl,
55 cwl=cwl,
56 read_latency=2 + cl_sys_latency + 2 + log2_int(4//nphases) + 4,
57 write_latency=cwl_sys_latency
58 )
59
60 ddrmodule = MT41K256M16(clk_freq, "1:2")
61 self.ddrphy = FakePHY(module=ddrmodule,
62 settings=physettings,
63 verbosity=SDRAM_VERBOSE_DBG)
64
65 self.dramcore = gramCore(
66 phy=self.ddrphy,
67 geom_settings=ddrmodule.geom_settings,
68 timing_settings=ddrmodule.timing_settings,
69 clk_freq=clk_freq)
70 self._decoder.add(self.dramcore.bus, addr=dramcore_addr)
71
72 self.drambone = gramWishbone(self.dramcore)
73 self._decoder.add(self.drambone.bus, addr=ddr_addr)
74
75 self.memory_map = self._decoder.bus.memory_map
76
77 self.clk_freq = clk_freq
78
79 def elaborate(self, platform):
80 m = Module()
81
82 m.submodules.decoder = self._decoder
83 m.submodules.ddrphy = self.ddrphy
84 m.submodules.dramcore = self.dramcore
85 m.submodules.drambone = self.drambone
86
87 m.d.comb += [
88 self.bus.connect(self._decoder.bus),
89 ]
90
91 return m
92
93 class SocTestCase(FHDLTestCase):
94 def init_seq(bus):
95 yield from wb_write(bus, 0x0, 0xE, 0xF) # DFII_CONTROL_ODT|DFII_CONTROL_RESET_N|DFI_CONTROL_CKE
96 yield from wb_write(bus, 0xC >> 2, 0x0, 0xF)
97 yield from wb_write(bus, 0x10 >> 2, 0x0, 0xF)
98 yield from wb_write(bus, 0x0, 0xC, 0xF)
99 yield from wb_write(bus, 0x0, 0xE, 0xF)
100
101 # MR2
102 yield from wb_write(bus, 0xC >> 2, 0x200, 0xF)
103 yield from wb_write(bus, 0x10 >> 2, 0x2, 0xF)
104 yield from wb_write(bus, 0x4 >> 2, 0xF, 0xF)
105 yield from wb_write(bus, 0x8 >> 2, 0x1, 0xF)
106
107 # MR3
108 yield from wb_write(bus, 0xC >> 2, 0x0, 0xF)
109 yield from wb_write(bus, 0x10 >> 2, 0x3, 0xF)
110 yield from wb_write(bus, 0x4 >> 2, 0xF, 0xF)
111 yield from wb_write(bus, 0x8 >> 2, 0x1, 0xF)
112
113 # MR1
114 yield from wb_write(bus, 0xC >> 2, 0x6, 0xF)
115 yield from wb_write(bus, 0x10 >> 2, 0x1, 0xF)
116 yield from wb_write(bus, 0x4 >> 2, 0xF, 0xF)
117 yield from wb_write(bus, 0x8 >> 2, 0x1, 0xF)
118
119 # MR0
120 yield from wb_write(bus, 0xC >> 2, 0x320, 0xF)
121 yield from wb_write(bus, 0x10 >> 2, 0x0, 0xF)
122 yield from wb_write(bus, 0x4 >> 2, 0xF, 0xF)
123 yield from wb_write(bus, 0x8 >> 2, 0x1, 0xF)
124 for i in range(200):
125 yield
126
127 # ZQ
128 yield from wb_write(bus, 0xC >> 2, 0x400, 0xF)
129 yield from wb_write(bus, 0x10 >> 2, 0x0, 0xF)
130 yield from wb_write(bus, 0x4 >> 2, 0x3, 0xF)
131 yield from wb_write(bus, 0x8 >> 2, 0x1, 0xF)
132 for i in range(200):
133 yield
134
135 yield from wb_write(bus, 0, 0x1, 0xF)
136 for i in range(2000):
137 yield
138
139 def test_multiple_reads(self):
140 soc = DDR3SoC(clk_freq=100e6,
141 dramcore_addr=0x00000000,
142 ddr_addr=0x10000000)
143
144 def process():
145 yield from SocTestCase.init_seq(soc.bus)
146
147 yield from wb_write(soc.bus, 0x10000000 >> 2, 0xACAB2020, 0xF, 128)
148 yield
149
150 # Check for data persistence
151 for i in range(10):
152 res = yield from wb_read(soc.bus, 0x10000000 >> 2, 0xF, 128)
153 yield
154 self.assertEqual(res, 0xACAB2020)
155
156 runSimulation(soc, process, "test_soc_multiple_reads.vcd")
157
158 def test_interleaved_read_write(self):
159 soc = DDR3SoC(clk_freq=100e6,
160 dramcore_addr=0x00000000,
161 ddr_addr=0x10000000)
162
163 def process():
164 yield from SocTestCase.init_seq(soc.bus)
165
166 yield from wb_write(soc.bus, 0x10000000 >> 2, 0xF00DFACE, 0xF, 128)
167 yield from wb_write(soc.bus, 0x10000004 >> 2, 0x12345678, 0xF, 128)
168 yield from wb_write(soc.bus, 0x10000008 >> 2, 0x00BA0BAB, 0xF, 128)
169
170 res = yield from wb_read(soc.bus, 0x10000000 >> 2, 0xF, 128)
171 self.assertEqual(res, 0xF00DFACE)
172
173 yield from wb_write(soc.bus, 0x10000008 >> 2, 0xCAFE1000, 0xF, 128)
174
175 res = yield from wb_read(soc.bus, 0x10000004 >> 2, 0xF, 128)
176 self.assertEqual(res, 0x12345678)
177
178 res = yield from wb_read(soc.bus, 0x10000008 >> 2, 0xF, 128)
179 self.assertEqual(res, 0xCAFE1000)
180
181 runSimulation(soc, process, "test_soc_interleaved_read_write.vcd")
182
183 def test_random_memtest(self):
184 soc = DDR3SoC(clk_freq=100e6,
185 dramcore_addr=0x00000000,
186 ddr_addr=0x10000000)
187
188 def process():
189 yield from SocTestCase.init_seq(soc.bus)
190
191 n = 64
192
193 memtest_values = []
194 for i in range(n):
195 memtest_values.append(random.randint(0, 0xFFFFFFFF))
196
197 # Write
198 for i in range(n):
199 yield from wb_write(soc.bus, (0x10000000 >> 2) + i, memtest_values[i], 0xF, 256)
200
201 # Read
202 for i in range(n):
203 self.assertEqual(memtest_values[i], (yield from wb_read(soc.bus, (0x10000000 >> 2) + i, 0xF, 256)))
204
205 runSimulation(soc, process, "test_soc_random_memtest.vcd")
206
207 def test_continuous_memtest(self):
208 soc = DDR3SoC(clk_freq=100e6,
209 dramcore_addr=0x00000000,
210 ddr_addr=0x10000000)
211
212 def process():
213 yield from SocTestCase.init_seq(soc.bus)
214
215 n = 128
216
217 # Write
218 for i in range(n):
219 yield from wb_write(soc.bus, (0x10000000 >> 2) + i, 0xFACE0000 | i, 0xF, 256)
220
221 # Read
222 for i in range(n):
223 self.assertEqual(0xFACE0000 | i, (yield from wb_read(soc.bus, (0x10000000 >> 2) + i, 0xF, 256)))
224
225 runSimulation(soc, process, "test_soc_continuous_memtest.vcd")
226
227
228 if __name__ == '__main__':
229 unittest.main()