1
1
#
2
2
# This file is part of LiteScope.
3
3
#
4
- # Copyright (c) 2016-2019 Florent Kermarrec <[email protected] >
4
+ # Copyright (c) 2016-2024 Florent Kermarrec <[email protected] >
5
5
# Copyright (c) 2018 bunnie <[email protected] >
6
6
# Copyright (c) 2016 Tim 'mithro' Ansell <[email protected] >
7
7
# SPDX-License-Identifier: BSD-2-Clause
8
8
9
9
from migen import *
10
10
from migen .genlib .cdc import MultiReg , PulseSynchronizer
11
11
12
+ from litex .gen import *
12
13
from litex .gen .genlib .misc import WaitTimer
14
+
13
15
from litex .build .tools import write_to_file
14
16
15
17
from litex .soc .interconnect .csr import *
16
- from litex .soc .cores .gpio import GPIOInOut
18
+
19
+ from litex .soc .cores .gpio import GPIOInOut
17
20
from litex .soc .interconnect import stream
18
21
19
22
# LiteScope IO -------------------------------------------------------------------------------------
20
23
21
- class LiteScopeIO (Module , AutoCSR ):
24
+ class LiteScopeIO (LiteXModule ):
22
25
def __init__ (self , data_width ):
23
26
self .data_width = data_width
24
27
self .input = Signal (data_width )
25
28
self .output = Signal (data_width )
26
29
27
30
# # #
28
31
29
- self .submodules . gpio = GPIOInOut (self .input , self .output )
32
+ self .gpio = GPIOInOut (self .input , self .output )
30
33
31
34
def get_csrs (self ):
32
35
return self .gpio .get_csrs ()
33
36
34
- # LiteScope Analyzer ------------------ -------------------------------------------------------------
37
+ # LiteScope Analyzer Constants/Layouts -------------------------------------------------------------
35
38
36
39
def core_layout (data_width ):
37
40
return [("data" , data_width ), ("hit" , 1 )]
38
41
42
+ # LiteScope Analyzer Trigger -----------------------------------------------------------------------
39
43
40
- class _Trigger (Module , AutoCSR ):
44
+ class _Trigger (LiteXModule ):
41
45
def __init__ (self , data_width , depth = 16 ):
42
46
self .sink = sink = stream .Endpoint (core_layout (data_width ))
43
47
self .source = source = stream .Endpoint (core_layout (data_width ))
@@ -52,17 +56,17 @@ def __init__(self, data_width, depth=16):
52
56
53
57
# # #
54
58
55
- # Control re-synchronization
59
+ # Control re-synchronization.
56
60
enable = Signal ()
57
61
enable_d = Signal ()
58
62
self .specials += MultiReg (self .enable .storage , enable , "scope" )
59
63
self .sync .scope += enable_d .eq (enable )
60
64
61
- # Status re-synchronization
65
+ # Status re-synchronization.
62
66
done = Signal ()
63
67
self .specials += MultiReg (done , self .done .status )
64
68
65
- # Memory and configuration
69
+ # Memory and configuration.
66
70
mem = stream .AsyncFIFO ([("mask" , data_width ), ("value" , data_width )], depth )
67
71
mem = ClockDomainsRenamer ({"write" : "sys" , "read" : "scope" })(mem )
68
72
self .submodules += mem
@@ -73,7 +77,7 @@ def __init__(self, data_width, depth=16):
73
77
self .mem_full .status .eq (~ mem .sink .ready )
74
78
]
75
79
76
- # Hit and memory read/flush
80
+ # Hit and memory read/flush.
77
81
hit = Signal ()
78
82
flush = WaitTimer (2 * depth )
79
83
flush = ClockDomainsRenamer ("scope" )(flush )
@@ -84,15 +88,17 @@ def __init__(self, data_width, depth=16):
84
88
mem .source .ready .eq ((enable & hit ) | ~ flush .done ),
85
89
]
86
90
87
- # Output
91
+ # Output.
88
92
self .comb += [
89
93
sink .connect (source ),
90
- # Done when all triggers have been consumed
94
+ # Done when all triggers have been consumed.
91
95
done .eq (~ mem .source .valid ),
92
96
source .hit .eq (done )
93
97
]
94
98
95
- class _SubSampler (Module , AutoCSR ):
99
+ # LiteScope Analyzer SubSampler --------------------------------------------------------------------
100
+
101
+ class _SubSampler (LiteXModule ):
96
102
def __init__ (self , data_width ):
97
103
self .sink = sink = stream .Endpoint (core_layout (data_width ))
98
104
self .source = source = stream .Endpoint (core_layout (data_width ))
@@ -121,8 +127,9 @@ def __init__(self, data_width):
121
127
source .valid .eq (sink .valid & done )
122
128
]
123
129
130
+ # LiteScope Analyzer Mux ---------------------------------------------------------------------------
124
131
125
- class _Mux (Module , AutoCSR ):
132
+ class _Mux (LiteXModule ):
126
133
def __init__ (self , data_width , n ):
127
134
self .sinks = sinks = [stream .Endpoint (core_layout (data_width )) for i in range (n )]
128
135
self .source = source = stream .Endpoint (core_layout (data_width ))
@@ -139,8 +146,9 @@ def __init__(self, data_width, n):
139
146
cases [i ] = sinks [i ].connect (source )
140
147
self .comb += Case (value , cases )
141
148
149
+ # LiteScope Analyzer Storage -----------------------------------------------------------------------
142
150
143
- class _Storage (Module , AutoCSR ):
151
+ class _Storage (LiteXModule ):
144
152
def __init__ (self , data_width , depth ):
145
153
self .sink = sink = stream .Endpoint (core_layout (data_width ))
146
154
@@ -156,7 +164,7 @@ def __init__(self, data_width, depth):
156
164
157
165
# # #
158
166
159
- # Control re-synchronization
167
+ # Control re-synchronization.
160
168
enable = Signal ()
161
169
enable_d = Signal ()
162
170
self .specials += MultiReg (self .enable .storage , enable , "scope" )
@@ -167,28 +175,27 @@ def __init__(self, data_width, depth):
167
175
self .specials += MultiReg (self .length .storage , length , "scope" )
168
176
self .specials += MultiReg (self .offset .storage , offset , "scope" )
169
177
170
- # Status re-synchronization
178
+ # Status re-synchronization.
171
179
done = Signal ()
172
180
level = Signal ().like (self .mem_level .status )
173
181
self .specials += MultiReg (done , self .done .status )
174
182
self .specials += MultiReg (level , self .mem_level .status )
175
183
176
- # Memory
184
+ # Memory.
177
185
mem = stream .SyncFIFO ([("data" , data_width )], depth , buffered = True )
178
186
mem = ClockDomainsRenamer ("scope" )(mem )
179
187
cdc = stream .AsyncFIFO ([("data" , data_width )], 4 )
180
- cdc = ClockDomainsRenamer (
181
- {"write" : "scope" , "read" : "sys" })(cdc )
188
+ cdc = ClockDomainsRenamer ({"write" : "scope" , "read" : "sys" })(cdc )
182
189
self .submodules += mem , cdc
183
190
184
191
self .comb += level .eq (mem .level )
185
192
186
- # Flush
193
+ # Flush.
187
194
mem_flush = WaitTimer (depth )
188
195
mem_flush = ClockDomainsRenamer ("scope" )(mem_flush )
189
196
self .submodules += mem_flush
190
197
191
- # FSM
198
+ # FSM.
192
199
fsm = FSM (reset_state = "IDLE" )
193
200
fsm = ClockDomainsRenamer ("scope" )(fsm )
194
201
self .submodules += fsm
@@ -222,7 +229,7 @@ def __init__(self, data_width, depth):
222
229
)
223
230
)
224
231
225
- # Memory read
232
+ # Memory read.
226
233
read_source = stream .Endpoint ([("data" , data_width )])
227
234
if data_width > read_width :
228
235
pad_bits = - data_width % read_width
@@ -238,9 +245,16 @@ def __init__(self, data_width, depth):
238
245
self .mem_data .status .eq (read_source .data )
239
246
]
240
247
248
+ # LiteScope Analyzer -------------------------------------------------------------------------------
241
249
242
- class LiteScopeAnalyzer (Module , AutoCSR ):
243
- def __init__ (self , groups , depth , samplerate = 1e12 , clock_domain = "sys" , trigger_depth = 16 , register = False , csr_csv = "analyzer.csv" ):
250
+ class LiteScopeAnalyzer (LiteXModule ):
251
+ def __init__ (self , groups , depth ,
252
+ samplerate = 1e12 ,
253
+ clock_domain = "sys" ,
254
+ trigger_depth = 16 ,
255
+ register = False ,
256
+ csr_csv = "analyzer.csv" ,
257
+ ):
244
258
self .groups = groups = self .format_groups (groups )
245
259
self .depth = depth
246
260
self .samplerate = int (samplerate )
@@ -251,12 +265,13 @@ def __init__(self, groups, depth, samplerate=1e12, clock_domain="sys", trigger_d
251
265
252
266
# # #
253
267
254
- # Create scope clock domain
255
- self .clock_domains . cd_scope = ClockDomain ()
268
+ # Create scope clock domain.
269
+ self .cd_scope = ClockDomain ()
256
270
self .comb += self .cd_scope .clk .eq (ClockSignal (clock_domain ))
257
271
258
- # Mux
259
- self .submodules .mux = _Mux (data_width , len (groups ))
272
+ # Mux.
273
+ # ----
274
+ self .mux = _Mux (data_width , len (groups ))
260
275
sd = getattr (self .sync , clock_domain )
261
276
for i , signals in groups .items ():
262
277
s = Cat (signals )
@@ -269,19 +284,23 @@ def __init__(self, groups, depth, samplerate=1e12, clock_domain="sys", trigger_d
269
284
self .mux .sinks [i ].data .eq (s )
270
285
]
271
286
272
- # Frontend
273
- self .submodules .trigger = _Trigger (data_width , depth = trigger_depth )
274
- self .submodules .subsampler = _SubSampler (data_width )
287
+ # Frontend.
288
+ # ---------
289
+ self .trigger = _Trigger (data_width , depth = trigger_depth )
290
+ self .subsampler = _SubSampler (data_width )
275
291
276
- # Storage
277
- self .submodules .storage = _Storage (data_width , depth )
292
+ # Storage.
293
+ # --------
294
+ self .storage = _Storage (data_width , depth )
278
295
279
- # Pipeline
280
- self .submodules .pipeline = stream .Pipeline (
281
- self .mux .source ,
296
+ # Pipeline: Mux -> Trigger -> Subsampler -> Storage.
297
+ # --------------------------------------------------
298
+ self .pipeline = stream .Pipeline (
299
+ self .mux ,
282
300
self .trigger ,
283
301
self .subsampler ,
284
- self .storage .sink )
302
+ self .storage ,
303
+ )
285
304
286
305
def format_groups (self , groups ):
287
306
if not isinstance (groups , dict ):
0 commit comments