comedi: remove editor modelines and cruft (again)
[linux-2.6-microblaze.git] / drivers / comedi / drivers / ni_routing / tools / convert_csv_to_c.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: GPL-2.0+
3
4 # This is simply to aide in creating the entries in the order of the value of
5 # the device-global NI signal/terminal constants defined in comedi.h
6 import comedi_h
7 import os, sys, re
8 from csv_collection import CSVCollection
9
10
11 def c_to_o(filename, prefix='\t\t\t\t\t   ni_routing/', suffix=' \\'):
12   if not filename.endswith('.c'):
13     return ''
14   return prefix + filename.rpartition('.c')[0] + '.o' + suffix
15
16
17 def routedict_to_structinit_single(name, D, return_name=False):
18   Locals = dict()
19   lines = [
20     '\t.family = "{}",'.format(name),
21     '\t.register_values = {',
22     '\t\t/*',
23     '\t\t * destination = {',
24           '\t\t *              source          = register value,',
25           '\t\t *              ...',
26           '\t\t * }',
27                 '\t\t */',
28   ]
29   if (False):
30     # print table with index0:src, index1:dest
31     D0 = D # (src-> dest->reg_value)
32     #D1 : destD
33   else:
34     D0 = dict()
35     for src, destD in D.items():
36       for dest, val in destD.items():
37         D0.setdefault(dest, {})[src] = val
38
39
40   D0 = sorted(D0.items(), key=lambda i: eval(i[0], comedi_h.__dict__, Locals))
41
42   for D0_sig, D1_D in D0:
43     D1 = sorted(D1_D.items(), key=lambda i: eval(i[0], comedi_h.__dict__, Locals))
44
45     lines.append('\t\t[B({})] = {{'.format(D0_sig))
46     for D1_sig, value in D1:
47       if not re.match('[VIU]\([^)]*\)', value):
48         sys.stderr.write('Invalid register format: {}\n'.format(repr(value)))
49         sys.stderr.write(
50           'Register values should be formatted with V(),I(),or U()\n')
51         raise RuntimeError('Invalid register values format')
52       lines.append('\t\t\t[B({})]\t= {},'.format(D1_sig, value))
53     lines.append('\t\t},')
54   lines.append('\t},')
55
56   lines = '\n'.join(lines)
57   if return_name:
58     return N, lines
59   else:
60     return lines
61
62
63 def routedict_to_routelist_single(name, D, indent=1):
64   Locals = dict()
65
66   indents = dict(
67     I0 = '\t'*(indent),
68     I1 = '\t'*(indent+1),
69     I2 = '\t'*(indent+2),
70     I3 = '\t'*(indent+3),
71     I4 = '\t'*(indent+4),
72   )
73
74   if (False):
75     # data is src -> dest-list
76     D0 = D
77     keyname = 'src'
78     valname = 'dest'
79   else:
80     # data is dest -> src-list
81     keyname = 'dest'
82     valname = 'src'
83     D0 = dict()
84     for src, destD in D.items():
85       for dest, val in destD.items():
86         D0.setdefault(dest, {})[src] = val
87
88   # Sort by order of device-global names (numerically)
89   D0 = sorted(D0.items(), key=lambda i: eval(i[0], comedi_h.__dict__, Locals))
90
91   lines = [ '{I0}.device = "{name}",\n'
92             '{I0}.routes = (struct ni_route_set[]){{'
93             .format(name=name, **indents) ]
94   for D0_sig, D1_D in D0:
95     D1 = [ k for k,v in D1_D.items() if v ]
96     D1.sort(key=lambda i: eval(i, comedi_h.__dict__, Locals))
97
98     lines.append('{I1}{{\n{I2}.{keyname} = {D0_sig},\n'
99                          '{I2}.{valname} = (int[]){{'
100                  .format(keyname=keyname, valname=valname, D0_sig=D0_sig, **indents)
101     )
102     for D1_sig in D1:
103       lines.append( '{I3}{D1_sig},'.format(D1_sig=D1_sig, **indents) )
104     lines.append( '{I3}0, /* Termination */'.format(**indents) )
105
106     lines.append('{I2}}}\n{I1}}},'.format(**indents))
107
108   lines.append('{I1}{{ /* Termination of list */\n{I2}.{keyname} = 0,\n{I1}}},'
109                .format(keyname=keyname, **indents))
110
111   lines.append('{I0}}},'.format(**indents))
112
113   return '\n'.join(lines)
114
115
116 class DeviceRoutes(CSVCollection):
117   MKFILE_SEGMENTS = 'device-route.mk'
118   SET_C = 'ni_device_routes.c'
119   ITEMS_DIR = 'ni_device_routes'
120   EXTERN_H = 'all.h'
121   OUTPUT_DIR = 'c'
122
123   output_file_top = """\
124 // SPDX-License-Identifier: GPL-2.0+
125 /*
126  *  comedi/drivers/ni_routing/{filename}
127  *  List of valid routes for specific NI boards.
128  *
129  *  COMEDI - Linux Control and Measurement Device Interface
130  *  Copyright (C) 2016 Spencer E. Olson <olsonse@umich.edu>
131  *
132  *  This program is free software; you can redistribute it and/or modify
133  *  it under the terms of the GNU General Public License as published by
134  *  the Free Software Foundation; either version 2 of the License, or
135  *  (at your option) any later version.
136  *
137  *  This program is distributed in the hope that it will be useful,
138  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
139  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
140  *  GNU General Public License for more details.
141  */
142
143 /*
144  * The contents of this file are generated using the tools in
145  * comedi/drivers/ni_routing/tools
146  *
147  * Please use those tools to help maintain the contents of this file.
148  */
149
150 #include "ni_device_routes.h"
151 #include "{extern_h}"\
152 """.format(filename=SET_C, extern_h=os.path.join(ITEMS_DIR, EXTERN_H))
153
154   extern_header = """\
155 /* SPDX-License-Identifier: GPL-2.0+ */
156 /*
157  *  comedi/drivers/ni_routing/{filename}
158  *  List of valid routes for specific NI boards.
159  *
160  *  COMEDI - Linux Control and Measurement Device Interface
161  *  Copyright (C) 2016 Spencer E. Olson <olsonse@umich.edu>
162  *
163  *  This program is free software; you can redistribute it and/or modify
164  *  it under the terms of the GNU General Public License as published by
165  *  the Free Software Foundation; either version 2 of the License, or
166  *  (at your option) any later version.
167  *
168  *  This program is distributed in the hope that it will be useful,
169  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
170  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171  *  GNU General Public License for more details.
172  */
173
174 /*
175  * The contents of this file are generated using the tools in
176  * comedi/drivers/ni_routing/tools
177  *
178  * Please use those tools to help maintain the contents of this file.
179  */
180
181 #ifndef _COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
182 #define _COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
183
184 #include "../ni_device_routes.h"
185
186 {externs}
187
188 #endif //_COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
189 """
190
191   single_output_file_top = """\
192 // SPDX-License-Identifier: GPL-2.0+
193 /*
194  *  comedi/drivers/ni_routing/{filename}
195  *  List of valid routes for specific NI boards.
196  *
197  *  COMEDI - Linux Control and Measurement Device Interface
198  *  Copyright (C) 2016 Spencer E. Olson <olsonse@umich.edu>
199  *
200  *  This program is free software; you can redistribute it and/or modify
201  *  it under the terms of the GNU General Public License as published by
202  *  the Free Software Foundation; either version 2 of the License, or
203  *  (at your option) any later version.
204  *
205  *  This program is distributed in the hope that it will be useful,
206  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
207  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
208  *  GNU General Public License for more details.
209  */
210
211 /*
212  * The contents of this file are generated using the tools in
213  * comedi/drivers/ni_routing/tools
214  *
215  * Please use those tools to help maintain the contents of this file.
216  */
217
218 #include "../ni_device_routes.h"
219 #include "{extern_h}"
220
221 struct ni_device_routes {table_name} = {{\
222 """
223
224   def __init__(self, pattern='csv/device_routes/*.csv'):
225     super(DeviceRoutes,self).__init__(pattern)
226
227   def to_listinit(self):
228     chunks = [ self.output_file_top,
229       '',
230       'struct ni_device_routes *const ni_device_routes_list[] = {'
231     ]
232     # put the sheets in lexical order of device numbers then bus
233     sheets = sorted(self.items(), key=lambda i : tuple(i[0].split('-')[::-1]) )
234
235     externs = []
236     objs = [c_to_o(self.SET_C)]
237
238     for sheet,D in sheets:
239       S = sheet.lower()
240       dev_table_name = 'ni_{}_device_routes'.format(S.replace('-','_'))
241       sheet_filename = os.path.join(self.ITEMS_DIR,'{}.c'.format(S))
242       externs.append('extern struct ni_device_routes {};'.format(dev_table_name))
243
244       chunks.append('\t&{},'.format(dev_table_name))
245
246       s_chunks = [
247         self.single_output_file_top.format(
248           filename    = sheet_filename,
249           table_name  = dev_table_name,
250           extern_h    = self.EXTERN_H,
251         ),
252         routedict_to_routelist_single(S, D),
253         '};',
254       ]
255
256       objs.append(c_to_o(sheet_filename))
257
258       with open(os.path.join(self.OUTPUT_DIR, sheet_filename), 'w') as f:
259         f.write('\n'.join(s_chunks))
260         f.write('\n')
261
262     with open(os.path.join(self.OUTPUT_DIR, self.MKFILE_SEGMENTS), 'w') as f:
263       f.write('# This is the segment that should be included in comedi/drivers/Makefile\n')
264       f.write('ni_routing-objs\t\t\t\t+= \\\n')
265       f.write('\n'.join(objs))
266       f.write('\n')
267
268     EXTERN_H = os.path.join(self.ITEMS_DIR, self.EXTERN_H)
269     with open(os.path.join(self.OUTPUT_DIR, EXTERN_H), 'w') as f:
270       f.write(self.extern_header.format(
271         filename=EXTERN_H, externs='\n'.join(externs)))
272
273     chunks.append('\tNULL,') # terminate list
274     chunks.append('};')
275     return '\n'.join(chunks)
276
277   def save(self):
278     filename=os.path.join(self.OUTPUT_DIR, self.SET_C)
279
280     try:
281       os.makedirs(os.path.join(self.OUTPUT_DIR, self.ITEMS_DIR))
282     except:
283       pass
284     with open(filename,'w') as f:
285       f.write( self.to_listinit() )
286       f.write( '\n' )
287
288
289 class RouteValues(CSVCollection):
290   MKFILE_SEGMENTS = 'route-values.mk'
291   SET_C = 'ni_route_values.c'
292   ITEMS_DIR = 'ni_route_values'
293   EXTERN_H = 'all.h'
294   OUTPUT_DIR = 'c'
295
296   output_file_top = """\
297 // SPDX-License-Identifier: GPL-2.0+
298 /*
299  *  comedi/drivers/ni_routing/{filename}
300  *  Route information for NI boards.
301  *
302  *  COMEDI - Linux Control and Measurement Device Interface
303  *  Copyright (C) 2016 Spencer E. Olson <olsonse@umich.edu>
304  *
305  *  This program is free software; you can redistribute it and/or modify
306  *  it under the terms of the GNU General Public License as published by
307  *  the Free Software Foundation; either version 2 of the License, or
308  *  (at your option) any later version.
309  *
310  *  This program is distributed in the hope that it will be useful,
311  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
312  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
313  *  GNU General Public License for more details.
314  */
315
316 /*
317  * This file includes the tables that are a list of all the values of various
318  * signals routes available on NI hardware.  In many cases, one does not
319  * explicitly make these routes, rather one might indicate that something is
320  * used as the source of one particular trigger or another (using
321  * *_src=TRIG_EXT).
322  *
323  * The contents of this file are generated using the tools in
324  * comedi/drivers/ni_routing/tools
325  *
326  * Please use those tools to help maintain the contents of this file.
327  */
328
329 #include "ni_route_values.h"
330 #include "{extern_h}"\
331 """.format(filename=SET_C, extern_h=os.path.join(ITEMS_DIR, EXTERN_H))
332
333   extern_header = """\
334 /* SPDX-License-Identifier: GPL-2.0+ */
335 /*
336  *  comedi/drivers/ni_routing/{filename}
337  *  List of valid routes for specific NI boards.
338  *
339  *  COMEDI - Linux Control and Measurement Device Interface
340  *  Copyright (C) 2016 Spencer E. Olson <olsonse@umich.edu>
341  *
342  *  This program is free software; you can redistribute it and/or modify
343  *  it under the terms of the GNU General Public License as published by
344  *  the Free Software Foundation; either version 2 of the License, or
345  *  (at your option) any later version.
346  *
347  *  This program is distributed in the hope that it will be useful,
348  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
349  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
350  *  GNU General Public License for more details.
351  */
352
353 /*
354  * The contents of this file are generated using the tools in
355  * comedi/drivers/ni_routing/tools
356  *
357  * Please use those tools to help maintain the contents of this file.
358  */
359
360 #ifndef _COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
361 #define _COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
362
363 #include "../ni_route_values.h"
364
365 {externs}
366
367 #endif //_COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
368 """
369
370   single_output_file_top = """\
371 // SPDX-License-Identifier: GPL-2.0+
372 /*
373  *  comedi/drivers/ni_routing/{filename}
374  *  Route information for {sheet} boards.
375  *
376  *  COMEDI - Linux Control and Measurement Device Interface
377  *  Copyright (C) 2016 Spencer E. Olson <olsonse@umich.edu>
378  *
379  *  This program is free software; you can redistribute it and/or modify
380  *  it under the terms of the GNU General Public License as published by
381  *  the Free Software Foundation; either version 2 of the License, or
382  *  (at your option) any later version.
383  *
384  *  This program is distributed in the hope that it will be useful,
385  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
386  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
387  *  GNU General Public License for more details.
388  */
389
390 /*
391  * This file includes a list of all the values of various signals routes
392  * available on NI 660x hardware.  In many cases, one does not explicitly make
393  * these routes, rather one might indicate that something is used as the source
394  * of one particular trigger or another (using *_src=TRIG_EXT).
395  *
396  * The contents of this file can be generated using the tools in
397  * comedi/drivers/ni_routing/tools.  This file also contains specific notes to
398  * this family of devices.
399  *
400  * Please use those tools to help maintain the contents of this file, but be
401  * mindful to not lose the notes already made in this file, since these notes
402  * are critical to a complete undertsanding of the register values of this
403  * family.
404  */
405
406 #include "../ni_route_values.h"
407 #include "{extern_h}"
408
409 const struct family_route_values {table_name} = {{\
410 """
411
412   def __init__(self, pattern='csv/route_values/*.csv'):
413     super(RouteValues,self).__init__(pattern)
414
415   def to_structinit(self):
416     chunks = [ self.output_file_top,
417       '',
418       'const struct family_route_values *const ni_all_route_values[] = {'
419     ]
420     # put the sheets in lexical order for consistency
421     sheets = sorted(self.items(), key=lambda i : i[0] )
422
423     externs = []
424     objs = [c_to_o(self.SET_C)]
425
426     for sheet,D in sheets:
427       S = sheet.lower()
428       fam_table_name = '{}_route_values'.format(S.replace('-','_'))
429       sheet_filename = os.path.join(self.ITEMS_DIR,'{}.c'.format(S))
430       externs.append('extern const struct family_route_values {};'.format(fam_table_name))
431
432       chunks.append('\t&{},'.format(fam_table_name))
433
434       s_chunks = [
435         self.single_output_file_top.format(
436           filename    = sheet_filename,
437           sheet       = sheet.upper(),
438           table_name  = fam_table_name,
439           extern_h    = self.EXTERN_H,
440         ),
441         routedict_to_structinit_single(S, D),
442         '};',
443       ]
444
445       objs.append(c_to_o(sheet_filename))
446
447       with open(os.path.join(self.OUTPUT_DIR, sheet_filename), 'w') as f:
448         f.write('\n'.join(s_chunks))
449         f.write( '\n' )
450
451     with open(os.path.join(self.OUTPUT_DIR, self.MKFILE_SEGMENTS), 'w') as f:
452       f.write('# This is the segment that should be included in comedi/drivers/Makefile\n')
453       f.write('ni_routing-objs\t\t\t\t+= \\\n')
454       f.write('\n'.join(objs))
455       f.write('\n')
456
457     EXTERN_H = os.path.join(self.ITEMS_DIR, self.EXTERN_H)
458     with open(os.path.join(self.OUTPUT_DIR, EXTERN_H), 'w') as f:
459       f.write(self.extern_header.format(
460         filename=EXTERN_H, externs='\n'.join(externs)))
461
462     chunks.append('\tNULL,') # terminate list
463     chunks.append('};')
464     return '\n'.join(chunks)
465
466   def save(self):
467     filename=os.path.join(self.OUTPUT_DIR, self.SET_C)
468
469     try:
470       os.makedirs(os.path.join(self.OUTPUT_DIR, self.ITEMS_DIR))
471     except:
472       pass
473     with open(filename,'w') as f:
474       f.write( self.to_structinit() )
475       f.write( '\n' )
476
477
478
479 if __name__ == '__main__':
480   import argparse
481   parser = argparse.ArgumentParser()
482   parser.add_argument( '--route_values', action='store_true',
483     help='Extract route values from csv/route_values/*.csv' )
484   parser.add_argument( '--device_routes', action='store_true',
485     help='Extract route values from csv/device_routes/*.csv' )
486   args = parser.parse_args()
487   KL = list()
488   if args.route_values:
489     KL.append( RouteValues )
490   if args.device_routes:
491     KL.append( DeviceRoutes )
492   if not KL:
493     parser.error('nothing to do...')
494   for K in KL:
495     doc = K()
496     doc.save()