-#!/usr/bin/python\r
-#######################################################################\r
-#\r
-# <COPYRIGHT_TAG>\r
-#\r
-#######################################################################\r
-\r
-"""This script run test cases with O-DU and O-RU\r
-"""\r
-import logging\r
-import sys\r
-import argparse\r
-import re\r
-import subprocess\r
-import os\r
-import shutil\r
-from itertools import dropwhile\r
-from datetime import datetime\r
-import json\r
-\r
-nNumRbsPerSymF1 = [\r
- # 5MHz 10MHz 15MHz 20 MHz 25 MHz 30 MHz 40 MHz 50MHz 60 MHz 70 MHz 80 MHz 90 MHz 100 MHz\r
- [25, 52, 79, 106, 133, 160, 216, 270, 0, 0, 0, 0, 0], # Numerology 0 (15KHz)\r
- [11, 24, 38, 51, 65, 78, 106, 133, 162, 0, 217, 245, 273], # Numerology 1 (30KHz)\r
- [0, 11, 18, 24, 31, 38, 51, 65, 79, 0, 107, 121, 135] # Numerology 2 (60KHz)\r
-]\r
-\r
-nNumRbsPerSymF2 = [\r
- # 50Mhz 100MHz 200MHz 400MHz\r
- [66, 132, 264, 0], # Numerology 2 (60KHz)\r
- [32, 66, 132, 264] # Numerology 3 (120KHz)\r
-]\r
-\r
-\r
-nRChBwOptions_keys = ['5','10','15','20', '25', '30', '40', '50', '60','70', '80', '90', '100', '200', '400']\r
-nRChBwOptions_values = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]\r
-nRChBwOptions = dict(zip(nRChBwOptions_keys, nRChBwOptions_values))\r
-\r
-nRChBwOptions_keys_mu2and3 = ['50', '100', '200', '400']\r
-nRChBwOptions_values_mu2and3 = [0,1,2,3]\r
-nRChBwOptions_mu2and3 = dict(zip(nRChBwOptions_keys_mu2and3, nRChBwOptions_values_mu2and3))\r
-\r
-# table of all test cases\r
-# (cat, mu, bw, test case)\r
-all_test_cases = [(0, 0, 5, 0),\r
- (0, 0, 10, 0),\r
- (0, 0, 20, 0),\r
- (0, 1, 100, 0),\r
- (0, 3, 100, 0),\r
- (1, 1, 100, 0)]\r
-#Cat B\r
-""" all_test_cases = [(1, 1, 100, 0),\r
- (1, 1, 100, 1),\r
- (1, 1, 100, 101),\r
- (1, 1, 100, 102),\r
- (1, 1, 100, 103),\r
- (1, 1, 100, 104),\r
- (1, 1, 100, 105),\r
- #(1, 1, 100, 106), 25G not enough\r
- (1, 1, 100, 107),\r
- (1, 1, 100, 108),\r
- #(1, 1, 100, 109), 25G not enough\r
- (1, 1, 100, 201),\r
- #(1, 1, 100, 202), 25G not enough\r
- (1, 1, 100, 203),\r
- (1, 1, 100, 204),\r
- (1, 1, 100, 205),\r
- (1, 1, 100, 206),\r
- (1, 1, 100, 211),\r
- #(1, 1, 100, 212), 25G not enough\r
- (1, 1, 100, 213),\r
- (1, 1, 100, 214),\r
- (1, 1, 100, 215),\r
- (1, 1, 100, 216)\r
-]\r
- """\r
-dic_dir = dict({0:'DL', 1:'UL'})\r
-dic_xu = dict({0:'o-du', 1:'o-ru'})\r
-\r
-def init_logger(console_level, logfile_level):\r
- """Initializes console and logfile logger with given logging levels"""\r
- # File logger\r
- logging.basicConfig(filename="runtests.log",\r
- filemode='w',\r
- format="%(asctime)s: %(levelname)s: %(message)s",\r
- level=logfile_level)\r
- # Console logger\r
- logger = logging.getLogger()\r
- handler = logging.StreamHandler()\r
- handler.setLevel(console_level)\r
- formatter = logging.Formatter("%(levelname)s: %(message)s")\r
- handler.setFormatter(formatter)\r
- logger.addHandler(handler)\r
-\r
-def parse_args(args):\r
- """Configures parser and parses command line configuration"""\r
- # Parser configuration\r
- parser = argparse.ArgumentParser(description="Run test cases: category numerology bandwidth test_num")\r
-\r
- parser.add_argument("--cat", type=int, default=0, help="Category: 0 (A) or 1 (B)", metavar="cat", dest="category")\r
- parser.add_argument("--mu", type=int, default=0, help="numerology [0,1,3]", metavar="num", dest="numerology")\r
- parser.add_argument("--bw", type=int, default=20, help="bandwidth [5,10,20,100]", metavar="bw", dest="bandwidth")\r
- parser.add_argument("--testcase", type=int, default=0, help="test case number", metavar="testcase", dest="testcase")\r
-\r
- # Parse arguments\r
- options = parser.parse_args(args)\r
- #parser.print_help()\r
- logging.debug("Options: category=%d num=%d bw=%d testcase=%d",\r
- options.category, options.numerology, options.bandwidth, options.testcase)\r
- return options\r
-\r
-def is_comment(s):\r
- """ function to check if a line\r
- starts with some character.\r
- Here # for comment\r
- """\r
- # return true if a line starts with #\r
- return s.startswith('#')\r
-\r
-class GetOutOfLoops( Exception ):\r
- pass\r
-\r
-def compare_resuts(cat, mu, bw, tcase, xran_path, test_cfg, direction):\r
- res = 0\r
-\r
- if mu < 3:\r
- nDlRB = nNumRbsPerSymF1[mu][nRChBwOptions.get(str(nDLBandwidth))]\r
- nUlRB = nNumRbsPerSymF1[mu][nRChBwOptions.get(str(nULBandwidth))]\r
- elif (mu >=2) & (mu <= 3):\r
- nDlRB = nNumRbsPerSymF2[mu - 2][nRChBwOptions_mu2and3.get(str(nDLBandwidth))]\r
- nUlRB = nNumRbsPerSymF2[mu - 2][nRChBwOptions_mu2and3.get(str(nULBandwidth))]\r
- print(nDlRB, nUlRB)\r
- else:\r
- print("Incorrect arguments\n")\r
- res = -1\r
- return res\r
-\r
- if 'compression' in globals():\r
- comp = compression\r
- else:\r
- comp = 0\r
-\r
- print("compare results: {} [compression {}]\n".format(dic_dir.get(direction), comp))\r
-\r
- #if cat == 1:\r
- # print("WARNING: Skip checking IQs and BF Weights for CAT B for now\n");\r
- # return res\r
-\r
- #get slot config\r
- if nFrameDuplexType == 1:\r
- SlotConfig = []\r
- for i in range(nTddPeriod):\r
- if i == 0:\r
- SlotConfig.insert(i, sSlotConfig0)\r
- elif i == 1:\r
- SlotConfig.insert(i, sSlotConfig1)\r
- elif i == 2:\r
- SlotConfig.insert(i, sSlotConfig2)\r
- elif i == 3:\r
- SlotConfig.insert(i, sSlotConfig3)\r
- elif i == 4:\r
- SlotConfig.insert(i, sSlotConfig4)\r
- elif i == 5:\r
- SlotConfig.insert(i, sSlotConfig5)\r
- elif i == 6:\r
- SlotConfig.insert(i, sSlotConfig6)\r
- elif i == 7:\r
- SlotConfig.insert(i, sSlotConfig7)\r
- elif i == 8:\r
- SlotConfig.insert(i, sSlotConfig8)\r
- elif i == 9:\r
- SlotConfig.insert(i, sSlotConfig9)\r
- else :\r
- raise Exception('i should not exceed nTddPeriod %d. The value of i was: {}'.format(nTddPeriod, i))\r
- #print(SlotConfig, type(sSlotConfig0))\r
- try:\r
-\r
- if (direction == 1) & (cat == 1): #UL\r
- flowId = ccNum*antNumUL\r
- else:\r
- flowId = ccNum*antNum\r
-\r
- for i in range(0, flowId):\r
- #read ref and test files\r
- tst = []\r
- ref = []\r
- if direction == 0:\r
- # DL\r
- nRB = nDlRB\r
- file_tst = xran_path+"/app/logs/"+"o-ru-rx_log_ant"+str(i)+".txt"\r
- file_ref = xran_path+"/app/logs/"+"o-du-play_ant"+str(i)+".txt"\r
- elif direction == 1:\r
- # UL\r
- nRB = nUlRB\r
- file_tst = xran_path+"/app/logs/"+"o-du-rx_log_ant"+str(i)+".txt"\r
- file_ref = xran_path+"/app/logs/"+"o-ru-play_ant"+str(i)+".txt"\r
- else:\r
- raise Exception('Direction is not supported %d'.format(direction))\r
-\r
- print("test result :", file_tst)\r
- print("test reference:", file_ref)\r
- if os.path.exists(file_tst):\r
- try:\r
- file_tst = open(file_tst, 'r')\r
- except OSError:\r
- print ("Could not open/read file:", file_tst)\r
- sys.exit()\r
- else:\r
- print(file_tst, "doesn't exist")\r
- res = -1\r
- return res\r
- if os.path.exists(file_ref):\r
- try:\r
- file_ref = open(file_ref, 'r')\r
- except OSError:\r
- print ("Could not open/read file:", file_ref)\r
- sys.exit()\r
- else:\r
- print(file_tst, "doesn't exist")\r
- res = -1\r
- return res\r
-\r
- tst = file_tst.readlines()\r
- ref = file_ref.readlines()\r
-\r
- print(len(tst))\r
- print(len(ref))\r
-\r
- file_tst.close();\r
- file_ref.close();\r
-\r
- print(numSlots)\r
-\r
- for slot_idx in range(0, numSlots):\r
- for sym_idx in range(0, 14):\r
- if nFrameDuplexType==1:\r
- #skip sym if TDD\r
- if direction == 0:\r
- #DL\r
- sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]\r
- if(sym_dir != 0):\r
- continue\r
- elif direction == 1:\r
- #UL\r
- sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]\r
- if(sym_dir != 1):\r
- continue\r
-\r
- #print("Check:","[",i,"]", slot_idx, sym_idx)\r
- for line_idx in range(0, nRB*12):\r
- offset = (slot_idx*nRB*12*14) + sym_idx*nRB*12 + line_idx\r
- line_tst = tst[offset].rstrip()\r
- line_ref = ref[offset].rstrip()\r
- if comp == 1:\r
- # discard LSB bits as BFP compression is not Bit Exact\r
- tst_i_value = int(line_tst.split(" ")[0]) & 0xFF80\r
- tst_q_value = int(line_tst.split(" ")[1]) & 0xFF80\r
- ref_i_value = int(line_ref.split(" ")[0]) & 0xFF80\r
- ref_q_value = int(line_ref.split(" ")[1]) & 0xFF80\r
-\r
- print("check:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")\r
- if (tst_i_value != ref_i_value) or (tst_q_value != ref_q_value) :\r
- print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")\r
- res = -1\r
- raise GetOutOfLoops\r
- else:\r
- #if line_idx == 0:\r
- #print("Check:", offset,"[",i,"]", slot_idx, sym_idx,":",line_tst, line_ref)\r
- if line_ref != line_tst:\r
- print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst:", line_tst, "ref:", line_ref)\r
- res = -1\r
- raise GetOutOfLoops\r
- except GetOutOfLoops:\r
- pass\r
-\r
- return res\r
-\r
-def parse_dat_file(cat, mu, bw, tcase, xran_path, test_cfg):\r
- #parse config files\r
- logging.info("parse config files %s\n", test_cfg[0])\r
- lineList = list()\r
- sep = '#'\r
- with open(test_cfg[0],'r') as fh:\r
- for curline in dropwhile(is_comment, fh):\r
- my_line = curline.rstrip().split(sep, 1)[0].strip()\r
- if my_line:\r
- lineList.append(my_line)\r
- global_env = {}\r
- local_env = {}\r
-\r
- for line in lineList:\r
- exe_line = line.replace(":", ",")\r
- if exe_line.find("/") > 0 :\r
- exe_line = exe_line.replace('./', "'")\r
- exe_line = exe_line+"'"\r
-\r
- code = compile(str(exe_line), '<string>', 'exec')\r
- exec (code, global_env, local_env)\r
-\r
- for k, v in local_env.items():\r
- globals()[k] = v\r
- print(k, v)\r
-\r
- return local_env\r
-\r
-def make_copy_mlog(cat, mu, bw, tcase, xran_path):\r
- res = 0\r
-\r
- src_bin = xran_path+"/app/mlog-o-du-c0.bin"\r
- src_csv = xran_path+"/app/mlog-o-du-hist.csv"\r
- dst_bin = xran_path+"/app/mlog-o-du-c0-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".bin"\r
- dst_csv = xran_path+"/app/mlog-o-du-hist-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".csv"\r
-\r
- try:\r
- d_bin = shutil.copyfile(src_bin, dst_bin)\r
- d_csv = shutil.copyfile(src_csv, dst_csv)\r
- except IOError:\r
- logging.info("MLog is not present\n")\r
- res = 1\r
- else:\r
- logging.info("Mlog was copied\n")\r
-\r
- print("Destination path:", d_bin)\r
- print("Destination path:", d_csv)\r
-\r
- d_bin = shutil.copyfile(src_bin, dst_bin)\r
- d_csv = shutil.copyfile(src_csv, dst_csv)\r
-\r
- #print("After copying file:")\r
- #print(os.listdir(xran_path+"/app/"))\r
-\r
- #print("Destination path:", d_bin)\r
- #print("Destination path:", d_csv)\r
-\r
- src_bin = xran_path+"/app/mlog-o-ru-c0.bin"\r
- src_csv = xran_path+"/app/mlog-o-ru-hist.csv"\r
- dst_bin = xran_path+"/app/mlog-o-ru-c0-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".bin"\r
- dst_csv = xran_path+"/app/mlog-o-ru-hist-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".csv"\r
-\r
- d_bin = shutil.copyfile(src_bin, dst_bin)\r
- d_csv = shutil.copyfile(src_csv, dst_csv)\r
-\r
- #print("After copying file:")\r
- #print(os.listdir(xran_path+"/app/"))\r
-\r
- #print("Destination path:", d_bin)\r
- #print("Destination path:", d_csv)\r
-\r
- try:\r
- d_bin = shutil.copyfile(src_bin, dst_bin)\r
- d_csv = shutil.copyfile(src_csv, dst_csv)\r
- except IOError:\r
- logging.info("MLog is not present\n")\r
- res = 1\r
- else:\r
- logging.info("Mlog was copied\n")\r
-\r
- #print("After copying file:")\r
- #print(os.listdir(xran_path+"/app/"))\r
-\r
- #print("Destination path:", d_bin)\r
- #print("Destination path:", d_csv)\r
-\r
- return res\r
-\r
-\r
-def run_tcase(cat, mu, bw, tcase, xran_path):\r
- if cat == 1:\r
- test_config = xran_path+"/app/usecase/cat_b/mu{0:d}_{1:d}mhz".format(mu, bw)\r
- elif cat == 0 :\r
- test_config = xran_path+"/app/usecase/mu{0:d}_{1:d}mhz".format(mu, bw)\r
- else:\r
- print("Incorrect arguments\n")\r
-\r
- if(tcase > 0) :\r
- test_config = test_config+"/"+str(tcase)\r
-\r
- app = xran_path+"/app/build/sample-app"\r
-\r
- logging.debug("run: %s %s", app, test_config)\r
- logging.debug("Started script: master.py, XRAN path %s", xran_path)\r
-\r
- test_cfg = []\r
- #TODO: add detection of ETH ports\r
- eth_cp_dev = ["0000:22:02.1", "0000:22:0a.1"]\r
- eth_up_dev = ["0000:22:02.0", "0000:22:0a.0"]\r
-\r
- test_cfg.append(test_config+"/config_file_o_du.dat")\r
- test_cfg.append(test_config+"/config_file_o_ru.dat")\r
-\r
- wd = os.getcwd()\r
- os.chdir(xran_path+"/app/")\r
-\r
- processes = []\r
- logfile_xu = []\r
- log_file_name = []\r
-\r
- os.system('rm -rf ./logs')\r
-\r
- for i in range(2):\r
- log_file_name.append("sampleapp_log_{}_cat_{}_mu{}_{}mhz_tst_{}.log".format(dic_xu.get(i),cat, mu, bw, tcase))\r
- with open(log_file_name[i], "w") as f:\r
- #, stdout=f, stderr=f\r
- p = subprocess.Popen([app, test_cfg[i], eth_up_dev[i], eth_cp_dev[i]], stdout=f, stderr=f)\r
- logfile_xu.insert(i, f)\r
- processes.append((p, logfile_xu[i]))\r
-\r
- logging.info("Running O-DU and O-RU see output in: %s %s\n", logfile_xu[0].name, logfile_xu[1].name)\r
- for p, f in processes:\r
- p.wait()\r
- p.communicate()[0]\r
- if p.returncode != 0:\r
- print("Application {} failed p.returncode:{}".format(dic_xu.get(i), p.returncode))\r
- print("FAIL")\r
- logging.info("FAIL\n")\r
- logging.shutdown()\r
- sys.exit(p.returncode)\r
-\r
- f.close()\r
-\r
- logging.info("O-DU and O-RU are done\n")\r
-\r
- make_copy_mlog(cat, mu, bw, tcase, xran_path)\r
-\r
- usecase_cfg = parse_dat_file(cat, mu, bw, tcase, xran_path, test_cfg)\r
-\r
- res = compare_resuts(cat, mu, bw, tcase, xran_path, test_cfg, 0)\r
- if res != 0:\r
- os.chdir(wd)\r
- print("FAIL")\r
- return res\r
-\r
- res = compare_resuts(cat, mu, bw, tcase, xran_path, test_cfg, 1)\r
- if res != 0:\r
- os.chdir(wd)\r
- print("FAIL")\r
- return res\r
-\r
- os.chdir(wd)\r
- print("PASS")\r
- return res\r
-\r
-def main():\r
- test_results = []\r
- test_executed_total = 0\r
- run_total = 0\r
- cat = 0\r
- mu = 0\r
- bw = 0\r
- tcase = 0\r
- """Processes input files to produce IACA files"""\r
- # Find path to XRAN\r
- xran_path = os.getenv("XRAN_DIR")\r
-\r
- # Set up logging with given level (DEBUG, INFO, ERROR) for console end logfile\r
- init_logger(logging.INFO, logging.DEBUG)\r
- logging.info("Started script: master.py, XRAN path %s", xran_path)\r
-\r
- # Parse input arguments\r
- if len(sys.argv) == 1 :\r
- run_total = len(all_test_cases)\r
- print(run_total)\r
- print("Run All test cases {}\n".format(run_total))\r
- else:\r
- options = parse_args(sys.argv[1:])\r
- cat = options.category\r
- mu = options.numerology\r
- bw = options.bandwidth\r
- tcase = options.testcase\r
-\r
-\r
- if (run_total):\r
- for test_run_ix in range(0, run_total):\r
- cat = all_test_cases[test_run_ix][0]\r
- mu = all_test_cases[test_run_ix][1]\r
- bw = all_test_cases[test_run_ix][2]\r
- tcase = all_test_cases[test_run_ix][3]\r
-\r
- res = run_tcase(cat, mu, bw, tcase, xran_path)\r
- if (res != 0):\r
- test_results.append((cat, mu, bw, tcase,'FAIL'))\r
- break;\r
-\r
- test_results.append((cat, mu, bw, tcase,'PASS'))\r
- else:\r
- res = run_tcase(cat, mu, bw, tcase, xran_path)\r
- if (res != 0):\r
- test_results.append((cat, mu, bw, tcase,'FAIL'))\r
- test_results.append((cat, mu, bw, tcase,'PASS'))\r
-\r
- with open('testresult.txt', 'w') as reshandle:\r
- json.dump(test_results, reshandle)\r
-\r
- return res\r
-\r
-if __name__ == '__main__':\r
- START_TIME = datetime.now()\r
- res = main()\r
- END_TIME = datetime.now()\r
- logging.debug("Start time: %s, end time: %s", START_TIME, END_TIME)\r
- logging.info("Execution time: %s", END_TIME - START_TIME)\r
- logging.shutdown()\r
- sys.exit(res)\r
+#!/usr/bin/python
+#******************************************************************************
+#
+# Copyright (c) 2019 Intel.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#******************************************************************************/
+
+"""This script run test cases with O-DU and O-RU
+"""
+import logging
+import sys
+import argparse
+import re
+import subprocess
+import os
+import shutil
+from itertools import dropwhile
+from datetime import datetime
+import json
+
+nNumRbsPerSymF1 = [
+ # 5MHz 10MHz 15MHz 20 MHz 25 MHz 30 MHz 40 MHz 50MHz 60 MHz 70 MHz 80 MHz 90 MHz 100 MHz
+ [25, 52, 79, 106, 133, 160, 216, 270, 0, 0, 0, 0, 0], # Numerology 0 (15KHz)
+ [11, 24, 38, 51, 65, 78, 106, 133, 162, 0, 217, 245, 273], # Numerology 1 (30KHz)
+ [0, 11, 18, 24, 31, 38, 51, 65, 79, 0, 107, 121, 135] # Numerology 2 (60KHz)
+]
+
+nNumRbsPerSymF2 = [
+ # 50Mhz 100MHz 200MHz 400MHz
+ [66, 132, 264, 0], # Numerology 2 (60KHz)
+ [32, 66, 132, 264] # Numerology 3 (120KHz)
+]
+
+
+nRChBwOptions_keys = ['5','10','15','20', '25', '30', '40', '50', '60','70', '80', '90', '100', '200', '400']
+nRChBwOptions_values = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
+nRChBwOptions = dict(zip(nRChBwOptions_keys, nRChBwOptions_values))
+
+nRChBwOptions_keys_mu2and3 = ['50', '100', '200', '400']
+nRChBwOptions_values_mu2and3 = [0,1,2,3]
+nRChBwOptions_mu2and3 = dict(zip(nRChBwOptions_keys_mu2and3, nRChBwOptions_values_mu2and3))
+
+# table of all test cases
+# (cat, mu, bw, test case)
+all_test_cases = [(0, 0, 5, 0),
+ (0, 0, 10, 0),
+ (0, 0, 20, 0),
+ (0, 1, 100, 0),
+ (0, 3, 100, 0),
+ (1, 1, 100, 0)]
+#Cat B
+""" all_test_cases = [(1, 1, 100, 0),
+ (1, 1, 100, 1),
+ (1, 1, 100, 101),
+ (1, 1, 100, 102),
+ (1, 1, 100, 103),
+ (1, 1, 100, 104),
+ (1, 1, 100, 105),
+ #(1, 1, 100, 106), 25G not enough
+ (1, 1, 100, 107),
+ (1, 1, 100, 108),
+ #(1, 1, 100, 109), 25G not enough
+ (1, 1, 100, 201),
+ #(1, 1, 100, 202), 25G not enough
+ (1, 1, 100, 203),
+ (1, 1, 100, 204),
+ (1, 1, 100, 205),
+ (1, 1, 100, 206),
+ (1, 1, 100, 211),
+ #(1, 1, 100, 212), 25G not enough
+ (1, 1, 100, 213),
+ (1, 1, 100, 214),
+ (1, 1, 100, 215),
+ (1, 1, 100, 216)
+]
+ """
+dic_dir = dict({0:'DL', 1:'UL'})
+dic_xu = dict({0:'o-du', 1:'o-ru'})
+
+def init_logger(console_level, logfile_level):
+ """Initializes console and logfile logger with given logging levels"""
+ # File logger
+ logging.basicConfig(filename="runtests.log",
+ filemode='w',
+ format="%(asctime)s: %(levelname)s: %(message)s",
+ level=logfile_level)
+ # Console logger
+ logger = logging.getLogger()
+ handler = logging.StreamHandler()
+ handler.setLevel(console_level)
+ formatter = logging.Formatter("%(levelname)s: %(message)s")
+ handler.setFormatter(formatter)
+ logger.addHandler(handler)
+
+def parse_args(args):
+ """Configures parser and parses command line configuration"""
+ # Parser configuration
+ parser = argparse.ArgumentParser(description="Run test cases: category numerology bandwidth test_num")
+
+ parser.add_argument("--cat", type=int, default=0, help="Category: 0 (A) or 1 (B)", metavar="cat", dest="category")
+ parser.add_argument("--mu", type=int, default=0, help="numerology [0,1,3]", metavar="num", dest="numerology")
+ parser.add_argument("--bw", type=int, default=20, help="bandwidth [5,10,20,100]", metavar="bw", dest="bandwidth")
+ parser.add_argument("--testcase", type=int, default=0, help="test case number", metavar="testcase", dest="testcase")
+
+ # Parse arguments
+ options = parser.parse_args(args)
+ #parser.print_help()
+ logging.debug("Options: category=%d num=%d bw=%d testcase=%d",
+ options.category, options.numerology, options.bandwidth, options.testcase)
+ return options
+
+def is_comment(s):
+ """ function to check if a line
+ starts with some character.
+ Here # for comment
+ """
+ # return true if a line starts with #
+ return s.startswith('#')
+
+class GetOutOfLoops( Exception ):
+ pass
+
+def compare_resuts(cat, mu, bw, tcase, xran_path, test_cfg, direction):
+ res = 0
+
+ if mu < 3:
+ nDlRB = nNumRbsPerSymF1[mu][nRChBwOptions.get(str(nDLBandwidth))]
+ nUlRB = nNumRbsPerSymF1[mu][nRChBwOptions.get(str(nULBandwidth))]
+ elif (mu >=2) & (mu <= 3):
+ nDlRB = nNumRbsPerSymF2[mu - 2][nRChBwOptions_mu2and3.get(str(nDLBandwidth))]
+ nUlRB = nNumRbsPerSymF2[mu - 2][nRChBwOptions_mu2and3.get(str(nULBandwidth))]
+ print(nDlRB, nUlRB)
+ else:
+ print("Incorrect arguments\n")
+ res = -1
+ return res
+
+ if 'compression' in globals():
+ comp = compression
+ else:
+ comp = 0
+
+ print("compare results: {} [compression {}]\n".format(dic_dir.get(direction), comp))
+
+ #if cat == 1:
+ # print("WARNING: Skip checking IQs and BF Weights for CAT B for now\n");
+ # return res
+
+ #get slot config
+ if nFrameDuplexType == 1:
+ SlotConfig = []
+ for i in range(nTddPeriod):
+ if i == 0:
+ SlotConfig.insert(i, sSlotConfig0)
+ elif i == 1:
+ SlotConfig.insert(i, sSlotConfig1)
+ elif i == 2:
+ SlotConfig.insert(i, sSlotConfig2)
+ elif i == 3:
+ SlotConfig.insert(i, sSlotConfig3)
+ elif i == 4:
+ SlotConfig.insert(i, sSlotConfig4)
+ elif i == 5:
+ SlotConfig.insert(i, sSlotConfig5)
+ elif i == 6:
+ SlotConfig.insert(i, sSlotConfig6)
+ elif i == 7:
+ SlotConfig.insert(i, sSlotConfig7)
+ elif i == 8:
+ SlotConfig.insert(i, sSlotConfig8)
+ elif i == 9:
+ SlotConfig.insert(i, sSlotConfig9)
+ else :
+ raise Exception('i should not exceed nTddPeriod %d. The value of i was: {}'.format(nTddPeriod, i))
+ #print(SlotConfig, type(sSlotConfig0))
+ try:
+
+ if (direction == 1) & (cat == 1): #UL
+ flowId = ccNum*antNumUL
+ else:
+ flowId = ccNum*antNum
+
+ for i in range(0, flowId):
+ #read ref and test files
+ tst = []
+ ref = []
+ if direction == 0:
+ # DL
+ nRB = nDlRB
+ file_tst = xran_path+"/app/logs/"+"o-ru-rx_log_ant"+str(i)+".txt"
+ file_ref = xran_path+"/app/logs/"+"o-du-play_ant"+str(i)+".txt"
+ elif direction == 1:
+ # UL
+ nRB = nUlRB
+ file_tst = xran_path+"/app/logs/"+"o-du-rx_log_ant"+str(i)+".txt"
+ file_ref = xran_path+"/app/logs/"+"o-ru-play_ant"+str(i)+".txt"
+ else:
+ raise Exception('Direction is not supported %d'.format(direction))
+
+ print("test result :", file_tst)
+ print("test reference:", file_ref)
+ if os.path.exists(file_tst):
+ try:
+ file_tst = open(file_tst, 'r')
+ except OSError:
+ print ("Could not open/read file:", file_tst)
+ sys.exit()
+ else:
+ print(file_tst, "doesn't exist")
+ res = -1
+ return res
+ if os.path.exists(file_ref):
+ try:
+ file_ref = open(file_ref, 'r')
+ except OSError:
+ print ("Could not open/read file:", file_ref)
+ sys.exit()
+ else:
+ print(file_tst, "doesn't exist")
+ res = -1
+ return res
+
+ tst = file_tst.readlines()
+ ref = file_ref.readlines()
+
+ print(len(tst))
+ print(len(ref))
+
+ file_tst.close();
+ file_ref.close();
+
+ print(numSlots)
+
+ for slot_idx in range(0, numSlots):
+ for sym_idx in range(0, 14):
+ if nFrameDuplexType==1:
+ #skip sym if TDD
+ if direction == 0:
+ #DL
+ sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
+ if(sym_dir != 0):
+ continue
+ elif direction == 1:
+ #UL
+ sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
+ if(sym_dir != 1):
+ continue
+
+ #print("Check:","[",i,"]", slot_idx, sym_idx)
+ for line_idx in range(0, nRB*12):
+ offset = (slot_idx*nRB*12*14) + sym_idx*nRB*12 + line_idx
+ line_tst = tst[offset].rstrip()
+ line_ref = ref[offset].rstrip()
+ if comp == 1:
+ # discard LSB bits as BFP compression is not Bit Exact
+ tst_i_value = int(line_tst.split(" ")[0]) & 0xFF80
+ tst_q_value = int(line_tst.split(" ")[1]) & 0xFF80
+ ref_i_value = int(line_ref.split(" ")[0]) & 0xFF80
+ ref_q_value = int(line_ref.split(" ")[1]) & 0xFF80
+
+ print("check:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
+ if (tst_i_value != ref_i_value) or (tst_q_value != ref_q_value) :
+ print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
+ res = -1
+ raise GetOutOfLoops
+ else:
+ #if line_idx == 0:
+ #print("Check:", offset,"[",i,"]", slot_idx, sym_idx,":",line_tst, line_ref)
+ if line_ref != line_tst:
+ print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst:", line_tst, "ref:", line_ref)
+ res = -1
+ raise GetOutOfLoops
+ except GetOutOfLoops:
+ pass
+
+ return res
+
+def parse_dat_file(cat, mu, bw, tcase, xran_path, test_cfg):
+ #parse config files
+ logging.info("parse config files %s\n", test_cfg[0])
+ lineList = list()
+ sep = '#'
+ with open(test_cfg[0],'r') as fh:
+ for curline in dropwhile(is_comment, fh):
+ my_line = curline.rstrip().split(sep, 1)[0].strip()
+ if my_line:
+ lineList.append(my_line)
+ global_env = {}
+ local_env = {}
+
+ for line in lineList:
+ exe_line = line.replace(":", ",")
+ if exe_line.find("/") > 0 :
+ exe_line = exe_line.replace('./', "'")
+ exe_line = exe_line+"'"
+
+ code = compile(str(exe_line), '<string>', 'exec')
+ exec (code, global_env, local_env)
+
+ for k, v in local_env.items():
+ globals()[k] = v
+ print(k, v)
+
+ return local_env
+
+def make_copy_mlog(cat, mu, bw, tcase, xran_path):
+ res = 0
+
+ src_bin = xran_path+"/app/mlog-o-du-c0.bin"
+ src_csv = xran_path+"/app/mlog-o-du-hist.csv"
+ dst_bin = xran_path+"/app/mlog-o-du-c0-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".bin"
+ dst_csv = xran_path+"/app/mlog-o-du-hist-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".csv"
+
+ try:
+ d_bin = shutil.copyfile(src_bin, dst_bin)
+ d_csv = shutil.copyfile(src_csv, dst_csv)
+ except IOError:
+ logging.info("MLog is not present\n")
+ res = 1
+ else:
+ logging.info("Mlog was copied\n")
+
+
+ src_bin = xran_path+"/app/mlog-o-ru-c0.bin"
+ src_csv = xran_path+"/app/mlog-o-ru-hist.csv"
+ dst_bin = xran_path+"/app/mlog-o-ru-c0-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".bin"
+ dst_csv = xran_path+"/app/mlog-o-ru-hist-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".csv"
+
+
+ try:
+ d_bin = shutil.copyfile(src_bin, dst_bin)
+ d_csv = shutil.copyfile(src_csv, dst_csv)
+ except IOError:
+ logging.info("MLog is not present\n")
+ res = 1
+ else:
+ logging.info("Mlog was copied\n")
+
+
+ return res
+
+
+def run_tcase(cat, mu, bw, tcase, xran_path):
+ if cat == 1:
+ test_config = xran_path+"/app/usecase/cat_b/mu{0:d}_{1:d}mhz".format(mu, bw)
+ elif cat == 0 :
+ test_config = xran_path+"/app/usecase/mu{0:d}_{1:d}mhz".format(mu, bw)
+ else:
+ print("Incorrect arguments\n")
+
+ if(tcase > 0) :
+ test_config = test_config+"/"+str(tcase)
+
+ app = xran_path+"/app/build/sample-app"
+
+ logging.debug("run: %s %s", app, test_config)
+ logging.debug("Started script: master.py, XRAN path %s", xran_path)
+
+ test_cfg = []
+ #TODO: add detection of ETH ports
+ eth_cp_dev = ["0000:22:02.1", "0000:22:0a.1"]
+ eth_up_dev = ["0000:22:02.0", "0000:22:0a.0"]
+
+ test_cfg.append(test_config+"/config_file_o_du.dat")
+ test_cfg.append(test_config+"/config_file_o_ru.dat")
+
+ wd = os.getcwd()
+ os.chdir(xran_path+"/app/")
+
+ processes = []
+ logfile_xu = []
+ log_file_name = []
+
+ os.system('rm -rf ./logs')
+
+ for i in range(2):
+ log_file_name.append("sampleapp_log_{}_cat_{}_mu{}_{}mhz_tst_{}.log".format(dic_xu.get(i),cat, mu, bw, tcase))
+ with open(log_file_name[i], "w") as f:
+ #, stdout=f, stderr=f
+ p = subprocess.Popen([app, test_cfg[i], eth_up_dev[i], eth_cp_dev[i]], stdout=f, stderr=f)
+ logfile_xu.insert(i, f)
+ processes.append((p, logfile_xu[i]))
+
+ logging.info("Running O-DU and O-RU see output in: %s %s\n", logfile_xu[0].name, logfile_xu[1].name)
+ for p, f in processes:
+ p.wait()
+ p.communicate()[0]
+ if p.returncode != 0:
+ print("Application {} failed p.returncode:{}".format(dic_xu.get(i), p.returncode))
+ print("FAIL")
+ logging.info("FAIL\n")
+ logging.shutdown()
+ sys.exit(p.returncode)
+
+ f.close()
+
+ logging.info("O-DU and O-RU are done\n")
+
+ make_copy_mlog(cat, mu, bw, tcase, xran_path)
+
+ usecase_cfg = parse_dat_file(cat, mu, bw, tcase, xran_path, test_cfg)
+
+ res = compare_resuts(cat, mu, bw, tcase, xran_path, test_cfg, 0)
+ if res != 0:
+ os.chdir(wd)
+ print("FAIL")
+ return res
+
+ res = compare_resuts(cat, mu, bw, tcase, xran_path, test_cfg, 1)
+ if res != 0:
+ os.chdir(wd)
+ print("FAIL")
+ return res
+
+ os.chdir(wd)
+ print("PASS")
+ return res
+
+def main():
+ test_results = []
+ test_executed_total = 0
+ run_total = 0
+ cat = 0
+ mu = 0
+ bw = 0
+ tcase = 0
+ """Processes input files to produce IACA files"""
+ # Find path to XRAN
+ xran_path = os.getenv("XRAN_DIR")
+
+ # Set up logging with given level (DEBUG, INFO, ERROR) for console end logfile
+ init_logger(logging.INFO, logging.DEBUG)
+ logging.info("Started script: master.py, XRAN path %s", xran_path)
+
+ # Parse input arguments
+ if len(sys.argv) == 1 :
+ run_total = len(all_test_cases)
+ print(run_total)
+ print("Run All test cases {}\n".format(run_total))
+ else:
+ options = parse_args(sys.argv[1:])
+ cat = options.category
+ mu = options.numerology
+ bw = options.bandwidth
+ tcase = options.testcase
+
+
+ if (run_total):
+ for test_run_ix in range(0, run_total):
+ cat = all_test_cases[test_run_ix][0]
+ mu = all_test_cases[test_run_ix][1]
+ bw = all_test_cases[test_run_ix][2]
+ tcase = all_test_cases[test_run_ix][3]
+
+ res = run_tcase(cat, mu, bw, tcase, xran_path)
+ if (res != 0):
+ test_results.append((cat, mu, bw, tcase,'FAIL'))
+ break;
+
+ test_results.append((cat, mu, bw, tcase,'PASS'))
+ else:
+ res = run_tcase(cat, mu, bw, tcase, xran_path)
+ if (res != 0):
+ test_results.append((cat, mu, bw, tcase,'FAIL'))
+ test_results.append((cat, mu, bw, tcase,'PASS'))
+
+ with open('testresult.txt', 'w') as reshandle:
+ json.dump(test_results, reshandle)
+
+ return res
+
+if __name__ == '__main__':
+ START_TIME = datetime.now()
+ res = main()
+ END_TIME = datetime.now()
+ logging.debug("Start time: %s, end time: %s", START_TIME, END_TIME)
+ logging.info("Execution time: %s", END_TIME - START_TIME)
+ logging.shutdown()
+ sys.exit(res)