- three adders, named a, b, and c, which are wired to
- input switches (checkboxes) which you can turn on or off, and
- "lamps" (the round things on the bottom), which turn bright or dark depending on whether they get "power".
proc main argv {
set w [canvas .c -width 160 -height 160]
pack $w
foreach x {40 80 120} name {p3 p2 p1} {input $name $w $x 20}
foreach x {60 100 140} name {q3 q2 q1} {input $name $w $x 50}
adder a $w 130 80
adder b $w 90 100
adder c $w 50 120
foreach x {20 60 100 140} name {r4 r3 r2 r1} {
lamp $name $w $x 150
}
#-- wires from inputs to adders:
wire $w p1 a1
wire $w q1 a2
wire $w p2 b1
wire $w q2 b2
wire $w p3 c1
wire $w q3 c2
#-- carry lines between adders:
wire $w a4 b3
wire $w b4 c3
#-- to lamps:
wire $w a5 r1
wire $w b5 r2
wire $w c5 r3
wire $w c4 r4
}
# Hardware components:
proc input {name w x y} {
checkbutton $w.$name -variable $name -onvalue 1 -offvalue 0
$w create window $x $y -window $w.$name
set ::g($name) [list $x $y]
}
proc adder {name w x y} {
global g ${name}1 ${name}2 ${name}3 ${name}4 ${name}5
$w create rect [- $x 12] [- $y 7] [+ $x 12] [+ $y 7]
$w create text $x $y -text $name
set g(${name}1) [list [- $x 10] [- $y 7]]
set g(${name}2) [list [+ $x 10] [- $y 7]]
set g(${name}3) [list [+ $x 12] $y]
set g(${name}4) [list [- $x 10] [+ $y 7]]
set g(${name}5) [list [+ $x 10] [+ $y 7]]
foreach i {1 2 3 4 5} {set ::$name$i 0}
foreach i {1 2 3} {trace var $name$i w "add $w $name;#"}
}
proc add {w name} {
global ${name}1 ${name}2 ${name}3 ${name}4 ${name}5
set sum [expr [set ${name}1]+[set ${name}2]+[set ${name}3]]
set ${name}4 [expr $sum>1] ;# carry
set ${name}5 [expr $sum%2] ;# lsb
}
proc lamp {name w x y} {
global $name
$w create oval [- $x 6] [- $y 6] [+ $x 6] [+ $y 6] -fill black -tag $name
set ::g($name) [list $x $y]
set $name 0
trace var $name w "toggleLamp $w $name ;#"
}
proc toggleLamp {w name} {
global $name
$w itemconfig $name -fill [expr {[set $name]? "yellow": "black"}]
}
proc wire {w from to} {
global g
foreach {x0 y0} $g($from) {x1 y1} $g($to) break
set ym [expr ($y0+$y1)/2]
$w create line $x0 $y0 $x0 $ym $x1 $ym $x1 $y1 -tag $from
trace var ::$from w "toggleWire $w $from $to;#"
}
proc toggleWire {w from to} {
global $from $to
$w itemconfig $from -fill [expr {[set $from]? "red" : "black"}]
set $to [set $from]
}
# Shortcut math:
foreach op {+ -} {proc $op {a b} "expr \$a $op \$b"}
main $argv
bind . <Escape> {exec wish $argv0 &; exit}For a more intuitive picture of a full adder, see http://micro.magnet.fsu.edu/creatures/pages/fulladder.html
:)See also: Nicholas Pippenger: Complexity of Addition available in MPEG format here: [1]
The behavior of a full-adder can be implemented by currying a generic proc as follows: lgate takes a list of output "lines" which indicate the 0/1 result for a given combination of the inputs, which form the rest of the arguments.
proc lgate {outputs args} {
set res {}
foreach pattern $outputs {
set index 0
set fac 1
foreach arg $args {
if $arg {incr index $fac}
incr fac $fac ;# double it
}
lappend res [string index $pattern $index]
}
set res
}First, try a half-adder: % lgate {0110 0001} 0 0
0 0
% lgate {0110 0001} 0 1
1 0
% lgate {0110 0001} 1 0
1 0
% lgate {0110 0001} 1 1
0 1Works as specified. Now for the full-adder: % lgate {01101001 00010111} 0 0 0
0 0
% lgate {01101001 00010111} 0 0 1
1 0
% lgate {01101001 00010111} 0 1 1
0 1
% lgate {01101001 00010111} 1 1 1
1 1 So we can implement the pure workings of the full-adder (still missing: assignment to output variables) as follows:interp alias {} full-adder {} lgate {01101001 00010111}or any other combination of m inputs and n outputs, just defined by n strings of 2**m bits... Explained: given this truth table for the half-adder, a, b and c are the inputs, and p and q its outputs, and each row is a case:c b a p q 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 1 1 0 1 1 0 1 1 0 1 0 1 1 1 1 1The input part is just an enumeration of possible states (counting up binary numbers); so each column of the output part is already a full specification of the behavior of that output under all circumstances.
TV (May 12 '04) I'll take a remark from RS on the tcl chat serious, and at least add a pointer to a related BWise page: simulating latch behaviour in Bwise where the bits of a graphical block input and output pins are shown as 0 or 1 instead of ticks. Maybe I should make the above into a bwise block. Almost starts to look like computer structures then: register blocks and adders....
See also Playing with circuits where I have unwittingly reinvented parts of the above code. I really have to do more research (at least in my own works) before starting a new fun project... - RS
| Arts and crafts of Tcl-Tk programming | [Category Electronics] |

