main.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. # vim: ts=8 sw=8 noexpandtab
  2. #
  3. # CRC code generator
  4. #
  5. # Copyright (c) 2019-2023 Michael Büsch <m@bues.ch>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. #
  21. from libcrcgen import CrcGen, CrcGenError, CRC_PARAMETERS, poly2int, int2poly
  22. import sys
  23. import argparse
  24. __all__ = [
  25. "main",
  26. ]
  27. def poly_convert(p, nr_crc_bits, shift_right):
  28. if nr_crc_bits is None:
  29. raise CrcGenError("-B|--nr-crc-bits is required for -T|--polynomial-convert")
  30. p = p.strip()
  31. try:
  32. # Hex format
  33. if not p.startswith("0x"):
  34. raise ValueError
  35. p = int(p[2:], 16)
  36. p = int2poly(p, nr_crc_bits, shift_right)
  37. print(p)
  38. return 0
  39. except ValueError:
  40. pass
  41. try:
  42. # Decimal format
  43. p = int(p, 10)
  44. p = int2poly(p, nr_crc_bits, shift_right)
  45. print(p)
  46. return 0
  47. except ValueError:
  48. pass
  49. try:
  50. # Polynomial coefficient format
  51. p = poly2int(p, nr_crc_bits, shift_right)
  52. print(f"0x{p:X}")
  53. return 0
  54. except ValueError:
  55. pass
  56. raise CrcGenError("-T|--polynomial-convert: Invalid polynomial")
  57. def main():
  58. try:
  59. def argInt(string):
  60. if string.startswith("0x"):
  61. return int(string[2:], 16)
  62. return int(string)
  63. p = argparse.ArgumentParser(
  64. description="CRC algorithm HDL code generator (VHDL, Verilog, MyHDL)"
  65. )
  66. g = p.add_mutually_exclusive_group(required=True)
  67. g.add_argument("-v", "--verilog-function", action="store_true",
  68. help="Generate Verilog function")
  69. g.add_argument("-m", "--verilog-module", action="store_true",
  70. help="Generate Verilog module")
  71. g.add_argument("-V", "--vhdl", action="store_true",
  72. help="Generate VHDL module")
  73. g.add_argument("-M", "--myhdl", action="store_true",
  74. help="Generate MyHDL block")
  75. g.add_argument("-p", "--python", action="store_true",
  76. help="Generate Python code (mainly useful for testing purposes)")
  77. g.add_argument("-c", "--c", action="store_true",
  78. help="Generate C code (mainly useful for testing purposes)")
  79. g.add_argument("-T", "--polynomial-convert", metavar="POLYNOMIAL", type=str,
  80. help="Convert a polynomial from string to int or vice versa and then exit.")
  81. g.add_argument("--test", action="store_true",
  82. help=argparse.SUPPRESS)
  83. p.add_argument("-a", "--algorithm", type=str,
  84. choices=CRC_PARAMETERS.keys(), default="CRC-32",
  85. help="Select the CRC algorithm. "
  86. "Individual algorithm parameters (e.g. polynomial) can be overridden with the options below.")
  87. p.add_argument("-P", "--polynomial", type=str,
  88. help="Use this CRC polynomial for code generation")
  89. p.add_argument("-B", "--nr-crc-bits", type=argInt,
  90. help="Number of CRC bits.")
  91. p.add_argument("-b", "--nr-data-bits", type=argInt, default="8",
  92. help="Number of input data word bits.")
  93. g = p.add_mutually_exclusive_group()
  94. g.add_argument("-R", "--shift-right", action="store_true",
  95. help="CRC algorithm shift direction: right shift")
  96. g.add_argument("-L", "--shift-left", action="store_true",
  97. help="CRC algorithm shift direction: left shift")
  98. p.add_argument("-n", "--name", type=str, default="crc",
  99. help="Generated function/module name")
  100. p.add_argument("-D", "--data-param", type=str, default="data",
  101. help="Generated function/module data parameter name")
  102. p.add_argument("-C", "--crc-in-param", type=str, default="crcIn",
  103. help="Generated function/module crc input parameter name")
  104. p.add_argument("-o", "--crc-out-param", type=str, default="crcOut",
  105. help="Generated module crc output parameter name")
  106. p.add_argument("-S", "--static", action="store_true",
  107. help="Generate static C function. (only if -c)")
  108. p.add_argument("-I", "--inline", action="store_true",
  109. help="Generate inline C function. (only if -c)")
  110. p.add_argument("-O", "--optimize", type=argInt, default=CrcGen.OPT_ALL,
  111. help=f"Select individual algorithm optimizer steps. "
  112. f"The argument to the -O option can be any sum of the following integers: "
  113. f"-O{CrcGen.OPT_FLATTEN} (Flatten the bit operation tree), "
  114. f"-O{CrcGen.OPT_ELIMINATE} (Eliminate redundant operations), "
  115. f"-O{CrcGen.OPT_LEX} (Sort the operands in lexicographical order where possible). "
  116. f"-O{CrcGen.OPT_NONE} disables all optimizer steps. "
  117. f"If this option is not given, then by default all optimizer steps are enabled (-O{CrcGen.OPT_ALL}).")
  118. args = p.parse_args()
  119. if (args.nr_crc_bits is not None and
  120. args.nr_crc_bits < 1):
  121. raise CrcGenError("Invalid -B|--nr-crc-bits argument.")
  122. if args.nr_data_bits < 1:
  123. raise CrcGenError("Invalid -b|--nr-data-bits argument.")
  124. if args.polynomial_convert is not None:
  125. return poly_convert(args.polynomial_convert,
  126. args.nr_crc_bits,
  127. args.shift_right)
  128. crcParameters = CRC_PARAMETERS[args.algorithm].copy()
  129. if args.nr_crc_bits is not None:
  130. crcParameters["nrBits"] = args.nr_crc_bits
  131. if args.shift_right:
  132. crcParameters["shiftRight"] = True
  133. if args.shift_left:
  134. crcParameters["shiftRight"] = False
  135. if args.polynomial is not None:
  136. crcParameters["polynomial"] = poly2int(
  137. args.polynomial,
  138. crcParameters["nrBits"],
  139. crcParameters["shiftRight"])
  140. polynomial = crcParameters["polynomial"]
  141. nrCrcBits = crcParameters["nrBits"]
  142. shiftRight = crcParameters["shiftRight"]
  143. if polynomial > ((1 << nrCrcBits) - 1):
  144. raise CrcGenError(f"Invalid polynomial. "
  145. f"It is bigger than the CRC width "
  146. f"of (2**{nrCrcBits})-1.")
  147. if args.test:
  148. from libcrcgen.generator_test import CrcGenTest
  149. CrcGenClass = CrcGenTest
  150. else:
  151. CrcGenClass = CrcGen
  152. gen = CrcGenClass(P=polynomial,
  153. nrCrcBits=nrCrcBits,
  154. nrDataBits=args.nr_data_bits,
  155. shiftRight=shiftRight,
  156. optimize=args.optimize)
  157. if args.test:
  158. gen.runTests()
  159. else:
  160. if args.python:
  161. print(gen.genPython(funcName=args.name,
  162. crcVarName=args.crc_in_param,
  163. dataVarName=args.data_param))
  164. elif args.verilog_function:
  165. print(gen.genVerilog(genFunction=True,
  166. name=args.name,
  167. inDataName=args.data_param,
  168. inCrcName=args.crc_in_param,
  169. outCrcName=args.crc_out_param))
  170. elif args.verilog_module:
  171. print(gen.genVerilog(genFunction=False,
  172. name=args.name,
  173. inDataName=args.data_param,
  174. inCrcName=args.crc_in_param,
  175. outCrcName=args.crc_out_param))
  176. elif args.vhdl:
  177. print(gen.genVHDL(name=args.name,
  178. inDataName=args.data_param,
  179. inCrcName=args.crc_in_param,
  180. outCrcName=args.crc_out_param))
  181. elif args.myhdl:
  182. print(gen.genMyHDL(blockName=args.name,
  183. inDataName=args.data_param,
  184. inCrcName=args.crc_in_param,
  185. outCrcName=args.crc_out_param))
  186. elif args.c:
  187. print(gen.genC(funcName=args.name,
  188. crcVarName=args.crc_in_param,
  189. dataVarName=args.data_param,
  190. static=args.static,
  191. inline=args.inline))
  192. else:
  193. assert False
  194. return 0
  195. except CrcGenError as e:
  196. print("ERROR: " + str(e), file=sys.stderr)
  197. return 1