MAGMA  1.2.0
MatrixAlgebraonGPUandMulticoreArchitectures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
codegen.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 __author__="alvaro"
3 __date__ ="$Sep 2, 2010 10:09:19 AM$"
4 
5 import sys;
6 import re;
7 import shlex;
8 import os;
9 from os import path;
10 from optparse import OptionParser;
11 from subs import subs;
12 
13 KEYWORD = '@precisions';
14 REGEX = '^.*'+KEYWORD+'\s+((\w+,?)+)\s+(\w+)\s+->\s*((\s\w+)+).*$';
15 
16 def relpath(p):
17  p = path.realpath(p);
18  return p.replace(path.realpath('.')+'/','');
19 
20 class Conversion:
21  debug = False;
22  test = False;
23  make = False;
24  prefix = None;
25  required_precisions = [];
26  files_in = [];
27  files_out = [];
28  def __init__(self, file, match, content):
29  self.content = content;
30  file = path.realpath(file);
31  rel = relpath(file);
32  self.file = list(path.split(file));
33  self.date = path.getmtime(file);
34  if path.samefile(path.join(self.file[0],self.file[1]),sys.argv[0]):
35  raise ValueError('Let\'s just forget codegen.py');
36  try:
37  # normal,all,mixed
38  self.types = match[0].split(',');
39  # z
40  self.precision = match[2].lower();
41  # ['c','d','s']
42  self.precisions = match[3].lower().split();
43  if len(self.required_precisions):
44  self.precstmp = [];
45  for prec in (self.required_precisions):
46  if prec in(self.precisions):
47  self.precstmp.append(prec);
48  self.precisions = self.precstmp;
49  except:
50  raise ValueError(path.join(self.file[0],self.file[1])+' : Invalid conversion string');
51  self.files_in.append(rel);
52 
53 
54  def run(self):
55  if self.convert_names() and not self.test:
56  self.convert_data();
57  self.export_data();
58 
59  def convert_names(self):
60  self.names = [];
61  self.dates = [];
62  self.converted = [];
63  load = False;
64  if self.debug: print '|'.join(self.types), self.precision, relpath(path.join(self.file[0],self.file[1]));
65  for precision in self.precisions:
66  new_file = self.convert(self.file[1], precision);
67  if self.debug: print precision,':',
68  if new_file <> self.file[1]:
69  if self.prefix is None:
70  prefix = self.file[0]
71  makeprefix = '';
72  else:
73  prefix = self.prefix;
74  makeprefix = '--prefix '+prefix;
75  conversion = path.join(prefix, new_file);
76  file_out = relpath(conversion);
77  if self.make:
78  file_in = relpath(path.join(self.file[0],self.file[1]));
79  print file_out+':',file_in;
80  print "\t$(PYTHON)",path.realpath(sys.argv[0]),makeprefix,'-p',precision,"--file",file_in;
81  self.names.append(new_file);
82  self.files_out.append(file_out);
83  if self.debug: print relpath(conversion), ':',
84  try:
85  date = path.getmtime(conversion);
86  diff = self.date - date;
87  self.dates.append(diff);
88  if self.debug:
89  if diff > 0: print 'Old',
90  else: print 'Current',
91  print diff;
92  if diff > 0: load = True;
93  except:
94  if self.debug: print 'Missing';
95  self.dates.append(None);
96  load = True;
97  else:
98  if self.debug: print '<No Change>',':';
99  else: print >> sys.stderr, new_file, 'had no change for', precision;
100  self.names.append(None);
101  self.dates.append(None);
102  return load;
103 
104  def export_data(self):
105  for i in range(len(self.names)):
106  name = self.names[i];
107  data = self.converted[i];
108  if data is None or name is None: continue;
109  if self.prefix is None:
110  fd = open(path.join(self.file[0],name), 'w');
111  else:
112  fd = open(path.join(self.prefix,name), 'w');
113  fd.write(data);
114  fd.close();
115 
116 
117  def convert_data(self):
118  for i in range(len(self.precisions)):
119  precision = self.precisions[i];
120  name = self.names[i];
121  date = self.dates[i];
122  if name is not None and (date is None or date > 0):
123  self.converted.append(self.convert(self.content, precision));
124  else: self.converted.append(None);
125 
126  def substitute(self, sub_type, data, precision):
127  try:
128  work = subs[sub_type];
129  prec_to = work[0].index(precision);
130  prec_from = work[0].index(self.precision);
131  except:
132  return data;
133  for i in range(1,len(work)):
134  try:
135  search = work[i][prec_from];
136  replace = work[i][prec_to];
137  if not search: continue;
138  replace.replace('\*','*');
139  data = re.sub(search, replace, data);
140  except:
141  print 'Bad replacement pair ',i,'in',sub_type;
142  continue;
143  return data;
144 
145  def convert(self, data, precision):
146  try:
147  data = self.substitute('all', data, precision);
148  except: pass;
149  for sub_type in self.types:
150  if sub_type == 'all': continue;
151  try:
152  data = self.substitute(sub_type, data, precision);
153  except Exception, e:
154  raise ValueError('I encountered an unrecoverable error while working in subtype:',sub_type+'.');
155  data = re.sub('@precisions '+','.join(self.types)+'.*', '@generated '+precision, data);
156  return data;
157 
158 def grep(string,list):
159  expr = re.compile(string)
160  return filter(expr.search,list)
161 
162 parser = OptionParser();
163 parser.add_option("-d", "--debug", help='Print debugging messages.', action='store_true', dest='debug', default=False);
164 parser.add_option("-P", "--prefix", help='The output directory if different from the input directory.', action='store', dest='prefix', default=None);
165 parser.add_option("-i", "--in-files", help='Print the filenames of files for precision generation.', action='store_true', dest='in_print', default=False);
166 parser.add_option("-o", "--out-files", help='Print the filenames for the precision generated files.', action='store_true', dest='out_print', default=False);
167 parser.add_option("-c", "--clean", help='Remove the files that are the product of generation.', action='store_true', dest='out_clean', default=False);
168 parser.add_option("-t", "--threads", help='Enter the number of threads to use for conversion.', action='store', dest='threads', default=1);
169 parser.add_option("-f", "--file", help='Specify a file(s) on which to operate.', action='store', dest='fileslst', type='string', default="");
170 parser.add_option("-p", "--prec", help='Specify a precision(s) on which to operate.', action='store', dest='precslst', type='string', default="");
171 parser.add_option("-m", "--make", help='Spew a GNU Make friendly file to standard out.', action='store_true', dest='make', default=False);
172 parser.add_option("-T", "--test", help='Don\'t actually do any work.', action='store_true', dest='test', default=False);
173 (options, args) = parser.parse_args();
174 
175 rex = re.compile(REGEX);
176 work = [];
177 
178 def check_gen(file):
179  fd = open(path.realpath(file), 'r');
180  lines = fd.readlines();
181  fd.close();
182  for line in lines:
183  m = rex.match(line);
184  if m is None: continue;
185  work.append((file, m.groups(), ''.join(lines)));
186 
187 if options.fileslst:
188  options.files = options.fileslst.split();
189  if len(options.files):
190  for file in options.files:
191  check_gen(file);
192 else:
193  startDir = '.';
194  for root, dirs, files in os.walk(startDir, True, None):
195  for file in files:
196  if file.startswith('.'): continue;
197  if not file.endswith('.c') and not file.endswith('.h') and not file.endswith('.f'):
198  continue;
199  check_gen(path.join(root,file));
200  if '.svn' in dirs:
201  dirs.remove('.svn');
202 
203 Conversion.debug = options.debug;
204 Conversion.make = options.make;
205 Conversion.prefix = options.prefix;
206 
207 if options.out_print or options.out_clean or options.in_print or options.make or options.test:
208  Conversion.test = True;
209 
210 if options.precslst:
211  options.precs = options.precslst.split();
212  if len(options.precs):
213  Conversion.required_precisions = options.precs;
214 if options.make:
215  print '## Automatically generated Makefile';
216  print 'PYTHON ?= python';
217 
218 if len(work) is 0:
219  print 'gen = ';
220  print 'cleangen:';
221  print '\trm -f $(gen)';
222  print 'generate: $(gen)';
223  print '.PHONY: cleangen generate';
224  sys.exit(0);
225 
226 for tuple in work:
227  try:
228  c = Conversion(tuple[0], tuple[1], tuple[2]);
229  c.run();
230  except Exception, e:
231  print >> sys.stderr, str(e);
232  continue;
233 
234 if options.make:
235  print 'gen = ',' '+' '.join(c.files_out);
236  print 'cleangen:';
237  print '\trm -f $(gen)';
238  print 'generate: $(gen)';
239  print '.PHONY: cleangen generate';
240 if options.in_print: print ' '.join(c.files_in);
241 if options.out_print: print ' '.join(c.files_out);
242 if options.out_clean:
243  for file in c.files_out:
244  if not path.exists(file): continue;
245  os.remove(file);