diff --git a/tools/vhdl_style_fix.py b/tools/vhdl_style_fix.py index 5f83e32d020091471a313e811ec35e47d24dd5fd..2ac9776a1ae6c00f47034274faab9df03b867efd 100755 --- a/tools/vhdl_style_fix.py +++ b/tools/vhdl_style_fix.py @@ -1,9 +1,38 @@ #!/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 collections import OrderedDict from argparse import ArgumentParser, RawTextHelpFormatter from textwrap import dedent -# from copy import copy +from yaml import load, FullLoader def main(): @@ -12,41 +41,53 @@ def main(): sdata = data_in.splitlines() - rts = RemoveTrailingSpaces(sdata) - sdata = rts.get_data() + if cnf["space"]["remove-trailing"]: + func = RemoveTrailingSpaces(sdata) + sdata = func.get_data() - asao = AddSpacesAroundOperators(sdata) - sdata = asao.get_data() + if cnf["space"]["add-around-operators"]: + func = AddSpacesAroundOperators(sdata) + sdata = func.get_data() - # asad = AddSpacesAroundDelimiters(sdata) - # sdata = asad.get_data() + if cnf["space"]["add-around-delimiters"]: + func = AddSpacesAroundDelimiters(sdata) + sdata = func.get_data() - csl = CaseStandardLogic(sdata) - sdata = csl.get_data() + if cnf["case"]["standard-logic"]: + func = CaseStandardLogic(sdata) + sdata = func.get_data() - cc = CaseConstants(sdata) - sdata = cc.get_data() + if cnf["case"]["constants"]: + func = CaseConstants(sdata) + sdata = func.get_data() - ck = CaseKeywords(sdata) - sdata = ck.get_data() + if cnf["case"]["reserved-words"]: + func = CaseReservedWords(sdata) + sdata = func.get_data() - ct = CaseTypes(sdata) - sdata = ct.get_data() + if cnf["case"]["types"]: + func = CaseTypes(sdata) + sdata = func.get_data() - cc = CaseConversions(sdata) - sdata = cc.get_data() + if cnf["case"]["conversions"]: + func = CaseConversions(sdata) + sdata = func.get_data() - cr = CaseResolutions(sdata) - sdata = cr.get_data() + if cnf["case"]["resolutions"]: + func = CaseResolutions(sdata) + sdata = func.get_data() - ca = CaseAttributes(sdata) - sdata = ca.get_data() + if cnf["case"]["attributes"]: + func = CaseAttributes(sdata) + sdata = func.get_data() - rsbb = RemoveSpaceBeforeBracket(sdata) - sdata = rsbb.get_data() + if cnf["space"]["remove-before-bracket"]: + func = RemoveSpaceBeforeBracket(sdata) + sdata = func.get_data() - # sdata = apa.get_data() - # apa = AlignProcedureArgs(sdata) + if cnf["align"]["procedure-args"]: + func = AlignProcedureArgs(sdata) + sdata = func.get_data() data = '\n'.join(sdata) + "\n" @@ -60,6 +101,7 @@ def main(): class BaseCheck: def __init__(self, data): self.splitchars = [] + self.tokens = None self.data = data self.n_data = len(self.data) @@ -110,7 +152,7 @@ class RemoveTrailingSpaces(BaseCheck): class AddSpacesAroundOperators(BaseCheck): def __init__(self, data): super().__init__(data) - self.tokens = Operators() + self.tokens = Tokens(cnf["tokens"]["operators"]) self.check() def check(self): @@ -130,7 +172,7 @@ class AddSpacesAroundOperators(BaseCheck): if iscomment: comment_str.append(ch) continue - + if ch in ['"']: if isoperator: code_str.append(' ') @@ -218,7 +260,7 @@ class AddSpacesAroundOperators(BaseCheck): class AddSpacesAroundDelimiters(BaseCheck): def __init__(self, data): super().__init__(data) - self.tokens = Delimiters() + self.tokens = Tokens(cnf["tokens"]["delimiters"]) self.check() def check(self): @@ -267,79 +309,65 @@ class AddSpacesAroundDelimiters(BaseCheck): self.data[i] = ''.join(new_line) -class CaseKeywords(BaseCheck): - def __init__(self, data): +class CaseCheck(BaseCheck): + def __init__(self, data, case, splitchars, tokens): super().__init__(data) - self.splitchars = [" ", ".", ";", "(", ")"] - self.reserved_words = ReservedWords() - self.check() + 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.reserved_words.is_valid(word): - line = line.replace(word, word.lower(), 1) + if self.tokens.is_valid(word): + line = line.replace(word, self.case(word), 1) self.data[i] = line -class CaseTypes(BaseCheck): +class CaseReservedWords(CaseCheck): def __init__(self, data): - super().__init__(data) - self.splitchars = [" ", ".", ";", "(", ")"] - self.tokens = Types() + super().__init__(data, + cnf["case"]["reserved-words"]["case"], + cnf["case"]["reserved-words"]["splitchars"], + cnf["tokens"]["reserved-words"]) self.check() - 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, word.lower(), 1) - self.data[i] = line - -class CaseConversions(BaseCheck): +class CaseTypes(CaseCheck): def __init__(self, data): - super().__init__(data) - self.splitchars = [" ", ".", ";", "(", ")"] - self.tokens = Conversions() + super().__init__(data, + cnf["case"]["types"]["case"], + cnf["case"]["types"]["splitchars"], + cnf["tokens"]["types"]) self.check() - 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, word.lower(), 1) - self.data[i] = line - -class CaseResolutions(BaseCheck): +class CaseConversions(CaseCheck): def __init__(self, data): - super().__init__(data) - self.splitchars = [" ", ".", ";", "(", ")"] - self.tokens = Resolutions() + super().__init__(data, + cnf["case"]["conversions"]["case"], + cnf["case"]["conversions"]["splitchars"], + cnf["tokens"]["conversions"]) self.check() - 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, word.lower(), 1) - self.data[i] = line +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(BaseCheck): + +class CaseAttributes(CaseCheck): def __init__(self, data): - super().__init__(data) - self.splitchars = [" ", ".", ";", "(", ")", "'"] - self.tokens = Attributes() + super().__init__(data, + cnf["case"]["resolutions"]["case"], + cnf["case"]["resolutions"]["splitchars"], + cnf["tokens"]["attributes"]) self.check() def check(self): @@ -354,51 +382,33 @@ class CaseAttributes(BaseCheck): self.data[i] = line -class CaseConstants(BaseCheck): +class CaseConstants(CaseCheck): def __init__(self, data): - super().__init__(data) - self.splitchars = [" ", ".", ";", "(", ")", ","] - self.tokens = Constants() + super().__init__(data, + cnf["case"]["constants"]["case"], + cnf["case"]["constants"]["splitchars"], + cnf["tokens"]["constants"]) 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): - line = line.replace(word, word.lower(), 1) - self.data[i] = line - -class CaseStandardLogic(BaseCheck): +class CaseStandardLogic(CaseCheck): def __init__(self, data): - super().__init__(data) - self.splitchars = [" ", ".", ";", "(", ")", ","] - self.tokens = StandardLogic() + super().__init__(data, + cnf["case"]["standard-logic"]["case"], + cnf["case"]["standard-logic"]["splitchars"], + cnf["tokens"]["standard-logic"]) 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): - line = line.replace(word, word.lower(), 1) - self.data[i] = line - class RemoveSpaceBeforeBracket(BaseCheck): def __init__(self, data): super().__init__(data) - self.types = Types() + self.tokens = Tokens(cnf["tokens"]["types"]) self.check() def check(self): for i in range(self.n_data): - for t in self.types.tokens(): + for t in self.tokens.all(): self.data[i] = self.data[i].replace(f"{t} (", f"{t}(") @@ -454,88 +464,27 @@ class AlignProcedureArgs(BaseCheck): proc_span = [0, 0] -class Token: +class Tokens: """ - Base class for tokens + Class for tokens """ def __init__(self, tokens): self._tokens = tokens - def tokens(self): + def all(self): return self._tokens - + def is_valid(self, val): if val.lower() in self._tokens: return True return False -class Types(Token): - def __init__(self): - super().__init__(["bit", "bit_vector", "integer", "natural", "positive", "boolean", "string", - "character", "real", "time", "delay_length", - "std_ulogic", "std_ulogic_vector", "std_logic", "std_logic_vector"]) - - -class Conversions(Token): - def __init__(self): - super().__init__(["signed", "unsigned", "to_signed", "to_unsigned", "to_integer", "to_uint", "to_sint", - "to_ureal", "to_sreal", "to_uvec", "to_svec"]) - - -class Resolutions(Token): - def __init__(self): - super().__init__(["'u'", "'x'", "'0'", "'1'", "'z'", "'w'", "'l'", "'h'", "'-'"]) - - -class Constants(Token): - def __init__(self): - super().__init__(["true", "false"]) - - -class StandardLogic(Token): - def __init__(self): - super().__init__(["ieee", "std_logic_1164", "numeric_std", "math_real", "std_logic_textio", "resize"]) - - -class Attributes(Token): - def __init__(self): - super().__init__(["base", "left", "right", "high", "low", "ascending", "image", "value", "pos", "val", "succ", - "pred", "leftof", "rightof", "left", "left", "right", "right", "high", "high", "low", "low", - "range", "range", "reverse_range", "reverse_range", "length", "length", "ascending", - "ascending", "delayed", "stable", "stable", "quiet", "quiet", "transaction", "event", - "active", "last_event", "last_active", "last_value", "driving", "driving_value", - "simple_name", "instance_name", "path_name"]) - - -class Operators(Token): - def __init__(self): - super().__init__(["*", "/", "+", "-", "&", "=", "<", ">", ":"]) - - -class Delimiters(Token): - def __init__(self): - super().__init__([":"]) - - -class ReservedWords(Token): - def __init__(self): - super().__init__(["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"]) - - 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("""\ diff --git a/tools/vhdl_style_fix.yaml b/tools/vhdl_style_fix.yaml new file mode 100644 index 0000000000000000000000000000000000000000..85bf16651482b63e7a190e7540348eb023a223a7 --- /dev/null +++ b/tools/vhdl_style_fix.yaml @@ -0,0 +1,240 @@ +# +# 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 index 4f175ef66cba34cdceef0a51312f715c99637e00..486e6c9026607fd94dcbfa371232bfac8b77c657 100755 --- a/tools/vhdl_style_fix_all_files.py +++ b/tools/vhdl_style_fix_all_files.py @@ -1,6 +1,38 @@ #!/usr/bin/python3 -from os import getenv +# ########################################################################## +# 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 @@ -71,7 +103,9 @@ class Worker(Process): """ Use vhdl_style_fix.py to fix the file """ - cmd = f"/home/donker/git/hdl/vhdl_style_fix.py {filename}" + 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) @@ -84,7 +118,7 @@ class Worker(Process): control = self.control.get() if control == "stop": self.stop = True - print(f"stop vsg worker {self.id}") + print(f"stop worker {self.id}") # get next vhd file to process filename = self.in_data.get(block=False)