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

Task #893 backup

parent f637bfe9
No related branches found
No related tags found
No related merge requests found
Showing
with 1046 additions and 472 deletions
...@@ -9,30 +9,30 @@ bf_unit: ...@@ -9,30 +9,30 @@ bf_unit:
g_nof_signal_paths: 64 g_nof_signal_paths: 64
g_nof_subbands: 24 g_nof_subbands: 24
g_nof_input_streams: 16 g_nof_input_streams: 16
g_nof_signal_paths_per_stream: 4 g_nof_signal_paths_per_stream: 4 # PD: 64/16 = 4, g_nof_signal_paths/g_nof_input_streams
ram_bf_weights: ram_bf_weights:
width: g_weights_w * cm.c_nof_complex width: g_weights_w * cm.c_nof_complex
depth: g_nof_weights * g_nof_signal_paths # 256*64 = 16384 depth: g_nof_weights * g_nof_signal_paths # 256*64 = 16384
mode : RW mode : RW
descr: > descr: >
Contains the weights. "Contains the weights.
The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part. The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part."
ram_ss_ss_wide: ram_ss_ss_wide:
width: cm.ceil_log2(g_nof_subbands * g_nof_signal_paths_per_stream) width: cm.ceil_log2(g_nof_subbands * g_nof_signal_paths_per_stream)
depth: g_nof_weights * g_nof_input_streams * g_nof_signal_paths_per_stream # 256*16*4, nof_weights*nof_input_streams*nof_signal_paths_per_stream = 256*16*4=16384 depth: g_nof_weights * g_nof_input_streams * g_nof_signal_paths_per_stream # 256*16*4, nof_weights*nof_input_streams*nof_signal_paths_per_stream = 256*16*4=16384
mode : RW mode : RW
descr: > descr: >
Contains the addresses to select from the stored subbands. "Contains the addresses to select from the stored subbands."
ram_st_sst_bf: ram_st_sst_bf:
width: 56 width: 56
depth: g_nof_weights * cm.c_nof_complex # 256*2 = 512 depth: g_nof_weights * cm.c_nof_complex # 256*2 = 512
mode : RO mode : RO
descr: > descr: >
Contains the weights. "Contains the weights.
The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part. The real and the imaginary parts are concatenated: W_real in Lower part. W_imag in Higher part."
reg_st_sst_bf: reg_st_sst_bf:
Treshold: Treshold:
...@@ -41,10 +41,10 @@ bf_unit: ...@@ -41,10 +41,10 @@ bf_unit:
offset : 0x0 offset : 0x0
default: 0 default: 0
descr : > descr : >
When the treshold register is set to 0 the statistics will be auto-correlations. "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 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. for the a-input of the multiplier.
The a-input of the multiplier is updated every treshold clockcycle. Thereby cross statistics can be created. The a-input of the multiplier is updated every treshold clockcycle. Thereby cross statistics can be created."
peripheral_description: | peripheral_description: |
This is the beamformer unit "This is the beamformer unit"
...@@ -8,17 +8,17 @@ fringe_stop: ...@@ -8,17 +8,17 @@ fringe_stop:
depth: 256 depth: 256
mode : RW mode : RW
descr: > descr: >
Contains the step size for all nof_channels channels. "Contains the step size for all nof_channels channels."
ram_fringe_stop_offset: ram_fringe_stop_offset:
width: 10 width: 10
depth: 256 depth: 256
mode : RW mode : RW
descr: > descr: >
Contains the offset for all nof_channels channels. "Contains the offset for all nof_channels channels."
peripheral_description: | peripheral_description: |
The fringe stopping peripheral is based on piecewise linear coefficients. The coefficients are indicated as offset and step. "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 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 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 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
...@@ -46,12 +46,14 @@ fringe_stop: ...@@ -46,12 +46,14 @@ fringe_stop:
the page that is NOT accessible for the software and vice-versa. This means that the values that are written to the RAMs 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: will only be actually used in the following sync-interval:
_ T0 _ T1 _ T2
sync __| |_____________________________| |_____________________________| |________________________ A| _ T0 _ T1 _ T2
| VHDL uses data T0 | VHDL uses data T1 | VHDL uses data T2 A| sync __| |___________________________| |___________________________| |________________________
| Software writes data T1 | Software writes data T2 | Software writes data T3 A| | VHDL uses data T0 | VHDL uses data T1 | VHDL uses data T2
| | | A| | Software writes data T1 | Software writes data T2 | Software writes data T3
page_swap page_swap page_swap A| | | |
A| 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 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 synchronization with the sync-pulse can be done, using one of the BSN Monitors in the system. In the Apertif system
...@@ -63,24 +65,29 @@ fringe_stop: ...@@ -63,24 +65,29 @@ fringe_stop:
This RAM contains the offset values for all channels, ranging from Channel 0 to Channel Max-1. The width of the RAM is 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. defined by the offset_w.
RAM_ADDRESS RAM_CONTENT +-----------------------------------------+
0x0 Offset_Channel_0 | RAM_address | RAM_content |
0x1 Offset_Channel_1 |-----------------------------------------|
0x2 Offset_Channel_2 | 0x0 | Offset_Channel_0 |
0x3 Offset_Channel_3 | 0x1 | Offset_Channel_1 |
.. .. | 0x2 | Offset_Channel_2 |
.. Offset_Channel_Max-1 | 0x3 | Offset_Channel_3 |
| .. | .. |
| .. | Offset_Channel_Max-1 |
+-----------------------------------------+
RAM_FRINGE_STOP_STEP 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 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. specified by the step_w.
RAM_ADDRESS RAM_CONTENT +-----------------------------------------+
0x0 Step_Channel_0 | RAM_address | RAM_content |
0x1 Step_Channel_1 |-----------------------------------------|
0x2 Step_Channel_2 | 0x0 | Step_Channel_0 |
0x3 Step_Channel_3 | 0x1 | Step_Channel_1 |
.. .. | 0x2 | Step_Channel_2 |
.. Step_Channel_Max-1 | 0x3 | Step_Channel_3 |
| .. | .. |
| .. | Step_Channel_Max-1 |
+-----------------------------------------+"
#! /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
# PD mrt 2017
#
###############################################################################
import os
import sys
import argparse
import yaml
import traceback
from subprocess import CalledProcessError
from py_mm_lib import *
def main():
""" main function """
while True:
menu_choice = show_menu().lower()
if menu_choice == 'q':
break
elif menu_choice == '1':
filename = get_filename()
show_overview(filename)
elif menu_choice == '2':
filename = get_filename()
generate_system_rom(filename)
elif menu_choice == '3':
filename = get_filename()
generate_report(filename)
else:
pass
def show_menu():
""" show main menu """
menu = []
menu.append("OneClick menu")
menu.append("------------------------")
menu.append("1 show config file overview")
menu.append("2 generate system-rom")
menu.append("3 make documentation")
menu.append("Q quit")
menu.append("select menu nr: ")
nr = raw_input('\n'.join(menu))
return nr
def get_filename():
return raw_input("wich file: ")
def generate_report(filename):
try:
config = yaml.load(open(filename, "r"))
name = config.keys()[0]
settings = config[name]
documentation = Documentation(name)
if settings['type'] == 'system':
system = System(filename)
documentation.add(name, system)
elif settings['type'] == 'peripheral':
peripheral = Peripheral(filename)
peripheral.eval_peripheral()
documentation.add(name, peripheral)
documentation.generate_pdf()
except IOError:
logger.error("config file '{}' does not exist".format(filename))
except CalledProcessError:
pass
def show_overview(filename):
try:
config = yaml.load(open(filename, "r"))
name = config.keys()[0]
settings = config[name]
if settings['type'] == 'system':
system = System(filename)
system.show_overview()
elif settings['type'] == 'peripheral':
peripheral = Peripheral(filename)
peripheral.eval_peripheral()
peripheral.show_overview()
except IOError:
logger.error("config file '{}' does not exist".format(filename))
def generate_system_rom(filename):
""" generate system_rom reg and txt file """
system_rom = SystemRom()
system_rom.read_system(filename)
system_rom.generate_reg()
system_rom.generate_txt()
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('DEBUG')
mylogger.set_file_log_level('DEBUG')
# 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))
try:
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("Normal Exit")
...@@ -15,7 +15,7 @@ mms_diag_block_gen: ...@@ -15,7 +15,7 @@ mms_diag_block_gen:
offset : 0x0 offset : 0x0
default : 0 default : 0
descr : > descr : >
Bit 0: enable the block generator Bit 1: enable the blok generator on PPS "Bit 0: enable the block generator Bit 1: enable the blok generator on PPS"
Samples_per_packet: Samples_per_packet:
width : 16 width : 16
...@@ -23,7 +23,7 @@ mms_diag_block_gen: ...@@ -23,7 +23,7 @@ mms_diag_block_gen:
offset : 0x1 offset : 0x1
default: 256 default: 256
descr : > descr : >
This register specifies the number samples in a packet "This register specifies the number samples in a packet"
Blocks_per_sync: Blocks_per_sync:
width : 16 width : 16
...@@ -31,7 +31,7 @@ mms_diag_block_gen: ...@@ -31,7 +31,7 @@ mms_diag_block_gen:
offset : 0x2 offset : 0x2
default: 781250 default: 781250
descr : > descr : >
This register specifies the number of packets in a sync period "This register specifies the number of packets in a sync period"
Gapsize: Gapsize:
width : 16 width : 16
...@@ -39,7 +39,7 @@ mms_diag_block_gen: ...@@ -39,7 +39,7 @@ mms_diag_block_gen:
offset : 0x3 offset : 0x3
default: 80 default: 80
descr : > descr : >
This register specifies the gap in number of clock cycles between two consecutive packets "This register specifies the gap in number of clock cycles between two consecutive packets"
Mem_low_address: Mem_low_address:
width : 8 width : 8
...@@ -47,7 +47,7 @@ mms_diag_block_gen: ...@@ -47,7 +47,7 @@ mms_diag_block_gen:
offset : 0x4 offset : 0x4
default: 0 default: 0
descr : > descr : >
This register specifies the starting address for reading from the waveform memory "This register specifies the starting address for reading from the waveform memory"
Mem_high_address: Mem_high_address:
width : 8 width : 8
...@@ -55,14 +55,14 @@ mms_diag_block_gen: ...@@ -55,14 +55,14 @@ mms_diag_block_gen:
offset : 0x5 offset : 0x5
default: 0 default: 0
descr : > descr : >
This register specifies the last address to be read when from the waveform memory "This register specifies the last address to be read when from the waveform memory"
BSN_init_low: BSN_init_low:
width : 32 width : 32
mode : RW mode : RW
offset : 0x6 offset : 0x6
default: 0 default: 0
descr : > descr : >
This register specifies the lower(LSB) 32 bits [31:0] of the initialization BSN "This register specifies the lower(LSB) 32 bits [31:0] of the initialization BSN"
BSN_init_high: BSN_init_high:
width : 32 width : 32
...@@ -70,15 +70,14 @@ mms_diag_block_gen: ...@@ -70,15 +70,14 @@ mms_diag_block_gen:
offset : 0x7 offset : 0x7
default: 0 default: 0
descr : > descr : >
This register specifies the higher(MSB) 32 bits [63:32] of the initialization BSN "This register specifies the higher(MSB) 32 bits [63:32] of the initialization BSN"
ram_diag_bg: ram_diag_bg:
width: g_buf_dat_w width: g_buf_dat_w
depth: 2**g_buf_addr_w * g_nof_streams depth: 2**g_buf_addr_w * g_nof_streams
mode : RW mode : RW
descr: > descr: >
Contains the Waveform data for the data-streams to be send "Contains the Waveform data for the data-streams to be send"
peripheral_description: | peripheral_description: |
Block generator "Block generator"
...@@ -15,8 +15,8 @@ mms_diag_data_buffer: ...@@ -15,8 +15,8 @@ mms_diag_data_buffer:
offset : 0x0 offset : 0x0
default: 0 default: 0
descr : > descr : >
Sync_cnt contains the nof times the buffer (ST) has received a sync pulse since the last MM read "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) (cleared when the last data word from the buffer is read)"
Word_cnt: Word_cnt:
width : 32 width : 32
...@@ -24,7 +24,7 @@ mms_diag_data_buffer: ...@@ -24,7 +24,7 @@ mms_diag_data_buffer:
offset : 0x1 offset : 0x1
default: 0 default: 0
descr : > descr : >
Word_cnt indicates the number of word currently (ST) written in the buffer. Cleared on (ST) re-write of buffer. "Word_cnt indicates the number of word currently (ST) written in the buffer. Cleared on (ST) re-write of buffer."
Valid_cnt_arm_ena: Valid_cnt_arm_ena:
width : 32 width : 32
...@@ -32,9 +32,9 @@ mms_diag_data_buffer: ...@@ -32,9 +32,9 @@ mms_diag_data_buffer:
offset : 0x2 offset : 0x2
default: 0 default: 0
descr : > descr : >
Valid_cnt contains the number of valid cycles since the last sync pulse. Cleared on every sync pulse. "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. 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. After the system is armed the next syn pulse will trigger the acquisition of data."
Reg_sync_delay: Reg_sync_delay:
width : 32 width : 32
...@@ -42,8 +42,8 @@ mms_diag_data_buffer: ...@@ -42,8 +42,8 @@ mms_diag_data_buffer:
offset : 0x3 offset : 0x3
default: 0 default: 0
descr : > descr : >
Reg_sync_delay contains the number of valid cycles to delay/wait after an armed-syncpulse, "Reg_sync_delay contains the number of valid cycles to delay/wait after an armed-syncpulse,
before the data is written to the databuffer. before the data is written to the databuffer."
Version: Version:
width : 32 width : 32
...@@ -51,17 +51,26 @@ mms_diag_data_buffer: ...@@ -51,17 +51,26 @@ mms_diag_data_buffer:
offset : 0x7 offset : 0x7
default: 0 default: 0
descr : > descr : >
Version contains the version number of the databuffer peripheral. "Version contains the version number of the databuffer peripheral."
ram_diag_data_buffer: ram_diag_data_buffer:
width: g_data_w width: g_data_w
depth: g_nof_streams * 2**cm.ceil_log2(g_buf_nof_data) depth: g_nof_streams * 2**cm.ceil_log2(g_buf_nof_data)
mode : RW mode : RW
descr: > descr: >
Contains the data that is being captured. "Contains the data that is being captured."
reg_rx_sequece:
Name??:
width : 32
mode : RW
offset : 0x0
default: 0
descr : >
"Name?? description."
peripheral_description: | peripheral_description: |
Peripheral diag_data_buffer "Peripheral diag_data_buffer
Memory map RAM_DIAG_DATA_BUFFER Memory map RAM_DIAG_DATA_BUFFER
...@@ -71,46 +80,39 @@ mms_diag_data_buffer: ...@@ -71,46 +80,39 @@ mms_diag_data_buffer:
The diag_data_buffer can store multiple streams in parallel. For example The diag_data_buffer can store multiple streams in parallel. For example
1024 data words for 16 streams the memory map becomes: 16 1024 data words for 16 streams the memory map becomes: 16
streamNr = 0: streamNr = 0:
+------------------------------------------------------------+
| byte 3 | byte 2 | byte 1 | byte 0 | wi |
|------------------------------------------------------------|
| data_0[31:0] | 0 |
| data_1[31:0] | 1 |
| ... | .. |
| data_1023[31:0] | 1023 |
+------------------------------------------------------------+
31 0 wi
|-----------------|-----------------|-----------------|-----------------|
| data_0[31:0] | 0
|-----------------------------------------------------------------------|
| data_1[31:0] | 1
|-----------------------------------------------------------------------|
| ... | ..
|-----------------------------------------------------------------------|
| data_1023[31:0] | 1023
|-----------------------------------------------------------------------|
streamNr = 1: streamNr = 1:
+------------------------------------------------------------+
31 0 wi | byte 3 | byte 2 | byte 1 | byte 0 | wi |
|-----------------|-----------------|-----------------|-----------------| |------------------------------------------------------------|
| data_0[31:0] | 1024 | data_0[31:0] | 1024 |
|-----------------------------------------------------------------------| | data_1[31:0] | 1025 |
| data_1[31:0] | 1025 | ... | .. |
|-----------------------------------------------------------------------| | data_1023[31:0] | 2047 |
| ... | .. +------------------------------------------------------------+
|-----------------------------------------------------------------------|
| data_1023[31:0] | 2047
|-----------------------------------------------------------------------|
streamNr = 15: streamNr = 15:
+------------------------------------------------------------+
| byte 3 | byte 2 | byte 1 | byte 0 | wi |
|------------------------------------------------------------|
| data_0[31:0] | 15360 |
| data_1[31:0] | 15361 |
| ... | .. |
| data_1023[31:0] | 16383 |
+------------------------------------------------------------+
31 0 wi
|-----------------|-----------------|-----------------|-----------------|
| data_0[31:0] | 15360
|-----------------------------------------------------------------------|
| data_1[31:0] | 15361
|-----------------------------------------------------------------------|
| ... | ..
|-----------------------------------------------------------------------|
| data_1023[31:0] | 16383
|-----------------------------------------------------------------------|
Remarks: Remarks:
- The data buffer stores valid data samples until it is full. - The data buffer stores valid data samples until it is full.
...@@ -120,26 +122,22 @@ mms_diag_data_buffer: ...@@ -120,26 +122,22 @@ mms_diag_data_buffer:
- The actual data width depends on the generic g_data_w in - The actual data width depends on the generic g_data_w in
diag_data_buffer.vhd. The value of unused MSBits is undefined. 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) Memory map REG_DIAG_DATA_BUFFER (one for each stream like the RAM above)
31 0 wi +----------------------------------------------------------------------------+
|-----------------|-----------------|-----------------|-----------------| | byte 3 | byte 2 | byte 1 | byte 0 | wi |
| sync_cnt[31:0] | 0 RO (Version 0 and 1) |----------------------------------------------------------------------------|
|-----------------------------------------------------------------------| | sync_cnt[31:0] | 0 RO (Version 0 and 1) |
| word_cnt[31:0] | 1 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) |
| 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) |
| reg_sync_delay[31:0] | 3 RW (Version 1 only) | RESERVED | 5 (Version 1 only) |
|-----------------------------------------------------------------------| | RESERVED | 6 (Version 1 only) |
| RESERVED | 4 (Version 1 only) | version[31:0] | 7 RO (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. There are 3 modes of operation of the data_buffer.
Version 0 supports Mode 1 and Mode 2 Version 0 supports Mode 1 and Mode 2
...@@ -174,4 +172,4 @@ mms_diag_data_buffer: ...@@ -174,4 +172,4 @@ mms_diag_data_buffer:
armed the next syn pulse will truigger the acquisition of data. 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, - reg_sync_delay contains the number of valid cycles to delay/wait after an armed-syncpulse,
before the data is written to the databuffer. before the data is written to the databuffer.
- version contains the version number of the databuffer peripheral. - version contains the version number of the databuffer peripheral."
\ No newline at end of file
...@@ -4,7 +4,7 @@ mms_dp_bsn_align: ...@@ -4,7 +4,7 @@ mms_dp_bsn_align:
nof_inst: 1 nof_inst: 1
parameters: parameters:
g_nof_input: 4 g_nof_input: 2
reg_dp_bsn_align: reg_dp_bsn_align:
Enable: Enable:
...@@ -14,8 +14,8 @@ mms_dp_bsn_align: ...@@ -14,8 +14,8 @@ mms_dp_bsn_align:
default: 0 default: 0
repeat : g_nof_input repeat : g_nof_input
descr : > descr : >
Input enable register for input 0. If set to 0 the input is discarded from alignment. "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. If set to 1 the corresopnding input is taken into account."
peripheral_description: | peripheral_description: |
This is the BSN aligner "This is the BSN aligner"
...@@ -14,7 +14,7 @@ mms_dp_fifo_fill: ...@@ -14,7 +14,7 @@ mms_dp_fifo_fill:
default: 0 default: 0
repeat : g_nof_streams repeat : g_nof_streams
descr : > descr : >
Register reflects the currently used nof words on the fifo. "Register reflects the currently used nof words on the fifo."
fifo_status: fifo_status:
width: 2 width: 2
...@@ -32,8 +32,8 @@ mms_dp_fifo_fill: ...@@ -32,8 +32,8 @@ mms_dp_fifo_fill:
default: 0 default: 0
repeat : g_nof_streams repeat : g_nof_streams
descr : > descr : >
Register contains the maximum number of words that have been in the fifo. "Register contains the maximum number of words that have been in the fifo.
Will be cleared after it has been read. Will be cleared after it has been read."
peripheral_description: | peripheral_description: |
This is the MM slave version of the dp_fifo_fill component. "This is the MM slave version of the dp_fifo_fill component."
...@@ -2,8 +2,15 @@ ...@@ -2,8 +2,15 @@
""" """
import os import os
cwd = os.getcwd()
print(cwd)
from my_logger import MyLogger from my_logger import MyLogger
mylogger = MyLogger(os.path.join(os.getcwd(), 'log')) mylogger = MyLogger(os.path.join(os.getcwd(), 'log'))
logger = mylogger.logger logger = mylogger.logger
from peripheral import PeripheralLibrary from peripheral import PeripheralLibrary, Peripheral
from system import System
from documentation import Documentation
from system_rom import SystemRom
\ No newline at end of file
###############################################################################
#
# 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
# PD feb 2017
#
###############################################################################
"""
Make automatic documentation
"""
import sys
import os
import argparse
import subprocess
import traceback
import logging
from pylatex import Document, Section, Subsection, Command, Package, Tabular, MultiColumn, MultiRow, SmallText, LargeText
from pylatex.utils import italic, bold, NoEscape, verbatim, escape_latex
from peripheral import PeripheralLibrary, Peripheral
from system import System
import common as cm
logger = logging.getLogger('main.documentation')
class Documentation(object):
""" make documentation for system or peripheral(s)
"""
def __init__(self, document_name):
self.root_dir = os.path.expandvars('$RADIOHDL/tools/oneclick/prestudy/YAML')
self.document_name = document_name
self.config = {}
geometry_options = {"tmargin": "1cm", "lmargin": "2.5cm"}
self.doc = Document(geometry_options=geometry_options)
#doc.packages.append(Package(u'listings'))
#doc.append(NoEscape(r'\lstset{columns=flexible}'))
#doc.append(NoEscape(r'\lstset{keepspaces=true}'))
#doc.append(NoEscape(r'\lstset{basicstyle=\ttfamily\color{blue}}'))
self.add_title()
def generate_pdf(self):
self.doc.generate_pdf('{}'.format(self.document_name), clean_tex=False)
#self.doc.generate_tex()
def add_title(self):
""" add title to document """
self.doc.preamble.append(Command('title', 'MM Documentation for {}'.format(self.document_name)))
self.doc.preamble.append(Command('author', 'oneclick-mm-documentation-script'))
self.doc.preamble.append(Command('date', NoEscape(r'\today')))
self.doc.append(NoEscape(r'\maketitle'))
def add(self, header, data):
""" add section (data) to the document with header as section name """
_type = type(data)
if _type == str:
self.add_text(header, data)
elif _type == dict:
self.add_dict(header, data)
elif _type == Peripheral:
self.add_peripheral(header, data)
elif _type == System:
self.add_system(header, data)
else:
pass
def add_text(self, header, text):
""" add text to the document """
self.add_section(header, text)
def add_dict(self, header, data):
""" add a dict to the document """
for key, val in data.items():
self.add(key, val)
def add_peripheral(self, header, data):
""" add a peripheral to the document """
self.add_section(data.get_name(), data.get_description() )
def add_system(self, header, data):
""" add a system to the document """
self.doc.append(Command('begin', 'huge'))
self.doc.append(NoEscape("{} description.".format(header)))
self.doc.append(Command('end', 'huge'))
self.add("", data.system['description'])
self.doc.append(Command('begin', 'huge'))
self.doc.append(NoEscape("Peripherals."))
self.doc.append(Command('end', 'huge'))
for key, val in sorted(data.peripherals.items()):
_header = key.strip()
_text = val.get_description()
self.add(_header, _text)
def add_section(self, heading='', text=''):
with self.doc.create(Section('%s' % heading)) as sec:
lines = text.splitlines(True)
n_lines = len(lines)
block_data = []
line_nr = 0
while line_nr < n_lines:
if lines[line_nr].startswith('+--'):
block_data = []
block_data.append(lines[line_nr])
line_nr += 1
while line_nr < n_lines:
block_data.append(lines[line_nr])
if lines[line_nr].startswith('+--'):
logger.debug("append table")
self.add_table(sec, block_data)
line_nr += 1
break
line_nr += 1
elif lines[line_nr].startswith('A|'):
block_data = []
block_data.append(lines[line_nr][2:])
line_nr += 1
while line_nr < n_lines:
block_data.append(lines[line_nr][2:])
if not lines[line_nr].startswith('A|'):
logger.debug("append AscciiArt")
self.add_ascii_art(sec, block_data)
break
line_nr += 1
else:
self.add_line(sec, lines[line_nr])
line_nr += 1
return
def add_line(self, doc, line, add=True):
n_spaces = 0
_line = []
text = []
if line[0] == '"':
line = line[1:]
if line[-1] == '"':
line = line[:-1]
for ch_nr, ch in enumerate(line):
if ch == ' ':
n_spaces += 1
else:
if n_spaces == 1:
text.append(' ')
elif n_spaces:
if text:
_line.append('%s' % ''.join(text))
text = []
_line.append(NoEscape(r'\hspace{%fcm}' % (n_spaces * 0.184)))
n_spaces = 0
text.append(ch)
if text:
_line.append('%s' % ''.join(text))
#_line.append('\n')
if add:
for i in _line:
doc.append(i)
return
return _line
def add_ascii_art(self, doc, data):
doc.append(Command('begin', 'small'))
doc.append(Command('begin', 'verbatim'))
doc.append(NoEscape(''.join(data)))
doc.append(Command('end', 'verbatim'))
doc.append(Command('end', 'small'))
def add_table(self, doc, data):
table = None
table_column_pos = []
table_n_columns = 0
# get vertical line positions of second line
pos = 0
while pos >= 0:
pos = data[1].find('|', pos)
if pos > -1:
table_column_pos.append(pos)
pos += 1
# make table
table_n_columns = len(table_column_pos) - 1
#table = Tabular('c'.join('|'*len(table_column_pos)))
tabular = ['|']
p1 = table_column_pos[0]
for p2 in table_column_pos[1:]:
cols = p2 - p1
tabular.append('p{%fcm}|' % (cols * 0.16))
p1 = p2
table = Tabular(''.join(tabular))
#table.add_hline()
for line_nr, line in enumerate(data):
logger.debug("%s, %d", line, len(line))
if line.startswith('+---'): # or line.startswith('|---'):
table.add_hline()
continue
if line.startswith('|---'):
continue
if line_nr == 1:
row_data = [bold(i) for i in line.strip()[1:-1].split('|')]
else:
row_data = [i for i in line.strip()[1:-1].split('|')]
logger.debug("%s", str(row_data))
row_n_cols = len(row_data)
# if all colums used add data
if row_n_cols == table_n_columns:
if len(table) > 1:
table.add_hline()
table.add_row(row_data)
else:
row_cells = []
row_data_index = 0
pos = table_column_pos[0] + 1
last_index = 0
while pos >= 0:
pos = line.find('|', pos)
if pos > -1:
for index, tcp in enumerate(table_column_pos):
if pos == tcp:
#rint "same pos, %d" % pos
#if (index - last_index) == 1:
# row_cells.append(row_data[row_data_index])
#else:
cols = index - last_index
text = row_data[row_data_index]
if len(row_data[row_data_index][:2].strip()) == 0:
row_cells.append(MultiColumn(cols, align='|c|', data=SmallText(text)))
else:
row_cells.append(MultiColumn(cols, align='|l|', data=SmallText(text)))
last_index = index
row_data_index += 1
pos += 1
else:
table.add_hline()
table.add_row(row_cells)
doc.append(table)
doc.append('\n')
return table
This diff is collapsed.
###############################################################################
#
# 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 copy
import logging
import yaml
import common as cm
from peripheral import PeripheralLibrary
logger = logging.getLogger('main.system')
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.system = {}
self.peripherals = {}
self.valid_file_type = False
if file_path_name is None:
logger.debug("No system configuration file specified")
self.system_config = None
self.system = None
else:
# list of peripheral configurations that are read from the available peripheral files
self.system_config = self.read_system_file(file_path_name)
self.create_system()
def is_valid(self):
""" return False or True if the given file is a valid system file """
return self.valid_file_type
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_name[0]
system_config = yaml.load(open(file_path_name, 'r'))
if system_config.values()[0]['type'] != 'system':
return {}
self.valid_file_type = True
return system_config
def create_system(self):
"""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 = self.system_config.keys()[0]
config = self.system_config[self.system_name]
for key, val in config.items():
if key == 'peripherals':
for peripheral_name, peripheral_config in val.items():
if '.' in peripheral_name:
peripheral_key, label = peripheral_name.split('.')
logger.debug("splitted %s in key=%s, label=%s", peripheral_name, peripheral_key, label)
else:
peripheral_key = peripheral_name
label = ''
# (Deep)Copy the peripheral from the library in order to avoid creating a reference
peripheral_from_lib = copy.deepcopy(self.peri_lib.find_peripheral(peripheral_key))
if peripheral_from_lib is None:
logger.warning("peripheral_key %s not found in library", peripheral_key)
continue
logger.debug(" Finding %s", 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 %s default value: %s is overwritten with new value: %s",
parameter_key, str(peripheral_from_lib.parameters[parameter_key]), str(parameter_val))
peripheral_from_lib.parameters[parameter_key] = parameter_val
else:
logger.warning(" !!! Parameter %s does not exist on peripheral: %s !!!",
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: %s label(%s)",
peripheral_from_lib.name, peripheral_from_lib.label)
else:
self.system[key] = val
logger.debug("Start evaluating the peripherals")
for peripheral_name, peripheral_config in self.peripherals.items():
peripheral_config.eval_peripheral()
return
def show_overview(self):
""" print system overview
"""
logger.info("----------------")
logger.info("SYSTEM OVERVIEW:")
logger.info("----------------")
logger.info("System name '%s'", self.system_name)
for peripheral in self.system_config[self.system_name]['slave_index_order']:
self.peripherals[peripheral].show_overview(header=False)
###############################################################################
#
# 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
# PD feb 2017
#
###############################################################################
"""
Generate system rom files
"""
import sys
import os
import argparse
import subprocess
import traceback
import logging
from math import ceil
from peripheral import PeripheralLibrary, Peripheral
from system import System
import common as cm
logger = logging.getLogger('main.system_rom')
class SystemRom(object):
def __init__(self):
self.filename = None
self.system = None
self.mm_reg_list = []
self.mm_ram_list = []
self.word_size = 32 # number of bits
def read_system(self, filename):
""" read system configuration file """
self.filename = filename
system = System(self.filename)
if system.is_valid():
self.system = system
return True
return False
def calc_offsets(self):
""" calculate register offsets """
slave_order = self.system.system['slave_index_order']
peripherals = self.system.peripherals
reg_info_start_address = self.system.system['reg_system_info']['locked_start_address']
rom_info_start_address = self.system.system['rom_system_info']['locked_start_address']
reg_addr = 0x0000
for name in slave_order:
peripheral = peripherals[name]
for key, val in peripheral.rams.items():
width = int(val['with'])
depth = int(val['depth'])
n_words = int(ceil(float(width) / self.word_size))
n_addresses = n_words * depth
self.mm_reg_list.append([key, reg_addr, n_words, depth])
reg_addr += n_addresses
'''
for rkey, rval in peripheral.registers.items():
for fkey, fval in rval.items():
width = int(val['with'])
n_words = int(ceil(float(width) / self.word_size))
n_addresses = n_words * depth
self.mm_reg_list.append([key, reg_addr, n_words, depth])
reg_addr += n_addresses
'''
print(self.mm_reg_list)
def generate_reg(self):
pass
def generate_txt(self):
pass
#!/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")
...@@ -2,19 +2,35 @@ ...@@ -2,19 +2,35 @@
demo: demo:
type: system type: system
description: |
"DEMO system for testing mm tools
Now with extra line ??"
board_select: unb1 board_select: unb1
bus_select : qsys bus_select : qsys
reg_system_info: reg_system_info:
locked_address: 0 locked_start_address: 0
rom_system_info: rom_system_info:
locked_address: 0x20 locked_start_address: 0x20
slave_index_order: [fringe_stop,
mms_diag_block_gen.input,
mms_diag_block_gen.mesh,
mms_diag_block_gen.proc,
bf_unit,
mms_diag_block_gen.output,
mms_diag_data_buffer.input_pre,
mms_diag_data_buffer.input_post,
mms_diag_data_buffer.mesh,
mms_diag_data_buffer.proc,
mms_dp_bsn_align.input,
mms_dp_fifo_fill]
peripherals: peripherals:
# use '- peripheral_name' to set address order'
fringe_stop: fringe_stop:
nof_inst: 1 nof_inst: 1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment