Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # Copyright lowRISC contributors. |
| 3 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 4 | # SPDX-License-Identifier: Apache-2.0 |
| 5 | r"""Generate RTL and documentation collateral from OTP memory |
| 6 | map definition file (hjson). |
| 7 | """ |
| 8 | import argparse |
| 9 | import logging as log |
| 10 | import random |
| 11 | from pathlib import Path |
| 12 | |
| 13 | import hjson |
Michael Schaffner | 1fff985 | 2021-01-08 14:06:35 -0800 | [diff] [blame] | 14 | from lib.common import wrapped_docstring |
| 15 | from lib.OtpMemMap import OtpMemMap |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 16 | from mako.template import Template |
| 17 | |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 18 | TABLE_HEADER_COMMENT = '''<!-- |
| 19 | DO NOT EDIT THIS FILE DIRECTLY. |
Michael Schaffner | 1fff985 | 2021-01-08 14:06:35 -0800 | [diff] [blame] | 20 | It has been generated with ./util/design/gen-otp-mmap.py |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 21 | --> |
| 22 | |
| 23 | ''' |
| 24 | |
| 25 | # memory map source |
Michael Schaffner | 1fff985 | 2021-01-08 14:06:35 -0800 | [diff] [blame] | 26 | MMAP_DEFINITION_FILE = "hw/ip/otp_ctrl/data/otp_ctrl_mmap.hjson" |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 27 | # documentation tables to generate |
Michael Schaffner | 1fff985 | 2021-01-08 14:06:35 -0800 | [diff] [blame] | 28 | PARTITIONS_TABLE_FILE = "hw/ip/otp_ctrl/doc/otp_ctrl_partitions.md" |
| 29 | DIGESTS_TABLE_FILE = "hw/ip/otp_ctrl/doc/otp_ctrl_digests.md" |
| 30 | MMAP_TABLE_FILE = "hw/ip/otp_ctrl/doc/otp_ctrl_mmap.md" |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 31 | # code templates to render |
Michael Schaffner | 1fff985 | 2021-01-08 14:06:35 -0800 | [diff] [blame] | 32 | TEMPLATES = [ |
| 33 | "hw/ip/otp_ctrl/data/otp_ctrl.hjson.tpl", |
| 34 | "hw/ip/otp_ctrl/rtl/otp_ctrl_part_pkg.sv.tpl" |
| 35 | ] |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 36 | |
| 37 | |
| 38 | def main(): |
Rupert Swarbrick | 4af3c81 | 2021-08-31 17:02:51 +0100 | [diff] [blame] | 39 | log.basicConfig(level=log.WARNING, |
Michael Schaffner | 3c6b2f3 | 2021-01-28 14:53:26 -0800 | [diff] [blame] | 40 | format="%(levelname)s: %(message)s") |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 41 | |
| 42 | parser = argparse.ArgumentParser( |
| 43 | prog="gen-otp-mmap", |
| 44 | description=wrapped_docstring(), |
| 45 | formatter_class=argparse.RawDescriptionHelpFormatter) |
| 46 | |
| 47 | # Generator options for compile time random netlist constants |
| 48 | parser.add_argument('--seed', |
| 49 | type=int, |
| 50 | metavar='<seed>', |
| 51 | help='Custom seed for RNG to compute default values.') |
| 52 | |
| 53 | args = parser.parse_args() |
| 54 | |
| 55 | with open(MMAP_DEFINITION_FILE, 'r') as infile: |
| 56 | config = hjson.load(infile) |
| 57 | |
| 58 | # If specified, override the seed for random netlist constant computation. |
| 59 | if args.seed: |
| 60 | log.warning('Commandline override of seed with {}.'.format( |
| 61 | args.seed)) |
| 62 | config['seed'] = args.seed |
| 63 | # Otherwise, we either take it from the .hjson if present, or |
| 64 | # randomly generate a new seed if not. |
| 65 | else: |
| 66 | random.seed() |
| 67 | new_seed = random.getrandbits(64) |
| 68 | if config.setdefault('seed', new_seed) == new_seed: |
| 69 | log.warning( |
| 70 | 'No seed specified, setting to {}.'.format(new_seed)) |
| 71 | |
Michael Schaffner | 6d32d8d | 2021-01-29 20:37:43 -0800 | [diff] [blame] | 72 | try: |
| 73 | otp_mmap = OtpMemMap(config) |
| 74 | except RuntimeError as err: |
| 75 | log.error(err) |
| 76 | exit(1) |
Michael Schaffner | ac16bb6 | 2020-12-30 17:48:11 -0800 | [diff] [blame] | 77 | |
| 78 | with open(PARTITIONS_TABLE_FILE, 'w') as outfile: |
| 79 | outfile.write(TABLE_HEADER_COMMENT + |
| 80 | otp_mmap.create_partitions_table()) |
| 81 | |
| 82 | with open(DIGESTS_TABLE_FILE, 'w') as outfile: |
| 83 | outfile.write(TABLE_HEADER_COMMENT + |
| 84 | otp_mmap.create_digests_table()) |
| 85 | |
| 86 | with open(MMAP_TABLE_FILE, 'w') as outfile: |
| 87 | outfile.write(TABLE_HEADER_COMMENT + otp_mmap.create_mmap_table()) |
| 88 | |
| 89 | # render all templates |
| 90 | for template in TEMPLATES: |
| 91 | with open(template, 'r') as tplfile: |
| 92 | tpl = Template(tplfile.read()) |
| 93 | with open( |
| 94 | Path(template).parent.joinpath(Path(template).stem), |
| 95 | 'w') as outfile: |
| 96 | outfile.write(tpl.render(otp_mmap=otp_mmap)) |
| 97 | |
| 98 | |
| 99 | if __name__ == "__main__": |
| 100 | main() |