wavekit 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavekit
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: a fundamental package for digital circuit waveform analysis
5
5
  License-File: LICENSE
6
6
  Author: cxzzzz
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "wavekit"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "a fundamental package for digital circuit waveform analysis"
5
5
  authors = ["cxzzzz <cxz19961010@outlook.com>"]
6
6
  readme = "README.md"
@@ -19,3 +19,10 @@ from .signal import Signal as Signal
19
19
  from .waveform import Waveform as Waveform
20
20
 
21
21
  __all__ = ['Waveform', 'VcdReader', 'FsdbReader', 'Scope', 'Signal']
22
+
23
+ try:
24
+ from .readers.fsdb.reader import FsdbReader as FsdbReader
25
+
26
+ __all__.append('FsdbReader')
27
+ except ImportError:
28
+ pass
@@ -46,6 +46,10 @@ class Reader:
46
46
  def get_signal_width(self, signal: str) -> int:
47
47
  pass
48
48
 
49
+ @abstractmethod
50
+ def get_signal_range(self, signal: str) -> tuple[int]:
51
+ pass
52
+
49
53
  @staticmethod
50
54
  def value_change_to_waveform(
51
55
  value_change: np.ndarray,
@@ -82,8 +82,13 @@ cdef extern from "npi_fsdb.h":
82
82
  npiFsdbScopeFullName
83
83
  npiFsdbScopeDefName
84
84
  npiFsdbScopeType
85
-
86
-
85
+
86
+ ctypedef enum npiFsdbSigCompositeType_e:
87
+ npiFsdbSigCtArray
88
+ npiFsdbSigCtStruct
89
+ npiFsdbSigCtUnion
90
+ npiFsdbSigCtTaggedUnion
91
+ npiFsdbSigCtRecord
87
92
 
88
93
 
89
94
  npiFsdbFileHandle npi_fsdb_open( const NPI_BYTE8* name )
@@ -113,3 +118,5 @@ cdef extern from "npi_fsdb.h":
113
118
  npiFsdbSigHandle npi_fsdb_iter_sig_next( npiFsdbSigIter iter )
114
119
  npiFsdbSigIter npi_fsdb_iter_sig( npiFsdbScopeHandle scope )
115
120
  npiFsdbSigIter npi_fsdb_iter_member( npiFsdbSigHandle sig )
121
+ NPI_INT32 npi_fsdb_iter_scope_stop( npiFsdbScopeIter iter )
122
+ NPI_INT32 npi_fsdb_iter_sig_stop( npiFsdbSigIter iter )
@@ -10,37 +10,53 @@ from libc.stdlib cimport malloc, free
10
10
  from libc.string cimport strcpy, strlen
11
11
  from .npi_fsdb cimport *
12
12
 
13
+
13
14
  cdef class NpiFsdbScope:
15
+ pass
16
+
17
+
18
+ cdef class NpiFsdbNormalScope(NpiFsdbScope):
14
19
  cdef npiFsdbScopeHandle scope_handle
15
20
 
16
21
  @staticmethod
17
22
  cdef init(npiFsdbScopeHandle scope_handle):
18
- scope = NpiFsdbScope()
23
+ scope = NpiFsdbNormalScope()
19
24
  scope.scope_handle = scope_handle
20
25
  return scope
21
26
 
22
27
  def __init__(self):
23
28
  self.scope_handle = NULL
24
29
 
25
- def child_scope_list(self) -> list[NpiFsdbScope]:
30
+ def child_scope_list(self, include_signal_scope:bool = True) -> list[NpiFsdbScope]:
26
31
  assert self.scope_handle != NULL
27
-
28
32
  res = []
29
33
  child_scope_handle_iter = npi_fsdb_iter_child_scope(self.scope_handle)
34
+
30
35
  cdef npiFsdbScopeHandle child_scope_handle
31
36
  while True:
32
37
  child_scope_handle = npi_fsdb_iter_scope_next(child_scope_handle_iter)
33
38
  if child_scope_handle == NULL:
34
39
  break
35
- res.append(NpiFsdbScope.init(child_scope_handle))
36
-
40
+ res.append(NpiFsdbNormalScope.init(child_scope_handle))
41
+ npi_fsdb_iter_scope_stop(child_scope_handle_iter)
42
+
43
+
44
+ cdef npiFsdbSigHandle child_sig_handle
45
+ if include_signal_scope:
46
+ child_sig_handle_iter = npi_fsdb_iter_sig(self.scope_handle)
47
+ while True:
48
+ child_sig_handle = npi_fsdb_iter_sig_next(child_sig_handle_iter)
49
+ if child_sig_handle == NULL:
50
+ break
51
+ res.append(NpiFsdbSignalScope.init(child_sig_handle))
52
+ npi_fsdb_iter_sig_stop(child_sig_handle_iter)
37
53
  return res
38
54
 
39
55
  def signal_list(self) -> list[str]:
40
56
  assert self.scope_handle != NULL
41
57
 
42
58
  res = []
43
- cdef npiFsdbScopeHandle sig_handle_iter = npi_fsdb_iter_sig(self.scope_handle)
59
+ sig_handle_iter = npi_fsdb_iter_sig(self.scope_handle)
44
60
  cdef npiFsdbSigHandle sig_handle
45
61
  cdef const char* c_str
46
62
  while True:
@@ -50,21 +66,92 @@ cdef class NpiFsdbScope:
50
66
  c_str = npi_fsdb_sig_property_str(npiFsdbSigName, sig_handle)
51
67
  name = c_str.decode('ascii')
52
68
  res.append(name)
69
+ npi_fsdb_iter_sig_stop(sig_handle_iter)
53
70
 
54
71
  return res
55
72
 
56
73
  def name(self) -> str:
57
74
  assert self.scope_handle != NULL
58
- return npi_fsdb_scope_property_str(npiFsdbScopeName, self.scope_handle).decode('ascii')
75
+ name = npi_fsdb_scope_property_str(npiFsdbScopeName, self.scope_handle).decode('ascii')
76
+ return name
59
77
 
60
78
  def type(self) -> str:
61
79
  assert self.scope_handle != NULL
62
- return npi_fsdb_scope_property_str(npiFsdbScopeType, self.scope_handle).decode('ascii')
80
+ type_str = npi_fsdb_scope_property_str(npiFsdbScopeType, self.scope_handle).decode('ascii')
81
+ return type_str
63
82
 
64
83
  def def_name(self) -> str:
65
84
  assert self.scope_handle != NULL
66
- return npi_fsdb_scope_property_str(npiFsdbScopeDefName, self.scope_handle).decode('ascii')
85
+ def_name = npi_fsdb_scope_property_str(npiFsdbScopeDefName, self.scope_handle).decode('ascii')
86
+ return def_name
87
+
88
+ cdef class NpiFsdbSignalScope(NpiFsdbScope):
89
+ cdef npiFsdbSigHandle sig_handle
90
+
91
+ @staticmethod
92
+ cdef init(npiFsdbSigHandle sig_handle):
93
+ scope = NpiFsdbSignalScope()
94
+ scope.sig_handle = sig_handle
95
+ return scope
96
+
97
+ def __init__(self):
98
+ self.sig_handle = NULL
99
+
100
+ def child_scope_list(self, include_signal_scope:bool = True) -> list[NpiFsdbScope]:
101
+ assert self.sig_handle != NULL
102
+
103
+ cdef int has_member
104
+ cdef npiFsdbSigIter member_iter
105
+ cdef npiFsdbSigHandle member_handle
106
+
107
+ res = []
108
+ if include_signal_scope:
109
+ if npi_fsdb_sig_property(npiFsdbSigHasMember, self.sig_handle, &has_member) and has_member:
110
+ member_iter = npi_fsdb_iter_member(self.sig_handle)
111
+ while True:
112
+ member_handle = npi_fsdb_iter_sig_next(member_iter)
113
+ if member_handle == NULL:
114
+ break
115
+ res.append(NpiFsdbSignalScope.init(member_handle))
116
+ npi_fsdb_iter_sig_stop(member_iter)
117
+ return res
118
+
119
+ def signal_list(self) -> list[str]:
120
+ assert self.sig_handle != NULL
121
+
122
+ cdef const char* c_str
123
+ cdef npiFsdbSigIter member_iter
124
+ cdef npiFsdbSigHandle member_handle
125
+ cdef int has_member
126
+ res = []
67
127
 
128
+ if npi_fsdb_sig_property(npiFsdbSigHasMember, self.sig_handle, &has_member) and has_member:
129
+ member_iter = npi_fsdb_iter_member(self.sig_handle)
130
+ while True:
131
+ member_handle = npi_fsdb_iter_sig_next(member_iter)
132
+ if member_handle == NULL:
133
+ break
134
+ c_str = npi_fsdb_sig_property_str(npiFsdbSigName, member_handle)
135
+ name = c_str.decode('ascii')
136
+ name = name.split(".")
137
+ name = name[len(name)-1]
138
+ res.append(name)
139
+ npi_fsdb_iter_sig_stop(member_iter)
140
+ return res
141
+
142
+ def name(self) -> str:
143
+ assert self.sig_handle != NULL
144
+ name = npi_fsdb_sig_property_str(npiFsdbSigName, self.sig_handle).decode('ascii')
145
+ #TODO: this only works for non-array type (array's name is like data[0],can't be split by ".")
146
+ name = name.split(".")
147
+ name = name[len(name)-1]
148
+ return name
149
+
150
+ def type(self) -> str:
151
+ raise NotImplementedError("type property of signal scope is not supported")
152
+
153
+ def def_name(self) -> str:
154
+ raise NotImplementedError("def_name property of signal scope is not supported")
68
155
  @cython.boundscheck(False) # 关闭边界检查以提升性能
69
156
  @cython.wraparound(False) # 关闭负索引检查以提升性能
70
157
  cdef inline cstr_to_ull(char* str, unsigned int xz_value, int max_bit_num = 2147483647):
@@ -150,7 +237,7 @@ cdef inline fsdb_read_value_change(vct_handle: npiFsdbVctHandle, begin_time, end
150
237
 
151
238
  return result
152
239
 
153
- cdef get_signal_handle_width( npiFsdbSigHandle signal_handle):
240
+ cdef get_signal_handle_width(npiFsdbSigHandle signal_handle):
154
241
  cdef int has_member
155
242
  cdef int width
156
243
  cdef npiFsdbSigIter sub_signal_iter
@@ -167,11 +254,33 @@ cdef get_signal_handle_width( npiFsdbSigHandle signal_handle):
167
254
  width += get_signal_handle_width(sub_signal)
168
255
  return width
169
256
 
257
+ cdef get_signal_handle_range(npiFsdbSigHandle signal_handle):
258
+ cdef int has_member
259
+ cdef int type
260
+ cdef int left_range, right_range
261
+ assert(npi_fsdb_sig_property(npiFsdbSigHasMember, signal_handle, &has_member))
262
+ assert(npi_fsdb_sig_property(npiFsdbSigLeftRange, signal_handle, &left_range))
263
+ assert(npi_fsdb_sig_property(npiFsdbSigRightRange, signal_handle, &right_range))
264
+ return (left_range, right_range)
265
+
266
+ if(has_member != 0):
267
+ assert(npi_fsdb_sig_property(npiFsdbSigCompositeType, signal_handle, &type))
268
+ if(type == <int>npiFsdbSigCtArray):
269
+ return (left_range, right_range)
270
+ return None
271
+
170
272
  cdef class NpiFsdbReader:
171
273
  cdef npiFsdbFileHandle fsdb_handle
172
274
  cdef str file
173
275
 
174
276
  def __init__(self, str file):
277
+ import os
278
+
279
+ # 检查VERDI_HOME环境变量
280
+ verdi_home = os.environ.get('VERDI_HOME')
281
+ if verdi_home:
282
+ npi_lib_path = os.path.join(verdi_home, 'share/NPI/lib/LINUX64/libNPI.so')
283
+
175
284
  #cdef int argc = len(sys.argv)
176
285
  #cdef char** argv = <char**>malloc((argc + 1) * sizeof(char*))
177
286
 
@@ -188,6 +297,8 @@ cdef class NpiFsdbReader:
188
297
  file_str = file.encode('utf-8')
189
298
  cdef char* file_s = file_str
190
299
  self.fsdb_handle = npi_fsdb_open(file_s)
300
+ if(self.fsdb_handle == NULL):
301
+ raise OSError(f"Failed to open fsdb file :{file_str}")
191
302
 
192
303
 
193
304
 
@@ -195,10 +306,22 @@ cdef class NpiFsdbReader:
195
306
  self,
196
307
  str signal
197
308
  ) -> int:
309
+
310
+ cdef npiFsdbSigHandle signal_handle = npi_fsdb_sig_by_name(self.fsdb_handle, signal.encode('ascii'), NULL)
311
+ assert signal_handle != NULL, f"can't find signal: {signal}"
312
+
313
+ cdef int width = get_signal_handle_width(signal_handle)
314
+ return width
198
315
 
316
+ def get_signal_range(
317
+ self,
318
+ str signal
319
+ ) -> tuple[int,int]:
320
+
199
321
  cdef npiFsdbSigHandle signal_handle = npi_fsdb_sig_by_name(self.fsdb_handle, signal.encode('ascii'), NULL)
200
322
  assert signal_handle != NULL, f"can't find signal: {signal}"
201
- return get_signal_handle_width(signal_handle)
323
+
324
+ return get_signal_handle_range(signal_handle)
202
325
 
203
326
  @cython.boundscheck(False) # 关闭边界检查以提升性能
204
327
  @cython.wraparound(False) # 关闭负索引检查以提升性能
@@ -209,7 +332,7 @@ cdef class NpiFsdbReader:
209
332
  unsigned long long end_time,
210
333
  int xz_value
211
334
  ) -> np.ndarray:
