From 3bbce6ace56b326f2f47862cae0a45e99da29b4e Mon Sep 17 00:00:00 2001
From: Pieter Donker <donker@astron.nl>
Date: Thu, 2 Mar 2017 12:19:29 +0000
Subject: [PATCH] Task #893 backup

---
 .../prestudy/YAML/bf_unit/peripheral.yaml     |  79 ++--
 .../prestudy/YAML/fringe_stop/peripheral.yaml | 157 +++----
 .../prestudy/YAML/make_documentation.py       |  87 ++++
 .../YAML/mms_diag_block_gen/peripheral.yaml   | 110 +++--
 .../YAML/mms_diag_data_buffer/peripheral.yaml | 304 +++++++------
 .../YAML/mms_dp_bsn_align/peripheral.yaml     |  19 +-
 .../YAML/mms_dp_fifo_fill/peripheral.yaml     |  43 +-
 tools/oneclick/prestudy/YAML/peripheral.py    | 416 ------------------
 .../prestudy/YAML/py_mm_lib/__init__.py       |   9 +
 .../prestudy/YAML/py_mm_lib/my_logger.py      |  77 ++++
 .../prestudy/YAML/py_mm_lib/peripheral.py     | 286 ++++++++++++
 tools/oneclick/prestudy/YAML/system.py        | 182 ++++++++
 tools/oneclick/prestudy/YAML/system.yaml      | 102 ++++-
 13 files changed, 1148 insertions(+), 723 deletions(-)
 create mode 100755 tools/oneclick/prestudy/YAML/make_documentation.py
 delete mode 100644 tools/oneclick/prestudy/YAML/peripheral.py
 create mode 100644 tools/oneclick/prestudy/YAML/py_mm_lib/__init__.py
 create mode 100644 tools/oneclick/prestudy/YAML/py_mm_lib/my_logger.py
 create mode 100755 tools/oneclick/prestudy/YAML/py_mm_lib/peripheral.py
 create mode 100755 tools/oneclick/prestudy/YAML/system.py

diff --git a/tools/oneclick/prestudy/YAML/bf_unit/peripheral.yaml b/tools/oneclick/prestudy/YAML/bf_unit/peripheral.yaml
index ccaf2e2360..0d668dcae4 100644
--- a/tools/oneclick/prestudy/YAML/bf_unit/peripheral.yaml
+++ b/tools/oneclick/prestudy/YAML/bf_unit/peripheral.yaml
@@ -1,35 +1,50 @@
 ---
-peripheral_name: bf_unit
+bf_unit:
+  type    : peripheral
+  nof_inst: 1
+ 
+  parameters:
+    g_weights_w:                   16
+    g_nof_weights:                 256
+    g_nof_signal_paths:            64  
+    g_nof_subbands:                24  
+    g_nof_input_streams:           16
+    g_nof_signal_paths_per_stream: 4
 
-nof_inst: 1
-
-parameters:
-  g_weights_w:                    16
-  g_nof_weights:                 256
-  g_nof_signal_paths:             64  
-  g_nof_subbands:                 24  
-  g_nof_input_streams:            16
-  g_nof_signal_paths_per_stream:   4
-
-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."
+  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.
+    
+  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
+    mode : RW   
+    descr: >
+      Contains the addresses to select from the stored subbands.
   
-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
-  mode:  RW   
-  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."
-
-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."}
-
-peripheral_description: "This is the beamformer unit"
\ No newline at end of file
+  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.
+  
+  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.
+  
+  peripheral_description: |
+    This is the beamformer unit
diff --git a/tools/oneclick/prestudy/YAML/fringe_stop/peripheral.yaml b/tools/oneclick/prestudy/YAML/fringe_stop/peripheral.yaml
index ee2c04a4d3..00b208bdf4 100644
--- a/tools/oneclick/prestudy/YAML/fringe_stop/peripheral.yaml
+++ b/tools/oneclick/prestudy/YAML/fringe_stop/peripheral.yaml
@@ -1,85 +1,86 @@
 ---
-peripheral_name: fringe_stop
+fringe_stop:
+  type    : peripheral
+  nof_inst: 1
 
-nof_inst: 1
+  ram_fringe_stop_step:
+    width: 17
+    depth: 256
+    mode : RW
+    descr: >
+      Contains the step size for all nof_channels channels.
 
