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

add new radiohdl toolset to git

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 2095 additions and 0 deletions
# This file contains a collection of convenience functions and definitions.
#
# automatically export to subsequent commands (-a)
set -a
#exits on any error in pipeline, not just the last error
set -o pipefail
# only set variables if we didn't set them before
if [ "${generic_read:-not_set}" = "not_set" ]; then
# display a (colourfull ...) error message.
# the script will be terminated immediately
# exit with <errorcode> (default=1)
# usage: hdl_error <caller> <message> [<errorcode>]
hdl_error() {
caller=${1:-""}
msg=${2:-""}
exitcode=${3:-1}
if [ -z "${caller}" -o -z "${msg}" ]; then
echo "usage: hdl_error <caller's name> <message> [<exitcode>]"
exit 1
fi
caller=`basename ${caller} | tr [a-z] [A-Z]`
echo -n "$(tput setaf 6)$(tput bold)[${caller}] "
echo -e "$(tput setaf 1)ERROR - ${msg}. $(tput sgr0)"
# Exit if $NO_EXIT does not exist, else only return
if [ -z ${NO_EXIT:-""} ]; then exit ${exitcode}; else return 1; fi
}
# Non-exiting version of hdl_error in case we wish to accumulate errors and
# call an exiting hdl_error after displaying accumulated errors.
hdl_error_noexit() {
caller=${1:-""}
msg=${2:-""}
if [ -z "${caller}" -o -z "${msg}" ]; then
echo "usage: hdl_error <caller's name> <message> [<exitcode>]"
exit 1
fi
caller=`basename ${caller} | tr [a-z] [A-Z]`
echo -n "$(tput setaf 6)$(tput bold)[${caller}] "
echo -e "$(tput setaf 1)ERROR - ${msg}.$(tput sgr0)"
}
hdl_warning() {
caller=${1:-""}
msg=${2:-""}
exitcode=${3:-1}
if [ -z "${caller}" -o -z "${msg}" ]; then
echo "usage: hdl_warning <caller's name> <message> [<exitcode>]"
exit 1
fi
caller=`basename ${caller} | tr [a-z] [A-Z]`
echo -n "$(tput setaf 6)$(tput bold)[${caller}] "
echo -e "$(tput setaf 3)WARNING - ${msg}.$(tput sgr0)"
return 0
}
# usage: hdl_info <caller> <message>
hdl_info() {
caller=${1:-""}
shift
if [ -z "${caller}" -o -z "$*" ]; then
echo "usage: hdl_info <scriptname> <msg1> [<msg2> .. <msgN>]"
exit 1
fi
caller=`basename ${caller} | tr [a-z] [A-Z]`
echo -e "$(tput setaf 6)$(tput bold)[${caller}] $* $(tput sgr0)"
return 0
}
# usage:
# hdl_exec <calling script> [OPTS] <command to run>
# OPTS:
# [msg=<override defaultmsg>]
# msg=no => suppress displaying of messages
# if command fails, do display the
# command that failed
# [expect=<expected exit code>] (default: 0)
# exits with same exitcode as the command
hdl_exec() {
# step one: extract calling scriptname, which is $1
caller=$1; shift
# anything left is supposedly the command to exec + args
# prepare the "msg" to display
msg=
output=
expect=0
# unless someone gave msg="...." as orginal 2nd arg
# (and now, since the first "shift", it is 1st)
for ac ; do
case ${ac} in
output=*)
# well allrighty then, override default msg
output=`echo "${ac}" | sed 's/^output=//'`
shift
;;
msg=*)
# well allrighty then, override default msg
msg=`echo "${ac}" | sed 's/^msg=//'`
shift
;;
expect=*)
expect=`echo "${ac}" | sed 's/^expect=//'`
shift
;;
* )
# first non-option argument; stop for loop!
break
;;
esac
done
if [ -z "${msg}" ]; then
msg="Running \"$*\""
fi
# show usr what we're up to
if [ "${msg}" != "no" ]; then
hdl_info ${caller} "${msg}"
fi
# remember if errexit is switched on because we have to disable it
exit_on_err=true
if [ "${SHELLOPTS//*errexit*}" == "$SHELLOPTS" ]; then
exit_on_err=false
fi
set +e
# and let's actually do it!
if [ "${output}" = "no" ]; then
$* >/dev/null 2>/dev/null
else
$*
fi
exitcode=$?
# switch errexit on if is was on when we were called (no side effects)
if [ $exit_on_err ]; then
set -e
fi
# Finally check if the exitcode of the command we executed is the expected one.
if [ "${exitcode}" -ne "${expect}" ]; then
if [ "${msg}" == "no" ]; then
echo "****** Failed command ****"
echo $*
exit ${exitcode}
fi
hdl_error ${caller} "\"${msg}\" failed" $?
fi
}
# format the date in a specific form
# if changing the format, make sure
# that dateindent has the same length
# again (dateindent used for pretty
# printing multiline stuff without
# having to print the date in every line)
date="/bin/date +'%d %m %Y %T'"
# format dd mm yyyy HH:MM:ss
dateindent=' '
#
# Some generic, often used functions
#
# return the current date/time in a
# predefined format - see above
# Use eg as
# echo "`timestamp` Aaargh - Failed to clobber!"
timestamp() {
echo ${date}
}
# Define function to add directories to a given environment variable
# args: name_of_env_var new_path [new_path ...]
# Directories are only added when they exist.
pathadd() {
for new_dir in ${@:2}
do
eval dir_to_add=`echo ${new_dir}`
if [ ! -d ${dir_to_add} ]; then
echo "WARNING: directory ${dir_to_add} NOT added to $1 because directory doesn't exist!"
else
if ! echo ${!1} | grep -E -q "(^|:)$dir_to_add($|:)" ; then
eval export ${1}=${1:+${!1#:}:}${dir_to_add}
fi
fi
done
unset dir_to_add new_dir
}
# Mark the fact that we read this file and end the guarded part
generic_read="yes"
fi
#!/usr/bin/env bash -e
###############################################################################
#
# 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$
#
###############################################################################
#
# Initialisation script to setup the environment variables for this branch
#
# Make sure no one accidentally gave the script execution rights and just executes it.
if [ "${0}" != "-bash" ]; then
echo "ERROR: Use this command with '. ' or 'source '"
exit
fi
# Figure out where this script is located and set environment variables accordingly
export RADIOHDL="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export ONECLICK=${RADIOHDL}/radiohdl/oneclick
# setup paths to build and config dir if not already defined by the user.
export HDL_BUILD_DIR=${HDL_BUILD_DIR:-${RADIOHDL}/build}
export HDL_CONFIG_DIR=${HDL_CONFIG_DIR:-${RADIOHDL}/config}
echo "RadioHDL environment will be setup for" $RADIOHDL
# Define function to add directories to a given environment variable
# args: name_of_env_var new_path [new_path ...]
# Directories are only added when they exist.
pathadd() {
for new_dir in ${@:2}
do
eval dir_to_add=`echo ${new_dir}`
if [ -d ${dir_to_add} ] && ! echo ${!1} | grep -E -q "(^|:)$dir_to_add($|:)" ; then
eval export ${1}=${1:+${!1#:}:}${dir_to_add}
fi
done
}
# Extend the PATH and PYTHONPATH variables
pathadd "PATH" ${RADIOHDL}/radiohdl/quartus ${RADIOHDL}/radiohdl/ise ${RADIOHDL}/radiohdl/modelsim
pathadd "PYTHONPATH" ${ONECLICK}/base ${ONECLICK}/components
# 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
#!/bin/bash
###############################################################################
#
# Copyright (C) 2014
# 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/>.
#
###############################################################################
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
#!/bin/bash
###############################################################################
#
# Copyright (C) 2016
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
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}
#!/bin/bash
###############################################################################
#
# Copyright (C) 2016
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
# General tool and project settings
# - use '. <script>.sh' to have the settings apply in this shell, otherwise they get lost when <script>.sh returns
# Tool settings for selected target "rsp"
. ${RADIOHDL}/tools/ise/set_ise ${1:-}
# Start the Impact GUI
impact
#!/bin/bash
###############################################################################
#
# Copyright (C) 2016
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
# General tool and project settings
# - use '. <script>.sh' to have the settings apply in this shell, otherwise they get lost when <script>.sh returns
# Tool settings for selected target "rsp"
. ${RADIOHDL}/tools/ise/set_ise ${1:-}
# Start the ISE GUI
ise
#!/bin/bash
###############################################################################
#
# Copyright (C) 2016
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
# Purpose: Map command line argument to a tool version
# Description:
# By using command line arguments like "rsp" to select the tool
# version it is easier to manage combinations of tool versions.
# General tool and project settings
# - use '. <script>.sh' to have the settings apply in this shell, otherwise they get lost when <script>.sh returns
# Select target
TOOLSET=${1:-}
echo "Make tool settings for RadioHDL with :"
echo " - Tool setting: ${TOOLSET}"
echo " - Site setting: ${SITE-}"
# Select tool version
if [ "${SITE-}" = "USN" ]; then
echo "Optionally use site dependent toolset for ${TOOLSET}"
else # default site
if [ "${TOOLSET}" = "rsp" ]; then
. ${RADIOHDL}/tools/ise/ise_version.sh 10.1.03
else
echo "error: unknown tool setting: ${TOOLSET} (choose 'rsp')"
exit 1
fi
fi
# Tool settings
. ${RADIOHDL}/tools/ise/ise_generic.sh
#!/bin/bash -eu
###############################################################################
#
# Copyright (C) 2014-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/>.
#
###############################################################################
# General tool and project settings
# - use '. <script>.sh' to have the settings apply in this shell, otherwise they get lost when <script>.sh returns
# read generic functions/definitions
. ${RADIOHDL}/tools/generic.sh
# helper function for command parsing
exit_with_error() {
hdl_error_noexit $0 "$@"
cat <<@EndOfHelp@
Usage: $(basename $0) buildset [.do-file]
Arguments: buildset Name of the buildset to start modelsim for.
project Command file to use.
@EndOfHelp@
exit 1
}
# parse cmdline
POSITIONAL=()
while [[ $# -gt 0 ]]
do
case $1 in
-*|--*)
exit_with_error "Unknown option: "$1
;;
*) POSITIONAL+=("$1")
;;
esac
shift
done
if [ ${#POSITIONAL[@]} -gt 0 ]; then
set -- "${POSITIONAL[@]}"
fi
# check the positional parameters
if [ $# -ne 1 ] && [ $# -ne 2 ]; then
exit_with_error "Wrong number of arguments specified."
fi
buildset=$1
do_file=${2:-}
. ${RADIOHDL}/tools/modelsim/set_modelsim ${buildset}
if [ -z "${do_file}" ]; then
# Start the Modelsim command line with commands.do
hdl_exec $0 $MODELSIM_DIR/$MODELSIM_PLATFORM/vsim -c -do ${RADIOHDL}/tools/modelsim/commands.do
else
# Start the Modelsim command line with user passed .do file
# Typically the do-file should start with 'do ${RADIOHDL}/tools/modelsim/commands.do' and end with 'quit -f'.
hdl_exec $0 $MODELSIM_DIR/$MODELSIM_PLATFORM/vsim -c -do ${do_file}
fi
###############################################################################
#
# Copyright (C) 2014
# 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/>.
#
###############################################################################
# Purpose: Provide useful commands for simulating Modelsim projects
# Desription:
#
# * The user commands are typically used at the Modelsim prompt are:
#
# . lp <name> : load HDL library <name>.mpf project
# . mk <name> : make one or range of HDL library mpf projects
# . as # : add signals for # levels of hierarchy to the wave window
# . ds : delete all signals from the wave window
#
# * The other procedures in this commands.do are internal command procedures
# that are typically not used at the Modelsim prompt.
#
# * The recommended project directory structure is:
#
# $arg_lib/build/modelsim : Modelsim project file
# /quartus : Quartus project file
# /src/vhdl : VHDL source code that gets synthesized
# /tb/vhdl : VHDL source code for test bench
#
# Alternatively the build/ directory may be located at another more central
# location.
#
#-------------------------------------------------------------------------------
# HDL library settings
#-------------------------------------------------------------------------------
echo "Loading general HDL library commands..."
proc hdl_env {} {
global env
return $env(RADIOHDL)
}
proc hdl_build {} {
global env
return $env(HDL_BUILD_DIR)
}
proc hdl_buildset {} {
global env
return $env(BUILDSET)
}
#-------------------------------------------------------------------------------
# LP = Load project
#-------------------------------------------------------------------------------
proc get_cur_lib {} {
set mpf [eval project env]
set cur_lib [string range $mpf [expr [string last / $mpf]+1] [expr [string last . $mpf]-1]]
return $cur_lib
}
proc lp {{arg_lib ""}} {
set cur_lib [get_cur_lib]
if {$arg_lib=="help"} {
echo ""
echo "lp \[project\]"
echo " possible projects are:"
echo " <lib_name> : load project <lib_name>.mpf"
echo " : report current project library"
echo " all : report all libraries that the current project library depends on"
echo " help : displays this help"
echo ""
} elseif {$arg_lib == "" || $arg_lib == $cur_lib} {
return $cur_lib
} elseif {$arg_lib=="all"} {
read_lib_compile_order_file $cur_lib
return
} else {
set sim [simdir $arg_lib]
if {[eval project env]!=""} {
project close ;# close current project
}
project open $sim/$arg_lib.mpf ;# load project for the requested library
return $arg_lib
}
}
#-------------------------------------------------------------------------------
# MK = Make project
#-------------------------------------------------------------------------------
proc project_mk_cmds {} {
return {clean execute compile files make test vmake} ;# mk with arg_cmd="" will default to "make"
}
# Get commands from the mk args
proc parse_for_cmds arg_list {
set cmds {}
if [ string equal $arg_list "help" ] then {
echo ""
echo "mk \[commands\] \[projects\]"
echo " possible commands are:"
echo " clean: removes the library files"
echo " execute: runs compile IP scripts"
echo " compile: runs project compileall"
echo " files: list files in compile order"
echo " help: displays this help"
echo " make: runs makefile"
echo " test: runs test cases"
echo " vmake: creates makefile"
echo ""
echo " commands are executed for the projects indicated"
echo " - when no command is specified, 'make' is used as default"
echo " - when no projects are specified, the current project is used"
echo " - when the keyword 'all' is specified, then the command is applied to all projects that the current project depends on"
echo ""
return
} else {
# search for commands in arg_list
foreach cmd [project_mk_cmds] {
if {[lsearch $arg_list $cmd] >= 0} then {
lappend cmds $cmd
}
}
if {[llength $cmds] == 0} then {
# no commands found, use default command
set cmds {make}
}
}
return $cmds
}
# Get libraries from the mk args
proc parse_for_libs arg_list {
# strip the commands from arg_list to keep only the libraries
set libs $arg_list
foreach cmd [project_mk_cmds] {
set i [lsearch $libs $cmd]
if {$i >= 0} then {
set libs [lreplace $libs $i $i]
}
}
return $libs
}
# Create work library
proc do_vlib arg_work {
set modelsimId [vsimId]
set dot_index [string first . $modelsimId]
set majorId [string range $modelsimId 0 [expr $dot_index-1]]
if {$majorId <= 6} {
vlib $arg_work
} else {
# The makefile that is created by vmake relies on using directories in vlib
vlib -type directory $arg_work
}
}
# Extract this lib or all libs that it depends on for arg_lib
proc extract_all_libs arg_lib {
if {$arg_lib=="all"} {
set cur_lib [get_cur_lib]
return [read_lib_compile_order_file $cur_lib]
} else {
return $arg_lib
}
}
# General make project
proc mk args {
# Parse the args, the args is a special TCL argument because it allows more than one formal.
set arg_cmd [parse_for_cmds $args]
set arg_lib [parse_for_libs $args]
# Extract arg_lib or all libs that it depends on for arg_lib
set arg_lib [extract_all_libs $arg_lib]
# keep current lib
set cur_lib [get_cur_lib]
# Without arguments mk current lib
if { [llength $arg_lib] == 0 } {
set arg_lib $cur_lib
}
# Perform the commands on the specified libs
foreach cmd $arg_cmd {
foreach lib $arg_lib {
if { [ catch { eval ["mk_$cmd" $lib] } msg ] } {
echo $msg
}
}
}
# back to original lib
lp $cur_lib
}
proc mk_clean {arg_lib} {
echo "\[mk clean $arg_lib\]"
set sim [simdir $arg_lib]
if {[file exists "$sim/work"]} then {
vdel -lib $sim/work -all
}
if {[file exists "$sim/makefile"]} then {
file delete $sim/makefile
}
if {[file exists "$sim/vsim.wlf"]} then {
file delete $sim/vsim.wlf
}
if {[file exists "$sim/$arg_lib.cr.mti"]} then {
file delete $sim/$arg_lib.cr.mti
}
}
proc mk_execute {arg_lib} {
# if there are compile scripts for IP files then first use use mk_execute to compile those into this work
set compile_ip [read_lib_compile_ip_file $arg_lib]
if {[llength $compile_ip] > 0} {
echo "\[mk execute $arg_lib\]"
set sim [simdir $arg_lib]
lp $arg_lib
# create work library if it does not already exist
if {![file exists "$sim/work"]} then {
do_vlib work
}
global env ;# Make global env() variable known locally. This is necessary for $env(*) in compile IP tcl script, alternatively use $::env(*) in compile IP tcl scrip
foreach ip $compile_ip {
echo "do $ip"
do $ip
}
}
}
proc mk_compile {arg_lib} {
set sim [simdir $arg_lib]
if {[string compare [env] "<No Context>"] != 0} {
echo "A project cannot be closed while a simulation is in progress.\nUse the \"quit -sim\" command to unload the simulation first."
return
}
echo "\[mk compile $arg_lib\]"
lp $arg_lib
# recreate work library
if {[file exists "$sim/work"]} then {
vdel -lib $sim/work -all
}
do_vlib work
# and then first execute any IP compile scripts
mk_execute $arg_lib
# and then compile the HDL
project compileall
}
proc mk_files {arg_lib} {
lp $arg_lib
foreach file [project compileorder] {
echo $file
}
}
proc mk_vmake {arg_lib} {
set sim [simdir $arg_lib]
if {![file exists "$sim/work/_info"]} then {
mk_compile $arg_lib
}
echo "\[mk vmake $arg_lib\]"
if {![file exists "$sim/makefile"] || ([file mtime "$sim/makefile"] < [file mtime "$sim/work/_info"]) } then {
# Both the specific library name $(arg_lib)_lib and the work library map to the same local work library,
# so to be compatible for both names always use work to generate the makefile
echo [exec vmake -fullsrcpath work > $sim/makefile]
}
# recreate work library
vdel -lib $sim/work -all
do_vlib work
# and then first execute any IP compile scripts
mk_execute $arg_lib
}
proc mk_make {arg_lib} {
set sim [simdir $arg_lib]
if {! [file exists "$sim/makefile"] } then {
mk_vmake $arg_lib
}
echo "\[mk make $arg_lib\]"
if {[this_os]=="Windows"} {
echo [exec [hdl_env]/tools/bin/make.exe -C $sim -s -k -f makefile]
} else {
echo [exec /usr/bin/make -C $sim -s -k -f makefile]
}
}
proc mk_test {arg_lib} {
echo "\[mk test $arg_lib\]"
radix -decimal
vsim -quiet tst_lib.tb_$arg_lib
set tb [tbdir $arg_lib]
foreach tc [glob -directory $tb/data -type d -nocomplain tc*] {
echo "testcase $tc"
foreach fileName [glob -directory $tc -type f -nocomplain *.in *.out *.ref] {
file copy -force $fileName .
}
restart -force
run 1 ms
foreach fileName [glob -dir . -type f -nocomplain *.in *.out *.ref] {
file delete -force $fileName
}
}
quit -sim
}
#-------------------------------------------------------------------------------
# Auxiliary procedures
#-------------------------------------------------------------------------------
proc read_modelsim_project_files_file {} {
set fp [open [hdl_build]/[hdl_buildset]/modelsim/modelsim_project_files.txt]
set data [read $fp]
close $fp
set lines [split $data \n]
set lib_names {}
set mpf_paths {}
foreach line $lines {
set ll [split $line]
if {[lindex $ll 1]== "="} {
lappend lib_names [lindex $ll 0]
lappend mpf_paths [lindex $ll 2]
}
}
set ret {}
lappend ret $lib_names
lappend ret $mpf_paths
return $ret
}
proc read_lib_compile_order_file {arg_lib} {
set sim [simdir $arg_lib]
set file_name $arg_lib
append file_name "_lib_order.txt"
set fp [open $sim/$file_name]
set data [read $fp]
set data [string trim $data] ;# trim any trailing white space
close $fp
set lib_names [split $data]
echo $lib_names
return $lib_names
}
proc read_lib_compile_ip_file {arg_lib} {
set sim [simdir $arg_lib]
set file_name $arg_lib
append file_name "_lib_compile_ip.txt"
if {[file exists "$sim/$file_name"]} then {
set fp [open $sim/$file_name]
set data [read $fp]
set data [string trim $data] ;# trim any trailing white space
close $fp
set compile_ip [split $data]
echo $compile_ip
return $compile_ip
} else {
return
}
}
# Compute simulation directory where the mpf is located
proc simdir {arg_lib} {
set project_libs [read_modelsim_project_files_file]
set lib_names [lindex $project_libs 0]
set mpf_paths [lindex $project_libs 1]
set lib_index [lsearch $lib_names $arg_lib]
if {$lib_index >= 0} {
return [lindex $mpf_paths $lib_index]
} else {
error "Project directory $arg_lib not found"
return -1
}
}
# Compute tb directory
proc tbdir {arg_lib} {
}
# find out which environment operating system we are on
proc this_os {} {
if {$::tcl_platform(platform)=="windows"} {
return "Windows"
} else {
return "Not Windows" ;# Linux, Unix, ...
}
}
#-------------------------------------------------------------------------------
# DS = Delete Signals : deletes all signals in the waveform window.
#-------------------------------------------------------------------------------
proc ds {} {
delete wave *
}
#-------------------------------------------------------------------------------
# AS = Add signals : adds all signals up to hierarchy depth to the wave window
#-------------------------------------------------------------------------------
proc as {depth {inst ""}} {
#asf $depth
asg $depth $inst
}
#-------------------------------------------------------------------------------
# ASF = add signals flat : flat adds all signals up to hierarchy depth to the wave window
# It will automatically add dividers between the blocks, and it will discard all
# nxt_ and i_ signals. Altera alt_ blocks will also be ignored.
#-------------------------------------------------------------------------------
proc asf depth {
global env
# Start with all signals in the model.
add wave -noupdate -divider {as}
add wave -noupdate -depth $depth -r "/*"
# Allow users to set environment variable if they don't want the signals to be deleted
if { ![info exists ::env(MODELSIM_WAVE_NO_DEL) ] } {
delete wave */nxt_*
delete wave */i_*
}
#delete wave */alt*
configure wave -signalnamewidth 0
echo "Done."
}
#-------------------------------------------------------------------------------
# ASG = add signals in groups : recursively scans the hierarchy and adds signals
# groupwise to the wave window.
# Normal use:
# . asg [depth]
# => Adds all signals down to a depth of [depth].
# Advanced/debugging use:
# . asg [depth] [instance_name]
# => Adds all signals in [instance_name] down to to a level of [depth]
# NOTE: instance_name = NOT the entity name!
#-------------------------------------------------------------------------------
proc asg {depth {inst ""}} {
add_wave_grouped_recursive "" "" $depth $inst 0
wave refresh
# The grouping already displays the hierarchy, so use short signal names.
config wave -signalnamewidth 1
# With our short signal names, the name column can be narrower than default.
config wave -namecolwidth 300
}
# called by ASG:
proc add_wave_grouped_recursive {current_level prev_group_option depth target_inst target_inst_det} {
# Find all instances (=next hierarchy levels) in the ecurrent hierarchy level
set found_instances [find instances "$current_level/*"]
# Find all blocks (=GENERATE statement labels that are also hierarchy levels to be explored)
set found_blocks [find blocks "$current_level/*"]
# Concatenate the instance list with the block list, sort them alphabetically
set objects [lsort -dictionary [concat $found_instances $found_blocks]]
foreach object $objects {
# Separate "/object_path" from "(entity_name)"
set object_path [lindex [split $object " "] 0]
# Get the word after last "/"
set gname [lrange [split $object_path "/"] end end]
if {[path_depth $object_path]<$depth} {
if { $gname == $target_inst || $target_inst_det==1} {
# Found an instance that matches user input - or we're already inside that instance.
add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 1
} else {
add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 0
}
}
}
if { $current_level != "" } {
# First check if what we're about to add is an instance, not merely a GENERATE level
if {[context isInst $current_level]==1} {
set CMD "add wave -noupdate -radix unsigned $prev_group_option $current_level/*"
if {$target_inst!=""} {
# User passed a target inst. Check if we inside of it.
if {$target_inst_det==0} {
# We're not in in instance. Only add a group and move on.
set CMD "add wave -noupdate -radix unsigned $prev_group_option"
}
}
# Use catch so e.g. empty entities don't cause script to fail
catch {eval $CMD}
}
return
}
}
# Count the number of occurences in a string:
proc scount {subs string} {
regsub -all $subs $string $subs string
}
# Return the depth of a given path; e.g. /some/path/to/some/thing = 5.
proc path_depth path {
scount "/" $path
}
#-------------------------------------------------------------------------------
# NOWARN default disables the library warnings for subsequent simulation runs.
# Use argument 0 to enable the warnings again.
#-------------------------------------------------------------------------------
proc nowarn {{off 1}} {
set ::StdArithNoWarnings $off
set ::NumericStdNoWarnings $off
}
#!/bin/bash
###############################################################################
#
# Copyright (C) 2014
# 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/>.
#
###############################################################################
# General tool and project settings
# - use '. <script>.sh' to have the settings apply in this shell, otherwise they get lost when <script>.sh returns
# read generic functions/definitions
. ${RADIOHDL}/tools/generic.sh
# check the positional parameters
if [ $# -ne 1 ]; then
hdl_error $0 "Syntax: $0 buildset"
fi
buildset=$1
# read in the configuration based on the user arguments
. ${RADIOHDL}/tools/modelsim/set_modelsim ${buildset}
# Start the Modelsim GUI
hdl_exec $0 $MODELSIM_DIR/$MODELSIM_PLATFORM/vsim -do ${RADIOHDL}/tools/modelsim/commands.do
#!/bin/bash -eu
###############################################################################
#
# Copyright (C) 2014-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$
#
###############################################################################
# does user wants feedback on what is happening?
if [ "${1:-}" == "--verbose" ]; then
verbose=$1
shift
else
verbose=""
fi
# read generic functions
. ${RADIOHDL}/tools/generic.sh
# Buildset settings for selected a target, e.g.: "unb1", or "unb2"
BUILDSET=${1:-}
if [ "${BUILDSET}" = "" ]; then
hdl_error $0 "Please specify all arguments\nUsage: $0 <buildset>"
fi
# Select output directory for the library compilation results
buildset_config_file="${HDL_CONFIG_DIR}/hdl_buildset_${BUILDSET}.cfg"
if [ ! -f $buildset_config_file ]; then
hdl_error $0 "File '$buildset_config_file' does not exist"
fi
. ${RADIOHDL}/tools/set_config_variable $verbose $buildset_config_file synth_tool_version
echo "Setting up modelsim for: ${BUILDSET}"
# Adopt buildset dependend directories
. ${RADIOHDL}/tools/set_config_variable $verbose $buildset_config_file modelsim_dir,modelsim_platform
# Adopt quartus installation dependend directories
modelsim_config_file="${HDL_CONFIG_DIR}/hdl_tool_modelsim.cfg"
. ${RADIOHDL}/tools/set_config_variable $verbose $modelsim_config_file model_tech_altera_lib
unset buildset_config_file modelsim_config_file verbose
#!/usr/bin/env python
###############################################################################
#
# 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, sys
from os.path import expandvars, isfile, isdir
from argparse import ArgumentParser
from hdl_configfile import HdlBuildset, HdlTool
def _do_basic_key_checking(cfgfile, indent=""):
# Check that all key references are solved
print "{}Checking references...".format(indent),
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),
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 _check_quartus_configfile(cfgfile, tool_types):
# check required dirs
for required_dir in [ "quartus_rootdir", "quartus_rootdir_override", "niosdir" ]:
print " Checking {}...".format(required_dir),
if isdir(expandvars(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 cfgfile.content.keys() if key.endswith("_paths") ]:
paths = [ expandvars(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 not opt_key in 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 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__':
# 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("${HDL_CONFIG_DIR}/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...",
lib_dirs = [ expandvars(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),
if not toolname in buildset_info.section_headers:
print "\n Warning: No sectionheader found.",
tool_dir = "{}_dir".format(toolname)
if not tool_dir in buildset_info.content.keys():
print "\n ERROR: Key {} is missing.".format(tool_dir),
else:
os.environ[tool_dir.upper()] = buildset_info[tool_dir]
tool_configfile = expandvars("${HDL_CONFIG_DIR}/hdl_tool_%s.cfg" % (toolname))
if not isfile(tool_configfile):
print "\n Warning: File {} is missing!".format(tool_configfile),
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)
This diff is collapsed.
#!/usr/bin/env python
###############################################################################
#
# 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$
#
###############################################################################
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_<boardtype>.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)))
###############################################################################
#
# Copyright (C) 2014-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$
#
###############################################################################
"""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 not required_key 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]
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.
"""
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!=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):
"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 (<key>) with the value of that key.
Note that this operation is irreversable.
"""
ref_pattern = r"<(.+?)>"
prog = re.compile(ref_pattern)
# loop over all items of the dict
for key, value in self.__content__.items():
# any reference in the value?
matchlist = list(set(prog.findall(value)))
for reference in matchlist:
if reference in 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
###############################################################################
#
# Copyright (C) 2014-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$
#
###############################################################################
import sys
import os
import os.path
import re
from common 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 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 == 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 = 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 == None or cfgfile.content[key] in values:
result.append(cfgfile)
return result
#!/usr/bin/env python
###############################################################################
#
# 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$
#
###############################################################################
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_<boardtype>.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.")
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: <key> <value> [<key> <value> [...]]
# check we have an even number of items
items = kv_pairs.split()
if len(items) % 2:
argparser.error("Key '{}' should contain an even number of items ({}).".format(key, items))
for idx in xrange(0, len(items)/2, 2):
print "export {}='{}'\n".format(items[idx].upper(), os.path.expandvars(items[idx+1]))
#!/usr/bin/env python
###############################################################################
#
# 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$
#
###############################################################################
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_<boardtype>.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("${HDL_CONFIG_DIR}/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)))
#!/usr/bin/env python
###############################################################################
#
# Copyright (C) 2014-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$
#
###############################################################################
import sys
from os.path import expandvars, dirname, basename
from subprocess import call, STDOUT
from common 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}/tools/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}/tools/quartus/set_quartus %s\n' % buildset
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 --output-directory=%s %s 2>&1) | grep -iv Info:\n' \
% (options, extra_options, outputdir, vhdl_file)
script += 'exit_code=$?\n'
script += 'exit $exit_code\n'
# execute script
print "compiling {} ... ".format(vhdl_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 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}/tools/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
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_<buildset>.cfg'")
args = argparser.parse_args()
# resolve full name of buildsetfile and force it to be explicit absolute or relative.
full_buildsetfile_name = expandvars("${HDL_CONFIG_DIR}/hdl_buildset_%s.cfg" % (args.buildset))
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 = [ expandvars(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 = expandvars("${HDL_CONFIG_DIR}/hdl_tool_{}.cfg".format(buildset_info.synth_tool_name))
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 = "${HDL_BUILD_DIR}/%s/%s" % (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"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment