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

Task #893 backup

parent 36b8faba
No related branches found
No related tags found
No related merge requests found
Showing
with 1148 additions and 307 deletions
---
peripheral_name: bf_unit
bf_unit:
type : peripheral
nof_inst: 1
parameters:
......@@ -15,21 +15,36 @@ ram_bf_weights:
width: g_weights_w * cm.c_nof_complex
depth: g_nof_weights * g_nof_signal_paths # 256*64 = 16384
mode : RW
descr: "Contains the weights. The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part."
descr: >
Contains the weights.
The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part.
ram_ss_ss_wide:
width: cm.ceil_log2(g_nof_subbands * g_nof_signal_paths_per_stream)
depth: g_nof_weights*g_nof_input_streams*g_nof_signal_paths_per_stream #256*16*4 # nof_weights*nof_input_streams*nof_signal_paths_per_stream = 256*16*4=16384
depth: g_nof_weights * g_nof_input_streams * g_nof_signal_paths_per_stream # 256*16*4, nof_weights*nof_input_streams*nof_signal_paths_per_stream = 256*16*4=16384
mode : RW
descr: "Contains the addresses to select from the stored subbands."
descr: >
Contains the addresses to select from the stored subbands.
ram_st_sst_bf:
width: 56
depth: g_nof_weights * cm.c_nof_complex # 256*2 = 512
mode : RO
descr: "Contains the weights. The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part."
descr: >
Contains the weights.
The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part.
reg_st_sst_bf:
- Treshold: { width: 32, mode: "RW", offset: 0x0, default: 0, descr: "When the treshold register is set to 0 the statistics will be auto-correlations. In case the treshold register is set to a non-zero value, it allows to create a sample & hold function for the a-input of the multiplier. The a-input of the multiplier is updated every treshold clockcycle. Thereby cross statistics can be created."}
Treshold:
width : 32
mode : RW
offset : 0x0
default: 0
descr : >
When the treshold register is set to 0 the statistics will be auto-correlations.
In case the treshold register is set to a non-zero value, it allows to create a sample & hold function
for the a-input of the multiplier.
The a-input of the multiplier is updated every treshold clockcycle. Thereby cross statistics can be created.
peripheral_description: "This is the beamformer unit"
\ No newline at end of file
peripheral_description: |
This is the beamformer unit
---
peripheral_name: fringe_stop
fringe_stop:
type : peripheral
nof_inst: 1
ram_fringe_stop_step:
width: 17
depth: 256
mode : RW
descr: "Contains the step size for all nof_channels channels"
descr: >
Contains the step size for all nof_channels channels.
ram_fringe_stop_offset:
width: 10
depth: 256
mode : RW
descr: "Contains the offset for all nof_channels channels"
descr: >
Contains the offset for all nof_channels channels.
peripheral_description: |
The fringe stopping peripheral is based on piecewise linear coefficients. The coefficients are indicated as offset and step.
The offset and step are used to calculate an index that is used to select a certain phase from a look-up table. The look-up
table contains a series of complex values that are based on a sinewave. The length of the look-up table is determined by the
......
#! /usr/bin/env python
"""
Make automatic documentation
"""
import sys
import os
import argparse
import subprocess
import traceback
from py_mm_lib import *
import common as cm
def main():
root_dir = os.path.expandvars('$RADIOHDL/tools/oneclick/prestudy/YAML')
peri_lib = PeripheralLibrary(root_dir, "peripheral.yaml")
data= {"system": "demo", "peripheral": "peri1", "description": "een iets lagere help tekst"}
make_documentation(data)
return "Normal ending"
def make_documentation(data):
"""
\vspace{1cm}
"""
header = \
r'''
\documentclass{article}
\title{VHDL documentation}
\date{-now-}
\begin{document}
\textbf{\huge Documentation of %(system)s \\}
\\
'''
footer= \
r'''
\end{document}
'''
content = \
r'''
\textbullet \hspace{0.5cm} \textbf{%(peripheral)s \\}
%(description)s \\
'''
with open('doc.tex','w') as f:
f.write(header%data)
f.write(content%data)
f.write(footer%data)
proc = subprocess.Popen(['pdflatex', 'doc.tex'])
proc.communicate()
os.unlink('doc.tex')
os.unlink('doc.aux')
os.unlink('doc.log')
return
if __name__ == "__main__":
# setup first log system before importing other user libraries
program_name = sys.argv[0].split('/')[-1].split('.')[0]
mylogger.set_logfile_name(name=program_name)
mylogger.set_stdout_log_level('INFO')
mylogger.set_file_log_level('DEBUG')
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--system', action='store_true', default=False, help='add system documentation')
parser.add_argument('-p', '--peripheral', action='store_true', default=False, help='add peripheral documentation')
parser.add_argument('-f', '--file', required=True, help='yaml file to generate documentation for.')
args = parser.parse_args()
response = None
try:
response = main()
except:
logger.error('Program fault, reporting and cleanup')
logger.error('Caught %s', str(sys.exc_info()[0]))
logger.error(str(sys.exc_info()[1]))
logger.error('TRACEBACK:\n%s', traceback.format_exc())
logger.error('Aborting NOW')
sys.exit("ERROR")
sys.exit(response)
---
peripheral_name: mms_diag_block_gen
mms_diag_block_gen:
type : peripheral
nof_inst: 1
parameters:
......@@ -9,20 +9,76 @@ parameters:
g_buf_addr_w : 7
reg_diag_bg:
- Enable: { width: 2, mode: "RW", offset: 0x0, default: 0, descr: "Bit 0: enable the block generator Bit 1: enable the blok generator on PPS"}
- Samples_per_packet: { width: 16, mode: "RW", offset: 0x1, default: 256, descr: "This register specifies the number samples in a packet"}
- Blocks_per_sync: { width: 16, mode: "RW", offset: 0x2, default: 781250, descr: "This register specifies the number of packets in a sync period"}
- Gapsize: { width: 16, mode: "RW", offset: 0x3, default: 80, descr: "This register specifies the gap in number of clock cycles between two consecutive packets"}
- Mem_low_address: { width: 8, mode: "RW", offset: 0x4, default: 0, descr: "This register specifies the starting address for reading from the waveform memory"}
- Mem_high_address: { width: 8, mode: "RW", offset: 0x5, default: 0, descr: "This register specifies the last address to be read when from the waveform memory"}
- BSN_init_low: { width: 32, mode: "RW", offset: 0x6, default: 0, descr: "This register specifies the lower(LSB) 32 bits [31:0] of the initialization BSN"}
- BSN_init_high: { width: 32, mode: "RW", offset: 0x7, default: 0, descr: "This register specifies the higher(MSB) 32 bits [63:32] of the initialization BSN"}
Enable:
width : 2
mode : RW
offset : 0x0
default : 0
descr : >
Bit 0: enable the block generator Bit 1: enable the blok generator on PPS
Samples_per_packet:
width : 16
mode : RW
offset : 0x1
default: 256
descr : >
This register specifies the number samples in a packet
Blocks_per_sync:
width : 16
mode : RW
offset : 0x2
default: 781250
descr : >
This register specifies the number of packets in a sync period
Gapsize:
width : 16
mode : RW
offset : 0x3
default: 80
descr : >
This register specifies the gap in number of clock cycles between two consecutive packets
Mem_low_address:
width : 8
mode : RW
offset : 0x4
default: 0
descr : >
This register specifies the starting address for reading from the waveform memory
Mem_high_address:
width : 8
mode : RW
offset : 0x5
default: 0
descr : >
This register specifies the last address to be read when from the waveform memory
BSN_init_low:
width : 32
mode : RW
offset : 0x6
default: 0
descr : >
This register specifies the lower(LSB) 32 bits [31:0] of the initialization BSN
BSN_init_high:
width : 32
mode : RW
offset : 0x7
default: 0
descr : >
This register specifies the higher(MSB) 32 bits [63:32] of the initialization BSN
ram_diag_bg:
width: g_buf_dat_w
depth: 2**g_buf_addr_w * g_nof_streams
mode : RW
descr: "Contains the Waveform data for the data-streams to be send"
descr: >
Contains the Waveform data for the data-streams to be send
peripheral_description: " Block generator "
peripheral_description: |
Block generator
---
peripheral_name: mms_diag_data_buffer
mms_diag_data_buffer:
type : peripheral
nof_inst: 1
parameters:
......@@ -9,19 +9,59 @@ parameters:
g_buf_nof_data: 1024
reg_diag_data_buffer:
- Sync_cnt: { width: 32, mode: "RO", offset: 0x0, default: 0, descr: "Sync_cnt contains the nof times the buffer (ST) has received a sync pulse since the last MM read (cleared when the last data word from the buffer is read)"}
- Word_cnt: { width: 32, mode: "RO", offset: 0x1, default: 0, descr: "Word_cnt indicates the number of word currently (ST) written in the buffer. Cleared on (ST) re-write of buffer."}
- Valid_cnt_arm_ena: { width: 32, mode: "RW", offset: 0x2, default: 0, descr: "Valid_cnt contains the number of valid cycles since the last sync pulse. Cleared on every sync pulse. Arm_enable: Write to this register to arm the system. After the system is armed the next syn pulse will trigger the acquisition of data."}
- Reg_sync_delay: { width: 32, mode: "RW", offset: 0x3, default: 0, descr: "Reg_sync_delay contains the number of valid cycles to delay/wait after an armed-syncpulse, before the data is written to the databuffer."}
- Version: { width: 32, mode: "RO", offset: 0x7, default: 0, descr: "Version contains the version number of the databuffer peripheral."}
Sync_cnt:
width : 32
mode : RO
offset : 0x0
default: 0
descr : >
Sync_cnt contains the nof times the buffer (ST) has received a sync pulse since the last MM read
(cleared when the last data word from the buffer is read)
Word_cnt:
width : 32
mode : RO
offset : 0x1
default: 0
descr : >
Word_cnt indicates the number of word currently (ST) written in the buffer. Cleared on (ST) re-write of buffer.
Valid_cnt_arm_ena:
width : 32
mode : RW
offset : 0x2
default: 0
descr : >
Valid_cnt contains the number of valid cycles since the last sync pulse. Cleared on every sync pulse.
Arm_enable: Write to this register to arm the system.
After the system is armed the next syn pulse will trigger the acquisition of data.
Reg_sync_delay:
width : 32
mode : RW
offset : 0x3
default: 0
descr : >
Reg_sync_delay contains the number of valid cycles to delay/wait after an armed-syncpulse,
before the data is written to the databuffer.
Version:
width : 32
mode : RO
offset : 0x7
default: 0
descr : >
Version contains the version number of the databuffer peripheral.
ram_diag_data_buffer:
width: g_data_w
depth: g_nof_streams * 2**cm.ceil_log2(g_buf_nof_data)
mode : RW
descr: "Contains the data that is being captured."
descr: >
Contains the data that is being captured.
peripheral_description: "Peripheral diag_data_buffer
peripheral_description: |
Peripheral diag_data_buffer
Memory map RAM_DIAG_DATA_BUFFER
......@@ -57,7 +97,7 @@ peripheral_description: "Peripheral diag_data_buffer
| data_1023[31:0] | 2047
|-----------------------------------------------------------------------|
...
streamNr = 15:
......@@ -73,11 +113,11 @@ peripheral_description: "Peripheral diag_data_buffer
|-----------------------------------------------------------------------|
Remarks:
. The data buffer stores valid data samples until it is full.
. The data buffer fills again after an external sync pulse or after the
- The data buffer stores valid data samples until it is full.
- The data buffer fills again after an external sync pulse or after the
last data word was read via the MM bus, dependend on whether the generic
g_use_in_sync is TRUE or FALSE in diag_data_buffer.vhd.
. The actual data width depends on the generic g_data_w in
- The actual data width depends on the generic g_data_w in
diag_data_buffer.vhd. The value of unused MSBits is undefined.
Memory map REG_DIAG_DATA_BUFFER (one for each stream like the RAM above)
......@@ -135,5 +175,3 @@ peripheral_description: "Peripheral diag_data_buffer
- reg_sync_delay contains the number of valid cycles to delay/wait after an armed-syncpulse,
before the data is written to the databuffer.
- version contains the version number of the databuffer peripheral.
"
\ No newline at end of file
---
peripheral_name: mms_dp_bsn_align
mms_dp_bsn_align:
type : peripheral
nof_inst: 1
parameters:
g_nof_input: 4
reg_dp_bsn_align:
- Enable: { width: 1, mode: "RW", offset: 0x0, default: 0, repeat: g_nof_input, descr: "Input enable register for input 0. If set to 0 the input is discarded from alignment. If set to 1 the corresopnding input is taken into account. "}
Enable:
width : 1
mode : RW
offset : 0x0
default: 0
repeat : g_nof_input
descr : >
Input enable register for input 0. If set to 0 the input is discarded from alignment.
If set to 1 the corresopnding input is taken into account.
peripheral_description: "This is the BSN aligner"
\ No newline at end of file
peripheral_description: |
This is the BSN aligner
---
peripheral_name: mms_dp_fifo_fill
mms_dp_fifo_fill:
type : peripheral
nof_inst: 1
parameters:
g_nof_streams: 4
reg_dp_fifo_fill:
- fifo_used_words: { width: 32, mode: "RO", offset: 0x0, default: 0, repeat: g_nof_streams, descr: "Register reflects the currently used nof words on the fifo."}
- fifo_status: { width: 2, mode: "RO", offset: 0x0, default: 0, repeat: g_nof_streams, descr: "Bit 0: fifo_read_empty Bit 1: fifo_wr_full"}
- max_fifo_used_words: { width: 32, mode: "RO", offset: 0x0, default: 0, repeat: g_nof_streams, descr: "Register contains the maximum number of words that have been in the fifo.Will be cleared after it has been read."}
fifo_used_words:
width : 32
mode : RO
offset : 0x0
default: 0
repeat : g_nof_streams
descr : >
Register reflects the currently used nof words on the fifo.
fifo_status:
width: 2
mode : RO
offset : 0x0
default: 0
repeat : g_nof_streams
descr : >
Bit 0: fifo_read_empty Bit 1: fifo_wr_full.
max_fifo_used_words:
width : 32
mode : RO
offset : 0x0
default: 0
repeat : g_nof_streams
descr : >
Register contains the maximum number of words that have been in the fifo.
Will be cleared after it has been read.
peripheral_description: "This is the MM slave version of the dp_fifo_fill component."
peripheral_description: |
This is the MM slave version of the dp_fifo_fill component.
""" init file for py_mm_lib
"""
import os
from my_logger import MyLogger
mylogger = MyLogger(os.path.join(os.getcwd(), 'log'))
logger = mylogger.logger
from peripheral import PeripheralLibrary
import os
import logging
import time
# first start main logging before including checkhardware_lib
# backup log files
class MyLogger(object):
def __init__(self, log_path, file_name=None):
self.log_levels = {'DEBUG' : logging.DEBUG,
'INFO' : logging.INFO,
'WARNING': logging.WARNING,
'ERROR' : logging.ERROR}
self.log_path = log_path
self.filename = None
self.stdout_log_level = 'WARNING'
self.file_log_level = 'INFO'
self.backup_depth = 4
self.file_logger_handler = None
self.stdout_logger_handler = None
self.logger = logging.getLogger('main')
self.logger.setLevel(logging.DEBUG)
self._setup_stdout_logging()
if file_name is not None:
self.set_logfile_name(file_name)
def set_logfile_name(self, name):
self.filename = name
self._backup_logfiles()
self._setup_file_logging()
def set_stdout_log_level(self, level):
if level in self.log_levels:
self.stdout_log_level = level
if self.stdout_logger_handler:
self.stdout_logger_handler.setLevel(self.log_levels[level])
else:
self.logger.error("'{}' is not a valid level".format(level))
def set_file_log_level(self, level):
if level in self.log_levels:
self.file_log_level = level
if self.file_logger_handler:
self.file_logger_handler.setLevel(self.log_levels[level])
else:
self.logger.error("'{}' is not a valid level".format(level))
def _backup_logfiles(self):
for nr in range(self.backup_depth-1, -1, -1):
if nr == 0:
full_filename = os.path.join(self.log_path, '{}.log'.format(self.filename))
else:
full_filename = os.path.join(self.log_path, '{}.log.{}'.format(self.filename, nr))
full_filename_new = os.path.join(self.log_path, '{}.log.{}'.format(self.filename, nr+1))
if os.path.exists(full_filename):
os.rename(full_filename, full_filename_new)
def _setup_stdout_logging(self):
# create console handler
stream_handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(name)-15s %(levelname)-7s %(message)s')
stream_handler.setFormatter(formatter)
stream_handler.setLevel(self.log_levels[self.stdout_log_level])
self.logger.addHandler(stream_handler)
self.stdout_logger_handler = self.logger.handlers[0]
def _setup_file_logging(self):
# create file handler
full_filename = os.path.join(self.log_path, '{}.log'.format(self.filename))
file_handler = logging.FileHandler(full_filename, mode='w')
formatter = logging.Formatter('%(asctime)s %(name)-15s %(levelname)-8s %(message)s')
file_handler.setFormatter(formatter)
file_handler.setLevel(self.log_levels[self.file_log_level])
self.logger.addHandler(file_handler)
self.file_logger_handler = self.logger.handlers[1]
......@@ -20,6 +20,7 @@
# Author Date
# HJ jan 2017 Original
# EK feb 2017
# PD feb 2017
#
###############################################################################
......@@ -27,22 +28,25 @@
###############################################################################
import os
import sys
import copy
import yaml
import argparse
import logging
import common as cm
field_modes = ["RO", "WO", "RW", "WP", "RR"]
logger = logging.getLogger('main.peripheral')
class Field:
class Field(object):
""" A field defines data at certain address or an array of addresses
"""
def __init__(self, name, width, mode, offset, default, descr, repeat=None):
self.name = name
self.width = width
if mode in field_modes:
self.valid_modes = ["RO", "WO", "RW", "WP", "RR"]
if mode in self.valid_modes:
self.mode = mode
else:
logger.warning("Field(), unknown mode '{}'".format(mode))
self.mode = ""
self.offset = offset
......@@ -51,7 +55,7 @@ class Field:
self.repeat = repeat
class Register:
class Register(object):
""" A register consists of Fields
"""
def __init__(self, name, fields = [], nof_inst = 1):
......@@ -60,14 +64,14 @@ class Register:
self.nof_inst = nof_inst
self.depth = self.nof_inst * cm.ceil_pow2(len(fields))
def addField(self, name, width, mode, offset, default, descr):
def add_field(self, name, width, mode, offset, default, descr):
self.fields.append(Field(name, width, mode, offset, default, descr))
self.depth = self.nof_inst * cm.ceil_pow2(len(fields))
def setDepth(self):
def set_depth(self):
self.depth = self.nof_inst * cm.ceil_pow2(len(self.fields))
def setNof_inst(self, nof_inst):
def set_nof_inst(self, nof_inst):
self.nof_inst = nof_inst
......@@ -94,7 +98,7 @@ class FIFO(Field):
self.depth = depth
class Parameter:
class Parameter(object):
""" A Parameter defines a name and value
"""
def __init__(self, name, value):
......@@ -102,7 +106,7 @@ class Parameter:
self.value = value
class Peripheral:
class Peripheral(object):
""" A Peripheral consists of 1 or more MM slaves. The slave can be a
Register, RAM or FIFO.
......@@ -132,25 +136,25 @@ class Peripheral:
self.rams = []
self.fifos = []
def setName(self, name):
def set_name(self, name):
self.name = name
def setNof_inst(self, nof_inst):
def set_nof_inst(self, nof_inst):
self.nof_inst = nof_inst
def setLabel(self, label):
def set_label(self, label):
self.label = label
def addParameter(self, name, value):
def add_parameter(self, name, value):
self.parameters.append(Parameter(name, value))
def addRegister(self, name, fields):
def add_register(self, name, fields):
self.registers.append(Register(name, fields, self.nof_inst))
def addRAM(self, name, width, mode, depth, descr):
def add_RAM(self, name, width, mode, depth, descr):
self.rams.append(RAM(name, width, mode, depth, self.nof_inst, descr))
def evalRAM(self):
def eval_RAM(self):
"""Evaluate the parameters and the nof_inst of the peripheral in order to define the real depth and width of the RAM.
For example: depth = c_nof_weights*c_nof_signal_paths
witdh = c_weights_w*c_nof_complex """
......@@ -158,16 +162,16 @@ class Peripheral:
exec("%s = %d" % (parameter, self.parameters[parameter])) # Here the parameters of the peripheral are promoted to real python variables
for ram in self.rams:
ram.name = ram.name + self.postfix
print ram.depth
logger.debug(" -RAM depth str: {}".format(ram.depth))
ram.depth = self.nof_inst * cm.ceil_pow2(eval(str(ram.depth))) # Here the variables are used to evaluate the true value for the depth parameter(taking int account the nof_inst as well)
print ram.depth
print ram.width
logger.debug(" -RAM depth eval: {}".format(ram.depth))
logger.debug(" -RAM width str: {}".format(ram.width))
ram.width = eval(str(ram.width)) # Here the variables are used to evaluate the true value for the width parameter.
print ram.width
print " " + ram.name + " " + "depth: " + str(ram.depth)
print " " + ram.name + " " + "width: " + str(ram.width)
logger.debug(" -RAM width eval: {}".format(ram.width))
logger.debug(" {} depth: {}".format(ram.name, ram.depth))
logger.debug(" {} width: {}".format(ram.name, ram.width))
def evalRegister(self):
def eval_register(self):
"""Evaluate the register depth based on the evaluation of the fields, nof registers and the nof_inst."""
for parameter in self.parameters:
exec("%s = %d" % (parameter, self.parameters[parameter])) # Here the parameters of the peripheral are promoted to real python variables
......@@ -186,231 +190,97 @@ class Peripheral:
offset = offset + 1
register.fields = fields_eval # Update the fields with evaluated fields
register.name = register.name + self.postfix # Create the name
register.setNof_inst(self.nof_inst)
register.setDepth() # Estimate the new depth after evaluation of the fields and nof_inst
print " " + register.name + " " + "depth: " + str(register.depth)
register.set_nof_inst(self.nof_inst)
register.set_depth() # Estimate the new depth after evaluation of the fields and nof_inst
logger.debug(" {} depth: {}".format(register.name, register.depth))
def evalPeripheral(self):
def eval_peripheral(self):
"""Evaluate name, label, nof_inst and the parameters to determine the true size of the RAMs and the register width and the name of the peripheral, registers and RAMS """
if self.label:
self.postfix = "_" + self.label
self.setName(self.name + self.postfix)
print " Evaluating peripheral: " + self.name
self.evalRAM()
self.evalRegister()
self.set_name(self.name + self.postfix)
logger.debug(" Evaluating peripheral '{}'".format(self.name))
self.eval_RAM()
self.eval_register()
class PeripheralLibrary:
class PeripheralLibrary(object):
""" List of all information for peripheral config files in the root dir
"""
def __init__(self, rootDir, fileName='peripheral.yaml'):
"""Store the dictionaries from all fileName files in rootDir."""
self.rootDir = rootDir
self.fileName = fileName # all peripheral files have the same fileName
self.filePaths = cm.find_all_file_paths(rootDir, fileName) # list of all directory paths of peripheral files that are available in the rootDir tree
if len(self.filePaths)==0:
sys.exit('Error : No %s file found in %s directory tree.' % (fileName, rootDir))
self.filePathNames = [] # list of all directory paths + fileName of the available peripheral files
for path in self.filePaths:
self.filePathNames.append(os.path.join(path, self.fileName))
self.peripheralConfigs = self.read_all_peripheral_files() # list of peripheral configurations that are read from the available peripheral files
self.nof_peripheralConfigs = len(self.peripheralConfigs) # number of peripheral configurations
def __init__(self, root_dir, file_name='peripheral.yaml'):
"""Store the dictionaries from all file_name files in root_dir."""
self.root_dir = root_dir
self.file_name = file_name # all peripheral files have the same file_name
self.file_paths = cm.find_all_file_paths(root_dir, file_name) # list of all directory paths of peripheral files that are available in the root_dir tree
if len(self.file_paths) == 0:
sys.exit('Error : No %s file found in %s directory tree.' % (file_name, root_dir))
self.file_path_names = [] # list of all directory paths + file_name of the available peripheral files
for path in self.file_paths:
self.file_path_names.append(os.path.join(path, self.file_name))
self.peripheral_configs = self.read_all_peripheral_files() # list of peripheral configurations that are read from the available peripheral files
self.nof_peripheral_configs = len(self.peripheral_configs) # number of peripheral configurations
self.peripherals = self.create_all_peripherals()
self.nof_peripherals = len(self.peripherals) # number of peripherals
def read_all_peripheral_files(self, filePathNames=None):
"""Read the peripheral information from all peripheral files that were found in the rootDir tree."""
if filePathNames==None: filePathNames=self.filePathNames
read_peripherals = []
for fp in self.filePathNames:
read_peripherals.append(self.read_peripheral_file(fp))
#print self.peripherals
def read_all_peripheral_files(self, file_path_names=None):
"""Read the peripheral information from all peripheral files that were found in the root_dir tree."""
if file_path_names is None:
file_path_names = self.file_path_names
read_peripherals = {}
for fp in self.file_path_names:
read_peripherals.update(self.read_peripheral_file(fp))
return read_peripherals
def read_peripheral_file(self, filePathName=None):
"""Read the peripheral information from the filePathName file."""
if filePathName==None: filePathName=self.filePathNames[0]
def read_peripheral_file(self, file_path_name=None):
"""Read the peripheral information from the file_path_name file."""
if file_path_name is None:
file_path_name = self.file_path_names[0]
with open (filePathName, "r") as myfile:
with open(file_path_name, "r") as myfile:
peripheral_yaml_config = myfile.read()
peripheral_config = yaml.load(peripheral_yaml_config)
return peripheral_config
def create_all_peripherals(self, peripheralConfigs=None):
def create_all_peripherals(self, peripheral_configs=None):
"""Create peripheral objects from all peripheral configurations."""
if peripheralConfigs==None: peripheralConfigs=self.peripheralConfigs
peripherals = []
for peripheralConfig in peripheralConfigs:
peripherals.append(self.create_peripheral(peripheralConfig))
if peripheral_configs is None:
peripheral_configs = self.peripheral_configs
peripherals = {}
for peripheral_name, peripheral_config in peripheral_configs.items():
peripherals[peripheral_name] = self.create_peripheral(peripheral_name, peripheral_config)
return peripherals
def create_peripheral(self, peripheralConfig=None):
"""Create a peripheral object based on the information in the peripheralConfig"""
if peripheralConfig==None: peripheralConfig=self.peripheralConfigs[0]
peripheral = Peripheral(peripheralConfig["peripheral_name"], peripheralConfig["nof_inst"], peripheralConfig["peripheral_description"])
def create_peripheral(self, peripheral_name, peripheral_config):
"""Create a peripheral object based on the information in the peripheral_config"""
peripheral = Peripheral(peripheral_name, peripheral_config["nof_inst"], peripheral_config["peripheral_description"])
for key in peripheralConfig.keys():
for key, val in peripheral_config.items():
if "ram_" in key:
peripheral.addRAM(key, peripheralConfig[key]["width"], peripheralConfig[key]["mode"], peripheralConfig[key]["depth"], peripheralConfig[key]["descr"])
peripheral.add_RAM(key, val["width"], val["mode"], val["depth"], val["descr"])
if "reg_" in key:
fields = []
for reg_key in peripheralConfig[key]:
for reg_key, reg_val in val.items():
# print reg_key
# print reg_key.keys()
# print reg_val
# print reg_key.values()
# print reg_key.values()[0]
repeat = None
if "repeat" in reg_key.values()[0].keys():
repeat = reg_key.values()[0]["repeat"] # print "YES!"
fields.append(Field(reg_key.keys()[0], reg_key.values()[0]["width"], reg_key.values()[0]["mode"], reg_key.values()[0]["offset"], reg_key.values()[0]["default"], reg_key.values()[0]["descr"], repeat))
peripheral.addRegister(key, fields)
if "parameters" in key:
for param_key in peripheralConfig[key]:
peripheral.parameters[param_key] = peripheralConfig[key][param_key]
return peripheral
def find_peripheral(self, name, peripheral_library=None):
if peripheral_library == None:
peripheral_library = self.peripherals
return_peripheral = None
for peripheral in peripheral_library:
if peripheral.name == name:
return_peripheral = peripheral
if "repeat" in reg_val:
repeat = reg_val['repeat'] # print "YES!"
return return_peripheral
fields.append(Field(reg_key, reg_val["width"], reg_val["mode"], reg_val["offset"], reg_val["default"], reg_val["descr"], repeat))
peripheral.add_register(key, fields)
class System:
""" A System consist of a set of one or more Peripherals.
"""
def __init__(self, filePathName=None):
self.filePathName = filePathName
self.rootDir = os.environ['RADIOHDL'] + "/tools/oneclick/prestudy/YAML"
self.peri_lib = PeripheralLibrary(self.rootDir, "peripheral.yaml")
self.peripherals = []
if filePathName==None:
print "No system configuration file specified"
self.systemConfig = None
self.system = None
else:
self.systemConfig = self.read_system_file(filePathName) # list of peripheral configurations that are read from the available peripheral files
self.system = self.create_system(self.systemConfig)
def read_system_file(self, filePathName=None):
"""Read the system information from the filePathName file."""
if filePathName==None: filePathName=self.filePathNames[0]
with open (filePathName, "r") as myfile:
system_yaml_config=myfile.read()
system_config = yaml.load(system_yaml_config)
return system_config
def create_system(self, systemConfig=None):
"""Create a system object based on the information in the systemConfig"""
print "Creating system"
print "Instantiating the peripherals from the peripheral Library"
for key in systemConfig.keys():
if key == "system_name":
self.name = systemConfig[key]
if key == "system_descr":
self.descr = systemConfig[key]
if key == "peripherals":
for peripheral in systemConfig[key]:
peripheral_from_lib = copy.deepcopy(self.peri_lib.find_peripheral(peripheral.keys()[0])) # (Deep)Copy the peripheral from the library in order to avoid creating a reference
print " Finding " + peripheral_from_lib.name
for parameter in peripheral.values()[0]:
if parameter == "nof_inst":
peripheral_from_lib.setNof_inst(peripheral.values()[0][parameter])
elif parameter == "label":
peripheral_from_lib.setLabel(peripheral.values()[0][parameter])
elif parameter in peripheral_from_lib.parameters:
print " Parameter " + parameter + " default value:" + str(peripheral_from_lib.parameters[parameter]) + " is overwritten with new value: " + str(peripheral.values()[0][parameter])
peripheral_from_lib.parameters[parameter] = peripheral.values()[0][parameter]
else:
print " !!! Parameter " + parameter + " does not exist on peripheral: " + peripheral_from_lib.name + " !!!"
peripheral_check = self.peri_lib.find_peripheral(peripheral_from_lib.name, self.peripherals)
if peripheral_check == None: # Check if peripheral already exists in the systemLibrary
self.peripherals.append(peripheral_from_lib)
elif peripheral_check.label == peripheral_from_lib.label:
print " Duplicate found: use unique labels per instance to distinguish between multiple instances of the same peripheral."
print " Cannot add a second instance of peripheral: " + peripheral_from_lib.name
else:
self.peripherals.append(peripheral_from_lib)
print "Evaluating the peripherals"
for peripheral in self.peripherals:
peripheral.evalPeripheral()
def display_system(self):
print ""
print "----------------"
print "SYSTEM OVERVIEW:"
print "----------------"
print " System name: " + self.name
for peripheral in self.peripherals:
print " " + peripheral.name + "(" + str(peripheral.nof_inst) + ")"
print " RAMs and registers:"
for ram in peripheral.rams:
print " " + ram.name + " " + str(ram.width) + " " + str(ram.depth)
for reg in peripheral.registers:
print " " + reg.name + " " + str(reg.depth)
for field in reg.fields:
print " " + field.name + " " + str(field.width) + " " + str(field.mode) + " " + str(field.offset)
print " parameters:"
for param in peripheral.parameters:
print " " + param + " " + str(peripheral.parameters[param])
print ""
class SystemParseArgs:
""" Parse command line arguments
"""
def __init__(self):
# Parse command line arguments
argparser = argparse.ArgumentParser(description='System and peripheral config command line parser arguments')
argparser.add_argument('-p','--peripheral', default=None, required=False, help='peripheral names separated by commas')
argparser.add_argument('-s','--system', default=None, required=False, help='system names separated by commas')
argparser.add_argument('-r','--run', required=False, action='store_true', default=False, help='run command')
argparser.add_argument('-v','--verbosity', required=False, type=int, default=0, help='verbosity >= 0 for more info')
args = vars(argparser.parse_args())
# Keep the argparser for external access of e.g. print_help
self.argparser = argparser
# Keep arguments in class record
self.peripheral_names = []
if args['peripheral']!=None:
self.peripheral_names = args['peripheral'].split(',')
self.system_names = []
if args['system']!=None:
self.system_names = args['system'].split(',')
self.run = args['run']
self.verbosity = args['verbosity']
if __name__ == '__main__':
# Mode
# 0 = Read YAML info from one system configuration file
# 1 = Read YAML info from all system and peripheral configuration files in the root directory
mode = 0
# Parse command line arguments
system_args = SystemParseArgs()
# Read the peripheral configuration files from the root in the current directory and the sub directories
#hdl = HdlConfig(toolRootDir=os.path.expandvars('$RADIOHDL/tools/oneclick/prestudy/YAML'), libFileName='hdllib.cfg', toolFileName=cli_args.toolFileName)
if mode==0:
rootDir = os.path.expandvars('$RADIOHDL/tools/oneclick/prestudy/YAML')
if "parameters" in key:
peripheral.parameters.update(val)
peri_lib = PeripheralLibrary(rootDir, "peripheral.yaml")
return peripheral
system = System(rootDir + "/system.yaml")
def find_peripheral(self, name, peripheral_library=None):
if peripheral_library is None:
return self.peripherals.get(name, None)
return peripheral_library.get(name, None)
system.display_system()
#!/usr/bin/env python
###############################################################################
#
# Copyright (C) 2016
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Author Date
# HJ jan 2017 Original
# EK feb 2017
# PD feb 2017
#
###############################################################################
###############################################################################
import os
import sys
import copy
import yaml
import argparse
import traceback
from py_mm_lib import *
import common as cm
class System(object):
""" A System consist of a set of one or more Peripherals.
"""
def __init__(self, file_path_name=None):
self.file_path_name = file_path_name
self.root_dir = os.path.join(os.environ['RADIOHDL'], "tools/oneclick/prestudy/YAML")
self.peri_lib = PeripheralLibrary(self.root_dir, "peripheral.yaml")
self.peripherals = {} # TODO: make dict
if file_path_name is None:
logger.debug("No system configuration file specified")
self.system_config = None
self.system = None
else:
self.system_config = self.read_system_file(file_path_name) # list of peripheral configurations that are read from the available peripheral files
self.system = self.create_system(self.system_config)
def read_system_file(self, file_path_name=None):
"""Read the system information from the file_path_name file."""
if file_path_name is None:
file_path_name = self.file_path_names[0]
with open(file_path_name, "r") as myfile:
system_yaml_config = myfile.read()
system_config = yaml.load(system_yaml_config)
#print system_config
return system_config
def create_system(self, system_config=None):
"""Create a system object based on the information in the system_config"""
logger.debug("Creating system")
logger.debug("Instantiating the peripherals from the peripheral Library")
self.system_name = system_config.keys()[0]
for peripheral_name, peripheral_config in system_config[self.system_name]['peripherals'].items():
if '.' in peripheral_name:
peripheral_key, label = peripheral_name.split('.')
logger.debug("splitted {} in key={}, label={}".format(peripheral_name, peripheral_key, label))
else:
peripheral_key = peripheral_name
label = ''
peripheral_from_lib = copy.deepcopy(self.peri_lib.find_peripheral(peripheral_key)) # (Deep)Copy the peripheral from the library in order to avoid creating a reference
if peripheral_from_lib is None:
logger.warning("peripheral_key {} not found in library".format(peripheral_key))
continue
logger.debug(" Finding {}".format(peripheral_from_lib.name))
peripheral_from_lib.set_label(label)
for parameter_key, parameter_val in peripheral_config.items():
if parameter_key == "nof_inst":
peripheral_from_lib.set_nof_inst(parameter_val)
elif parameter_key in peripheral_from_lib.parameters:
logger.debug(" Parameter {} default value: {} is overwritten with new value: {}".format(
parameter_key, peripheral_from_lib.parameters[parameter_key], parameter_val))
peripheral_from_lib.parameters[parameter_key] = parameter_val
else:
logger.warning(" !!! Parameter {} does not exist on peripheral: {} !!!".format(
parameter_key, peripheral_from_lib.name))
#peripheral_name2 = "{}.{}".format(peripheral_key, peripheral_from_lib.label)
if peripheral_name not in self.peripherals:
self.peripherals[peripheral_name] = peripheral_from_lib
else:
logger.warning(" Duplicate found: use unique labels per instance to distinguish between multiple instances of the same peripheral.")
logger.warning(" Cannot add a second instance of peripheral: {} label({})".format(peripheral_from_lib.name, peripheral_from_lib.label))
logger.debug("Start evaluating the peripherals")
for peripheral_name, peripheral_config in self.peripherals.items():
peripheral_config.eval_peripheral()
def log_system_overview(self):
logger.info("----------------")
logger.info("SYSTEM OVERVIEW:")
logger.info("----------------")
logger.info("System name '{}'".format(self.system_name))
for peripheral_name, peripheral_config in self.peripherals.items():
logger.info("{} ({}):".format(peripheral_config.name, peripheral_config.nof_inst))
logger.info(" RAMs and registers:")
for ram in peripheral_config.rams:
logger.info(" {} {} {}".format(ram.name, ram.width, ram.depth))
for reg in peripheral_config.registers:
logger.info(" {} {}".format(reg.name, reg.depth))
for field in reg.fields:
logger.info(" {} {} {} {}".format(field.name, field.width, field.mode, field.offset))
logger.info(" parameters:")
for param in peripheral_config.parameters:
logger.info(" {} {}".format(param, peripheral_config.parameters[param]))
def get_arguments():
""" Parse command line arguments
"""
# Parse command line arguments
parser = argparse.ArgumentParser(description='System and peripheral config command line parser arguments')
parser.add_argument('-p','--peripheral', nargs='*', default=None, help='peripheral names separated by commas')
parser.add_argument('-s','--system', nargs='*', default=None, help='system names separated by commas')
parser.add_argument('-r','--run', action='store_true', default=False, help='run command')
parser.add_argument('-v','--verbosity', type=int, default=0, help='verbosity >= 0 for more info')
args = parser.parse_args()
logger.debug("Used arguments: {}".format(args))
return args
if __name__ == '__main__':
# setup first log system before importing other user libraries
program_name = sys.argv[0].split('/')[-1].split('.')[0]
mylogger.set_logfile_name(name=program_name)
mylogger.set_stdout_log_level('INFO')
mylogger.set_file_log_level('DEBUG')
try:
# Mode
# 0 = Read YAML info from one system configuration file
# 1 = Read YAML info from all system and peripheral configuration files in the root directory
mode = 0
# Parse command line arguments
args = get_arguments()
# Read the peripheral configuration files from the root in the current directory and the sub directories
#hdl = HdlConfig(toolroot_dir=os.path.expandvars('$RADIOHDL/tools/oneclick/prestudy/YAML'), libfile_name='hdllib.cfg', toolfile_name=cli_args.toolfile_name)
if mode == 0:
root_dir = os.path.expandvars('$RADIOHDL/tools/oneclick/prestudy/YAML')
#peri_lib = PeripheralLibrary(root_dir, "peripheral.yaml")
system = System(os.path.join(root_dir, "system.yaml"))
system.log_system_overview()
except:
logger.error('Program fault, reporting and cleanup')
logger.error('Caught %s', str(sys.exc_info()[0]))
logger.error(str(sys.exc_info()[1]))
logger.error('TRACEBACK:\n%s', traceback.format_exc())
logger.error('Aborting NOW')
sys.exit("ERROR")
---
system_name: demo
demo:
type: system
board_select: unb1
bus_select : qsys
reg_system_info:
locked_address: 0
rom_system_info:
locked_address: 0x20
peripherals:
#- reg_system_info {locked_address : 0}
#- rom_system_info {locked_address : 0x20}
- fringe_stop: {nof_inst: 1}
- mms_diag_block_gen: {nof_inst: 1, label: "input", g_nof_streams: 12, g_buf_addr_w: 7}
- mms_diag_block_gen: {nof_inst: 1, label: "mesh", g_nof_streams: 8, g_buf_addr_w: 8}
- mms_diag_block_gen: {nof_inst: 1, label: "proc", g_nof_streams: 12, g_buf_addr_w: 7}
- bf_unit: {nof_inst: 3, g_weights_w: 3, g_nof_weights: 128, g_nof_signal_paths: 32, g_nof_subbands: 12, g_nof_signal_paths_per_stream: 2, g_nof_input_streams: 8}
- mms_diag_block_gen: {nof_inst: 1, label: "output", g_nof_streams: 2}
- mms_diag_data_buffer: {nof_inst: 1, label: "input_pre", g_nof_streams: 12, g_data_w: 16, g_buf_nof_data: 8192}
- mms_diag_data_buffer: {nof_inst: 1, label: "input_post", g_nof_streams: 12, g_data_w: 16, g_buf_nof_data: 8192}
- mms_diag_data_buffer: {nof_inst: 1, label: "mesh", g_nof_streams: 8, g_data_w: 16, g_buf_nof_data: 8}
- mms_diag_data_buffer: {nof_inst: 1, label: "proc", g_nof_streams: 12, g_data_w: 16, g_buf_nof_data: 128}
- mms_dp_bsn_align: {nof_inst: 1, label: "input", g_nof_input: 3}
- mms_dp_fifo_fill: {nof_inst: 1, label: "", g_nof_streams: 3}
fringe_stop:
nof_inst: 1
mms_diag_block_gen.input:
nof_inst : 1
g_nof_streams: 12
g_buf_addr_w : 7
mms_diag_block_gen.mesh:
nof_inst : 1
g_nof_streams: 8
g_buf_addr_w : 8
mms_diag_block_gen.proc:
nof_inst : 1
g_nof_streams: 12
g_buf_addr_w : 7
bf_unit:
nof_inst : 3
g_weights_w : 3
g_nof_weights : 128
g_nof_signal_paths : 32
g_nof_subbands : 12
g_nof_signal_paths_per_stream: 2
g_nof_input_streams: 8
mms_diag_block_gen.output:
nof_inst : 1
g_nof_streams: 2
mms_diag_data_buffer.input_pre:
nof_inst : 1
g_nof_streams : 12
g_data_w : 16
g_buf_nof_data: 8192
mms_diag_data_buffer.input_post:
nof_inst : 1
g_nof_streams : 12
g_data_w : 16
g_buf_nof_data: 8192
mms_diag_data_buffer.mesh:
nof_inst : 1
g_nof_streams : 8
g_data_w : 16
g_buf_nof_data: 8
mms_diag_data_buffer.proc:
nof_inst : 1
g_nof_streams : 12
g_data_w : 16
g_buf_nof_data: 128
mms_dp_bsn_align.input:
nof_inst : 1
g_nof_input: 3
mms_dp_fifo_fill:
nof_inst : 1
g_nof_streams: 3
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment