[#72179] move SAIF parsing code to driver.py and add it to SAIF testing pipeline
This commit is contained in:
parent
94de419932
commit
0e2cf72966
|
|
@ -66,6 +66,142 @@ class staticproperty(property):
|
|||
def __get__(self, owner_self, owner_cls):
|
||||
return self.fget()
|
||||
|
||||
#######################################################################
|
||||
#######################################################################
|
||||
# SAIF parser utilities
|
||||
|
||||
|
||||
class SAIFSignalBit:
|
||||
def __init__(self):
|
||||
self.last_val = 0
|
||||
self.high_time = 0
|
||||
self.low_time = 0
|
||||
self.transitions = 0
|
||||
|
||||
def aggregate(self, dt, new_val):
|
||||
if int(new_val) != int(self.last_val):
|
||||
self.transitions += 1
|
||||
|
||||
if self.last_val:
|
||||
self.high_time += dt
|
||||
|
||||
self.last_val = new_val
|
||||
|
||||
class SAIFSignal:
|
||||
def __init__(self, signal_name, signal_width = 0):
|
||||
self.name = signal_name
|
||||
self.width = signal_width
|
||||
self.last_time = 0
|
||||
|
||||
self.bits = []
|
||||
for _ in range(self.width):
|
||||
self.bits.append(SAIFSignalBit())
|
||||
|
||||
|
||||
class VCDToSAIFParser:
|
||||
def __init__(self):
|
||||
self.signal_definitions = {}
|
||||
self.signal_indirections = {}
|
||||
self.current_time = 0
|
||||
|
||||
def parse(self, vcd_filename):
|
||||
with open(vcd_filename, 'r') as vcd_file:
|
||||
for line in vcd_file:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
match = re.match(r'\$var\s+(\w+)\s+(\d+)\s+(\S+)\s+(\S+)\s*(\S*)\s*\$end', line)
|
||||
if match:
|
||||
_, signal_width, signal_id, signal_name, _ = match.groups()
|
||||
if signal_id in self.signal_indirections:
|
||||
continue
|
||||
|
||||
self.signal_indirections[signal_id] = signal_name
|
||||
self.signal_definitions[signal_name] = SAIFSignal(signal_name, int(signal_width))
|
||||
continue
|
||||
|
||||
match = re.match(r'\#(\d+)', line)
|
||||
if match:
|
||||
timestamp = match.groups()
|
||||
self.current_time = int(timestamp[0])
|
||||
continue
|
||||
|
||||
match = re.match(r'b(\d+)\s+(\S+)', line)
|
||||
if match:
|
||||
value, signal_id = match.groups()
|
||||
|
||||
dt = self.current_time - self.signal_definitions[self.signal_indirections[signal_id]].last_time
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].last_time = self.current_time
|
||||
|
||||
index = 0
|
||||
for bit in reversed(value):
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].bits[index].aggregate(dt, int(bit))
|
||||
index += 1
|
||||
|
||||
continue
|
||||
|
||||
match = re.match(r'(\d+)(\S+)', line)
|
||||
if match:
|
||||
value, signal_id = match.groups()
|
||||
|
||||
dt = self.current_time - self.signal_definitions[self.signal_indirections[signal_id]].last_time
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].last_time = self.current_time
|
||||
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].bits[0].aggregate(dt, int(value))
|
||||
|
||||
for _, signal in self.signal_definitions.items():
|
||||
for i in range(signal.width):
|
||||
if signal.bits[i].last_val == 1:
|
||||
signal.bits[i].high_time += self.current_time - signal.last_time
|
||||
|
||||
signal.bits[i].low_time = self.current_time - signal.bits[i].high_time
|
||||
|
||||
|
||||
class SAIFParser:
|
||||
def __init__(self):
|
||||
self.signal_definitions = {}
|
||||
|
||||
def parse(self, saif_filename):
|
||||
with open(saif_filename, 'r') as saif_file:
|
||||
for line in saif_file:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
match = re.search(r'(\w+)\[*(\d*)\]*\s+(\(T(.+)\))+', line)
|
||||
if match:
|
||||
signal_name, bit_index, bit_values, _ = match.groups()
|
||||
|
||||
if bit_index == '':
|
||||
bit_index = 0
|
||||
|
||||
if signal_name not in self.signal_definitions:
|
||||
self.signal_definitions[signal_name] = SAIFSignal(signal_name)
|
||||
|
||||
for _ in range(0, int(bit_index) - self.signal_definitions[signal_name].width + 1):
|
||||
self.signal_definitions[signal_name].bits.append(SAIFSignalBit())
|
||||
|
||||
self.signal_definitions[signal_name].width = int(bit_index) + 1
|
||||
|
||||
match = re.search(r'T0 (\d+)', bit_values)
|
||||
if match:
|
||||
low_time = match.groups()[0]
|
||||
|
||||
self.signal_definitions[signal_name].bits[int(bit_index)].low_time = low_time
|
||||
|
||||
match = re.search(r'T1 (\d+)', bit_values)
|
||||
if match:
|
||||
high_time = match.groups()[0]
|
||||
|
||||
self.signal_definitions[signal_name].bits[int(bit_index)].high_time = high_time
|
||||
|
||||
match = re.search(r'TC (\d+)', bit_values)
|
||||
if match:
|
||||
toggle_count = match.groups()[0]
|
||||
|
||||
self.signal_definitions[signal_name].bits[int(bit_index)].transitions = toggle_count
|
||||
|
||||
|
||||
#######################################################################
|
||||
#######################################################################
|
||||
|
|
@ -2368,9 +2504,38 @@ class VlTest:
|
|||
self.fst2vcd(fn1, tmp)
|
||||
self.vcd_identical(tmp, fn2)
|
||||
|
||||
def compare_saif_contents(self, first, second):
|
||||
# Golden SAIF contents object should have all bits declared, even if zero transitions
|
||||
for signal_name, signal in first.signal_definitions.items():
|
||||
tested_object_signal = second.signal_definitions[signal_name]
|
||||
|
||||
for bit in range(signal.width):
|
||||
golden_bit = signal.bits[bit]
|
||||
|
||||
valid_signal_width = tested_object_signal.width > bit
|
||||
|
||||
if int(golden_bit.transitions) <= 0 and valid_signal_width and int(tested_object_signal.bits[bit].transitions) > 0:
|
||||
print(f"{signal.name}[{bit}] (T0 {golden_bit.low_time}) (T1 {golden_bit.high_time}) (TC {golden_bit.transitions})")
|
||||
print(f"{signal.name}[{bit}] (T0 {tested_object_signal.bits[bit].low_time}) (T1 {tested_object_signal.bits[bit].high_time}) (TC {tested_object_signal.bits[bit].transitions})")
|
||||
self.error("Transitions number mismatch!\n")
|
||||
|
||||
if valid_signal_width:
|
||||
tested_bit = tested_object_signal.bits[bit]
|
||||
if int(golden_bit.transitions) != int(tested_bit.transitions) or int(golden_bit.high_time) != int(tested_bit.high_time) or int(golden_bit.low_time) != int(tested_bit.low_time):
|
||||
print(f"{signal.name}[{bit}] (T0 {golden_bit.low_time}) (T1 {golden_bit.high_time}) (TC {golden_bit.transitions})")
|
||||
print(f"{signal.name}[{bit}] (T0 {tested_bit.low_time}) (T1 {tested_bit.high_time}) (TC {tested_bit.transitions})")
|
||||
self.error("Signal bit mismatch!\n")
|
||||
|
||||
|
||||
def saif_identical(self, fn1: str, fn2: str) -> None:
|
||||
"""Test if two SAIF files have logically-identical contents"""
|
||||
#TODO: implement checking if two SAIF file are logically-identical
|
||||
vcd_to_saif_parser = VCDToSAIFParser()
|
||||
vcd_to_saif_parser.parse(fn2)
|
||||
|
||||
saif_parser = SAIFParser()
|
||||
saif_parser.parse(fn1)
|
||||
|
||||
self.compare_saif_contents(vcd_to_saif_parser, saif_parser)
|
||||
|
||||
def _vcd_read(self, filename: str) -> str:
|
||||
data = {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,625 @@
|
|||
$version Generated by VerilatedVcd $end
|
||||
$timescale 1ps $end
|
||||
$scope module top $end
|
||||
$var wire 1 # clk $end
|
||||
$var wire 8 $ state [7:0] $end
|
||||
$scope module t $end
|
||||
$var wire 1 # clk $end
|
||||
$var wire 1 % rst $end
|
||||
$var wire 8 $ state [7:0] $end
|
||||
$var wire 32 & cyc [31:0] $end
|
||||
$scope module c0 $end
|
||||
$var wire 1 # clk $end
|
||||
$var wire 1 % rst $end
|
||||
$var wire 8 $ out [7:0] $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
|
||||
|
||||
#0
|
||||
0#
|
||||
b00000000 $
|
||||
0%
|
||||
b00000000000000000000000000000000 &
|
||||
#10
|
||||
1#
|
||||
1%
|
||||
b00000000000000000000000000000001 &
|
||||
#15
|
||||
0#
|
||||
#20
|
||||
1#
|
||||
b00000001 $
|
||||
b00000000000000000000000000000010 &
|
||||
#25
|
||||
0#
|
||||
#30
|
||||
1#
|
||||
b00000010 $
|
||||
b00000000000000000000000000000011 &
|
||||
#35
|
||||
0#
|
||||
#40
|
||||
1#
|
||||
b00000011 $
|
||||
b00000000000000000000000000000100 &
|
||||
#45
|
||||
0#
|
||||
#50
|
||||
1#
|
||||
b00000100 $
|
||||
b00000000000000000000000000000101 &
|
||||
#55
|
||||
0#
|
||||
#60
|
||||
1#
|
||||
b00000101 $
|
||||
b00000000000000000000000000000110 &
|
||||
#65
|
||||
0#
|
||||
#70
|
||||
1#
|
||||
b00000110 $
|
||||
b00000000000000000000000000000111 &
|
||||
#75
|
||||
0#
|
||||
#80
|
||||
1#
|
||||
b00000111 $
|
||||
b00000000000000000000000000001000 &
|
||||
#85
|
||||
0#
|
||||
#90
|
||||
1#
|
||||
b00001000 $
|
||||
b00000000000000000000000000001001 &
|
||||
#95
|
||||
0#
|
||||
#100
|
||||
1#
|
||||
b00001001 $
|
||||
b00000000000000000000000000001010 &
|
||||
#105
|
||||
0#
|
||||
#110
|
||||
1#
|
||||
b00001010 $
|
||||
0%
|
||||
b00000000000000000000000000001011 &
|
||||
#115
|
||||
0#
|
||||
#120
|
||||
1#
|
||||
b00000000 $
|
||||
1%
|
||||
b00000000000000000000000000001100 &
|
||||
#125
|
||||
0#
|
||||
#130
|
||||
1#
|
||||
b00000001 $
|
||||
b00000000000000000000000000001101 &
|
||||
#135
|
||||
0#
|
||||
#140
|
||||
1#
|
||||
b00000010 $
|
||||
b00000000000000000000000000001110 &
|
||||
#145
|
||||
0#
|
||||
#150
|
||||
1#
|
||||
b00000011 $
|
||||
b00000000000000000000000000001111 &
|
||||
#155
|
||||
0#
|
||||
#160
|
||||
1#
|
||||
b00000100 $
|
||||
b00000000000000000000000000010000 &
|
||||
#165
|
||||
0#
|
||||
#170
|
||||
1#
|
||||
b00000101 $
|
||||
b00000000000000000000000000010001 &
|
||||
#175
|
||||
0#
|
||||
#180
|
||||
1#
|
||||
b00000110 $
|
||||
b00000000000000000000000000010010 &
|
||||
#185
|
||||
0#
|
||||
#190
|
||||
1#
|
||||
b00000111 $
|
||||
b00000000000000000000000000010011 &
|
||||
#195
|
||||
0#
|
||||
#200
|
||||
1#
|
||||
b00001000 $
|
||||
b00000000000000000000000000010100 &
|
||||
#205
|
||||
0#
|
||||
#210
|
||||
1#
|
||||
b00001001 $
|
||||
b00000000000000000000000000010101 &
|
||||
#215
|
||||
0#
|
||||
#220
|
||||
1#
|
||||
b00001010 $
|
||||
b00000000000000000000000000010110 &
|
||||
#225
|
||||
0#
|
||||
#230
|
||||
1#
|
||||
b00001011 $
|
||||
b00000000000000000000000000010111 &
|
||||
#235
|
||||
0#
|
||||
#240
|
||||
1#
|
||||
b00001100 $
|
||||
b00000000000000000000000000011000 &
|
||||
#245
|
||||
0#
|
||||
#250
|
||||
1#
|
||||
b00001101 $
|
||||
b00000000000000000000000000011001 &
|
||||
#255
|
||||
0#
|
||||
#260
|
||||
1#
|
||||
b00001110 $
|
||||
b00000000000000000000000000011010 &
|
||||
#265
|
||||
0#
|
||||
#270
|
||||
1#
|
||||
b00001111 $
|
||||
b00000000000000000000000000011011 &
|
||||
#275
|
||||
0#
|
||||
#280
|
||||
1#
|
||||
b00010000 $
|
||||
b00000000000000000000000000011100 &
|
||||
#285
|
||||
0#
|
||||
#290
|
||||
1#
|
||||
b00010001 $
|
||||
b00000000000000000000000000011101 &
|
||||
#295
|
||||
0#
|
||||
#300
|
||||
1#
|
||||
b00010010 $
|
||||
b00000000000000000000000000011110 &
|
||||
#305
|
||||
0#
|
||||
#310
|
||||
1#
|
||||
b00010011 $
|
||||
b00000000000000000000000000011111 &
|
||||
#315
|
||||
0#
|
||||
#320
|
||||
1#
|
||||
b00010100 $
|
||||
b00000000000000000000000000100000 &
|
||||
#325
|
||||
0#
|
||||
#330
|
||||
1#
|
||||
b00010101 $
|
||||
b00000000000000000000000000100001 &
|
||||
#335
|
||||
0#
|
||||
#340
|
||||
1#
|
||||
b00010110 $
|
||||
b00000000000000000000000000100010 &
|
||||
#345
|
||||
0#
|
||||
#350
|
||||
1#
|
||||
b00010111 $
|
||||
b00000000000000000000000000100011 &
|
||||
#355
|
||||
0#
|
||||
#360
|
||||
1#
|
||||
b00011000 $
|
||||
b00000000000000000000000000100100 &
|
||||
#365
|
||||
0#
|
||||
#370
|
||||
1#
|
||||
b00011001 $
|
||||
b00000000000000000000000000100101 &
|
||||
#375
|
||||
0#
|
||||
#380
|
||||
1#
|
||||
b00011010 $
|
||||
b00000000000000000000000000100110 &
|
||||
#385
|
||||
0#
|
||||
#390
|
||||
1#
|
||||
b00011011 $
|
||||
b00000000000000000000000000100111 &
|
||||
#395
|
||||
0#
|
||||
#400
|
||||
1#
|
||||
b00011100 $
|
||||
b00000000000000000000000000101000 &
|
||||
#405
|
||||
0#
|
||||
#410
|
||||
1#
|
||||
b00011101 $
|
||||
b00000000000000000000000000101001 &
|
||||
#415
|
||||
0#
|
||||
#420
|
||||
1#
|
||||
b00011110 $
|
||||
b00000000000000000000000000101010 &
|
||||
#425
|
||||
0#
|
||||
#430
|
||||
1#
|
||||
b00011111 $
|
||||
b00000000000000000000000000101011 &
|
||||
#435
|
||||
0#
|
||||
#440
|
||||
1#
|
||||
b00100000 $
|
||||
b00000000000000000000000000101100 &
|
||||
#445
|
||||
0#
|
||||
#450
|
||||
1#
|
||||
b00100001 $
|
||||
b00000000000000000000000000101101 &
|
||||
#455
|
||||
0#
|
||||
#460
|
||||
1#
|
||||
b00100010 $
|
||||
b00000000000000000000000000101110 &
|
||||
#465
|
||||
0#
|
||||
#470
|
||||
1#
|
||||
b00100011 $
|
||||
b00000000000000000000000000101111 &
|
||||
#475
|
||||
0#
|
||||
#480
|
||||
1#
|
||||
b00100100 $
|
||||
b00000000000000000000000000110000 &
|
||||
#485
|
||||
0#
|
||||
#490
|
||||
1#
|
||||
b00100101 $
|
||||
b00000000000000000000000000110001 &
|
||||
#495
|
||||
0#
|
||||
#500
|
||||
1#
|
||||
b00100110 $
|
||||
b00000000000000000000000000110010 &
|
||||
#505
|
||||
0#
|
||||
#510
|
||||
1#
|
||||
b00100111 $
|
||||
b00000000000000000000000000110011 &
|
||||
#515
|
||||
0#
|
||||
#520
|
||||
1#
|
||||
b00101000 $
|
||||
b00000000000000000000000000110100 &
|
||||
#525
|
||||
0#
|
||||
#530
|
||||
1#
|
||||
b00101001 $
|
||||
b00000000000000000000000000110101 &
|
||||
#535
|
||||
0#
|
||||
#540
|
||||
1#
|
||||
b00101010 $
|
||||
b00000000000000000000000000110110 &
|
||||
#545
|
||||
0#
|
||||
#550
|
||||
1#
|
||||
b00101011 $
|
||||
b00000000000000000000000000110111 &
|
||||
#555
|
||||
0#
|
||||
#560
|
||||
1#
|
||||
b00101100 $
|
||||
b00000000000000000000000000111000 &
|
||||
#565
|
||||
0#
|
||||
#570
|
||||
1#
|
||||
b00101101 $
|
||||
b00000000000000000000000000111001 &
|
||||
#575
|
||||
0#
|
||||
#580
|
||||
1#
|
||||
b00101110 $
|
||||
b00000000000000000000000000111010 &
|
||||
#585
|
||||
0#
|
||||
#590
|
||||
1#
|
||||
b00101111 $
|
||||
b00000000000000000000000000111011 &
|
||||
#595
|
||||
0#
|
||||
#600
|
||||
1#
|
||||
b00110000 $
|
||||
b00000000000000000000000000111100 &
|
||||
#605
|
||||
0#
|
||||
#610
|
||||
1#
|
||||
b00110001 $
|
||||
b00000000000000000000000000111101 &
|
||||
#615
|
||||
0#
|
||||
#620
|
||||
1#
|
||||
b00110010 $
|
||||
b00000000000000000000000000111110 &
|
||||
#625
|
||||
0#
|
||||
#630
|
||||
1#
|
||||
b00110011 $
|
||||
b00000000000000000000000000111111 &
|
||||
#635
|
||||
0#
|
||||
#640
|
||||
1#
|
||||
b00110100 $
|
||||
b00000000000000000000000001000000 &
|
||||
#645
|
||||
0#
|
||||
#650
|
||||
1#
|
||||
b00110101 $
|
||||
b00000000000000000000000001000001 &
|
||||
#655
|
||||
0#
|
||||
#660
|
||||
1#
|
||||
b00110110 $
|
||||
b00000000000000000000000001000010 &
|
||||
#665
|
||||
0#
|
||||
#670
|
||||
1#
|
||||
b00110111 $
|
||||
b00000000000000000000000001000011 &
|
||||
#675
|
||||
0#
|
||||
#680
|
||||
1#
|
||||
b00111000 $
|
||||
b00000000000000000000000001000100 &
|
||||
#685
|
||||
0#
|
||||
#690
|
||||
1#
|
||||
b00111001 $
|
||||
b00000000000000000000000001000101 &
|
||||
#695
|
||||
0#
|
||||
#700
|
||||
1#
|
||||
b00111010 $
|
||||
b00000000000000000000000001000110 &
|
||||
#705
|
||||
0#
|
||||
#710
|
||||
1#
|
||||
b00111011 $
|
||||
b00000000000000000000000001000111 &
|
||||
#715
|
||||
0#
|
||||
#720
|
||||
1#
|
||||
b00111100 $
|
||||
b00000000000000000000000001001000 &
|
||||
#725
|
||||
0#
|
||||
#730
|
||||
1#
|
||||
b00111101 $
|
||||
b00000000000000000000000001001001 &
|
||||
#735
|
||||
0#
|
||||
#740
|
||||
1#
|
||||
b00111110 $
|
||||
b00000000000000000000000001001010 &
|
||||
#745
|
||||
0#
|
||||
#750
|
||||
1#
|
||||
b00111111 $
|
||||
b00000000000000000000000001001011 &
|
||||
#755
|
||||
0#
|
||||
#760
|
||||
1#
|
||||
b01000000 $
|
||||
b00000000000000000000000001001100 &
|
||||
#765
|
||||
0#
|
||||
#770
|
||||
1#
|
||||
b01000001 $
|
||||
b00000000000000000000000001001101 &
|
||||
#775
|
||||
0#
|
||||
#780
|
||||
1#
|
||||
b01000010 $
|
||||
b00000000000000000000000001001110 &
|
||||
#785
|
||||
0#
|
||||
#790
|
||||
1#
|
||||
b01000011 $
|
||||
b00000000000000000000000001001111 &
|
||||
#795
|
||||
0#
|
||||
#800
|
||||
1#
|
||||
b01000100 $
|
||||
b00000000000000000000000001010000 &
|
||||
#805
|
||||
0#
|
||||
#810
|
||||
1#
|
||||
b01000101 $
|
||||
b00000000000000000000000001010001 &
|
||||
#815
|
||||
0#
|
||||
#820
|
||||
1#
|
||||
b01000110 $
|
||||
b00000000000000000000000001010010 &
|
||||
#825
|
||||
0#
|
||||
#830
|
||||
1#
|
||||
b01000111 $
|
||||
b00000000000000000000000001010011 &
|
||||
#835
|
||||
0#
|
||||
#840
|
||||
1#
|
||||
b01001000 $
|
||||
b00000000000000000000000001010100 &
|
||||
#845
|
||||
0#
|
||||
#850
|
||||
1#
|
||||
b01001001 $
|
||||
b00000000000000000000000001010101 &
|
||||
#855
|
||||
0#
|
||||
#860
|
||||
1#
|
||||
b01001010 $
|
||||
b00000000000000000000000001010110 &
|
||||
#865
|
||||
0#
|
||||
#870
|
||||
1#
|
||||
b01001011 $
|
||||
b00000000000000000000000001010111 &
|
||||
#875
|
||||
0#
|
||||
#880
|
||||
1#
|
||||
b01001100 $
|
||||
b00000000000000000000000001011000 &
|
||||
#885
|
||||
0#
|
||||
#890
|
||||
1#
|
||||
b01001101 $
|
||||
b00000000000000000000000001011001 &
|
||||
#895
|
||||
0#
|
||||
#900
|
||||
1#
|
||||
b01001110 $
|
||||
b00000000000000000000000001011010 &
|
||||
#905
|
||||
0#
|
||||
#910
|
||||
1#
|
||||
b01001111 $
|
||||
b00000000000000000000000001011011 &
|
||||
#915
|
||||
0#
|
||||
#920
|
||||
1#
|
||||
b01010000 $
|
||||
b00000000000000000000000001011100 &
|
||||
#925
|
||||
0#
|
||||
#930
|
||||
1#
|
||||
b01010001 $
|
||||
b00000000000000000000000001011101 &
|
||||
#935
|
||||
0#
|
||||
#940
|
||||
1#
|
||||
b01010010 $
|
||||
b00000000000000000000000001011110 &
|
||||
#945
|
||||
0#
|
||||
#950
|
||||
1#
|
||||
b01010011 $
|
||||
b00000000000000000000000001011111 &
|
||||
#955
|
||||
0#
|
||||
#960
|
||||
1#
|
||||
b01010100 $
|
||||
b00000000000000000000000001100000 &
|
||||
#965
|
||||
0#
|
||||
#970
|
||||
1#
|
||||
b01010101 $
|
||||
b00000000000000000000000001100001 &
|
||||
#975
|
||||
0#
|
||||
#980
|
||||
1#
|
||||
b01010110 $
|
||||
b00000000000000000000000001100010 &
|
||||
#985
|
||||
0#
|
||||
#990
|
||||
1#
|
||||
b01010111 $
|
||||
b00000000000000000000000001100011 &
|
||||
#995
|
||||
0#
|
||||
#1000
|
||||
1#
|
||||
b01011000 $
|
||||
b00000000000000000000000001100100 &
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
import re
|
||||
from collections import defaultdict
|
||||
|
||||
class SAIFSignalBit:
|
||||
def __init__(self):
|
||||
self.last_val = 0
|
||||
self.high_time = 0
|
||||
self.low_time = 0
|
||||
self.transitions = 0
|
||||
|
||||
def aggregate(self, dt, new_val):
|
||||
if int(new_val) != int(self.last_val):
|
||||
self.transitions += 1
|
||||
|
||||
if self.last_val:
|
||||
self.high_time += dt
|
||||
|
||||
self.last_val = new_val
|
||||
|
||||
class SAIFSignal:
|
||||
def __init__(self, signal_name, signal_width = 0):
|
||||
self.name = signal_name
|
||||
self.width = signal_width
|
||||
self.last_time = 0
|
||||
|
||||
self.bits = []
|
||||
for _ in range(self.width):
|
||||
self.bits.append(SAIFSignalBit())
|
||||
|
||||
|
||||
class VCDToSAIFParser:
|
||||
def __init__(self):
|
||||
self.signal_definitions = {}
|
||||
self.signal_indirections = {}
|
||||
self.current_time = 0
|
||||
|
||||
def parse(self, vcd_filename):
|
||||
with open(vcd_filename, 'r') as vcd_file:
|
||||
for line in vcd_file:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
match = re.match(r'\$var\s+(\w+)\s+(\d+)\s+(\S+)\s+(\S+)\s*(\S*)\s*\$end', line)
|
||||
if match:
|
||||
_, signal_width, signal_id, signal_name, _ = match.groups()
|
||||
self.signal_indirections[signal_id] = signal_name
|
||||
self.signal_definitions[signal_name] = SAIFSignal(signal_name, int(signal_width))
|
||||
continue
|
||||
|
||||
match = re.match(r'\#(\d+)', line)
|
||||
if match:
|
||||
timestamp = match.groups()
|
||||
self.current_time = int(timestamp[0])
|
||||
continue
|
||||
|
||||
match = re.match(r'b(\d+)\s+(\S+)', line)
|
||||
if match:
|
||||
value, signal_id = match.groups()
|
||||
|
||||
dt = self.current_time - self.signal_definitions[self.signal_indirections[signal_id]].last_time
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].last_time = self.current_time
|
||||
|
||||
index = 0
|
||||
for bit in reversed(value):
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].bits[index].aggregate(dt, int(bit))
|
||||
index += 1
|
||||
|
||||
continue
|
||||
|
||||
match = re.match(r'(\d+)(\S+)', line)
|
||||
if match:
|
||||
value, signal_id = match.groups()
|
||||
|
||||
dt = self.current_time - self.signal_definitions[self.signal_indirections[signal_id]].last_time
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].last_time = self.current_time
|
||||
|
||||
self.signal_definitions[self.signal_indirections[signal_id]].bits[0].aggregate(dt, int(value))
|
||||
|
||||
for _, signal in self.signal_definitions.items():
|
||||
for i in range(signal.width):
|
||||
if signal.bits[i].last_val == 1:
|
||||
signal.bits[i].high_time += self.current_time - signal.last_time
|
||||
|
||||
signal.bits[i].low_time = self.current_time - signal.bits[i].high_time
|
||||
|
||||
|
||||
class SAIFParser:
|
||||
def __init__(self):
|
||||
self.signal_definitions = {}
|
||||
|
||||
def parse(self, saif_filename):
|
||||
with open(saif_filename, 'r') as saif_file:
|
||||
for line in saif_file:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
match = re.search(r'(\w+)\[*(\d*)\]*\s+(\(T(.+)\))+', line)
|
||||
if match:
|
||||
signal_name, bit_index, bit_values, _ = match.groups()
|
||||
|
||||
if bit_index == '':
|
||||
bit_index = 0
|
||||
|
||||
if signal_name not in self.signal_definitions:
|
||||
self.signal_definitions[signal_name] = SAIFSignal(signal_name)
|
||||
|
||||
for _ in range(0, int(bit_index) - self.signal_definitions[signal_name].width + 1):
|
||||
self.signal_definitions[signal_name].bits.append(SAIFSignalBit())
|
||||
|
||||
self.signal_definitions[signal_name].width = int(bit_index) + 1
|
||||
|
||||
match = re.search(r'T0 (\d+)', bit_values)
|
||||
if match:
|
||||
low_time = match.groups()[0]
|
||||
|
||||
self.signal_definitions[signal_name].bits[int(bit_index)].low_time = low_time
|
||||
|
||||
match = re.search(r'T1 (\d+)', bit_values)
|
||||
if match:
|
||||
high_time = match.groups()[0]
|
||||
|
||||
self.signal_definitions[signal_name].bits[int(bit_index)].high_time = high_time
|
||||
|
||||
match = re.search(r'TC (\d+)', bit_values)
|
||||
if match:
|
||||
toggle_count = match.groups()[0]
|
||||
|
||||
self.signal_definitions[signal_name].bits[int(bit_index)].transitions = toggle_count
|
||||
|
||||
vcd_to_saif_parser = VCDToSAIFParser()
|
||||
vcd_to_saif_parser.parse("simx.vcd")
|
||||
|
||||
saif_parser = SAIFParser()
|
||||
saif_parser.parse("simx.saif")
|
||||
|
||||
print("From VCD")
|
||||
for signal_name, signal in vcd_to_saif_parser.signal_definitions.items():
|
||||
for bit in range(signal.width):
|
||||
print(f"{signal.name}[{bit}] (T0 {signal.bits[bit].low_time}) (T1 {signal.bits[bit].high_time}) (TC {signal.bits[bit].transitions})")
|
||||
|
||||
print()
|
||||
|
||||
print("From SAIF")
|
||||
for signal_name, signal in saif_parser.signal_definitions.items():
|
||||
for bit in range(signal.width):
|
||||
print(f"{signal.name}[{bit}] (T0 {signal.bits[bit].low_time}) (T1 {signal.bits[bit].high_time}) (TC {signal.bits[bit].transitions})")
|
||||
Loading…
Reference in New Issue