Categories
Tools

Systems analysis

Dedicated design engineering tools are often oriented towards simple usage scenarios for one design aspect at a time. Complete systems in realistic scenarios are more costly and difficult to analyse due to multiple licensing fees and few working examples. The result is sub-optimal systems with poor performance. Quflow is currently integrating a multi-discipline and multi-scenario systems analysis framework using the following free open source tools:

Of these packages, pyvisa, spiro, traits, quantities and sympy are integrated and playing well together already.

Comments, requests for early releases and collaborations are welcome!

Categories
Tools

Less is more

Quflow example: Working inside a subsystem as if it was the complete system:
[python]
>>> from quflow import Attributes
>>> obj = Attributes(x = 1)
>>> with obj:
… y = x + 1
… del x

>>> obj
Attributes(y = 2)
[/python]
Same example without quflow requires cluttering with symbols that hides the intention and does not provide any focus area to the logic:
[python]
>>> obj = dict(x=1)
>>> obj[‘y’] = obj[‘x’] + 1
>>> del obj[‘x’]
>>> obj
{‘y’: 2}
[/python]

Categories
Tools

System integration

Quflow example: Assembling and dynamically changing components of a system.
[python]
>>> from quflow import Scope
>>> s0 = Scope(x=1)
>>> s1, s2 = s0(y=10), s0(y=100)
>>> with s2: z = x + y + s1.y

>>> s3 = s2(s1) # s1 hides s2 in s3
>>> with s3: print x, y, z

1 10 111
>>> # above came from s0.x, s1.y and s2.z
>>> del s0.x, s1.y
>>> x = 0
>>> with s3: print x, y, z

0 100 111
>>> # above came from x, s2.y and s2.z
[/python]

Categories
Tools

Working with device drivers

Quflow example: Using a phone modem by defining a simple driver on-the-fly.
[python]
>>> from quflow import enter, exit, Driver, ports, sleep
>>> class Phone(Driver):
… commands = dict(attention = “AT”, call = “ATD%s”, hangup = “H0”)
… events = dict(ok = “OK”)
… procedures = dict(enter = “attention(), ok()”)
… expectEcho = True

>>> phonePort = ports()[2] # Assuming the third port controls the phone.
>>> phone = Phone(phonePort, timeout = 25)
>>> me = “+123456789” # My phone number – a global variable.
>>> enter(phone) # Beginning command-oriented usage.
Entering Phone(‘ASRL5::INSTR’)
Executing ‘attention(), ok()’ % ()
ASRL5::INSTR> AT
ASRL5::INSTR< AT
ASRL5::INSTR< OK
>>> # Items defined now affect only the phone object.
>>> procedure(trick = “call(‘%s’), sleep(15), no_carrier(), hangup()”)
>>> trick(me)
Executing “call(‘%s’), sleep(15), no_carrier(), hangup()” % (‘+123456789’,)
ASRL5::INSTR> ATD+123456789
ASRL5::INSTR< ATD+123456789
ASRL5::INSTR< NO CARRIER
ASRL5::INSTR> H0
ASRL5::INSTR< H0
>>> exit(phone) # Ending command-oriented usage.
Exiting Phone(‘ASRL5::INSTR’)
>>>
[/python]

Categories
Examples Tools

Interoperability

Working with multiple connected systems is complicated in other tools and therefore often not prioritized, leading to poor interoperability and user complaints. With quflow, interoperability testing is much easier:

1. Start a server for workspaces on one system. In this example the server publishes a phone (‘serverPhone=phone’) and its protocol on all workspaces so that other devices can use it during experiments.

[python]
>>> from quflow import Driver, Workspaces
>>> protocol = dict(
… commands = dict(
… attention="AT",call="ATD%s", answer="H1", hangup="H0"),
… events = dict(
… ok="OK", receiving="INCOMING CALL %s",
… connected="CONNECTED", disconnected="DISCONNECTED"),
… expectEcho = True)
>>> phone = Driver("COM5", number="+17654321", ** protocol)
>>> workspaces = Workspaces(protocol = protocol, serverPhone = phone)
Service spiro://:9091/<workspace> started.
>>>
[/python]

2. Control the experiment from a client system. In this case one that is connected to another phone on COM7. The printouts show communication to and from the COM ports (using their VISA resource name equivalents) when a test scenario is created and tested. Printouts in brackets indicate messages that are pending – these are programmed into the scenario as events on the line after.

[python highlight=”29″]
>>> from quflow import Driver, Workspace, enter, exit
>>> call_test = Workspace(‘localhost/call_1’)
>>> myPhone = Driver("COM7", number = ‘+12345678’, ** call_test.protocol)
>>> enter(call_test) # start a manual experiment
>>> myPhone.call(serverPhone.number)
ASRL7::INSTR> ATD+17654321
ASRL7::INSTR< ATD+17654321
(ASRL5::INSTR< INCOMING CALL +12345678)
>>> serverPhone.receiving(myPhone.number)
ASRL5::INSTR< INCOMING CALL +12345678
>>> serverPhone.answer()
ASRL5::INSTR> H1
ASRL5::INSTR< H1
(ASRL5::INSTR< CONNECTED)
(ASRL7::INSTR< CONNECTED)
>>> serverPhone.connected() and myPhone.connected()
ASRL5::INSTR< CONNECTED
ASRL7::INSTR< CONNECTED
>>> serverPhone.hangup() and myPhone.hangup()
ASRL5::INSTR> H0
ASRL5::INSTR< H0
ASRL7::INSTR> H0
ASRL7::INSTR< H0
(ASRL5::INSTR< DISCONNECTED)
(ASRL7::INSTR< DISCONNECTED)
>>> serverPhone.disconnected() and myPhone.disconnected()
ASRL5::INSTR< DISCONNECTED
ASRL7::INSTR< DISCONNECTED
>>> verdict("OK – myPhone *could* initiate a call with serverPhone")
VERDICT: OK – myPhone *could* initiate a call with serverPhone.
>>> exit(call_test) # finish the experiment
>>>
[/python]

The highlighted verdict line above is automatically converted into a static test purpose (where “OK – (dut) *could* (action)” becomes “Can (dut) (action)?”) and a dynamic test status that depends on the outcome of the latest run (“OK – (dut) *could* (action).” or “FAIL – (dut) *could not* (action).”). To make it re-run after an inconclusive failure, catch the bad situation once:

[python]
>>> call_test() # Re-run the test
TEST: Can myPhone initiate a call with serverPhone?
ASRL7::INSTR> ATD+17654321
ASRL7::INSTR< ATD+17654321
(ASRL7::INSTR< BUSY)
VERDICT: FAIL – myPhone *could not* initiate a call with serverPhone.
REASON: (‘ASRL7::INSTR< BUSY’) when expecting ‘ASRL5::INSTR< CONNECTED’ and ‘ASRL7::INSTR< CONNECTED’.
‘FAIL – myPhone *could not* initiate a call with serverPhone.’
>>> call_test("ServerPhone was buzy – trying again")
STATUS: ServerPhone was buzy – trying again.
TEST: Can myPhone initiate a call with serverPhone?
ASRL3::INSTR> ATD+17654321
ASRL3::INSTR< ATD+17654321
ASRL5::INSTR< INCOMING CALL +12345678
ASRL5::INSTR> H1
ASRL5::INSTR< H1
ASRL5::INSTR< CONNECTED
ASRL3::INSTR< CONNECTED
ASRL5::INSTR> H0
ASRL5::INSTR< H0
ASRL3::INSTR> H0
ASRL3::INSTR< H0
ASRL5::INSTR< DISCONNECTED
ASRL3::INSTR< DISCONNECTED
VERDICT: OK – myPhone *could* initiate a call with serverPhone.
‘OK – myPhone *could* initiate a call with serverPhone.’
>>>
[/python]

3. Run the experiment again, this time on the target system. If the target is a device tested in high volume production this is done in a separate thread within a pre-compiled boot script so that it consumes as little resources as possible and can run other tests in parallel, and with logging enabled so that any error messages can be used to document the reason for repair decisions and corrective actions.

[python]
>>> from quflow import Driver, Workspace
>>> from myplatform import myPhone
>>> call_test = Workspace(‘workspaces.myfactory.net/call_1’)
>>> call_test()
TEST: Can myPhone initiate a call with serverPhone?
ASRL3::INSTR> ATD+17654321
ASRL3::INSTR< ATD+17654321
ASRL5::INSTR< INCOMING CALL +12345678
ASRL5::INSTR> H1
ASRL5::INSTR< H1
ASRL5::INSTR< CONNECTED
ASRL3::INSTR< CONNECTED
ASRL5::INSTR> H0
ASRL5::INSTR< H0
ASRL3::INSTR> H0
ASRL3::INSTR< H0
ASRL5::INSTR< DISCONNECTED
ASRL3::INSTR< DISCONNECTED
VERDICT: OK – myPhone *could* initiate a call with serverPhone.
‘OK – myPhone *could* initiate a call with serverPhone.’
>>>
[/python]