Skip to content

Commit

Permalink
better handle arrays and structs
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasKl committed May 13, 2024
1 parent 7f5747b commit b7972b7
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 45 deletions.
35 changes: 35 additions & 0 deletions tests/test_trace_eq.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,41 @@ def test_rising_clocks(self):
def test_overflow(self):
self.eval_eq('(count tb.overflow')

def test_signals(self):
self.eval_eq('SIGNALS')

def test_scopes(self):
self.eval_eq('SCOPES')

def test_local_scopes(self):
self.eval_eq('LOCAL-SCOPES')
self.eval_eq("(in-scope 'tb CS)")
self.eval_eq("(in-scope 'tb LOCAL-SCOPES)")

def test_local_signals(self):
wal = "(in-scope 'tb LOCAL-SIGNALS)"
res = list(map(lambda t: self.wal_eval([t, wal]), self.traces))

for pair in combinations(res, 2):
self.assertEqual(sorted(pair[0]), sorted(pair[1]))


class SVArrayEqualTest(TraceEqTest, unittest.TestCase):
'''Test counter traces for equality'''

def setUp(self):
self.traces = ['sv_struct_array.vcd', 'sv_struct_array.fst']
super().setUp()

def test_group_clk(self):
self.eval_eq('(groups something)')

def test_signals(self):
self.eval_eq('SIGNALS')

def test_scopes(self):
self.eval_eq('SCOPES')

def test_local_scopes(self):
self.eval_eq('LOCAL-SCOPES')
self.eval_eq("(in-scope 'tb CS)")
Expand Down
25 changes: 22 additions & 3 deletions tests/test_trace_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import unittest

from wal.core import Wal
from wal.ast_defs import WalEvalError

class BasicParserTest(unittest.TestCase):
'''Test trace readers'''
Expand All @@ -10,6 +11,24 @@ def test_sv_arrays(self):
'''Test SystemVerilog arrays'''
for trace_format in ['vcd', 'fst']:
wal = Wal()
wal.load(f'tests/traces/array.{trace_format}')
self.assertEqual(wal.eval_str('TOP.tb.data<0>'), 2)
self.assertEqual(wal.eval_str('TOP.tb.data<1>'), 0)
wal.load(f'tests/traces/sv_struct_array.{trace_format}')
self.assertEqual(wal.eval_str('TOP.tb.data<0>.data.something'), 5)


class ReadUndefinedSignalTest(unittest.TestCase):
'''Test trace readers'''

def test_read_undefined_signals(self):
'''Test SystemVerilog arrays'''
for trace_format in ['vcd', 'fst']:
wal = Wal()
wal.load(f'tests/traces/sv_struct_array.{trace_format}')

with self.assertRaises(WalEvalError):
wal.eval_str('TOP.tb.data<0>.wrongname')

with self.assertRaises(WalEvalError):
wal.eval_str('(in-scope "TOP.tb.data<0>" ~wrongname)')

with self.assertRaises(WalEvalError):
wal.eval_str('(in-group "TOP.tb.data<0>" #.wrongname)')
Binary file removed tests/traces/array.fst
Binary file not shown.
33 changes: 0 additions & 33 deletions tests/traces/array.vcd

This file was deleted.

Binary file added tests/traces/sv_struct_array.fst
Binary file not shown.
25 changes: 25 additions & 0 deletions tests/traces/sv_struct_array.vcd
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
$version Generated by VerilatedVcd $end
$timescale 1ps $end

$scope module TOP $end
$scope module tb $end
$scope module data[0] $end
$scope module data $end
$var wire 3 # something [2:0] $end
$upscope $end
$upscope $end
$scope module data[1] $end
$scope module data $end
$var wire 3 $ something [2:0] $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end


#0
b101 #
b000 $
#10
b010 #
12 changes: 4 additions & 8 deletions wal/implementation/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,10 +431,8 @@ def op_resolve_scope(seval, args):
else: # if scope is not a real scope it must be a group name, no dot required
name = seval.global_environment.read('CS') + args[0].name

if seval.traces.contains(name):
return seval.traces.signal_value(name)

return None
assert seval.traces.contains(name), f'resolve-scope: No signal with name "{name}"'
return seval.traces.signal_value(name)


def op_set_scope(seval, args):
Expand Down Expand Up @@ -542,10 +540,8 @@ def op_resolve_group(seval, args):

name = seval.group + args[0].name

if seval.traces.contains(name):
return seval.traces.signal_value(name)

return None
assert seval.traces.contains(name), f'resolve-group: No signal with name "{name}"'
return seval.traces.signal_value(name)


def op_slice(seval, args):
Expand Down
6 changes: 6 additions & 0 deletions wal/trace/fst.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ def __init__(self, file, tid, container, from_string=False, keep_signals=None):
(self.scopes, signals) = fst.get_scopes_signals2(self.fst)
self.references_to_ids = signals.by_name

# rename grouped scopes
self.scopes = [
re.sub(r'\(([0-9]+)\)', r'<\1>', scope) for scope in self.scopes]
self.scopes = [
re.sub(r'\[([0-9]+)\]', r'<\1>', scope) for scope in self.scopes]

# get mapping from name to tid and remove trailing signal width, ' [31:0]' etc.
self.references_to_ids = {re.sub(r' *\[\d+:\d+\]', '', k): v for
k, v in self.references_to_ids.items()}
Expand Down
8 changes: 7 additions & 1 deletion wal/trace/vcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ def parse(self, vcddata):
# header section
while (not header_done) and tokens:
if tokens[i] == '$scope':
scope.append(tokens[i + 2])
name = tokens[i + 2]

# array entries should not clash with WAL operators
name = re.sub(r'\[([0-9]+)\]', r'<\1>', name)
name = re.sub(r'\(([0-9]+)\)', r'<\1>', name)

scope.append(name)
self.scopes.append('.'.join(scope))
i += 4
elif tokens[i] == '$var':
Expand Down

0 comments on commit b7972b7

Please sign in to comment.