| #!/usr/bin/env python3 |
| ''' |
| Concatenate Verilog source files and process include directives inside them. |
| |
| Usage: concatenate_v_sources.py [-h] inputfile [inputfile ...] outputfile |
| ''' |
| |
| import argparse |
| import sys |
| import re |
| from os import path |
| |
| parser = argparse.ArgumentParser() |
| parser.add_argument( |
| "inputfile", |
| nargs='+', |
| type=argparse.FileType('r'), |
| help="Input Verilog file" |
| ) |
| parser.add_argument( |
| "outputfile", type=argparse.FileType('w'), help="Output file" |
| ) |
| |
| include_re = re.compile(r'^`include *"([^"]+)"', flags=re.MULTILINE) |
| slash_star_re = re.compile(r'\s*/\*.*\*/\s*', flags=re.DOTALL) |
| slash_slash_re = re.compile(r'\s*//[^\n]*') |
| v2x_re = re.compile( |
| r'.*\(\*.*((DELAY)|(CLOCK)|(MODEL)|(SETUP)|(HOLD)|(FASM)).*\*\)\n' |
| ) |
| |
| |
| def process_includes(file, includes_list): |
| file_name = path.realpath(file.name) |
| if file_name in includes_list: |
| return '' |
| |
| includes_list.append(file_name) |
| |
| code = file.read() |
| code = slash_star_re.sub('', code) |
| code = slash_slash_re.sub('', code) |
| code = v2x_re.sub('', code) |
| |
| def process_match(match): |
| include_path = path.join(path.dirname(file_name), match[1]) |
| include_file = open(include_path, 'r') |
| return process_includes(include_file, includes_list) |
| |
| rel_file_name = path.relpath(file_name) |
| |
| result = f'// {rel_file_name} {{{{{{\n' + \ |
| include_re.sub(process_match, code) + \ |
| f'// {rel_file_name} }}}}}}\n' |
| return result |
| |
| |
| def main(argv): |
| args = parser.parse_args(argv[1:]) |
| print(args) |
| |
| includes_list = [] |
| |
| print( |
| *(process_includes(f, includes_list) for f in args.inputfile), |
| sep='\n', |
| end='', |
| file=args.outputfile |
| ) |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv)) |