more improvements.
[vutg.git] / src / vut_parser.py
blobd93a0aceb889f24f8c366c9ec633f99d7cbfa10b
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 """
4 =======================================
5 module_name: vut_analyser
6 ---------------------------------------
7 Author: Rodrigo Peixoto
8 Data: 10/02/2008
9 ---------------------------------------
10 Description:
11 - This moludes fetchs the data from
12 the waveform to generate the Module
13 Skeleton and the UnitTest Module
14 =======================================
15 License: GPL
16 ======================================================================
18 This program is free software: you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation, either version 3 of the License, or
21 (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 =======================================================================
32 """
34 from elementtree.ElementTree import *
35 from vut_generator import *
36 from utils import *
37 import re
38 import sys
39 import random
41 class VUTParser:
43 def __init__(self, xml_source):
44 self.vut = ElementTree(file=xml_source)
45 self.root = self.vut.getroot()
46 self.vmodule = VerilogModule(self.root.get("module_name"))
47 print "Initing parser to %s..." % xml_source
49 def clear_comments(self, dlist):
50 for i in dlist:# removing commets
51 if "#" in i:
52 dlist[dlist.index(i)] = i[:i.index("#")]
53 return map(str.strip, dlist)
56 def parse_waveform(self, *args):
57 print "parsing waveform tag..."
58 waves = map(str.strip, args[0].text.splitlines())
59 waves = [x for x in waves if((x!= "") and ("-" not in x) and ("=" not in x))]
60 for signal in waves:
61 t = re.findall(r'(^[a-zA-z]\w*( )*\[)|(^[a-zA-z]\w*( )*[io]\@)', signal)[0]
62 sig_name = [x for x in t if x!=""][0].split()[0].replace('[', '') #Cleaning all once!
63 slice = re.findall(r'\[\d+\:\d+\]', signal)
64 port = None
65 if slice:
66 port = (sig_name, tuple(map(int, re.findall(r'\d+', slice[0]))))
67 else: port = (sig_name,)
69 if re.match(r'.*i@.*', signal):
70 self.vmodule.in_ports.append(port)
71 ref = re.findall(r"random_alloc\(.*\)",signal)
72 if ref:
73 print " found random_alloc to %s: %s" % (sig_name,ref[0])
74 rs = re.findall(r"R\d+",ref[0])
75 n = int(re.findall(r"\,\d+",ref[0])[0][1:])
76 self.vmodule.random_alloc[sig_name] = (rs,n)
77 #DEBUG: print self.vmodule.random_alloc
80 else:
81 self.vmodule.out_ports.append(port)
82 ref = re.findall(r"ref_function\(.*\)",signal)
83 sigs = []
84 if ref:
85 print " found reference_function to %s: %s" % (sig_name, ref[0])
86 sigs = re.findall(r"\(.*\)",ref[0])[0][1:-1].split(',')
87 self.vmodule.out_ports_signal_dependecies[sig_name] = sigs
89 #DEBUG: print "What HELL!!!", self.vmodule.out_ports_signal_dependecies
90 waves = map(lambda a : a.replace(" ", ""), waves)
91 self.parse_signal_values(waves)
93 def parse_gen_with(self, *args):
94 '''
95 @param *args:
96 '''
97 print "parsing gen_with tag...\n parsing randrange values..."
98 ran = map(str.strip, args[0].text.splitlines())
99 ran = [x for x in ran if((x!= "") and (x[0]!="#"))]
100 #ran = self.clear_comments(ran)
101 for i in ran:
102 self.vmodule.ran_range[re.findall(r'R\d+', i)[0]] =\
103 (int(re.findall(r'[0-9A-Fa-f]+\s*\,', i)[0][:-1],16),\
104 int(re.findall(r'[0-9A-Fa-f]+\s*\)', i)[0][:-1],16))
105 #print self.vmodule.ran_range
106 for code in args[0].getchildren():
107 var = code.get("output")
108 assert var, "Output not defined into python_code tag.\n"\
109 'Usage <python_code output="port_name">...code...</python_code>!'
110 port_name = re.findall(r'[a-zA-Z][a-zA-Z0-9_]*$', var)[0]
111 assert port_name, ""
112 self.python_code_parser(port_name, code.text)
114 def parse_time_scale(self, *args):
116 @param *args:
118 print "parsing time_scale tag..."
119 t_div = args[0].get("t_div")
120 unit = args[0].get("unit")
121 assert t_div, 'Time division not defined in time_scale tag.\n'\
122 'Usage <time_scale t_div="val_integer" unit="unit{(ump)s}"/>!'
123 assert unit, "Unit not defined in time_scale tag!"
125 def parse_signal_values(self, pwaves):
126 print " creating memories..."
127 list_imem = []
128 list_omem = []
129 for wav in pwaves:
130 sig_name = re.sub("\[\d+:\d+\]", '', wav[:wav.index('@')-1])
131 #Random alloc values
132 if sig_name in self.vmodule.random_alloc:
133 ran_val = []
134 tmp_val,n = self.vmodule.random_alloc[sig_name]
135 for i in range(n):
136 ran_val.append(tmp_val[random.randrange(len(tmp_val))])
137 wav = re.sub(r"random_alloc\(.*\)","|".join(ran_val),wav)
138 #DEBUG: print "TESTE DE RANDOMALLOC",wav
140 values = wav[wav.index('@')+1:].split('|')[1:-1]
141 if wav[wav.index('@')-1] == 'i':
142 mem = MemoryIO("%s"% sig_name, values)
143 #print mem
144 #exec ("imem_%s = %s" % (sig_name, values)) #wav[wav.index('@')+1:].split('|')[1:-1]))
145 list_imem.append(mem)
146 else:
147 mem = MemoryIO("%s"% sig_name, values)
148 #exec ("omem_%s = %s"% (sig_name, values)) #wav[wav.index('@')+1:].split('|')[1:-1]))
149 #exec("list_omem.append(omem_%s)"% sig_name)
150 list_omem.append(mem)
151 #print list_imem
152 #print list_omem
153 self.vmodule.set_in_ports_behavior(list_imem)
154 self.vmodule.set_out_ports_behavior(list_omem)
157 def parse_all(self):
160 root_children = self.root.getchildren()
161 switch = {"waveform": self.parse_waveform,
162 "gen_with": self.parse_gen_with,
163 "time_scale": self.parse_time_scale}
165 for item in root_children:
166 try:
167 switch[item.tag](item)
168 except KeyError, e:
169 raise InvalidTagException(e)
170 print "Parse complete successful!!!"
171 return self.vmodule
173 def python_code_parser(self, port_name, pycode):
174 #TODO: Ajsutar isso aqui!!!
175 print " parsing python code tag..."
177 code = self.clear_comments(pycode.splitlines())
178 code = [x for x in code if(x!= "")]
180 try:
181 ref_function = None
182 if re.match(r"\s*include_python_file\(\"(((\/\w+)+|\.)\/)?\w+.py[oc]?\"\)\s*$",pycode):
183 #print " " + pycode.strip()
184 print " fetching local reference function... %s" % pycode.strip()
185 function_file = re.findall(r"\"(((\/\w+)+|\.)\/)?\w+.py[oc]?\"", pycode)[0]
186 exec """import %(file)s;ref_function = %(file)s.reference_function""" % {'file':port_name}
187 #DEBUG: print "test ref_function: ", ref_function(10,20)
188 else:
189 exec("ref_function = " + "\n".join(code))
190 print " fetching external reference function... ", "\n\t".join(code)
191 #DEBUG: print "test ref_function: ", ref_function(10,20)
192 self.vmodule.ref_functions[port_name] = ref_function
193 #DEBUG: print self.vmodule.ref_functions
194 except:
195 print "Python reference model code error: ", sys.exc_info()
196 if __name__ == '__main__':
197 test = VUTParser("example5.vut")
198 vm = test.parse_all()
199 #VUTGenerator(vm).gen()