OpenCores
URL https://opencores.org/ocsvn/radiohdl/radiohdl/trunk

Subversion Repositories radiohdl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/radiohdl/trunk/config/hdl_buildset_rsp.cfg
0,0 → 1,24
# TODO: Does RadioHDL still works for RSP??
buildset_name = rsp
technology_names = ip_virtex4
family_names = virtex4
block_design_names = sopc
 
synth_tool_name = ise
synth_tool_version = 11.1
sim_tool_name = modelsim
sim_tool_version = 6.6c
ip_tool_name = coregen
 
project_dir_depth_sim = 4
project_dir_depth_synth = 0
 
lib_root_dirs = $RSP
 
[quartus]
quartus_dir = ${ALTERA_DIR}/<synth_tool_version>
 
[modelsim]
modelsim_dir = ${MENTOR_DIR}/<sim_tool_version>/modeltech
modelsim_platform = linux_x86_64
modelsim_search_libraries =
/radiohdl/trunk/config/hdl_buildset_unb1.cfg
0,0 → 1,23
# Uniboard 1 configuration
buildset_name = unb1
technology_names = ip_stratixiv
family_names = stratixiv
block_design_names = sopc
 
synth_tool_name = quartus
synth_tool_version = 11.1
sim_tool_name = modelsim
sim_tool_version = 6.6c
 
lib_root_dirs = ${RADIOHDL_WORK}/libraries ${RADIOHDL_WORK}/applications ${RADIOHDL_WORK}/boards
 
[quartus]
quartus_dir = ${ALTERA_DIR}/<synth_tool_version>
 
[modelsim]
modelsim_dir = ${MENTOR_DIR}/<sim_tool_version>/modeltech
modelsim_platform = linux_x86_64
modelsim_search_libraries =
# stratixiv only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver
altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip
/radiohdl/trunk/config/hdl_buildset_unb2.cfg
0,0 → 1,27
# Uniboard 2 configuration
buildset_name = unb2
technology_names = ip_arria10
family_names = arria10 stratixiv
block_design_names = sopc
 
synth_tool_name = quartus
synth_tool_version = 15.0
sim_tool_name = modelsim
sim_tool_version = 10.4
 
lib_root_dirs = ${RADIOHDL_WORK}/libraries ${RADIOHDL_WORK}/applications ${RADIOHDL_WORK}/boards
 
[quartus]
quartus_dir = ${ALTERA_DIR}/<synth_tool_version>
 
[modelsim]
modelsim_dir = ${MENTOR_DIR}/<sim_tool_version>/questasim
modelsim_platform = linux_x86_64
model_tech_altera_lib = ${MODELSIM_ALTERA_LIBS_DIR}/<synth_tool_version>
modelsim_search_libraries =
# arria10 only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
altera lpm sgate altera_mf altera_lnsim twentynm twentynm_hssi twentynm_hip
# both stratixiv and arria10
#altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
#altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip twentynm twentynm_hssi twentynm_hip
/radiohdl/trunk/config/hdl_buildset_unb2a.cfg
0,0 → 1,26
# Uniboard 2a configuration
buildset_name = unb2a
technology_names = ip_arria10_e3sge3
family_names = arria10
block_design_names = sopc
 
synth_tool_name = quartus
synth_tool_version = 16.0
sim_tool_name = modelsim
sim_tool_version = 10.4
 
lib_root_dirs = ${RADIOHDL_WORK}/libraries ${RADIOHDL_WORK}/applications ${RADIOHDL_WORK}/boards
 
[quartus]
quartus_dir = ${ALTERA_DIR}/<synth_tool_version>
 
[modelsim]
modelsim_dir = ${MENTOR_DIR}/<sim_tool_version>/questasim
modelsim_platform = linux_x86_64
modelsim_search_libraries =
# arria10 only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
altera lpm sgate altera_mf altera_lnsim twentynm twentynm_hssi twentynm_hip
# both stratixiv and arria10
#altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
#altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip twentynm twentynm_hssi twentynm_hip
/radiohdl/trunk/config/hdl_buildset_unb2b.cfg
0,0 → 1,26
# Uniboard 2b configuration
buildset_name = unb2b
technology_names = ip_arria10_e1sg
family_names = arria10
block_design_names = qsys
 
synth_tool_name = quartus
synth_tool_version = 18.0
sim_tool_name = modelsim
sim_tool_version = 10.4
 
lib_root_dirs = ${RADIOHDL_WORK}/libraries ${RADIOHDL_WORK}/applications ${RADIOHDL_WORK}/boards
 
[quartus]
quartus_dir = ${ALTERA_DIR}/<synth_tool_version>
 
[modelsim]
modelsim_dir = ${MENTOR_DIR}/<sim_tool_version>/questasim
modelsim_platform = linux_x86_64
modelsim_search_libraries =
# arria10 only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
altera lpm sgate altera_mf altera_lnsim twentynm twentynm_hssi twentynm_hip
# both stratixiv and arria10
#altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
#altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip twentynm twentynm_hssi twentynm_hip
/radiohdl/trunk/config/hdl_buildset_unb2c.cfg
0,0 → 1,26
# Uniboard 2c configuration
buildset_name = unb2c
technology_names = ip_arria10_e1sg
family_names = arria10
block_design_names = qsys
 
synth_tool_name = quartus
synth_tool_version = 18.0
sim_tool_name = modelsim
sim_tool_version = 10.4
 
lib_root_dirs = ${RADIOHDL_WORK}/libraries ${RADIOHDL_WORK}/applications ${RADIOHDL_WORK}/boards
 
[quartus]
quartus_dir = ${ALTERA_DIR}/<synth_tool_version>
 
[modelsim]
modelsim_dir = ${MENTOR_DIR}/<sim_tool_version>/questasim
modelsim_platform = linux_x86_64
modelsim_search_libraries =
# arria10 only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
altera lpm sgate altera_mf altera_lnsim twentynm twentynm_hssi twentynm_hip
# both stratixiv and arria10
#altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver twentynm_ver twentynm_hssi_ver twentynm_hip_ver
#altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip twentynm twentynm_hssi twentynm_hip
/radiohdl/trunk/config/hdl_tool_modelsim.cfg
0,0 → 1,2
# configuration file for defining the model installation on this system
model_tech_altera_lib = ${MODELSIM_ALTERA_LIBS_DIR}/${SYNTH_TOOL_VERSION}
/radiohdl/trunk/config/hdl_tool_quartus.cfg
0,0 → 1,35
# configuration file for defining the quartus installation on this system
quartus_rootdir = ${QUARTUS_DIR}/quartus
quartus_rootdir_override = ${QUARTUS_DIR}/quartus
niosdir = ${QUARTUS_DIR}/nios2eds
 
# extension to the PATH variable
quartus_paths =
<quartus_rootdir>/bin
<niosdir>/bin
<niosdir>/bin/gnu/H-i686-pc-linux-gnu/bin
<niosdir>/bin/gnu/H-x86_64-pc-linux-gnu/bin
<niosdir>/sdk2/bin
 
[sopc]
sopc_paths =
<quartus_rootdir>/sopc_builder/bin
sopc_environment_variables =
sopc_kit_nios2 <niosdir>
 
[qsys]
qsys_paths =
<quartus_rootdir>/../qsys/bin
 
[ip generation]
ip_tools = qmegawiz qsys-generate quartus_sh
qmegawiz_default_options = -silent
qsys-generate_default_options = --synthesis=VHDL --simulation=VHDL --allow-mixed-language-simulation --block-symbol-file
quartus_sh_default_options =
 
[user settings]
user_paths =
user_environment_variables =
altera_hw_tcl_keep_temp_files 1
 
#unb_compile_stamps 1
/radiohdl/trunk/core/test/cdf_dir/correct_files/dangling_test.txt
0,0 → 1,6
# Testfile for testing sections the CommonDictFile class
#
# First some keys with different spacing (spaces and tabs)
this is a lost value which causes an exception
 
global_key_1 = global_1
/radiohdl/trunk/core/test/cdf_dir/correct_files/key_value_test.txt
0,0 → 1,43
# Testfile for testing the CommonDictFile class
#
# First some keys with different spacing (spaces and tabs)
 
space_key_0=
space_key_1=value_1
space_key_2 =value_2
space_key_3= value_3
space_key_4 = value_4
space_key_5 = value_5
space_key_6 = value_6
space_key_7 = value_7
 
# Test keys with multiple values
multi_key_1 = value10 value11 value12
multi_key_2 = value20, value21, value22
multi_key_3 = value30
value31
value32
value33
multi_key_4 = value40 = value41 =
value42
 
# Difference between empty keys and multiline keys
tricky_key_1 =
tricky_key_2 =
tricky_value_2
tricky_key_3 =
 
["my_section"]
section_key_1 =
section_value_10
 
section_value_11
= # equal sign without a key is added as value
value which is also part of section_key_1
 
warning_key_1 = Be aware that multiline values can be tricky:
 
this also belongs
to previous
key 'warning_key_1'
but_this = a new key-value pair
/radiohdl/trunk/core/test/cdf_dir/correct_files/section_test.txt
0,0 → 1,18
# Testfile for testing sections the CommonDictFile class
#
# First some keys with different spacing (spaces and tabs)
 
global_key_1 = global_1
global_key_2 = [ "aap", "noot", "mies" ] # this is seen as a section header instead of a value!!!
 
just_some_key_1 = global value1 which is lost without a warning
just_some_key_2 = global value2 which is lost without a warning
 
[section_1]
just_some_key_1 = section1 value1 which is lost without a warning
just_some_key_2 = section1 value2 which is lost without a warning
 
[section_2]
just_some_key_1 = section2 value1
just_some_key_2 = section2 value2
 
/radiohdl/trunk/core/test/cdf_dir/empty_file/comment_only_dict.txt
0,0 → 1,4
# This file only
# contains comments
# and no
# key = value lines
/radiohdl/trunk/core/test/cdf_dir/empty_file/empty_dict.txt --- radiohdl/trunk/core/test/cdf_dir/hdlbuildset_files/hdl_buildset_rsp.cfg (nonexistent) +++ radiohdl/trunk/core/test/cdf_dir/hdlbuildset_files/hdl_buildset_rsp.cfg (revision 4) @@ -0,0 +1,22 @@ +# TODO: Does RadioHDL still works for RSP?? +buildset_name = rsp +technology_names = ip_virtex4 +family_names = virtex4 +block_design_names = sopc + +sim_tool_name = modelsim +sim_tool_version = 6.6c +synth_tool_name = ise +synth_tool_version = 11.1 +ip_tool_name = coregen + +project_dir_depth_sim = 4 +project_dir_depth_synth = 0 + +lib_root_dir = $RSP +build_dir = $RADIOHDL_BUILD_DIR +quartus_dir = /home/software/Altera/ +model_tech_altera_lib = /home/software/modelsim_altera_libs/ +model_tech_dir = /home/software/Mentor//modeltech +vsim_dir = /linux_x86_64 +modelsim_search_libraries =
/radiohdl/trunk/core/test/cdf_dir/hdlbuildset_files/hdl_buildset_unb1.cfg
0,0 → 1,21
# Uniboardd 1 configuration
buildset_name = unb1
technology_names = ip_stratixiv
family_names = stratixiv
block_design_names = sopc
 
sim_tool_name = modelsim
sim_tool_version = 6.6c
synth_tool_name = quartus
synth_tool_version = 11.1sp2
 
lib_root_dirs = ${RADIOHDL_WORK}/libraries ${RADIOHDL_WORK}/applications ${RADIOHDL_WORK}/boards
build_dir = $RADIOHDL_BUILD_DIR
quartus_dir = /home/software/Altera/<synth_tool_version>
model_tech_altera_lib = /home/software/modelsim_altera_libs/<synth_tool_version>
model_tech_dir = /home/software/Mentor/<sim_tool_version>/modeltech
vsim_dir = <model_tech_dir>/linux_x86_64
modelsim_search_libraries =
# stratixiv only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver
altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip
/radiohdl/trunk/core/test/cdf_dir/hdlbuildset_files/hdl_buildset_wrong.cfg
0,0 → 1,21
# Uniboardd 1 configuration
buildset_name = unb1
#technology_names = ip_stratixiv
family_names = stratixiv
block_design_names = sopc
 
sim_tool_name = modelsim
sim_tool_version = 6.6c
synth_tool_name = quartus
synth_tool_version = 11.1sp2
 
lib_root_dir = $HDL
build_dir = $RADIOHDL_BUILD_DIR
quartus_dir = /home/software/Altera/<synth_tool_version>
model_tech_altera_lib = /home/software/modelsim_altera_libs/<synth_tool_version>
model_tech_dir = /home/software/Mentor/<sim_tool_version>/modeltech
vsim_dir = <model_tech_dir>/linux_x86_64
modelsim_search_libraries =
# stratixiv only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver
altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip
/radiohdl/trunk/core/test/cdf_dir/hdllib_files/hdllib_wrong.cfg
0,0 → 1,24
hdl_lib_name = technology
hdl_library_clause_name = technology_lib
#hdl_lib_uses_synth =
hdl_lib_uses_sim =
hdl_lib_technology =
 
synth_files =
technology_pkg.vhd
$RADIOHDL_BUILD_DIR/<buildset_name>/modelsim/technology/technology_select_pkg.vhd
test_bench_files =
 
regression_test_vhdl =
# no self checking tb available yet
 
 
[modelsim_project_file]
modelsim_copy_files =
technology_select_pkg_<buildset_name>.vhd $RADIOHDL_BUILD_DIR/<buildset_name>/modelsim/technology/technology_select_pkg.vhd
 
 
 
[quartus_project_file]
quartus_copy_files =
technology_select_pkg_<buildset_name>.vhd $RADIOHDL_BUILD_DIR/<buildset_name>/quartus/technology/technology_select_pkg.vhd
/radiohdl/trunk/core/test/cdf_dir/hdllib_files/test_hdllib.cfg
0,0 → 1,24
hdl_lib_name = technology
hdl_library_clause_name = technology_lib
hdl_lib_uses_synth =
hdl_lib_uses_sim =
hdl_lib_technology =
 
synth_files =
technology_pkg.vhd
$RADIOHDL_BUILD_DIR/<buildset_name>/modelsim/technology/technology_select_pkg.vhd
test_bench_files =
 
regression_test_vhdl =
# no self checking tb available yet
 
 
[modelsim_project_file]
modelsim_copy_files =
technology_select_pkg_<buildset_name>.vhd $RADIOHDL_BUILD_DIR/<buildset_name>/modelsim/technology/technology_select_pkg.vhd
 
 
 
[quartus_project_file]
quartus_copy_files =
technology_select_pkg_<buildset_name>.vhd $RADIOHDL_BUILD_DIR/<buildset_name>/quartus/technology/technology_select_pkg.vhd
/radiohdl/trunk/core/test/cdf_dir/hdltool_files/hdl_tool_quartus.cfg
0,0 → 1,27
# configuration file for defining the quartus installation on this system
quartus_rootdir = ${QUARTUS_DIR}/quartus
quartus_rootdir_override = ${QUARTUS_DIR}/quartus
niosdir = ${QUARTUS_DIR}/nios2eds
 
# extension to the PATH variable
quartus_paths =
<quartus_rootdir>/bin
<niosdir>/bin
<niosdir>/bin/gnu/H-i686-pc-linux-gnu/bin
<niosdir>/bin/gnu/H-x86_64-pc-linux-gnu/bin
<niosdir>/sdk2/bin
 
[sopc]
sopc_paths =
<quartus_rootdir>/sopc_builder/bin
sopc_environment_variables =
sopc_kit_nios2 <niosdir>
 
[qsys]
qsys_paths =
<quartus_rootdir>/../qsys/bin
 
[user settings]
user_environment_variables =
altera_hw_tcl_keep_temp_files 1
 
/radiohdl/trunk/core/test/cdf_dir/referenced_files/reference_test.txt
0,0 → 1,34
# Testfile for testing the CommonDictFile class
#
non_ref_key_1 = some_value
non_ref_key_2 = some_other_value
 
early_ref_key1 = before <ref_key_2> is defined
 
ref_key_1 = single_reference
ref_key_2 = multiple words in the value
 
simple_ref_1 = a value with <ref_key_1>
double_ref_1 = a value with twice <ref_key_1><ref_key_1>
triple_key_1 = its here <ref_key_1> and here <ref_key_1> and here <ref_key_1>!!!
triple_key_2 = its here <ref_key_2> and here <ref_key_1>!!!
 
ref_only_key_1 = <ref_key_1>
 
wrong_ref_1 = what will double brackets <<ref_key_2>> do? # will not be replaced
 
# this will give all nested_key_x the value 'some_value'
nested_key_1 = some_value
nested_key_2 = <nested_key_1>
nested_key_3 = <nested_key_2>
 
reverse_nested_key_1 = <reverse_nested_key_2> # becomes <reverse_nested_key_3> after substitution!!!
reverse_nested_key_2 = <reverse_nested_key_3>
reverse_nested_key_3 = some_value
 
mutual_key_1 = <mutual_key_2> # becomes <<mutual_key_1> after substitution
mutual_key_2 = <mutual_key_1> # remains the same
 
loop_key_1 = <loop_key_1> # remains the same
 
undefined_key_1 = reference to <non existing key>
/radiohdl/trunk/core/test/cdf_dir/tree/cfgfile/a/dict.txt
0,0 → 1,3
# Testfile for testing the CommonDictFile class
#
key_1 = top_dir/a
/radiohdl/trunk/core/test/cdf_dir/tree/cfgfile/b/0/dict.txt
0,0 → 1,3
# Testfile for testing the CommonDictFile class
#
key_1 = top_dir/b/0
/radiohdl/trunk/core/test/cdf_dir/tree/cfgfile/b/1/dict.txt
0,0 → 1,3
# Testfile for testing the CommonDictFile class
#
key_1 = top_dir/b/1
/radiohdl/trunk/core/test/cdf_dir/tree/cfgfile/b/2/dict.txt
0,0 → 1,3
# Testfile for testing the CommonDictFile class
#
key_1 = top_dir/b/2
/radiohdl/trunk/core/test/cdf_dir/tree/cfgfile/b/dict.txt
0,0 → 1,3
# Testfile for testing the CommonDictFile class
#
key_1 = top_dir/b
/radiohdl/trunk/core/test/cdf_dir/tree/cfgfile/c/dict.txt
0,0 → 1,3
# Testfile for testing the CommonDictFile class
#
key_1 = top_dir/c
/radiohdl/trunk/core/test/cdf_dir/tree/cfgfile/dict.txt
0,0 → 1,3
# Testfile for testing the CommonDictFile class
#
key_1 = top_dir
/radiohdl/trunk/core/test/cdf_dir/tree/hdlbuildset/hdl_buildset_rsp.cfg
0,0 → 1,22
# TODO: Does RadioHDL still works for RSP??
buildset_name = rsp
technology_names = ip_virtex4
family_names = virtex4
block_design_names = sopc
 
sim_tool_name = modelsim
sim_tool_version = 6.6c
synth_tool_name = ise
synth_tool_version = 11.1
ip_tool_name = coregen
 
project_dir_depth_sim = 4
project_dir_depth_synth = 0
 
lib_root_dir = $RSP
build_dir = $RADIOHDL_BUILD_DIR
quartus_dir = /home/software/Altera/<synth_tool_version>
model_tech_altera_lib = /home/software/modelsim_altera_libs/<synth_tool_version>
model_tech_dir = /home/software/Mentor/<sim_tool_version>/modeltech
vsim_dir = <model_tech_dir>/linux_x86_64
modelsim_search_libraries =
/radiohdl/trunk/core/test/cdf_dir/tree/hdlbuildset/hdl_buildset_unb1.cfg
0,0 → 1,21
# Uniboardd 1 configuration
buildset_name = unb1
technology_names = ip_stratixiv
family_names = stratixiv
block_design_names = sopc
 
sim_tool_name = modelsim
sim_tool_version = 6.6c
synth_tool_name = quartus
synth_tool_version = 11.1sp2
 
lib_root_dir = $HDL
build_dir = $RADIOHDL_BUILD_DIR
quartus_dir = /home/software/Altera/<synth_tool_version>
model_tech_altera_lib = /home/software/modelsim_altera_libs/<synth_tool_version>
model_tech_dir = /home/software/Mentor/<sim_tool_version>/modeltech
vsim_dir = <model_tech_dir>/linux_x86_64
modelsim_search_libraries =
# stratixiv only
altera_ver lpm_ver sgate_ver altera_mf_ver altera_lnsim_ver stratixiv_ver stratixiv_hssi_ver stratixiv_pcie_hip_ver
altera lpm sgate altera_mf altera_lnsim stratixiv stratixiv_hssi stratixiv_pcie_hip
/radiohdl/trunk/core/test/cdf_dir/tree/hdllib/technology/test_hdllib.cfg
0,0 → 1,24
hdl_lib_name = technology
hdl_library_clause_name = technology_lib
hdl_lib_uses_synth =
hdl_lib_uses_sim =
hdl_lib_technology =
 
synth_files =
technology_pkg.vhd
$RADIOHDL_BUILD_DIR/<buildset_name>/modelsim/technology/technology_select_pkg.vhd
test_bench_files =
 
regression_test_vhdl =
# no self checking tb available yet
 
 
[modelsim_project_file]
modelsim_copy_files =
technology_select_pkg_<buildset_name>.vhd $RADIOHDL_BUILD_DIR/<buildset_name>/modelsim/technology/technology_select_pkg.vhd
 
 
 
[quartus_project_file]
quartus_copy_files =
technology_select_pkg_<buildset_name>.vhd $RADIOHDL_BUILD_DIR/<buildset_name>/quartus/technology/technology_select_pkg.vhd
/radiohdl/trunk/core/test/cdf_dir/tree/hdllib/util/test_hdllib.cfg
0,0 → 1,22
hdl_lib_name = util
hdl_library_clause_name = util_lib
hdl_lib_uses_synth = mm common common_mult technology
hdl_lib_uses_sim =
hdl_lib_technology =
 
synth_files =
src/vhdl/util_logic.vhd
src/vhdl/util_heater_pkg.vhd
src/vhdl/util_heater.vhd
 
test_bench_files =
tb/vhdl/tb_util_heater.vhd
 
regression_test_vhdl =
# no self checking tb available yet
 
[modelsim_project_file]
 
 
[quartus_project_file]
 
/radiohdl/trunk/core/test/cdf_dir/tree/hdltool/hdl_tool_altera.cfg
0,0 → 1,23
# configuration file for defining the altera installation on this system
altera_rootdir = ${ALTERA_DIR}/altera
altera_rootdir_override = ${ALTERA_DIR}/altera
niosdir = ${ALTERA_DIR}/nios2eds
 
# extension to the PATH variable
altera_paths =
<altera_rootdir>/bin
<niosdir>/bin
<niosdir>/bin/gnu/H-i686-pc-linux-gnu/bin
<niosdir>/bin/gnu/H-x86_64-pc-linux-gnu/bin
<niosdir>/sdk2/bin
 
[sopc]
sopc_paths =
sopc_environment_variables =
 
[qsys]
qsys_paths =
 
[user settings]
user_environment_variables =
 
/radiohdl/trunk/core/test/cdf_dir/tree/hdltool/hdl_tool_quartus.cfg
0,0 → 1,27
# configuration file for defining the quartus installation on this system
quartus_rootdir = ${QUARTUS_DIR}/quartus
quartus_rootdir_override = ${QUARTUS_DIR}/quartus
niosdir = ${QUARTUS_DIR}/nios2eds
 
# extension to the PATH variable
quartus_paths =
<quartus_rootdir>/bin
<niosdir>/bin
<niosdir>/bin/gnu/H-i686-pc-linux-gnu/bin
<niosdir>/bin/gnu/H-x86_64-pc-linux-gnu/bin
<niosdir>/sdk2/bin
 
[sopc]
sopc_paths =
<quartus_rootdir>/sopc_builder/bin
sopc_environment_variables =
sopc_kit_nios2 <niosdir>
 
[qsys]
qsys_paths =
<quartus_rootdir>/../qsys/bin
 
[user settings]
user_environment_variables =
altera_hw_tcl_keep_temp_files 1
 
