README for ICn (native) version 1.1 compiler sources

**********************************************************************
* Original code for IC version 2.860 (beta) by Randy Sargent and Anne
* Wright 
*				Wed Dec 7 1994
*
* Code for ICn 1.0 (alpha) native compiler and syntactic enhancements
* by Kurt Konolige [konolige@ai.sri.com]
*				Thurs May 25 1995
**********************************************************************


This is an updated version of IC version 2.860 beta:

	ICn version 1.2 (beta)

ICn has the following changes from IC:

	* Option to compile individual functions to native code
	* Enchanced syntax, especially for memory access
	* Bug fixes to source code

ICn will compile either to pcodes or native codes, and both can run
compatibly on the 6.270 or Rug Warrior boards.  Native codes are
significantly faster (2x-25x), but usually take more space (0.9x-2x).
Use native-code functions when you want the speed, e.g., in interrupt
code.  Details on constraints for producing fast native code are given
below.

Several new syntactic features enhance the usability, efficiency, and
readability of ICn.  These include automatic type promotion, automatic
casts in assignments, contant declarations, and pointer access to
memory.  Future modifications will include pointer arithmetic.

*** NOTE *** 

ICn v1.2 is now stable enough to be a beta release.  Most standard IC
constructs will work in pcode mode, including arrays.  Almost all
features will also work in native mode; see below for exceptions.


NATIVE MODE COMPILER

ICn's compiler recognizes a "native" procedure declaration, e.g.,

	int *MSLO = 0x14;
	int *TCNT = 0x100E;
	int *bb   = 0x1024;

	native int time1(int n)
	{	
	  int a, b;

	  a = *MSLO;
	  while(--n)
	    *bb += *TCNT;
	  b = *MSLO;
	  return b-a;
	}

ICn will compile time1 not to pcodes, but to native HC11 instructions,
together with initial and final code to interface to the pcode
interpreter.  Native procedures can be called just like pcode
procedures.  It is not currently possible to call other procedures
(native or pcode) from native ones, but this will be fixed shortly.

Here are time and space figures for time1:

	Mode	us/iteration   bytes
	--------------------------------
	Native	    11		73	
	Pcode	   291		64	

These figures are for an HC11F1 using a 4 MHz bus (16 MHz crystal);
the 6.270 and miniboard are half this speed.

The compiler first converts syntactic statements into semantic
expressions, performs some reductions, and then spits out either
pcodes or native codes, depending on the declaration.  There is little
optimization; typical loops coded by ICn take about twice the time of
hand-coded ones.  With some additional work, optimization could reduce
this difference.  I don't know how ICn compares with commercial
compilers.


  Efficient Native Code

There are several constraints to keep in mind when writing native
procedures.  In general, using float and long types makes native code
less advantageous, and also increases native code size relative to
pcodes.  For example, consider the following function.

	float fa;

	native int time2(int n)
	{
	  int a, b;
	
	  a = *MSLO;
	  while(--n)
	    fa = fa + (1.0*fa);
	  b = *MSLO;
	  return b-a;
	}

Here are time and space figures for time2:

	Mode	us/iteration   bytes
	--------------------------------
	Native	   218		128	
	Pcode	   469		 70	

Here the speedup is only a factor of two.  If the difference in loop
overhead time is subtracted out, the floating-point operations
themselves take 206us in native mode, and 239us with pcodes.

Since the HC11 is *very* slow on any floating-point operation, and on
longword multiplication and division, these should be avoided.  Use
int's and char's whenever possible, e.g., try scaled arithmetic
instead of floating-point.

Conditionals have not yet been optimized in native mode.  while loops
with a countdown to zero, as in the functions above, work best.

Prefix increment and decrement are faster than postfix.

Use const declarations for variables whenever possible.

Shift operations are not optimized in native mode.


  Restrictions

	* Arrays are not yet implemented in native mode. 
	* poke, pokeword, peek, peekword, bit_set, bit_clear, and
	     	mseconds have been supplanted by newer constructs (see
		below).  They are still available for compatibility.
	* None of the process commands (start_process defer, etc.) are
		available in native mode.


  Multiprocessing

Native mode procedures currently hog the processor until they exit.
This can be an advantage for some applications, but not others.  A
workaround is to use smaller native procedures, called by a pcode
procedure.  I plan to implement an operation that lets native
procedures cede the processor at a given point.


  Interrupts

Native mode procedures can be installed as interrupts, since they run
HC11 code.  I haven't implemented this feature yet; more details in a
future release.


SYNTACTIC ENHANCEMENTS

I've been frustrated by the clunkiness of POKE/PEEK constructs, when
C's dereferencing mechanism is so elegant, as well as a number of
other features.  Here are some modifications in ICn.


  Pointer assignments and dereferencing

Pointers can be set to memory locations by assigning them to an
integer.  char, int, and long types are available for 1, 2, and 4 byte
access.   For example,

	char *ca = 0x100A;

sets ca as a pointer to the byte at memory location 0x100A.  ca can be
used in assignments and references, e.g.,

	*ca += 3;

increments the byte at location 0x100A by 3.  In IC, you would have to
use the statement

	poke(0x100A,peek(0x100A)+3);
	
Similarly, bit_set and bit_clear are implemented with assignment
statements on memory pointers:

	*ca = *ca & !0x0f;  instead of   bit_clear(0x100A,0x0f);

More elegant is:

	*ca &= !0x0f;

The function mseconds() has been superseded by the pointer syntax;
use:
	const long *MS = 0x12;
	... + *MS + ...

Or you can access the low and high words of the system ms timer as:	
	
	const int *MSLO = 0x14;
	const int *MSHI = 0x12;



  Constant Declarations

Global and local variables can be declared constant.  This is most
useful in setting constant referred to in other parts of the program
or other files, since there is no preprocessing facility.  It is also
a more efficient way to set up memory pointers.

	const int a = 34;
	const int *b = 0x100A;

Constant declarations must have an initialization.  They are treated
like constant numbers in expressions, and reduced by the compiler.
For example,

	const int a = 34;
	...
	i = a/2;

declares a a constant integer, so a/2 is reduced to the constant 17
before it is compiled into the assignment.

Constants may not appear on the left-hand side of an assignment
expression. 


  Type Promotion and Automatic Casts

IC does not perform type promotion, which may be a Good Thing in
reminding the user when longs and floats are being produced.  But it
can also be a pain.  In expressions, ICn does automatic type promotion
according to standard rules, e.g.,

	int/long   -> long
	int/float  -> float
	long/float -> float
	char/x     -> x

NOTE: there is an error in ICn's (and IC's) type promotion from ints
to longs: negative ints are *not* sign-extended.  Chars are always
considered to be unsigned.

In assignments, casts are also made automatically to the assigned
variable type, by conversion and truncation if necessary.  ICn will
cast integers to pointers.


  Pointer Addition

This is a useful feature in some applications.  It is not yet
implemented, but will be in a future release.


GETTING AND RUNNING ICn

The Unix sources for ICn are direct descendents of IC version 2.860
(beta).  There is a distribution file in

	ftp://ftp.ai.sri.com/pub/konolige/ICn-1.1b.tar.gz. 

To compile ICn, untar the distribution, then go into the libs
directory and type "configure" to autoconfigure the libraries.  You
might check the original config.h file included with the distribution;
this is the config file I used on a Sparc SunOs 4.1.3/4 machine.

After configuring ICn, go into the libs directory and type "make".  If
all goes well, do the same in the "ic" directory.  I've also included
the original dl (downloader) and mon (monitor) directories; they
work as before.

To run ICn, you need to download the pcoder22.s19 (6.270 board) or
pcoderwl.s19 (Rug Warrior board) file included in the pcode directory.
This file contains only a minor modification to the pcode assembler
file included with the IC 2.860 distribution.  After downloading and
resetting the board, start up ICn (type "icn") and you should be in
business.  Note that it takes a little longer to start icn, since it
reads jumptable addresses from the board during initialization.


OTHER USEFUL INFORMATION

IC was originally written by Randy Sargent and Anne Wright for use
with the miniboard and 6.270 board at MIT.  There is a commercial
version of IC (3.0) available from 

Randy Sargent
Imachinations
2 Newton St.  Apt. 1
Cambridge, MA 02139
(617) 547-6664

The original pcode interpreter was written by Randy Sargent, Anne
Wright, and Fred Martin.

I've used IC to experiment with low-level control of various
home-built robotics platforms in AI courses.  The latest one, Erratic,
placed second in the 1994 AAAI robotics contest.  A commercial version
of this platform is available from 

Real World Interface, Inc.
P.O. Box 375
Jaffrey, NH 03452
(603) 532-6900