blob: 76e167c7767b1ad21fc2b56b07ba65a4b7e4906b [file] [log] [blame]
#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
r"""Flash Controller Generator
"""
import logging as log
import sys
from collections import OrderedDict
from pathlib import Path
import hjson
from mako.template import Template
class Flash:
"""Flash class contains information regarding parameter defaults.
For now, only expose banks / pages_per_bank for user configuration.
For now, also enforce power of 2 requirement.
"""
max_banks = 4
max_pages_per_bank = 1024
def __init__(self, mem, base_addr):
self.base_addr = int(base_addr, 16)
self.banks = mem.get('banks', 2)
self.pages_per_bank = mem.get('pages_per_bank', 8)
self.program_resolution = mem.get('program_resolution', 128)
self.words_per_page = 256
self.data_width = 64
self.metadata_width = 12
self.info_types = 3
self.infos_per_bank = [10, 1, 2]
self.word_bytes = int(self.data_width / 8)
self.pgm_resolution_bytes = int(self.program_resolution * self.word_bytes)
self.check_values()
# populate size variable
self.bytes_per_page = self.word_bytes * self.words_per_page
self.bytes_per_bank = self.bytes_per_page * self.pages_per_bank
self.total_bytes = self.bytes_per_bank * self.banks
size_int = int(self.total_bytes)
self.size = hex(size_int)
self.end_addr = self.base_addr + size_int
def is_pow2(self, n):
return (n != 0) and (n & (n - 1) == 0)
def check_values(self):
pow2_check = (self.is_pow2(self.banks) and
self.is_pow2(self.pages_per_bank) and
self.is_pow2(self.program_resolution))
limit_check = ((self.banks <= Flash.max_banks) and
(self.pages_per_bank <= Flash.max_pages_per_bank))
if not pow2_check:
raise ValueError(f'flash power of 2 check failed. A supplied parameter '
'is not power of 2')
if not limit_check:
raise ValueError(f'flash number of banks and pages per bank too large')
# Common header for generated files
def main():
current = Path(__file__).parent.absolute()
hjson_tpl = Template(filename=str(current / '../data/flash_ctrl.hjson.tpl'))
region_cfg_tpl = Template(filename=str(current / '../data/flash_ctrl_region_cfg.sv.tpl'))
rtl_tpl = Template(filename=str(current / '../data/flash_ctrl.sv.tpl'))
pkg_tpl = Template(filename=str(current / '../data/flash_ctrl_pkg.sv.tpl'))
hjson_out = current / '../data/flash_ctrl.hjson'
region_cfg_out = current / '../rtl/flash_ctrl_region_cfg.sv'
rtl_out = current / '../rtl/flash_ctrl.sv'
pkg_out = current / '../rtl/flash_ctrl_pkg.sv'
cfgpath = current / '../../../top_earlgrey/data/autogen/top_earlgrey.gen.hjson'
try:
with open(cfgpath, 'r') as cfg:
topcfg = hjson.load(cfg, use_decimal=True, object_pairs_hook=OrderedDict)
except ValueError:
log.error("{} not found".format(cfgpath))
raise SystemExit(sys.exc_info()[1])
flash_mems = [module for module in topcfg['module'] if module['type'] == 'flash_ctrl']
if len(flash_mems) > 1:
log.error("This design does not currently support multiple flashes")
return
cfg = Flash(flash_mems[0]['memory']['mem']['config'],
flash_mems[0]['base_addrs']['mem'])
# generate hjson
hjson_out.write_text(hjson_tpl.render(cfg=cfg))
# generate rtl package
pkg_out.write_text(pkg_tpl.render(cfg=cfg))
# generate reg wrap
region_cfg_out.write_text(region_cfg_tpl.render(cfg=cfg))
# generate top level
rtl_out.write_text(rtl_tpl.render(cfg=cfg))
if __name__ == "__main__":
main()