1 |
2 |
wzab |
#!/usr/bin/python3
|
2 |
|
|
# This file was written by Wojciech M. Zabolotny (wzab@ise.pw.edu.pl)
|
3 |
|
|
# And is published under BSD license
|
4 |
|
|
import os
|
5 |
|
|
import sys
|
6 |
|
|
import string
|
7 |
|
|
import copy
|
8 |
|
|
|
9 |
|
|
#The C_LATEQ_MRK_MAX must be set to the same value as in lateq_pkg.vhd!
|
10 |
|
|
C_LATEQ_MRK_MAX = 1000000
|
11 |
|
|
|
12 |
|
|
""" Below we define the package template, which will be later filled with generated data
|
13 |
|
|
"""
|
14 |
|
|
PkgTemp="""
|
15 |
|
|
-------------------------------------------------------------------------------
|
16 |
|
|
-- Title : Function returning delay values for delay equalizers
|
17 |
|
|
-- Project :
|
18 |
|
|
-------------------------------------------------------------------------------
|
19 |
|
|
-- File : ${file_name}
|
20 |
|
|
-- This file is automatically generated, please don't edit it manually
|
21 |
|
|
-- Standard : VHDL'93/02
|
22 |
|
|
-------------------------------------------------------------------------------
|
23 |
|
|
-- Description: Function, which returns delays associated with particular
|
24 |
|
|
-- identifier
|
25 |
|
|
--
|
26 |
|
|
library ieee;
|
27 |
|
|
use ieee.std_logic_1164.all;
|
28 |
|
|
use ieee.numeric_std.all;
|
29 |
|
|
use std.textio.all;
|
30 |
|
|
|
31 |
|
|
library work;
|
32 |
|
|
${packages}
|
33 |
|
|
|
34 |
|
|
package ${package_name} is
|
35 |
|
|
|
36 |
|
|
function ${function_name} (
|
37 |
|
|
constant desc : in string;
|
38 |
|
|
constant n : in integer)
|
39 |
|
|
return integer;
|
40 |
|
|
|
41 |
|
|
|
42 |
|
|
end package ${package_name};
|
43 |
|
|
|
44 |
|
|
package body ${package_name} is
|
45 |
|
|
|
46 |
|
|
function ${function_name} (
|
47 |
|
|
constant desc : in string;
|
48 |
|
|
constant n : in integer)
|
49 |
|
|
return integer is
|
50 |
|
|
begin -- function ${function_name}
|
51 |
|
|
if desc = "" then
|
52 |
|
|
return 0;
|
53 |
|
|
${generated_clauses}
|
54 |
|
|
else
|
55 |
|
|
return 0;
|
56 |
|
|
end if;
|
57 |
|
|
end function ${function_name};
|
58 |
|
|
|
59 |
|
|
end package body ${package_name};
|
60 |
|
|
"""
|
61 |
|
|
# Function below compares two time markers, considering
|
62 |
|
|
# their wrapping
|
63 |
|
|
def del_cmp(v1, v2):
|
64 |
|
|
res=v1-v2
|
65 |
|
|
if res > C_LATEQ_MRK_MAX/2:
|
66 |
|
|
res -= C_LATEQ_MRK_MAX
|
67 |
|
|
if res < -C_LATEQ_MRK_MAX/2:
|
68 |
|
|
res += C_LATEQ_MRK_MAX
|
69 |
|
|
return res
|
70 |
|
|
|
71 |
|
|
class del_checker(object):
|
72 |
|
|
def __init__(self):
|
73 |
|
|
self.dels = {}
|
74 |
|
|
self.new_dels = {}
|
75 |
|
|
self.is_set = False
|
76 |
|
|
def feed(self,t):
|
77 |
|
|
#print(t)
|
78 |
|
|
if t[1]=="end":
|
79 |
|
|
#New data entered, verify them
|
80 |
|
|
dmin = self.new_dels[0]
|
81 |
|
|
for i in self.new_dels.values():
|
82 |
|
|
if i<0:
|
83 |
|
|
#At least one input not initialized. Skip the line
|
84 |
|
|
return
|
85 |
|
|
if del_cmp(dmin,i) > 0:
|
86 |
|
|
dmin = i
|
87 |
|
|
#We have found the "minimal" (considering wrapping) value
|
88 |
|
|
for k in self.new_dels.keys():
|
89 |
|
|
tmp =self.new_dels[k] - dmin
|
90 |
|
|
if tmp < 0: #Wrap the value
|
91 |
|
|
tmp += C_LATEQ_MRK_MAX
|
92 |
|
|
self.new_dels[k] = tmp
|
93 |
|
|
if self.is_set:
|
94 |
|
|
#Verify, that delay has not changed
|
95 |
|
|
if not (self.new_dels == self.dels):
|
96 |
|
|
raise Exception("Error, delay has changed:" + t[0]+" :"+str(self.dels)+"<->"+str(self.new_dels))
|
97 |
|
|
else:
|
98 |
|
|
self.dels = copy.copy(self.new_dels) # We MUST use deep copy here!
|
99 |
|
|
self.is_set = True
|
100 |
|
|
else:
|
101 |
|
|
self.new_dels[int(t[1])]=int(t[2])
|
102 |
|
|
|
103 |
|
|
# Definition of function, which analyses the delay report
|
104 |
|
|
# and generates the delay defining function
|
105 |
|
|
def analyse_del_rep(fname):
|
106 |
|
|
# Now read the delay report file (generated by simulation)
|
107 |
|
|
# If it is the first run, the file may not exist yet
|
108 |
|
|
# In this case we generate function which always returns
|
109 |
|
|
# delay=0
|
110 |
|
|
try:
|
111 |
|
|
with open(report_file,"r") as fin:
|
112 |
|
|
# The delay report contains lines containing the desc, the input number and the delay value.
|
113 |
|
|
# Each series of values is finished with line containing the desc and the "end" string.
|
114 |
|
|
# We read lines from the file. For each new identifier found we create an object which
|
115 |
|
|
# will accumulate delay data for that identifier.
|
116 |
|
|
# Then we will feed that object with lines. After the line with "end" is received, we calculate
|
117 |
|
|
# the delay difference. IT SHOULD NOT CHANGE DURING THE SIMULATION
|
118 |
|
|
ids = {}
|
119 |
|
|
for line in fin:
|
120 |
|
|
t=line.strip().split(",")
|
121 |
|
|
if len(t) < 2:
|
122 |
|
|
break
|
123 |
|
|
#desc is in t[0]
|
124 |
|
|
if not t[0] in ids:
|
125 |
|
|
#add the object
|
126 |
|
|
ids[t[0]] = del_checker()
|
127 |
|
|
#Feed the analyser with the received line
|
128 |
|
|
ids[t[0]].feed(t)
|
129 |
|
|
except IOError as e:
|
130 |
|
|
#Delay report could not be read - don't adjust delays
|
131 |
|
|
return("")
|
132 |
|
|
#All lines read, now generate the results
|
133 |
|
|
#Iterate over all identifiers
|
134 |
|
|
res=""
|
135 |
|
|
for ni in ids.keys():
|
136 |
|
|
res += " elsif desc=\""+ni+"\" then\n"
|
137 |
|
|
res += " case n is\n"
|
138 |
|
|
for k,v in ids[ni].dels.items():
|
139 |
|
|
res += " when "+str(k)+" => return "+str(v)+";\n"
|
140 |
|
|
res += " when others => return -1;\n"
|
141 |
|
|
res += " end case;\n"
|
142 |
|
|
return res
|
143 |
|
|
|
144 |
|
|
if len(sys.argv)<5:
|
145 |
|
|
appname=sys.argv[0]
|
146 |
|
|
print(string.Template("""
|
147 |
|
|
Correct calling syntax:
|
148 |
|
|
${appname} report_file output_file package_name function_name
|
149 |
|
|
""").substitute(locals()))
|
150 |
|
|
sys.exit(0)
|
151 |
|
|
fout=open(sys.argv[2], "w")
|
152 |
|
|
ndef={}
|
153 |
|
|
report_file=sys.argv[1]
|
154 |
|
|
ndef['file_name']=sys.argv[2]
|
155 |
|
|
ndef['package_name']=sys.argv[3]
|
156 |
|
|
ndef['function_name']=sys.argv[4]
|
157 |
|
|
ndef['packages']="""
|
158 |
|
|
use work.lateq_pkg.all;
|
159 |
|
|
"""
|
160 |
|
|
ndef['generated_clauses']=analyse_del_rep(report_file)
|
161 |
|
|
tout=string.Template(PkgTemp).substitute(ndef)
|
162 |
|
|
fout.write(tout)
|
163 |
|
|
fout.close()
|