home .. forth .. colorforth mail list archive ..

Re: [colorforth] objects and forth


David J. Goehrig wrote on Thu, 5 Feb 2009 06:56:51 -0500
> On Wed, Feb 04, 2009 at 10:33:42PM -0300, Jecel Assumpcao Jr wrote:
> > 
> > You might find this course interesting:
> > 
> > http://www1.idc.ac.il/tecs/
> 
> Thanks Jecel, it does look interesting. I got to say, I disagree 100% with
> their approach on the software side.  Any student is better off learning
> on real hardware, or at least an emulator of real hardware like Bochs.

I think both alternatives have their advantages. There are things that
shouldn't matter but in practice they sometimes do. For example: there
is little difference between a software emulation of some old computer,
like a TRS-80, on a modern PC and a reimplementation of the same machine
using some FPGA development kit. The screen looks the same, the keyboard
feels the same and the speed is the same. Yet the sensation of using the
two is different. But it might be just nostalgia on my part - I should
test it with someone who has never seen the original machine and see
what they think.
 
> > About the subject, I worked on hardware for OO Color Forth in 2001/2002
> 
> Do you have anything on it on your sites?  I'm guessing you were looking to
> use it to power your Self port?

Here are some pictures of the machine I was talking about:

http://www.merlintec.com:8080/hardware/uploads/14/oliver002.jpg

http://www.merlintec.com:8080/hardware/uploads/16/oliver11.jpg

This terminal for truck drivers started out life as an ATMega603
microcontroller programmed in Forth. But my clients were not happy with
the limitations (128KB Flash not programmable in the field, 4KB RAM) so
I replaced this with the board in the first picture in 2001, which
reduced the cost while eliminating the restrictions (512KB Flash field
upgradable, 8MB RAM). Instead of an interpreted Forth on the 4MHz
processor we would have a MISC running Forth natively at 57MHz. The Self
project was a parallel effort (with a much larger FPGA) but the two
influenced each other in interesting ways over the years.

Given that all information would come from the 512KB Flash whenever the
machine lost power, it might seem silly to have more than 1.5MB (suppose
a 3:1 compression for data in the Flash). But building the machine with
just 4MB or 2MB would actually have made it more expensive! You would
have to go all the way down to 32KB before you saved any money.

The most natural size for the MISC processor was 16 bits since that was
the width of all the memories used. But it would have to address more
than 128KB (64K words) so an option would be 32 bits, but that was too
wasteful. 24 bits would have been about right, but really awkward.

On the software side, a small problem with Forth is that you have very
local data (on the stack) and very global stuff (the dictionary). It is
sometimes nice to have something in between. Imagine the code for the
serial port, for example. You need stuff like the address of the status
register or the setting of some counter. Globals work ok for one serial
port, but become awkward when you have two or more. One solution is to
use objects - then you have a single very local data (the object
reference on the stack) and it leads you to context dependent global
data. So now I could have 64K objects in a 16 bit implementations and
these would make good use of the memory I had.

So I added just one register to MISC and called it "self". It always
pointed to the current object. When you addressed the memory using the @
and ! instructions, the offset would come from the "a" register and the
base address would come from an object table indexed by "self". There
was a small, virtually addressed cache (which meant that the object
table was only accessed when the cache missed and not on every memory
instruction).

The call instruction was replaced with two variations of send. One which
kept the value of "self" as it was and another that loaded "self" from
the top of the data stack. The old value of "self" was pushed to the
return stack along with the "PC" (the return instruction popped the two
registers).

Normally message sending is a slow process with lots of indirections and
complicated caches to try to make it faster. That was not acceptable to
me since I wanted it to run as fast as normal ColorForth. But I had all
this RAM being wasted, so I simply implemented a full selector/class
table. This is something that is used in the literature as a comparison
with practical implementations but is not considered itself to be
practical (because the table is normally 5 to 20% full at most). This is
simply a huge 2D table where the row index is derived from the class of
the object and the column index is the selector (or name) of the
message. That gives you the address where you should jump to.

Since most methods are small, I put the start of each one in the table
entry. That eliminated one indirection in the common case, and when the
method was too large to fit in there you just put in a jump to the
actual method and would be no worse off than in the original table.

One popular solution for finding the class of an object is to have its
first field point to it. But the alternative I used encodes the class
into the object pointer itself, avoiding a memory access to fetch that
every time. So given the value in "self" and the selector (encoded into
the send instruction) I could start fetching the first instruction from
the new method on the very next clock cycle, which made this as fast as
a call in normal ColorForth.

In early 2003 my clients asked me if I could switch to Smalltalk since
they found that more readable than ColorForth. I said it wouldn't fit
into 15K gates like the modified MISC did. But after thinking about it
for a couple of weeks I figured out a way of converting MISC into a
reasonable Smalltalk processor by just adding two banks of 8 registers
each. They liked this change but in early 2004 the project was still
late and was cancelled though I continued to work on it for a few more
years. These register banks were used to implement Smalltalk blocks, but
other than that the difference compared to normal MISC and ColorForth
was really tiny. Since I was so busy with the hardware level I didn't
write a lot of code in this OO ColorForth, but what I did write turned
out very nice. The most significant difference was the use of a garbage
collector instead of the traditional Forth memory allocation. This makes
string manipulation a bit more convenient. And like I wrote above,
having objects as places to store intermediate level data worked really
well.

I used the term "class" above several times but the system was actually
prototype based like Self instead of like Smalltalk. This is a very
minor detail.

There are many programming languages I like to use: Forth, Lisp,
Smalltalk, APL, C, Prolog and so on. Mixing them up doesn't often get
you very good results, but sometimes it works.None of these is good for
all problems, but sometimes I see Forth fans deny that by refusing to
consider as valid problems for which their favorite language is not the
best option. Like the old joke: "Doctor, it hurts when I do this...",
"Then don't do that!"

-- Jecel


---------------------------------------------------------------------
To unsubscribe, e-mail: colorforth-unsubscribe@xxxxxxxxxxxxxxxxxx
For additional commands, e-mail: colorforth-help@xxxxxxxxxxxxxxxxxx
Main web page - http://www.colorforth.com