Skip to content
Snippets Groups Projects
Commit 2bb62ab7 authored by Pieter Donker's avatar Pieter Donker
Browse files

gen_doc.py now works for unb1_minimal_sopc

parent 3f8133eb
No related branches found
No related tags found
No related merge requests found
...@@ -46,7 +46,6 @@ from math import ceil ...@@ -46,7 +46,6 @@ from math import ceil
from py_args_lib import * from py_args_lib import *
#import common as cm
def gen_reg_tables(subsection, group_fields): def gen_reg_tables(subsection, group_fields):
""" """
...@@ -65,7 +64,7 @@ def gen_reg_tables(subsection, group_fields): ...@@ -65,7 +64,7 @@ def gen_reg_tables(subsection, group_fields):
# print("New field group") # print("New field group")
for field in group_fields[::-1]: for field in group_fields[::-1]:
i = i+1 i = i+1
field_name = field.name() if field.group_name() == 'None' else field.name().split(field.group_name() + '_')[-1] field_name = field.name() if field.group_name() is None else field.name().split(field.group_name() + '_')[-1]
char_sum = char_sum + len(field_name) char_sum = char_sum + len(field_name)
if char_sum > c_max_chars: if char_sum > c_max_chars:
char_sum = len(field_name) char_sum = len(field_name)
...@@ -76,7 +75,8 @@ def gen_reg_tables(subsection, group_fields): ...@@ -76,7 +75,8 @@ def gen_reg_tables(subsection, group_fields):
last_bit_boundary = bit_bounds[-1] last_bit_boundary = bit_bounds[-1]
# print("field {} upper {} lower {}".format(field.name(), str(field.bit_offset() + field.width() -1), str(field.bit_offset()))) # print("field {} upper {} lower {}".format(field.name(), str(field.bit_offset() + field.width() -1), str(field.bit_offset())))
# print(*bit_bounds) # print(*bit_bounds)
if bit_bounds[-1] != 0 : bit_bounds.append(0) if bit_bounds[-1] != 0:
bit_bounds.append(0)
bit_bounds = [32, 16, 0] if len(bit_bounds) < 3 else bit_bounds bit_bounds = [32, 16, 0] if len(bit_bounds) < 3 else bit_bounds
nof_tables = len(bit_bounds) nof_tables = len(bit_bounds)
...@@ -97,7 +97,7 @@ def gen_reg_tables(subsection, group_fields): ...@@ -97,7 +97,7 @@ def gen_reg_tables(subsection, group_fields):
end_bit = bit_bounds[i] end_bit = bit_bounds[i]
# print("Table {} bounding {} and {}".format(str(i),str(gap_bit+1), str(end_bit))) # print("Table {} bounding {} and {}".format(str(i),str(gap_bit+1), str(end_bit)))
for field in group_fields[::-1]: for field in group_fields[::-1]:
field_name = field.name() if field.group_name() == 'None' else field.name().split(field.group_name() + '_')[-1] field_name = field.name() if field.group_name() is None else field.name().split(field.group_name() + '_')[-1]
upper_bit = field.bit_offset() + field.width() - 1 # inclusive upper_bit = field.bit_offset() + field.width() - 1 # inclusive
# print("field {} has upper bit {} gap bit is {}".format(field_name,str(upper_bit), str(gap_bit))) # print("field {} has upper bit {} gap bit is {}".format(field_name,str(upper_bit), str(gap_bit)))
if upper_bit < gap_bit: if upper_bit < gap_bit:
...@@ -105,7 +105,8 @@ def gen_reg_tables(subsection, group_fields): ...@@ -105,7 +105,8 @@ def gen_reg_tables(subsection, group_fields):
col_list.append(MultiColumn(gap_width, align='|c|', data='RES')) col_list.append(MultiColumn(gap_width, align='|c|', data='RES'))
gap_bit = max(upper_bit, bit_bounds[i]-1) # gap_bit-(nof_cols-1)) gap_bit = max(upper_bit, bit_bounds[i]-1) # gap_bit-(nof_cols-1))
# print("added gap before field {} of width {}".format(field_name, str(gap_width))) # print("added gap before field {} of width {}".format(field_name, str(gap_width)))
if gap_bit == (end_bit-1): break; if gap_bit == (end_bit-1):
break
# print("field {} bit offset {} should be more or equal to {} and upper bit {} should be less than {}".format(field_name, str(field.bit_offset()), str(bit_bounds[i]), str(upper_bit), str(bit_bounds[i-1]))) # print("field {} bit offset {} should be more or equal to {} and upper bit {} should be less than {}".format(field_name, str(field.bit_offset()), str(bit_bounds[i]), str(upper_bit), str(bit_bounds[i-1])))
if field.bit_offset() >= end_bit and upper_bit < bit_bounds[i-1]: # field fully contained if field.bit_offset() >= end_bit and upper_bit < bit_bounds[i-1]: # field fully contained
...@@ -122,7 +123,8 @@ def gen_reg_tables(subsection, group_fields): ...@@ -122,7 +123,8 @@ def gen_reg_tables(subsection, group_fields):
# print("added lower partial for field {} of width {}".format(field_name, str(bit_bounds[i-1]-field.bit_offset()))) # print("added lower partial for field {} of width {}".format(field_name, str(bit_bounds[i-1]-field.bit_offset())))
gap_bit = field.bit_offset()-1 gap_bit = field.bit_offset()-1
if field.bit_offset() == (bit_bounds[i]): break if field.bit_offset() == (bit_bounds[i]):
break
if gap_bit != (bit_bounds[i] - 1): # bottom gap if gap_bit != (bit_bounds[i] - 1): # bottom gap
gap_width = max(0, gap_bit - (bit_bounds[i]-1)) gap_width = max(0, gap_bit - (bit_bounds[i]-1))
...@@ -139,9 +141,18 @@ def gen_reg_tables(subsection, group_fields): ...@@ -139,9 +141,18 @@ def gen_reg_tables(subsection, group_fields):
return subsection return subsection
def main(): def main():
# find all "*.fpga.yaml" files
if args.fpga:
fpga_libs = FPGALibrary(os.path.expandvars('$RADIOHDL_WORK')).library
# find all "*.peripheral.yaml" files
if args.peripheral:
periph_libs = PeripheralLibrary(os.path.expandvars('$RADIOHDL_WORK')).library
try: try:
for fpganame in args.system: for fpganame in args.fpga:
doc = FPGADocumentation(fpganame, fpga_libs[fpganame]) doc = FPGADocumentation(fpganame, fpga_libs[fpganame])
doc.fill() doc.fill()
doc.make_pdf() doc.make_pdf()
...@@ -156,22 +167,27 @@ def main(): ...@@ -156,22 +167,27 @@ def main():
time.sleep(0.5) time.sleep(0.5)
except IOError: except IOError:
logger.error("config file '{}' does not exist".format(filename)) logger.error("config file '{}' does not exist".format('??')) # filename))
# class SamePage(Environment): # class SamePage(Environment):
# """ A class to wrap a section in same page environment """ # """ A class to wrap a section in same page environment """
# packages = [Package('MiniPage')] # packages = [Package('MiniPage')]
# escape = False # not sure # escape = False # not sure
class FPGADocumentation(object): class FPGADocumentation(object):
def __init__(self, fpga_name, fpga_lib): def __init__(self, fpga_name, fpga_lib):
self.fpga_name = fpga_name self.fpga_name = fpga_name
self.out_dir = os.path.expandvars('$HDL_BUILD_DIR/ARGS/{}'.format(self.fpga_name)) # self.out_dir = os.path.expandvars('$HDL_ARGS_DIR/{}'.format(self.fpga_name))
self.out_dir = os.path.join(os.getenv('HDL_ARGS_DIR'), self.fpga_name, 'doc')
try: try:
os.stat(os.path.expandvars('$HDL_BUILD_DIR/ARGS/{}'.format(self.fpga_name))) os.stat(self.out_dir)
except: except:
os.mkdir(os.path.expandvars('$HDL_BUILD_DIR/ARGS/{}'.format(self.fpga_name))) logger.debug("$HDL_ARGS_DIR = %s", os.getenv('HDL_ARGS_DIR'))
logger.debug("%s does not exist in args dir, make it now", self.out_dir)
os.makedirs(self.out_dir)
self.fpga = fpga_lib['fpga'] self.fpga = fpga_lib['fpga']
self.fpga_lib = fpga_lib self.fpga_lib = fpga_lib
# self.fpga_filename = "./systems/{}.fpga.yaml".format(fpganame) # self.fpga_filename = "./systems/{}.fpga.yaml".format(fpganame)
...@@ -198,7 +214,6 @@ class FPGADocumentation(object): ...@@ -198,7 +214,6 @@ class FPGADocumentation(object):
# self.system = System(self.fpga_filename) # self.system = System(self.fpga_filename)
# self.fpga = fpga # self.fpga = fpga
def __del__(self): def __del__(self):
del self.doc del self.doc
del self.fpga del self.fpga
...@@ -275,6 +290,7 @@ class FPGADocumentation(object): ...@@ -275,6 +290,7 @@ class FPGADocumentation(object):
time.sleep(0.5) time.sleep(0.5)
except CalledProcessError: except CalledProcessError:
pass pass
sys.stdout = stdout
def peripheral_fill(self, periph, periph_name): def peripheral_fill(self, periph, periph_name):
self.doc.append(NewPage()) self.doc.append(NewPage())
...@@ -345,7 +361,7 @@ class FPGADocumentation(object): ...@@ -345,7 +361,7 @@ class FPGADocumentation(object):
row = [] row = []
for j in range(nof_cols): for j in range(nof_cols):
if i+c_max_rows*j < len(group_list): if i+c_max_rows*j < len(group_list):
field.group_name() if field.group_name() != "None" else field.name() field.group_name() if field.group_name() is not None else field.name()
row.extend([str(hex(group_list[i+c_max_rows*j].address_offset())), group_list[i+c_max_rows*j].name()]) row.extend([str(hex(group_list[i+c_max_rows*j].address_offset())), group_list[i+c_max_rows*j].name()])
else : else :
row.extend(['', '']) row.extend(['', ''])
...@@ -365,10 +381,11 @@ class FPGADocumentation(object): ...@@ -365,10 +381,11 @@ class FPGADocumentation(object):
# group_page = MiniPage() # group_page = MiniPage()
group_subsection = Subsection('{} {}'.format(str(hex(field.address_offset())), field.name() if field.group_name() == 'None' else field.group_name()), numbering=False) group_subsection = Subsection('{} {}'.format(str(hex(field.address_offset())), field.name() if field.group_name() == 'None' else field.group_name()), numbering=False)
group_fields = [field for field in slave.fields if field.address_offset() == group_address] group_fields = [field for field in slave.fields if field.address_offset() == group_address]
if len(group_fields)>10: slave_subsection.append(NewPage()) if len(group_fields) > 10:
slave_subsection.append(NewPage())
group_subsection = gen_reg_tables(group_subsection, group_fields) group_subsection = gen_reg_tables(group_subsection, group_fields)
for field in group_fields[::-1]: for field in group_fields[::-1]:
field_name = field.name() if field.group_name() == 'None' else field.name().split(field.group_name() + '_')[-1] field_name = field.name() if field.group_name() is None else field.name().split(field.group_name() + '_')[-1]
bit_string = "Bit {}".format(str(field.bit_offset())) if field.width() == 1 else "Bits {}:{}".format(str(field.bit_offset()+field.width()-1), str(field.bit_offset())) bit_string = "Bit {}".format(str(field.bit_offset())) if field.width() == 1 else "Bits {}:{}".format(str(field.bit_offset()+field.width()-1), str(field.bit_offset()))
group_subsection.append(bold("{}\t\t{} ({}):".format(bit_string, field_name, field.access_mode()))) group_subsection.append(bold("{}\t\t{} ({}):".format(bit_string, field_name, field.access_mode())))
group_subsection.append("\t\t{}".format(field.field_description())) group_subsection.append("\t\t{}".format(field.field_description()))
...@@ -385,7 +402,8 @@ class FPGADocumentation(object): ...@@ -385,7 +402,8 @@ class FPGADocumentation(object):
slave_subsections.append(slave_subsection) slave_subsections.append(slave_subsection)
periph_reg_section.append(periph_reg_table) periph_reg_section.append(periph_reg_table)
self.doc.append(periph_subsection) self.doc.append(periph_subsection)
if any([isinstance(slave, Register) for slave in periph.slaves]): self.doc.append(periph_reg_section) if any([isinstance(slave, Register) for slave in periph.slaves]):
self.doc.append(periph_reg_section)
# for i in range(len(slave_subsections)): # for i in range(len(slave_subsections)):
# self.doc.append(slave_subsections[i]) # self.doc.append(slave_subsections[i])
self.doc.append(slave_subsections) self.doc.append(slave_subsections)
...@@ -398,15 +416,16 @@ class PeripheralDocumentation(object): ...@@ -398,15 +416,16 @@ class PeripheralDocumentation(object):
def __init__(self, periph_lib_name, periph_lib): # accepts an item from periph_libs def __init__(self, periph_lib_name, periph_lib): # accepts an item from periph_libs
self.periph_lib_name = periph_lib_name self.periph_lib_name = periph_lib_name
self.periph_lib = periph_lib self.periph_lib = periph_lib
self.out_dir = os.path.expandvars('$HDL_BUILD_DIR/ARGS/{}'.format(self.periph_lib_name))
try: self.out_dir = os.path.join(os.getenv('HDL_ARGS_DIR'), self.periph_lib_name, 'doc')
os.stat(os.path.expandvars('$HDL_BUILD_DIR/ARGS'))
except:
os.mkdir(os.path.expandvars('$HDL_BUILD_DIR/ARGS'))
try: try:
os.stat(os.path.expandvars('$HDL_BUILD_DIR/ARGS/{}'.format(self.periph_lib_name))) os.stat(self.out_dir)
except: except:
os.mkdir(os.path.expandvars('$HDL_BUILD_DIR/ARGS/{}'.format(self.periph_lib_name))) # logger.debug("$HDL_ARGS_DIR = %s", os.getenv('HDL_ARGS_DIR'))
logger.debug("%s does not exist in args dir, make it now", self.out_dir)
os.makedirs(self.out_dir)
# self.peripheral_filename = "./peripherals/{}.peripheral.yaml".format(peripheralname) # self.peripheral_filename = "./peripherals/{}.peripheral.yaml".format(peripheralname)
# self.config = yaml.load(open(self.peripheral_filename, "r")) # self.config = yaml.load(open(self.peripheral_filename, "r"))
...@@ -431,7 +450,6 @@ class PeripheralDocumentation(object): ...@@ -431,7 +450,6 @@ class PeripheralDocumentation(object):
self.doc.append(Command('tableofcontents')) self.doc.append(Command('tableofcontents'))
self.doc.append(NewPage()) self.doc.append(NewPage())
def fill(self): def fill(self):
# with self.doc.create(Section("{} library.".format(self.config['hdl_library_name']))): # with self.doc.create(Section("{} library.".format(self.config['hdl_library_name']))):
# with self.doc.create(Section("{} library".format(self.periph_lib_name))): # with self.doc.create(Section("{} library".format(self.periph_lib_name))):
...@@ -559,7 +577,7 @@ class PeripheralDocumentation(object): ...@@ -559,7 +577,7 @@ class PeripheralDocumentation(object):
row = [] row = []
for j in range(nof_cols): for j in range(nof_cols):
if i+c_max_rows*j < len(group_list): if i+c_max_rows*j < len(group_list):
field.group_name() if field.group_name() != "None" else field.name() field.group_name() if field.group_name() is not None else field.name()
row.extend([str(hex(group_list[i+c_max_rows*j].address_offset())), group_list[i+c_max_rows*j].name()]) row.extend([str(hex(group_list[i+c_max_rows*j].address_offset())), group_list[i+c_max_rows*j].name()])
else : else :
row.extend(['', '']) row.extend(['', ''])
...@@ -579,7 +597,8 @@ class PeripheralDocumentation(object): ...@@ -579,7 +597,8 @@ class PeripheralDocumentation(object):
# group_page = MiniPage() # group_page = MiniPage()
group_subsection = Subsection('{} {}'.format(str(hex(field.address_offset())), field.name() if field.group_name() == 'None' else field.group_name()),numbering=False) group_subsection = Subsection('{} {}'.format(str(hex(field.address_offset())), field.name() if field.group_name() == 'None' else field.group_name()),numbering=False)
group_fields = [field for field in slave.fields if field.address_offset() == group_address] group_fields = [field for field in slave.fields if field.address_offset() == group_address]
if len(group_fields)>10: slave_subsection.append(NewPage()) if len(group_fields) > 10:
slave_subsection.append(NewPage())
group_subsection = gen_reg_tables(group_subsection, group_fields) group_subsection = gen_reg_tables(group_subsection, group_fields)
for field in group_fields[::-1]: for field in group_fields[::-1]:
field_name = field.name() if field.group_name() == 'None' else field.name().split(field.group_name() + '_')[-1] field_name = field.name() if field.group_name() == 'None' else field.name().split(field.group_name() + '_')[-1]
...@@ -599,7 +618,8 @@ class PeripheralDocumentation(object): ...@@ -599,7 +618,8 @@ class PeripheralDocumentation(object):
slave_subsections.append(slave_subsection) slave_subsections.append(slave_subsection)
periph_reg_section.append(periph_reg_table) periph_reg_section.append(periph_reg_table)
self.doc.append(periph_subsection) self.doc.append(periph_subsection)
if any([isinstance(slave, Register) for slave in periph.slaves]): self.doc.append(periph_reg_section) if any([isinstance(slave, Register) for slave in periph.slaves]):
self.doc.append(periph_reg_section)
# for i in range(len(slave_subsections)): # for i in range(len(slave_subsections)):
# self.doc.append(slave_subsections[i]) # self.doc.append(slave_subsections[i])
self.doc.append(slave_subsections) self.doc.append(slave_subsections)
...@@ -619,7 +639,6 @@ class PeripheralDocumentation(object): ...@@ -619,7 +639,6 @@ class PeripheralDocumentation(object):
sys.stdout = stdout sys.stdout = stdout
if __name__ == "__main__": if __name__ == "__main__":
# setup first log system before importing other user libraries # setup first log system before importing other user libraries
PROGRAM_NAME = __file__.split('/')[-1].split('.')[0] PROGRAM_NAME = __file__.split('/')[-1].split('.')[0]
...@@ -628,22 +647,18 @@ if __name__ == "__main__": ...@@ -628,22 +647,18 @@ if __name__ == "__main__":
# Parse command line arguments # Parse command line arguments
parser = argparse.ArgumentParser(description="System and peripheral config command line parser arguments") parser = argparse.ArgumentParser(description="System and peripheral config command line parser arguments")
parser.add_argument('-s','--system', nargs='*', default=[], help="system names separated by spaces") parser.add_argument('-f', '--fpga', nargs='*', default=[], help="fpga system names separated by spaces")
parser.add_argument('-p', '--peripheral', nargs='*', default=[], help="peripheral names separated by spaces") parser.add_argument('-p', '--peripheral', nargs='*', default=[], help="peripheral names separated by spaces")
parser.add_argument('-v', '--verbosity', default='INFO', help="verbosity level can be [ERROR | WARNING | INFO | DEBUG]") parser.add_argument('-v', '--verbosity', default='INFO', help="verbosity level can be [ERROR | WARNING | INFO | DEBUG]")
args = parser.parse_args() args = parser.parse_args()
if not args.peripheral and not args.system:
parser.print_help()
else:
if args.system:
fpga_libs = FPGALibrary(os.path.expandvars('$RADIOHDL_WORK')).library
if args.peripheral:
periph_libs = PeripheralLibrary(os.path.expandvars('$RADIOHDL_WORK')).library
unit_logger.set_stdout_log_level(args.verbosity) unit_logger.set_stdout_log_level(args.verbosity)
logger.debug("Used arguments: {}".format(args)) logger.debug("Used arguments: {}".format(args))
if not args.peripheral and not args.fpga:
parser.print_help()
sys.exit(1)
try: try:
main() main()
except: except:
...@@ -653,4 +668,5 @@ if __name__ == "__main__": ...@@ -653,4 +668,5 @@ if __name__ == "__main__":
logger.error('TRACEBACK:\n%s', traceback.format_exc()) logger.error('TRACEBACK:\n%s', traceback.format_exc())
logger.error('Aborting NOW') logger.error('Aborting NOW')
sys.exit("ERROR") sys.exit("ERROR")
sys.exit("Normal Exit") sys.exit("Normal Exit")
\ No newline at end of file
...@@ -34,5 +34,20 @@ if [[ "$_" == "${0}" ]]; then ...@@ -34,5 +34,20 @@ if [[ "$_" == "${0}" ]]; then
exit exit
fi fi
# Figure out where this script is located and set environment variables accordingly
export ARGS_GEAR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Figure out where this script is located and set environment variables accordingly # Figure out where this script is located and set environment variables accordingly
export RADIOHDL_WORK="$GIT/hdl" export RADIOHDL_WORK="$GIT/hdl"
# setup paths to build and config dir if not already defined by the user.
export HDL_BUILD_DIR=${HDL_BUILD_DIR:-${RADIOHDL_WORK}/build}
# args uses this dir for output
export HDL_ARGS_DIR=${HDL_ARGS_DIR:-${HDL_BUILD_DIR}/args}
if ! [[ -e HDL_ARGS_DIR ]]; then
echo "make args dir"
mkdir ${HDL_BUILD_DIR}/args
fi
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
# HJ jan 2017 Original # HJ jan 2017 Original
# EK feb 2017 # EK feb 2017
# PD feb 2017 # PD feb 2017
# PD nov 2019
# #
############################################################################### ###############################################################################
...@@ -30,7 +31,6 @@ import logging ...@@ -30,7 +31,6 @@ import logging
import yaml import yaml
import time import time
import collections import collections
import common as cm
from py_args_lib import * from py_args_lib import *
from peripheral_lib import * from peripheral_lib import *
import numpy as np import numpy as np
...@@ -39,11 +39,11 @@ logger = logging.getLogger('main.fpga') ...@@ -39,11 +39,11 @@ logger = logging.getLogger('main.fpga')
class FPGA(object): class FPGA(object):
""" A System consist of a set of one or more Peripherals. """ A FPGA System consist of a set of one or more Peripherals.
""" """
def __init__(self, file_path_name=None, periph_lib=None): def __init__(self, file_path_name=None, periph_lib=None):
self.file_path_name = file_path_name self.file_path_name = file_path_name
self.root_dir = os.environ['RADIOHDL'] self.root_dir = os.environ['RADIOHDL_WORK']
if periph_lib is None: if periph_lib is None:
self.peri_lib = PeripheralLibrary(self.root_dir) self.peri_lib = PeripheralLibrary(self.root_dir)
else: else:
...@@ -81,7 +81,6 @@ class FPGA(object): ...@@ -81,7 +81,6 @@ class FPGA(object):
self.valid_file_type = True self.valid_file_type = True
return system_config return system_config
def create_system(self): def create_system(self):
""" Create a system object based on the information in the system_config """ """ Create a system object based on the information in the system_config """
logger.debug("Creating system") logger.debug("Creating system")
...@@ -126,7 +125,6 @@ class FPGA(object): ...@@ -126,7 +125,6 @@ class FPGA(object):
value = parameter_set['value'] value = parameter_set['value']
logger.debug("eval of name=%s and value=%s not posible", name, value) logger.debug("eval of name=%s and value=%s not posible", name, value)
logger.debug("parameters={}".format(self.parameters)) logger.debug("parameters={}".format(self.parameters))
for peripheral_config in config['peripherals']: for peripheral_config in config['peripherals']:
...@@ -138,8 +136,8 @@ class FPGA(object): ...@@ -138,8 +136,8 @@ class FPGA(object):
peripheral_from_lib = copy.deepcopy(self.peri_lib.find_peripheral(component_name, component_lib, self.fpga_name)) peripheral_from_lib = copy.deepcopy(self.peri_lib.find_peripheral(component_name, component_lib, self.fpga_name))
if peripheral_from_lib is None: if peripheral_from_lib is None:
logger.error("Peripheral component '{}' referenced in {}.fpga.yaml not found in " logger.error("Peripheral component '{}' referenced in {}.fpga.yaml not found in peripheral library {}"
"peripheral library {}".format(component_name, self.fpga_name, '\'' + component_lib + '\'' if component_lib is not None else '')) .format(component_name, self.fpga_name, '\'' + component_lib + '\'' if component_lib is not None else ''))
sys.exit() sys.exit()
logger.debug(" Finding %s", peripheral_from_lib.name()) logger.debug(" Finding %s", peripheral_from_lib.name())
...@@ -151,7 +149,6 @@ class FPGA(object): ...@@ -151,7 +149,6 @@ class FPGA(object):
value = parameter_set['value'] value = parameter_set['value']
peripheral_from_lib.parameter(key=name, val=self._eval(value)) peripheral_from_lib.parameter(key=name, val=self._eval(value))
if 'slave_port_names' in peripheral_config: if 'slave_port_names' in peripheral_config:
logger.debug("slave_port_names={}".format(peripheral_config['slave_port_names'])) logger.debug("slave_port_names={}".format(peripheral_config['slave_port_names']))
for slave_nr, slave_port_name in enumerate(peripheral_config['slave_port_names']): for slave_nr, slave_port_name in enumerate(peripheral_config['slave_port_names']):
...@@ -208,14 +205,14 @@ class FPGA(object): ...@@ -208,14 +205,14 @@ class FPGA(object):
Configurable ranges are 4k, 8k, 16k, 32k, 64k i.e. 2^(12,13,14,15,16) Configurable ranges are 4k, 8k, 16k, 32k, 64k i.e. 2^(12,13,14,15,16)
There is a maximum of one register group per peripheral There is a maximum of one register group per peripheral
""" """
print("[fpga.py] create_address_map('{:s}')".format(self.fpga_name)) logger.debug("[fpga.py] create_address_map('{:s}')".format(self.fpga_name))
# Largest peripheral will determine spacing between peripheral base addresses # Largest peripheral will determine spacing between peripheral base addresses
largest_addr_range = 4096 # minimal allowed address-decode spacing with Xilinx interconnect largest_addr_range = 4096 # minimal allowed address-decode spacing with Xilinx interconnect
for peripheral in self.peripherals.values(): for peripheral in self.peripherals.values():
if peripheral.reg_len > largest_addr_range: if peripheral.reg_len > largest_addr_range:
largest_addr_range = peripheral.reg_len largest_addr_range = peripheral.reg_len
peripheral_spacing = cm.ceil_pow2(largest_addr_range) peripheral_spacing = ceil_pow2(largest_addr_range)
lowest_free_addr = 0 lowest_free_addr = 0
for peripheral in self.peripherals.values(): for peripheral in self.peripherals.values():
...@@ -225,7 +222,7 @@ class FPGA(object): ...@@ -225,7 +222,7 @@ class FPGA(object):
if len(p_nam) > 20: if len(p_nam) > 20:
p_nam = p_nam[0:20] p_nam = p_nam[0:20]
pad = ' ' * (21-len(peripheral.name())) pad = ' ' * (21-len(peripheral.name()))
print('** PERIPHERAL: {} {}base_addr=0x{:08x} [occupied size=0x{:x}]'.format(p_nam, pad, lowest_free_addr, peripheral.reg_len)) logger.debug('** PERIPHERAL: {:21s} base_addr=0x{:08x} [occupied size=0x{:04x}]'.format(p_nam, lowest_free_addr, peripheral.reg_len))
# assigned_reg = False # assigned_reg = False
# _nof_regs = sum([isinstance(slave, Register) for slave in peripheral.slaves]) # _nof_regs = sum([isinstance(slave, Register) for slave in peripheral.slaves])
# _minus_regs = _nof_regs - 1 if _nof_regs > 0 else 0 # _minus_regs = _nof_regs - 1 if _nof_regs > 0 else 0
...@@ -234,8 +231,8 @@ class FPGA(object): ...@@ -234,8 +231,8 @@ class FPGA(object):
assigned_reg = False assigned_reg = False
for slave in peripheral.slaves: for slave in peripheral.slaves:
if isinstance(slave, Register) and not getattr(slave, 'isIP', False): if isinstance(slave, Register) and not getattr(slave, 'isIP', False):
if assigned_reg == False: #calc for entire register slave port if assigned_reg is False: # calc for entire register slave port
reg_span = cm.ceil_pow2(max(peripheral.reg_len, 4096)) reg_span = ceil_pow2(max(peripheral.reg_len, 4096))
lowest_free_addr = int(np.ceil(lowest_free_addr/reg_span)*reg_span) lowest_free_addr = int(np.ceil(lowest_free_addr/reg_span)*reg_span)
register_base = lowest_free_addr register_base = lowest_free_addr
else : else :
...@@ -244,17 +241,21 @@ class FPGA(object): ...@@ -244,17 +241,21 @@ class FPGA(object):
ram_span = slave.base_address() - slave.rams[0].base_address() if any(slave.rams) else 0 ram_span = slave.base_address() - slave.rams[0].base_address() if any(slave.rams) else 0
slave_span = slave.address_length()*slave.number_of_slaves()+ram_span slave_span = slave.address_length()*slave.number_of_slaves()+ram_span
slave_port_name = peripheral.name() + '_' + slave.name() + (('_' + str(periph_num)) if peripheral.number_of_peripherals() > 1 else '') slave_port_name = peripheral.name() + '_' + slave.name() + (('_' + str(periph_num)) if peripheral.number_of_peripherals() > 1 else '')
self.address_map[slave_port_name] = {'base':lowest_free_addr,'span':slave_span,'type':'LITE','port_index':self.nof_lite,'peripheral':peripheral,'periph_num':periph_num,'slave':slave} self.address_map[slave_port_name] = {'base': lowest_free_addr, 'span': slave_span, 'type': 'LITE',
'port_index': self.nof_lite, 'peripheral': peripheral,
'periph_num': periph_num, 'slave': slave}
logger.info("Register for %s has span 0x%x", peripheral.name(), slave_span) logger.info("Register for %s has span 0x%x", peripheral.name(), slave_span)
lowest_free_addr = lowest_free_addr + int(slave_span) lowest_free_addr = lowest_free_addr + int(slave_span)
self.nof_lite = self.nof_lite + 1 self.nof_lite = self.nof_lite + 1
assigned_reg = True assigned_reg = True
elif isinstance(slave, Register) and getattr(slave, 'isIP', False): elif isinstance(slave, Register) and getattr(slave, 'isIP', False):
slave_span = cm.ceil_pow2(max(slave.address_length()*slave.number_of_slaves(), 4096)) #slave.address_length()*slave.number_of_slaves()# slave_span = ceil_pow2(max(slave.address_length()*slave.number_of_slaves(), 4096)) # slave.address_length()*slave.number_of_slaves()#
lowest_free_addr = int(np.ceil(lowest_free_addr/slave_span)*slave_span) lowest_free_addr = int(np.ceil(lowest_free_addr/slave_span)*slave_span)
slave_port_name = peripheral.name() + '_' + slave.name() # + '_reg_ip' slave_port_name = peripheral.name() + '_' + slave.name() # + '_reg_ip'
self.address_map[slave_port_name] = {'base':lowest_free_addr, 'span':slave_span, 'type':slave.protocol, 'port_index':eval("self.nof_{}".format(slave.protocol.lower())),'peripheral':peripheral,'periph_num':periph_num,'slave':slave} self.address_map[slave_port_name] = {'base': lowest_free_addr, 'span': slave_span, 'type': slave.protocol,
'port_index': eval("self.nof_{}".format(slave.protocol.lower())),
'peripheral': peripheral, 'periph_num': periph_num, 'slave': slave}
if slave.protocol.lower() == 'lite': if slave.protocol.lower() == 'lite':
self.nof_lite = self.nof_lite + 1 self.nof_lite = self.nof_lite + 1
else : else :
...@@ -263,24 +264,28 @@ class FPGA(object): ...@@ -263,24 +264,28 @@ class FPGA(object):
elif isinstance(slave, RAM): elif isinstance(slave, RAM):
slave_type = 'ram' slave_type = 'ram'
size_in_bytes = np.ceil(slave.width()/8)*slave.address_length()*cm.ceil_pow2(slave.number_of_slaves()) size_in_bytes = np.ceil(slave.width()/8)*slave.address_length()*ceil_pow2(slave.number_of_slaves())
slave_span = cm.ceil_pow2(max(size_in_bytes, 4096)) slave_span = ceil_pow2(max(size_in_bytes, 4096))
logger.info("Slave %s has span 0x%x", peripheral.name() + '_' + slave.name() , slave_span) logger.info("Slave %s has span 0x%x", peripheral.name() + '_' + slave.name() , slave_span)
# slave_name = slave.name() + ('_{}'.format(slave_no) if slave.number_of_slaves() >1 else '') # slave_name = slave.name() + ('_{}'.format(slave_no) if slave.number_of_slaves() >1 else '')
lowest_free_addr = int(np.ceil(lowest_free_addr/slave_span)*slave_span) lowest_free_addr = int(np.ceil(lowest_free_addr/slave_span)*slave_span)
slave_port_name = peripheral.name() + '_' + slave.name() + '_' + slave_type + (('_' + str(periph_num)) if peripheral.number_of_peripherals() > 1 else '') slave_port_name = peripheral.name() + '_' + slave.name() + '_' + slave_type + (('_' + str(periph_num)) if peripheral.number_of_peripherals() > 1 else '')
self.address_map[slave_port_name] = {'base':lowest_free_addr,'span':slave_span,'type':'FULL','port_index':self.nof_full,'peripheral':peripheral,'periph_num':periph_num,'slave':slave} self.address_map[slave_port_name] = {'base': lowest_free_addr, 'span': slave_span, 'type': 'FULL',
'port_index': self.nof_full, 'peripheral': peripheral,
'periph_num': periph_num, 'slave': slave}
self.nof_full = self.nof_full + 1 self.nof_full = self.nof_full + 1
lowest_free_addr = lowest_free_addr + slave_span lowest_free_addr = lowest_free_addr + slave_span
elif isinstance(slave, FIFO): elif isinstance(slave, FIFO):
slave_type = 'fifo' slave_type = 'fifo'
size_in_bytes = np.ceil(slave.width()/8)*slave.address_length() size_in_bytes = np.ceil(slave.width()/8)*slave.address_length()
slave_span = cm.ceil_pow2(max(size_in_bytes, 4096)) slave_span = ceil_pow2(max(size_in_bytes, 4096))
for i in range(slave.number_of_slaves()): for i in range(slave.number_of_slaves()):
lowest_free_addr = int(np.ceil(lowest_free_addr/slave_span)*slave_span) lowest_free_addr = int(np.ceil(lowest_free_addr/slave_span)*slave_span)
slave_port_name = peripheral.name() + '_' + slave.name() + '_' + slave_type+ (('_' + str(periph_num)) if peripheral.number_of_peripherals() > 1 else '') + ('_{}'.format(i) if slave.number_of_slaves() > 1 else '') slave_port_name = peripheral.name() + '_' + slave.name() + '_' + slave_type+ (('_' + str(periph_num)) if peripheral.number_of_peripherals() > 1 else '') + ('_{}'.format(i) if slave.number_of_slaves() > 1 else '')
self.address_map[slave_port_name] = {'base':lowest_free_addr,'span':slave_span,'type':'FULL','port_index':self.nof_full,'access':slave.access_mode(),'peripheral':peripheral,'periph_num':periph_num,'slave':slave} self.address_map[slave_port_name] = {'base': lowest_free_addr, 'span': slave_span, 'type': 'FULL',
'port_index': self.nof_full, 'access': slave.access_mode(),
'peripheral': peripheral, 'periph_num': periph_num, 'slave': slave}
self.nof_full = self.nof_full + 1 self.nof_full = self.nof_full + 1
lowest_free_addr = lowest_free_addr + slave_span lowest_free_addr = lowest_free_addr + slave_span
...@@ -291,20 +296,21 @@ class FPGA(object): ...@@ -291,20 +296,21 @@ class FPGA(object):
def show_overview(self): def show_overview(self):
""" print system overview """ print system overview
""" """
logger.info("----------------") logger.info("----------------------")
logger.info("SYSTEM OVERVIEW:") logger.info(" FPGA SYSTEM OVERVIEW ")
logger.info("----------------") logger.info("----------------------")
logger.info("System name '%s'", self.fpga_name) logger.info("FPGA name '%s'", self.fpga_name)
logger.info("- System parameters:") logger.info("- system parameters:")
for key, val in iter(self.parameters.items()): for key, val in iter(self.parameters.items()):
if isinstance(val, dict): if isinstance(val, dict):
for _key, _val in val.items(): for _key, _val in val.items():
logger.info(" %-25s %s", "{}.{}".format(key, _key), str(_val)) logger.info(" %-25s %s", "{}.{}".format(key, _key), str(_val))
else: else:
logger.info(" %-20s %s", key, str(val)) logger.info(" %-20s %s", key, str(val))
logger.info("- System Address Map:") logger.info("- FPGA Address Map:")
for slave_name, attributes in self.address_map.items(): for slave_name, attributes in self.address_map.items():
logger.info(" %-30s 0x%x, range %dkB at port MSTR_%s[%d]", slave_name, attributes['base'], attributes['span']/1024, attributes['type'],attributes['port_index']) logger.info(" %-30s 0x%x, range %dkB at port MSTR_%s[%d]",
slave_name, attributes['base'], attributes['span']/1024, attributes['type'], attributes['port_index'])
logger.info("- Peripherals:") logger.info("- Peripherals:")
for peripheral in sorted(self.peripherals): for peripheral in sorted(self.peripherals):
self.peripherals[peripheral].show_overview(header=False) self.peripherals[peripheral].show_overview(header=False)
...@@ -324,7 +330,7 @@ class FPGALibrary(object): ...@@ -324,7 +330,7 @@ class FPGALibrary(object):
for root, dirs, files in os.walk(self.root_dir, topdown=True): for root, dirs, files in os.walk(self.root_dir, topdown=True):
if 'tools' not in root: if 'tools' not in root:
for name in files: for name in files:
if self.file_extension in name: if name.endswith(self.file_extension):
try : try :
library_config = yaml.load(open(os.path.join(root, name), 'r')) library_config = yaml.load(open(os.path.join(root, name), 'r'))
except: except:
...@@ -332,16 +338,16 @@ class FPGALibrary(object): ...@@ -332,16 +338,16 @@ class FPGALibrary(object):
print('ERROR:\n' + sys.exc_info()[1]) print('ERROR:\n' + sys.exc_info()[1])
sys.exit() sys.exit()
if not isinstance(library_config, dict): if not isinstance(library_config, dict):
logger.warning('File {} is not readable as a dictionary, it will not be' logger.warning('File %s is not readable as a dictionary, it will not be'
' included in the FPGA library of peripherals'.format(name)) ' included in the FPGA library of peripherals', name)
continue continue
lib_name = name.replace(self.file_extension, '') lib_name = name.replace(self.file_extension, '')
logger.info("Found fpga.yaml file {}".format(lib_name)) logger.info("Found fpga.yaml file %s", lib_name)
if lib_name in self.library: if lib_name in self.library:
logger.warning("{} library already exists in FPGALibrary, being overwritten".format(lib_name)) logger.warning("%s library already exists in FPGALibrary, being overwritten", lib_name)
self.library[lib_name] = {'file_path': root, 'file_path_name': os.path.join(root, name), 'peripherals': {}} self.library[lib_name] = {'file_path': root, 'file_path_name': os.path.join(root, name), 'peripherals': {}}
toc = time.time() toc = time.time()
logger.debug("FPGALibrary os.walk took %.4f seconds" %(toc-tic)) logger.debug("FPGALibrary os.walk took %.4f seconds", toc-tic)
self.read_all_fpga_files() self.read_all_fpga_files()
def read_all_fpga_files(self, file_path_names=None): def read_all_fpga_files(self, file_path_names=None):
...@@ -358,7 +364,7 @@ class FPGALibrary(object): ...@@ -358,7 +364,7 @@ class FPGALibrary(object):
tic = time.time() tic = time.time()
fpga = FPGA(fpn, periph_lib=periph_lib) fpga = FPGA(fpn, periph_lib=periph_lib)
toc = time.time() toc = time.time()
logger.debug("fpga creation for %s took %.4f seconds" %(fpn, toc-tic)) logger.debug("fpga creation for %s took %.4f seconds", fpn, toc-tic)
fpga.show_overview() fpga.show_overview()
self.library[fpga.fpga_name].update({'fpga': fpga}) self.library[fpga.fpga_name].update({'fpga': fpga})
for lib, peripheral in fpga.peripherals.items(): for lib, peripheral in fpga.peripherals.items():
......
...@@ -33,8 +33,6 @@ from math import ceil ...@@ -33,8 +33,6 @@ from math import ceil
import logging import logging
import yaml import yaml
import collections import collections
#from constants import *
from common import c_word_w, c_nof_complex, ceil_pow2, ceil_log2, unique, path_string
from peripheral_lib import * from peripheral_lib import *
logger = logging.getLogger('main.peripheral') logger = logging.getLogger('main.peripheral')
...@@ -228,7 +226,7 @@ class Peripheral(BaseObject): ...@@ -228,7 +226,7 @@ class Peripheral(BaseObject):
sys.exit() sys.exit()
i = 0 i = 0
_slave_type = slave_info.get('slave_type', '').lower() _slave_type = slave_info.get('slave_type', '').upper()
if _slave_type in VALID_SLAVE_TYPES: if _slave_type in VALID_SLAVE_TYPES:
number_of_slaves = slave_info.get('number_of_slaves', DEFAULT_NUMBER_OF_SLAVES) number_of_slaves = slave_info.get('number_of_slaves', DEFAULT_NUMBER_OF_SLAVES)
...@@ -236,9 +234,11 @@ class Peripheral(BaseObject): ...@@ -236,9 +234,11 @@ class Peripheral(BaseObject):
if 'fields' in slave_info: if 'fields' in slave_info:
# for field_info in slave_info['fields']: # list of addresses # for field_info in slave_info['fields']: # list of addresses
defaults = {} defaults = {}
logger.debug("slave_info['fields'] = %s", str(slave_info['fields']))
for field_group in slave_info['fields']: for field_group in slave_info['fields']:
if isinstance(field_group, dict): # labelled field group if isinstance(field_group, dict): # labelled field group
(group_label, v), = field_group.items() logger.debug('field_group=%s', field_group)
(group_label, v) = field_group.items()
field_group = v field_group = v
elif len(field_group) > 1: # unlabelled field group elif len(field_group) > 1: # unlabelled field group
group_label = "reg{}".format(i) group_label = "reg{}".format(i)
...@@ -246,6 +246,8 @@ class Peripheral(BaseObject): ...@@ -246,6 +246,8 @@ class Peripheral(BaseObject):
else : else :
group_label = None # only one field in group group_label = None # only one field in group
logger.debug('group_label=%s', str(group_label))
for field_info in field_group: for field_info in field_group:
# logger.debug("field_info=%s", str(field_info)) # logger.debug("field_info=%s", str(field_info))
...@@ -259,8 +261,11 @@ class Peripheral(BaseObject): ...@@ -259,8 +261,11 @@ class Peripheral(BaseObject):
continue continue
field_name = field_info['field_name'] field_name = field_info['field_name']
logger.debug("%s, info= %s", field_name, str(field_info))
try : try :
field = Field(field_name, _slave_type) #PD print(f'field_name={field_name} _slave_type={_slave_type}')
#field = Field(field_name, _slave_type)
field = Field(field_name, field_info)
except ARGSNameError: except ARGSNameError:
logger.error("Invalid name '{}' for field in {}.peripheral.yaml".format(field_name, self.lib)) logger.error("Invalid name '{}' for field in {}.peripheral.yaml".format(field_name, self.lib))
sys.exit() sys.exit()
...@@ -300,7 +305,7 @@ class Peripheral(BaseObject): ...@@ -300,7 +305,7 @@ class Peripheral(BaseObject):
else: else:
self.add_fifo(slave_nr, slave_name, field, number_of_slaves) self.add_fifo(slave_nr, slave_name, field, number_of_slaves)
else: # slave_type is REG or REG_IP else: # slave_type is REG or REG_IP
logger.debug('adding register %s', slave_name) logger.debug('adding register %s\n', slave_name)
self.add_register(slave_nr, slave_name, fields, number_of_slaves, slave_info['slave_type'].upper() == 'REG_IP', slave_info.get('slave_protocol', None),slave_info.get('slave_span', None)) self.add_register(slave_nr, slave_name, fields, number_of_slaves, slave_info['slave_type'].upper() == 'REG_IP', slave_info.get('slave_protocol', None),slave_info.get('slave_span', None))
if 'slave_description' in slave_info.keys(): if 'slave_description' in slave_info.keys():
self.slaves[-1].update_args({'slave_description': slave_info['slave_description']}) self.slaves[-1].update_args({'slave_description': slave_info['slave_description']})
...@@ -322,20 +327,20 @@ class Peripheral(BaseObject): ...@@ -322,20 +327,20 @@ class Peripheral(BaseObject):
1) trying to parse values of known parameter into the value 1) trying to parse values of known parameter into the value
2) eval the value, known imported function are also evaluated """ 2) eval the value, known imported function are also evaluated """
_val = str(val) _val = str(val)
# first replace all knowns parameter names with its assigned value # first replace all knowns parameter names with its assigned value
for key1, val1 in self._parameters.items(): for key1, val1 in self._parameters.items():
logger.debug("key1={}, val1={}".format(key1, val1)) #logger.debug("key={}, val={}".format(key1, val1))
# if val is a dict, in vhdl it's a struct # if val is a dict, in vhdl it's a struct
if isinstance(val1, dict): if isinstance(val1, dict):
for key2, val2 in val1.items(): for key2, val2 in val1.items():
key = "{}.{}".format(key1, key2) key = "{}.{}".format(key1, key2)
#logger.debug("replace %s with %s", key, str(val2)) if key in _val:
logger.debug("replace %s with %s", key, str(val2))
_val = _val.replace(key, str(val2)) _val = _val.replace(key, str(val2))
else: else:
#logger.debug("replace %s with %s", key1, str(val1)) if key1 in _val:
logger.debug("replace %s with %s", key1, str(val1))
_val = _val.replace(key1, str(val1)) _val = _val.replace(key1, str(val1))
# logger.debug("_val={}".format(_val)) # logger.debug("_val={}".format(_val))
if val is None: if val is None:
...@@ -371,7 +376,7 @@ class Peripheral(BaseObject): ...@@ -371,7 +376,7 @@ class Peripheral(BaseObject):
""" add register to peripheral """ add register to peripheral
""" """
register = self.init_slave('Register', name, fields) register = deepcopy(self.init_slave('Register', name, fields))
register.number_of_slaves(number_of_slaves) register.number_of_slaves(number_of_slaves)
register.isIP = isIP register.isIP = isIP
register.slave_span = slave_span register.slave_span = slave_span
...@@ -388,7 +393,7 @@ class Peripheral(BaseObject): ...@@ -388,7 +393,7 @@ class Peripheral(BaseObject):
""" """
logger.debug("name is %s", name) logger.debug("name is %s", name)
ram = self.init_slave('RAM', name, settings) ram = deepcopy(self.init_slave('RAM', name, settings))
ram.number_of_slaves(number_of_slaves) ram.number_of_slaves(number_of_slaves)
self.rams['slave_{}'.format(slave_nr)] = ram self.rams['slave_{}'.format(slave_nr)] = ram
self.slaves.append(ram) self.slaves.append(ram)
...@@ -397,7 +402,7 @@ class Peripheral(BaseObject): ...@@ -397,7 +402,7 @@ class Peripheral(BaseObject):
""" add FIFO to peripheral """ add FIFO to peripheral
""" """
# fifo = FIFO(name, field) # fifo = FIFO(name, field)
fifo = self.init_slave('FIFO', name, field) fifo = deepcopy(self.init_slave('FIFO', name, field))
fifo.number_of_slaves(number_of_slaves) fifo.number_of_slaves(number_of_slaves)
self.fifos['slave_{}'.format(slave_nr)] = fifo self.fifos['slave_{}'.format(slave_nr)] = fifo
self.slaves.append(fifo) self.slaves.append(fifo)
...@@ -421,11 +426,11 @@ class Peripheral(BaseObject): ...@@ -421,11 +426,11 @@ class Peripheral(BaseObject):
# 'address_offset', 'reset_value', 'software_value', 'radix', 'field_description'] # 'address_offset', 'reset_value', 'software_value', 'radix', 'field_description']
for field in fields: # .values(): for field in fields: # .values():
logger.debug("eval field %s", field.name()) logger.debug("eval_fields= %s", field.name())
if [(field.name() == _field.name() and field.group_name() == _field.group_name())for _field in fields].count(True) > 1: if [(field.name() == _field.name() and field.group_name() == _field.group_name())for _field in fields].count(True) > 1:
logger.error("Field name '{}' group_name '{}' is not unique within slave field list in {}.peripheral.yaml".format(field.name(), field.group_name(), self.lib)) logger.error("Field name '{}' group_name '{}' is not unique within slave field list in {}.peripheral.yaml".format(field.name(), field.group_name(), self.lib))
sys.exit() sys.exit()
if field.group_name() != "None": if field.group_name() is not None:
field.name(field.group_name() + '_' + field.name()) field.name(field.group_name() + '_' + field.name())
field.width(val=self._eval(field.width(), int)) field.width(val=self._eval(field.width(), int))
field.bit_offset(val=self._eval(field.bit_offset(), int)) field.bit_offset(val=self._eval(field.bit_offset(), int))
...@@ -437,7 +442,6 @@ class Peripheral(BaseObject): ...@@ -437,7 +442,6 @@ class Peripheral(BaseObject):
field.software_value(val=self._eval(field.software_value(), int)) field.software_value(val=self._eval(field.software_value(), int))
field.radix(val=self._eval(field.radix())) field.radix(val=self._eval(field.radix()))
def eval_fifo(self): def eval_fifo(self):
""" Evaluate the paramters and the nof_inst of the peripheral """ """ Evaluate the paramters and the nof_inst of the peripheral """
...@@ -456,7 +460,6 @@ class Peripheral(BaseObject): ...@@ -456,7 +460,6 @@ class Peripheral(BaseObject):
logger.debug(" -FIFO depth eval: %s", fifo.address_length()) logger.debug(" -FIFO depth eval: %s", fifo.address_length())
logger.debug(" -FIFO width str: %s", fifo.width()) logger.debug(" -FIFO width str: %s", fifo.width())
def eval_ram(self): def eval_ram(self):
"""Evaluate the parameters and the nof_inst of the peripheral in order to define the """Evaluate the parameters and the nof_inst of the peripheral in order to define the
real address_length and width of the RAM. real address_length and width of the RAM.
...@@ -508,7 +511,6 @@ class Peripheral(BaseObject): ...@@ -508,7 +511,6 @@ class Peripheral(BaseObject):
logger.debug(" %s depth: %d", ram.name(), ram.address_length()) logger.debug(" %s depth: %d", ram.name(), ram.address_length())
logger.debug(" %s width: %d", ram.name(), ram.user_width()) logger.debug(" %s width: %d", ram.name(), ram.user_width())
def eval_register(self): def eval_register(self):
"""Evaluate the register address_length based on the evaluation of the fields, """Evaluate the register address_length based on the evaluation of the fields,
nof registers and the nof_inst.""" nof registers and the nof_inst."""
...@@ -528,6 +530,7 @@ class Peripheral(BaseObject): ...@@ -528,6 +530,7 @@ class Peripheral(BaseObject):
register = slave register = slave
else : else :
continue continue
logger.debug("evaluate %s", register.name())
# register.number_of_slaves(val=self._eval(register.number_of_slaves())) # register.number_of_slaves(val=self._eval(register.number_of_slaves()))
# Evaluate the fields and see if there are field that have to be repeated. # Evaluate the fields and see if there are field that have to be repeated.
...@@ -537,18 +540,23 @@ class Peripheral(BaseObject): ...@@ -537,18 +540,23 @@ class Peripheral(BaseObject):
for i in range(field.number_of_fields()): for i in range(field.number_of_fields()):
_field = deepcopy(field) _field = deepcopy(field)
_field.name("{}{}".format(field.name(), i)) _field.name("{}{}".format(field.name(), i))
if _field.bit_offset() != UNASSIGNED_BIT and _field.group_name() != "None" and i > 0:# if fields repeated within the same group and bit offset is set, reset to 0 from the 2nd repeated field
if i > 0:
if _field.bit_offset() != UNASSIGNED_BIT and _field.group_name() is not None: # if fields repeated within the same group and bit offset is set, reset to 0 from the 2nd repeated field
# TODO-PD check size, max = 32 bit
_field.bit_offset(field.bit_offset() + i * _field.width()) # duplicate within the field group _field.bit_offset(field.bit_offset() + i * _field.width()) # duplicate within the field group
if _field.address_offset() != UNASSIGNED_ADDRESS and i > 0: # field is manually assigned
if _field.group_name() == None or (field.bit_offset() + _field.number_of_fields()*_field.width()) >= DEFAULT_WIDTH: # not part of a field group if _field.address_offset() != UNASSIGNED_ADDRESS: # field is manually assigned
_field.address_offset(field.address_offset()+i) # duplicate across addresses # TODO-PD check, only bit size check is done if address offset is set?
if _field.group_name() is None or (field.bit_offset() + _field.number_of_fields() * _field.width()) >= DEFAULT_WIDTH: # not part of a field group
_field.address_offset(field.address_offset() + i * WIDTH_IN_BYTES) # duplicate across addresses
fields_eval.append(_field) fields_eval.append(_field)
elif field.number_of_fields() >= 32: elif field.number_of_fields() >= 32:
register.rams.append(field) register.rams.append(field)
else : else :
fields_eval.append(field) fields_eval.append(field)
self.eval_fields(fields_eval) self.eval_fields(fields_eval)
self.eval_fields(register.rams) self.eval_fields(register.rams)
register.number_of_slaves(val=self._eval(register.number_of_slaves())) register.number_of_slaves(val=self._eval(register.number_of_slaves()))
...@@ -580,24 +588,27 @@ class Peripheral(BaseObject): ...@@ -580,24 +588,27 @@ class Peripheral(BaseObject):
for field in fields_eval: for field in fields_eval:
# skip address and bit placement for fields resulting in RAM blocks, addresses already set above # skip address and bit placement for fields resulting in RAM blocks, addresses already set above
if field.number_of_fields() >= 32: if field.number_of_fields() >= 32:
logger.warning("Field %s number_of_fields >= 32, a dual port RAM will be instantiated within the Register module") logger.warning("Field %s number_of_fields >= 32, a dual port RAM will be instantiated within the Register module", field.name())
continue; continue
# new field group or single field # new field group or single field
if field.group_name() != last_group or field.group_name() == "None": if field.group_name() != last_group or field.group_name() is None:
if field.group_name() != "None": if field.group_name() is not None:
field_group = [_field for _field in fields_eval if _field.group_name() == field.group_name()] field_group = [_field for _field in fields_eval if _field.group_name() == field.group_name()]
occupied_bits = [bit for _field in field_group for bit in range(_field.bit_offset(), _field.bit_offset()+_field.width()) if _field.bit_offset() != UNASSIGNED_BIT] occupied_bits = [bit for _field in field_group for bit in range(_field.bit_offset(), _field.bit_offset()+_field.width()) if _field.bit_offset() != UNASSIGNED_BIT]
else : else :
occupied_bits = list(range(field.bit_offset(), field.bit_offset() + field.width())) if field.bit_offset() != UNASSIGNED_BIT else [] occupied_bits = list(range(field.bit_offset(), field.bit_offset() + field.width())) if field.bit_offset() != UNASSIGNED_BIT else []
while (lowest_free_addr) in occupied_addresses: while (lowest_free_addr) in occupied_addresses:
lowest_free_addr = lowest_free_addr + WIDTH_IN_BYTES lowest_free_addr = lowest_free_addr + WIDTH_IN_BYTES
if len(set(occupied_bits)) < len(occupied_bits) or any([bit > (DATA_WIDTH-1) or bit < 0 for bit in occupied_bits]): if len(set(occupied_bits)) < len(occupied_bits) or any([bit > (DATA_WIDTH-1) or bit < 0 for bit in occupied_bits]):
logger.error("{}.peripheral.yaml: Manually assigned bits for field {} is outside of data width or contains bit collisions".format(self.lib, field.name() if field.group_name() == "None" else "group " + field.group_name())) logger.error('%s.peripheral.yaml: Manually assigned bits for field %s is outside of data width or contains bit collisions',
self.lib, field.name() if field.group_name() is None else "group " + field.group_name())
logger.error("{}".format(str(occupied_bits))) logger.error("{}".format(str(occupied_bits)))
sys.exit() sys.exit()
# track beginning of group address # track beginning of group address
if field.group_name() != "None": if field.group_name() is not None:
if field.group_name() == last_group: # for all subsequent fields in field group if field.group_name() == last_group: # for all subsequent fields in field group
field.address_offset(group_address) field.address_offset(group_address)
else: # new group, do for first field in group, checks addresses within group and determines group_address or sets as unassigned else: # new group, do for first field in group, checks addresses within group and determines group_address or sets as unassigned
...@@ -607,7 +618,8 @@ class Peripheral(BaseObject): ...@@ -607,7 +618,8 @@ class Peripheral(BaseObject):
if len(group_addresses) == 1: if len(group_addresses) == 1:
group_address = group_addresses[0] group_address = group_addresses[0]
elif len(group_addresses) > 1: elif len(group_addresses) > 1:
logger.error("{}.peripheral.yaml: Manually set addresses within field group \"{}\"are conflicting, please change in configuration file".format(self.lib, field.group_name())) logger.error('%s.peripheral.yaml: Manually set addresses within field group %s %s are conflicting, please change in configuration file',
self.lib, field.group_name(), type(field.group_name()))
sys.exit() sys.exit()
else: # address not assigned else: # address not assigned
group_address = UNASSIGNED_ADDRESS group_address = UNASSIGNED_ADDRESS
...@@ -621,7 +633,8 @@ class Peripheral(BaseObject): ...@@ -621,7 +633,8 @@ class Peripheral(BaseObject):
while any([i in occupied_bits for i in range(free_bit, free_bit + field.width()+1)]): # bit is occupied while any([i in occupied_bits for i in range(free_bit, free_bit + field.width()+1)]): # bit is occupied
free_bit = free_bit + 1 # try next bit free_bit = free_bit + 1 # try next bit
if free_bit == DEFAULT_WIDTH: # 31 didn't work if free_bit == DEFAULT_WIDTH: # 31 didn't work
logger.error("{}.peripheral.yaml: No suitable gap available for automatic bit offset assignment of field{}".format(self.lib, field.name())) logger.error('%s.peripheral.yaml: No suitable gap available for automatic bit offset assignment of field%s',
self.lib, field.name())
logger.error("Check peripheral.yaml file. Field group may be overstuffed or manual bit assignment may have precluded space for other fields") logger.error("Check peripheral.yaml file. Field group may be overstuffed or manual bit assignment may have precluded space for other fields")
break break
field.bit_offset(free_bit) field.bit_offset(free_bit)
...@@ -746,7 +759,7 @@ class PeripheralLibrary(object): ...@@ -746,7 +759,7 @@ class PeripheralLibrary(object):
self.library = collections.OrderedDict() self.library = collections.OrderedDict()
self.nof_peripherals = 0 # number of peripherals self.nof_peripherals = 0 # number of peripherals
exclude = set([path_string(os.path.expandvars('$HDL_BUILD_DIR')), path_string(os.path.join(os.path.expandvars('$RADIOHDL'),'tools'))]) exclude = set([path_string(os.path.expandvars('$HDL_BUILD_DIR'))])
if root_dir is not None: if root_dir is not None:
for root, dirs, files in os.walk(self.root_dir, topdown=True): # topdown=False): for root, dirs, files in os.walk(self.root_dir, topdown=True): # topdown=False):
dirs[:] = [d for d in dirs if path_string(root+d) not in exclude and '.svn' not in d] dirs[:] = [d for d in dirs if path_string(root+d) not in exclude and '.svn' not in d]
...@@ -760,8 +773,9 @@ class PeripheralLibrary(object): ...@@ -760,8 +773,9 @@ class PeripheralLibrary(object):
print(sys.exc_info()[1]) print(sys.exc_info()[1])
sys.exit() sys.exit()
if not isinstance(library_config, dict): if not isinstance(library_config, dict):
logger.warning('File {} is not readable as a dictionary, it will not be' logger.warning('File %s is not readable as a dictionary, it will not be'
' included in the RadioHDL library of ARGS peripherals'.format(name)) ' included in the RadioHDL library of ARGS peripherals',
name)
continue continue
else: else:
try: try:
...@@ -769,18 +783,20 @@ class PeripheralLibrary(object): ...@@ -769,18 +783,20 @@ class PeripheralLibrary(object):
library_config['peripherals'] library_config['peripherals']
library_config['hdl_library_name'] library_config['hdl_library_name']
except KeyError: except KeyError:
logger.warning('File {0} will not be included in the RadioHDL library. ' logger.warning('File %s will not be included in the RadioHDL library.'
'{0} is missing schema_type and/or peripherals and/or hdl_library_name key'.format(name)) '%s is missing schema_type and/or peripherals and/or hdl_library_name key',
name, name)
continue continue
lib_name = library_config['hdl_library_name'] # name.replace(file_extension, '') lib_name = library_config['hdl_library_name'] # name.replace(file_extension, '')
if lib_name != name.split('.')[0]: if lib_name != name.split('.')[0]:
logger.error("File {} has mismatching filename \'{}\' and hdl_library_name \'{}\'".format(os.path.join(root,name), name.split('.')[0], lib_name)) logger.error("File %s has mismatching filename '%s' and hdl_library_name '%s'",
os.path.join(root, name), name.split('.')[0], lib_name)
sys.exit() sys.exit()
if self.library.get(lib_name, None) is None: # check peripheral library name is unique if self.library.get(lib_name, None) is None: # check peripheral library name is unique
self.library.update({lib_name: {'file_path': root, 'file_path_name': os.path.join(root, name), 'peripherals': collections.OrderedDict(), 'description': library_config.get('hdl_library_description', "")}}) self.library.update({lib_name: {'file_path': root, 'file_path_name': os.path.join(root, name), 'peripherals': collections.OrderedDict(), 'description': library_config.get('hdl_library_description', "")}})
else : else :
logger.error("More than one instance of args peripheral library '{}' found under {}".format(lib_name, root_dir)) logger.error("More than one instance of args peripheral library '{}' found under {}".format(lib_name, root_dir))
logger.error("\nConflicting files:\n\t{}\n\t{}".format(self.library[lib_name]['file_path_name'], os.path.join(root,name))) logger.error("\nConflicting files:\n\t%s\n\t%s", self.library[lib_name]['file_path_name'], os.path.join(root, name))
sys.exit() sys.exit()
# list of peripheral configurations that are read from the available peripheral files # list of peripheral configurations that are read from the available peripheral files
......
...@@ -7,6 +7,7 @@ cwd = os.path.dirname(os.path.realpath(__file__)) ...@@ -7,6 +7,7 @@ cwd = os.path.dirname(os.path.realpath(__file__))
sys.path.append(cwd) sys.path.append(cwd)
from constants import * from constants import *
from common_func import *
from base_object import BaseObject from base_object import BaseObject
from field import Field from field import Field
from register import Register from register import Register
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
this constants can be used in the yaml files this constants can be used in the yaml files
""" """
from common import c_word_w, c_byte_w c_byte_w = 8
c_word_w = 32
c_nof_complex = 2
VALID_SCHEMA_NAME = ['args'] VALID_SCHEMA_NAME = ['args']
VALID_SCHEMA_TYPES = ['system', 'peripheral'] VALID_SCHEMA_TYPES = ['system', 'peripheral']
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
import logging import logging
import sys import sys
from constants import * from constants import *
from common import c_word_w, c_nof_complex, ceil_pow2, ceil_log2 from common_func import ceil_pow2, ceil_log2
from base_object import BaseObject from base_object import BaseObject
from numpy import mod from numpy import mod
...@@ -72,7 +72,7 @@ class Field(BaseObject): ...@@ -72,7 +72,7 @@ class Field(BaseObject):
if settings is not None: if settings is not None:
# print(name) # print(name)
# print(settings) # logger.debug(f"settings=%s", str(settings))
for key, val in settings.items(): for key, val in settings.items():
if key in self._valid_dict: # self._valid_keys: if key in self._valid_dict: # self._valid_keys:
...@@ -103,6 +103,8 @@ class Field(BaseObject): ...@@ -103,6 +103,8 @@ class Field(BaseObject):
if val is not None: if val is not None:
self.set_kv('group_name', val) self.set_kv('group_name', val)
return return
if self.get_kv('group_name') is None:
return None
return self._as_str('group_name') return self._as_str('group_name')
def width(self, val=None): def width(self, val=None):
...@@ -239,7 +241,8 @@ class Field(BaseObject): ...@@ -239,7 +241,8 @@ class Field(BaseObject):
if check_alignment: if check_alignment:
if mod(_val, WIDTH_IN_BYTES): if mod(_val, WIDTH_IN_BYTES):
logger.error("Address offset for field {} is not word aligned".format(self.name())) logger.error("Address offset for field %s is not word aligned (%s=%s)",
self.name(), yaml_key, str(_val))
sys.exit() sys.exit()
if _min is not None: if _min is not None:
......
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
from math import ceil from math import ceil
import logging import logging
from constants import * from constants import c_word_w, c_nof_complex
from common import c_word_w, c_nof_complex, ceil_pow2, ceil_log2 from common_func import ceil_pow2, ceil_log2
from base_object import BaseObject from base_object import BaseObject
from field import Field from field import Field
from register import Register from register import Register
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
from math import ceil from math import ceil
import logging import logging
from constants import * from constants import *
from common import c_word_w, c_nof_complex, ceil_pow2, ceil_log2 from common_func import ceil_pow2, ceil_log2
from base_object import BaseObject from base_object import BaseObject
from field import Field from field import Field
......
...@@ -28,12 +28,13 @@ from math import ceil ...@@ -28,12 +28,13 @@ from math import ceil
from numpy import mod from numpy import mod
import logging import logging
from constants import * from constants import *
from common import c_word_w, c_nof_complex, ceil_pow2, ceil_log2 from common_func import ceil_pow2, ceil_log2
from base_object import BaseObject from base_object import BaseObject
from field import Field from field import Field
logger = logging.getLogger('main.periph.register') logger = logging.getLogger('main.periph.register')
class Register(BaseObject): class Register(BaseObject):
""" A register consists of Fields """ A register consists of Fields
""" """
...@@ -102,7 +103,6 @@ class Register(BaseObject): ...@@ -102,7 +103,6 @@ class Register(BaseObject):
return self.set_kv('address_length', val) return self.set_kv('address_length', val)
return self._as_int('address_length', default=1) return self._as_int('address_length', default=1)
def base_address(self, val=None): def base_address(self, val=None):
if val is not None: if val is not None:
return self.set_kv('base_address', val) return self.set_kv('base_address', val)
......
...@@ -5,6 +5,8 @@ import time ...@@ -5,6 +5,8 @@ import time
# first start main logging before including checkhardware_lib # first start main logging before including checkhardware_lib
# backup log files # backup log files
class UnitLogger(object): class UnitLogger(object):
def __init__(self, log_path, file_name=None): def __init__(self, log_path, file_name=None):
self.log_levels = {'DEBUG' : logging.DEBUG, self.log_levels = {'DEBUG' : logging.DEBUG,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment