Theory of Operations for bridge-tcl Component

A bridge-tcl component is a shell that hooks all SID API calls to an embedded Tcl interpreter so that they can be handled as Tcl procedure calls. In addition, SID API calls are exposed to that interpreter, so the Tcl procedures can call back out to the C++ system. With these two capabilities, a user-provided Tcl package may become a first class SID component.

Objects such as bus, component, and pin pointers may be passed through Tcl scripts safely, because the bridging calls represent these as unique strings, and convert them back to C++ pointers automatically. Any pointers seen through incoming call arguments, or outgoing call return values, are transparently converted into unique long-lived opaque strings. This way, C++ pointers can safely pass through the Tcl bridge in both directions.

Unlike C++ components, Tcl scripts that run in a bridge-tcl do not have access to the sidutil:: group of utility classes. This means that only low level operations are directly provided, and sidutil:: abstractions would need to be rewritten (if needed) in tcl.

Incoming SID API Calls

Almost all incoming SID API calls are passed through verbatim to the embedded Tcl interpreter. (Exceptions are parametrized and noted below.) Plain types are mapped according to the table below: C++ object to Tcl for arguments, and Tcl to C++ for return values. If Tcl procedures by the appropriate names are not loaded into the interpreter by the time they are invoked from another SID component, a TCL ERROR message is printed to cerr, and a function-specific error indication is returned.

Calls belonging to sid::pin and sid::bus are similarly mapped to Tcl procedure calls. The C++ pin/bus object on which they are called is passed to the procedures as an extra argument. (C++ pin/bus objects may be constructed for a Tcl component through special callback functions, listed below.)

Functions with multiple outputs, like the sid::bus::read reference arguments, map to Tcl procedures returning a list with the mapped C++ return type as first element, and the output reference argument as second element.

C++ TypeTcl Type
stringstring
vector<string>list of strings
component,bus,pin pointeropaque strings
{little,big,host}_int_{1,2,4,8}numeric integer - care with 64-bit ints
component::status string: ok, bad_value, not_found
bus::status string: ok, misaligned, unmapped, unpermitted
vector<component*>list of opaque strings
vector<pin*>list of opaque strings
0 (null pointer) ""

In sid::component:

Incoming C++ callOutgoing Tcl call
attribute_names()attribute_names
attribute_names(category)attribute_names_in_category $category
attribute_value(name) attribute_value $name
set_attribute_value(name,value)set_attribute_value $name $value
pin_names pin_names
find_pin(name) find_pin $name
connect_pin(name, pin) connect_pin $name $pin
disconnect_pin(name, pin)disconnect_pin $name $pin
connected_pins(name)connected_pins $name
bus_namesbus_names
find_bus(name)find_bus $name
accessor_namesaccessor_names
connect_accessor(name,bus)connect_accessor $name $bus
disconnect_accessor(name,bus)disconnect_accessor $name $bus
connected_bus(name)connected_bus $name
relationships()relationships
set_related_components(rel,comps)set_related_components $rel $comp1 $comp2 $comp3 ...
related_components(rel)related_components $rel

In sid::pin:

Incoming C++ callOutgoing Tcl call
drivendriven $pin
driven(value)driven_h4 $pin $value

In sid::bus, for host_int_4 address and {big,little}_int_Y data types:

Incoming C++ callOutgoing Tcl call
read(address,data)read_h4_{l,b}Y $address ** return [list $status $data] **
write(address,data)write_h4_{l,b}Y $address $data

Incoming C++ calls that access these parameters are not passed through to the embedded Tcl interpreter. Rather, they are processed in the bridge code attribute.

load!

Loads the given Tcl script into the interpreter using the source procedure pin

event!

Passes control to the tcl/Tk event loop, in non-blocking mode