![]() |
||||
|
DOWNLOAD
|
CHANGES
|
SCREENSHOTS
|
DOCUMENTATION
| |
This Python module contains the core functionality: building systems, generating source code, simulating systems.
Prototype-based programming (PBP) is a style of programming similar to object-oriented programming (OOP), but lacking classes. There are only objects and new objects are created by cloning other objects. The idea is not at all new and there are many PBP programming languages (e.g. lua and self), but PBP has not enjoyed even a fraction of the popularity of OOP. Nonetheless, I found it interesting enough to experiment basing the whole WhatOS design on PBP. Although I am not ready to make general assertions, my experiences were pleasant: higher flexibility, simpler modeling, simpler documentation.
Although PBP research is more complex than this, I decided to keep it simple. To begin with there is one single object (obj). New objects are created by cloning this object. These objects can themselves be cloned into other objects, and so on. An object inherits as defaults all members of its parent, overriding only the members it needs to change. Below is a set of operations which covers the basic functionality:
First way of creating objects
>>> a = obj('a') # clone obj >>> a.x = 1 # add and set an attribute >>> def f(self): return self.x * 10 >>> a.f = f # add a method >>> a.f() # call a method 10 >>> b = a('b') # clone a >>> b.x = 2 # add and set an attribute >>> b.f() # call a method 20 >>> a.f() # a.x is unchanged 10Members may also be specified at the time of cloning. The following code is equivalent:
>>> def f(self): return self.x * 10 >>> a = obj('a', x = 1, f = f) >>> b = a('b', x = 2) >>> a.f(), b.f() (10, 20)Second way of creating objects
This implementation uses regular Python classes as "objects". Understanding the implementation will give great insight into the behavior. The following code is equivalent to the previous example:
class a(obj): x = 1 def f(self): return self.x * 10 class b(a): x = 2The only difference between a regular class 'a' and object 'a' (above) is that f is automatically bound to a; in a regular class f would be bound to instances of a. All functions which are members of an object are bound to that object and have the object as the first parameter. No exceptions, no class methods/static methods/object methods, etc.. Internally, metaclasses are used to achieve this.
Special methods and properties
If you want to add special methods like __init__, __str__, or properties (calculated attributes) to objects you have to do one extra step:
# first way >>> def gety(self): return self.x * 100 >>> # make sure you specify newmeta = 1 >>> a = obj('a', newmeta = 1, x = 1, y = property(y)) >>> a.y 100 # second way class a(obj): x = 1 def gety(self): return self.x * 100 y = property(gety) # the following must be last statement: __metaclass__ = obj.newmeta(locals()) # if you were cloning from obj 'foo' instead of 'obj': # __metaclass__ = foo.newmeta(locals())Multiple inheritance
There is no multiple inheritance. However, as in the language Ruby, mixins are supported via the obj mixins attribute. In essence, all members of a mixin class (regular class, not obj), become members of the object.
Gotchas
You may get unexpected behaviour if you modify an inherited attribute. For example:
>>> a = obj(l = []) >>> b = a() >>> b.l.append(1) >>> a.l [1]Remember, only attribute assignment (=) ensures you are not modifying inherited attributes. Maybe what you wanted is:
>>> a = obj(l = []) >>> b = a(l = []) >>> b.l.append(1) >>> a.l []This is a common Python gotcha applicable to other non-PBP code.
Object collaborations
A set of objects interract in object collaborations to achieve a certain task. Objects interact by calling methods of other objects and setting/reading attributes of other objects. Objects which play in object collaborations almost always change state.
You should keep this in mind when using ready-made objects, like WhatOS ctask, pytask, wostype, system, and so on. These objects are not meant to be used in object collaborations; clones of these objects are meant to be used in object collaborations. For example, if you put the object pytask into a system, pytask will change state and will behave differently than described in this documentation.
Return non-zero if o1 is a direct/indirect child of o2.
The first, most primitive object. All other objects are either direct/indirect children of this object.
attribute mixins = ()
A list/tuple of standard Python classes from which attributes and methods will be copied into this object.method __call__ (self, *pa, **ka)
Calls method new with all arguments untouched:
child = parent('child', x = 10, y = 20)method attrs (self, t)
Scan all self's attributes and their values, and return only the values that are direct/indirect children of t. This method is not fast; it should not be used in time-critical loops.method attrs2 (self, t)
Same as method attrs, only return a dictionary {'attrname' : attrvalue}.method new (self, name = None, newmeta = 0, **dict)
Clone this object into a new object. All attributes and methods are passed as keyword arguments (key = value). If name is not given, __name__ of new object will be the same as the name of this object. If newmeta is non-zero, the new object will have a new metaclass; the only time you need this is when making an object which has special methods (__init__, __str__, etc.) or properties (calculated attributes). Usage:
child = parent.new('child', x = 10, y = 20)method newmeta (self, dict)
Return a class useable as a metaclass for this object. The only time you need this is when making an object which has special methods (__init__, __str__, etc.) or properties (calculated attributes). It is meant to be called only like this (note that it is the last statement):
class child(parent): # attributes and methods # ... __metaclass__ = parent.newmeta(locals())
A signal may be a pure signal or a valued signal. A pure signal carries no value; its mere presence is all the information it carries. A good example of a pure signal is 'clock_tick()'. A valued signal carries a value. A good example of a valued signal is 'show_integer(8)' You must define the types of all valued signals.
Types are objects derived from wostype. A type has attributes that describe it, as well as methods which operate on values. A value is an instance of wosvalue.
In the C domain, for efficiency reasons, a value may be allocated or not allocated. The value attached to a signal is implemented as a void pointer. If a value is small enough to fit inside a void pointer (signed/unsigned 8/16 bit integers, and depending on processor even larger values), then one declares it as not allocated and the void pointer itself carries the value. Otherwise, the value is allocated and the void pointer points to the allocated value.
A type is defined by a format attribute. This is a non-empty list/tuple of ('fieldname', 'fieldtype') pairs. The easiest way to think of a general type is a C struct, having a non-empty set of fields, each field having a type. fieldname can be anything a C struct would permit. fieldtype is a type character prefixed by an optional repeat count (borrowed almost verbatim from the standard Python module struct). Below are the allowable format characters. WhatOS automatically defines some simple types; these are shown in the last column.
Character Description WhatOS fundamental type b signed 8-bit integer wint8 B unsigned 8-bit integer wuint8 h signed 16-bit integer wint16 H unsigned 16-bit integer wuint16 i signed 32-bit integer wint32 I unsigned 32-bit integer wuint32 f 32-bit IEEE floating point number wfloat d 64-bit IEEE floating point number wdouble s string Making a new type is easy: start off with wostype. Below is the wuint8 type:
class wuint8(wostype): format = (('val', 'B'),) def to_str(self, v): return str(v.val) def from_python(self, v): return wosvalue(val = v)Below is a little more complicated packet type:
C synthesis
A type gets synthesized to C source code (in wossystem.h) with the following rules. If there is only one field, and the field is called 'val', the C synthesis is a simple typedef:
>>> print wostype('t', format = [('val', 'B')]).genc() typedef wuint8 t; >>> print wostype('t', format = [('val', '3B')]).genc() typedef wuint8 t[3];Otherwise, the type gets synthesized to a C struct typedef:
>>> print wostype('t', format = [('x', '5B'), ('y', 'f')]).genc() typedef struct t { wuint8 x[5]; wfloat y; } t;Values
Notice that methods of types operate on values. A value (wosvalue) behaves just like a dictionary with a bit of syntactic sugar: it is initialized from keyword arguments and fields may be accessed as attributes:
>>> x = wosvalue(foo = 1, bar = 2) >>> x.foo 1 >>> x['foo'] 1Note: there is nothing in a value that identifies its type; all values are instances of wosvalue. Besides manipulating values directly, you manipulate them by using the methods of the appropriate type.
A wostype representing "no type".
Used in place of wosvalue when a "no value" is needed.
Base object for WhatOS fundamental numeric types. These types all have one field called 'val', and may be created from Python using a single numeric argument. For example:
>>> wuint8.from_python(77) {'val': 77}
64-bit IEEE floating point number
attribute format = (('val', 'd'),)
32-bit IEEE floating point number
attribute format = (('val', 'f'),)
16-bit signed integer
attribute format = (('val', 'h'),)
32-bit signed integer
attribute format = (('val', 'i'),)
8-bit signed integer
attribute format = (('val', 'b'),)
WhatOS internal signal type. Visible in Python just so that one may define how many signals are allocated in the system (length of signal queue).
Base object for all types.
attribute alloc = 0
1 if values of this type are allocated; 0 otherwise.attribute allocate = 0
Number of units to allocate for values of this type. alloc = 1 is assumed.attribute ctype = 0
Is this type used by C tasks? Set by system during initialization.attribute format = ()
The format of the type. (see Signal value types.)attribute id = 255
Type id. Set by system during initialization. Applies only to types used by C tasks.attribute networkable = 0
Is this type networkable? Currently support for serializing/deserializing values of types containing floats and doubles is not supported. Any other type is networkable. This is set automatically based on format.method compatible (self, other)
Used by system to test type compatibility between connected signals. Returns 1 if self is superior, -1 if self is inferior, 0 if self is identical to other, 2 if self is not compatible to other.
Type compatibility rules
When making connections between tasks, connected signals must have compatible types. Types do not have to be identical because WhatOS can do some forms of type casting from inferior to superior types. Below are the rules:
- A pure signal is compatible only with a pure signal.
- Two types are incompatible if one is allocated and the other is not.
- Two types are incompatible if they have different field names or the same field names in different order. The format of each each field is then compared for compatibility. If the format character is different, the types are incompatible. If the format character is the same and there are no multipliers, the fields are compatible. If the format character is the same and there are multipliers, the field with the larger multiplier is superior.
- The type with at least one superior field is superior. If both types have at least on superior field, the types are incompatible.
During the type casting mechanism a type may be replaced with a superior type. Therefore the following rule must be obeyed when writing tasks:
- A task must also be functional with superior types.
method from_native (self, val)
Create a value from serialized representation in native format. Used by system for C -> Python conversion of a value during simulation. Uses attribute format.method from_net (self, val)
Create a value from serialized representation in network (portable) format.method from_python (self, v)
Define a way to make a value from a single argument.
default code:
return apply(wosvalue, (), v)method genc (self)
Generates C typedef source code for this type. You shouldn't need to call this directly. It's called by system.genh() when generating the wossystem.h header file.method to_native (self, v)
Return serialized representation of a value in native format. Used by system for Python -> C conversion of a value during simulation. Uses attribute format.method to_net (self, v)
Return serialized representation of a value in network format.method to_str (self, v)
Return a pretty string represenation of a value.
A dictionary-like object which holds the data of a value. Data is accessed by field name. Usage:
>>> x = wosvalue(foo = 1, bar = 2) >>> x.foo 1 >>> x['foo'] 1
16-bit unsigned integer
attribute format = (('val', 'H'),)
32-bit unsigned integer
attribute format = (('val', 'I'),)
8-bit unsigned integer
attribute format = (('val', 'B'),)
See pyautotask for a description common to both cautotask and pyautotask.
attribute transition_code = ''
Generated C source code containing if-then-else + action statements. transition_code is also added automatically to attribute "defines" so you may execute inside process like this:
process = ''' /* code before transition */ transition_code() /* code after transition */ '''Look for yourself at samples of generated transition_code to understand exactly how it works.
attribute transitions_viewer = <obj 'transitions_null_viewer'>
The transitions_viewer which is notified of state transitions.method decisioncount (self)
Total number of tests performed in transition_code.method gendot_transitions (self)
Generate Graphviz dot graph representation of state transition diagram. Graph nodes are states and graph edges are transitions, labelled with the condition expression which must evaluate to true for transition to take place.method optimize_states (self)
Change state encoding to try to minimize number of decisions in transition_code. The algorithm used is simulated annealing; the starting point is the current state encoding.
A C task. Specify inputs and outputs by setting input attributes and output attributes. Specify types used for inputs and outputs by setting wostype attributes. Realize that inputs, outputs and types may be customized by a user of the task before the task is inserted into a system. At the end of system initialization type attributes will be replaced by system global "most superior" types; input and output attributes will be replaced by global signal objects. Example:
# generate a_task: class a_task(ctask): a_type = wostype() w = input('w') x = output('x', type = 'a_type') # put 2 copies of a_task into a system with # different names and modified interfaces: class a_system(system): a = a_task('a', w = a_task.w('w2')) b = a_task('b', a_type = a_compatible_type) # at this point: # a_system.a.w = a_system.w2 is a signal named w2 # a_system.b.a_type = a_system.a_compatible_typeattribute defines = {}
Dictionary {'key' : 'value'} which synthesizes to C code:
#define key (value)After the task process, all defines are undefined in order to avoid compiler warnings about redefining macros.
attribute external = ''
C code which will appear right before the task process function in source code file wossystem.c.attribute group = 0
Task group. Communication between tasks in the same group is faster but less flexible(see C API). Group 0 means no group.
attribute header = ''
C code which will appear in header file wossystem.h.attribute id = -1
Task id. Set by system during initialization.attribute priority = 64
Task priority. Integer between 0 and 127 inclusive. Tasks with higher priority (lower number) receive signals before tasks with higher priority (see C API scheduling).
attribute process = ''
C code which processes input signals. See C API internal task interface for a list of all macros/functions available to the task.
Python task representing environment. All signals not emitted within a task appear to be emitted from the environment. All signals not received by any task appear to be received by the environment.
A task input port.
i386 + gcc compiler target. This is used for simulation.
A task output port.
Similar to a signal but is used only to specify the type and name of a signal. Upon system initialization all port attributes are replaced by signal attributes.
attribute type = 'notype'
A string containing the local name of the type. A wostype attribute having the same name must be found in the task. For example:
class a_task(pytask): a_type = wostype() x = output('x', type = 'a_type')
A task with automatically generated state machine code. This documentation applies to pyautotask and cautotask.
An autotask allows one to specify the behaviour of a state machine using transitions. A transition is: a source state, a destination state, a condition expression which must evaluate to true, and an action to be performed when the transition takes place. A transition is specified using object methods. For example, given two states {state1, state2}, two binary tests {test1, test2}, an output signal {x}, a single transition is specified as follows:
# pyautotask class a_pytask(pyautotask): def state1_TO_state2(self): 'test1 & ~test2' # perform the action as Python code self.x.emit() # more transitions ... # cautotask class a_ctask(cautotask): def state1_TO_state2(self): 'test1 & ~test2' # return a string containing the action as C code return 'emit(x);' # more transitions ...Upon initialization of these objects, both a_pytask and a_ctask will have attribute transition_code set to generated source code in Python or C which contains one big if-then-else statement. Additionally, a_ctask will have transition_code defined in its defines attribute. Look for yourself at samples of generated transition_code to understand exactly how it works. You call the generated transition_code as part of the process of the task.
Note: generated transition code assumes nothing about how you store state. You have to manually set the state as part of the action performed during the transition.
Multiple transitions between the same two states
You may have multiple transitions between the same states, differring only in the condition expression. You specify these as follows:
def state1_TO_state2__foo(self): 'test1 & test2' def state1_TO_state2__bar(self): 'test1 | test2'The __foo and __bar suffixes (foo and bar can be anything) are there just to differentiate between the two transitions; they are otherwise ignored.
Condition expression
The condition expression may contain binary variables (variables which evaluate to either true or false) and the operators ~ (not), & (and), | (or). The binary variables will appear inside transition_code and you will need to define these externally. For example:
class a_ctask(cautotask): defines = {'test1' : 'input > 5', 'test2' : 'input < 10'} process = ''' /* all variables have been defined */ transition_code() ''' class a_pytask(pyautotask): def process(self, input, inputval): test1 = inputval.val > 5 test2 = inputval.val < 10 # all variables have been defined exec self.transition_codeState encoding
The number and names of the states are automatically determined by the transitions you specify. However, states must be encoded into a binary representation. For example, given 3 states {a, b, c}, we need 2 bits (int(ceil(log(len(states))/log(2)))) in order to encode these states. Sometimes the encoding you use affects the efficiency(number of tests performed) of the generated transition code. Therefore the task tries to optimize the state encoding; all assigned state encodings will appear as attributes for both pyautotask and cautotask. Additionally, the state encodings will be added to the defines attribute of a cautotask. A possible scenario:
class a_pytask(pyautotask): # transitions using states a, b, c class a_ctask(cautotask): # transitions using states a, b, c >>> a_pytask.a >>> 1 >>> a_pytask.b >>> 3 >>> a_ctask.a >>> 2 >>> a_ctask.b >>> 1 >>> a_ctask.defines >>> {'a' : 2, 'b' : 1}The transitions_code is generated using Reduced Ordered Binary Decision Diagrams (ROBDDs) [1]. Therefore, only binary variables are allowed; that is, only simple true/false tests are permitted. Therefore, inside transition_code, each bit of the state encoding is tested separately. For example, you'll see statements like:
if state_0: if state_1: # ... else: # ...Just like condition variables (test1, test2 above), these extra variables must be defined externally of transition_code because autotask assumes nothing of how you store state. For example, you can provide tests which test each particular bit of an integer state variable; adding to the previous example:
class a_ctask(cautotask): defines = {'test1' : 'input > 5', 'test2' : 'input < 10', 'state_0' : 'state & 1', 'state_1' : 'state & 2', 'state_2' : 'state & 4'} process = ''' static wuint8 state = a; /* all variables have been defined */ transition_code() ''' class a_pytask(pyautotask): def process(self, input, inputval): # initialize state the first time if not getattr(self, 'state'): self.state = self.a test1 = inputval.val > 5 test2 = inputval.val < 10 state_0 = self.state & 1 state_1 = self.state & 2 state_2 = self.state & 4 # all variables have been defined exec self.transition_codeWhen an autotask is initialized, if the autotask does not specify the state encoding, a default numerical sequence encoding is assigned to all states. State encoding can be optimized by calling method optimize_states. An autotask specifies state encoding by setting attributes. For example, given a_ctask with 3 states {a, b, c}:
class a_ctask(cautotask): a = 3 b = 1 c = 2The state encoding optimization algorithm does not find the "exact optimal" encoding because computationally-wise it is too time-consuming when the number of states grows [2]. It uses an algorithm called simulated annealing, which includes random properties. Therefore optimize_states() can generate different encodings every time it is called. For this reason, the intended design cycle for an autotask is:
- Don't specify any state encoding while you are developing and testing the autotask.
- Once the autotask is complete, call optimize_states() until you are happy with the state encoding (check decisioncount() to see how many tests are performed in transition_code).
- Save this encoding by setting one attribute for each state.
attribute compile_code = 1
Generated transition code is a string containing Python source code. Set this attribute to 1 if you want to byte-code compile this string for execution speed improvements.attribute transition_code = ''
Generated Python source code containing if-then-else + action statements. If attribute compile_code is set to 1, this transition_code will be byte-compiled code. Execute inside process() like this:
def proces(self, input, inputval): # code before transition ... exec self.transition_code # code after transition ...Look for yourself at samples of generated transition_code to understand exactly how it works.
attribute transitions_viewer = <obj 'transitions_null_viewer'>
The transitions_viewer which is notified of state transitions.method decisioncount (self)
Total number of tests performed in transition_code.method gendot_transitions (self)
Generate Graphviz dot graph representation of state transition diagram. Graph nodes are states and graph edges are transitions, labelled with the condition expression which must evaluate to true for transition to take place.method optimize_states (self)
Change state encoding to try to minimize number of decisions in transition_code. The algorithm used is simulated annealing; the starting point is the current state encoding.
A Python task. Specify inputs and outputs by setting input attributes and output attributes. Specify types used for inputs and outputs by setting wostype attributes. Realize that inputs, outputs and types may be customized by a user of the task before the task is inserted into a system. At the end of system initialization type attributes will be replaced by system global "most superior" types; input and output attributes will be replaced by global signal objects. Example:
# generate a_task: class a_task(pytask): a_type = wostype() w = input('w') x = output('x', type = 'a_type') # put 2 copies of a_task into a system with # different names and modified interfaces: class a_system(system): a = a_task('a', w = a_task.w('w2')) b = a_task('b', a_type = a_compatible_type) # at this point: # a_system.a.w = a_system.w2 is a signal named w2 # a_system.b.a_type = a_system.a_compatible_typemethod process (self, input, inputval)
Process a received signal. input is a signal and inputval is a wosvalue. You identify the input signal by the test: input == self.<input>. Do not check the name of the signal since the input may have been renamed. Emit a signal like this: self.<output>.emit(). You may operate on inputval like this: input.type.<method>(inputval).
Signals are objects implementing connections between tasks.
attribute bridges = ()
List/tuple of signal objects which will be emitted when this signal is emitted. Use this attribute to create signal "bridges" between multiple separate systems. If you want system1.signalx to be emitted whenever system2.signaly is emitted:
system2.signaly.bridges = [system1.signalx]attribute id = -1
Signal id. Set by system during initialization. Applies only to signals used by C tasks.attribute sinks = ()
Tasks which receive this signal.attribute sources = ()
Tasks which emit this signal.attribute system = None
The system which this signal belongs to.attribute type = <obj 'notype'>
Value type of this signal (wostype).method emit (self, value = {}, source = None)
Emit this signal. Ignore parameter source since it is set automatically in all contexts. If this is a pure signal do not pass anything for parameter value. If this is a valued signal, parameter value must be a wosvalue or anything that self.type.from_python understands. Signals emitted in C are handled by system. Signals emitted in Python are typically emitted in two contexts:
# inside a python task def process(self, input, inputval): # ... self.a_signal.emit(10) # ... # outside the system a_system.a_signal.emit(10)
A simulation_viewer which does nothing.
A simulation_viewer which prints all messages.
A viewer used to view various simulation events which occur in the system. Clone and customize.
method cassert (self, id, message, line)
An ASSERT statement has executed in the system. id is a string. If the ASSERT statement occurred inside a task, id is the name of the task; otherwise id is the name of the internal system component in which the ASSERT statement occurred (e.g. "allocator", "signalqueue"). message is a string and line is the line number of the ASSERT statement. Note that ASSERT must be enabled explicitly for each component/task (see C API).
method ctrace (self, id, message, line)
A TRACE statement has executed in the system. id is a string. If the TRACE statement occurred inside a task, id is the name of the task; otherwise id is the name of the internal system component in which the TRACE statement occurred (e.g. "allocator", "signalqueue"). message is a string and line is the line number of the TRACE statement. Note that TRACE must be enabled explicitly for each component/task (see C API).
method presented (self, source, dest, signal, value)
A signal has been presented to a task. source, dest are tasks, signal is a signal, value is a wosvalue or novalue.
A collection of tasks connected together through signals. It offers operations to generate source code, build a Python extension module from generated source code and signal communication between the tasks. Signal communication can be "viewed" using different viewers.
System initialization
Object system is designed to be cloned only one level deep. That is, system1 = system(), system2 = system() is ok, but system3 = system2() is not. The reason has to do with system initialization, discussed here.
When a new system object is created the following takes place:
- All wostype, ctask, pytask, cautotask, pyautotask attributes are inspected.
- Connections are formed between all tasks' input/output ports having the same name.
- Tests are performed to ensure compatibility of signal types when making the connections. Type casting is performed: among two compatible types the superior of two types is chosen as the signal type. The default starting set of system types is the set of wostype attributes of the system at the beginning of initialization.
- All task local signals reduce to a single global set of signals. All of these signals become attributes of the system. All task input/output attributes are replaced by the global signal objects.
- All task local types reduce to a single global set of types. All of these types become attributes of the system. All task type attributes are replaced by the global wostype objects.
- All C tasks and types and signals used by C tasks are assigned a numerical ID.
- The system gets a "unique" signature (attribute signature) used for matching generated source code with the original system which generated the source code.
Conveniently, all tasks, types and signals are attributes of the system. Below are some examples of accessing these:
>>> system = system( ... a = pytask('a', f = output('f')), ... b = ctask('b', f = input('f'))) >>> system.attrs(pytask), system.attrs(ctask) ([<obj 'a'>], [<obj 'b'>]) >>> system.attrs(wostype), system.attrs(signal) ([<obj 'wos_Signal'>, <obj 'notype'>], [<obj 'f'>]) >>> system.a, system.b, system.f (<obj 'a'>, <obj 'b'>, <obj 'f'>) >>> system.f.emit() # emit signal fattribute clean = 1
If set to 0 intermediate files are not erased after building output files.attribute header = ''
Source code to appear in the generated system header. For simulation using the Python extension DLL, make sure you specify:
#define WOS_DBG_SIM #define WOS_ASSERT_INTERNALSattribute id2signal = {}
Dictionary {signalid : signal}; only includes signals used by C tasks.attribute id2task = {}
Dictionary {taskid : task}; only includes C tasks.attribute id2type = {0: <obj 'wos_Signal'>}
Dictionary {typeid : wostype}; only includes types used by C tasks.attribute signature = 49365
A system signature calculated based on the tasks, signals and types in the system.attribute simulation_viewer = <obj 'simulation_printer'>
simulation_viewer which receives all simulation messages.method dllbuild (self)
Generate Python extension module DLL (libwossystem.so) containing C tasks of this system. Calls self.genh() and self.genc(). If there are external libraries (or other special cases) you will have to build this DLL manually, since this method is convenient but not very flexible.method dllload (self)
Load Python extension module DLL (libwossystem.so) containing C tasks of this system. Must be called prior to emitting any signal which is received by any C task in this system.method genc (self)
Generate C source code file for this system (typically named wossystem.c). See C API. Only C tasks and types and signals used by C tasks are included.
method gendot (self)
Generate graphviz dot representation of the signal connections in the system. This is useful for graphical visualization.method genh (self, target = <obj 'native'>)
Generate C header file for this system (typically named wossystem.h). See C API. Only C tasks and types and signals used by C tasks are included.
method threadstart (self)
Start separate signal processing thread. Sometimes it is convenient to write tasks which emit signals from separate threads (for example a serial port task which waits for input in a separate thread). If there are any such tasks in the system, threadstart must be called.
Contains all target-dependent definitions. target = processor + compiler combination.
attribute endianess = 'little'
Endianess: 'little' (1234), 'big' (4321), or 'pdp' (3412).attribute header = ''
String which will appear in generated header file.attribute wint16 = 'short'
Definition of 16-bit signed integer.attribute wint32 = 'int'
Definition of 32-bit signed integer.attribute wint8 = 'char'
Definition of 8-bit signed integer.attribute wuint16 = 'unsigned short'
Definition of 16-bit unsigned integer.attribute wuint32 = 'unsigned int'
Definition of 32-bit unsigned integer.attribute wuint8 = 'unsigned char'
Definition of 8-bit unsigned integer.
An object representing a transition.
attribute condition = ''
The condition expression string (expression which must evaluate to true for transition to take place).attribute destname = ''
The name of the destination state.attribute sourcename = ''
The name of the source state.
A transitions_viewer which does nothing.
A transitions_viewer wich prints all messages.
attribute task = None
The cautotask or pyautotask which is being monitored by this viewer. You must set this by cloning a transitions_printer like this:
task = a_system.a_task task.transitions_viewer = transitions_printer(task = task)
A viewer used to view state transitions within a cautotask or pyautotask. Clone and customize.
method transition (self, transition)
A transition is taking place. Argument transition is a transition object.
| [1] | The third-party software used for binary decision diagrams is BuDDy. |
| [2] | I tried to approximate the algorithm in the following article: W. Gosti, T. Villa, A. Saldanha, A. Sangiovanni-Vincentelli. Input Encoding for Minimum BDD Size: Theory and Experiments, 1997. |
©
Mircea Hossu ( ) |
WhatOS
2.0.3 (2006 Feb 26) |