BASIC CAM-Forth WORD LIST This is a list of the most useful CAM Forth words. The descriptions here are short, and are supplemented by other files (such as "fields.txt") that treat some topics in more depth. The Sun Forth on which this system is built is documented in "softman.ps": a description of these extensions will soon be incorporated into that manual. You can also find out more details about these and related functions by looking at the extensive comments in the source code. ** KEY FUNCTIONS ** Any of these can be used as part of your own key definitions, but be careful about controlling the value of ARG (the numeric argument given to the key -- see "arg" and ">arg"). Look at the source code for these words to see how these functions are built out of lower-level functions. Note that I/O operations are all named from the point of view of CAM. Put-pattern-file send space-data from CAM to disk (save them gzip-ed) Get-pattern-file get space-data from disk to CAM (look for .gz first) Write-colormap write a named colormap from CAM to disk Read-colormap read a named colormap from disk to CAM Rand-percent ARG sets the "percent" value used by "Randomize-slice" Randomize-slice set the ARG-th bit-slice to a random pattern of 1's Go-up shift viewpoint up Go-dn shift viewpoint down Go-lt shift viewpoint left Go-rt shift viewpoint right Go-pos-xN shift viewpoint in the +xN dir (ARG changes N) Go-neg-xN shift -xN Toggle-X-display turn XCAM display on or off Toggle-function turn use of display function (display-table) on or off Toggle-spread turn Spread display (visible at high mag) on or off Toggle-hide when in Spread mode, un/hide ARG bit (16=all) Toggle-checker when in Spread mode, do/don't use red/blue chkbd Zoom-in show next power-of-two enlargement of center of space Zoom-out unmagnify the display one power-of-two step View-subcell display and I/O should involve subcell given by ARG Load-file load a file (ARG=0 tells ?rule>table to recompile all) Base-directory reset base from which subdirectories are specified Experiment-subdirectory change to a subdirectory containing related experiments Directory-listing list a directory (default= base directory) Single-step run update step(s) (last ARG = how many before display) Run-continuously same as single step (shares last ARG), but don't stop Slower insert idle steps Faster remove idle steps Count-slices count bits of the displayed subcell (or ARG subcell) Quit exit from key interpreter program, to run Forth ** KEY-INTERPRETER RELATED FUNCTIONS ** These are slightly lower level words that are used for defining your own key-interpreter keys. The main word here is "press", which appears immediately after a Forth colon definition that should be attached to a key. By convention, capital letters are reserved for keys defined by experiments. press (s -- ) ( ---- keyname "comment") Attach latest definition to a keyname. A following menu comment delimited by surrounding double quote marks (") is *required*. Forth input following the keyname will be skipped until such a "comment" is found! Don't redefine keys. EXPERIMENT-KEYS These are the vocabularies into which keys are INITIALIZE-KEYS divided. All user defined keys go into the RUN-KEYS "EXPERIMENT-KEYS" vocabulary by default. ANALYZE-KEYS These groupings are used for showing Menus. KEY-INTERP-KEYS key-bindings Make current vocabulary the one that keys are put into. >arg (s value -- ) puts value into ARG used by keys. arg (s -- arg ) puts ARG on stack (0 if no ARG). arg? (s -- flag) flag is true if ARG was specified. =arg (s addr -- ) changes addr to ARG iff ARG specified. go When in Forth, use this to restart the key interpreter. this Puts pointer to most recent definition on the stack. is (s acf -- ) ( ---- name.defer ) standard Forth "is" update-step Deferred word: points to step-list to be repeated. steps/display (s n -- ) affects "Run-continuously" and "Single-step" when-starting Deferred word: action before restarting updating. when-stopping Deferred word: action before interrupting updating. step-count Variable. Contains #steps that have been run. -step-count Negate "step-count". "Run-continuously" stops at 0. steps (s n -- ) Run "update-step" n times and display (increments "step-count"). ** CONTROLLING THE DISPLAY ** The main routine here is called "show": this regenerates a display step-list (and then executes it) as needed, whenever display parameters (such as magnification) have been changed. If no parameters have been changed, then no recompilation is needed, and so display is fast. There are also some deferred words that provide "hooks" to be executed before or after display (to save images to files, collect statistics, etc.). Note that only the low 8-bits of display data go through a colormap and are displayed. You can use a display table to remap 16-bits into 8 to show exactly what you want. "show-subcell" and "show-fields" are useful for assembling a display consisting of bits from various subcells. Subcell bits for I/O are controlled separately from those for display. show display an image using current display parameters display-table table sometimes used by "show" (see "show-function") show-state Tell "show" to start displaying site data directly. show-function Tell "show" to display lut data using "display-table" (ignored in Spread mode). set-logmag (s n -- ) set log of magnification (can be -ive) full-size set magnification so that whole space fills the screen (this is the default after "new-experiment") show-spread show "spread" display if zoom is high enough (each assembled cell is shown as a 4x4 array of bits) show-unspread turn off spread show-capture show displays CAM data while sending camera data to CAM (only works for 512x512 space at 0 mag) show-nocapture turn off capture show-subcell (s n -- ) show displays subcell n show-fields (s cfa1...cfaN N --) show displays specified fields (see "assemble-fields", and the file "fields.txt") reset-display-limits (s max-width max-height -- ) used for large X display mono-smap Colormap used for monochrome Spread-mode display. cboard-smap Colormap used for checkerboard Spread-mode display. before-display Deferred word executed at start of each "show". after-display Deferred word executed at end of each "show". stop-centering-hd Center display on front face of space (z=0, etc.). start-centering-hd Center display along all dimensions (z=Z/2, etc.). use-no-display Turn off both displays ("show" does nothing). use-X-display Use only XCAM display (video display doesn't update). use-cam-display Use only cam video display (no XCAM window). use-both-displays Update both XCAM and cam displays. ** SITE INITIALIZATION ** Reading and writing between fields and disk. "cam>file" is equivalent to "cell field field>file", i.e., the "cam" versions are for convenience. "fd" is a unix file descriptor -- this allows i/o to pipes and to other processes. clear-all-subcells clear all memory to zero cam>file (s filename.pstr -- ) field>file (s filename.pstr -- ) cam>fd (s fd -- ) field>fd (s fd -- ) file>cam (s pattern.pstr -- ) file>field (s filename.pstr -- ) fd>cam (s fd -- ) fd>field (s fd -- ) The fractional randomness words make all bits of the specified field have exactly the same value within a given cell. The "random>cam" and "random>field" words set all indicated bits to independent 50% randomness. /random>cam (s numerator denominator -- ) /random>field (s numerator denominator -- ) random>cam random>field To initialize lines and points, surround a group of read and write commands with one "begin-line-io" and "end-line-io", to avoid doing slow io initialization each time. begin-line-io end-line-io linebuf The buffer read and written by these routines. read-line (s line# -- ) write-line (s line# -- ) read-point (s x y -- value.field ) write-point (s value.field x y -- ) Similarly, to read and write a bunch of 2d slices in an N-dimensional space, surround the read and writes with "begin-slices" and "end-slices". begin-slices end-slices buffer>2d-slice (s slice# -- ) Uses current buffer 2d-slice>buffer (s slice# -- ) Uses current buffer If you've created a buffer large enough to hold a whole spatial configuration, you can read and write it using these. They read and write the current buffer. If the space is too big, you won't be able to fit such a buffer into the SPARC I/O address space, so you will have to do your I/O from disk, or read/write smaller objects (lines or slices). cam>buffer Most recently executed buffer name is current buffer buffer>cam ** EVENT COUNTING ** Although hardware event counting can proceed in parallel during any updating scan of the space without slowing down the processing, we provide some separate event counting routines for convenience. Until there is a high-level compiler, the complexity of interleaving event counting with updating is typically not worth the trouble, particularly since you usually don't need to count at every step. The main user routines here are "*count*", "*count-lut*", "count-field", and "count-bits/field". These accumulate global counts over the whole space. If you want an array of counts over blocks of the space, use "counts>buf". *count* Perform global counts using site data for all layers. *count-lut* Perform global counts using active lut for all layers. nth-count (s n -- value ) look in the count buffer containing the results and pick out the count for the nth field. count-field (s -- count ) add counts for bits of field, each weighted by the appropriate power of two. count-bits/field (s -- count ) add counts unweighted counts>buf (s x1 x2 .. xd -- ) Dimensions of block that you want to accumulate over. All dimensions must be powers of two, and current version has limitation that block must be smaller than the sector in all dimensions. Note that event count source should be specified before you execute this (e.g., "event-src lut"). resultbuf Place where results from counts>buf are accumulated. The entries are each 32 CAM-words long, and organized in the order of increasing x, then y, then z, etc. ** EXPERIMENT INTIALIZATION ** Every experiment starts off by reinitializing CAM and the software using "new-experiment", and then specifying the size and shape of the space using "by" and "space". This also provides the basic size information needed by "show" to generate display step-lists as needed. The words "X", "Y", etc., return the dimensions of the full space, while "U", "V", etc., return the size of the portion of the space handled by each hardware module (the size of the "sector"). new-experiment clear software and machine to a standard state single-module disconnect glue and use only one module by (s size -- ) set dimensions of space space (s size -- ) set all space default values, and compile and install all display routines that will be used for this size space. SBus-clock constant set from "STEP-SPEED" environment variable full-space reset space to full size, in case you have been scanning only part of it. X (s -- size ) x size of the full space Y (s -- size ) y size of the full space Z (s -- size ) z size of the full space Xn (s n -- size ) size of n-th dim of the full space U (s -- size ) x size of a sector V (s -- size ) y size of a sector W (s -- size ) z size of a sector Un (s n -- size ) size of n-th dim of a sector shift-space (s shift.1 shift.2 ... shift.#dim -- ) ** FIELDS and PERMUTATIONS ** Once the size of the space is specified, all of the memory of CAM is divided up evenly into this array of cells. Consecutive 16-bit segments of these cells are called "subcells". We can define bit-fields consisting of consecutive bits within subcells, and assemble up to 16 bits at a time from various bit-fields (the currently assembled cell). This organization reflects the fact that lookup tables can only update 16 bits at a time. The main words defined here are "==" (for defining fields) and "assemble-fields" for bringing together bit fields in a specified order for an updating scan of the space. For more details, see "fields.txt". == (s first-bit last-bit -- ) ( ---- name ) Define field n (s #bits -- first-bit last-bit) Look at most recent "==" definition, and return the numbers of the first and last bits for an adjacent "n" bit field. Used as in "3 n == fieldname" subcell: (s n -- ) Following subcell definitions refer to subcell "n". New experiment sets this to 0. field (s n -- ) Removes field value from stack, and makes most recent field reflected in the current layer mask. +field (s n -- ) OR this field into the layer mask. { (s -- ) ( ---- word1 word2 ... wordN ) Begin a list of Forth names that will be left as acf's (pointers) on the stack. } (s -- acf1 acf2 ... acfN N ) Ends a list begun with "{". Put acf pointers to these words in the given order, followed by the number of items in the list. assemble-fields (s acf1 acf2 ... acfN N ) Given a list of acf pointers to field words, compile step-list instructions for all permutations and subcell-bit-selections to bring the given fields together in the given order. If less than 16-bits are specified, the high bits will come from subcell 0. activate-subcell (s n -- ) Assemble all field bits from subcell n. assume-field-order (s acf1 acf2 ... acfN N ) Given a list of acf pointers to field words, change the action of the listed field words to point to the fields in their new positions. When another "assume-field-order" command is issued, the old field positions will be restored before the new are modified. "assemble-fields" also has this action. identity identity lookup table (see "create-lut" below) identity-perm (s -- identity-perm.double ) Puts a double word permutation index on the stack that specifies the identity permutation. Each nibble specifies which bit of the 16-bit cell should appear at the corresponding position after the permutation. Here, perm.double = fedcba98 76543210 send-table (s acf.table #layers perm.dbl --) Send permuted table send-perm-table in step-list, works like "lut-data", but specifies perm inverse-perm (s perm.double -- inverse-perm.double ) ** BUFFERS ** All CAM I/O goes to/from SPARC I/O address space. We can create buffers that are mapped into both user space and I/O space for convenience. When buffers appear in step lists, the I/O space addressing is used to link them in place. When buffers are used outsize of step-lists, the user-space address is usually the relevant one. create-buffer (s #cam-words -- ) ( ---- name ) copy-buffer (s acf.source.buffer acf.dest.buffer -- ) change-reglen (s reglen acf.buffer.word -- ) guarantee-alloc (s acf.buffer.word -- ) These words all operate on the current buffer, which is the last buffer name executed. randomize-buf Makes 50% randomness in all bits /randomize-buf (s numerator denominator -- ) Given fraction of 1's buffer (s -- addr.current.buffer ) User space address length (s -- #camwords) Len of current buf in 16-bit camwords part (s part# #parts -- ) Changes current buffer pointers to divide the current buffer into "#parts", and point to the "part#"-th piece of this buffer (first part is numbered 0, last is "#parts" minus 1) load-buffer (s filename-pstr -- ) Load array of shorts from disk save-buffer (s filename-pstr -- ) Save array of shorts to disk bytebuf<> (s buf.addr -- flag ) Compare buffers bytebuf= (s buf.addr -- flag ) buf<> (s buf.addr -- flag ) buf= (s buf.addr -- flag ) buf! (s n0 n1 n2 .. nk -- ) Fill buffer from the stack. ** TABLE GENERATION ** During table generation, a rule is evaluated for all cases and a table is generated. For each possible cell-contents case, an index variable called "lut-in" and a result variable called "lut-out" are both initialized to the case number. All field words access the "lut-in" bits, and it is the "lut-out" bits that get changed. Any bits not specifically changed retain their initial values. "update" is used to allow rules to be defined as if two or more cell updates are executed consecutively to the same cell. create-lut (s -- ) ( ---- name ) Create a lut-sized buffer. rule>table (s -- ) ( ---- rulename tablename ) Compile a rule for all cases, filling up the specified table table! (s afc.rule afc.table rulename.pstr -- ) Like "rule>table", but with all arguments on the stack. ?rule>table (s -- ) ( ---- rulename tablename ) Like "rule>table", but saves table to disk. If table exists on disk, it will use that version, rather than run through a compilation. ?table! (s afc.rule afc.table rulename.pstr -- ) Like "?rule>table", but with all args on the stack. Note that this allows the rulename used for the disk copy of the table to be explicitly specified, which is sometimes useful if a single rulename with a varying global parameter is used to specify several tables. n0 (s -- bit ) Predefined names for each cell bit field. n1 n2 n3 n4 n5 n6 n7 n8 n9 na nb nc nd ne nf nn (s n -- n' ) Execute n'th predefined bit-field name. cell (s -- n ) All bits of cell (subcell 0). -> (s n -- ) ( ---- field.name ) Store n into the indicated field in the "lut-out" result variable. <-> (s field0.value -- ) ( ---- field1.name ) Exchange field0 and field1 in the "lut-out" result variable. !! (s field0.value field1.value -- ) Drop the field1 value, and store the field0 value into field1. For example, "5 nn 4 nn !!" copies n5 into n4. update Copy "lut-out" into "lut-in". update-cell Copy "lut-out" into "lut-in". This definition is useful for writing rules that are compositions of two or more successive rules. Once the cell is updated, the result of what you've done so far becomes visible using the field words that you have defined (see "=="). ** COLOR MAP GENERATION ** Colors: Colormap construction is similar to table construction. The low 8 bits of the site (or lut output) are visible, and can be accessed by the same field words as are used to access the cell. The main word is "colormap", which is applied to a colormap rule definition. The colormap is generated and immediately sent to CAM. colormap (s -- ) ( ---- mapname ) Compile and send color map. half-bright constant of half max brightness value for color map bright constant of max brightness value for color map >red (s n -- ) send brightness value to red >green (s n -- ) send brightness value to green >grn same as >green >blue (s n -- ) send brightness value to blue >blu same as >blue >grey (s n -- ) send same value to red, green & blue >gray same as >grey >b&w same as >grey >color directly set 24-bit color value >rgb same as >color ** STEP LISTS and CAM REGISTERS ** At the lowest level, control of CAM is managed via linked lists of CAM-register I/O operations that reside in the SPARCstation I/O address space. A custom SBus card follows these "step lists", and performs the indicated I/O operations to/from CAM registers. Many CAM Forth words construct step lists dynamically just before they are executed. The word "define-step" is used to precompile and name step-lists that will be used repeatedly -- this avoids repeating the bit-twiddling overhead of step-list construction each time the list is executed. Each time a precompiled list is presented for execution, any dynamically-linked list under construction will first be scheduled for execution. define-step (s -- ) ( ---- name ) Precompile a step list. end-step "define-step (s pstr -- ) Get step list name from stack. step Schedule dynamically linked list that was just compiled stop Wait for most recent list scheduled to finish. *step* Equivalent to "step stop" begin-defaults Begin changing default values for CAM registers. Notation used is as if you were constructing step-list entries. Eg., "kick 5 x" would make the default for kick in the x direction be 5. end-defaults my-defaults Select user copy of defaults (normal situation). Any defaults changed will be restored by "new-experiment". standard-defaults Select system copy of defaults. Any changes are permanent until the "step" program is restarted. read Used after a register word, means that you want to read rather than write the register. You should only have one module selected when you read, and you may want to specify a buffer into which to read (see ".regs" for register lengths). reg! (s value -- ) Value to put in current reg for all selected layers. layer-mask (s -- addr ) 16 bit mask -- which layers are affected by following operations (until new CAM register is started) all-layers reset layer mask to all layers CAM registers (see hardware manual). User programs will normally only directly manipulate the first few of these registers. When a register name is executed, a default step-list entry is added to the current step-list. Subsequent register-specific words may modify parts of this entry, before another register name is executed, ending the previous entry and starting the next. Note that even within a "define-step", register words are executed to produce a step-list entry. Thus normal colon definitions can be used as macros for step-list construciton, which is how all the higher-level step-list constructs work. .regs List all registers and lengths select select which modules are being addressed (usually all for writes to CAM, and just one for reads from CAM). For very advanced users only! run run a scan of the space kick shift bit-slices sa-bit specify site address bits as possible data sources lut-src select input bits to the lookup table fly-src select input bits to the flywheel output site-src select new input data to replace site bits event-src select input bits to hardware event counters display select display output (controlled by "show") show-scan low level control (don't change) event event count I/O register lut-index lut address index used during I/O (see "lut-data") lut-perm lut address permutation for I/O (see "send-perm-table") lut-io lut I/O register (use "lut-data" or "send-perm-table") scan-index logical scan address (and starting point for I/O) scan-perm scan or I/O in permuted site-address order scan-io site-data I/O register scan-format control scan parameters (set by "space" and "sector") offset cumulative offset from kicks (used also for assemble) dimension specify dimension boundaries environment hardware environment info (e.g., type of DRAMs) multi multipurpose pin hardware control connect intermodule glue-wire connectivity control module-id name of module group-id group info about module int-enable hardware interrupt enable flags int-flags hardware interrupt asserted flags verify changes subsequent write operations to "compare" ops dram-count keep 1's count for DRAM as they update (error checking) delay (noop, "delay 10 clocks" delays for 10 SPARC clocks) Higher level: switch-luts Swap active and inactive luts. save-select/sector/src Used to save module selection information, info about what part of space is being scanned, and source information. restore-select/sector/src Restores above info. Can only be used within the same step list as the "save" above. ** LINKING C ROUTINES ** The "clink" routine is part of standard Sun Forth, but we describe it here as a reminder that any desired external C routines can be easily linked into Forth and used as Forth primitives. Routines which are actually macros must be explicitly redefined as the body of named subroutines to make them available. clink (S object-file-name -- ) An object file is produced from a ".c" file using 'cc -c myprog.c' yielding "myprog.o". This is then linked using '"" myprog.o clink'. All C subroutines in the file will get names in Forth with an underscore prepended ("abc" becomes "_abc"), and all arguments (up to 5) should be put on the Forth stack in the reverse of the C order. None of the arguments will be dropped by the C subroutine, and the result register from the C execution will be put on the stack by the Forth word "ret". ** PIPE IO and INTERPROCESS COMMUNICATION ** We provide routines for starting Unix programs from within "step" and interfacing with them via pipes. See "step-xmon" for an example of the use of these routines to control the XCAM display. In this case, the Forth asks XCAM to set up shared memory buffers which are used for image and colormap communication, and the pipe interface is just used for control. fork+pipes (s 0 p2 p1 prog wr.pipe.addr rd.pipe.addr -- pid ) Given pointers to a read pipe and a write pipe and a cstr giving the unix program name, along with cstr's giving two parameters for the program, this routine will fork and start the indicated program, with the specified command line arguments and with its standard input and standard output connected to the specified pipes. command>pipe (s data op wr.pipe.adr rd.pipe.adr -- data' errorcode ) Send 8 bytes of data to another process via a pipe. Four of the bytes are considered to be op code, the other 4 are considered to be data. If the variable "pc-half-duplex" is false, this word will wait for 8 bytes of data to be returned by the other process, and these will be left on the stack; otherwise, 0 0 will be left on the stack. create-pipe ( ----- pipe-name ) (s -- addr.pipe ) Create a named pipe data object. When executed, it returns a pointer. We need to create two pipes for our interprocess I/O: one for read and one for write. ccstr ( ----- name ) (s -- addr.cstr ) Used to define a fixed C string. ** DEBUGGING ** This software includes a number of features to aid in debugging. The "view" utility will allow you to see the first line of a word's definition (which will include its argument list), and will also indicate which file the definition is in. "see" will uncompile a definition from its Forth code. "debug" will allow a single-step trace of instruction execution. "sifting" will show all Forth words whose name contains a specified substring. "'used" will list all colon definitions that use a specified word. "vocs" will list all vocabularies that contain a definition with the specified name. view (s -- ) ( ---- name ) First line of source. see (s -- ) ( ---- name ) Uncompile Forth word. (see) (s acf -- ) Uncompile Forth word. debug (s -- ) ( ---- name ) Trace execution of Forth word. debug-off Turn off debugging. fence Variable. Specifies address before which debugger ignores definitions. sifting (s -- ) ( ---- partial.name ) List dictionary matches. 'used (s -- ) ( ---- name ) Find where used. vocs (s -- ) ( ---- name ) List vocabularies where defined. For lower level debugging, we provide some words to list machine parameters, dump contents of buffers, and show the contents of a given register on all modules (particularly useful for "int-flags" after an error interrupt). We also have some flags that can be turned on to cause step-list compiling instructions to print out human readable information about what they are doing as the step-lists are produced. .machine Print all machine parameters. bdump (s n -- ) Screen-dump 1st n CAM-wds of current buffer. show-all (s -- ) ( ---- name.reg ) Read and display register. verbose Variable. "verbose on" prints out step lists in text form as they are compiled and scheduled. perm-verbose Variable. "perm-verbose on" prints out information about permutations generated, for example, by "assemble-fields". Finally, we should mention some techniques for CAM experiment debugging. First of all, during debugging, you should turn all step lists that are giving you problems into colon definitions ending in *step*. Then you can freely insert "show" at various points in these lists, to display partial results. You may wish to insert extra scans of the space to let you see situations both before and after kicks. The spread display is particularly useful for watching the bits change. Note that "show" will not use its specified "show-subcell" or "show-fields" unless the assembled cell is all from subcell 0 when it is executed. If not, it will show the assembled cell instead. You can use "->" and "update" together with field names to test what a rule does for specific cases. For example, to set the "center" field to 1, execute "1 -> center update" either directly in Forth, or in a file that you load. Set all of the other fields that you want in a similar manner, and then (assuming your rule is called "myrule"), you can see the new value of specified fields (such as "center") by executing "myrule update center ." where "." is the Forth command that prints a number on the stack.