pax_global_header 0000666 0000000 0000000 00000000064 13437225564 0014525 g ustar 00root root 0000000 0000000 52 comment=647571b98b49255a1fc3f29d58bf71048eb56466
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/ 0000775 0000000 0000000 00000000000 13437225564 0021510 5 ustar 00root root 0000000 0000000 conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/.gitignore 0000664 0000000 0000000 00000000007 13437225564 0023475 0 ustar 00root root 0000000 0000000 *.pyc
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/README.md 0000664 0000000 0000000 00000000340 13437225564 0022764 0 ustar 00root root 0000000 0000000 # CONV-RS485-OPT-RTM Production Test System (PTS)
This is the repository for the the CONV-RS485-OPT-RTM.
Currently it contains the [software for the Production Test System software (PTS)](pts/), under the
`pts` directory.
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/ 0000775 0000000 0000000 00000000000 13437225564 0022316 5 ustar 00root root 0000000 0000000 conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/.gitignore 0000664 0000000 0000000 00000000006 13437225564 0024302 0 ustar 00root root 0000000 0000000 log/
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/CONFIG.ini 0000664 0000000 0000000 00000000607 13437225564 0023767 0 ustar 00root root 0000000 0000000 [DUT.FEC]
MgtHostName = cfvm-774-opt-pts2
MgtPort = 23
MgtUserName = admin
MgtPassword = Gr@nBr@st0
Slot = 5
[CTR.FEC]
TstDuration = 60.0
MgtHostName = cfvm-774-opt-pts1
MgtPort = 23
MgtUserName = admin
MgtPassword = Gr@nBr@st0
CpuHostName = cfv-774-opt-pts1
CpuPort = 22
# Please set CpuUserName to an account name you have access to on the CTR.FEC
CpuUserName = nobody
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/README.md 0000664 0000000 0000000 00000000720 13437225564 0023574 0 ustar 00root root 0000000 0000000 # CONV-RS485-OPT-RTM Production Test System (PTS)
This is the software for the the CONV-RS485-OPT-RTM PTS.
To configure it, please edit directly the file `CONFIG.ini`. In particular, please make sure that
you have set `CpuUserName` to an account name you have access to on the Front-End Computer (FEC)
that is hosting the Central Timing Receiver (CTR) cards.
To run it, simply run the `run-pts.py` python script.
**Dependencies:**
- snmp
- python configparser
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/ 0000775 0000000 0000000 00000000000 13437225564 0023637 5 ustar 00root root 0000000 0000000 conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/pts.py 0000664 0000000 0000000 00000042764 13437225564 0025034 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: pts.py
##
## description: Generic PTS framework used for running the various tests and
## logging their outputs.
##
################################################################################
## Copyright CERN 2011-2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
import sys
import cmd
import glob
import re
import os, os.path
import stat
import datetime
import random
import warnings
import zipfile
import string
import fnmatch
from ConfigParser import ConfigParser, NoOptionError
from optparse import OptionParser
from ptsexcept import *
default_config_file = 'ptsdefault.cfg'
default_log_pattern = '{timestamp}_pts_tst_{board}_{serial}_{number}.txt'
default_log_name = '{timestamp}_pts_run_{board}_{serial}.txt'
default_zip_name = '{timestamp}_zip_run_{board}_{serial}.zip'
default_test_pattern = r'test[0-9][0-9]'
default_test_syntax = r'(test)?(\d\d)'
original_raw_input = raw_input
def get_files(dirname,pattern):
files = []
for file in os.listdir(dirname):
if fnmatch.fnmatch(file, pattern):
file=os.path.join(dirname,file)
files.append(file)
return files
def pts_raw_input(msg, default='y'):
try:
ret = original_raw_input(msg)
except EOFError:
return default
return ret
def make_zip(zipname, ziplist):
with zipfile.ZipFile(zipname, 'w') as z:
for f in ziplist:
dir, base_filename = os.path.split(f)
os.chdir(dir)
z.write(base_filename)
def run_test(testname, logname, card, test_path, serial, yes=False):
"""run test testname with output redirected to logname
If yes is true, assume affirmative answers from the user
"""
try:
tmpout = sys.stdout
sys.stdout = open(logname, 'w')
if yes:
tmpin = sys.stdin
sys.stdin = open('/dev/null')
__builtins__.raw_input = pts_raw_input
mod = __import__(testname, globals(), locals(), [])
card = mod.main(card, default_directory=test_path, serial=serial)
finally:
# sys.stdout.close()
sys.stdout = tmpout
if yes:
sys.stdin = tmpin
raw_input = original_raw_input
return card
class Suite(object):
def __init__(self, cfgfilename=default_config_file):
self.required = [ 'board', 'serial', 'extra_serial', 'test_path',
'log_path', 'sequence' ]
for fieldname in self.required:
self.__setattr__(fieldname, None)
self.config = default_config_file
self.log_pattern = default_log_pattern
self.log_name = default_log_name
self.zip_name = default_zip_name
#self.read_config(self.config)
def missing(self):
"""report missing fields before suite run"""
missing = [ fieldname for fieldname in self.required
if self.__getattribute__(fieldname) is None ]
return missing
def read_config(self, name=None):
if name:
self.config = name
try:
cfg = file(self.config).read()
except IOError:
errmsg = 'could not read configuration file {0}'
errmsg = errmsg.format(self.config)
raise PtsCritical(errmsg)
config = ConfigParser(cfg)
try:
self.board = config.get('global', 'board')
self.serial = config.get('global', 'serial')
self.extra_serial = config.get('global', 'extra_serial')
self.test_path = config.get('global', 'test_path')
self.log_path = config.get('global', 'log_path')
self.sequence = config.get('global', 'sequence')
self.repeat = config.get('global', 'repeat')
self.randomize = config.get('global', 'randomize')
except NoOptionError:
pass
def save(self):
config = ConfigParser()
config.add_section('global')
config.set('global', 'board', self.board)
config.set('global', 'serial', self.serial)
config.set('global', 'extra_serial', self.extra_serial)
config.set('global', 'test_path', self.test_path)
config.set('global', 'log_path', self.log_path)
config.set('global', 'sequence', self.sequence)
config.set('global', 'repeat', self.repeat)
config.set('global', 'randomize', self.randomize)
# Writing our configuration file
configfile = open(self.config, 'wb')
config.write(configfile)
configfile.close()
def validate_and_compute_run(self):
"""validate run paramenters"""
if not self.board:
msg = 'invalid board name [{0}]'.format(self.board)
raise PtsInvalid(msg)
if not self.serial:
msg = 'invalid serial number [{0}]'.format(self.serial)
raise PtsInvalid(msg)
#self.serial = self.serial.strip(',')
if not self.extra_serial:
self.extra_serial = '0000'
else :
self.extra_serial = self.extra_serial.strip(',')
warnings.simplefilter('error')
try:
tmp = os.tempnam(self.test_path)
open(tmp, 'w')
os.unlink(tmp)
except RuntimeWarning:
pass
except IOError:
msg = 'invalid test path [{0}]'.format(self.test_path)
raise PtsInvalid(msg)
try:
tmp = os.tempnam(self.log_path)
open(tmp, 'w')
os.unlink(tmp)
except RuntimeWarning:
pass
except:
msg = 'invalid log path [{0}]'.format(self.log_path)
raise PtsInvalid(msg)
if not self.repeat:
self.repeat = 1
else:
try:
self.repeat = int(self.repeat)
except ValueError:
msg = 'invalid repeat factor [{0}]'.format(self.repeat)
raise PtsInvalid(msg)
if not self.sequence:
raise PtsNoBatch('null test sequence')
run = []
for testno in self.sequence:
test_glob = os.path.join(self.test_path, 'test' + testno + '.py')
files = glob.glob(test_glob)
if not files:
print files, test_glob
raise PtsBadTestNo('no test number [%s], aborting' % testno)
run.append(files[0])
if self.randomize:
random.shuffle(run)
self.run_ = self.repeat * run
return self.run_
def search_prev_logs(self) :
"""Search for previous logs and ask the operator why repeat the test"""
for filename in os.listdir(self.log_path):
if string.find(filename, "run") == -1 :
continue;
try:
serial = re.match(r'^.*_([^_.]+)\.txt$', filename).group(1)
if serial == self.serial :
self.comment = raw_input('Previous logs for this board have been recorded.\nWhy do you want to repeat the test? (press ENTER to finish) : \n')
break;
except AttributeError:
pass
def run(self):
self.comment = ""
self.search_prev_logs()
card = None
sequence = self.validate_and_compute_run()
ts = timestamp()
logfilename = self.log_name.format(board=self.board,
serial=self.serial,
timestamp=ts)
logfilename = os.path.join(self.log_path, logfilename)
log = file(logfilename, 'wb')
zipfilename = self.zip_name.format(board=self.board,
serial=self.serial,
timestamp=ts)
zipfilename = os.path.join(self.log_path, zipfilename)
ziplist = [ logfilename ]
if self.test_path not in sys.path:
sys.path.append(self.test_path)
log.write('test run\n'
' board = {0}\n'
' serial = {1}\n'
' optional serial = {2}\n'
' comment = {3}\n'
' timestamp = {4}\n'.format(
self.board, self.serial, self.extra_serial, self.comment, ts))
failures = []
for test in sequence:
try:
testname = os.path.splitext(os.path.basename(test))[0]
shortname= re.match('test(\d\d)', testname).group(1)
logname = self.log_pattern.format(board=self.board,
serial=self.serial,
timestamp=ts,
number=shortname)
logname = os.path.join(self.log_path, logname)
ziplist.append(logname)
log.write('------------------------\n')
log.write('running test {0} = {1}\n'.format(shortname, test))
print 'running test ' + shortname
card = run_test(testname, logname, card, self.test_path, (self.serial + "_" + self.extra_serial), self.yes)
except PtsCritical, e:
print 'test [%s]: critical error, aborting: [%s]' % (shortname, e)
log.write(' critical error in test {0}, exception [{1}]\n'.format(shortname, e))
log.write(' cannot continue, aborting test suite')
failures.append((shortname, e, ))
break
except PtsError, e:
print 'test [%s]: error, continuing: [%s]' % (shortname, e)
log.write(' error in test {0}, exception [{1}]\n'.format(shortname, e))
failures.append((shortname, e, ))
except PtsUser, e:
print 'test [%s]: user error, user intervention required: [%s]' % (shortname, e)
log.write(' error in test {0}, exception [{1}]\n'.format(shortname, e))
failures.append((shortname, e, ))
while True:
if self.yes:
log.write(' user intervention: continue (assuming --yes)\n')
continue
ans = raw_input('Abort or Continue? (A/C) ')
ans = ans.lower()
if ans in ('a', 'c'):
break
if ans == 'a':
log.write(' user intervention: abort\n')
break
elif ans == 'c':
log.write(' user intervention: continue\n')
continue
except PtsWarning, e:
print 'test [%s]: warning: [%s]' % (shortname, e)
log.write(' warning in test {0}, exception [{1}]\n'.format(shortname, e))
failures.append((shortname, e, ))
except Exception, e:
print 'test [%s]: unknown exception [%s]' % (shortname, e)
log.write(' unknown exception in test {0}, exception [{1}]\n'.format(shortname, e))
failures.append((shortname, e, ))
else:
log.write(' OK\n')
print 'test '+ shortname + ' OK\n'
log.write('\n')
log.write('------------------------\n')
log.write('Test suite finished.\n')
if not failures:
msg = 'All tests OK\n'
else:
msg = [ 'FAILED:' ]
for fail in failures:
msg.append(fail[0])
msg = ' '.join(msg)
print msg
log.write(msg)
log.close()
make_zip(zipfilename, ziplist)
def get_serial():
"""return serial number of current board to test
"""
return raw_input('board serial number? ').strip()
def get_extra_serial():
"""return serial number of current board to test
"""
return raw_input('board serial number? ').strip()
def timestamp():
"""timestamp for now
"""
return datetime.datetime.now().strftime('%Y%m%d.%H%M%S.%f')
class Cli(cmd.Cmd, Suite):
def __init__(self, cfgfilename=default_config_file):
cmd.Cmd.__init__(self)
Suite.__init__(self, cfgfilename)
self.ruler = ''
def do_board(self, arg):
if arg:
self.board = arg
else:
print self.board
def do_serial(self, arg):
if arg:
self.serial = arg
else:
print self.serial
def do_extra_serial(self, arg):
if arg:
self.extra_serial = arg
else:
print self.extra_serial
def do_test_path(self, arg):
if arg:
self.test_path = arg
else:
print self.test_path
def do_log_path(self, arg):
if arg:
self.log_path = arg
else:
print self.log_path
def do_save(self, arg):
self.write_config()
def do_run(self, arg):
pass
def do_repeat(self, arg):
if arg:
try:
self.repeat = int(arg)
except ValueError:
print arg, 'is not an integer'
else:
print self.repeat
def do_EOF(self, arg):
print
return True
def do_quit(self, arg):
"exit cli"
return True
def do_show(self, arg):
"show current configuration of suite"
params_to_list = (
'board',
'serial',
'extra_serial',
'test_path',
'log_path',
'repeat',
'random', )
for param in params_to_list:
if param in self.__dict__:
print '%-12s' % (param + ':'),
print self.__getattribute__(param)
do_q = do_quit
do_h = cmd.Cmd.do_help
def normalize_testname(name):
if name[:4] == 'test':
return name[4:]
return name
def validate_args(args):
valid_args = [ normalize_testname(arg) for arg in args
if re.match(default_test_syntax, arg) ]
invalid_args = [ arg for arg in args
if not re.match(default_test_syntax, arg) ]
return valid_args, invalid_args
def main():
usage = ( '%prog: [options] test ...\n'
'run %prog with option -h or --help for more help' )
parser = OptionParser(usage)
parser.add_option("-c", "--config", dest="config",
default=default_config_file,
help="config file name")
parser.add_option("-C", "--cli", dest="cli", action="store_true",
help="enter command-line interpreter")
parser.add_option("-b", "--board", dest="board",
help="board name (e.g. -b SPEC)", metavar="NAME")
parser.add_option("-s", "--serial", dest="serial",
help="board serial number", metavar="SERIAL")
parser.add_option("-e", "--extra_serial", dest="extra_serial",
help="another board serial number [Optional]", metavar="SERIAL")
parser.add_option("-t", "--test-path", dest="test_path",
help="path to test files", metavar="PATH",
default=os.getcwd()+"/tests")
parser.add_option("-l", "--log-path", dest="log_path",
help="path to log files", metavar="PATH")
parser.add_option("-n", "--ntimes", dest="repeat",
help="number of times to repeat the batch of tests",
metavar="NUMBER")
parser.add_option("-r", "--randomize", action="store_true",
default=False,
help="run the batch in random order", )
parser.add_option("-w", "--write-config", action="store_true",
help="write configuration data to config file", )
parser.add_option("-y", "--yes", action="store_true",
help="assume all user interventions are affirmative", )
(options, args) = parser.parse_args()
# validate arguments and set up Suite object
if not args:
parser.print_usage()
return
valid, invalid = validate_args(args)
if invalid:
print 'invalid test names, aborting:',
for i in invalid: print i,
print
return
s = Cli(options.config)
s.__dict__.update(options.__dict__)
s.sequence = valid
try:
s.validate_and_compute_run()
except PtsInvalid, e:
print 'bad parameters:', e
return
# decide what to do
if options.write_config:
s.save()
elif options.cli:
s.cmdloop()
else:
s.run()
if __name__ == '__main__':
main()
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/ptsexcept.py 0000664 0000000 0000000 00000004135 13437225564 0026233 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: ptsexcept.py
##
## description: Generic PTS framework used for running the various tests and
## logging their outputs: common exceptions and handling
##
################################################################################
## Copyright CERN 2011-2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
class PtsException(Exception):
pass
class PtsCritical(PtsException):
"""critical error, abort the whole test suite"""
pass
class PtsError(PtsException):
"""error, continue remaining tests in test suite"""
pass
class PtsUser(PtsException):
"""error, user intervention required"""
pass
class PtsWarning(PtsException):
"""warning, a cautionary message should be displayed"""
pass
class PtsInvalid(PtsException):
"""reserved: invalid parameters"""
class PtsNoBatch(PtsInvalid):
"""reserved: a suite was created without batch of tests to run"""
pass
class PtsBadTestNo(PtsInvalid):
"""reserved: a bad test number was given"""
pass
if __name__ == '__main__':
pass
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/tests/ 0000775 0000000 0000000 00000000000 13437225564 0025001 5 ustar 00root root 0000000 0000000 conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/tests/test00.py 0000664 0000000 0000000 00000006412 13437225564 0026475 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: test00.py
##
## description: Test for reading out the RTM ID over I2C
##
################################################################################
## Copyright CERN 2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
# Import system modules
import os
import sys
import time
import configparser
# Import common modules
sys.path.append('..')
import utilities as util
import vv_skt
def main (card=None, default_directory='.',suite=None, serial=""):
testname= "Test00: DUT identification"
util.header_msg( testname, ["DUT identification"] )
###############################################################################
############################ initialization ###################################
###############################################################################
util.section_msg("I2C to read RTM ID")
test_results={}
config = configparser.ConfigParser()
config.read(default_directory + "/../../CONFIG.ini")
lun = int(config['DUT.FEC']['Slot'])
ip = config['DUT.FEC']['MgtHostName']
port = int(config['DUT.FEC']['MgtPort'])
user = config['DUT.FEC']['MgtUserName']
pwrd = config['DUT.FEC']['MgtPassword']
dut = vv_skt.SKT(lun, ip, port, user, pwrd)
###############################################################################
############################ actual test ######################################
###############################################################################
rtm = (dut.vv_read(4) >> 16) & 0x3f
if (rtm == 0x05):
test_results['DUT identification']= 1
util.info_msg("DUT identified; detection lines read correctly: 0x%02X" % rtm)
else:
test_results['DUT identification']= 0
util.err_msg("Identified wrong DUT; expected RTM ID 0x05 and received 0x%02X" % rtm)
###############################################################################
########################## result processing ##################################
###############################################################################
errors = util.summarise_test_results(testname, test_results)
sys.stdout.flush()
return 0;
if __name__ == '__main__' :
main()
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/tests/test01.py 0000664 0000000 0000000 00000006223 13437225564 0026476 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: test01.py
##
## description: Test LEDs
##
################################################################################
## Copyright CERN 2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
import sys
import os
import string
import time
sys.path.append('..')
import utilities as util
import ptsexcept
def test_led_all():
util.section_msg("Testing LEDs OFF state")
if not util.ask_user("Are all LEDs OFF now?"):
util.err_msg("Some LEDs might be broken")
return 0
util.section_msg("Testing LEDs ON state")
util.user_msg("---> Now make all the front panel connections and press [ENTER]")
ret = raw_input("")
# switch ON VME crate now..
# loop vv_read of BIDR reg to check when initialization is completed
if not util.ask_user("Are all LEDs ON now?"):
util.err_msg("Some LEDs or other board components might be broken")
return 0
util.info_msg("All LEDs verified successfully!")
return 1
def main (card=None, default_directory='.',suite=None, serial=""):
testname= "Test01: LEDs and basic connectivity"
util.header_msg( testname, [ "LED connectivity"] )
###############################################################################
############################ initialization ###################################
###############################################################################
test_results={}
###############################################################################
############################ actual test ######################################
###############################################################################
test_results['LEDs'] = test_led_all()
###############################################################################
########################## result processing ##################################
###############################################################################
errors = util.summarise_test_results( testname, test_results)
sys.stdout.flush()
return 0;
if __name__ == '__main__' :
main()
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/tests/test02.py 0000664 0000000 0000000 00000011437 13437225564 0026502 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: test02.py
##
## description: Test all transmitters and receivers by feeding them with a GMT
## signal and verifying that there are no errors on the CTRs.
##
################################################################################
## Copyright CERN 2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
###TODO: it seems the test passes when there is no CTR in the crate:-o
import os
import string
import time
import sys
import configparser
sys.path.append('..')
import utilities as util
import ptsexcept
def get_ctrtest_err(user, host, port, module):
cmd = 'echo "mo {0} rst" | /usr/local/bin/ctrtest-timdt | grep -A 7 -e MsMissedErrs | xargs'.format(module)
output = os.popen("ssh -p %d %s@%s '%s'" % (port, user, host, cmd)).read()
items = string.split(output)
mserr = '{0} {1} {2}'.format(items[1][1:], items[3][1:], items[4])
pllerr = '{0} {1} {2}'.format(items[6][1:], items[8][1:], items[9])
misserr = '{0} {1} {2}'.format(items[11][1:], items[13][1:], items[14])
return mserr, pllerr, misserr
def main (card=None, default_directory='.',suite=None, serial=""):
testname= "Test02: GMT transmission / reception"
util.header_msg( testname, [ "GMT transmission / reception"] )
###############################################################################
############################ initialization ###################################
###############################################################################
config = configparser.ConfigParser()
config.read(default_directory + "/../../CONFIG.ini")
host = config['CTR.FEC']['CpuHostName']
port = int(config['CTR.FEC']['CpuPort'])
user = config['CTR.FEC']['CpuUserName']
duration = float(config['CTR.FEC']['TstDuration'])
ms1 = [0, 0, 0, 0]
pll1 = [0, 0, 0, 0]
miss1 = [0, 0, 0, 0]
ms2 = [0, 0, 0, 0]
pll2 = [0, 0, 0, 0]
miss2 = [0, 0, 0, 0]
errors = False
test_results={}
test_results['Ms errors'] = 1
test_results['PLL errors'] = 1
test_results['Missed errors'] = 1
util.user_msg("---> Please make sure that the CTR FEC is powered on and has finished booting and then press [ENTER]")
ret = raw_input("")
util.user_msg("---> Please make sure that both the PLL and TMG LEDs on all four CTR cards are on and then press [ENTER]")
ret = raw_input("")
###############################################################################
############################ actual test ######################################
###############################################################################
for i in range(0,4):
ms1[i], pll1[i], miss1[i] = get_ctrtest_err(user, host, port, i+1)
time.sleep(duration)
for i in range(0,4):
ms2[i], pll2[i], miss2[i] = get_ctrtest_err(user, host, port, i+1)
if (ms1[i] != ms2[i]):
test_results['Ms errors'] = 0
util.err_msg("Module %s: Ms errors detected ({%s} != {%s})"%(i+1, ms2[i], ms1[i]))
if (pll1[i] != pll2[i]):
test_results['PLL errors'] = 0
util.err_msg("Module %s: PLL errors detected ({%s} != {%s})"%(i+1, pll2[i], pll1[i]))
if (miss1[i] != miss2[i]):
test_results['Missed errors'] = 0
util.err_msg("Module %s: Missed errors detected ({%s} != {%s})"%(i+1, miss2[i], miss1[i]))
###############################################################################
########################## result processing ##################################
###############################################################################
errors = util.summarise_test_results(testname, test_results)
sys.stdout.flush()
return 0
if __name__ == '__main__' :
main()
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/utilities.py 0000664 0000000 0000000 00000013132 13437225564 0026224 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: utilities.py
##
## description: Generic PTS framework used for running the various tests and
## logging their outputs: common utilities
##
################################################################################
## Copyright CERN 2011-2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
import os
import sys
import inspect
import numpy as np
import string
import ptsexcept
DEBUG = False
INFO = True
WARRNING = True
CRITICAL = True
def lineno(steps = 1):
"""Returns the current line number in our program."""
ptr = inspect.currentframe().f_back
for i in xrange(steps) :
ptr = ptr.f_back
ptr = ptr.f_lineno;
return ptr
# return inspect.currentframe().f_back.f_back.f_lineno
def linefile(steps = 1):
"""Returns the current line number in our program."""
ptr = inspect.currentframe().f_back
for i in xrange(steps) :
ptr = ptr.f_back
ptr = ptr.f_code;
return ptr
# return inspect.currentframe().f_back.f_back.f_code
# find absolute path of directory of name stored in topdirname
def find_prj_topdir(topdirname):
[ tmppath, dirname ] = os.path.split( os.getcwd() );
while( tmppath != '/' ):
if dirname == topdirname:
return os.path.join( tmppath, dirname)+"/"
[ tmppath, dirname ] = os.path.split(tmppath);
crit_msg("Top directory path not found\nPlease make sure that top directory of PTS OPT RTM is called \"opt-pts\"")
return "";
def user_msg( msg ):
print >> sys.__stdout__, ( "%s" % msg );
def dbg_msg( msg, steps = 1 ):
msg = string.replace(msg, "\n", "\n\t\t\t\t")
if DEBUG == True :
print ( "\t\t\tDEBUG: %s %s %s" % ( msg, linefile(steps), lineno(steps) ) );
def info_msg( msg ):
msg = string.replace(msg, "\n", "\n\t")
if INFO == True :
print ( "\t%s" % msg);
def warr_msg( string ):
string = string.replace(string, "\n", "\n\t\t")
if WARRNING == True :
print ( "\tWARRNING: %s" % string);
def err_msg( msg ):
# msg = string.replace(msg, "\n", "\n")
print ( "ERROR: %s" % msg);
def header_msg( testname, undertest ):
print ( "_______________________________________________________________");
print ( " %s " % testname );
print ( "_______________________________________________________________");
print ( "Testing:" );
for t in undertest:
print ("\t%s" % t )
print ( "_______________________________________________________________");
print("")
def info_err_msg( msg, err ):
if err:
err_msg(msg)
else :
info_msg(msg)
def section_msg( msg ):
# msg = string.replace(msg, "\n", "\n\t")
print ( "\n_________________ %s _________________" % msg);
def crit_msg( msg ):
print ( "CRITICAL: %s" % msg);
raise Exception("Critical: %s" % msg )
def ask_user( question ):
user_msg(question+" (Y/n)");
ret = raw_input("")
info_msg("User was asked:")
info_msg(question)
if ret == 'n':
info_msg("User replied: No")
return False
else:
info_msg("User replied: Yes")
return True
def u2int8(val):
if val & 0x8000:
val = np.int8( np.uint8( val ) ^ np.uint8( 0xfffff ) + 1 )
return val
def u2int16(val):
if val & 0x8000:
val = np.int16( np.uint16( val ) ^ np.uint16( 0xfffff ) + 1 )
return val
def u2int32(val):
if val & 0x80000000:
val = np.int32( np.uint32( val ) ^ np.uint32( 0xffffffffff ) + 1 )
return val
def u2int16arr(arr):
for i in xrange( len( arr ) ):
arr[i]=u2int16(arr[i])
return arr
def summarise_test_results( test_name, test_results ):
print "\n\n\n"
section_msg("Summary of %s" % test_name)
errors = 0
for k, v in test_results.iteritems():
if v == 0:
errors += 1;
info_msg("Subtest FAILED: %s!" % k )
else:
info_msg("Subtest SUCCESSFULL: %s!" % k )
if errors:
section_msg("%s failed with %d errors" % ( test_name, errors) )
raise ptsexcept.PtsError("%s failed with %d errors" % ( test_name, errors) )
else:
section_msg("%s finished successful" % test_name )
def bitvector( word, low, high ):
word = word & ( pow(2,high+1)-1 )
word = word >> low
return word
def merge_dictionaries(dict0, dict1):
return dict( dict0.items() + dict1.items() )
def merge_dictionaries_prefix(dict0, dict1, prefix0, prefix1):
tmp ={}
for k, v in dict0.iteritems():
tmp[prefix0+k]=v
for k, v in dict1.iteritems():
tmp[prefix1+k]=v
return tmp
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/python/vv_skt.py 0000664 0000000 0000000 00000006322 13437225564 0025530 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: vv_skt.py
##
## description: A simple python class to handle Telnet communication with an
## ELMA crate.
##
################################################################################
## Copyright CERN 2014-2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
import socket
from ptsexcept import *
import utilities as util
class SKT:
def __init__(self, lun, ip, port, user, pwrd):
""" Telnet access over a socket to ELMA I2C bus
"""
self.lun = lun
self.ip = ip
self.port = port
self.user = user
self.pwrd = pwrd
addr = (self.ip, self.port)
s = socket.create_connection(addr)
s.recv(256)
s.send("%s\r\n" % self.user)
s.recv(256)
s.send("%s\r\n" % self.pwrd)
s.recv(256)
self.handle = s
# get crate firmware version, to apply proper address in readreg/writereg
self.handle.send("version\r\n")
ver = self.handle.recv(256)
pos = ver.find("Software version")
if (pos == -1):
util.crit_msg("Crate %s not responding as expected" % self.addr)
sys.exit(2)
ver = float(ver[pos+17:pos+21])
self.ver = ver
def vv_read(self, byte_offset):
""" Read from the application FPGA via ELMA telnet
The byte offset will be aligned to D32
The value will contain the 32 bit integer read
"""
try:
cm = "readreg %d %x\r\n" % (self.lun, byte_offset)
if (self.ver < 2.27):
rn = byte_offset/4 + 1
cm = "readreg %d %d\r\n" % (self.lun,rn)
self.handle.send(cm)
orig = self.handle.recv(256)
rp = orig
rp = rp.split(" ")[3]
rp = rp.split("\n")[0]
rp = int(rp,16)
except Exception as e:
msg = "vv_read: No reply from register at address 0x%03x " % (byte_offset)
raise PtsException(msg)
return rp
def vv_close(self):
""" Close the socket
"""
self.handle.shutdown(SHUT_RDWR)
self.handle.close()
self.handle = 0
return 0
conv-rs485-opt-rtm-647571b98b49255a1fc3f29d58bf71048eb56466/pts/run-pts.py 0000775 0000000 0000000 00000006332 13437225564 0024307 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
################################################################################
## CERN BE-CO-HT
## CONV-RS485-OPT-RTM
## https://www.ohwr.org/projects/conv-rs485-opt-rtm
################################################################################
##
## unit name: run-pts.py
##
## description: Top level script to run the full PTS of the CONV-RS485-OPT-RTM.
##
################################################################################
## Copyright CERN 2019
################################################################################
##
## 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 .
##
## SPDX-License-Identifier: GPL-3.0-or-later
################################################################################
import os
import subprocess
import sys
import errno
import time
import configparser
BOARD = "OptRtm"
LOGDIR = os.path.abspath('log')
config = configparser.ConfigParser()
config.read('CONFIG.ini')
ip = config['DUT.FEC']['MgtHostName']
pwrd = config['DUT.FEC']['MgtPassword']
# Turn off DUT.FEC
fd = os.popen("snmpset -v2c -c %s %s 1.3.6.1.4.1.37968.1.1.7.2.1.3.1 i 1" % (pwrd, ip))
ret = fd.close()
if (ret != None):
print "ERROR accessing DUT.FEC over SNMP, exiting..."
sys.exit(ret >> 8)
time.sleep(2)
try:
os.makedirs(LOGDIR)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(LOGDIR):
pass
else:
raise
serial = "0000"
if (len(sys.argv) > 1):
serial = sys.argv[1]
else:
serial = raw_input(
"Please scan CERN serial number bar-code, then press [ENTER]: ")
if (serial == ""):
serial = "0000"
if (len(sys.argv) > 2):
extra_serial = sys.argv[2]
else:
extra_serial = raw_input(
"If needed input extra serial number and press [ENTER] OR just press [ENTER]: ")
if (extra_serial == ""):
extra_serial = "0000"
print
board_plugged = raw_input("---> Now please plug in the board and then press [ENTER]")
# Turn on DUT.FEC
fd = os.popen("snmpset -v2c -c %s %s 1.3.6.1.4.1.37968.1.1.7.2.1.3.1 i 0" % (pwrd, ip))
ret = fd.close()
if (ret != None):
print "ERROR accessing DUT.FEC over SNMP, exiting..."
sys.exit(ret >> 8)
time.sleep(10)
# run tests
os.chdir('python')
cmd = 'python pts.py -b {0} -s {1} -e {2} -l {3} 00 01 02'.format(
BOARD, serial, extra_serial, LOGDIR)
subprocess.call(cmd, shell = True)
os.chdir('..')
# Turn off DUT.FEC
fd = os.popen("snmpset -v2c -c %s %s 1.3.6.1.4.1.37968.1.1.7.2.1.3.1 i 1" % (pwrd, ip))
ret = fd.close()
if (ret != None):
print "ERROR accessing DUT.FEC over SNMP, exiting..."
sys.exit(ret >> 8)
time.sleep(2)
print
print "---------------"
print
print "End of the test"