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 6import comedi_h 7import os, sys, re 8from csv_collection import CSVCollection 9 10 11def 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 17def 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 63def 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 116class 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 221struct 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 289class 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 409const 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 479if __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() 497