212
-
335
+
213
336
  cdef npiFsdbSigHandle signal_handle = npi_fsdb_sig_by_name(self.fsdb_handle, signal.encode('ascii'), NULL)
214
337
  assert signal_handle != NULL, f"can't find signal: {signal}"
215
338
  cdef int width = get_signal_handle_width(signal_handle)
@@ -235,6 +358,7 @@ cdef class NpiFsdbReader:
235
358
  stat = npi_fsdb_goto_time(signal_vct_handle, <npiFsdbTime> begin_time)
236
359
  else:
237
360
  stat = npi_fsdb_goto_next(signal_vct_handle)
361
+
238
362
  if stat == 0:
239
363
  break
240
364
 
@@ -245,6 +369,7 @@ cdef class NpiFsdbReader:
245
369
  if cur_time > end_time:
246
370
  break
247
371
  time_array.push_back(cur_time)
372
+ first = False
248
373
 
249
374
  if width == 1: # opt for clk
250
375
  value_array[0].push_back(cstr_to_bit(<char*>cur_value.value.str, xz_value))
@@ -287,7 +412,8 @@ cdef class NpiFsdbReader:
287
412
  top_scope_handle = npi_fsdb_iter_scope_next(top_scope_iter)
288
413
  if top_scope_handle == NULL:
