diff --git a/tools/readme.md b/tools/readme.md deleted file mode 100644 index ed3d8e651b1085ab02a88d1357f880b1dce9f3c7..0000000000000000000000000000000000000000 --- a/tools/readme.md +++ /dev/null @@ -1,30 +0,0 @@ -# VHDL STYLE FIX - -Style fixing done: - -- Remove trailing spaces. -- Add spaces around operators. -- StandardLogic to lowercase. -- Constants to lowercase. -- Keywords to lowercase. -- Types to lowercase. -- Type Conversions to lowercase. -- Resolutions to lowercase. -- Attributes to lowercase. -- Remove space between type-function and the open bracket. - -## Usage: - -run fix on all vhdl files: - -``` -cd git/hdl -. ./init_hdl.sh -./vhdl_style_fix_all_files.py -p 4 -``` - -## Todo: - -- Align all code. -- Check if all tabs are converted to spaces. -- Remove spaces between all type of functions and the open bracked. \ No newline at end of file diff --git a/tools/vhdl_style_fix.py b/tools/vhdl_style_fix.py deleted file mode 100755 index 2ac9776a1ae6c00f47034274faab9df03b867efd..0000000000000000000000000000000000000000 --- a/tools/vhdl_style_fix.py +++ /dev/null @@ -1,499 +0,0 @@ -#!/usr/bin/python3 - -# ########################################################################## -# Copyright 2020 -# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ########################################################################## - -# ########################################################################## -# Author: Pieter Donker -# Purpose: convert hdl code to fixed format -# Description: -# This script will handle one file. -# usage: -# vhdl_style_fix.py [filename] -# -# ########################################################################## - -from os import getenv, path -import sys -from argparse import ArgumentParser, RawTextHelpFormatter -from textwrap import dedent -from yaml import load, FullLoader - - -def main(): - with open(args.filename, 'r') as fd: - data_in = fd.read() - - sdata = data_in.splitlines() - - if cnf["space"]["remove-trailing"]: - func = RemoveTrailingSpaces(sdata) - sdata = func.get_data() - - if cnf["space"]["add-around-operators"]: - func = AddSpacesAroundOperators(sdata) - sdata = func.get_data() - - if cnf["space"]["add-around-delimiters"]: - func = AddSpacesAroundDelimiters(sdata) - sdata = func.get_data() - - if cnf["case"]["standard-logic"]: - func = CaseStandardLogic(sdata) - sdata = func.get_data() - - if cnf["case"]["constants"]: - func = CaseConstants(sdata) - sdata = func.get_data() - - if cnf["case"]["reserved-words"]: - func = CaseReservedWords(sdata) - sdata = func.get_data() - - if cnf["case"]["types"]: - func = CaseTypes(sdata) - sdata = func.get_data() - - if cnf["case"]["conversions"]: - func = CaseConversions(sdata) - sdata = func.get_data() - - if cnf["case"]["resolutions"]: - func = CaseResolutions(sdata) - sdata = func.get_data() - - if cnf["case"]["attributes"]: - func = CaseAttributes(sdata) - sdata = func.get_data() - - if cnf["space"]["remove-before-bracket"]: - func = RemoveSpaceBeforeBracket(sdata) - sdata = func.get_data() - - if cnf["align"]["procedure-args"]: - func = AlignProcedureArgs(sdata) - sdata = func.get_data() - - data = '\n'.join(sdata) + "\n" - - if data_in != data: - if args.verbose: - print(f"fix {args.filename}") - with open(args.filename, 'w') as fd: - fd.write(data) - - -class BaseCheck: - def __init__(self, data): - self.splitchars = [] - self.tokens = None - self.data = data - self.n_data = len(self.data) - - def set_data(self, data): - self.data = data - self.n_data = len(self.data) - - def get_data(self): - return self.data - - def check(self): - pass - - def splitline(self, line): - # remove comment - code = line.split("--")[0].strip() - words = [] - word = '' - for ch in code: - if ch in self.splitchars: - if word: - words.append(word.strip()) - word = '' - words.append(ch) - elif ch == '"': - word += ch - elif ch == "'": - word += ch - elif ch.isascii(): - word += ch - else: - pass - if word: - words.append(word) - return words - - -class RemoveTrailingSpaces(BaseCheck): - def __init__(self, data): - super().__init__(data) - self.check() - - def check(self): - for i in range(self.n_data): - self.data[i] = self.data[i].rstrip() - - -class AddSpacesAroundOperators(BaseCheck): - def __init__(self, data): - super().__init__(data) - self.tokens = Tokens(cnf["tokens"]["operators"]) - self.check() - - def check(self): - for i in range(self.n_data): - if self.data[i].strip().startswith('--'): - continue - - code_str = [] - comment_str = [] - operator = '' - isoperator = False - isstring = False - iscomment = False - for j in range(len(self.data[i])): - ch = self.data[i][j] - - if iscomment: - comment_str.append(ch) - continue - - if ch in ['"']: - if isoperator: - code_str.append(' ') - operator = '' - isoperator = False - isstring = not isstring - - if isstring: - code_str.append(ch) - continue - - if ch.isspace(): - operator = '' - isoperator = False - - elif ch.isidentifier() or ch in [")"]: - if isoperator: - code_str.append(' ') - isoperator = False - operator = '' - - elif self.tokens.is_valid(ch): - if isoperator: - operator += ch - else: - isoperator = True - try: - if code_str[-1] not in [" ", "("]: - code_str.append(' ') - except IndexError: - pass - operator += ch - - elif isoperator and (ch.isnumeric() or ch == "."): - of = False - for jj in range(j-2, -1, -1): - if self.data[i][jj] in [",", "(", "=", ":"]: - isoperator = False - break - if (self.data[i][jj].isidentifier() - or self.data[i][jj].isnumeric()): - of = True - break - for jj in range(j, len(self.data[i])): - if of or not isoperator: - break - if self.data[i][jj] in [",", ")", ";"]: - isoperator = False - break - if (self.data[i][jj].isspace() - or self.data[i][jj].isidentifier()): - break - - if isoperator: - code_str.append(' ') - isoperator = False - else: - operator = '' - - elif ch.isascii() and ch != ';': - if isoperator: - code_str.append(' ') - isoperator = False - operator = '' - - code_str.append(ch) - - if operator == "--": - comment_str = code_str[-3:] - code_str = code_str[:-3] - iscomment = True - operator = '' - - code_line = ''.join(code_str).rstrip() - comment_line = ''.join(comment_str).strip() - - for str in [" ** ", " **", "** "]: - code_line = code_line.replace(str, "**") - - self.data[i] = code_line - if comment_line: - self.data[i] += " " + comment_line - - -class AddSpacesAroundDelimiters(BaseCheck): - def __init__(self, data): - super().__init__(data) - self.tokens = Tokens(cnf["tokens"]["delimiters"]) - self.check() - - def check(self): - for i in range(self.n_data): - if self.data[i].strip().startswith('--'): - continue - - new_line = [] - last_word = '' - isdelimiter = False - iscomment = False - for ch in self.data[i]: - if iscomment: - new_line.append(ch) - continue - - if ch.isspace(): - last_word = ' ' - isdelimiter = False - - elif ch.isidentifier(): - if isdelimiter: - new_line.append(' ') - isdelimiter = False - last_word += ch - - elif self.tokens.is_valid(ch): - if isdelimiter: - last_word += ch - else: - isdelimiter = True - if last_word != ' ': - new_line.append(' ') - last_word += ch - - elif ch.isascii() and ch != ';': - if isdelimiter: - new_line.append(' ') - isdelimiter = False - last_word += ch - if last_word == "--": - iscomment = True - - new_line.append(ch) - - self.data[i] = ''.join(new_line) - - -class CaseCheck(BaseCheck): - def __init__(self, data, case, splitchars, tokens): - super().__init__(data) - self.case = str.lower if case == "lower" else str.upper - self.splitchars = splitchars - self.tokens = Tokens(tokens) - - def check(self): - for i in range(self.n_data): - line = self.data[i] - sline = self.splitline(line) - for word in sline: - if self.tokens.is_valid(word): - line = line.replace(word, self.case(word), 1) - self.data[i] = line - - -class CaseReservedWords(CaseCheck): - def __init__(self, data): - super().__init__(data, - cnf["case"]["reserved-words"]["case"], - cnf["case"]["reserved-words"]["splitchars"], - cnf["tokens"]["reserved-words"]) - self.check() - - -class CaseTypes(CaseCheck): - def __init__(self, data): - super().__init__(data, - cnf["case"]["types"]["case"], - cnf["case"]["types"]["splitchars"], - cnf["tokens"]["types"]) - self.check() - - -class CaseConversions(CaseCheck): - def __init__(self, data): - super().__init__(data, - cnf["case"]["conversions"]["case"], - cnf["case"]["conversions"]["splitchars"], - cnf["tokens"]["conversions"]) - self.check() - - -class CaseResolutions(CaseCheck): - def __init__(self, data): - super().__init__(data, - cnf["case"]["resolutions"]["case"], - cnf["case"]["resolutions"]["splitchars"], - cnf["tokens"]["resolutions"]) - self.check() - - -class CaseAttributes(CaseCheck): - def __init__(self, data): - super().__init__(data, - cnf["case"]["resolutions"]["case"], - cnf["case"]["resolutions"]["splitchars"], - cnf["tokens"]["attributes"]) - self.check() - - def check(self): - for i in range(self.n_data): - line = self.data[i] - sline = self.splitline(line) - for j in range(len(sline)): - word = sline[j] - if self.tokens.is_valid(word): - if sline[j-1] == "'": - line = line.replace(word, word.lower(), 1) - self.data[i] = line - - -class CaseConstants(CaseCheck): - def __init__(self, data): - super().__init__(data, - cnf["case"]["constants"]["case"], - cnf["case"]["constants"]["splitchars"], - cnf["tokens"]["constants"]) - self.check() - - -class CaseStandardLogic(CaseCheck): - def __init__(self, data): - super().__init__(data, - cnf["case"]["standard-logic"]["case"], - cnf["case"]["standard-logic"]["splitchars"], - cnf["tokens"]["standard-logic"]) - self.check() - - -class RemoveSpaceBeforeBracket(BaseCheck): - def __init__(self, data): - super().__init__(data) - self.tokens = Tokens(cnf["tokens"]["types"]) - self.check() - - def check(self): - for i in range(self.n_data): - for t in self.tokens.all(): - self.data[i] = self.data[i].replace(f"{t} (", f"{t}(") - - -class AlignProcedureArgs(BaseCheck): - def __init__(self, data): - super().__init__(data) - self.check() - - def check(self): - proc_span = [0, 0] - pos1 = 0 - for i, _ in enumerate(self.data): - line = self.data[i] - if line.strip().startswith('procedure'): - if ":" in line: - proc_span[0] = i - pos1 = line.find('(') + 2 - elif proc_span[0] > 0: - line = ' ' * pos1 + line.strip() - - if proc_span[0] > 0 and (line.strip().endswith('is') or line.strip().endswith(');')): - proc_span[1] = i - - self.data[i] = line - - if proc_span[1] > proc_span[0]: - print(proc_span) - type_len = [] - name_len = [] - dir_len = [] - for j in range(proc_span[0], proc_span[1]+1): - sline = self.data[j][pos1:].split() - if len(sline) >= 4: - type_len.append(len(sline[0])) - name_len.append(len(sline[1])) - dir_len.append(len(sline[3])) - else: - print(f"{j}: ERROR1: {self.data[j]} -> {sline}") - sys.stdout.flush() - type_len = max(type_len) - name_len = max(name_len) - dir_len = max(dir_len) - - for j in range(proc_span[0], proc_span[1]+1): - line = self.data[j][:pos1] - sline = self.data[j][pos1:].split() - if len(sline) >= 5: - line += f"{sline[0]:{type_len}s} {sline[1]:{name_len}s} {sline[2]} {sline[3]:{dir_len}s} {' '.join(sline[4:])}" - else: - print(f"{j}: ERROR2: {self.data[j]} -> {sline}") - sys.stdout.flush() - self.data[j] = line - proc_span = [0, 0] - - -class Tokens: - """ - Class for tokens - """ - def __init__(self, tokens): - self._tokens = tokens - - def all(self): - return self._tokens - - def is_valid(self, val): - if val.lower() in self._tokens: - return True - return False - - -if __name__ == "__main__": - # load config file - basedir = getenv("HDL_WORK") - config_file = path.join(basedir, "tools", "vhdl_style_fix.yaml") - cnf = load(open(config_file, 'r'), Loader=FullLoader) - # Parse command line arguments - parser = ArgumentParser( - description="".join(dedent("""\ - vhdl style fixer: - * vhdl_style_fix.py filename -h - \n""")), - formatter_class=RawTextHelpFormatter) - parser.add_argument('filename', type=str, help="filename to fix") - parser.add_argument('-v', '--verbose', action='store_true', help="verbose output") - args = parser.parse_args() - - main() diff --git a/tools/vhdl_style_fix.yaml b/tools/vhdl_style_fix.yaml deleted file mode 100644 index 85bf16651482b63e7a190e7540348eb023a223a7..0000000000000000000000000000000000000000 --- a/tools/vhdl_style_fix.yaml +++ /dev/null @@ -1,240 +0,0 @@ -# -# config file for vhdl_style_fix.py -# - -space: - remove-trailing: True - add-around-operators: True - add-around-delimiters: False - remove-before-bracket: True - -indend: - apply: False - size: 2 - -align: - procedure-args: False - -case: - standard-logic: - convert: True - case: "lower" - splitchars: [" ", ".", ";", "(", ")", ","] - constants: - convert: True - case: "lower" - splitchars: [" ", ".", ";", "(", ")", ","] - reserved-words: - convert: True - case: "lower" - splitchars: [" ", ".", ";", "(", ")"] - types: - convert: True - case: "lower" - splitchars: [" ", ".", ";", "(", ")"] - conversions: - convert: True - case: "lower" - splitchars: [" ", ".", ";", "(", ")"] - resolutions: - convert: True - case: "lower" - splitchars: [" ", ".", ";", "(", ")"] - attributes: - convert: True - case: "lower" - splitchars: [" ", ".", ";", "(", ")", "'"] - -# all tokens used -tokens: - types: - - "bit" - - "bit_vector" - - "integer" - - "natural" - - "positive" - - "boolean" - - "string" - - "character" - - "real" - - "time" - - "delay_length" - - "std_ulogic" - - "std_ulogic_vector" - - "std_logic" - - "std_logic_vector" - conversions: - - "signed" - - "unsigned" - - "to_signed" - - "to_unsigned" - - "to_integer" - - "to_uint" - - "to_sint" - - "to_ureal" - - "to_sreal" - - "to_uvec" - - "to_svec" - resolutions: - - "'u'" - - "'x'" - - "'0'" - - "'1'" - - "'z'" - - "'w'" - - "'l'" - - "'h'" - - "'-'" - constants: - - "true" - - "false" - standard-logic: - - "ieee" - - "std_logic_1164" - - "numeric_std" - - "math_real" - - "std_logic_textio" - - "resize" - operators: - - "*" - - "/" - - "+" - - "-" - - "&" - - "=" - - "<" - - ">" - - ":" - delimiters: - - ":" - attributes: - - "base" - - "left" - - "right" - - "high" - - "low" - - "ascending" - - "image" - - "value" - - "pos" - - "val" - - "succ" - - "pred" - - "leftof" - - "rightof" - - "range" - - "reverse_range" - - "length" - - "ascending" - - "delayed" - - "stable" - - "quiet" - - "transaction" - - "event" - - "active" - - "last_event" - - "last_active" - - "last_value" - - "driving" - - "driving_value" - - "simple_name" - - "instance_name" - - "path_name" - reserved-words: - - "abs" - - "access" - - "after" - - "alias" - - "all" - - "and" - - "architecture" - - "array" - - "assert" - - "attribute" - - "begin" - - "block" - - "body" - - "buffer" - - "bus" - - "case" - - "component" - - "configuration" - - "constant" - - "disconnect" - - "downto" - - "else" - - "elsif" - - "end" - - "entity" - - "exit" - - "file" - - "for" - - "function" - - "generate" - - "generic" - - "group" - - "guarded" - - "if" - - "impure" - - "in" - - "inertial" - - "inout" - - "is" - - "label" - - "library" - - "linkage" - - "literal" - - "loop" - - "map" - - "mod" - - "nand" - - "new" - - "next" - - "nor" - - "not" - - "null" - - "of" - - "on" - - "open" - - "or" - - "others" - - "out" - - "package" - - "port" - - "postponed" - - "procedure" - - "process" - - "pure" - - "range" - - "record" - - "register" - - "reject" - - "rem" - - "report" - - "return" - - "rol" - - "ror" - - "select" - - "severity" - - "signal" - - "shared" - - "sla" - - "sll" - - "sra" - - "srl" - - "subtype" - - "then" - - "to" - - "transport" - - "type" - - "unaffected" - - "units" - - "until" - - "use" - - "variable" - - "wait" - - "when" - - "while" - - "with" - - "xnor" - - "xor" \ No newline at end of file diff --git a/tools/vhdl_style_fix_all_files.py b/tools/vhdl_style_fix_all_files.py deleted file mode 100755 index 486e6c9026607fd94dcbfa371232bfac8b77c657..0000000000000000000000000000000000000000 --- a/tools/vhdl_style_fix_all_files.py +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/python3 - -# ########################################################################## -# Copyright 2020 -# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ########################################################################## - -# ########################################################################## -# Author: Pieter Donker -# Purpose: run vhdl_style_fix.py on all files in the hdl dir using multiple -# workers -# Description: -# -p: number of workers to use -# -v: verbose -# usage: -# cd git/hdl/ -# . ./init_hdl.sh -# vhdl_style_fix_all_files.py -p 4 -# -# ########################################################################## - -from os import getenv, path -from sys import exit, version_info -from time import sleep -from argparse import ArgumentParser, RawTextHelpFormatter -from textwrap import dedent -from subprocess import Popen, PIPE - -from multiprocessing import Process, Queue -from queue import Empty - -PYTHON_VERSION = version_info[0] - - -def run_cmd(cmd): - """ run_cmd() - run 'cmd' in a terminal and return response - cmd: command to execute in terminal - return: 'stdout' or 'Error, stderr' in case of a error - """ - - proc = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE) - _stdout, _stderr = proc.communicate() - if _stderr: - stderr = _stderr.decode('utf - 8') if PYTHON_VERSION == 3 else _stderr - print(stderr) - return 'Error, {}'.format(stderr) - stdout = _stdout.decode('utf - 8') if PYTHON_VERSION == 3 else _stdout - return stdout - - -class Worker(Process): - """ Worker, used for file checking before giving it to vsg to fix. - generated files and files with inside message 'DO NOT EDIT' are skipped. - """ - def __init__(self, id, control, in_data, out_data, verbose=None): - Process.__init__(self) - self.id = id - self.control = control - self.in_data = in_data - self.out_data = out_data - self.verbose = False if verbose is None else verbose - self.stop = False - - def is_generated(self, filename): - """ - Look if 'generated' is found in the pathname. - Return the skip message and return True if found, else False - """ - if "generated" in filename: - response = f"skip {filename}: (generated file)" - self.out_data.put(response) - return True - return False - - def is_do_not_edit(self, filename): - """ - Look if 'DO NOT EDIT' is found inside the file. - Return the skip message and return True if found, else False - """ - with open(filename, 'r') as fd: - data = fd.read() - if "DO NOT EDIT" in data: - response = f"skip {filename}: (DO NOT EDIT)" - self.out_data.put(response) - return True - return False - - def run_fix(self, filename): - """ - Use vhdl_style_fix.py to fix the file - """ - basedir = getenv("HDL_WORK") - fixtool = path.join(basedir, "tools", "vhdl_style_fix.py") - cmd = f"{fixtool} {filename}" - if self.verbose: - cmd += " --verbose" - response = run_cmd(cmd) - self.out_data.put(response.strip()) - - def run(self): - while not self.stop: - try: - if not self.control.empty(): - control = self.control.get() - if control == "stop": - self.stop = True - print(f"stop worker {self.id}") - - # get next vhd file to process - filename = self.in_data.get(block=False) - - # look if generated is part of the full-filename, skip if found - if self.is_generated(filename): - continue - - # look if inside the file is a DO NOT EDIT message, skip if found - if self.is_do_not_edit(filename): - continue - - # fix the vhd file with vsg - self.run_fix(filename) - - except Empty: - sleep(0.001) - - -def main(): - basedir = getenv("HDL_WORK") - print(f"basedir = {basedir}") - # dirs in basedir to check/fix - checkdirs = ["/libraries/base/", "/libraries/dsp/", "/libraries/io/", - "/libraries/technology/", "/boards/", "/applications/"] - - # info for the workers, number of workers to use is given by cmdline arg --proc - n_workers = args.proc - workers = [] - worker_control = [Queue() for i in range(n_workers)] - process_queue = Queue() - response_queue = Queue() - - n_files = 0 - n_files_done = 0 - - # start the workers - for id in range(n_workers): - if args.verbose: - print(f"start vsg worker {id}") - _p = Worker(id, worker_control[id], process_queue, response_queue) - workers.append(_p) - _p.start() - - # put all vhd files in the - for checkdir in checkdirs: - dirname = basedir + checkdir - if args.verbose: - print(f"dirname = {dirname}") - cmd = f'find {dirname} -name "*vhd"' - response = run_cmd(cmd) - for filename in response.splitlines(): - process_queue.put(filename) - n_files += 1 - - if args.verbose: - print(f"put {n_files} in the worker queue") - fd = open("vhdl_fix_all_response.txt", 'w') - while True: - if response_queue.empty(): - sleep(0.001) - else: - response = response_queue.get() - if response: - fd.write(response + '\n') - fd.flush() - if args.verbose: - print(response) - n_files_done += 1 - - if n_files == n_files_done: - if args.verbose: - print("All files processed, stop workers now") - for nr in range(n_workers): - worker_control[nr].put("stop") - sleep(0.5) - - for worker in workers: - worker.terminate() - break - fd.close() - return 0 - - -if __name__ == "__main__": - # Parse command line arguments - parser = ArgumentParser( - description="".join(dedent(""" - run vhdl-style-guide on all found hdl files with settings from vsg_config.yaml: - with --proc the number of vsg workers can be selected, output from this script - is put in 'vsg_fix_all_response.txt' and send to stdout if --verbose is used. - \n""")), - formatter_class=RawTextHelpFormatter) - parser.add_argument('-p', '--proc', type=int, default=4, help="number of processes to use") - parser.add_argument('-v', '--verbose', action='store_true', help="verbose output") - args = parser.parse_args() - exit_code = main() - exit(exit_code)