/radiohdl/trunk/core/test/cdf_dir/wrong_files/dangling_test.txt
0,0 → 1,6
# Testfile for testing sections the CommonDictFile class
#
# First some keys with different spacing (spaces and tabs)
this is a lost value which causes an exception
 
global_key_1 = global_1
/radiohdl/trunk/core/test/cdf_dir/wrong_files/wrong_key_test.txt
0,0 → 1,6
# Testfile for testing the CommonDictFile class
#
# First some keys with different spacing (spaces and tabs)
 
key with spaces = should result in an exception
 
/radiohdl/trunk/core/test/t_hdl_configfile.py
0,0 → 1,147
import unittest
from configfile import *
from hdl_configfile import *
 
 
class Test_construction(unittest.TestCase):
"Class to the various ways of construction"
 
def test_wrong_filename(self):
"Test constructor with non-existing file"
self.assertRaises(ConfigFileException, ConfigFile, "/Is/Not/A/Valid/Directory")
 
def test_empty_dictfile(self):
"Test constructor with empty config file"
cfg = ConfigFile("./cdf_dir/empty_file/empty_dict.txt")
self.assertEqual(len(cfg.content), 0)
 
def test_comment_only_dictfile(self):
"Test constructor with comment-only config files"
cfg = ConfigFile("./cdf_dir/empty_file/comment_only_dict.txt")
self.assertEqual(len(cfg.content), 0)
 
 
class Test_key_value_spacing(unittest.TestCase):
"Class to the various kind of spacing between the keys and the values"
 
def test_key_value_spacing(self):
cfg = ConfigFile("./cdf_dir/correct_files/key_value_test.txt")
self.assertEqual(cfg.space_key_1, "value_1")
self.assertEqual(cfg.space_key_2, "value_2")
self.assertEqual(cfg.space_key_3, "value_3")
self.assertEqual(cfg.space_key_4, "value_4")
self.assertEqual(cfg.space_key_5, "value_5")
self.assertEqual(cfg.space_key_6, "value_6")
self.assertEqual(cfg.space_key_7, "value_7")
self.assertEqual(cfg.multi_key_1, "value10 value11 value12")
self.assertEqual(cfg.multi_key_2, "value20, value21, value22")
self.assertEqual(cfg.multi_key_3, "value30 value31 value32 value33")
self.assertEqual(cfg.multi_key_4, "value40 = value41 = value42")
self.assertEqual(cfg.tricky_key_1, "")
self.assertEqual(cfg.tricky_key_2, "tricky_value_2")
self.assertEqual(cfg.tricky_key_3, "")
self.assertEqual(cfg.section_headers, ['"my_section"'])
self.assertEqual(cfg.warning_key_1, "Be aware that multiline values can be tricky: this also belongs to previous key 'warning_key_1'")
# also test attribute access versus item access
self.assertEqual(cfg.multi_key_2, cfg['multi_key_2'])
print(cfg.content)
 
def test_sections(self):
cfg = ConfigFile("./cdf_dir/correct_files/section_test.txt")
self.assertEqual(cfg.global_key_1, "global_1"),
self.assertEqual(cfg.global_key_2, '[ "aap", "noot", "mies" ]'),
self.assertEqual(cfg.just_some_key_1, "section2 value1"),
self.assertEqual(cfg.just_some_key_2, "section2 value2"),
self.assertEqual(cfg.section_headers, ['section_1', 'section_2'])
 
def test_dangling_value(self):
"Test if a value without a key is detected"
self.assertRaises(ConfigFileException, ConfigFile, "./cdf_dir/wrong_files/dangling_test.txt")
 
def test_keys_with_spaces(self):
"Test if a key that contains spaces is detected"
self.assertRaises(ConfigFileException, ConfigFile, "./cdf_dir/wrong_files/wrong_key_test.txt")
 
 
class Test_reference_key_substitution(unittest.TestCase):
"Class to the the substitution of referenced keys."
 
def test_read_the_file(self):
cfg = ConfigFile("./cdf_dir/referenced_files/reference_test.txt")
self.assertEqual(cfg.early_ref_key1, "before <ref_key_2> is defined")
self.assertEqual(cfg.simple_ref_1, "a value with <ref_key_1>")
self.assertEqual(cfg.double_ref_1, "a value with twice <ref_key_1><ref_key_1>")
self.assertEqual(cfg.triple_key_1, "its here <ref_key_1> and here <ref_key_1> and here <ref_key_1>!!!")
self.assertEqual(cfg.triple_key_2, "its here <ref_key_2> and here <ref_key_1>!!!")
self.assertEqual(cfg.ref_only_key_1, "<ref_key_1>")
self.assertEqual(cfg.wrong_ref_1, "what will double brackets <<ref_key_2>> do?")
self.assertEqual(cfg.undefined_key_1, "reference to <non existing key>")
 
self.assertEqual(cfg.nested_key_1, "some_value")
self.assertEqual(cfg.nested_key_2, "<nested_key_1>")
self.assertEqual(cfg.nested_key_3, "<nested_key_2>")
self.assertEqual(cfg.reverse_nested_key_1, "<reverse_nested_key_2>")
self.assertEqual(cfg.reverse_nested_key_2, "<reverse_nested_key_3>")
self.assertEqual(cfg.reverse_nested_key_3, "some_value")
self.assertEqual(cfg.mutual_key_1, "<mutual_key_2>")
self.assertEqual(cfg.mutual_key_2, "<mutual_key_1>")
self.assertEqual(cfg.loop_key_1, "<loop_key_1>")
 
cfg.resolve_key_references()
 
self.assertEqual(cfg.early_ref_key1, "before multiple words in the value is defined")
self.assertEqual(cfg.simple_ref_1, "a value with single_reference")
self.assertEqual(cfg.double_ref_1, "a value with twice single_referencesingle_reference")
self.assertEqual(cfg.triple_key_1, "its here single_reference and here single_reference and here single_reference!!!")
self.assertEqual(cfg.triple_key_2, "its here multiple words in the value and here single_reference!!!")
self.assertEqual(cfg.ref_only_key_1, "single_reference")
self.assertEqual(cfg.wrong_ref_1, "what will double brackets <<ref_key_2>> do?")
self.assertEqual(cfg.undefined_key_1, "reference to <non existing key>")
 
self.assertEqual(cfg.nested_key_1, "some_value")
self.assertEqual(cfg.nested_key_2, "some_value")
self.assertEqual(cfg.nested_key_3, "some_value")
self.assertEqual(cfg.reverse_nested_key_1, "<reverse_nested_key_3>")
self.assertEqual(cfg.reverse_nested_key_2, "some_value")
self.assertEqual(cfg.reverse_nested_key_3, "some_value")
self.assertEqual(cfg.mutual_key_1, "<mutual_key_1>")
self.assertEqual(cfg.mutual_key_2, "<mutual_key_1>")
self.assertEqual(cfg.loop_key_1, "<loop_key_1>")
 
 
class Test_hdltool_file(unittest.TestCase):
"Class to test the hdltool class."
 
def test_read_good_hdltool_file(self):
tool = HdlTool("./cdf_dir/hdltool_files/hdl_tool_quartus.cfg")
self.assertEqual(tool.user_environment_variables, "altera_hw_tcl_keep_temp_files 1")
 
 
class Test_hdl_buildset_file(unittest.TestCase):
"Class to test the hdltool class."
 
def test_read_good_hdlbuildset_file(self):
buildset = HdlBuildset("./cdf_dir/hdlbuildset_files/hdl_buildset_unb1.cfg")
self.assertEqual(buildset.buildset_name, "unb1")
self.assertEqual(buildset.technology_names, "ip_stratixiv")
self.assertEqual(buildset.lib_root_dirs, "${RADIOHDL_WORK}/libraries ${RADIOHDL_WORK}/applications ${RADIOHDL_WORK}/boards")
 
def test_read_wrong_hdlbuildset_file(self):
self.assertRaises(ConfigFileException, HdlBuildset, "./cdf_dir/hdlbuildset_files/hdl_buildset_wrong.cfg")
 
 
class Test_hdllib_file(unittest.TestCase):
"Class to test the hdllib class."
 
def test_read_good_hdllib_file(self):
lib = HdlLib("./cdf_dir/hdllib_files/test_hdllib.cfg")
self.assertEqual(lib.hdl_lib_name, "technology")
self.assertEqual(lib.hdl_library_clause_name, "technology_lib")
self.assertEqual(lib.hdl_lib_technology, "")
 
def test_read_wrong_hdllib_file(self):
self.assertRaises(ConfigFileException, HdlLib, "./cdf_dir/hdllib_files/hdllib_wrong.cfg")
 
 
if __name__ == '__main__':
unittest.main(verbosity=2)
/radiohdl/trunk/core/test/t_hdl_configtree.py
0,0 → 1,70
import unittest
from configtree import *
from hdl_configtree import *
 
 
class Test_construction(unittest.TestCase):
"Class to the various ways of construction"
 
def test_wrong_filename(self):
"Test constructor with non-existing rootdir"
self.assertRaises(ConfigFileException, ConfigTree, "/Is/Not/A/Valid/Directory", "dict.txt")
 
def test_empty_dictfile(self):
"Test constructor with empty config file"
tree = ConfigTree("./cdf_dir/empty_file", "empty_dict.txt")
self.assertEqual(len(tree.configfiles), 1)
 
def test_comment_only_dictfile(self):
"Test constructor with comment-only config files"
tree = ConfigTree("./cdf_dir/empty_file", "comment_only_dict.txt")
self.assertEqual(len(tree.configfiles), 1)
 
 
class Test_tree_behaviour(unittest.TestCase):
"Class to test the 'tree' functionality of the class"
 
def test_tree_with_configfiles(self):
"Test constructor with a tree with configfiles all containing a 'key_1' label"
"that holds its relative path in the tree"
tree = ConfigTree("./cdf_dir/tree/cfgfile", "dict.txt")
for cfg in list(tree.configfiles.values()):
# print cfg.ID, cfg.content
expected_value = cfg.ID.replace("./cdf_dir/tree/cfgfile", "top_dir").replace("/dict.txt", "")
self.assertEqual(expected_value, cfg.key_1)
 
def test_hdllib_tree(self):
"Test if we can read in a tree with hdllib files."
tree = HdlLibTree("./cdf_dir/tree/hdllib", "test_hdllib.cfg")
self.assertEqual(len(tree.configfiles), 2)
util = tree.configfiles['util']
self.assertEqual(util.hdl_library_clause_name, 'util_lib')
self.assertEqual(util.synth_files, 'src/vhdl/util_logic.vhd src/vhdl/util_heater_pkg.vhd src/vhdl/util_heater.vhd')
technology = tree.configfiles['technology']
self.assertEqual(technology.hdl_library_clause_name, 'technology_lib')
self.assertEqual(technology.synth_files, 'technology_pkg.vhd $RADIOHDL_BUILD_DIR/<buildset_name>/modelsim/technology/technology_select_pkg.vhd')
 
def test_hdlbuildset_tree(self):
"Test if we can read in a tree with hdlbuildset files."
tree = HdlBuildsetTree("./cdf_dir/tree/hdlbuildset", "hdl_buildset_*.cfg")
self.assertEqual(len(tree.configfiles), 2)
rsp = tree.configfiles['rsp']
self.assertEqual(rsp.technology_names, 'ip_virtex4')
self.assertEqual(rsp.model_tech_altera_lib, '/home/software/modelsim_altera_libs/<synth_tool_version>')
unb1 = tree.configfiles['unb1']
self.assertEqual(unb1.technology_names, 'ip_stratixiv')
self.assertEqual(unb1.model_tech_altera_lib, '/home/software/modelsim_altera_libs/<synth_tool_version>')
 
def test_hdltool_tree(self):
"Test if we can read in a tree with hdltool files."
tree = HdlToolTree("./cdf_dir/tree/hdltool", "hdl_tool_*.cfg")
self.assertEqual(len(tree.configfiles), 2)
altera = tree.configfiles['./cdf_dir/tree/hdltool/hdl_tool_altera.cfg']
self.assertEqual(altera.altera_rootdir, "${ALTERA_DIR}/altera")
quartus = tree.configfiles['./cdf_dir/tree/hdltool/hdl_tool_quartus.cfg']
self.assertEqual(quartus.quartus_rootdir, "${QUARTUS_DIR}/quartus")
 
 
if __name__ == '__main__':
unittest.main(verbosity=2)
 
/radiohdl/trunk/core/check_config
0,0 → 1,167
#!/usr/bin/env python3
###############################################################################
#
# Copyright (C) 2018
# 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/>.
#
# $Id: generate_ip_libs.py 18842 2018-08-29 10:47:05Z overeem $
#
###############################################################################
 
import os
from os.path import expandvars, isfile, isdir
from argparse import ArgumentParser
from hdl_configfile import HdlBuildset, HdlTool
from configfile import ConfigFileException
 
 
def _do_basic_key_checking(cfgfile, indent=""):
# Check that all key references are solved
print("{}Checking references...".format(indent), end=' ')
all_refs_solved = cfgfile.resolve_key_references()
if all_refs_solved:
print("OK")
else:
print("\n{}ERROR: The following reference cannot be solved: {}".format(indent, cfgfile.unresolved_refs))
 
# Check that all key required keys contain values
print("{}Checking required keys...".format(indent), end=' ')
empty_keys = []
for key in cfgfile.required_keys:
if cfgfile.content[key] == "":
empty_keys.append(key)
if not empty_keys:
print("OK")
else:
print("\n{}ERROR: The following required keys don't have a value: {}".format(indent, empty_keys))
 
 
def expand_all_vars(dir_name):
_dirname = dir_name
while '$' in _dirname:
# print(_dirname)
_dirname = expandvars(_dirname)
return _dirname
 
 
def _check_quartus_configfile(cfgfile, tool_types):
# check required dirs
for required_dir in ["quartus_rootdir", "quartus_rootdir_override", "niosdir"]:
print(" Checking {}...".format(required_dir), end=' ')
 
if isdir(expand_all_vars(cfgfile[required_dir])):
print("OK")
else:
print("\n ERROR: path {} does not exist!".format(cfgfile[required_dir]))
 
# check _paths variables
required_paths = ["{}_paths".format(tool) for tool in tool_types]
for path_key in [key for key in list(cfgfile.content.keys()) if key.endswith("_paths")]:
paths = [expand_all_vars(pathname) for pathname in cfgfile[path_key].replace("\t", " ").split(" ") if pathname != ""]
print(" Checking {}...".format(path_key))
if not paths:
print(" no paths defined.")
else:
for path in paths:
if isdir(path):
print(" {}: OK".format(path))
else:
if path_key in required_paths:
print(" {}: DOES NOT EXIST!".format(path))
else:
print(" {}: does not exist but is not required".format(path))
 
# check IP generation
print(" Checking ip generation...")
ip_tools = [tool for tool in cfgfile.ip_tools.replace("\t", " ").split(" ") if tool != '']
for ip_tool in ip_tools:
opt_key = "{}_default_options".format(ip_tool)
if opt_key not in list(cfgfile.content.keys()):
print(" {}: key is MISSING!".format(opt_key))
else:
print(" {}: OK".format(opt_key))
 
# check environment variables
for envvar_key in [key for key in list(cfgfile.content.keys()) if key.endswith("_environment_variables")]:
items = [item for item in cfgfile[envvar_key].replace("\t", " ").split(" ") if item != ""]
print(" Checking {}...".format(envvar_key))
if not items:
print(" no variables defined.")
else:
if len(items) % 2 == 0:
print(" number of values is correct")
else:
print(" expected even number of values (not {})".format(len(items)))
 
 
if __name__ == '__main__':
 
keys = ['QUARTUS_DIR', 'ALTERA_DIR', 'MENTOR_DIR', 'MODELSIM_ALTERA_LIBS_DIR']
for key in keys:
if key not in os.environ:
print("{} not in os.environ".format(key))
 
# setup parser and parse the arguments.
argparser = ArgumentParser(description='Check to content of your hdl_buildset file and the corresponding hdl_tool file.')
argparser.add_argument('buildset', help="Filename like 'hdl_buildset_<buildset>.cfg'")
args = argparser.parse_args()
 
# construct full name of buildsetfile and read the file
full_buildsetfile_name = expandvars("${RADIOHDL_CONFIG}/hdl_buildset_%s.cfg" % (args.buildset))
print("Reading {}...".format(full_buildsetfile_name))
buildset_info = HdlBuildset(full_buildsetfile_name)
 
_do_basic_key_checking(buildset_info)
 
# check if lib_root_dirs exist
print("Checking defined library directories...", end=' ')
lib_dirs = [expand_all_vars(libdir) for libdir in buildset_info.lib_root_dirs.replace("\t", " ").split(" ")
if libdir != '']
wrong_dirs = []
for libdir in lib_dirs:
if not isdir(libdir):
wrong_dirs.append(libdir)
if not wrong_dirs:
print("OK")
else:
print("\nERROR: The following library rootdir do not exist: ", wrong_dirs)
 
# Check tools
subtoolnames = [subtool for subtool in buildset_info.block_design_names.replace("\t", " ").split(" ") if subtool != '']
toolnames = [buildset_info.synth_tool_name, buildset_info.sim_tool_name]
for toolname in toolnames:
print("Checking tool {}...".format(toolname), end=' ')
if toolname not in buildset_info.section_headers:
print("\n Warning: No sectionheader found.", end=' ')
tool_dir = "{}_dir".format(toolname)
if tool_dir not in list(buildset_info.content.keys()):
print("\n ERROR: Key {} is missing.".format(tool_dir), end=' ')
else:
os.environ[tool_dir.upper()] = buildset_info[tool_dir]
tool_configfile = expandvars("${RADIOHDL_CONFIG}/hdl_tool_%s.cfg" % (toolname))
if not isfile(tool_configfile):
print("\n Warning: File {} is missing!".format(tool_configfile), end=' ')
else:
try:
print("\n Reading {}...".format(tool_configfile))
tool_info = HdlTool(tool_configfile)
_do_basic_key_checking(tool_info, indent=" ")
except ConfigFileException as excp:
print("\n ERROR: File contains an error: {}".format(excp))
 
if toolname == "quartus":
_check_quartus_configfile(tool_info, toolnames+subtoolnames)
radiohdl/trunk/core/check_config Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/core/common_radiohdl.py =================================================================== --- radiohdl/trunk/core/common_radiohdl.py (nonexistent) +++ radiohdl/trunk/core/common_radiohdl.py (revision 4) @@ -0,0 +1,83 @@ + +import os +import inspect + + +def listify(obj): + """ + Can be used to force method input to a list. + """ + if isinstance(obj, list): + return obj + else: + return [obj] + + # try: + # return list(obj) + # except TypeError: + # return [obj] + + +def unlistify(obj): + """ + Converts 1-element list to x. + """ + # The isinstance() built-in function is recommended over the type() + # built-in function for testing the type of an object + if isinstance(obj, list): + if len(obj) == 1: + return obj[0] + return obj + + +def remove_from_list_string(list_str, item_str, sep=' '): + """Treat the string list_str as a list of items that are separated by sep and then + remove the specified item_str string from the list and return the list as a + string of items separated by sep. Also remove any duplicate items. + """ + _list_str = list_str.split(sep) + _list_str = unique(_list_str) + _list_str.remove(item_str) + return sep.join(_list_str) + + +def unique(in_list): + """ + Extract unique list elements (without changing the order like set() does) + """ + result = [] + for item in in_list: + if item in result: + continue + result.append(item) + return result + + +def method_name(caller_depth=0): + """ + Returns the name of the caller method. + """ + # Note: inspect.stack()[0][3] would return the name of this method. + return inspect.stack()[caller_depth+1][3] + + +def mkdir(path): + """Recursively create leave directory and intermediate directories if they do not already exist.""" + expand_path = os.path.expandvars(path) # support using environment variables in the file path + expand_path = os.path.expanduser(expand_path) # support using ~ in the file path + if not os.path.exists(expand_path): + os.makedirs(expand_path) + + +def expand_file_path_name(fpn, dir_path=''): + """ Expand environment variables in fpn to get file_path_name. + - if it is an absolute path return file_path_name else + - if it still has a local file path prepend dir_path to the file_path_name and return dir_path + file_path_name. + """ + file_path_name = os.path.expandvars(fpn) # support using environment variables in the file path + file_path_name = os.path.expanduser(file_path_name) # support using ~ in the file path + if os.path.isabs(file_path_name): + return file_path_name # use absolute path to file + + # derive path to file from the directory path and a directory path to the file + return os.path.join(os.path.expandvars(dir_path), file_path_name) Index: radiohdl/trunk/core/config_variable.py =================================================================== --- radiohdl/trunk/core/config_variable.py (nonexistent) +++ radiohdl/trunk/core/config_variable.py (revision 4) @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### +import sys +import os +from os.path import expandvars, dirname, basename +from argparse import ArgumentParser +from configfile import ConfigFile + +if __name__ == '__main__': + # setup parser and parse the arguments. + argparser = ArgumentParser(description='Options and arguments for showing hdl_config keys values') + argparser.add_argument('configfile', help="Filename like 'hdl_buildset_.cfg'") + argparser.add_argument('keyname', help="Name of the key to show the value of.") + args = argparser.parse_args() + + # resolve full name of configfile and force it to be explicit absolute or relative. + full_configfile_name = expandvars(args.configfile) + if full_configfile_name[0] != '/': + full_configfile_name = "./" + full_configfile_name + # read the file + cfg_info = ConfigFile(full_configfile_name) + cfg_info.resolve_key_references() + + print("{}\n".format(os.path.expandvars(cfg_info.get_value(args.keyname, must_exist=True)))) +
radiohdl/trunk/core/config_variable.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/core/configfile.py =================================================================== --- radiohdl/trunk/core/configfile.py (nonexistent) +++ radiohdl/trunk/core/configfile.py (revision 4) @@ -0,0 +1,291 @@ +############################################################################### +# +# Copyright (C) 2014-2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### + +"""Class for accessing the values of a configuration file of RadioHDL. + + The contents of the configuration file consist of a series of key - value + pairs. These key - value pairs are read from the file and kept in a + single dictionary of keys and values that can be accessed via .content. + + The format of the configuration file is similar to that of an ini file. For ini + files Python has the ConfigParser package, but that is not used here because + we need other parsing rules than the ones implemented in ConfigParser. + The parsing is done during the allocation of the class. + + Like an ini file the configurationfile can contain one or more sections. The + first section is common, has no header and always included. The specific + sections have a header that is marked by [section header]. The square brackets + '[' and ']' are used to identify the section header. If the 'section header' is + included in the argument 'sections' of the constructor then the keys of that + section will be included in the dictionary. + + 'sections' = None --> ignore fileSections to include all sections in + the dict. + 'sections' = [] --> empty list to include only the common first + section in the dict. + 'sections' = ['section header' ...] --> + dedicated list of one or more section header + strings to include these specific sections, + and also the common first section, in the + dict. + + The key and value string in the dictionary file are separated by '='. Hence + the '=' character can not be used in keys. The '=' can be used in values, + because subsequent '=' on the same line are part of the value. + Each key must start on a new line and may not contain whitespace. + The value string can extend over one or multiple lines. + + Comment in line is supported by preceding it with a '#'. The '#' and the + text after it on the line are stripped. The remainder of the line before + the '#' is still interpreted. + + Example: + # This is a comment section + # a key starts on a new line and extends until the '=' + # a key and its values are separated by '=' + + key=string # this is a comment and the key is still interpreted + key=string + key =string + key = string + + # a key with multiple values in its string + key = value value value + + # how the values are separated depends on the dictionary user + key = value, value, value + key = value value + + # a key with many values can have its string extend on multiple lines, + # the newline is replaced by a ' ' and any indent is removed + key = + value + value + value + + # empty lines and spaces are allowed + key = value +""" + +import os.path +import re +from collections import OrderedDict + +__all__ = ['CFG_COMMENT_CHAR', 'CFG_ASSIGNMENT_CHAR', 'ConfigFileException', 'ConfigFile'] + +CFG_COMMENT_CHAR = '#' +CFG_ASSIGNMENT_CHAR = '=' + + +class ConfigFileException(Exception): + "Exception class used in the ConfigFile class" + pass + + +class ConfigFile(object): + """ + :filename The full filename of the configfile. May contain environment variables. + :sections Optional. May contain a list of sections names. The key-value pairs in the other sections + are ignored. + :required_keys Optional. May contain a list of all keys that must exist in the configfile. If one or more + of those keys is missing in the configfile an exception is raised. + """ + _CONFIGFILE_ATTRIBUTES = ['_own_attr_', 'filename', 'location', 'sections', 'required_keys', + '__content__', 'section_headers', 'unresolved_refs', 'warnings'] + + def __init__(self, filename, sections=None, required_keys=[]): + """ + Store the dictionaries from all fileName files in rootDir. + :raise ConfigFileException + """ + full_filename = os.path.expanduser(os.path.expandvars(filename)) + if not os.path.isfile(full_filename): + raise ConfigFileException("configfile '%s' not found" % full_filename) + + # Crucial: define dict for storing our (simulated) attributes + self.__dict__['_own_attr_'] = {} + self.__content__ = OrderedDict() + + self.filename = os.path.basename(full_filename) + self.location = os.path.dirname(full_filename) + self.sections = sections + self.required_keys = required_keys + self.section_headers = [] + self.unresolved_refs = [] + self.warnings = '' + + # Try to read the configuration file. + self._read_file() + + # Check if all required keys are available + for required_key in self.required_keys: + if required_key not in self.__content__: + raise ConfigFileException("configfile '%s' missing key '%s'" % (filename, required_key)) + + def __getattr__(self, name): + """ + Catch read-access to attributes to fetch values from the content dictionary. + :raise AtttributeError + """ + if name in self._CONFIGFILE_ATTRIBUTES: + return self.__dict__['_own_attr_'][name] + + if name in self.__dict__['_own_attr_']['__content__']: + return self.__dict__['_own_attr_']['__content__'][name] + + print('%s object has no attribute %s' % (str(self.__class__.__name__), str(name))) + + if not hasattr(self, name): + raise AttributeError("%r object has no attribute %r" % (self.__class__.__name__, name)) + + return getattr(self, name) + + def __setattr__(self, name, value): + """ + Catch write-access to attributes to store values in the content dictionary. + :raise AtttributeError + """ + if name in self._CONFIGFILE_ATTRIBUTES: + self.__dict__['_own_attr_'][name] = value + elif name in self.__dict__['_own_attr_']['__content__']: + self.__dict__['_own_attr_']['__content__'][name] = value + else: + if not hasattr(self, name): + raise AttributeError("%r object has no attribute %r" % (self.__class__.__name__, name)) + setattr(self, name, value) + + def __getitem__(self, key): + "Also allow access to the information as item." + return self.__getattr__(key) + + def __setitem__(self, key, value): + "Also allow access to the information as item." + self.__setattr__(key, value) + + def _add_kv_pair(self, key, value, include_in_section): + """ + Internal function for adding a key-value pair in a neat way. + """ + # print("add_kv_pair: key={}, value={}\n".format(key, value)) + if not include_in_section: + return + if key.find(' ') > 0: + self.warnings += "Error: Key may not contain spaces: file '{}/{}', key '{}'"\ + .format(self.location, self.filename, key) + elif key != '': + self.__content__[key] = value.strip() # Update dict with key and value + + def _read_file(self): + """ + Read the dictionary information the filePathName file. + The dictionary will contain all key-value pairs as well as a + 'section_headers' key that contains all the sections found in the file + (regardless if the keys of that section where included in the dict or not). + :raise ConfigFileException + """ + include_section = True # default include all sections + key = '' + value = '' + linenr = 0 + with open("{}/{}".format(self.location, self.filename), 'r') as configfile: + for line in configfile: + linenr += 1 + ln = line.split(CFG_COMMENT_CHAR, 1)[0] # Strip comment from line + if len(ln) == 0: + continue + section_begin = ln.find('[') # Search for [section] header in this line + section_end = ln.find(']') + # section MUST start at first character of the line + if section_begin == 0 and section_end > 0: + self._add_kv_pair(key, value, include_section) # complete action on current key + key = '' + value = '' + # administrate new section + section_header = ln[1:section_end].strip() # new section header + self.section_headers.append(section_header) + include_section = True # default include this new section + if self.sections is not None: + if section_header not in self.sections: + include_section = False # skip this section + else: + key_end = ln.find(CFG_ASSIGNMENT_CHAR) # Search for key in this line + if key_end > 0: + self._add_kv_pair(key, value, include_section) # complete action on current key + key = ln[0:key_end].strip() # start with new key + value = ln[key_end+1:].strip() # and new value + else: + # no assignment char found, append this line to the current value + value += ' ' # replace newline by space to separate values + value += ln.strip() # append value + if value.strip() != '' and key == '': + self.warnings += "Warning: value without a key: file '{}/{}', line {} ({})"\ + .format(self.location, self.filename, linenr, value) + value = '' + self._add_kv_pair(key, value, include_section) # complete action on current key + + if self.warnings != '': + raise ConfigFileException(self.warnings) + + @property + def content(self): + # print(self.__content__) + "The content of the configfile as ordered dictionary." + return self.__content__ + + @property + def ID(self): + "Returns uniq ID (string) to identify this particular file. Fullfilename is used." + return "{}/{}".format(self.location, self.filename) + + def resolve_key_references(self): + """ + Replaces in all values the references to keys () with the value of that key. + Note that this operation is irreversable. + """ + ref_pattern = r"<(.+?)>" + prog = re.compile(ref_pattern) + # print('__content__={}'.format(self.__content__.items())) + # loop over all items of the dict + for key, value in list(self.__content__.items()): + # any reference in the value? + matchlist = list(set(prog.findall(value))) + for reference in matchlist: + if reference in list(self.__content__.keys()): + self.__content__[key] = re.sub("<{}>".format(reference), self.__content__[reference], value) + value = self.__content__[key] + else: + self.unresolved_refs.append("<{}>".format(reference)) + return len(self.unresolved_refs) == 0 + + def get_value(self, key, must_exist=False): + """ + Get the value of a key. If the key does not exist and that is allowed 'None' is returned, in case the + key should have been there an exception is raised. + """ + if key in self.__content__: + return self.__content__[key] + + if must_exist: + raise ConfigFileException("Key '%s' does not exist in configfile %s/%s." % (key, self.location, self.filename)) + + return None Index: radiohdl/trunk/core/configtree.py =================================================================== --- radiohdl/trunk/core/configtree.py (nonexistent) +++ radiohdl/trunk/core/configtree.py (revision 4) @@ -0,0 +1,123 @@ +############################################################################### +# +# Copyright (C) 2014-2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### +import sys +import os +import os.path +import re +from common_radiohdl import listify +from configfile import ConfigFile, ConfigFileException + + +class ConfigTree(object): + + def __init__(self, rootdirs, filename, sections=None): + """ + Collect the information of all configuration files that are present under the rootdirs. + """ + # Save construction arguments + self.rootdirs = listify(rootdirs) + self.filename = filename + self.sections = listify(sections) + + # Define result variables + self._configfiles = {} + + # search and read the config files. + self._read_all_configfiles() + if len(self._configfiles) == 0: + raise ConfigFileException("No '%s' files found in directory tree(s) '%s'." % (filename, rootdirs)) + + def _read_all_configfiles(self): + """ + Recursively search the rootdirs to find the configfiles and add the content to our admin. + """ + ref_pattern = self.filename.replace("*", "(.+?)") + name_mask = re.compile(ref_pattern+"$") + for rootdir in self.rootdirs: + for root, _, files in os.walk(rootdir): + for some_filename in files: + if name_mask.search(some_filename): + cfgfile = self._factory_constructor("{}/{}".format(root, some_filename)) + # check for duplicates + if cfgfile.ID in list(self._configfiles.keys()): + raise ConfigFileException("File with id '%s' found twice (at '%s' and '%s')" + % (cfgfile.ID, self._configfiles[cfgfile.ID].location, cfgfile.location)) + self._configfiles[cfgfile.ID] = cfgfile + + def _factory_constructor(self, full_filename): + """ + Function for returning the readin configfile. Derived classes *must* redefine this function. + """ + return ConfigFile(full_filename, sections=self.sections) + + @property + def configfiles(self): + return self._configfiles + + def remove_files_from_tree(self, files_to_remove): + """ + Remove the given list of configfiles from our configfile administration. + :raise KeyError when one of the files does not exist in our admin. + """ + for cfgfileID in files_to_remove: + self._configfiles.pop(cfgfileID) + + def limit_tree_to(self, files_to_keep): + """ + Limit the configfile collection in our admin to the ones given in the files_to_keep argument. + """ + for cfgfile in self._configfiles: + if cfgfile.ID not in files_to_keep: + self._configfiles.pop(cfgfile.ID) + + def get_key_values(self, key, configfiles=None, must_exist=False): + """ + Get the value of a key in all configfiles. If the key does not exist in a configfile and + the flag must_exist is False then None is added to the result list. When the flag must_exist + is true and the key is not defined in a configfile then an exception is raised. + The configfiles to search in may be limited to 'configfiles' otherwise the whole tree is used. + :return List of values + :raises ConfigFileException + """ + if configfiles is None: + configfiles = self._configfiles + + result = [] + for cfgfile in configfiles: + result.append(cfgfile.get_value(key, must_exist)) + return result + + def get_configfiles(self, key, values=None, user_configfiles=None): + """ + Get a list with all configfiles that contain the key with a value specified in values. + If values==None then a list of all configfiles is returned that contain the key. + The configfiles to search in may be restricted to the user_configfiles. + """ + file_list = list(self._configfiles.values()) if not user_configfiles else user_configfiles + + result = [] + for cfgfile in file_list: + if cfgfile not in result and key in cfgfile.content: + if values is None or cfgfile.content[key] in values: + result.append(cfgfile) + return result Index: radiohdl/trunk/core/export_config_variables.py =================================================================== --- radiohdl/trunk/core/export_config_variables.py (nonexistent) +++ radiohdl/trunk/core/export_config_variables.py (revision 4) @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### +import sys +import os +from os.path import expandvars, dirname, basename +from argparse import ArgumentParser +from configfile import ConfigFile + +if __name__ == '__main__': + # setup parser and parse the arguments. + argparser = ArgumentParser(description="Options and arguments for constructing an 'export' command for shell based on the content of a hdltool config file.") + argparser.add_argument('configfile', help="Filename like 'hdl_buildset_.cfg'") + argparser.add_argument('keynames', help="Name(s) of the key(s) to show the value of. Use comma to seperate multiple keys.") + argparser.add_argument('--varnames', help="Name(s) of the environment variable(s) the keys are mapped to. Default the keynames in capitals are used as environment variable names.") + argparser.add_argument('--is-group', help="The keynames refer to groups of environment variables that must be set.", + action="store_true") + argparser.add_argument('--optional', help="The keynames are optional. When them do not exist not error is generated", + action="store_true") + args = argparser.parse_args() + + # resolve full name of configfile and force it to be explicit absolute or relative. + full_configfile_name = expandvars(args.configfile) + if full_configfile_name[0] != '/': + full_configfile_name = "./" + full_configfile_name + # read the file + cfg_info = ConfigFile(full_configfile_name) + cfg_info.resolve_key_references() + + # parse the keys if they are no group references + if not args.is_group: + # setup key- and variable- names + keys = args.keynames.split(',') + if args.varnames: + env_vars = args.varnames.split(',') + if len(keys) != len(env_vars): + argparser.error("Number of variable names must match the number of keys.") + else: + env_vars = [] + for key in keys: + env_vars.append(key.upper()) + + # finally construct an export command for the key value pairs. + for idx, key in enumerate(keys): + print("export {}='{}'\n".format(env_vars[idx], + os.path.expandvars(cfg_info.get_value(key, must_exist=not(args.optional))))) + sys.exit(0) + + # Each key contains key-value pairs that must be exported in stead of a value + if args.varnames: + argparser.error("The option --varnames can not be used in combination with the option --is-group.") + + # print("args.keynames=%s" % str(args.keynames)) + keys = args.keynames.split(',') + for key in keys: + kv_pairs = cfg_info.get_value(key, must_exist=not(args.optional)) + # currently 'by definition' the value we got has the format: [ [...]] + # check we have an even number of items + # print("KV_pairs={}".format(kv_pairs)) + if kv_pairs is None: + continue + items = kv_pairs.split() + if len(items) % 2: + argparser.error("Key '{}' should contain an even number of items ({}).".format(key, items)) + for idx in range(0, len(items)//2, 2): + print("export {}='{}'\n".format(items[idx].upper(), os.path.expandvars(items[idx+1]))) +
radiohdl/trunk/core/export_config_variables.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/core/export_hdllib_variables.py =================================================================== --- radiohdl/trunk/core/export_hdllib_variables.py (nonexistent) +++ radiohdl/trunk/core/export_hdllib_variables.py (revision 4) @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### +import sys +import os +from os.path import expandvars, dirname, basename +from argparse import ArgumentParser +from hdl_configfile import HdlBuildset +from hdl_configtree import HdlLibTree + +if __name__ == '__main__': + # setup parser and parse the arguments. + argparser = ArgumentParser(description='Options and arguments for exporting hdllib keys values') + argparser.add_argument('buildset', help="Filename like 'hdl_buildset_.cfg'") + argparser.add_argument('libname', help="Name of the library to search in.") + argparser.add_argument('keys', help="Name of variable(s) to export.") + args = argparser.parse_args() + + # read the buildset file + full_buildsetfile_name = expandvars("${RADIOHDL_CONFIG}/hdl_buildset_%s.cfg" % (args.buildset)) + buildset_info = HdlBuildset(full_buildsetfile_name) + buildset_info.resolve_key_references() + + # find out where the hdllibs files are and read them in + root_dirs = [expandvars(rootdir) for rootdir in buildset_info.lib_root_dirs.replace("\t", " ").split(" ") + if rootdir != ''] + lib_tree = HdlLibTree(rootdirs=root_dirs, filename="hdllib.cfg") + for key in args.keys.split(','): + print("export {}='{}'\n".format( + key.lower(), + os.path.expandvars(lib_tree.configfiles[args.libname].get_value(key=key, must_exist=True)))) + +
radiohdl/trunk/core/export_hdllib_variables.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/core/generate_ip_libs =================================================================== --- radiohdl/trunk/core/generate_ip_libs (nonexistent) +++ radiohdl/trunk/core/generate_ip_libs (revision 4) @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2014-2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### + +import sys +import os +from os.path import expandvars, dirname, basename +from subprocess import call, STDOUT +from common_radiohdl import listify, mkdir +from argparse import ArgumentParser +from hdl_configfile import HdlBuildset, HdlTool +from hdl_configtree import HdlLibTree + + +def run_qmegawiz(buildset, outputdir, hdllib, vhdl_files, options): + """ + Run qmegawiz for the configuration in the given hdllib. + The script takes care that the exit code of qmegawiz is returned to the caller. + """ + extra_options = hdllib.get_value("qmegawiz_extra_options", False) + if not extra_options: + extra_options = "" + + error_code = 0 + for vhdl_file in vhdl_files: + script = '. ${RADIOHDL_GEAR}/quartus/set_quartus %s\n' % buildset + script += 'cd %s\n' % outputdir + script += 'cp %s/%s .\n' % (hdllib.location, vhdl_file) + script += 'set -o pipefail\n' + # echo line without 'Info:' to make sure grep it's exit code is 0 + script += '(echo " " ; qmegawiz %s %s %s 2>&1) | grep -iv Info:\n' \ + % (options, extra_options, vhdl_file) + script += 'exit_code=$?\n' + script += 'rm %s\n' % vhdl_file + script += 'exit $exit_code\n' + # execute script + print("compiling {} ... ".format(vhdl_file)) + return_code = call(script, stdout=None, stderr=STDOUT, shell=True) + # qmegawiz is very sloppy with it's exitcodes. We assume 0 is OK although this not always the case. :-( + if return_code == 0: + print("*** Generation (probably) OK\n") + else: + print("*** Error during generation, exitcode={}\n".format(return_code)) + error_code |= return_code + return error_code + + +def run_qsys(buildset, outputdir, hdllib, vhdl_files, options): + """ + Run qsys for the configuration in the given hdllib. + The script takes care that the exit code of qsys is returned to the caller. + """ + extra_options = hdllib.get_value("qsys-generate_extra_options", False) + if not extra_options: + extra_options = "" + + error_code = 0 + for vhdl_file in vhdl_files: + script = '. ${RADIOHDL_GEAR}/quartus/set_quartus %s\n' % buildset + script += 'cd %s\n' % outputdir + script += 'cp %s/%s .\n' % (hdllib.location, vhdl_file) + #script += 'cd %s\n' % hdllib.location + script += 'set -o pipefail\n' + # echo line without 'Info:' to make sure grep it's exit code is 0 + script += '(echo " " ; qsys-generate %s %s %s --search-path=%s --output-directory=%s 2>&1) | grep -iv Info:\n' \ + % (vhdl_file, options, extra_options, "outputdir,$", outputdir) + script += 'exit_code=$?\n' + script += 'rm %s\n' % vhdl_file + script += 'exit $exit_code\n' + # execute script + print("compiling {} ... , output-dir = {}".format(vhdl_file, outputdir)) + return_code = call(script, stdout=None, stderr=STDOUT, shell=True) + if return_code == 0: + print("*** Generation OK\n") + else: + print("*** Error during generation, exitcode={}\n".format(return_code)) + error_code |= return_code + return error_code + + +def run_quartus_sh(buildset, outputdir, hdllib, tcl_files, options): + """ + Run quartus_sh for the configuration in the given hdllib. + The script takes care that the exit code of quartus_sh is returned to the caller. + """ + extra_options = hdllib.get_value("quartus_sh_extra_options", False) + if not extra_options: + extra_options = "" + + error_code = 0 + for tcl_file in tcl_files: + script = '. ${RADIOHDL_GEAR}/quartus/set_quartus %s\n' % buildset + script += 'cd %s/%s\n' % (outputdir, hdllib.quartus_sh_ip_srcdir) + script += 'set -o pipefail\n' + # echo line without 'Info:' to make sure grep it's exit code is 0 + script += '(echo " " ; quartus_sh %s %s -t %s 2>&1) | grep -iv Info:\n' \ + % (options, extra_options, tcl_file) + script += 'exit_code=$?\n' + script += 'exit $exit_code\n' + # execute script + print("compiling {} ... ".format(tcl_file)) + return_code = call(script, stdout=None, stderr=STDOUT, shell=True) + if return_code == 0: + print("*** Generation OK\n") + else: + print("*** Error during generation, exitcode={}\n".format(return_code)) + error_code |= return_code + return error_code + + +def expand_all_vars(dir_name): + _dirname = dir_name + while '$' in _dirname: + # print(_dirname) + _dirname = expandvars(_dirname) + return _dirname + + +if __name__ == '__main__': + # setup parser and parse the arguments. + argparser = ArgumentParser(description='Generate the IP libraries for all technologies of the given buildset') + argparser.add_argument('buildset', help="Filename like 'hdl_buildset_.cfg'") + args = argparser.parse_args() + + # resolve full name of buildsetfile and force it to be explicit absolute or relative. + full_buildsetfile_name = os.path.join(os.getenv('RADIOHDL_CONFIG'), 'hdl_buildset_{}.cfg'.format(args.buildset)) + print('full_buildsetfile_name={}'.format(full_buildsetfile_name)) + if full_buildsetfile_name[0] != '/': + full_buildsetfile_name = "./" + full_buildsetfile_name + # read the file + buildset_info = HdlBuildset(full_buildsetfile_name) + buildset_info.resolve_key_references() + + # read in all hdllib configfiles + root_dirs = [expand_all_vars(rootdir) for rootdir in buildset_info.lib_root_dirs.replace("\t", " ").split(" ") + if rootdir != ''] + lib_tree = HdlLibTree(rootdirs=root_dirs, filename="hdllib.cfg", sections="generate_ip_libs") + + # read in the tool environment settings + tool_config_file = os.path.join(os.getenv('RADIOHDL_CONFIG'), 'hdl_tool_{}.cfg'.format(buildset_info.synth_tool_name)) + print('tool_config_file={}'.format(tool_config_file)) + tool_info = HdlTool(tool_config_file) + tool_info.resolve_key_references() + ip_tools = [tool for tool in tool_info.ip_tools.replace("\t", " ").split(" ") + if tool != ''] + + files_with_errors = [] + for technology in listify(buildset_info.technology_names): + print() + print("Generating IP libraries for technology:", technology) + # for all tools supported by quartus + for ip_tool in ip_tools: + tool_options = tool_info['{}_default_options'.format(ip_tool)] + ip_tool_key = "{}_ip_files".format(ip_tool) + # for all hdllib.cfg files found + for ip_lib_name in sorted(lib_tree.configfiles.keys())[::-1]: # TODO reverse order issue! + ip_lib_info = lib_tree.configfiles[ip_lib_name] + # if technology matches and there are files defined for the current tool + if ip_lib_info.hdl_lib_technology == technology and ip_tool_key in ip_lib_info.content: + # we have a match do the compilation + print("==> Processing {} with {}".format(ip_lib_info.ID, ip_tool)) + outputdir = os.path.join(os.getenv('RADIOHDL_BUILD_DIR'), '{}/{}/'.format(args.buildset, ip_tool)) + mkdir(outputdir) + vhdl_files = [name for name in ip_lib_info[ip_tool_key].replace("\t", " ").split(" ") + if name != ''] + if ip_tool == 'qmegawiz': + err_code = run_qmegawiz(args.buildset, outputdir, ip_lib_info, vhdl_files, tool_options) + elif ip_tool == 'qsys-generate': + err_code = run_qsys(args.buildset, outputdir, ip_lib_info, vhdl_files, tool_options) + + elif ip_tool == 'quartus_sh': + err_code = run_quartus_sh(args.buildset, outputdir, ip_lib_info, vhdl_files, tool_options) + else: + raise NameError("Hdllib file in %s contains a unknown tool (%s) for generating IP." % + (ip_lib_info.ID, ip_tool)) + if err_code: + files_with_errors.append(ip_lib_info.ID) + + if files_with_errors: + print("##### The following files had compile errors:") + print(" ", files_with_errors) + else: + print("+++++ No errors during compilation! +++++\n")
radiohdl/trunk/core/generate_ip_libs Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/core/generate_qsys =================================================================== --- radiohdl/trunk/core/generate_qsys (nonexistent) +++ radiohdl/trunk/core/generate_qsys (revision 4) @@ -0,0 +1,218 @@ +#!/usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2015 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +############################################################################### + +""" +Purpose: +. Generate an Altera QSYS file from a base QSYS file and user supplied list of regs. +Usage: +. python generate_qsys.py +""" + +from common import * + +def _to_element_str(reg_name, reg_base_addr): + """ + Returns a template XML 'element' filled in with reg_name and reg_base_addr. + """ + ELEMENT_TEMPLATE = """ + element HDL_REG_NAME.mem + { + datum baseAddress + { + value = HDL_REG_BASE_ADDR; + type = "long"; + } + datum _sortIndex + { + value = "8"; + type = "int"; + } + datum sopceditor_expanded + { + value = "0"; + type = "boolean"; + } + } + """ + return ELEMENT_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_BASE_ADDR', str(reg_base_addr)) + +def _to_interface_str(reg_name): + """ + Returns a template XML 'interface' filled in with reg_name. + """ + INTERFACE_TEMPLATE = """ + + + + + + + + """ + return INTERFACE_TEMPLATE.replace('HDL_REG_NAME', reg_name) + +def _append_to_modules_mid_str(modules_mid_str, reg_name, reg_base_addr, reg_end_addr): + """ + The modules_mid section contains one line (dataSlaveMapParam) for all start- and end addresses. + Append the start and end address of our register to this line. + """ + DATASLAVEMAPPARAM_TEMPLATE = "" + return modules_mid_str + DATASLAVEMAPPARAM_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_BASE_ADDR', str(reg_base_addr)).replace('HDL_REG_END_ADDR', str(reg_end_addr)) + +def _to_module_str(reg_name, reg_addr_w): + """ + Returns a template XML 'module' filled in with reg_name and reg_addr_w. + """ + MODULE_TEMPLATE = """ + + + + + + + """ + return MODULE_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_ADDR_W', str(reg_addr_w)) + +def _to_connection_str(reg_name, reg_base_addr): + """ + Returns a template XML 'connection' filled in with reg_name and reg_base_addr. + """ + CONNECTION_TEMPLATE = """ + + + + + + + + """ + return CONNECTION_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_BASE_ADDR', str(reg_base_addr)) + + +def generate_qsys(input_qsys, regs, output_filename): + """ + Creates an XML QSYS file (output_filename) from a base QSYS and a user-supplied list of registers to add (regs). + . regs = [ (reg_name, reg_base_addr, reg_span), .. ] + """ + # Read the base QSYS contents into a string + with open (input_qsys, "r") as base_qsys_file: + data=base_qsys_file.read() + + # We'll split the base QSYS string up in 5 sections. + # . Note that string.split() throws away the delimiter so we'll restore those later. + elements = data.split(']]>', 1)[0] + parameters = data.split(']]>', 1)[1].split('', 1)[0] + interfaces = data.split(']]>', 1)[1].split('', 1)[1].split('', 1)[1].split('', 1)[1].split('')[0] + modules_mid = data.split(']]>', 1)[1].split('', 1)[1].split('')[1].split(']]>',1)[0] + modules_tail = data.split(']]>', 1)[1].split('', 1)[1].split('')[1].split(']]>',1)[1] + connections = data.split(']]>', 1)[1].split('', 1)[1].split('\n' + \ + parameters + \ + '\n' + \ + interfaces + \ + '' + \ + modules_mid + \ + ']]>\n' + \ + modules_tail + \ + '\n' + + # Write the QSYS string to the output_file. + output_file = open(output_filename, "w") + output_file.write(qsys_str) + output_file.close() + + +################################################################################ +# Example main on execution of this file +################################################################################ +if __name__ == '__main__': + base_qsys_path = 'qsys_input.qsys' + regs = [('reg_my_peripheral', 16384, 3), ('reg_another_peripheral', 17152, 6)] + generate_qsys(base_qsys_path, regs, 'qsys_generated.qsys') Index: radiohdl/trunk/core/hdl_configfile.py =================================================================== --- radiohdl/trunk/core/hdl_configfile.py (nonexistent) +++ radiohdl/trunk/core/hdl_configfile.py (revision 4) @@ -0,0 +1,82 @@ +############################################################################### +# +# Copyright (C) 2014-2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### + +from configfile import ConfigFile + +__all__ = ['HdlTool', 'HdlBuildset', 'HdlLib'] + + +class HdlTool(ConfigFile): + """ + Class the represents the content of a hdltool_.cfg configuration file. + """ + _HDLTOOL_ATTRIBUTES = [] + + def __init__(self, filename, sections=None): + """ + Read the hdltoolset configuration file and check presence of the required keys. + :raise ConfigFileException + """ + super(HdlTool, self).__init__(filename, sections, required_keys=self._HDLTOOL_ATTRIBUTES) + + +class HdlBuildset(ConfigFile): + """ + Class the represents the content of a hdl_buildset_.cfg configuration file. + """ + _HDLBUILDSET_ATTRIBUTES = ['buildset_name', 'technology_names', 'family_names', 'block_design_names', + 'lib_root_dirs', 'sim_tool_name', 'sim_tool_version', + 'synth_tool_name', 'synth_tool_version'] + + def __init__(self, filename, sections=None): + """ + Read the hdlbuildset configuration file and check presence of the required keys. + :raise ConfigFileException + """ + super(HdlBuildset, self).__init__(filename, sections, required_keys=self._HDLBUILDSET_ATTRIBUTES) + + @property + def ID(self): + "Returns uniq ID (string) to identify this particular file." + return self.buildset_name + + +class HdlLib(ConfigFile): + """ + Class the represents the content of a hdllib.cfg configuration file. + """ + _HDLLIB_ATTRIBUTES = ['hdl_lib_name', 'hdl_library_clause_name', 'hdl_lib_uses_synth', + 'hdl_lib_uses_sim', 'hdl_lib_technology', 'synth_files', + 'test_bench_files'] + + def __init__(self, filename, sections=None): + """ + Read the hdllib configuration file and check presence of the required keys. + :raise ConfigFileException + """ + super(HdlLib, self).__init__(filename, sections, required_keys=self._HDLLIB_ATTRIBUTES) + + @property + def ID(self): + "Returns uniq ID (string) to identify this particular file." + return self.hdl_lib_name Index: radiohdl/trunk/core/hdl_configtree.py =================================================================== --- radiohdl/trunk/core/hdl_configtree.py (nonexistent) +++ radiohdl/trunk/core/hdl_configtree.py (revision 4) @@ -0,0 +1,75 @@ +############################################################################### +# +# Copyright (C) 2014-2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### + +from hdl_configfile import HdlTool, HdlBuildset, HdlLib +from configtree import ConfigTree + +__all__ = ['HdlToolTree', 'HdlBuildsetTree', 'HdlLibTree'] + + +class HdlToolTree(ConfigTree): + """ + Class the represents the content of a set of hdltool_.cfg configuration files. + """ + def __init__(self, rootdirs, filename, sections=None): + """ + Read the hdltool configuration files and stores them in this tree. + :raise ConfigFileException + """ + super(HdlToolTree, self).__init__(rootdirs, filename, sections) + + def _factory_constructor(self, full_filename): + "Function for returning the readin configfile." + return HdlTool(full_filename) + + +class HdlBuildsetTree(ConfigTree): + """ + Class the represents the content of a set of hdl_buildset_.cfg configuration files. + """ + def __init__(self, rootdirs, filename, sections=None): + """ + Read the hdlbuildset configuration files and stores them in this tree. + :raise ConfigFileException + """ + super(HdlBuildsetTree, self).__init__(rootdirs, filename, sections) + + def _factory_constructor(self, full_filename): + "Function for returning the readin configfile." + return HdlBuildset(full_filename) + + +class HdlLibTree(ConfigTree): + """ + Class the represents the content of a set of hdllib.cfg configuration files. + """ + def __init__(self, rootdirs, filename, sections=None): + """ + Reads the hdllib configuration files and stores them in this tree. + :raise ConfigFileException + """ + super(HdlLibTree, self).__init__(rootdirs, filename, sections) + + def _factory_constructor(self, full_filename): + "Function for returning the readin configfile." + return HdlLib(full_filename) Index: radiohdl/trunk/core/hdl_libraries_wizard.py =================================================================== --- radiohdl/trunk/core/hdl_libraries_wizard.py (nonexistent) +++ radiohdl/trunk/core/hdl_libraries_wizard.py (revision 4) @@ -0,0 +1,649 @@ +############################################################################### +# +# Copyright (C) 2014 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +############################################################################### + +"""HDL configuration for building simulation and synthesis targets. + + There should be one hdl_buildset_.cfg file per buildset somewhere in the + toolRootDir and at least one hdllib.cfg file somewhere in the libRootDir. + Every HDL library that is in the libRootDir can be found if it has a hdllib.cfg file. + Together the hdl_buildset_.cfg and hdllib.cfg files contain all the keys and + values that are sufficient to be able to build the targets for the HDL + library. The possible targets are: + + - compile to created the library binaries for simulation + - synthesize to created an image that can be loaded ion the FPGA + - verify VHDL test benches in simulation + - verify Python test cases via the MM control interface in simulation + - validate Python test cases on hardware via the MM control interface + + The contents of the cfg files consist of a series of key - value pairs + that are read into a dictionary as defined in hdl_configfile.py. Whether + the key is a valid key depends on the application that interprets the + dictionary. + + The methods can have the library dictionary or the library name as + argument. The default arguments are the self.libs.dicts and the + corresponding self.lib_names. The argument can be a list or a single value. + Similar the return can be a list or a single value, because a list of one + element is unlistified. + +""" + +import sys +import fnmatch +from os import listdir, walk, getenv +from os.path import expandvars, isabs, join, isfile +import shutil +from distutils.dir_util import copy_tree +from argparse import ArgumentParser +import collections +import common_radiohdl as cm +from configfile import ConfigFile +from hdl_configfile import HdlBuildset +from hdl_configtree import HdlLibTree + +__all__ = ['HdlLibrariesWizard'] + + +class HdlLibrariesWizard: + + def __init__(self, toolRootDir, toolFileName, libFileName='hdllib.cfg', libFileSections=None): + """Get tool dictionary info from toolRootDir and all HDL library dictionary info for it + + - self.tool.dicts = single dictionary that contains the tool info (only one tool dict in dicts list) + - self.libs.dicts = list of dictionaries that contains the info of the HDL libraries. + + The libRootDir parameter is defined in the hdl_buildset_.cfg file and is the root directory from where the hdllib.cfg + files are searched for. + + - self.lib_names = the library names of self.libs.dicts + + In parallel to the self.libs.dicts list of dictionaries a list of self.lib_names is created to be able to identify + a HDL library dict also by its library name. Iherefore it is important that the indexing of parallel lists remains + intact at all times. + + - self.technologyNames = the technologyNames parameter is defined in the hdl_buildset_.cfg file. All generic HDL + libraries and these technology specific libraries are kept. If self.technologyNames is: + [] : Keep all HDL libraries that were found. + ['ip_stratixiv', 'ip_arria10'] : The HDL libraries with a hdl_lib_technology that is not '' or does not match one of the technologies + in technologyNames are removed from the list of HDL library dictionaries. + + - self.removed_libs = contains the HDL library dicts that have been removed from self.libs.dicts, because they are for + a technology that is not within technologyNames. + + Keep lists of all unavailable library names that were found at the hdl_lib_uses_synth, hdl_lib_uses_ip, hdl_lib_uses_sim and + hdl_lib_include_ip keys in the self.libs.dicts: + + - self.unavailable_use_libs = self.unavailable_use_synth_libs + self.unavailable_use_ip_libs + self.unavailable_use_sim_libs + - self.unavailable_include_ip_libs + + Unavailable used libraries can be missing for a valid reason when they are not required (e.g. IP for another technology). Being able to + ignore missing libraries does require that the entities from these libraries are instantiated as components in the VHDL. The difference + between a removed library and an unavailable library is that for a removed library the HDL config information is still known, whereas + for an unavailable library it is not. Therefore the library clause names for referred but unavailable HDL libraries are disclosed at the + 'hdl_lib_disclose_library_clause_names' keys of the libraries that use them and kept in a dictionary: + + - self.disclosed_library_clause_names + + """ + print("HdlLibrariesWizard(toolRootDir=%s, toolFileName=%s, libFileName=%s, libFileSections=%s)" + % (toolRootDir, toolFileName, libFileName, libFileSections)) + self.toolRootDir = toolRootDir # TODO almost obsolete + + # read the buildset file. This file contains major information about paths, technologies, and so on + full_buildsetfile_name = "%s/%s" % (toolRootDir, toolFileName) + buildset_info = HdlBuildset(full_buildsetfile_name) + buildset_info.resolve_key_references() + self.buildset = buildset_info.content + + # HDL library config files + self.libRootDirs = [expandvars(rootdir) for rootdir in self.buildset['lib_root_dirs'].replace("\t", " ").split(" ") + if rootdir != ''] + self.libs = HdlLibTree(rootdirs=self.libRootDirs, + filename=libFileName, + sections=libFileSections) # library dict files + if len(self.libs.configfiles) == 0: + sys.exit('Error : No HDL library config files found') + print("Found %d hdllib files:" % len(self.libs.configfiles)) + + # Substitute key words occurring in hdllib.cfg files with their value. + self.substitute_key_words() + + self.familyNames = self.buildset['family_names'].split() + print("### self.familyNames = ", self.familyNames) + + # Keep the generic HDL libraries and remove those that do not match the specified IP technologies + self.technologyNames = self.buildset['technology_names'].split() + print("### self.technologyNames = ", self.technologyNames) + self.removed_libs = {} + + buildset_files = [] + for root, dirs, files in walk(join(getenv("RADIOHDL_GEAR"), 'config')): + for name in files: + if fnmatch.fnmatch(name, 'hdl_buildset_*.cfg'): + buildset_files.append(join(root, name)) + all_buildset_names = [bs[bs.rfind('_')+1:bs.rfind('.')] for bs in buildset_files] + # print(all_buildset_names) + + for cfglib_name in list(self.libs.configfiles.keys()): + techname = self.libs.configfiles[cfglib_name]['hdl_lib_technology'] + if (techname != '' and techname not in self.technologyNames): + # keep the removed libs we need the content of those libs later. + self.removed_libs[cfglib_name] = self.libs.configfiles[cfglib_name] + else: + # accept only projects for active buildset_name + # this method asume the hdl_lib_name is starting with the buildset_name and ending with + # the project name seperated by a '_' + # for example unb2b_ + for buildset_name in sorted(all_buildset_names)[::-1]: + if buildset_name == self.buildset['buildset_name']: + continue + if buildset_name+'_' in self.libs.configfiles[cfglib_name]['hdl_lib_name']: + # keep the removed libs we need the content of those libs later. + self.removed_libs[cfglib_name] = self.libs.configfiles[cfglib_name] + + self.libs.remove_files_from_tree(list(self.removed_libs.keys())) + print(len(self.removed_libs), "REMOVED LIBS:", sorted(self.removed_libs)) + + # Keep list of used HDL library names + self.lib_names = list(self.libs.configfiles.keys()) + print(len(self.lib_names), "KEPT LIBS:", sorted(self.lib_names)) + + # No need to check for duplicates since HdlLibTree did that already. + + # create dictionary of library names with library clause names that are disclosed at the 'hdl_lib_disclose_library_clause_names' keys. + self.disclosed_library_clause_names = {} + for lib in list(self.libs.configfiles.values()): + if lib.get_value('hdl_lib_disclose_library_clause_names'): + key_values = lib.get_value('hdl_lib_disclose_library_clause_names').split() + lib_name = key_values[0::2] + lib_clause_name = key_values[1::2] + lib_pairs = list(zip(lib_name, lib_clause_name)) + # No need to check for duplicate lib_names, because a dictionary cannot have duplicate keys + for lp in lib_pairs: + self.disclosed_library_clause_names[lp[0]] = lp[1] + # Check whether the used libraries from the self.libs.dicts keys indeed exist, otherwise remove them from the dictionary key + # string and add the used library name to the list of unavailable used library names and check that the library use clause + # name was disclosed at the 'hdl_lib_disclose_library_clause_names' key. In this way other methods do not have to check a + # used library does indeed exist. + self.unavailable_use_synth_libs = [] + self.unavailable_use_ip_libs = [] + self.unavailable_use_sim_libs = [] + self.unavailable_include_ip_libs = [] + for lib in list(self.libs.configfiles.values()): + use_synth_libs = [] + use_ip_libs = [] + use_sim_libs = [] + include_ip_libs = [] + if lib.get_value('hdl_lib_uses_synth'): + use_synth_libs = lib.get_value('hdl_lib_uses_synth').split() + if lib.get_value('hdl_lib_uses_ip'): + use_ip_libs += lib.get_value('hdl_lib_uses_ip').split() + if lib.get_value('hdl_lib_uses_sim'): + use_sim_libs += lib.get_value('hdl_lib_uses_sim').split() + if lib.get_value('hdl_lib_include_ip'): + include_ip_libs = lib.get_value('hdl_lib_include_ip').split() + for use_name in use_synth_libs: + if (use_name not in self.lib_names) and (use_name not in self.removed_libs): + lib['hdl_lib_uses_synth'] = cm.remove_from_list_string(lib['hdl_lib_uses_synth'], use_name) + self.unavailable_use_synth_libs.append(use_name) + if use_name not in list(self.disclosed_library_clause_names.keys()): + sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_synth' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name)) + for use_name in use_ip_libs: + if (use_name not in self.lib_names) and (use_name not in self.removed_libs): + lib['hdl_lib_uses_ip'] = cm.remove_from_list_string(lib['hdl_lib_uses_ip'], use_name) + self.unavailable_use_ip_libs.append(use_name) + if use_name not in list(self.disclosed_library_clause_names.keys()): + sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_ip' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name)) + for use_name in use_sim_libs: + if (use_name not in self.lib_names) and (use_name not in self.removed_libs): + lib['hdl_lib_uses_sim'] = cm.remove_from_list_string(lib['hdl_lib_uses_sim'], use_name) + self.unavailable_use_sim_libs.append(use_name) + if use_name not in list(self.disclosed_library_clause_names.keys()): + sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_sim' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name)) + for use_name in include_ip_libs: + if (use_name not in self.lib_names) and (use_name not in self.removed_libs): + lib['hdl_lib_include_ip'] = cm.remove_from_list_string(lib['hdl_lib_include_ip'], use_name) + self.unavailable_include_ip_libs.append(use_name) + if use_name not in list(self.disclosed_library_clause_names.keys()): + sys.exit("Error : Unavailable library %s at 'hdl_lib_include_ip' key in library %s is not disclosed at any 'hdl_lib_disclose_library_clause_names' key" % (use_name, lib_name)) + # remove all duplicates from the list + self.unavailable_use_synth_libs = cm.unique(self.unavailable_use_synth_libs) + self.unavailable_use_ip_libs = cm.unique(self.unavailable_use_ip_libs) + self.unavailable_use_sim_libs = cm.unique(self.unavailable_use_sim_libs) + self.unavailable_include_ip_libs = cm.unique(self.unavailable_include_ip_libs) # list of include_ip_use_libs + self.unavailable_use_libs = self.unavailable_use_synth_libs + self.unavailable_use_ip_libs + self.unavailable_use_sim_libs + self.unavailable_use_libs = cm.unique(self.unavailable_use_libs) # aggregate list of use_*_libs + + # The Key value pairs defined in hdltool.cfg can be used in hdllib.cfg files. See hdllib.cfg of technology library + def substitute_key_words(self): + for lib in list(self.libs.configfiles.values()): + for lib_key, lib_value in list(lib.content.items()): + for tool_key, tool_value in list(self.buildset.items()): + tool_key_string = '<%s>' % tool_key + if tool_key_string in lib_value: + lib[lib_key] = lib_value.replace(tool_key_string, tool_value) + + def check_library_names(self, check_lib_names, lib_names=None): + """Check that HDL library names exists within the list of library names, if not then exit with Error message. + The list of library names can be specified via the argument lib_names, or it defaults to the list of + self.lib_names of HDL libraries that were found in the toolRootDir for the libFileName of this object. + """ + if lib_names is None: + lib_names = self.lib_names + for check_lib_name in cm.listify(check_lib_names): + if check_lib_name not in cm.listify(lib_names): + sys.exit('Error : Unknown HDL library name %s found with %s' % (check_lib_name, cm.method_name())) + + def get_used_libs(self, build_type, lib_dict, arg_include_ip_libs=[]): + """Get the list of used HDL libraries from the lib_dict that this library directly depends on, so only at this HDL library hierachy level. + + Which libraries are actually used depends on the build_type. The build_type can be: + '' uses all libraries from 'hdl_lib_uses_synth', 'hdl_lib_uses_ip' and 'hdl_lib_uses_sim' in the lib_dict + 'sim' uses all libraries from 'hdl_lib_uses_synth', 'hdl_lib_uses_ip' and 'hdl_lib_uses_sim' in the lib_dict + 'synth' uses all libraries from 'hdl_lib_uses_synth' in the lib_dict and from 'hdl_lib_uses_ip' it only uses the IP + libraries that are mentioned in the local 'hdl_lib_include_ip' key or in the global arg_include_ip_libs + + The 'hdl_lib_uses_*' keys all appear locally in the same hdllib.cfg file. The 'hdl_lib_include_ip' key appears at this level or at + a higher level (design) library hdllib.cfg file to select which of all available 'hdl_lib_uses_ip' IP libraries will actually be + used in the design. The 'hdl_lib_include_ip' cannot appear in a lower level hdllib.cfg, because a lower level HDL library cannot + depend on a higher level HDL library. Therefore the IP libraries that need to be included from 'hdl_lib_uses_ip' will be known in + include_ip_libs. + """ + # Get local library dependencies + use_synth_libs = [] + use_ip_libs = [] + use_sim_libs = [] + include_ip_libs = [] + if 'hdl_lib_uses_synth' in lib_dict.content: + use_synth_libs = lib_dict['hdl_lib_uses_synth'].split() + if 'hdl_lib_uses_ip' in lib_dict.content: + use_ip_libs += lib_dict['hdl_lib_uses_ip'].split() + if 'hdl_lib_uses_sim' in lib_dict.content: + use_sim_libs += lib_dict['hdl_lib_uses_sim'].split() + if 'hdl_lib_include_ip' in lib_dict.content: + include_ip_libs = lib_dict['hdl_lib_include_ip'].split() + + # Append include_ip_libs from this level to the global list of arg_include_ip_libs + include_ip_libs = list(arg_include_ip_libs) + include_ip_libs + + # Get the actually use_libs for lib_dict + use_libs = use_synth_libs + use_ip_libs + use_sim_libs # default include all IP, so ignore include_ip_libs + if build_type == 'sim': + use_libs = use_synth_libs + use_ip_libs + use_sim_libs # for simulation included all IP, so ignore include_ip_libs + if build_type == 'synth': + use_libs = use_synth_libs + # For synthesis only keep the local use_ip_libs if it is mentioned in the global include_ip_libs. Vice versa also only + # include the global include_ip_libs if they appear in a local use_ip_libs, to avoid that an IP library that is mentioned + # in the global include_ip_libs gets included while it is not instantiated anywhere in the design. + for ip_lib in use_ip_libs: + if ip_lib in include_ip_libs: + use_libs += [ip_lib] + + # Remove any duplicate library names from the lists + use_libs = cm.unique(use_libs) + include_ip_libs = cm.unique(include_ip_libs) + + # Remove libraries that are in the removed technologies (use list() to take copy) + for use_name in list(use_libs): + if use_name in self.removed_libs: + use_libs.remove(use_name) + for use_name in list(include_ip_libs): + if use_name in self.removed_libs: + include_ip_libs.remove(use_name) + + return use_libs, include_ip_libs + + def derive_all_use_libs(self, build_type, lib_name, arg_include_ip_libs=[]): + """Recursively derive a complete list of all HDL libraries that the specified HDL lib_name library depends on, so from this + HDL library down the entire hierachy. + + The hdl_lib_uses_* key only needs to contain all libraries that are declared at the VHDL LIBRARY clauses of the + source files in this VHDL library. This derive_all_use_libs() will recursively find all deeper level VHDL libraries as well. + + The arg_include_ip_libs selects the IP library to keep from 'hdl_lib_uses_ip'. The include_ip_libs is passed on + through the recursion hierarchy via arg_include_ip_libs to ensure that the from the top level library down all + multiple choice IP libraries in 'hdl_lib_uses_ip' that need to be included are indeed included. The multiple choice IP + libraries in 'hdl_lib_uses_ip' that are not in include_ip_libs are excluded. + + Note: + . Only the generic HDL libraries and the technology specific libraries that match self.technologyNames are used, + because the other technology libraries have been removed from self.libs.dicts already at __init__() and from the + library dependency lists in get_used_libs() + . If Python breaks because recursion limit is reached, then two hdllib.cfg probably mutually use eachother which is + not allowed. + """ + # use list() to take local copy, to avoid next that default empty list argument arg_include_ip_libs=[] gets disturbed + include_ip_libs = list(arg_include_ip_libs) + if lib_name in self.lib_names: + all_use_libs = [lib_name] + lib_dict = self.libs.configfiles[lib_name] + use_libs, include_ip_libs = self.get_used_libs(build_type, lib_dict, include_ip_libs) + + for use_lib in use_libs: + if use_lib not in all_use_libs: + all_use_libs.append(use_lib) + # use recursion to include all used libs + all_use_libs += self.derive_all_use_libs(build_type, use_lib, include_ip_libs) + # remove all duplicates from the list + return cm.unique(all_use_libs) + else: + sys.exit('Error : Unknown HDL library name %s in %s()' % (lib_name, cm.method_name())) + + def derive_lib_order(self, build_type, lib_name, lib_names=None): + """Derive the dependency order for all HDL libraries in lib_names that HDL library lib_name depends on. + """ + if lib_names is None: + # At first entry derive the list of all HDL libraries that lib_name depends on + lib_names = self.derive_all_use_libs(build_type, lib_name) + + # Derive the order of all HDL libraries that lib_name depends on, start with the order of lib_names + lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names) + # use list() to take local copy to avoid modifying list order of self.lib_names which matches self.libs.dicts list order + lib_order = list(lib_names) + for lib_dict in lib_dicts: + lib_name = lib_dict['hdl_lib_name'] + use_libs, _ = self.get_used_libs('', lib_dict, []) + for use_lib in use_libs: + if use_lib in lib_names: + if lib_order.index(use_lib) > lib_order.index(lib_name): + lib_order.remove(use_lib) + lib_order.insert(lib_order.index(lib_name), use_lib) # move used lib to just before this lib + # use recursion to keep on reordering the lib_order until it is stable + if lib_names != lib_order: + lib_order = self.derive_lib_order(build_type, lib_name, lib_order) + return lib_order + + def get_lib_dicts_from_lib_names(self, lib_names=None): + """Get list the HDL libraries lib_dicts from list of HDL libraries lib_names and preseve the library order. + """ + if lib_names is None: + lib_names = self.lib_names + + # Cannot use: + # lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names) + # because then the order of self.libs.dicts is used + lib_dicts = [] + for lib_name in cm.listify(lib_names): + lib_dicts.append(self.libs.configfiles[lib_name]) + return lib_dicts + + def get_lib_names_from_lib_dicts(self, lib_dicts=None): + """Get list the HDL libraries lib_names from list of HDL libraries lib_dicts and preseve the library order. + """ + lib_names = self.libs.get_key_values('hdl_lib_name', lib_dicts) + return lib_names + + def get_tool_build_dir(self, build_type): + """Get the central tool build directory. + + The build_type can be: + 'sim' uses the 'sim_tool_name' key in the self.buildset + 'synth' uses the 'synth_tool_name' key in the self.buildset + When another name is used that name is used directly as toolname in the construction of the path. + + The function returns a tuple with the following four components: + - the absolute path to the central main build directory + - the buildset_name key value as subdirectory + - the toolname as subdirectory (derived from *_tool_name or the given value of 'build_type') + - project_deeper_subdir. See explanation below. + + The project file will be located in the build dir or at some levels deeper in the build dir. + These optional extra subdirectory levels allow for relative file reference from project file + location. This is useful to be able to keep memory initialisation files in the library build + directory that are referred to using some fixed ../../ path in the HDL code. + - project_deeper_subdir = '' when project_dir_depth_ = 0 or not in buildset + - project_deeper_subdir = 'p/' when project_dir_depth_ = 1 + - project_deeper_subdir = 'p/p/' when project_dir_depth_ = 2, + - project_deeper_subdir = 'p/p/p/' when project_dir_depth_ = 3, etc + """ + # Determine build_maindir + build_maindir = expandvars('${RADIOHDL_BUILD_DIR}') + if not isabs(build_maindir): + sys.exit('Error : The build_dir value must be an absolute path') + + # Determine build_buildset_dir + build_buildset_dir = self.buildset['buildset_name'] + + # Determine build_tooldir + tool_name_key = build_type + '_tool_name' + if tool_name_key in self.buildset: + build_tooldir = self.buildset[tool_name_key] + else: + build_tooldir = build_type + + # Determine project_deeper_subdir + project_dir_depth_key = 'project_dir_depth_' + build_type + if project_dir_depth_key not in self.buildset: + project_deeper_subdir = '' + else: + project_deeper_subdir = 'p/' * int(self.buildset[project_dir_depth_key]) + + return build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir + + def get_lib_build_dirs(self, build_type, lib_dicts=None): + """Get the subdirectories within the central tool build directory for all HDL libraries in the specified list of lib_dicts. + + The build_type can be: + 'sim' uses the 'sim_tool_name' key in the self.buildset + 'synth' uses the 'synth_tool_name' key in the self.buildset + + The build dir key value must be an absolute directory path. The lib build dir consists of + - the absolute path to the central main build directory + - the buildset_name key value as subdirectory + - the tool_name_key value as subdirectory + - the library name as library subdirectory + - zero or more extra subdirectory levels to allow for relative file reference from project file location + """ + if lib_dicts is None: + lib_dicts = list(self.libs.configfiles.values()) + build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type) + build_dirs = [] + for lib_dict in cm.listify(lib_dicts): + lib_name = lib_dict['hdl_lib_name'] + build_dirs.append(join(build_maindir, build_buildset_dir, build_tooldir, lib_name, project_deeper_subdir)) # central build main directory with subdirectory per library + return cm.unlistify(build_dirs) + + def create_lib_order_files(self, build_type, lib_names=None): + """Create the compile order file '_lib_order.txt' for all HDL libraries in the specified list of lib_names. + + The file is stored in the sim build directory of the HDL library. + The file is read by commands.do in Modelsim to avoid having to derive the library compile order in TCL. + """ + if lib_names is None: + lib_names = self.lib_names + + lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names) + for lib_dict in lib_dicts: + lib_name = lib_dict['hdl_lib_name'] + lib_order = self.derive_lib_order(build_type, lib_name) + file_name = lib_name + '_lib_order.txt' + file_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict) + cm.mkdir(file_path) + filePathName = join(file_path, file_name) + with open(filePathName, 'w') as fp: + for lib in lib_order: + fp.write('%s ' % lib) + print("Created {} lib-order files".format(len(lib_dicts))) + + # Methods to create sub directories at various levels in the build directory as defined in HDL tool config file + def create_sub_directory_in_build_main_dir(self, build_type, subdir_name): + """Create / in the central / directory + """ + build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type) + subdir_path = join(build_maindir, subdir_name) + cm.mkdir(subdir_path) + + def create_sub_directory_in_build_buildset_dir(self, build_type, subdir_name): + """Create / in the central // directory. + """ + build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type) + subdir_path = join(build_maindir, build_buildset_dir, subdir_name) + cm.mkdir(subdir_path) + + def create_sub_directory_in_build_tool_dir(self, build_type, subdir_name): + """Create / in the central /// directory. + """ + build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type) + subdir_path = join(build_maindir, build_buildset_dir, build_tooldir, subdir_name) + cm.mkdir(subdir_path) + + def create_sub_directory_in_build_lib_dir(self, build_type, subdir_name, lib_names=None): + """Create / in project local build directory / for all HDL libraries in the specified list of lib_names. + """ + if lib_names is None: + lib_names = self.lib_names + lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names) + for lib_dict in lib_dicts: + lib_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict) + subdir_path = join(lib_path, subdir_name) + cm.mkdir(subdir_path) + print("Created {} subdirectories".format(len(lib_dicts))) + + def copy_files(self, build_type, lib_names=None): + """ + Copy all source directories and source files listed at the _copy_files key. + The build_type selects the _copy_files key using the _tool_name key value + from the hdl_buildset_.cfg. + The _copy_files key expects a source and a destination pair per listed directory or file: + - The sources need to be specified with absolute path or relative to the HDL library source directory + where the hdllib.cfg is stored + - The destinations need to be specified with absolute path or relative to HDL library build directory + where the project file (e.g. mpf, qpf) gets stored + + Arguments: + - lib_names : zero or more HDL libraries + """ + if lib_names is None: + lib_names = self.lib_names + + lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names) + tool_name_key = build_type + '_tool_name' + tool_name_value = self.buildset[tool_name_key] + tool_name_copy_key = tool_name_value + '_copy_files' + lib_count = 0 + dir_count = 0 + file_count = 0 + for lib_dict in lib_dicts: + if tool_name_copy_key in lib_dict.content: + lib_count += 1 + lib_path = lib_dict.location + build_dir_path = self.get_lib_build_dirs(build_type, lib_dicts=lib_dict) + cm.mkdir(build_dir_path) + key_values = lib_dict[tool_name_copy_key].split() + sources = key_values[0::2] + destinations = key_values[1::2] + file_io = list(zip(sources, destinations)) + for fpn_io in file_io: + sourcePathName = cm.expand_file_path_name(fpn_io[0], lib_path) + destinationPath = cm.expand_file_path_name(fpn_io[1], build_dir_path) + # print("Copy '{}'' to '{}'".format(sourcePathName, destinationPath)) + if isfile(sourcePathName): + file_count += 1 + shutil.copy(sourcePathName, destinationPath) # copy file + else: + dir_count += 1 + copy_tree(sourcePathName, destinationPath) # copy directory tree (will create new destinationPath directory) + print("Copied {} files and {} directories for {} libraries".format(file_count, dir_count, lib_count)) + + +if __name__ == '__main__': + # Parse command line arguments + buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(expandvars('$RADIOHDL_CONFIG')) + if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")]) + argparser = ArgumentParser(description='Hdl_config shows several selections of all of your hdllib.cfg files.') + argparser.add_argument('buildset', help='choose buildset %s' % (buildsetSelect)) + argparser.add_argument('--toplib', default=None, required=False, help='top library to show more information about.') + args = argparser.parse_args() + + # check arguments + if args.buildset not in buildsetSelect: + print('buildset %s is not supported' % args.buildset) + print("Supported buildset are:", buildsetSelect) + sys.exit(1) + args.buildsetFile = 'hdl_buildset_' + args.buildset + '.cfg' + + # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories + hdl = HdlLibrariesWizard(toolRootDir=expandvars('${RADIOHDL_CONFIG}'), + toolFileName=args.buildsetFile, + libFileName='hdllib.cfg') + + print('#') + print('# HdlLibrariesWizard:') + print('#') + for libname in list(hdl.libs.configfiles.keys()): + print("\n", libname) + libinfo = hdl.libs.configfiles[libname] + for k, v in libinfo.content.items(): + print(k, '=', v) + print('') + + print('') + print('Library paths :') + for libname in list(hdl.libs.configfiles.keys()): + print(' ', hdl.libs.configfiles[libname].location) + + print('') + print('Library file names :"') + for libname in list(hdl.libs.configfiles.keys()): + print(' ', libname) + + print('') + print('Library section headers :') + for libname, libinfo in hdl.libs.configfiles.items(): + print(' %-52s : %s' % (libname, libinfo['section_headers'])) + + print('') + print('Build directories for simulation:') + for build_dir in hdl.get_lib_build_dirs('sim'): + print(' ', build_dir) + + print('') + print('Build directories for synthesis:') + for build_dir in hdl.get_lib_build_dirs('synth'): + print(' ', build_dir) + + print('') + print('Removed library names = \n', list(hdl.removed_libs.keys())) + + print('') + print("Unavailable library names in any 'hdl_lib_uses_synth' key = \n", hdl.unavailable_use_synth_libs) + print("Unavailable library names in any 'hdl_lib_uses_ip' key = \n", hdl.unavailable_use_ip_libs) + print("Unavailable library names in any 'hdl_lib_uses_sim' key = \n", hdl.unavailable_use_sim_libs) + print("Unavailable library names in any 'hdl_lib_uses_*' key = \n", hdl.unavailable_use_libs) + print('') + print("Unavailable library names in any 'hdl_lib_include_ip' key = \n", hdl.unavailable_include_ip_libs) + + print('') + print("Used library clause names that are explicitly disclosed at the 'hdl_lib_disclose_library_clause_names' keys:") + for key in list(hdl.disclosed_library_clause_names.keys()): + print(' %-52s : %s' % (key, hdl.disclosed_library_clause_names[key])) + + if args.toplib: + for build_type in ['sim', 'synth']: + print('') + print('derive_all_use_libs for %s of %s = \n' + % (build_type, args.toplib), hdl.derive_all_use_libs(build_type, args.toplib)) + print('') + print('derive_lib_order for %s of %s = \n' + % (build_type, args.toplib), hdl.derive_lib_order(build_type, args.toplib)) + + Index: radiohdl/trunk/core/hdl_raw_access.py =================================================================== --- radiohdl/trunk/core/hdl_raw_access.py (nonexistent) +++ radiohdl/trunk/core/hdl_raw_access.py (revision 4) @@ -0,0 +1,201 @@ +############################################################################### +# +# Copyright (C) 2014-2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id$ +# +############################################################################### + +import re +import os.path +from configfile import * +from configtree import ConfigTree + +__all__ = ['RawConfigFile', 'RawConfigTree'] + +""" +File that implements the configfile <-> configtree concept but this time with the +intention to modify the keys and/or values in those configfiles. So the content of +the configfiels is kept as raw as possible. +""" + + +class RawConfigFile(object): + """ + Class that holds the raw content of a configfile. To simplify the manipulation of the + content the file is internally stored as lines. + """ + def __init__(self, filename): + """ + Read the hdl configuration file and check presence of the required keys. + :raise ConfigFileException + """ + full_filename = os.path.expanduser(os.path.expandvars(filename)) + if not os.path.isfile(full_filename): + raise ConfigFileException("configfile '%s' not found" % full_filename) + + self.filename = full_filename + self.content = open(self.filename, 'r').readlines() + + @property + def ID(self): + "Returns uniq ID (string) to identify this particular file. Fullfilename is used." + return self.filename + + def _save_content(self, verbose=False): + """ + Write the content to the file. + """ + with open(self.filename, 'w') as fp: + fp.writelines(self.content) + + if verbose: + print(self.filename) + + def change_value(self, key, new_value, verbose): + """ + Change the value of the given key. The old value may be empty, be on one or multiple lines. + The new value may use \n characters to create a new multiline value. + """ + # Search the key in the lines + prog = re.compile("^{}[ \t]*{}".format(key, CFG_ASSIGNMENT_CHAR)) + for (linenr, line) in enumerate(self.content): + # search if line starts with this key + match = prog.search(line) + if not match: + continue + + # replace the value that is on this line with the whole new value + value_start = match.end() + line = line[0:value_start] + ' ' + new_value.replace("\\n", "\n") + "\n" + self.content[linenr] = line + + # to support removing old multiline values we have to skip lines until we find a + # sectionheader|other key|empty line or are at the end of the file + linenr += 1 + while linenr < len(self.content): + if not re.match(r"(\[[a-zA-Z0-9_]+\]|[a-zA-Z0-9_]+[ \t]*{}|^[ \t]*$)".format(CFG_ASSIGNMENT_CHAR), self.content[linenr]): + self.content.pop(linenr) + else: + break + + self._save_content(verbose) + break + + def append_key_value(self, key, value, verbose): + """ + Append the given key and value to the end of the configfile. + \n characters can be used both in the key and the value to start at a new line. + """ + self.content.append("{} {} {}\n".format(key.replace("\\n", "\n"), + CFG_ASSIGNMENT_CHAR, + value.replace("\\n", "\n"))) + self._save_content(verbose) + + def rename_key(self, old_key, new_key, verbose): + """ + Change the name of a key. + """ + # Search the key in the lines + prog = re.compile("^{}[ \t]*{}".format(old_key, CFG_ASSIGNMENT_CHAR)) + for (linenr, line) in enumerate(self.content): + # search if line starts with this old_key + match = prog.search(line) + if not match: + continue + + # change the name of the key + value_start = match.end() + line = "{} {}{}\n".format(new_key.replace("\\n", "\n"), CFG_ASSIGNMENT_CHAR, line[value_start:]) + self.content[linenr] = line + self._save_content(verbose) + break + + def remove_key(self, key, verbose): + """ + Remove a key and value pair from the dictfile. + """ + # difficulty here is that we can delete the lines immediately because the enumeration over the + # file content gets messed up. So we setup the variables first_line and last_line that mark + # the part of the list that has to be removed. After the enumeration we cut the lines. + + # First search the key in the lines + searching_key = True + last_line = len(self.content) + key_mask = re.compile(r"^{}[ \t]*{}".format(key, CFG_ASSIGNMENT_CHAR)) + end_of_value_mask = re.compile(r"(\[[a-zA-Z0-9_]+\]|[a-zA-Z0-9_]+[ \t]*{})".format(CFG_ASSIGNMENT_CHAR)) + for (linenr, line) in enumerate(self.content): + if searching_key: + # search if line starts with this key + match = key_mask.search(line) + if match: + first_line = linenr + searching_key = False + else: + # not searching for the key anymore, we now have to find the and of the value. + # to support removing old multiline values we have to skip lines until we find a + # sectionheader|other key or are at the end of the file + if not end_of_value_mask.match(self.content[linenr]): + continue + last_line = linenr + break + + del self.content[first_line:last_line] + self._save_content(verbose) + + def insert_key_at_linenr(self, new_key, new_value, linenumber, verbose): + """ + Insert a new key = value pair in the configfile at linenumber. The first line has number 1. + """ + if linenumber > len(self.content): + return self.append_key_value(new_key, new_value, verbose) + + # Read dict file into string and insert new key = value pair at insertLineNr + new_line = "{} {} {}\n".format(new_key.replace("\\n", "\n"), CFG_ASSIGNMENT_CHAR, new_value) + self.content.insert(linenumber-1, new_line) + self._save_content(verbose) + + def insert_key_value_before_key(self, new_key, new_value, before_key, verbose): + """ + Insert a new key = value pair in the configfile just before another key.. + """ + # Search the key in the lines + prog = re.compile("^{}[ \t]*{}".format(before_key, CFG_ASSIGNMENT_CHAR)) + for (linenr, line) in enumerate(self.content): + # search if line starts with this key + match = prog.search(line) + if not match: + continue + + return self.insert_key_at_linenr(new_key, new_value, linenr+1, verbose) + + +class RawConfigTree(ConfigTree): + """ + Class the represents the collection of 'raw content' configfiles. + """ + def __init__(self, rootdirs, filename, sections=None): + """ + Read the raw configuration files and stores them in this tree. + :raise ConfigFileException + """ + super(RawConfigTree, self).__init__(rootdirs, filename, sections) + + def _factory_constructor(self, full_filename): + "Function for returning the readin configfile." + return RawConfigFile(full_filename) Index: radiohdl/trunk/core/modelsim_config =================================================================== --- radiohdl/trunk/core/modelsim_config (nonexistent) +++ radiohdl/trunk/core/modelsim_config (revision 4) @@ -0,0 +1,472 @@ +#! /usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2014 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +############################################################################### + +"""HDL configuration for building Modelsim simulation targets. + + Usage: + > python ${RADIOHDL_GEAR}/oneclick/base/modelsim_config.py -t unb1 +""" + +import sys +import os.path +from os import listdir +from argparse import ArgumentParser +import common_radiohdl as cm +import hdl_libraries_wizard +from configfile import ConfigFile + + +class ModelsimConfig(hdl_libraries_wizard.HdlLibrariesWizard): + + def __init__(self, toolRootDir, buildsetFile, libFileName): + """Get Modelsim tool info from toolRootDir and all HDL library info from libRootDir. + + This class uses the default keys and the keys from the libFileSections in the libFileName config file. + + Arguments: + - toolRootDir : Root directory from where the hdl_buildset_.cfg file is searched for. + - buildsetFile : Default HDL tools configuration file name + - libFileName : Default HDL library configuration file name + + The libRootDir is defined in the hdl_buildset_.cfg file and is the root directory from where the hdllib.cfg + files are searched for. + + Files: + - hdl_buildset_.cfg : HDL tool configuration dictionary file. One central file per buildset. + + - hdllib.cfg : HDL library configuration dictionary file. One file for each HDL library. + + - modelsim_project_files.txt + The modelsim_project_files.txt file is a dictionary file with the list the Modelsim project files for all HDL + libraries that were found in the libRootDir. The keys are the library names and the values are the paths to the + corresponding modelsim project files. The modelsim_project_files.txt file is created by + create_modelsim_project_files_file() and is read by the TCL commands.do file in Modelsim. Creating the file in + Python and then reading this in TCL makes the commands.do much simpler. + + - .mpf : Modelsim project file for a certain HDL library based on the hdllib.cfg. The file is created by + create_modelsim_project_file(). + + - _lib_order.txt + The _lib_order.txt file contains the library compile order for a certain HDL library. The files are + created by create_lib_order_files() in the same build directory as where the Modelsim project file is stored. + The _lib_order.txt files are read by the TCL commands.do file in Modelsim. Creating the files in Python + and then reading them in TCL makes the commands.do much simpler. + """ + libFileSections = ['modelsim_project_file'] + hdl_libraries_wizard.HdlLibrariesWizard.__init__(self, toolRootDir, buildsetFile, libFileName, libFileSections) + + def read_compile_order_from_mpf(self, mpfPathName): + """Utility to read the compile order of the project files from an existing .mpf.""" + # read .mpf to find all project files + project_file_indices = [] + project_file_names = [] + with open(mpfPathName, 'r') as fp: + for line in fp: + words = line.split() + if words: + key = words[0] + if key.find('Project_File_') >= 0 and key.find('Project_File_P_') == -1: + project_file_indices.append(key[len('Project_File_'):]) + project_file_names.append(words[2]) + # read .mpf again to find compile order for the project files + compile_order = list(range(len(project_file_names))) + with open(mpfPathName, 'r') as fp: + for line in fp: + words = line.split() + if words: + key = words[0] + if key.find('Project_File_P_') >= 0: + project_file_index = project_file_indices.index(key[len('Project_File_P_'):]) + project_file_name = project_file_names[project_file_index] + k = words.index('compile_order') + k = int(words[k + 1]) + compile_order[k] = project_file_name + return compile_order + + def read_hdl_libraries_technology_file(self, technologyName, filePath=None): + """Read the list of technology HDL libraries from a file. + + Arguments: + - technologyName : refers to the hdl_libraries_.txt file + - filePath : path to hdl_libraries_.txt, when None then the file is + read in the default toolRootDir + """ + fileName = 'hdl_libraries_ip_' + technologyName + '.txt' # use fixed file name format + if filePath is None: + toolDir = os.path.expandvars('$RADIOHDL_BUILD_DIR') + toolSubDir = self.buildset['buildset_name'] + fileNamePath = os.path.join(toolDir, toolSubDir, fileName) # default file path + else: + fileNamePath = os.path.join(filePath, fileName) # specified file path + tech_dict = ConfigFile(fileNamePath).content + return tech_dict + + def create_modelsim_lib_compile_ip_files(self, lib_names=None): + """ + Create the '_lib_compile_ip.txt' file for all HDL libraries in the specified list of lib_names. + The file is stored in the sim build directory of the HDL library. + The file is read by commands.do in Modelsim to know which IP needs to be compiled before the library is compiled. + """ + if lib_names is None: + lib_names = self.lib_names + + count = 0 + lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names) + for lib_dict in lib_dicts: + if 'modelsim_compile_ip_files' in lib_dict.content: + count += 1 + compile_ip_files = lib_dict['modelsim_compile_ip_files'].split() + lib_name = lib_dict['hdl_lib_name'] + file_name = lib_name + '_lib_compile_ip.txt' + file_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict) + cm.mkdir(file_path) + filePathName = os.path.join(file_path, file_name) + with open(filePathName, 'w') as fp: + for fpn in compile_ip_files: + # Write the expanded file path name for _lib_compile_ip.txt so that it can be executed directly from its location in SVN using the Modelsim "do"-command in the commands.do. + # An alternative would be to write the basename, so only _lib_compile_ip.txt, but that would require copying the basename file to the mpf build directory + efpn = os.path.expandvars(fpn) + fp.write('%s ' % efpn) + print("Created {} compile-ip files".format(count)) + + def simulation_configuration(self, list_mode=False): + """Prepare settings for simulation configuration. + The output format is string or list, dependent on list_mode. + Return tuple of project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization. + """ + # project_sim_p_defaults + project_sim_p_defaults = 'Generics {} timing default -std_output {} -nopsl 0 +notimingchecks 0 selected_du {} -hazards 0 -sdf {} ok 1 -0in 0 -nosva 0 +pulse_r {} -absentisempty 0 -multisource_delay {} +pulse_e {} vopt_env 1 -coverage 0 -sdfnoerror 0 +plusarg {} -vital2.2b 0 -t default -memprof 0 is_vopt_flow 0 -noglitch 0 -nofileshare 0 -wlf {} -assertdebug 0 +no_pulse_msg 0 -0in_options {} -assertfile {} -sdfnowarn 0 -Lf {} -std_input {}' + + # project_sim_p_search_libraries + if list_mode: + project_sim_p_search_libraries = self.buildset['modelsim_search_libraries'].split() + else: + project_sim_p_search_libraries = '-L {}' + if 'modelsim_search_libraries' in self.buildset: + project_sim_p_search_libraries = '-L {' + for sl in self.buildset['modelsim_search_libraries'].split(): + project_sim_p_search_libraries += sl + project_sim_p_search_libraries += ' ' + project_sim_p_search_libraries += '}' + + # project_sim_p_otherargs + # Note: + # E.g. the vsim-8684 load warning does not occur when the simulation is loaded via double click, but it + # does occur when the simulation is relaoded via the command line, because in the command line history + # the +nowarn8684 is then for some reason not preserved by Modelsim. + otherargs = '' + otherargs = '+nowarn8684 +nowarn8683 -quiet' + otherargs = '+nowarn8684 +nowarn8683' + otherargs = '+nowarn8684 +nowarn8683 +nowarnTFMPC +nowarnPCDPC' # nowarn on verilog IP connection mismatch warnings + if list_mode: + project_sim_p_otherargs = otherargs.split() + else: + project_sim_p_otherargs = 'OtherArgs {' + otherargs + '}' + + # project_sim_p_optimization + project_sim_p_optimization = 'is_vopt_opt_used 2' # = when 'Enable optimization' is not selected in GUI + project_sim_p_optimization = 'is_vopt_opt_used 1 voptargs {OtherVoptArgs {} timing default VoptOutFile {} -vopt_keep_delta 0 -0in 0 -fvopt {} VoptOptimize:method 1 -vopt_00 2 +vopt_notimingcheck 0 -Lfvopt {} VoptOptimize:list .vopt_opt.nb.canvas.notebook.cs.page1.cs.g.spec.listbox -Lvopt {} +vopt_acc {} VoptOptimize .vopt_opt.nb.canvas.notebook.cs.page1.cs -vopt_hazards 0 VoptOptimize:Buttons .vopt_opt.nb.canvas.notebook.cs.page1.cs.g.spec.bf 0InOptionsWgt .vopt_opt.nb.canvas.notebook.cs.page3.cs.zf.ze -0in_options {}}' # = when 'Enable optimization' is selected in GUI for full visibility + + return project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization + + def create_modelsim_project_file(self, lib_names=None): + """ + Create the Modelsim project file for all technology libraries and RTL HDL libraries. + + Arguments: + - lib_names : one or more HDL libraries + + Library mapping: + - Technology libraries that are available, but not used are mapped to work. + - Unavailable libraries are also mapped to work. The default library clause name is + with postfix '_lib'. This is a best effort guess, because it is impossible to know the library clause name + for an unavailable library. If the best effort guess is not suitable, then the workaround is to create a + place holder directory with hdllib.cfg that defines the actual library clause name as it appears in the + VHDL for the unavailable HDL library. unavailable library names occur when e.g. a technology IP library + is not available in the toolRootDir because it is not needed, or it may indicate a spelling error. + """ + if lib_names is None: + lib_names = self.lib_names + + lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names) + print("SELF.BUILDSET=", self.buildset) + for lib_dict in lib_dicts: + # Open mpf + lib_name = lib_dict['hdl_lib_name'] + mpf_name = lib_name + '.mpf' + mpf_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict) + cm.mkdir(mpf_path) + mpfPathName = os.path.join(mpf_path, mpf_name) + with open(mpfPathName, 'w') as fp: + # Write [Library] section for all used libraries + fp.write('[Library]\n') + + # . map used vendor technology libs to their target directory + # for technologyName in self.technologyNames: + # tech_dict = self.read_hdl_libraries_technology_file(technologyName) + # for lib_clause, lib_work in tech_dict.items(): + # fp.write('%s = %s\n' % (lib_clause, lib_work)) + + for familyName in self.familyNames: + tech_dict = self.read_hdl_libraries_technology_file(familyName) + for lib_clause, lib_work in tech_dict.items(): + fp.write('%s = %s\n' % (lib_clause, lib_work)) + + # . not used vendor technology libs are not compiled but are mapped to work to avoid compile error when mentioned in the LIBRARY clause + for removed_lib in sorted(self.removed_libs): + fp.write('%s = work\n' % self.removed_libs[removed_lib]['hdl_library_clause_name']) + + # . unavailable used libs are not compiled but are mapped to work to avoid compile error when mentioned in the LIBRARY clause + for unavailable_use_name in sorted(self.unavailable_use_libs): + # if the unavailable library is not in the dictionary of disclosed unavailable library clause names, then assume that the library clause + # name has the default postfix '_lib'. + if unavailable_use_name in self.disclosed_library_clause_names: + fp.write('%s = work\n' % self.disclosed_library_clause_names[unavailable_use_name]) + else: + fp.write('%s_lib = work\n' % unavailable_use_name) + + # . all used libs for this lib_name + use_lib_names = self.derive_all_use_libs('sim', lib_name) + use_lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=use_lib_names) + use_lib_build_sim_dirs = self.get_lib_build_dirs('sim', lib_dicts=use_lib_dicts) + use_lib_clause_names = self.libs.get_key_values('hdl_library_clause_name', use_lib_dicts) + for lib_clause, lib_dir in zip(use_lib_clause_names, cm.listify(use_lib_build_sim_dirs)): + lib_work = os.path.join(lib_dir, 'work') + fp.write('%s = %s\n' % (lib_clause, lib_work)) + + # . work + fp.write('work = work\n') + + # . others modelsim default libs + model_tech_dir = os.path.expandvars(self.buildset['modelsim_dir']) + fp.write('others = %s\n' % os.path.join(model_tech_dir, 'modelsim.ini')) + + # Write [Project] section for all used libraries + fp.write('[Project]\n') + fp.write('Project_Version = 6\n') # must be >= 6 to fit all + fp.write('Project_DefaultLib = work\n') + fp.write('Project_SortMethod = unused\n') + + # - project files + synth_files = lib_dict['synth_files'].split() + test_bench_files = lib_dict['test_bench_files'].split() + project_files = synth_files + test_bench_files + if 'modelsim_compile_ip_files' in lib_dict.content: + compile_ip_files = lib_dict['modelsim_compile_ip_files'].split() + project_files += compile_ip_files + fp.write('Project_Files_Count = %d\n' % len(project_files)) + for i, fn in enumerate(project_files): + filePathName = cm.expand_file_path_name(fn, lib_dict.location) + fp.write('Project_File_%d = %s\n' % (i, filePathName)) + + project_file_p_defaults_hdl = 'vhdl_novitalcheck 0 group_id 0 cover_nofec 0 vhdl_nodebug 0 vhdl_1164 1 vhdl_noload 0 vhdl_synth 0 vhdl_enable0In 0 vlog_1995compat 0 last_compile 0 vhdl_disableopt 0 cover_excludedefault 0 vhdl_vital 0 vhdl_warn1 1 vhdl_warn2 1 vhdl_explicit 1 vhdl_showsource 0 cover_covercells 0 vhdl_0InOptions {} vhdl_warn3 1 vlog_vopt {} cover_optlevel 3 voptflow 1 vhdl_options {} vhdl_warn4 1 toggle - ood 0 vhdl_warn5 1 cover_noshort 0 compile_to work cover_nosub 0 dont_compile 0 vhdl_use93 2002 cover_stmt 1' + project_file_p_defaults_vhdl = 'file_type vhdl' + project_file_p_defaults_verilog = 'file_type verilog' + project_file_p_defaults_tcl = 'last_compile 0 compile_order -1 file_type tcl group_id 0 dont_compile 1 ood 1' + + project_folders = [] + offset = 0 + + nof_synth_files = len(synth_files) + if nof_synth_files > 0: + project_folders.append('synth_files') + for i in range(nof_synth_files): + + # Add file type specific settings + file_ext = synth_files[i].split('.')[-1] + if file_ext == 'vhd' or file_ext == 'vhdl': + project_file_p_defaults_file_specific = project_file_p_defaults_vhdl + elif file_ext == 'v': + project_file_p_defaults_file_specific = project_file_p_defaults_verilog + else: + print('\nERROR - Undefined file extension in synth_files:', lib_name, synth_files[i]) + sys.exit() + + fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % ( + offset+i, project_folders[-1], offset+i, project_file_p_defaults_hdl+' '+project_file_p_defaults_file_specific)) + offset = nof_synth_files + + nof_test_bench_files = len(test_bench_files) + if nof_test_bench_files > 0: + project_folders.append('test_bench_files') + for i in range(nof_test_bench_files): + + # Add file type specific settings + file_ext = test_bench_files[i].split('.')[-1] + if file_ext == 'vhd' or file_ext == 'vho' or file_ext == 'vhdl': + project_file_p_defaults_file_specific = project_file_p_defaults_vhdl + elif file_ext == 'v': + project_file_p_defaults_file_specific = project_file_p_defaults_verilog + else: + print('\nERROR - Undefined file extension in test_bench_files:', lib_name, test_bench_files[i]) + sys.exit() + + fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % ( + offset+i, project_folders[-1], offset+i, project_file_p_defaults_hdl+' '+project_file_p_defaults_file_specific)) + offset += nof_test_bench_files + + if 'modelsim_compile_ip_files' in lib_dict.content: + nof_compile_ip_files = len(compile_ip_files) + if nof_compile_ip_files > 0: + project_folders.append('compile_ip_files') + for i in range(nof_compile_ip_files): + fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % ( + offset + i, project_folders[-1], offset + i, project_file_p_defaults_tcl)) + offset += nof_compile_ip_files + + # - project folders + fp.write('Project_Folder_Count = %d\n' % len(project_folders)) + for i, fd in enumerate(project_folders): + fp.write('Project_Folder_%d = %s\n' % (i, fd)) + fp.write('Project_Folder_P_%d = folder {Top Level}\n' % i) + + # - simulation configurations + fp.write('Project_Sim_Count = %d\n' % len(test_bench_files)) + project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization = self.simulation_configuration() + for i, fn in enumerate(test_bench_files): + fName = os.path.basename(fn) + tbName = os.path.splitext(fName)[0] + fp.write('Project_Sim_%d = %s\n' % (i, tbName)) + for i, fn in enumerate(test_bench_files): + fName = os.path.basename(fn) + tbName = os.path.splitext(fName)[0] + fp.write('Project_Sim_P_%d = folder {Top Level} additional_dus work.%s %s %s %s %s\n' % ( + i, tbName, project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization)) + + # Write [vsim] section + fp.write('[vsim]\n') + fp.write('RunLength = 0 ps\n') + fp.write('resolution = 1fs\n') + fp.write('IterationLimit = 5000\n') # According to 'verror 3601' the default is 5000, typically 100 is enough, but e.g. the ip_stratixiv_phy_xaui_0 requires more. + fp.write('DefaultRadix = decimal\n') + print("Created {} project files".format(len(lib_dicts))) + + def create_modelsim_project_files_file(self, lib_names=None): + """Create file with list of the Modelsim project files for all HDL libraries. + + Arguments: + - lib_names : one or more HDL libraries + """ + fileName = 'modelsim_project_files.txt' # use fixed file name + build_maindir, build_buildsetdir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir('sim') + fileNamePath = os.path.join(build_maindir, build_buildsetdir, build_tooldir, fileName) # and use too build dir for file path + if lib_names is None: + lib_names = self.lib_names + with open(fileNamePath, 'w') as fp: + lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names) + mpf_paths = self.get_lib_build_dirs('sim', lib_dicts=lib_dicts) + for lib_name, mpf_path in zip(cm.listify(lib_names), cm.listify(mpf_paths)): + fp.write('%s = %s\n' % (lib_name, mpf_path)) + print("Created project file {}".format(fileNamePath)) + + +if __name__ == '__main__': + # Mode + # 0 = Create Modelsim mpf files for all hdllib.cfg + # 1 = Read compile order from mpf for a single and write itinto the hdllib.cfg. + # This is useful to avoid having to manually edit the compile order for an existing $UNB .mpf into the hdllib.cfg. + # The compile order is important for the synth_files that need to be in hierarchical order. The test_bench_files are typically + # independent so these may be put in alphabetical order. The compile order is read from the .mpf and saved in the + # hdllib.cfg. The hdllib.cfg still does need some manual editing to set the proper key and paths. + mode = 0 + + buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(os.path.expandvars('$RADIOHDL_CONFIG')) + if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")]) + # Parse command line arguments + argparser = ArgumentParser(description='Modelsim creates/updates all your modelsim environment(s).') + argparser.add_argument('buildset', help='choose buildset %s' % (buildsetSelect)) + argparser.add_argument('-v', '--verbosity', required=False, type=int, default=0, help='verbosity >= 0 for more info') + args = argparser.parse_args() + + # check arguments + if args.buildset not in buildsetSelect: + print('buildset %s is not supported' % args.buildset) + print("Supported buildset are:", buildsetSelect) + sys.exit(1) + args.buildsetFile = 'hdl_buildset_' + args.buildset + '.cfg' + + # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories + msim = ModelsimConfig(toolRootDir=os.path.expandvars('$RADIOHDL_CONFIG'), + buildsetFile=args.buildsetFile, + libFileName='hdllib.cfg') + + if mode == 0: + # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories + if args.verbosity >= 2: + print('#') + print('# ModelsimConfig:') + print('#') + print('') + print('HDL library paths that are found in %s:' % msim.libRootDirs) + for lib in sorted(msim.libs.configfiles.values()): + print(' ', lib.location) + + if args.verbosity >= 2: + print('') + print('Build directories for simulation:') + for sim_dir in msim.get_lib_build_dirs('sim'): + print(' ', sim_dir) + + print('') + print('Create library compile order files for simulation...') + msim.create_lib_order_files('sim') + # sys.exit(0) + + print('') + print('Create library compile ip files...') + msim.create_modelsim_lib_compile_ip_files() + + print('') + print('Create modelsim projects list file...') + msim.create_modelsim_project_files_file() + + print('') + print('Create sub directory in project dir for all HDL libraries that are found in %s...' % msim.libRootDirs) + msim.create_sub_directory_in_build_lib_dir('sim', 'mmfiles') # should match c_mmf_local_dir_path in mm_file_pkg.vhd + + print('') + print('Copy directories and files from HDL library source tree to project dir for all HDL libraries that are found in %s...' % msim.libRootDirs) + msim.copy_files('sim') + + print('') + print('Create Modelsim Project Files for technology %s and all HDL libraries in %s...' % (msim.technologyNames, msim.libRootDirs)) + msim.create_modelsim_project_file() + # sys.exit(0) + + if mode == 1: + # for lib_name in ['ado','ap','bf','bist','blp','bp','cdo','cim','cir','cp','cr','dc','eth','fmf','i2c','lvds','pfs','pft2','rcuh','ri','rsp','rsr','rsu','sens','serdes','si','st','tbbi','tdsh']: + for lib_name in ['tst']: + # Read compile order from existing .mpf + # First manually create rudimentary hdllib.cfg file for the library with lib name and clause filled in. Then run this script to get + # the ordered list of src and tb files. Then manualy edit the hdllib.cfg to put the files at the synth or sim key. + # mpfPathName = os.path.expandvars('$UNB/Firmware/designs/%s/build/synth/quartus/sopc_%s_sim/%s.mpf' % (lib_name, lib_name, lib_name)) + # mpfPathName = os.path.expandvars('$UNB/Firmware/modules/Lofar/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name)) + # mpfPathName = os.path.expandvars('$UNB/Firmware/modules/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name)) + mpfPathName = os.path.expandvars('$RSP/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name)) + compile_order = msim.read_compile_order_from_mpf(mpfPathName) + # Append the compile_order list to the lib_name dictionary hdllib.cfg file + lib_dict = msim.libs.get_configfiles(key='hdl_lib_name', values=lib_name) + lib_path = msim.libs.get_filePath(lib_dict) + filePathName = os.path.join(lib_path, 'hdllib.cfg') + print('') + print('Save modelsim compile order for', lib_name, 'in HDL library config file', filePathName) + msim.libs.append_key_to_dict_file(filePathName, 'files', compile_order)
radiohdl/trunk/core/modelsim_config Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/core/modify_configfiles =================================================================== --- radiohdl/trunk/core/modify_configfiles (nonexistent) +++ radiohdl/trunk/core/modify_configfiles (revision 4) @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2014-2018 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +# $Id: configfile_modifier.py 18609 2018-07-18 08:06:30Z overeem $ +# +############################################################################### + +""" +Interactive program to modify all configfiles found in the hierarchical directory +structure under the given top directory. +""" + +from argparse import ArgumentParser +from hdl_raw_access import RawConfigTree + +# Define a simple menu system that is based on a dict that contains the menu actions: +# the keys are the valid strings the user may enter +# the values are lists: the first element is the menu tekst, the second the function to call and +# the remaining elememts (if any) are the arguments to ask the user +# All arguments are stored in a kwargs structure and passed to the functions that is called. + + +def get_menu_choice(menu, title): + """ + Iterate over the menu dict, show the menu choices and ask for input till valid input is received. + """ + print("\n", title) + print("-" * len(title)) + input_ok = False + while not input_ok: + for key in sorted(menu.keys()): + print("{} {}".format(key, menu[key][0])) + choice = input("\n >>: ") + if choice not in list(menu.keys()): + print("ERROR: This input is not a valid menu choice. Try again.") + else: + input_ok = True + return menu[choice] + + +def execute_menu_line(line_spec, verbose): + """ + Given a menu line specification it asks the user for the specified arguments, stores the values in a + kwargs structure and finally call the specified function with this kwargs. + """ + print("\n--- {} ---".format(line_spec[0])) + nr_args = len(line_spec) - 2 + if nr_args < 0: + raise SyntaxError("Invalid formatted menuline definition: {}.\nNeed at least two items in the list".format(line_spec)) + if nr_args == 0: + return line_spec[1]() + # Iterate over the remaining items and get values for them + kwargs = {"verbose": verbose} + for spec_idx in range(2, len(line_spec)): + answer = input(line_spec[spec_idx].capitalize().replace("_", " ") + ": ") + kwargs[line_spec[spec_idx]] = answer + line_spec[1](**kwargs) + + +# ## Implementation of the menu commands +# Note: cleaner would to implement this with the Strategy pattern but we want to keep the code +# to be readable for everyone. ;-) +def change_value_of_key(**kwargs): + key = kwargs.pop("key") + new_value = kwargs.pop("new_value") + verbose = kwargs.pop("verbose") + global tree + for filename in sorted(tree.configfiles.keys()): + tree.configfiles[filename].change_value(key, new_value, verbose) + + +def append_key_value(**kwargs): + key = kwargs.pop("new_key") + new_value = kwargs.pop("new_value") + verbose = kwargs.pop("verbose") + global tree + for filename in sorted(tree.configfiles.keys()): + tree.configfiles[filename].append_key_value(key, new_value, verbose) + + +def insert_key_at_linenr(**kwargs): + new_key = kwargs.pop("new_key") + new_value = kwargs.pop("new_value") + linenumber = int(kwargs.pop("linenumber")) + verbose = kwargs.pop("verbose") + global tree + for filename in sorted(tree.configfiles.keys()): + tree.configfiles[filename].insert_key_at_linenr(new_key, new_value, linenumber, verbose) + + +def insert_key_value_before_key(**kwargs): + new_key = kwargs.pop("new_key") + new_value = kwargs.pop("new_value") + before_key = kwargs.pop("before_key") + verbose = kwargs.pop("verbose") + global tree + for filename in sorted(tree.configfiles.keys()): + tree.configfiles[filename].insert_key_value_before_key(new_key, new_value, before_key, verbose) + + +def rename_key(**kwargs): + old_key = kwargs.pop("old_key") + new_key = kwargs.pop("new_key") + verbose = kwargs.pop("verbose") + global tree + for filename in sorted(tree.configfiles.keys()): + tree.configfiles[filename].rename_key(old_key, new_key, verbose) + + +def remove_key(**kwargs): + key = kwargs.pop("key") + verbose = kwargs.pop("verbose") + global tree + for filename in sorted(tree.configfiles.keys()): + tree.configfiles[filename].remove_key(key, verbose) + + +def end_menu(): + global running + running = False + + +if __name__ == '__main__': + # setup parser and parse the arguments. + argparser = ArgumentParser(description='Options and arguments for modifying collections of configfiles.') + argparser.add_argument('filename', help="Filename like 'hdl_buildset_.cfg'") + argparser.add_argument('rootdir', help="Top directory to start the search for configfiles.") + argparser.add_argument('-v', '--verbose', help="Show more information on what happens.", action="store_true") + args = argparser.parse_args() + + tree = RawConfigTree(args.rootdir, args.filename) + print("Found {} configfiles in {}".format(len(tree.configfiles), args.rootdir)) + if args.verbose: + for filename in sorted(tree.configfiles.keys()): + print(filename) + + # define the menu including actions + # choice choice description function to call arguments to ask for + menu = {'1': ["Change value", change_value_of_key, "key", "new_value"], + '2': ["Append key", append_key_value, "new_key", "new_value"], + '3': ["Insert key at linenr", insert_key_at_linenr, "new_key", "new_value", "linenumber"], + '4': ["Insert key before other key", insert_key_value_before_key, "new_key", "new_value", "before_key"], + '5': ["Rename key", rename_key, "old_key", "new_key"], + '6': ["Remove key", remove_key, "key"], + 'q': ["Exit", end_menu] + } + + running = True + while running: + execute_menu_line(get_menu_choice(menu, "Menu for changing multiple configfiles"), args.verbose) +
radiohdl/trunk/core/modify_configfiles Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/core/qsys_input.qsys =================================================================== --- radiohdl/trunk/core/qsys_input.qsys (nonexistent) +++ radiohdl/trunk/core/qsys_input.qsys (revision 4) @@ -0,0 +1,669 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + qsys_input_onchip_memory2_0 + + + + + + + + + + + + + + + + + + + + + + + + + INTERACTIVE_ASCII_OUTPUT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SIMPLE_PERIODIC_INTERRUPT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cpu_0.jtag_debug_module + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + ]]> + + + + + ADDRESS_STALL 1 CELL_LEVEL_BACK_ANNOTATION_DISABLED 0 COMPILER_SUPPORT 1 DSP 1 DSP_SHIFTER_BLOCK 1 DUMP_ASM_LAB_BITS_FOR_POWER 1 EMUL 0 ENABLE_ADVANCED_IO_ANALYSIS_GUI_FEATURES 1 EPCS 1 ESB 0 FAKE1 0 FAKE2 0 FAKE3 0 FITTER_USE_FALLING_EDGE_DELAY 1 GENERATE_DC_ON_CURRENT_WARNING_FOR_INTERNAL_CLAMPING_DIODE 1 HARDCOPY 0 HAS_18_BIT_MULTS 1 HAS_ACE_SUPPORT 1 HAS_ADJUSTABLE_OUTPUT_IO_TIMING_MEAS_POINT 1 HAS_ADVANCED_IO_INVERTED_CORNER 1 HAS_ADVANCED_IO_POWER_SUPPORT 1 HAS_ADVANCED_IO_TIMING_SUPPORT 1 HAS_ALM_SUPPORT 1 HAS_ATOM_AND_ROUTING_POWER_MODELED_TOGETHER 0 HAS_AUTO_DERIVE_CLOCK_UNCERTAINTY_SUPPORT 1 HAS_AUTO_FIT_SUPPORT 1 HAS_BALANCED_OPT_TECHNIQUE_SUPPORT 1 HAS_BENEFICIAL_SKEW_SUPPORT 1 HAS_BITLEVEL_DRIVE_STRENGTH_CONTROL 1 HAS_BSDL_FILE_GENERATION 1 HAS_CGA_SUPPORT 1 HAS_CHECK_NETLIST_SUPPORT 1 HAS_CLOCK_REGION_CHECKER_ENABLED 1 HAS_CORE_JUNCTION_TEMP_DERATING 0 HAS_CROSSTALK_SUPPORT 0 HAS_CUSTOM_REGION_SUPPORT 1 HAS_DATA_DRIVEN_ACVQ_HSSI_SUPPORT 0 HAS_DDB_FDI_SUPPORT 0 HAS_DESIGN_ANALYZER_SUPPORT 1 HAS_DETAILED_IO_RAIL_POWER_MODEL 1 HAS_DETAILED_LEIM_STATIC_POWER_MODEL 0 HAS_DETAILED_LE_POWER_MODEL 1 HAS_DETAILED_ROUTING_MUX_STATIC_POWER_MODEL 0 HAS_DETAILED_THERMAL_CIRCUIT_PARAMETER_SUPPORT 1 HAS_DEVICE_MIGRATION_SUPPORT 1 HAS_DIAGONAL_MIGRATION_SUPPORT 0 HAS_EMIF_TOOLKIT_SUPPORT 1 HAS_FAMILY_VARIANT_MIGRATION_SUPPORT 0 HAS_FANOUT_FREE_NODE_SUPPORT 1 HAS_FAST_FIT_SUPPORT 1 HAS_FITTER_EARLY_TIMING_ESTIMATE_SUPPORT 1 HAS_FITTER_ECO_SUPPORT 1 HAS_FIT_NETLIST_OPT_RETIME_SUPPORT 1 HAS_FIT_NETLIST_OPT_SUPPORT 1 HAS_FORMAL_VERIFICATION_SUPPORT 1 HAS_FPGA_XCHANGE_SUPPORT 1 HAS_FSAC_LUTRAM_REGISTER_PACKING_SUPPORT 0 HAS_FULL_DAT_MIN_TIMING_SUPPORT 1 HAS_FULL_INCREMENTAL_DESIGN_SUPPORT 1 HAS_FUNCTIONAL_SIMULATION_SUPPORT 1 HAS_GLITCH_FILTERING_SUPPORT 1 HAS_HC_READY_SUPPORT 1 HAS_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 1 HAS_HOLD_TIME_AVOIDANCE_ACROSS_CLOCK_SPINE_SUPPORT 1 HAS_HSPICE_WRITER_SUPPORT 1 HAS_HSSI_POWER_CALCULATOR 1 HAS_IBISO_WRITER_SUPPORT 0 HAS_INCREMENTAL_DAT_SUPPORT 1 HAS_INCREMENTAL_SYNTHESIS_SUPPORT 1 HAS_IO_ASSIGNMENT_ANALYSIS_SUPPORT 1 HAS_IO_DECODER 1 HAS_IO_PLACEMENT_OPTIMIZATION_SUPPORT 1 HAS_IO_SMART_RECOMPILE_SUPPORT 0 HAS_JITTER_SUPPORT 1 HAS_JTAG_SLD_HUB_SUPPORT 1 HAS_LOGIC_LOCK_SUPPORT 1 HAS_MICROPROCESSOR 0 HAS_MIF_SMART_COMPILE_SUPPORT 1 HAS_MINMAX_TIMING_MODELING_SUPPORT 1 HAS_MIN_TIMING_ANALYSIS_SUPPORT 1 HAS_MUX_RESTRUCTURE_SUPPORT 1 HAS_NEW_HC_FLOW_SUPPORT 0 HAS_NEW_SERDES_MAX_RESOURCE_COUNT_REPORTING_SUPPORT 1 HAS_NEW_VPR_SUPPORT 1 HAS_NONSOCKET_TECHNOLOGY_MIGRATION_SUPPORT 1 HAS_NO_JTAG_USERCODE_SUPPORT 0 HAS_OPERATING_SETTINGS_AND_CONDITIONS_REPORTING_SUPPORT 1 HAS_PAD_LOCATION_ASSIGNMENT_SUPPORT 0 HAS_PARTIAL_RECONFIG_SUPPORT 0 HAS_PHYSICAL_NETLIST_OUTPUT 0 HAS_PHYSICAL_ROUTING_SUPPORT 1 HAS_PIN_SPECIFIC_VOLTAGE_SUPPORT 1 HAS_PLDM_REF_SUPPORT 1 HAS_POWER_ESTIMATION_SUPPORT 1 HAS_PRELIMINARY_CLOCK_UNCERTAINTY_NUMBERS 0 HAS_PRE_FITTER_FPP_SUPPORT 0 HAS_PRE_FITTER_LUTRAM_NETLIST_CHECKER_ENABLED 1 HAS_PVA_SUPPORT 1 HAS_RCF_SUPPORT 1 HAS_RCF_SUPPORT_FOR_DEBUGGING 0 HAS_RED_BLACK_SEPARATION_SUPPORT 0 HAS_RE_LEVEL_TIMING_GRAPH_SUPPORT 1 HAS_RISEFALL_DELAY_SUPPORT 1 HAS_SIGNAL_PROBE_SUPPORT 1 HAS_SIGNAL_TAP_SUPPORT 1 HAS_SIMULATOR_SUPPORT 0 HAS_SPLIT_IO_SUPPORT 1 HAS_SPLIT_LC_SUPPORT 1 HAS_SYNTH_FSYN_NETLIST_OPT_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_RETIME_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_SUPPORT 1 HAS_TECHNOLOGY_MIGRATION_SUPPORT 1 HAS_TEMPLATED_REGISTER_PACKING_SUPPORT 1 HAS_TIME_BORROWING_SUPPORT 0 HAS_TIMING_DRIVEN_SYNTHESIS_SUPPORT 1 HAS_TIMING_INFO_SUPPORT 1 HAS_TIMING_OPERATING_CONDITIONS 1 HAS_TIMING_SIMULATION_SUPPORT 1 HAS_TITAN_BASED_MAC_REGISTER_PACKER_SUPPORT 1 HAS_USER_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 1 HAS_USE_FITTER_INFO_SUPPORT 0 HAS_VCCPD_POWER_RAIL 1 HAS_VERTICAL_MIGRATION_SUPPORT 1 HAS_VIEWDRAW_SYMBOL_SUPPORT 0 HAS_VIO_SUPPORT 1 HAS_VIRTUAL_DEVICES 0 HAS_WYSIWYG_DFFEAS_SUPPORT 1 HAS_XIBISO_WRITER_SUPPORT 1 INCREMENTAL_DESIGN_SUPPORTS_COMPATIBLE_CONSTRAINTS 1 INSTALLED 0 IS_CONFIG_ROM 0 IS_DEFAULT_FAMILY 0 IS_HARDCOPY_FAMILY 0 LVDS_IO 1 M10K_MEMORY 0 M144K_MEMORY 1 M20K_MEMORY 0 M4K_MEMORY 0 M512_MEMORY 0 M9K_MEMORY 1 MLAB_MEMORY 1 MRAM_MEMORY 0 NOT_LISTED 0 NO_RPE_SUPPORT 0 NO_SUPPORT_FOR_LOGICLOCK_CONTENT_BACK_ANNOTATION 1 NO_SUPPORT_FOR_STA_CLOCK_UNCERTAINTY_CHECK 0 NO_TDC_SUPPORT 0 POSTFIT_BAK_DATABASE_EXPORT_ENABLED 1 POSTMAP_BAK_DATABASE_EXPORT_ENABLED 1 PROGRAMMER_SUPPORT 1 QFIT_IN_DEVELOPMENT 0 QMAP_IN_DEVELOPMENT 0 RAM_LOGICAL_NAME_CHECKING_IN_CUT_ENABLED 1 REPORTS_METASTABILITY_MTBF 1 REQUIRES_INSTALLATION_PATCH 0 REQUIRES_LIST_OF_TEMPERATURE_AND_VOLTAGE_OPERATING_CONDITIONS 1 RESERVES_SIGNAL_PROBE_PINS 0 RESOLVE_MAX_FANOUT_EARLY 1 RESOLVE_MAX_FANOUT_LATE 0 RESPECTS_FIXED_SIZED_LOCKED_LOCATION_LOGICLOCK 1 RESTRICTED_USER_SELECTION 0 RISEFALL_SUPPORT_IS_HIDDEN 0 SUPPORTS_ADDITIONAL_OPTIONS_FOR_UNUSED_IO 1 SUPPORTS_CRC 1 SUPPORTS_DIFFERENTIAL_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_DSP_BALANCING_BACK_ANNOTATION 0 SUPPORTS_GENERATION_OF_EARLY_POWER_ESTIMATOR_FILE 1 SUPPORTS_GLOBAL_SIGNAL_BACK_ANNOTATION 1 SUPPORTS_MAC_CHAIN_OUT_ADDER 1 SUPPORTS_RAM_PACKING_BACK_ANNOTATION 0 SUPPORTS_REG_PACKING_BACK_ANNOTATION 0 SUPPORTS_SIGNALPROBE_REGISTER_PIPELINING 1 SUPPORTS_SINGLE_ENDED_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_USER_MANUAL_LOGIC_DUPLICATION 1 TMV_RUN_CUSTOMIZABLE_VIEWER 1 TMV_RUN_INTERNAL_DETAILS 1 TMV_RUN_INTERNAL_DETAILS_ON_IO 0 TMV_RUN_INTERNAL_DETAILS_ON_IOBUF 1 TMV_RUN_INTERNAL_DETAILS_ON_LCELL 0 TMV_RUN_INTERNAL_DETAILS_ON_LRAM 0 TRANSCEIVER_3G_BLOCK 1 TRANSCEIVER_6G_BLOCK 1 USES_ACV_FOR_FLED 1 USES_ADB_FOR_BACK_ANNOTATION 1 USES_ASIC_ROUTING_POWER_CALCULATOR 0 USES_DATA_DRIVEN_PLL_COMPUTATION_UTIL 1 USES_DEV 1 USES_ICP_FOR_ECO_FITTER 0 USES_LIBERTY_TIMING 0 USES_POWER_SIGNAL_ACTIVITIES 1 USES_THIRD_GENERATION_TIMING_MODELS_TIS 1 USE_ADVANCED_IO_POWER_BY_DEFAULT 1 USE_ADVANCED_IO_TIMING_BY_DEFAULT 1 USE_BASE_FAMILY_DDB_PATH 0 USE_OCT_AUTO_CALIBRATION 0 USE_RISEFALL_ONLY 1 USE_SEPARATE_LIST_FOR_TECH_MIGRATION 1 USE_SINGLE_COMPILER_PASS_PLL_MIF_FILE_WRITER 1 USE_TITAN_IO_BASED_IO_REGISTER_PACKER_UTIL 1 WYSIWYG_BUS_WIDTH_CHECKING_IN_CUT_ENABLED 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: radiohdl/trunk/core/quartus_config =================================================================== --- radiohdl/trunk/core/quartus_config (nonexistent) +++ radiohdl/trunk/core/quartus_config (revision 4) @@ -0,0 +1,304 @@ +#! /usr/bin/env python3 +############################################################################### +# +# Copyright (C) 2014 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +############################################################################### + +"""HDL configuration for building Quartus synthesis targets. + + Usage: + > python ${RADIOHDL_GEAR}/core/quartus_config -t unb1 +""" + +import sys +from os import listdir +import os.path +from argparse import ArgumentParser +import common_radiohdl as cm +import hdl_libraries_wizard + + +class QuartusConfig(hdl_libraries_wizard.HdlLibrariesWizard): + + def __init__(self, toolRootDir, toolFileName, libFileName='hdllib.cfg'): + """Get Quartus tool info from toolRootDir and all HDL library info from libRootDir. + + This class uses the default keys and the keys from the libFileSections in the libFileName config file. + + Arguments: + - toolRootDir : Root directory from where the hdl_buildset_.cfg file is searched for. + - toolFileName : Default HDL tools configuration file name + - libFileName : Default HDL library configuration file name + + The libRootDir is defined in the hdl_buildset_.cfg file and is the root directory from where the hdllib.cfg + files are searched for. + + The technologyNames parameter is defined in the hdl_buildset_.cfg file. All generic HDL libraries and these + technology specific libraries are kept. + + Files: + - hdl_buildset_.cfg : HDL tool configuration dictionary file. One central file per buildset. + + - hdllib.cfg : HDL library configuration dictionary file. One file for each HDL library. + + - .qpf : Quartus project file (QPF) for a certain HDL library based on the hdllib.cfg. The file is created by + create_quartus_project_file(). + + - .qsf : Quartus settings file (QSF) for a certain HDL library based on the hdllib.cfg. The file is created by + create_quartus_settings_file(). There is one QSF per Quartus synthesis project. + """ + print("QuartusConfig(toolRootDir=%s, toolFileName=%s, libFileName=%s)" % (toolRootDir, toolFileName, libFileName)) + libFileSections = ['quartus_project_file'] + hdl_libraries_wizard.HdlLibrariesWizard.__init__(self, toolRootDir, toolFileName, libFileName, libFileSections) + + def create_quartus_ip_lib_file(self, lib_names=None): + """Create the Quartus IP file _lib.qip for all HDL libraries. The .qip file contains the list of files that are given + by the synth_files key and the quartus_*_file keys. + + Note: + . Use post fix '_lib' in QIP file name *_lib.qip to avoid potential conflict with *.qip that may come with the IP. + . The HDL library *_lib.qip files contain all files that are listed by the synth_files key. Hence when these qip files are included then + the Quartus project will analyse all files even if there entity is not instantiated in the design. This is fine, it is unnecessary + to parse the hierarchy of the synth_top_level_entity VHDL file to find and include only the source files that are actually used. + + Arguments: + - lib_names : one or more HDL libraries + """ + if lib_names is None: + lib_names = self.lib_names + + lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names) + for lib_dict in lib_dicts: + # Open qip + lib_name = lib_dict['hdl_lib_name'] + qip_name = lib_name + '_lib.qip' + qip_path = self.get_lib_build_dirs('synth', lib_dicts=lib_dict) + cm.mkdir(qip_path) + qipPathName = cm.expand_file_path_name(qip_name, qip_path) + with open(qipPathName, 'w') as fp: + if lib_dict.get_value('synth_files'): + fp.write('# synth_files\n') + synth_files = lib_dict['synth_files'].split() + for fn in synth_files: + filePathName = cm.expand_file_path_name(fn, lib_dict.location) + + file_ext = fn.split('.')[-1] + if file_ext == 'vhd' or file_ext == 'vhdl': + file_type = 'VHDL_FILE' + elif file_ext == 'v': + file_type = 'VERILOG_FILE' + else: + print('\nERROR - Undefined file extension in synth_files:', fn) + sys.exit() + + fp.write('set_global_assignment -name %s %s -library %s\n' % (file_type, filePathName, lib_name + '_lib')) + + if lib_dict.get_value('quartus_vhdl_files'): + fp.write('\n') + fp.write('# quartus_vhdl_files\n') + quartus_vhdl_files = lib_dict['quartus_vhdl_files'].split() + for fn in quartus_vhdl_files: + filePathName = cm.expand_file_path_name(fn, lib_dict.location) + + file_ext = fn.split('.')[-1] + if file_ext == 'vhd' or file_ext == 'vhdl': + file_type = 'VHDL_FILE' + elif file_ext == 'v': + file_type = 'VERILOG_FILE' + else: + print('\nERROR - Undefined file extension in quartus_vhdl_files:', fn) + sys.exit() + + fp.write('set_global_assignment -name VHDL_FILE %s -library %s\n' % (filePathName, lib_name + '_lib')) + + if lib_dict.get_value('quartus_qip_files'): + fp.write('\n') + fp.write('# quartus_qip_files\n') + quartus_qip_files = lib_dict['quartus_qip_files'].split() + for fn in quartus_qip_files: + filePathName = cm.expand_file_path_name(fn, lib_dict.location) + fp.write('set_global_assignment -name QIP_FILE %s\n' % filePathName) + + if lib_dict.get_value('quartus_tcl_files'): + fp.write('\n') + fp.write('# quartus_tcl_files\n') + quartus_tcl_files = lib_dict['quartus_tcl_files'].split() + for fn in quartus_tcl_files: + filePathName = cm.expand_file_path_name(fn, lib_dict.location) + fp.write('set_global_assignment -name SOURCE_TCL_SCRIPT_FILE %s\n' % filePathName) + + if lib_dict.get_value('quartus_sdc_files'): + fp.write('\n') + fp.write('# quartus_sdc_files\n') + quartus_sdc_files = lib_dict['quartus_sdc_files'].split() + for fn in quartus_sdc_files: + filePathName = cm.expand_file_path_name(fn, lib_dict.location) + fp.write('set_global_assignment -name SDC_FILE %s\n' % filePathName) + print("Created {} .qip files".format(len(lib_dicts))) + + def create_quartus_project_file(self, lib_names=None): + """Create the Quartus project file (QPF) for all HDL libraries that have a toplevel entity key synth_top_level_entity. + + Note: + . Default if the synth_top_level_entity key is defined but left empty then the top level entity has the same name as the lib_name in hdl_lib_name. + Otherwise synth_top_level_entity can specify another top level entity name in the library. Each HDL library can only have one Quartus project + file + . The project revision has the same name as the lib_name and will result in a .sof FPGA image file. + . For each additional revision a subdirectory can be used. + This subdirectory can be named 'revisions/' and lists a number of revisions as subdirectories. Each revision will have a separate hdllib.cfg file and a + .vhd file with the toplevel entity. The toplevel .vhd file specifies the for the revision in the generics. + + Arguments: + - lib_names : one or more HDL libraries + """ + if lib_names is None: + lib_names = self.lib_names + lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names) + syn_dicts = self.libs.get_configfiles(key='synth_top_level_entity', values=None, user_configfiles=lib_dicts) + for syn_dict in syn_dicts: + # Open qpf for each HDL library that has a synth_top_level_entity + lib_name = syn_dict['hdl_lib_name'] + qpf_name = lib_name + '.qpf' + qpf_path = self.get_lib_build_dirs('synth', lib_dicts=syn_dict) + cm.mkdir(qpf_path) + qpfPathName = cm.expand_file_path_name(qpf_name, qpf_path) + with open(qpfPathName, 'w') as fp: + fp.write('PROJECT_REVISION = "%s"\n' % lib_name) + print("Created {} .qpf files".format(len(syn_dicts))) + + def create_quartus_settings_file(self, lib_names=None): + """Create the Quartus settings file (QSF) for all HDL libraries that have a toplevel entity key synth_top_level_entity. + + Note: + . No support for revisions, so only one qsf per qpf + + Arguments: + - lib_names : one or more HDL libraries + """ + if lib_names is None: + lib_names = self.lib_names + lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names) + syn_dicts = self.libs.get_configfiles(key='synth_top_level_entity', values=None, user_configfiles=lib_dicts) + for syn_dict in syn_dicts: + # Open qsf for each HDL library that has a synth_top_level_entity + lib_name = syn_dict['hdl_lib_name'] + top_level_entity = syn_dict['synth_top_level_entity'] + if top_level_entity == '': + top_level_entity = lib_name + qsf_path = self.get_lib_build_dirs('synth', lib_dicts=syn_dict) + cm.mkdir(qsf_path) + + # One qsf per lib_name + qsf_name = lib_name + '.qsf' + qsfPathName = cm.expand_file_path_name(qsf_name, qsf_path) + with open(qsfPathName, 'w') as fp: + fp.write('# synth_top_level_entity\n') + fp.write('set_global_assignment -name TOP_LEVEL_ENTITY %s\n' % top_level_entity) + + fp.write('\n') + fp.write('# quartus_qsf_files\n') + quartus_qsf_files = syn_dict['quartus_qsf_files'].split() + for fn in quartus_qsf_files: + filePathName = cm.expand_file_path_name(fn, syn_dict.location) + fp.write('set_global_assignment -name SOURCE_TCL_SCRIPT_FILE %s\n' % filePathName) + + fp.write('\n') + fp.write('# All used HDL library *_lib.qip files in order with top level last\n') + use_lib_order = self.derive_lib_order('synth', lib_name) + # use_lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=use_lib_order) # uses original libs.dicts order, but + use_lib_dicts = self.get_lib_dicts_from_lib_names(lib_names=use_lib_order) # must preserve use_lib_order order to ensure that top level design qip with sdc file is include last in qsf + for lib_dict in cm.listify(use_lib_dicts): + qip_path = self.get_lib_build_dirs('synth', lib_dicts=lib_dict) + qip_name = lib_dict['hdl_lib_name'] + '_lib.qip' + qipPathName = cm.expand_file_path_name(qip_name, qip_path) + fp.write('set_global_assignment -name QIP_FILE %s\n' % qipPathName) + + if syn_dict.get_value('quartus_ip_files'): + # print(syn_dict['quartus_ip_files']) + fp.write('\n') + fp.write('# All used HDL library *.ip files in order with top level last\n') + quartus_ip_files = syn_dict['quartus_ip_files'].split() + for fn in quartus_ip_files: + filePathName = cm.expand_file_path_name(fn) + fp.write('set_global_assignment -name IP_FILE %s\n' % filePathName) + + fp.write('\n') + print("Created {} .qsf files".format(len(syn_dicts))) + + +if __name__ == '__main__': + # Parse command line arguments + buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(os.getenv('RADIOHDL_CONFIG')) + if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")]) + argparser = ArgumentParser(description='Quartus_config creates/updates all your quartus projectfiles.') + argparser.add_argument('buildset', help='choose buildset %s' % (buildsetSelect)) + argparser.add_argument('-v', '--verbosity', required=False, type=int, default=0, help='verbosity >= 0 for more info') + args = argparser.parse_args() + + # check arguments + if args.buildset not in buildsetSelect: + print('buildset %s is not supported' % args.buildset) + print("Supported buildset are:", buildsetSelect) + sys.exit(1) + args.buildsetFile = 'hdl_buildset_' + args.buildset + '.cfg' + + # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories + qsyn = QuartusConfig(toolRootDir=os.getenv('RADIOHDL_CONFIG'), + toolFileName=args.buildsetFile, + libFileName='hdllib.cfg') + + if args.verbosity >= 2: + print('#') + print('# QuartusConfig:') + print('#') + print('') + print('HDL library paths that are found in $%s:' % qsyn.libRootDirs) + for p in sorted(qsyn.libs.configfiles.values()): + print(' ', p.location) + + if args.verbosity >= 1: + print('') + print('HDL libraries with a top level entity for synthesis that are found in $%s:' % qsyn.libRootDirs) + print(' %-40s' % 'HDL library', ': Top level entity') + syn_dicts = qsyn.libs.get_configfiles(key='synth_top_level_entity') + for d in syn_dicts: + if d['synth_top_level_entity'] == '': + print(' %-40s' % d['hdl_lib_name'], ':', d['hdl_lib_name']) + else: + print(' %-40s' % d['hdl_lib_name'], ':', d['synth_top_level_entity']) + + print('') + print('Create Quartus IP library qip files for all HDL libraries in $%s.' + % qsyn.libRootDirs) + qsyn.create_quartus_ip_lib_file() + + print('') + print('Copy Quartus directories and files from HDL library source tree to build_dir for all HDL libraries that are found in $%s.' + % qsyn.libRootDirs) + qsyn.copy_files('synth') + + print('') + print('Create Quartus project files (QPF) for technology %s and all HDL libraries with a top level entity for synthesis that are found in $%s.' + % (qsyn.technologyNames, qsyn.libRootDirs)) + qsyn.create_quartus_project_file() + + print('') + print('Create Quartus settings files (QSF) for technology %s and all HDL libraries with a top level entity for synthesis that are found in $%s.' + % (qsyn.technologyNames, qsyn.libRootDirs)) + qsyn.create_quartus_settings_file()
radiohdl/trunk/core/quartus_config Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/doc/HDL User manual.docx =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: radiohdl/trunk/doc/HDL User manual.docx =================================================================== --- radiohdl/trunk/doc/HDL User manual.docx (nonexistent) +++ radiohdl/trunk/doc/HDL User manual.docx (revision 4)
radiohdl/trunk/doc/HDL User manual.docx Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: radiohdl/trunk/doc/HDL User manual.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: radiohdl/trunk/doc/HDL User manual.pdf =================================================================== --- radiohdl/trunk/doc/HDL User manual.pdf (nonexistent) +++ radiohdl/trunk/doc/HDL User manual.pdf (revision 4)
radiohdl/trunk/doc/HDL User manual.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: radiohdl/trunk/doc/HDL programmers manual.docx =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: radiohdl/trunk/doc/HDL programmers manual.docx =================================================================== --- radiohdl/trunk/doc/HDL programmers manual.docx (nonexistent) +++ radiohdl/trunk/doc/HDL programmers manual.docx (revision 4)
radiohdl/trunk/doc/HDL programmers manual.docx Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: radiohdl/trunk/doc/HDL programmers manual.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: radiohdl/trunk/doc/HDL programmers manual.pdf =================================================================== --- radiohdl/trunk/doc/HDL programmers manual.pdf (nonexistent) +++ radiohdl/trunk/doc/HDL programmers manual.pdf (revision 4)
radiohdl/trunk/doc/HDL programmers manual.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: radiohdl/trunk/doc/HDLgear overview.pptx =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: radiohdl/trunk/doc/HDLgear overview.pptx =================================================================== --- radiohdl/trunk/doc/HDLgear overview.pptx (nonexistent) +++ radiohdl/trunk/doc/HDLgear overview.pptx (revision 4)
radiohdl/trunk/doc/HDLgear overview.pptx Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: radiohdl/trunk/doc/HDLgear.eap =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: radiohdl/trunk/doc/HDLgear.eap =================================================================== --- radiohdl/trunk/doc/HDLgear.eap (nonexistent) +++ radiohdl/trunk/doc/HDLgear.eap (revision 4)
radiohdl/trunk/doc/HDLgear.eap Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: radiohdl/trunk/doc/hdltool_readme.txt =================================================================== --- radiohdl/trunk/doc/hdltool_readme.txt (nonexistent) +++ radiohdl/trunk/doc/hdltool_readme.txt (revision 4) @@ -0,0 +1,380 @@ + +g) Tool start scripts + +The definitions for actually running Modelsim and Quartus are not kept in the ~/.bashrc file or the setup script but are +set in a tool start script: + + ${RADIOHDL_GEAR}/modelsim/run_modelsim # calls set_quartus and starts the Modelsim GUI for simulation + ${RADIOHDL_GEAR}/quartus/run_quartus # calls set_quartus and starts the Quartus GUI for synthesis + +The paths to these tool start scripts are defined in setup_radiohdl.sh. In addition to the advantages mentioned above for the environment setup scripts, +the advantages of using a seperate tool start script is: + + - different versions of the tool can be started in parallel on the same machine, because the tool start script settings + only apply to the started tool environment + + + +i) How to start Quartus for RadioHDL + +For building a SOPC system use: + > run_sopc unb1 unb1_minimal_sopc + > run_app unb1 unb1_minimal_sopc # calls: run_bsp, run_reg, run_mif + > run_app_clean unb1 unb1_minimal_sopc app=unb_osy + > run_qcomp unb1 unb1_minimal_sopc + > run_all_sopc unb1 unb1_minimal_sopc # sequentially running: run_sopc + run_app + run_qcomp + > run_rbf unb1 unb1_minimal_sopc + > run_sof unb1 unb1_minimal_sopc 0 + +For building a QSYS system use: + > run_qsys unb1 unb1_minimal_qsys + > run_sopc unb1 unb1_minimal_sopc # (normally not needed but the unb1_minimal_qsys revision has a GENERATE sopc-OR-qsys section) + > run_app unb1 unb1_minimal_qsys use=qsys + > run_qcomp unb1 unb1_minimal_qsys + > run_all_qsys unb1 unb1_minimal_qsys # sequentially running: run_qsys + run_app + run_qcomp + > run_rbf unb1 unb1_minimal_qsys + > run_sof unb1 unb1_minimal_qsys 0 + + +j) How to start Modelsim for UNB + +GUI: + + > unb_msim & # for UNB + > aaf_msim & # for AARTFAAC + > paasar_msim & # for PAASAR + +See the setup_unb.sh environment script and ASTRON_RP_1354_unb_minimal.pdf for more description. + + +n) How to use RadioHDL for Lofar RSP + +* The Lofar Station firmware is kept in a separate SVN repository at: + + https://svn.astron.nl/Station + + The firmware for the RSP board is kept in: + + https://svn.astron.nl/Station/trunk/RSP + + In setup_radiohdl.sh add the path to the local SVN checkout of the Station + firmware: + + export RSP=${SVN}/../Station/trunk/RSP + + and add ${RADIOHDL_GEAR}/ise to the PATH environment variable. + +* To compile the Xilinx ISE10.1.03 models with Modelsim 6.6c under linux do: + + The compxlib adds the Xilinx libraries to the [libraries] section in the + /home/software/Mentor/6.6c/modeltech/modelsim.ini file. Therefore make + sure to first copy this original installation modelsim.ini file, so that + we can restore it. + + cd /home/software/modelsim_xilinx_libs/ise/10.1.03 + sudo mkdir vhdl + sudo mkdir verilog + sudo /home/software/Xilinx/ISE/10.1/ISE/bin/lin/compxlib -s mti_se -f all -l vhdl -dir vhdl -p /home/software/Mentor/6.6c/modeltech/linux_x86_64 + sudo /home/software/Xilinx/ISE/10.1/ISE/bin/lin/compxlib -s mti_se -f all -l verilog -dir verilog -p /home/software/Mentor/6.6c/modeltech/linux_x86_64 + + Use the library mappings in the modelsim.ini that was modified by compxlib + to create: + + tools/ise/create hdl_libraries_ip_virtex4.txt + + The modelsim_config.py using hdl_libraries_ip_virtex4.txt to map the Xilinx + library files in each HDL library project files. Therefore the central + mapping in the Modelsim installation modelsim.ini file is unwanted and not + needed. + +* Create tools/hdl_buildset_rsp.cfg HDL tool configuration dictionary file for buildset 'rsp' + +* Create bash scripts to start up ISE based on the buildset 'rsp' in tools/ise: + run_ise + \--> set_ise + \--> ise_version.sh + \--> ise_generic.sh + + This is similar as for other tools like Modelsim, Quartus. The advantage of + this approach is that the tool settings are only made when the tool is ran + and not in the .bashrc file. These bash scripts are kept in SVN and thus the + same tool settings are used by all engineers. + +* Add 'rsp' buildset for Modelsim and ISE versions to tools/modelsim/set_modelsim. + +* To start the ISE GUI do: + > run_ise rsp & + +* To start the Modelsim GUI do: + > run_modelsim rsp & + + +3) HDL environment configuration files + +d) hdl_buildset_.cfg key descriptions + +- project_dir_depth_sim = + The project file will be located in the build dir or at some levels deeper in the build dir. + These optional extra subdirectory levels allow for relative file reference from project file + location. This is useful to be able to keep memory initialisation files in the library build + directory that are referred to using some fixed ../../ path in the HDL code. + . project_deeper_subdir = '' when project_dir_depth_ = 0 or not in tool_dict + . project_deeper_subdir = 'p/' when project_dir_depth_ = 1 + . project_deeper_subdir = 'p/p/' when project_dir_depth_ = 2, + . project_deeper_subdir = 'p/p/p/' when project_dir_depth_ = 3, etc + +- project_dir_depth_synth = + Same purpose as project_dir_depth_sim, but for synthesis project file location in build tree. + + + +5) Build directory location + +The Modelsim and Quartus build location central outside the $HDL sources directory tree, whereby the +subdirectory names are defined by the corresponding keysin the hdl_buildset_.cfg: + + ${RADIOHDL_BUILD_DIR}// + +eg. + + ${RADIOHDL_BUILD_DIR}/unb1/modelsim/common + +The advantage of the central directory build tree is that it can easily be removed (using rm -rf) and +recreated (using modelsim_config.py and quartus_config.py). For synthesis recreation of targets like sof files can take much +time though. + + + +100) To do + +a) quartus_* keys and synth_top_level_entity + . The quartus_* keys are now source oriented. Instead it may be better to redefine them as target oriented. Eg. a + quartus_create_qsf key that defines to create a qsf file using the information listed in the values. + Whether a key is source oriented or target oriented depends on whether its files are used for one or more targets. + In general if a file is used for more targets then source oriented is preferred to avoid having to list the file + name twice. If a file is used only for one target then target oriented is preferred to be more clear about the + purpose of the key. + . The synth_top_level_entity enforces the creation of a qpf and qsf. This kind of hidden behavior is not so nice. + Instead it is more clear to have an explicit quartus_create_qpf and quartus_create_qsf key to define this. + +b) Generate Quartus IP key + The generate_ip.sh scripts for generating the MegaWizard or QSYS IP components in fact are merely a wrapper script + around the qsys-generate command. The generate_ip.sh may seem an unnecessary intermediate step if the IP is + generated automatically. The IP could be generated automatically based on a megawizard key or a qsys key that + has the description file as value. However the advantage of a generate_ip.sh script is that it can hide whether the + MegaWizard or QSYS needs to be used to generate the IP, so in that way a 'quartus_generate_ip' key can fit both: + + quartus_copy_files = + generate_ip.sh + _.qsys + quartus_generate_ip = generate_ip.sh + + The 'quartus_copy_files' key is used to copy the IP generation source file and the generation script to the + build directory. The 'quartus_generate_ip' key identifies the script that needs to be ran when the IP has to be + generated. Eg. a --generate_ip command line argument for quartus_config.py (rather than a separate + quartus_generate_ip.py script) can then generate the IP for all libraries that have such a key. The IP can then + be generated outside the SVN tree. The $IP_DIR path compile_ip.tcl needs to be adjusted to generated/ and the + IP then gets generated in: + + $RADIOHDL_BUILD_DIR//quartus//generated + + For generated IP that is kept in SVN that IP could still remain there. + + The hdllib.cfg should then also define a IP toolname subdirectory in build dir, eg.: + + // = $RADIOHDL_BUILD_DIR/qsys or + $RADIOHDL_BUILD_DIR/megawizard + + or more general $RADIOHDL_BUILD_DIR/ip? + The $RADIOHDL_BUILD_DIR now has a modelsim and quartus subdir: + + $RADIOHDL_BUILD_DIR//modelsim -- made by modelsim_config.py using sim_tool_name from hdl_buildset_.cfg + $RADIOHDL_BUILD_DIR//quartus -- made by quartus_config.py using synth_tool_name from hdl_buildset_.cfg + + The IP can be put in a subdir using eg 'ip_tool_name' = quartus_ip: + + $RADIOHDL_BUILD_DIR//quartus_ip -- made by quartus_config.py using a new ip_tool_name from hdl_buildset_.cfg + + or can it be put in the synth_tool_name directory: + + $RADIOHDL_BUILD_DIR//quartus + + or do we need tool_name_megawizard and tool_name_qsys to be able to create: + + // + $RADIOHDL_BUILD_DIR/unb1/megawizard -- Altera MegaWizard + $RADIOHDL_BUILD_DIR/unb1/qsys -- Altera QSYS + $RADIOHDL_BUILD_DIR/unb1/coregen -- Xilinx + + Probably it is not so important whether the IP is generated by MegaWizard or Qsys, because that selection is + already covered by the generate_ip.sh scripts. In the hdl_buildset_.cfg both MegaWizard and Qsys can be regarded as + being part of the Quartus tool. Therefore using ip_tool_name provides sufficient distinction in IP build + sub directory. However the IP could also be generated into the synth_tool_name build directory and then even + the ip_tool_name key is not needed, because the synth_tool_name sub directory also suits the Quartus IP + generation. + + Conclusion: + - Using synth_tool_name = quartus is also sufficient/suitable to define the build subdirectory for IP generation. + Having a dedicate ip_tool_name could be nice, to more clearly see in the build tree which libraries have IP. + +c) regression test script + * For pure HDL tests the modelsim_regression_test.py script can simulate VHDL test benches that are listed at + the 'regression_test_vhdl' key and report the result. + * For Python test cases another key can be defined 'regression_test_py_hdl'. The values they may contain the entire command + to run the Python test case with the HDL test bench. Note that the pure VHDL test benches could be perphaps also be + regarded as a special case of the Python MM - VHDL tests, ie. as a test without MM. + * Another bash or Python script that synthesises a set of designs to check that they still run through synthesis ok. + +d) multiple libRootDirs for finding hdllib.cfg files + The libRootDir is now defined via a the 'lib_root_dir' key in the hdl_buildset_.cfg. + Currently hdlib.cfg files are search from one rootDir by find_all_dict_file_paths() in common_dict_file.py. It + would be usefule to be able to specify multiple rootDirs for the search path. This allows finding eg. all + hdllib.cfg in two different directory trees without having to specifiy their common higher directory root which + could be a very large tree to search through. Furthermore by being able to specify the rootDirs more precisely + avoids finding unintended hdllib.cfg files. Support for multiple rootdirs needs to be implemented in + common_dict_file.py because the results from all root dirs need to be in a common object. + +e) Python peripherals + The Python peripherals are still in the $UNB/Software/python/peripherals directory. At some time we need to move + these also to RadioHDL. The peripherals could be located central again or local in a src/python directory. A first + step can be to svn copy the $UNB/Software/python dir to ${RADIOHDL_WORK}/software/python to become independent of the + $UNB tree. An intermediate scheme is also possible whereby the periperal is kept local but copied to a central + build/python directory by means of a python_config.py script. The advantage of a central directory is that the periperals + are grouped so that only a single Python search path is needed. The disadvantage of having a fixed central + location in SVN is that peripherals that are application specific also need to be located there. Another option + may be to use a synbolic link from a central directory to each local Python peripheral. + + +f) Improve support IP for multiple FPGA device types and Quartus tool versions + +The IP is FPGA type specific (because it needs to be defined in the Qsys source file) and tool version specific +(because some parameters and even port IO may change). Currently there is only one IP directory per FPGA +technology (eg. ip_arria10) so there is no further separation into device family type and tool version. The +disadvantage of this scheme is that only one version of Quartus can be supported. For a minor version +change it may not be necessary to upgrade, but for a major version change or for a device family type (eg. from +engineering sample to production sample) change it probably is. To preserve the old version IP it is best to +treat the both the FPGA device version id and the Quartus tool version as a new technology. For example for +Arria10 we now use Quartus 15.0 and device family of UniBoard2 v0 and the IP for that is kept in: + + ${RADIOHDL_WORK}/libraries/technology/ip_arria10/ + +This can be renamed in: + + ${RADIOHDL_WORK}/libraries/technology/ip_arria10_device_10AX115U4F45I3SGES_quartus_15.0/ + +For a directory name it is allowed to use a '.' instead of a '_'. The directory name is not mandatory, but the name convention is +to define the FPGA technology as a triplet: + + ip__device__quartus_ + +A future version of the IP can be kept in: + + ${RADIOHDL_WORK}/libraries/technology/ip_arria10_device_10AX115U4F45I3SGES_quartus_16.0/ + +The technology_pkg.vhd then gets; + + c_tech_arria10_device_10AX115U4F45I3SGES_quartus_14_1 = ...; + c_tech_arria10_device_10AX115U4F45I3SGES_quartus_15_0 = ...; + c_tech_arria10 = c_tech_arria10_device_10AX115U4F45I3SGES_quartus_15_0; -- optional default + +The hdllib.cfg of the specific technology IP library then has key (only one value): + + hdl_lib_technology = ip_arria10_device_10AX115U4F45I3SGES_quartus_15_0 + +The hdl_buildset_.cfg can support multiple technologies eg. to be able to simulate a system with more than one FPGA that are +of different technology (eg. an application with Uniboard1 and Uniboard2): + + technology_names = ip_stratixiv + ip_arria10_device_10AX115U4F45I3SGES_quartus_15_0 + +All libraries that have hdl_lib_technology value that is not in the list of technology_names are removed from the dictionary list +by hdl_config.py, so these IP libraries will not be build. + +The build directory currently contains: + + // + +This scheme is probably still sufficent to also support the FPGA technology as a triplet. However it may be necessary to rename the +library key values in the IP hdllib.cfg to contain the full triplet information, so eg. + + hdl_lib_name = ip_arria10_fifo + hdl_library_clause_name = ip_arria10_fifo_lib + +then becomes: + + hdl_lib_name = ip_arria10_device_10AX115U4F45I3SGES_quartus_15_0_fifo + hdl_library_clause_name = ip_arria10_device_10AX115U4F45I3SGES_quartus_15_0_fifo_lib + +this is a bit awkward. If only one Quartus version and only one device type are supported per buildset, then all these versions can keep +the same basic hdl_lib_name and hdl_library_clause_name because the IP libraries that are not used can be removed from the build. +Alternatively the hdllib_config.py could support multiple technology version IP libraries that use the same logical library name and use +clause. + +The purpose is to be able to handle in parallel different FPGA vendors, different FPGA types and different tool version. We do not have +to support all combinations, but only the combinations that we actually use. Eg. for the FPGA type this implies that we only support the FPGA types +that are actually used on our board. If we make a new board with another FPGA, then we add the technology triplet for that FPGA. + + +g) Improve buildset scheme + +The buildset defines the combination of Modelsim version and Quartus version. Currently there are buildsets 'unb1', 'unb2' and 'unb2a'. This +buildset scheme can be improved because: + +- for python they are defined by the hdl_buildset_.cfg, but for the run_* bash scripts they are defined in set_quartus, + can they be defined in a common source (eg. base on hdl_buildset_.cfg set an environment variable and uses that for bash). The bash + script must then be ran from the same terminal as where the python config script was used to set the environment variable, because otherwise + the environment variable is not set or may not be correct. +- the buildsets are tight to a board name 'unb1' (is that oke?) or should we use more general buildset names, or do we need a symbolic buildset names at all? +- there is also a 'site' level in the bash scripts set_quartus (is that still needed?) + + +h) Declare IP libraries to ensure default binding in simulation. + +Currently the IP library is declared in the technology VHDL file e.g. like 'LIBRARY ip_arria10_ddr4_4g_1600_altera_emif_150;' in tech_ddr_arria10.vhd. +This IP library clause is ignored by synthesis. The IP library must be mapped for simulation, because otherwise Modelsim gives +an error when it compiles the VHDL. Therefore the IP library can then not be excluded for simulation with 'hdl_lib_include_ip' key. +Alternatively the LIBRARY clause could be omitted if the IP library is added to the -L libraries search list of each simulation configuration the +Modelsim project file. This can be achieved adding the IP library to the modelsim_search_libraries key in the hdl_buildset_unb2.cfg. However the problem is +then that if the IP library is not mapped to a directory then Modelsim will issue an error when it tries to search it. +--> For now keep the 'hdl_lib_include_ip' but only use it for synthesis. For simulation the 'hdl_lib_include_ip' is ignored. Which is fine because + for simulation there is no need to exclude IP libraries. + + + +101) More ideas + +a) zip scripts + A zip script can gather all sources that are needed for a particular RadioHDL view point, eg. + + - zip all required libraries for a certain level library --> useful for somebody who wants to reuse a HDL library. + - zip all code necessary to run Python test cases on HW target --> useful for somebody who only wants to use the HW. + - zip all tool environent code --> useful for somebody who wants to use our tool flow but not our HDL. + + Related to this is (how) can we more clearly divide up the RadioHDL/ directory to eg. reuse only parts of it and + to develop these in other locations/repositories (eg. GIT). Eg. the applications/ directory may not be needed or + even suitable in RadioHDL/ because applications could be kept elsewhere, even in another repository at another + institute. + +b) support dynamic generation of IP + Very preliminary ideas: + Currently the MegaWizard or QSYS component description file is fixed and created manually in advance via the + GUI. In future the component description file could be created based on parameters that are defined in the + hdllib.cfg or even parameters that depend on the requirements from the design. In a dynamic flow the hdllib.cfg + for IP could even not exist as a file, but only as a dictionary in the script. + +c) Link RadioHDL developments with the OneClick MyHDL developments. + The hdllib.cfg dictionary format seems useful also in the OneClick flow. For some created libraries the hdllib.cfg + may not exist as a file and but only as the dictionary in the script. The various methods in modelsim_config.py + and quartus_config.py can also be reused in a OneClick flow. + + +102) Know errors + +a) ** Fatal: Error occurred in protected context. when loading a simulation in Modelsim + - Example: + # Loading ip_stratixiv_phy_xaui_lib.ip_stratixiv_phy_xaui_0(rtl) + # ** Fatal: Error occurred in protected context. + # Time: 0 fs Iteration: 0 Instance: /tb_<...>//ip_stratixiv_phy_xaui_0_inst////// File: nofile + # FATAL ERROR while loading design + + Make sure that the StratixIV IP search libraries are defined by modelsim_search_libraries in the hdl_buildset_.cfg. Index: radiohdl/trunk/ise/hdl_libraries_ip_virtex4.txt =================================================================== --- radiohdl/trunk/ise/hdl_libraries_ip_virtex4.txt (nonexistent) +++ radiohdl/trunk/ise/hdl_libraries_ip_virtex4.txt (revision 4) @@ -0,0 +1,19 @@ +# Used by modelsim_config.py to create library paths in the HDL library project files +# VHDL +unisim = $MODEL_TECH_XILINX_LIB/vhdl/unisim +unimacro = $MODEL_TECH_XILINX_LIB/vhdl/unimacro +simprim = $MODEL_TECH_XILINX_LIB/vhdl/simprim +xilinxcorelib = $MODEL_TECH_XILINX_LIB/vhdl/XilinxCoreLib +secureip = $MODEL_TECH_XILINX_LIB/vhdl/secureip +aim = $MODEL_TECH_XILINX_LIB/vhdl/abel/aim +pls = $MODEL_TECH_XILINX_LIB/vhdl/abel/pls +cpld = $MODEL_TECH_XILINX_LIB/vhdl/cpld + +# Verilog +unisims_ver = $MODEL_TECH_XILINX_LIB/verilog/unisims_ver +unimacro_ver = $MODEL_TECH_XILINX_LIB/verilog/unimacro_ver +uni9000_ver = $MODEL_TECH_XILINX_LIB/verilog/uni9000_ver +simprims_ver = $MODEL_TECH_XILINX_LIB/verilog/simprims_ver +xilinxcorelib_ver = $MODEL_TECH_XILINX_LIB/verilog/XilinxCoreLib_ver +aim_ver = $MODEL_TECH_XILINX_LIB/verilog/aim_ver +cpld_ver = $MODEL_TECH_XILINX_LIB/verilog/cpld_ver Index: radiohdl/trunk/ise/ise_generic.sh =================================================================== --- radiohdl/trunk/ise/ise_generic.sh (nonexistent) +++ radiohdl/trunk/ise/ise_generic.sh (revision 4) @@ -0,0 +1,48 @@ +#!/bin/bash +############################################################################### +# +# Copyright (C) 2014 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +############################################################################### + +echo "Run ise_generic.sh" + +# Derive generic ISE tool version related paths from $ISE_DIR that gets defined in ise_version.sh + +# Add to the $PATH, only once to avoid double entries +pathadd ${ISE_DIR}/bin/lin + +#WARNING:Place:957 - Placer has detected that XIL_PLACE_ALLOW_LOCAL_BUFG_ROUTING has been set. This environment variable +# has been deprecated. An ERROR in clock placement rules can be demoted to a WARNING by using the CLOCK_DEDICATED_ROUTE +# constraint on a specific component pin in the .ucf file. + +#set XIL_PLACE_ALLOW_LOCAL_BUFG_ROUTING=1 + +# ERROR:Pack:1653 - At least one timing constraint is impossible to meet because +# component delays alone exceed the constraint. A timing constraint summary +# below shows the failing constraints (preceded with an Asterisk (*)). Please +# use the Timing Analyzer (GUI) or TRCE (command line) with the Mapped NCD and +# PCF files to identify which constraints and paths are failing because of the +# component delays alone. If the failing path(s) is mapped to Xilinx components +# as expected, consider relaxing the constraint. If it is not mapped to +# components as expected, re-evaluate your HDL and how synthesis is optimizing +# the path. To allow the tools to bypass this error, set the environment +# variable XIL_TIMING_ALLOW_IMPOSSIBLE to 1. + +set XIL_TIMING_ALLOW_IMPOSSIBLE=1 +
radiohdl/trunk/ise/ise_generic.sh Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/ise/ise_version.sh =================================================================== --- radiohdl/trunk/ise/ise_version.sh (nonexistent) +++ radiohdl/trunk/ise/ise_version.sh (revision 4) @@ -0,0 +1,30 @@ +#!/bin/bash +############################################################################### +# +# Copyright (C) 2016 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +############################################################################### + +ISE_VERSION=${1} +echo "Select ISE version: ${ISE_VERSION}" + +# Set path to ISE version +export ISE_DIR=/home/software/Xilinx/ISE/${ISE_VERSION}/ISE + +# Select the path to the technology libraries that is used in the [libraries] section of the modelsim.ini +export MODEL_TECH_XILINX_LIB=/home/software/modelsim_xilinx_libs/ise/${ISE_VERSION}
radiohdl/trunk/ise/ise_version.sh Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: radiohdl/trunk/ise/run_impact =================================================================== --- radiohdl/trunk/ise/run_impact (nonexistent) +++ radiohdl/trunk/ise/run_impact (revision 4) @@ -0,0 +1,30 @@ +#!/bin/bash +############################################################################### +# +# Copyright (C) 2016 +# ASTRON (Netherlands Institute for Radio Astronomy) +# 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 . +# +############################################################################### + +# General tool and project settings +# - use '.
© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.