-ram_fringe_stop_step:
-  width: 17    
-  depth: 256         
-  mode:  RW   
-  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"
+  ram_fringe_stop_offset:
+    width: 10
+    depth: 256
+    mode : RW
+    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 
-  width of the offset RAM (offset_w). If offset_w = 10 then the length of the look-up table is 2^offset_w=1024. In that case
-  the look-up table contains 1024 complex values that make one sine-wave period. 
-  
-  The index is determined as follows: 
-  
-    index(t) = (offset + step*t) MOD 2^offset_w
+  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
+    width of the offset RAM (offset_w). If offset_w = 10 then the length of the look-up table is 2^offset_w=1024. In that case
+    the look-up table contains 1024 complex values that make one sine-wave period.
+    
+    The index is determined as follows:
+    
+      index(t) = (offset + step*t) MOD 2^offset_w
+    
+    Where t ranges from 0 to Tmax-1. Tmax is the number of samples that fit in the control interval (the sync interval).
+    The fringe stop peripheral is capable to process 1 or more channels in series (nof_channels).
+    
+    Accumulation Register
+    The accumulation register that maintains the accumulated step value is flushed by the sync pulse in the system.
+    The accumulation register in the Apertif case is 31 bit wide. For the additon of the offset and the accumulated step the
+    10 (offset_w) highest bit of the accumulated value are used --> offset(9:0) + step_accumulated(30:21).
+    
+    RAMs
+    The fringe stop interface is facilitated by two RAMs:
+    
+      -RAM_FRINGE_STOP_OFFSET
+      -RAM_FRINGE_STOP_STEP
     
-  Where t ranges from 0 to Tmax-1. Tmax is the number of samples that fit in the control interval (the sync interval). 
-  The fringe stop peripheral is capable to process 1 or more channels in series (nof_channels). 
-  
-  Accumulation Register
-  The accumulation register that maintains the accumulated step value is flushed by the sync pulse in the system. 
-  The accumulation register in the Apertif case is 31 bit wide. For the additon of the offset and the accumulated step the 
-  10 (offset_w) highest bit of the accumulated value are used --> offset(9:0) + step_accumulated(30:21). 
-  
-   RAMs
-  The fringe stop interface is facilitated by two RAMs: 
+    Both RAMs are implemented as dual-page RAMs.The page swap is triggered by the sync-pulse. The VHDL is always accessing
+    the page that is NOT accessible for the software and vice-versa. This means that the values that are written to the RAMs
+    will only be actually used in the following sync-interval:
     
-    -RAM_FRINGE_STOP_OFFSET 
-    -RAM_FRINGE_STOP_STEP
-  
-  Both RAMs are implemented as dual-page RAMs.The page swap is triggered by the sync-pulse. The VHDL is always accessing
-  the page that is NOT accessible for the software and vice-versa. This means that the values that are written to the RAMs 
-  will only be actually used in the following sync-interval: 
-  
-           _             T0                _              T1               _              T2
-   sync __| |_____________________________| |_____________________________| |________________________   
-          |     VHDL uses data T0         |     VHDL uses data T1         |     VHDL uses data T2        
-          |     Software writes data T1   |     Software writes data T2   |     Software writes data T3      
-          |                               |                               |
-      page_swap                       page_swap                       page_swap     
-  
-  The software should be sure to write the next set of data before the sync_interval expires. Keeping track of the 
-  synchronization with the sync-pulse can be done, using one of the BSN Monitors in the system. In the Apertif system 
-  the BSN Monitor at the input of the beamformer can be used. 
-  
-  The depth of both RAMs is determined by the number of unique channels that ought to be processed. 
-  
-  RAM_FRINGE_STOP_OFFSET 
-  This RAM contains the offset values for all channels, ranging from Channel 0 to Channel Max-1. The width of the RAM is 
-  defined by the offset_w. 
-  
-  RAM_ADDRESS    RAM_CONTENT  
-     0x0       Offset_Channel_0
-     0x1       Offset_Channel_1
-     0x2       Offset_Channel_2
-     0x3       Offset_Channel_3
-     ..              ..
-     ..        Offset_Channel_Max-1 
-     
-  RAM_FRINGE_STOP_STEP
-  This RAM contains the step size values for all channels, ranging from Channel 0 to Channel Max-1. The width of the RAM is
-  specified by the step_w. 
-  
-  RAM_ADDRESS    RAM_CONTENT  
-     0x0        Step_Channel_0
-     0x1        Step_Channel_1
-     0x2        Step_Channel_2
-     0x3        Step_Channel_3
-     ..              ..
-     ..         Step_Channel_Max-1 
-                             
+             _             T0                _              T1               _              T2
+     sync __| |_____________________________| |_____________________________| |________________________
+            |     VHDL uses data T0         |     VHDL uses data T1         |     VHDL uses data T2
+            |     Software writes data T1   |     Software writes data T2   |     Software writes data T3
+            |                               |                               |
+        page_swap                       page_swap                       page_swap
+    
+    The software should be sure to write the next set of data before the sync_interval expires. Keeping track of the
+    synchronization with the sync-pulse can be done, using one of the BSN Monitors in the system. In the Apertif system
+    the BSN Monitor at the input of the beamformer can be used.
+    
+    The depth of both RAMs is determined by the number of unique channels that ought to be processed.
+    
+    RAM_FRINGE_STOP_OFFSET
+    This RAM contains the offset values for all channels, ranging from Channel 0 to Channel Max-1. The width of the RAM is
+    defined by the offset_w.
+    
+    RAM_ADDRESS    RAM_CONTENT
+       0x0       Offset_Channel_0
+       0x1       Offset_Channel_1
+       0x2       Offset_Channel_2
+       0x3       Offset_Channel_3
+       ..              ..
+       ..        Offset_Channel_Max-1
+    
+    RAM_FRINGE_STOP_STEP
+    This RAM contains the step size values for all channels, ranging from Channel 0 to Channel Max-1. The width of the RAM is
+    specified by the step_w.
+    
+    RAM_ADDRESS    RAM_CONTENT
+       0x0        Step_Channel_0
+       0x1        Step_Channel_1
+       0x2        Step_Channel_2
+       0x3        Step_Channel_3
+       ..              ..
+       ..         Step_Channel_Max-1
+
 
diff --git a/tools/oneclick/prestudy/YAML/make_documentation.py b/tools/oneclick/prestudy/YAML/make_documentation.py
new file mode 100755
index 0000000000..0a5cce3150
--- /dev/null
+++ b/tools/oneclick/prestudy/YAML/make_documentation.py
@@ -0,0 +1,87 @@
+#! /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)
diff --git a/tools/oneclick/prestudy/YAML/mms_diag_block_gen/peripheral.yaml b/tools/oneclick/prestudy/YAML/mms_diag_block_gen/peripheral.yaml
index 1953cdda17..ebfc568fd7 100644
--- a/tools/oneclick/prestudy/YAML/mms_diag_block_gen/peripheral.yaml
+++ b/tools/oneclick/prestudy/YAML/mms_diag_block_gen/peripheral.yaml
@@ -1,28 +1,84 @@
 ---
-peripheral_name: mms_diag_block_gen
-
-nof_inst: 1
-
-parameters:
-  g_nof_streams:  1
-  g_buf_dat_w:   32 
-  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"}
-
-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"
-
-peripheral_description: " Block generator " 
-        
\ No newline at end of file
+mms_diag_block_gen:
+  type    : peripheral
+  nof_inst: 1
+
+  parameters:
+    g_nof_streams: 1
+    g_buf_dat_w  : 32
+    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
+
+  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
+
+  peripheral_description: |
+    Block generator
+
diff --git a/tools/oneclick/prestudy/YAML/mms_diag_data_buffer/peripheral.yaml b/tools/oneclick/prestudy/YAML/mms_diag_data_buffer/peripheral.yaml
index 2fbd03e181..cbf4c95e1b 100644
--- a/tools/oneclick/prestudy/YAML/mms_diag_data_buffer/peripheral.yaml
+++ b/tools/oneclick/prestudy/YAML/mms_diag_data_buffer/peripheral.yaml
@@ -1,139 +1,177 @@
 ---
-peripheral_name: mms_diag_data_buffer
+mms_diag_data_buffer:
+  type    : peripheral
+  nof_inst: 1
 
-nof_inst: 1
+  parameters:
+    g_nof_streams : 1
+    g_data_w      : 32
+    g_buf_nof_data: 1024
 
-parameters:
-  g_nof_streams:     1
-  g_data_w:         32 
-  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)
 
-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."}
+    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.
 
-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."
+    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.
 
-peripheral_description: "Peripheral diag_data_buffer                                                                     
-                                                                                                     
- Memory map RAM_DIAG_DATA_BUFFER                                                                 
-                                                                                                 
- If there is only one instance then the RAM name is RAM_DIAG_DATA_BUFFER, else it                
- gets an instanceName as post fix so RAM_DIAG_DATA_BUFFER_<instanceName>.                        
-                                                                                                 
- The diag_data_buffer can store multiple streams in parallel. For example                        
- 1024 data words for 16 streams the memory map becomes:      16                                    
-                                                                                                 
- streamNr = 0:                                                                                   
-                                                                                                 
-  31                                                                    0  wi                    
- |-----------------|-----------------|-----------------|-----------------|                       
- |                                 data_0[31:0]                          | 0                     
- |-----------------------------------------------------------------------|                       
- |                                 data_1[31:0]                          | 1                     
- |-----------------------------------------------------------------------|                       
- |                                 ...                                   | ..                    
- |-----------------------------------------------------------------------|                       
- |                              data_1023[31:0]                          | 1023                  
- |-----------------------------------------------------------------------|                       
-                                                                                                 
- streamNr = 1:                                                                                   
-                                                                                                 
-  31                                                                    0  wi                    
- |-----------------|-----------------|-----------------|-----------------|                       
- |                                 data_0[31:0]                          | 1024                  
- |-----------------------------------------------------------------------|                       
- |                                 data_1[31:0]                          | 1025                  
- |-----------------------------------------------------------------------|                       
- |                                 ...                                   | ..                    
- |-----------------------------------------------------------------------|                       
- |                              data_1023[31:0]                          | 2047                  
- |-----------------------------------------------------------------------|                       
-                                                                                                 
- ...                                                                                             
-                                                                                                 
- streamNr = 15:                                                                                  
-                                                                                                 
-  31                                                                    0  wi                    
- |-----------------|-----------------|-----------------|-----------------|                       
- |                                 data_0[31:0]                          | 15360                 
- |-----------------------------------------------------------------------|                       
- |                                 data_1[31:0]                          | 15361                 
- |-----------------------------------------------------------------------|                       
- |                                 ...                                   | ..                    
- |-----------------------------------------------------------------------|                       
- |                              data_1023[31:0]                          | 16383                 
- |-----------------------------------------------------------------------|                       
-                                                                                                 
- 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                         
-   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                                      
-   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)                        
-                                                                                                 
-  31                                                                     0  wi                   
- |-----------------|-----------------|-----------------|-----------------|                       
- |                             sync_cnt[31:0]                            | 0 RO (Version 0 and 1)
- |-----------------------------------------------------------------------|                       
- |                             word_cnt[31:0]                            | 1 RO (Version 0 and 1)
- |-----------------------------------------------------------------------|                       
- |                   R = valid_cnt[31:0] W = arm_enable                  | 2 RW (Version 1 only) 
- |-----------------------------------------------------------------------|                       
- |                          reg_sync_delay[31:0]                         | 3 RW (Version 1 only) 
- |-----------------------------------------------------------------------|                       
- |                                RESERVED                               | 4    (Version 1 only) 
- |-----------------------------------------------------------------------|                       
- |                                RESERVED                               | 5    (Version 1 only) 
- |-----------------------------------------------------------------------|                       
- |                                RESERVED                               | 6    (Version 1 only) 
- |-----------------------------------------------------------------------|                       
- |                             version[31:0]                             | 7 RO (Version 1 only) 
- |-----------------------------------------------------------------------|                       
-                                                                                                 
-  There are 3 modes of operation of the data_buffer.                                             
-  Version 0 supports Mode 1 and Mode 2                                                           
-  Version 1 supports Mode 1, Mode 2 and Mode 3                                                   
-                                                                                                 
-  (1) NON-SYNC MODE: g_use_in_sync = FALSE                                                       
-  In this mode the first g_nof_data valid data input words are stored in the                     
-  data buffer. A new set of data will be stored when the last word is read                       
-  from the buffer via the MM interface.                                                          
-                                                                                                 
-  (2) SYNC-MODE: g_use_in_sync = TRUE and reg_sync_delay = 0                                     
-  On every received sync pulse a number of g_nof_data valid words are written                    
-  to the databuffer. Data will be overwritten on every new sync pulse. It is                     
-  up to the user to read out the data in time in between two sync pulses                         
-                                                                                                 
-  (3) ARM-MODE: g_use_in_sync = TRUE and reg_sync_delay > 0                                      
-  First the reg_sync_delay should be written with a desired delay value. Then                    
-  the arm register must be written. After being armed the databuffer will wait                   
-  for the first sync pulse to arrive. When it has arrived it will wait for                       
-  reg_sync_delay valid cycles before g_nof_data valid words are written to the                   
-  databuffer. The data can then be read out through the MM interface. New data                   
-  will only be written if the databuffer is being armed again.                                   
-                                                                                                 
- - 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 indicates the number of word currently (ST) written in the buffer.                   
-   Cleared on (ST) re-write of buffer.                                                           
- - 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 truigger the acquisition of data.                               
- - 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
+    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.
+
+  peripheral_description: |
+    Peripheral diag_data_buffer
+    
+    Memory map RAM_DIAG_DATA_BUFFER
+    
+    If there is only one instance then the RAM name is RAM_DIAG_DATA_BUFFER, else it
+    gets an instanceName as post fix so RAM_DIAG_DATA_BUFFER_<instanceName>.
+    
+    The diag_data_buffer can store multiple streams in parallel. For example
+    1024 data words for 16 streams the memory map becomes:      16
+    
+    streamNr = 0:
+    
+     31                                                                    0  wi
+    |-----------------|-----------------|-----------------|-----------------|
+    |                                 data_0[31:0]                          | 0
+    |-----------------------------------------------------------------------|
+    |                                 data_1[31:0]                          | 1
+    |-----------------------------------------------------------------------|
+    |                                 ...                                   | ..
+    |-----------------------------------------------------------------------|
+    |                              data_1023[31:0]                          | 1023
+    |-----------------------------------------------------------------------|
+    
+    streamNr = 1:
+    
+     31                                                                    0  wi
+    |-----------------|-----------------|-----------------|-----------------|
+    |                                 data_0[31:0]                          | 1024
+    |-----------------------------------------------------------------------|
+    |                                 data_1[31:0]                          | 1025
+    |-----------------------------------------------------------------------|
+    |                                 ...                                   | ..
+    |-----------------------------------------------------------------------|
+    |                              data_1023[31:0]                          | 2047
+    |-----------------------------------------------------------------------|
+    
+    
+    
+    streamNr = 15:
+    
+     31                                                                    0  wi
+    |-----------------|-----------------|-----------------|-----------------|
+    |                                 data_0[31:0]                          | 15360
+    |-----------------------------------------------------------------------|
+    |                                 data_1[31:0]                          | 15361
+    |-----------------------------------------------------------------------|
+    |                                 ...                                   | ..
+    |-----------------------------------------------------------------------|
+    |                              data_1023[31:0]                          | 16383
+    |-----------------------------------------------------------------------|
+    
+    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
+      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
+      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)
+    
+     31                                                                     0  wi
+    |-----------------|-----------------|-----------------|-----------------|
+    |                             sync_cnt[31:0]                            | 0 RO (Version 0 and 1)
+    |-----------------------------------------------------------------------|
+    |                             word_cnt[31:0]                            | 1 RO (Version 0 and 1)
+    |-----------------------------------------------------------------------|
+    |                   R = valid_cnt[31:0] W = arm_enable                  | 2 RW (Version 1 only)
+    |-----------------------------------------------------------------------|
+    |                          reg_sync_delay[31:0]                         | 3 RW (Version 1 only)
+    |-----------------------------------------------------------------------|
+    |                                RESERVED                               | 4    (Version 1 only)
+    |-----------------------------------------------------------------------|
+    |                                RESERVED                               | 5    (Version 1 only)
+    |-----------------------------------------------------------------------|
+    |                                RESERVED                               | 6    (Version 1 only)
+    |-----------------------------------------------------------------------|
+    |                             version[31:0]                             | 7 RO (Version 1 only)
+    |-----------------------------------------------------------------------|
+    
+    There are 3 modes of operation of the data_buffer.
+    Version 0 supports Mode 1 and Mode 2
+    Version 1 supports Mode 1, Mode 2 and Mode 3
+    
+    (1) NON-SYNC MODE: g_use_in_sync = FALSE
+    In this mode the first g_nof_data valid data input words are stored in the
+    data buffer. A new set of data will be stored when the last word is read
+    from the buffer via the MM interface.
+    
+    (2) SYNC-MODE: g_use_in_sync = TRUE and reg_sync_delay = 0
+    On every received sync pulse a number of g_nof_data valid words are written
+    to the databuffer. Data will be overwritten on every new sync pulse. It is
+    up to the user to read out the data in time in between two sync pulses
+    
+    (3) ARM-MODE: g_use_in_sync = TRUE and reg_sync_delay > 0
+    First the reg_sync_delay should be written with a desired delay value. Then
+    the arm register must be written. After being armed the databuffer will wait
+    for the first sync pulse to arrive. When it has arrived it will wait for
+    reg_sync_delay valid cycles before g_nof_data valid words are written to the
+    databuffer. The data can then be read out through the MM interface. New data
+    will only be written if the databuffer is being armed again.
+    
+    - 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 indicates the number of word currently (ST) written in the buffer.
+      Cleared on (ST) re-write of buffer.
+    - 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 truigger the acquisition of data.
+    - 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.
diff --git a/tools/oneclick/prestudy/YAML/mms_dp_bsn_align/peripheral.yaml b/tools/oneclick/prestudy/YAML/mms_dp_bsn_align/peripheral.yaml
index 5880fd0730..9d652c1363 100644
--- a/tools/oneclick/prestudy/YAML/mms_dp_bsn_align/peripheral.yaml
+++ b/tools/oneclick/prestudy/YAML/mms_dp_bsn_align/peripheral.yaml
@@ -1,12 +1,21 @@
 ---
-  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. "}
- 
-  peripheral_description: "This is the BSN aligner"
\ No newline at end of file
+    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
diff --git a/tools/oneclick/prestudy/YAML/mms_dp_fifo_fill/peripheral.yaml b/tools/oneclick/prestudy/YAML/mms_dp_fifo_fill/peripheral.yaml
index bed785c93e..d8d82a127c 100644
--- a/tools/oneclick/prestudy/YAML/mms_dp_fifo_fill/peripheral.yaml
+++ b/tools/oneclick/prestudy/YAML/mms_dp_fifo_fill/peripheral.yaml
@@ -1,14 +1,39 @@
 ---
-peripheral_name: mms_dp_fifo_fill
+mms_dp_fifo_fill:
+  type    : peripheral
+  nof_inst: 1
 
-nof_inst: 1
+  parameters:
+    g_nof_streams: 4
 
-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.
 
-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_status:
+      width:  2
+      mode   : RO
+      offset : 0x0
+      default: 0
+      repeat : g_nof_streams
+      descr  : >
+        Bit 0: fifo_read_empty Bit 1: fifo_wr_full.
 
-peripheral_description: "This is the MM slave version of the dp_fifo_fill component."
+    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.
diff --git a/tools/oneclick/prestudy/YAML/peripheral.py b/tools/oneclick/prestudy/YAML/peripheral.py
deleted file mode 100644
index f6506e9db2..0000000000
--- a/tools/oneclick/prestudy/YAML/peripheral.py
+++ /dev/null
@@ -1,416 +0,0 @@
-###############################################################################
-#
-# 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  
-#
-###############################################################################
-
-
-###############################################################################
-
-import os
-import copy
-import yaml
-import argparse
-import common as cm
-
-field_modes = ["RO", "WO", "RW", "WP", "RR"]
-
-class Field:
-    """ 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.mode = mode
-        else: 
-            self.mode = ""
-            
-        self.offset  = offset
-        self.default = default
-        self.descr   = descr  
-        self.repeat  = repeat
-
-
-class Register:
-    """ A register consists of Fields
-    """
-    def __init__(self, name, fields = [], nof_inst = 1):
-        self.name     = name        
-        self.fields   = fields
-        self.nof_inst = nof_inst
-        self.depth    = self.nof_inst * cm.ceil_pow2(len(fields))
-        
-    def addField(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):
-        self.depth = self.nof_inst * cm.ceil_pow2(len(self.fields))
-    
-    def setNof_inst(self, nof_inst):
-        self.nof_inst = nof_inst
-
-
-class RAM(Field):
-    """ A RAM is a Field that is repeated depth times
-    """
-    def __init__(self, name, width, mode, depth, nof_inst, descr):
-        Field.__init__(self, name, width, mode, 0x0, 0, descr)
-        self.depth    = depth
-        self.nof_inst = nof_inst
-
-
-class FIFO(Field):
-    """ A FIFO is a specific set of Fields
-    """
-    def __init__(self, name, width, mode, default, depth): 
-        Field.__init__(self, name, width, mode, 0, default)
-        fifo_fields = []
-        fifo_fields.append(Field(fifo_status,        4, "RO", 0x0, 0, "fifo status register. Bit 0: Fifo Full Bit 1: Fifo Empty"))
-        fifo_fields.append(Field(fifo_used_w,       32, "RO", 0x4, 0, "fifo used words register."))
-        fifo_fields.append(Field(fifo_read_reg,  width, "RO", 0x8, 0, "fifo read register."))
-        fifo_fields.append(Field(fifo_write_reg, width, "WO", 0xC, 0, "fifo write register."))        
-        self.Register = Register("FIFO Register", fifo_fields)   
-        self.depth = depth
-
-
-class Parameter:
-    """ A Parameter defines a name and value
-    """
-    def __init__(self, name, value):
-        self.name  = name        
-        self.value = value
-      
-
-class Peripheral:
-    """ A Peripheral consists of 1 or more MM slaves. The slave can be a
-    Register, RAM or FIFO.
-        
-    The Peripheral has parameters to configure the MM slaves.
-        
-    A Peripheral has two levels of supporting multiple instances:
-    1) At system level a peripheral can be used more than once. The individual
-       peripherals are then distinghuised by defining a unique label per
-       instance.
-    2) At peripheral level internally in the peripheral if the peripheral
-       support an array of instances. The size of the array is then specified
-       via nof_inst. Dependent on the specific definition of the peripheral,
-       the nof_inst then either replicates some fields in a register or it
-       replicates some or all MM slaves nof_inst times.
-           
-    The Peripheral evaluates the nof_inst and parameters to set the
-    dimensions of the MM slaves.
-    """
-    def __init__(self, name, nof_inst, descr, label = ""):
-        self.name        = name
-        self.postfix     = ""
-        self.label       = label  # the label is used to make it unique in case multiple instances are required in a system
-        self.nof_inst    = nof_inst
-        self.descr       = descr 
-        self.parameters  = {}
-        self.registers   = []
-        self.rams        = []
-        self.fifos       = []   
-        
-    def setName(self, name):              
-        self.name = name  
-
-    def setNof_inst(self, nof_inst):
-        self.nof_inst = nof_inst
-    
-    def setLabel(self, label):              
-        self.label = label  
-
-    def addParameter(self, name, value):              
-        self.parameters.append(Parameter(name, value))  
-
-    def addRegister(self, name, fields):              
-        self.registers.append(Register(name, fields, self.nof_inst))      
-
-    def addRAM(self, name, width, mode, depth, descr):              
-        self.rams.append(RAM(name, width, mode, depth, self.nof_inst, descr))      
-
-    def evalRAM(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 """ 
-        for parameter in self.parameters:
-            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
-            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
-            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)
-
-    def evalRegister(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 
-        for register in self.registers:
-            # Evaluate the fields and see if there are field that have to be repeated. 
-            for field in register.fields:
-                field.repeat = eval(str(field.repeat))
-            fields_eval = []
-            offset = 0
-            for field in register.fields:
-                if field.repeat == None:           # If no repeat is required, just copy. 
-                    fields_eval.append(field)
-                else:
-                    for f in range(field.repeat):  # Repeat the field as many times as required. Keep track of the offset.  
-                        fields_eval.append(Field(field.name + str(f), field.width, field.mode, offset, field.default, field.descr))  
-                        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)
-    
-    def evalPeripheral(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()
-        
-        
-class PeripheralLibrary:
-    """ 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
-        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))
-        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]
-
-        with open (filePathName, "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):
-        """Create peripheral objects from all peripheral configurations."""
-        if peripheralConfigs==None: peripheralConfigs=self.peripheralConfigs
-        peripherals = []
-        for peripheralConfig in peripheralConfigs:
-            peripherals.append(self.create_peripheral(peripheralConfig))
-        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"])
-
-        for key in peripheralConfig.keys():
-            if "ram_" in key: 
-                peripheral.addRAM(key, peripheralConfig[key]["width"], peripheralConfig[key]["mode"], peripheralConfig[key]["depth"], peripheralConfig[key]["descr"])
-            if "reg_" in key:       
-                fields = []
-                for reg_key in peripheralConfig[key]:   
-#                    print reg_key
-#                    print reg_key.keys()
-#                    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
-         
-        return return_peripheral       
-
-
-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')
-
-        peri_lib = PeripheralLibrary(rootDir, "peripheral.yaml")
-
-        system = System(rootDir + "/system.yaml") 
-
-        system.display_system()
diff --git a/tools/oneclick/prestudy/YAML/py_mm_lib/__init__.py b/tools/oneclick/prestudy/YAML/py_mm_lib/__init__.py
new file mode 100644
index 0000000000..466784ccfb
--- /dev/null
+++ b/tools/oneclick/prestudy/YAML/py_mm_lib/__init__.py
@@ -0,0 +1,9 @@
+""" 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
diff --git a/tools/oneclick/prestudy/YAML/py_mm_lib/my_logger.py b/tools/oneclick/prestudy/YAML/py_mm_lib/my_logger.py
new file mode 100644
index 0000000000..715d8ca5fa
--- /dev/null
+++ b/tools/oneclick/prestudy/YAML/py_mm_lib/my_logger.py
@@ -0,0 +1,77 @@
+
+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]
diff --git a/tools/oneclick/prestudy/YAML/py_mm_lib/peripheral.py b/tools/oneclick/prestudy/YAML/py_mm_lib/peripheral.py
new file mode 100755
index 0000000000..fb686cbc68
--- /dev/null
+++ b/tools/oneclick/prestudy/YAML/py_mm_lib/peripheral.py
@@ -0,0 +1,286 @@
+###############################################################################
+#
+# 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 logging
+import common as cm
+
+logger = logging.getLogger('main.peripheral')
+
+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
+        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
+        self.default = default
+        self.descr   = descr  
+        self.repeat  = repeat
+
+
+class Register(object):
+    """ A register consists of Fields
+    """
+    def __init__(self, name, fields = [], nof_inst = 1):
+        self.name     = name        
+        self.fields   = fields
+        self.nof_inst = nof_inst
+        self.depth    = self.nof_inst * cm.ceil_pow2(len(fields))
+        
+    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 set_depth(self):
+        self.depth = self.nof_inst * cm.ceil_pow2(len(self.fields))
+    
+    def set_nof_inst(self, nof_inst):
+        self.nof_inst = nof_inst
+
+
+class RAM(Field):
+    """ A RAM is a Field that is repeated depth times
+    """
+    def __init__(self, name, width, mode, depth, nof_inst, descr):
+        Field.__init__(self, name, width, mode, 0x0, 0, descr)
+        self.depth    = depth
+        self.nof_inst = nof_inst
+
+
+class FIFO(Field):
+    """ A FIFO is a specific set of Fields
+    """
+    def __init__(self, name, width, mode, default, depth): 
+        Field.__init__(self, name, width, mode, 0, default)
+        fifo_fields = []
+        fifo_fields.append(Field(fifo_status,        4, "RO", 0x0, 0, "fifo status register. Bit 0: Fifo Full Bit 1: Fifo Empty"))
+        fifo_fields.append(Field(fifo_used_w,       32, "RO", 0x4, 0, "fifo used words register."))
+        fifo_fields.append(Field(fifo_read_reg,  width, "RO", 0x8, 0, "fifo read register."))
+        fifo_fields.append(Field(fifo_write_reg, width, "WO", 0xC, 0, "fifo write register."))        
+        self.Register = Register("FIFO Register", fifo_fields)   
+        self.depth = depth
+
+
+class Parameter(object):
+    """ A Parameter defines a name and value
+    """
+    def __init__(self, name, value):
+        self.name  = name        
+        self.value = value
+      
+
+class Peripheral(object):
+    """ A Peripheral consists of 1 or more MM slaves. The slave can be a
+    Register, RAM or FIFO.
+        
+    The Peripheral has parameters to configure the MM slaves.
+        
+    A Peripheral has two levels of supporting multiple instances:
+    1) At system level a peripheral can be used more than once. The individual
+       peripherals are then distinghuised by defining a unique label per
+       instance.
+    2) At peripheral level internally in the peripheral if the peripheral
+       support an array of instances. The size of the array is then specified
+       via nof_inst. Dependent on the specific definition of the peripheral,
+       the nof_inst then either replicates some fields in a register or it
+       replicates some or all MM slaves nof_inst times.
+           
+    The Peripheral evaluates the nof_inst and parameters to set the
+    dimensions of the MM slaves.
+    """
+    def __init__(self, name, nof_inst, descr, label = ""):
+        self.name        = name
+        self.postfix     = ""
+        self.label       = label  # the label is used to make it unique in case multiple instances are required in a system
+        self.nof_inst    = nof_inst
+        self.descr       = descr 
+        self.parameters  = {}
+        self.registers   = []
+        self.rams        = []
+        self.fifos       = []   
+        
+    def set_name(self, name):              
+        self.name = name  
+
+    def set_nof_inst(self, nof_inst):
+        self.nof_inst = nof_inst
+    
+    def set_label(self, label):              
+        self.label = label  
+
+    def add_parameter(self, name, value):              
+        self.parameters.append(Parameter(name, value))  
+
+    def add_register(self, name, fields):              
+        self.registers.append(Register(name, fields, self.nof_inst))      
+
+    def add_RAM(self, name, width, mode, depth, descr):              
+        self.rams.append(RAM(name, width, mode, depth, self.nof_inst, descr))      
+
+    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 """ 
+        for parameter in self.parameters:
+            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
+            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)
+            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.
+            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 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 
+        for register in self.registers:
+            # Evaluate the fields and see if there are field that have to be repeated. 
+            for field in register.fields:
+                field.repeat = eval(str(field.repeat))
+            fields_eval = []
+            offset = 0
+            for field in register.fields:
+                if field.repeat == None:           # If no repeat is required, just copy. 
+                    fields_eval.append(field)
+                else:
+                    for f in range(field.repeat):  # Repeat the field as many times as required. Keep track of the offset.  
+                        fields_eval.append(Field(field.name + str(f), field.width, field.mode, offset, field.default, field.descr))  
+                        offset = offset + 1
+            register.fields = fields_eval                  # Update the fields with evaluated fields
+            register.name = register.name + self.postfix   # Create the name
+            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 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.set_name(self.name + self.postfix)
+        logger.debug(" Evaluating peripheral '{}'".format(self.name))
+        self.eval_RAM()
+        self.eval_register()
+ 
+ 
+class PeripheralLibrary(object):
+    """ List of all information for peripheral config files in the root dir
+    """
+    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
+        #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, 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(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, peripheral_configs=None):
+        """Create peripheral objects from all peripheral configurations."""
+        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, 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, val in peripheral_config.items():
+            if "ram_" in key: 
+                peripheral.add_RAM(key, val["width"], val["mode"], val["depth"], val["descr"])
+            if "reg_" in key:       
+                fields = []
+                for reg_key, reg_val in val.items():   
+#                    print reg_key
+#                    print reg_val
+#                    print reg_key.values()
+#                    print reg_key.values()[0]
+                    repeat = None
+                    if "repeat" in reg_val:
+                        repeat = reg_val['repeat']  # print "YES!"
+                    
+                    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)
+            
+            if "parameters" in key:
+                peripheral.parameters.update(val)
+
+        return peripheral  
+    
+    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)           
+        
diff --git a/tools/oneclick/prestudy/YAML/system.py b/tools/oneclick/prestudy/YAML/system.py
new file mode 100755
index 0000000000..0b687afaae
--- /dev/null
+++ b/tools/oneclick/prestudy/YAML/system.py
@@ -0,0 +1,182 @@
+#!/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")
diff --git a/tools/oneclick/prestudy/YAML/system.yaml b/tools/oneclick/prestudy/YAML/system.yaml
index 98f8cde46f..5aa6647f53 100644
--- a/tools/oneclick/prestudy/YAML/system.yaml
+++ b/tools/oneclick/prestudy/YAML/system.yaml
@@ -1,24 +1,80 @@
 ---
-system_name: demo
-
-board_select: unb1
-bus_select : qsys
-
-
-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}  
-                                             
-                                             
\ No newline at end of file
+demo:
+  type: system
+
+  board_select: unb1
+
+  bus_select : qsys
+
+  reg_system_info:
+    locked_address: 0
+
+  rom_system_info:
+    locked_address: 0x20
+
+
+  peripherals:
+
+    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
+
-- 
GitLab