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