289
414
  break
290
- res.append(NpiFsdbScope.init(top_scope_handle))
415
+ res.append(NpiFsdbNormalScope.init(top_scope_handle))
416
+ npi_fsdb_iter_scope_stop(top_scope_iter)
291
417
  return res
292
418
 
293
419
  def min_time(self) -> int:
@@ -10,7 +10,7 @@ from ...scope import Scope
10
10
  from ...signal import Signal
11
11
  from ...waveform import Waveform
12
12
  from ..base import Reader
13
- from .npi_fsdb_reader import NpiFsdbReader, NpiFsdbScope
13
+ from .npi_fsdb_reader import NpiFsdbReader, NpiFsdbScope, NpiFsdbSignalScope
14
14
 
15
15
 
16
16
  class FsdbScope(Scope):
@@ -39,6 +39,13 @@ class FsdbScope(Scope):
39
39
  def child_scope_list(self) -> Sequence[Scope]:
40
40
  return [FsdbScope(c, self, self.reader) for c in self.handle.child_scope_list()]
41
41
 
42
+ @cached_property
43
+ def child_normal_scope_list(self) -> Sequence[Scope]:
44
+ return [
45
+ FsdbScope(c, self, self.reader)
46
+ for c in self.handle.child_scope_list(include_signal_scope=False)
47
+ ]
48
+
42
49
  @property
43
50
  def type(self) -> str:
44
51
  if not hasattr(self, '_type'):
@@ -65,8 +72,11 @@ class FsdbScope(Scope):
65
72
  return self.parent_scope.end_time if self.parent_scope else 0
66
73
 
67
74
  def preload_module_scope(self):
75
+ if isinstance(self.handle, NpiFsdbSignalScope):
76
+ return {}
77
+
68
78
  preloaded_module_scope = defaultdict(list)
69
- for c in self.child_scope_list:
79
+ for c in self.child_normal_scope_list:
70
80
  for module_name, module_scope_list in c.preload_module_scope().items():
71
81
  preloaded_module_scope[module_name].extend(module_scope_list)
72
82
 
@@ -141,6 +151,9 @@ class FsdbReader(Reader):
141
151
  def get_signal_width(self, signal: str) -> int:
142
152
  return self.file_handle.get_signal_width(signal)
143
153
 
154
+ def get_signal_range(self, signal: str) -> tuple[int]:
155
+ return self.file_handle.get_signal_range(signal)
156
+
144
157
  @property
145
158
  def begin_time(self) -> str:
146
159
  return self.file_handle.min_time()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes