Skip to content

Commit 896ab6e

Browse files
author
Qinghao Shi
authored
Merge CI_test branch into master (#5)
* update README.md with commands install GreanTea and htrun * update settings.json according to CI test * add files and changes for code coverage * update README.md reflex Greentea update * update configuration files with correct port number * update setup.py * update README for more details * update script for python3 support
1 parent 6542fee commit 896ab6e

File tree

10 files changed

+206
-31
lines changed

10 files changed

+206
-31
lines changed

README.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,31 @@
44

55
mbed-fastmodel-agent is a python module for Mbed OS GreenTea testing framework using FastModels FVP (Fixed Virtual Platforms).
66

7-
This module only designed to work with [Greentea](https://github.com/ARMmbed/greentea) and [Htrun](https://github.com/ARMmbed/htrun),
7+
This module only designed to work with [Greentea](https://github.com/ARMmbed/mbed-os-tools/tree/master/packages/mbed-greentea) and [Htrun](https://github.com/ARMmbed/mbed-os-tools/tree/master/packages/mbed-host-tests),
88
It enables enables Fast Models to run Mbed OS Greentea test suites.
99

1010
If user only need to run mbed OS applications or examples rather than Greentea tests on Fast Models, please referencing [this mbed OS documents](https://os.mbed.com/docs/v5.10/tools/fast-models.html)
1111

1212

1313
## Requirements
14-
1. Make sure you have Arm Fast Models Libraries files installed to your host machines, as well as the Fast Models PyCADI.
15-
2. A valid Fast Models license been set up correctly.
16-
2. Install [Greentea](https://github.com/ARMmbed/greentea) latest master from GitHub (current 1.4.0 release do not contains the support for Fast Models)
17-
3. Htrun Version 1.4.1 or later
14+
1. Make sure you have Arm Fast Models Libraries files installed to your host machines, as well as the Fast Models PyCADI.
15+
16+
>please referencing [Fast Models User Guide](https://developer.arm.com/docs/100965/latest)
17+
18+
2. A valid Fast Models license been set up correctly.
19+
20+
>please referencing [Fast Models User Guide](https://developer.arm.com/docs/100965/latest)
21+
22+
3. Greentea version 1.5.0 or later
23+
```
24+
pip install mbed-greentea -U
25+
mbedgt --version
26+
```
27+
4. Htrun version 1.4.1 or later
28+
```
29+
pip install mbed-host-tests -U
30+
mbedhtrun --version
31+
```
1832

1933
## Download
2034
```
@@ -114,4 +128,5 @@ Then users need to edit `mbed-fastmodel-agent\fm_agent\settings.json` file eithe
114128
Key `configs_add` can be added for additional config files for each model, Or Key `config` can be added to overwrite `GLOBAL` config files.
115129

116130
## Known limitations:
117-
1. Fast Models normally have 3 or 4 serial terminal ports. But currently only one port is supported at moment.
131+
1. Fast Models normally have 3 or 4 serial terminal ports. But currently only one port is used at moment.
132+

fm_agent/configs/COVERAGE.conf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
## Turn off terminal1 and terminal2, keep terminal0 open
2+
fvp_mps2.telnetterminal1.quiet=1
3+
fvp_mps2.telnetterminal2.quiet=1
4+
5+
## Control the output format of the telnet terminal
6+
fvp_mps2.telnetterminal0.mode=raw
7+
8+
9+
## Suppress the telnet/xterm to be launched, so that model agent can talk to the port
10+
fvp_mps2.telnetterminal0.start_telnet=0
11+
12+
13+
## logging the UART output to a file
14+
# fvp_mps2.UART0.out_file=out_file.txt
15+
16+
## turn the rate limite off
17+
fvp_mps2.mps2_visualisation.rate_limit-enable=0
18+
19+
## Enable Ethernet Port
20+
fvp_mps2.hostbridge.userNetworking=1
21+
fvp_mps2.smsc_91c111.enabled=1

fm_agent/configs/DEFAULT.conf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ fvp_mps2.telnetterminal2.quiet=1
44

55

66
## Control the output format of the telnet terminal
7-
fvp_mps2.telnetterminal1.mode=raw
7+
fvp_mps2.telnetterminal0.mode=raw
88

99

1010
## Suppress the telnet/xterm to be launched, so that model agent can talk to the port
1111
fvp_mps2.telnetterminal0.start_telnet=0
1212

1313

1414
## logging the UART output to a file
15-
# fvp_mps2.UART1.out_file=out_file.txt
15+
# fvp_mps2.UART0.out_file=out_file.txt

fm_agent/configs/FAST.conf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ fvp_mps2.telnetterminal2.quiet=1
44

55

66
## Control the output format of the telnet terminal
7-
fvp_mps2.telnetterminal1.mode=raw
7+
fvp_mps2.telnetterminal0.mode=raw
88

99

1010
## Suppress the telnet/xterm to be launched, so that model agent can talk to the port
1111
fvp_mps2.telnetterminal0.start_telnet=0
1212

1313

1414
## logging the UART output to a file
15-
# fvp_mps2.UART1.out_file=out_file.txt
15+
# fvp_mps2.UART0.out_file=out_file.txt
1616

1717
## turn the rate limite off
18-
fvp_mps2.mps2_visualisation.rate_limit-enable=0
18+
fvp_mps2.mps2_visualisation.rate_limit-enable=0

fm_agent/configs/NETWORK.conf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ fvp_mps2.telnetterminal2.quiet=1
44

55

66
## Control the output format of the telnet terminal
7-
fvp_mps2.telnetterminal1.mode=raw
7+
fvp_mps2.telnetterminal0.mode=raw
88

99

1010
## Suppress the telnet/xterm to be launched, so that model agent can talk to the port
1111
fvp_mps2.telnetterminal0.start_telnet=0
1212

1313

1414
## Logging the UART output to a file
15-
# fvp_mps2.UART1.out_file=out_file.txt
15+
# fvp_mps2.UART0.out_file=out_file.txt
1616

1717
## Enable Ethernet Port
1818
fvp_mps2.hostbridge.userNetworking=1
19-
fvp_mps2.smsc_91c111.enabled=1
19+
fvp_mps2.smsc_91c111.enabled=1

fm_agent/fm_agent.py

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ def setup_simulator(self, model_name, model_config):
8383

8484
def __connect_terminal(self):
8585
""" connect socket terminal to a launched fastmodel"""
86-
86+
self.logger.prn_inf("Establishing socket connection to FastModel Terminal")
87+
time.sleep(2)
8788
try:
8889
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
8990
self.socket.connect((self.host, self.port))
@@ -146,13 +147,22 @@ def run_simulator(self):
146147
def reset_simulator(self):
147148
""" reset a launched fastmodel and connect terminal """
148149
if self.is_simulator_alive():
149-
self.model.stop()
150+
self.logger.prn_wrn("STOP and RESTART FastModel")
151+
self.__closeConnection()
152+
self.model.release(shutdown=True)
153+
time.sleep(1)
154+
import fm.debug
155+
self.model = fm.debug.LibraryModel(self.model_lib, self.model_params)
156+
# check which host socket port is used for terminal0
157+
terminal = self.model.get_target('fvp_mps2.telnetterminal0')
158+
self.port = terminal.read_register('Port')
150159
cpu = self.model.get_cpus()[0]
151-
cpu.reset()
152160
if self.image:
153161
cpu.load_application(self.image)
162+
self.logger.prn_wrn("RELOAD new image to FastModel")
154163
self.model.run(blocking=False)
155164
self.__connect_terminal()
165+
self.logger.prn_wrn("Reconnect Terminal")
156166
return True
157167
else:
158168
return False
@@ -219,9 +229,90 @@ def __closeConnection(self):
219229
else:
220230
self.logger.prn_inf("Terminal socket connection already closed")
221231

232+
def __run_to_breakpoint(self):
233+
try:
234+
self.model.run(timeout=15)
235+
except:
236+
# On timeout, model hangs
237+
self.logger.prn_err("ERROR: Timeout reached without stop at breakpoint")
238+
self.model.stop()
239+
return False
240+
else:
241+
return True
242+
243+
def __CodeCoverage(self):
244+
""" runs code coverage dump gcda file """
245+
246+
self.model.stop()
247+
cpu = self.model.get_cpus()[0]
248+
249+
symbol_table = []
250+
self.logger.prn_inf("Reading symbols from %s" % self.image)
251+
if self.image:
252+
symbol_table = read_symbol(self.image)
253+
254+
data_hex_addr = get_symbol_addr(symbol_table, "__gcov_var__ported")
255+
data_int_addr = HexToInt(data_hex_addr)
256+
self.logger.prn_inf("Address for [__gcov_var__ported] is %s" % data_hex_addr )
257+
258+
dump_hex_addr = get_symbol_addr(symbol_table, "__gcov_close__ported")
259+
dump_int_addr = HexToInt(dump_hex_addr)
260+
self.logger.prn_inf("Address for [__gcov_close__ported] is %s" % dump_hex_addr )
261+
262+
exit_hex_addr = get_symbol_addr(symbol_table, "collect_coverage")
263+
exit_int_addr = HexToInt(exit_hex_addr)
264+
self.logger.prn_inf("Address for [collect_coverage] is %s" % exit_hex_addr )
265+
266+
267+
268+
self.logger.prn_inf("Setting breakpoints...")
269+
bkpt_dump = cpu.add_bpt_prog( dump_int_addr + 57 )
270+
bkpt_exit = cpu.add_bpt_prog( exit_int_addr + 43 )
271+
272+
self.logger.prn_inf("Removing old gcda files...")
273+
remove_gcda()
274+
275+
self.__run_to_breakpoint()
276+
stopped_loc = cpu.read_register('Core.R15')
277+
278+
while stopped_loc == bkpt_dump.address :
279+
280+
start_addr = ByteToInt( cpu.read_memory( data_int_addr , size=4 ) )
281+
end_addr = ByteToInt( cpu.read_memory( data_int_addr+4 , size=4 ) )
282+
file_var_addr = ByteToInt( cpu.read_memory( data_int_addr+8 , size=4 ) )
283+
284+
file_var = r''
285+
mem_char = " "
286+
287+
while ord(mem_char) != 0:
288+
mem_char = cpu.read_memory(file_var_addr)
289+
file_var += str(mem_char)
290+
file_var_addr += 1
291+
292+
filename = file_var.rstrip(' \t\r\n\0')
293+
self.logger.prn_inf("dumping to " + filename)
294+
with open(filename, "wb") as f:
295+
mem = cpu.read_memory(start_addr, count=(end_addr-start_addr))
296+
f.write(mem)
297+
298+
if self.__run_to_breakpoint():
299+
stopped_loc = cpu.read_register('Core.R15')
300+
else:
301+
stopped_loc = cpu.read_register('Core.R15')
302+
break
303+
304+
305+
if stopped_loc == bkpt_exit.address:
306+
self.logger.prn_inf("Coverage dump program run to the end.")
307+
else:
308+
self.logger.prn_wrn("Coverage dump ended somewhere else!!")
309+
lcov_collect(os.path.basename(self.image))
310+
222311
def shutdown_simulator(self):
223312
""" shutdown fastmodel if any """
224313
if self.is_simulator_alive():
314+
if self.config_name == "COVERAGE":
315+
self.__CodeCoverage()
225316
self.logger.prn_inf("Fast-Model agent shutting down model")
226317
self.__closeConnection()
227318
self.model.release(shutdown=True)

fm_agent/mbedfm.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ def print_version():
3434
print(get_version())
3535

3636
def print_models():
37-
print list_fastmodels()
38-
print "Import PyCADI Test ... {}".format("PASSED" if check_import() else "FAILED")
37+
print(list_fastmodels())
38+
print("Import PyCADI Test ... {}".format("PASSED" if check_import() else "FAILED"))
3939

4040
def self_test():
41-
print list_fastmodels(check_models=True)
42-
print "Import PyCADI Test ... {}".format("PASSED" if check_import() else "FAILED")
41+
print(list_fastmodels(check_models=True))
42+
print("Import PyCADI Test ... {}".format("PASSED" if check_import() else "FAILED"))
4343

4444
def list_fastmodels(check_models=False):
4545
"""! List all models and configs in fm_agent"""
@@ -84,7 +84,7 @@ def list_fastmodels(check_models=False):
8484
c_test_cell.append("PASSED" if resource.is_simulator_alive() else "FAILED")
8585
resource.shutdown_simulator()
8686
except Exception as e:
87-
print str(e)
87+
print(str(e))
8888
c_test_cell.append("FAILED")
8989
else:
9090
c_avail_cell.append("NO 'CONFIG FILE' NOT EXIST")

fm_agent/settings.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
{
22
"GLOBAL": {
33
"Windows":{
4-
"PyCADI_path": "C:\\Program Files\\ARM\\FastModelsPortfolio_11.4\\lib\\python27",
4+
"PyCADI_path": "C:\\work\\model_libs\\python27",
55
"model_lib_path": "C:\\work\\model_libs",
66
"configs": {
77
"DEFAULT": "DEFAULT.conf",
88
"NETWORK": "NETWORK.conf",
9-
"FAST": "FAST.conf"
9+
"COVERAGE":"COVERAGE.conf"
1010
}
1111
},
1212
"Linux":{
13-
"PyCADI_path": "/home/user/ARM/FastModelsPortfolio_11.4/lib/python2.7/",
14-
"model_lib_path": "/home/user/model_libs",
13+
"PyCADI_path": "/work/model_libs/python2.7/",
14+
"model_lib_path": "/work/model_libs",
1515
"configs": {
1616
"DEFAULT": "DEFAULT.conf",
17+
"FAST": "FAST.conf",
1718
"NETWORK": "NETWORK.conf",
18-
"FAST": "FAST.conf"
19+
"COVERAGE":"COVERAGE.conf"
1920
}
2021
}
2122
},

fm_agent/utils.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import time
2424
import socket
2525
import logging
26+
import subprocess
2627
from functools import partial
2728

2829
class SimulatorError(Exception):
@@ -94,8 +95,8 @@ def check_import():
9495
import fm.debug
9596
except ImportError as e:
9697
for warning in warning_msgs:
97-
print warning
98-
print "Error: Failed to import fast models PyCADI!!!"
98+
print(warning)
99+
print("Error: Failed to import fast models PyCADI!!!")
99100
return False
100101
else:
101102
return True
@@ -172,3 +173,44 @@ def find_free_port():
172173
s.close()
173174
return port
174175

176+
""" the following function mainly for coverage mode """
177+
178+
def read_symbol(image):
179+
"""this function reads images symbol to a global variable"""
180+
symbol_table = []
181+
try:
182+
symbol_table = subprocess.check_output('arm-none-eabi-readelf -sW "{}"'.format(image), shell=True).split("\n")
183+
except Exception as e:
184+
print("Make sure you have arm-none-eabi-readelf tool in PATH")
185+
print("ERROR - {}.".format(str(e)))
186+
sys.exit(1)
187+
return symbol_table
188+
189+
def get_symbol_addr(symbol_table, symbol_name):
190+
"""
191+
Num: Value Size Type Bind Vis Ndx Name
192+
24: 0002f45a 0 NOTYPE LOCAL DEFAULT 2 init_bss
193+
25: 0002f470 0 NOTYPE LOCAL DEFAULT 2 system_startup
194+
26: 0002f468 0 NOTYPE LOCAL DEFAULT 2 zero
195+
"""
196+
for line in symbol_table:
197+
data = line.split()
198+
if symbol_name in data:
199+
return data[1]
200+
201+
def ByteToInt( byteList ):
202+
return int(''.join( [ "{:02x}".format(x) for x in reversed(byteList) ] ),16)
203+
204+
def HexToInt( hex ):
205+
return int(hex,16)
206+
207+
def lcov_collect(filename):
208+
"""this function reads images symbol to a global variable"""
209+
subprocess.call('lcov -c -d . --no-external -o BUILD/{}.info'.format(filename), shell=True)
210+
211+
def remove_gcda(rootdir="."):
212+
"""this function removes gcda files"""
213+
for root, dirs, files in os.walk(rootdir):
214+
for file in files:
215+
if file.endswith(".gcda"):
216+
os.remove(os.path.join(root, file))

setup.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
"""
77
mbed SDK
8-
Copyright (c) 2011-2018 ARM Limited
8+
Copyright (c) 2018-2019 ARM Limited
99
1010
Licensed under the Apache License, Version 2.0 (the "License");
1111
you may not use this file except in compliance with the License.
@@ -51,5 +51,10 @@ def read(fname):
5151
license=LICENSE,
5252
test_suite = 'test',
5353
include_package_data=True,
54-
install_requires=["PrettyTable>=0.7.2"])
54+
install_requires=[
55+
"PrettyTable>=0.7.2",
56+
"mbed-host-tests>=1.4.1",
57+
"mbed-greentea>=1.5.0"
58+
]
59+
)
5560

0 commit comments

Comments
 (0)