ROMable Forth

Topics relating to various Forth models on the 6502, 65816, and related microprocessors and microcontrollers.
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Post by kc5tja »

You have the wrong link, as they've somewhat reorganized the website. I recommend just visiting the home page of the project:

http://thinking-forth.sourceforge.net/

and going from there.

Concerning Starting Forth, an updated version is available online from: http://www.forth.com/starting-forth/index.html

The forth.com book has nearly all of the original illustrations restored, and is properly updated for ANSI Forth.
User avatar
BillO
Posts: 1038
Joined: 12 Dec 2008
Location: Canada

Post by BillO »

Wow!

It seems when it comes to Forth, there is considerable scope for getting beyond one’s depth. Unfortunately I may not have the time to plumb these depths for a year or two, and at my advanced age that could mean a lifetime.

No problem though. The day I stop learning... well, I’d hate to think about it…
Bill
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

GARTHWILSON wrote:
I really should do a YouTube video of my interactive embedded development. We have a digital camera that can do video, but I guess we'll have to find and learn some video-editing software...

You don't really need to edit alot, plus youtube allows you to annotate the video with text and do basic start and end clipping. If you make a large video and need to split it into parts, I think 2GB or ten minutes was the criteria, there's free windows software out there, not sure about linux. You will need alot of patience while uploading however!
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

searching for linux tools

Post by BigEd »

(off-topic!) For any question about choosing or finding tools to run on linux, it's always handy to try a site:lwn.net search. In the case of video editing, Linux Weekly News has this three part series
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Advantages of 65816 for Forth

Post by BigEd »

Hi Garth
Quote:
The '02 ITC Forth averages about 12,500 primitives per second per MHz. My '816 does about 31,000 per second per MHz.
Could you say which aspects of the 65816 give you that advantage? Does much of the improvement come from improved techniques which you could in theory apply in 6502?
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Post by GARTHWILSON »

Quote:
Could you say which aspects of the 65816 give you that advantage?

It's primarily that the '816 is so much more efficient at handling the 16-bit cells than the '02 which has to take 8 bits at a time and increment addresses or indexes in between and such. Here's the simple example of @ (pronounced "fetch"), which takes a 16-bit address placed on the top of the data stack and replaces it with the 16-bit contents of that address.

First for 6502:

Code: Select all

       LDA  (0,X)
       PHA
       INC  0,X
       BNE  fet1
       INC  1,X
fet1:  LDA  (0,X)
       JMP  PUT
; and elsewhere, PUT which is used in so many places is:
PUT:   STA  1,X
       PLA
       STA  0,X


For the '816, the whole thing is only:

Code: Select all

       LDA  (0,X)
       STA  0,X         ; For the '816, PUT is only one 2-byte instruction anyway, so there's no sense in jumping to it.


@ was given such a short name because it's one of the things used most. You can see the difference in the code length, 2 instructions versus 10.

Then there are the 816's extra instructions and addressing modes that improve efficiency, like MVN and MVP (the memory-move instructions), and the stack-relative addressing which helps in looping for incrementing the index and comparing to the limit and getting the indexes for nested loops. (Think of the typical I and J indexes in nested BASIC FOR-NEXT loops, except that you can do it in Forth without taking variable space.) These are just a couple off the top of my head.

Note of course that I'm not talking about running '02 Forth on an '816, something which in itself would not result in any performance gain. The '816 Forth was re-written to take advantage of the 816's extra capabilities.

Then because of the shorter assembly code, it became practical to re-write a lot of secondaries as primitives. In Forth, basically everything is a "word"—even a variable which puts the address of its data space on the data stack. A primitive is a word that is defined in assembly language, so of course it has the best performance. A secondary is a word that is defined in terms of other Forth words, and those words can in turn be primitives or secondaries (or any mix thereof). A secondary has overhead between each pair of words. Even in subroutine-threaded Forth, that usually means a JSR/RTS pair. So to execute a single secondary, you might, depending on its complexity, execute a lot of JSRs and RTSs. In indirect-threaded Forth which is what I'm using and is slower but not without its advantages, there are almost no JSRs or RTSs, but there's often nest and unnest (which have functions similar to JSR and RTS), and there's always NEXT which is the inner loop, and these add overhead. The nice thing on the '816 is that the assembly language becomes short enough that now you can suddenly justify taking a lot of those words that pretty much had to be secondaries on the '02 and re-write them as primitives, not only speeding them up a lot but sometimes even making them shorter instead of longer!

BTW, to avoid too much confusion if you come across another terminology: Primitives are also called "code definitions," and secondaries are also called "colon definitions."
Last edited by GARTHWILSON on Mon Mar 15, 2010 4:25 am, edited 1 time in total.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Post by BigEd »

Thanks - that's a great explanation. Interesting that the 16-bit registers running through an 8-bit wide memory interface doesn't hurt too much (which is to say, it might hurt to some extent, but you still got a very impressive speedup and density improvement.)
User avatar
commodorejohn
Posts: 299
Joined: 21 Jan 2016
Location: Placerville, CA
Contact:

Re: ROMable Forth

Post by commodorejohn »

I know this is an old topic, but I figure it's worth reviving. I'm trying to find a good solution for a ROM-resident 65C02 Forth since I picked up one of floobydust's SBCs and want to get something a little more flexible than EhBasic running on it. "Performant" would be preferable to "small," since there's about 24KB of free space in the ROM, but "small" is always nice when you're limited to 32KB of RAM. I know Daryl put together a 'C02 port of FIG-Forth, but from what I'm noticing in the source comments and the FIG-Forth installation manual, it looks like the system is designed with the dictionary at the bottom of memory, which makes sense for a RAM-based system but is obviously not ideal for a ROM application on the 6502. Is there a workaround for this?
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: ROMable Forth

Post by GARTHWILSON »

commodorejohn wrote:
I know Daryl put together a 'C02 port of FIG-Forth, but from what I'm noticing in the source comments and the FIG-Forth installation manual, it looks like the system is designed with the dictionary at the bottom of memory, which makes sense for a RAM-based system but is obviously not ideal for a ROM application on the 6502. Is there a workaround for this?

Hopefully this will be more clear than mud. Here goes.

Just change how VARIABLE works, to put the data in RAM, while the code remains in ROM. HERE returns the normal dictionary pointer, so you'll need another word, THERE (only in your assembler or metacompiler), to keep track of where the first available RAM address is after the space previously allotted for variables. After the Forth system is compiled or assembled, HERE and THERE become aliases, as do GAP and ALLOT, because when the target system runs, it will compile code into RAM, since it can't write to its own ROM (or at least not quickly, in the case of EEPROM).

My 6502 Forth experience began with a metacompiler we bought at work in 1990. There were loads of shortcomings which I immediately began remedying. One was that I wanted to take the address of a variable array, and add an offset into that array, and the metacompiler wouldn't let me,. It said the data area of the target is not available to the metacompiler. Of course not! I know that! I don't want the data right now! I just want the address! So I made a new variable definition like this:

Code: Select all

: VAR  ( n -- )                   \ n is how many bytes you
   THERE SWAP ALLOT CONSTANT ;    \ want in the variable.

Now the same code will work with both the metacompiler and compilation on the target itself. (Actually, I made mine IMMEDIATE, although I can't think of a reason for that right now. I should have written it in the comments.) It's using CONSTANT to point to the address. A typical syntax example would be

Code: Select all

WSIZE VAR FLLEN
to get a variable named FLLEN (file length) with WSIZE bytes allotted to it. I know this operation is slightly different from that of VARIABLE, since I'm putting the amount of RAM I want first, instead of letting VARIABLE allot two bytes and then if I wanted six I have to manually allot four more. Why not just tell it up front that you want six. I think that's more clear.

Again, THERE is a variable only in the assembler or metacompiler, not the running target system. INIT-DP (initialize dictionary pointer) is a constant in the target system. If you had a metacompiler, one the last lines of your source code would be:

Code: Select all

THERE  INIT-DP  !
or, if putting the system together win an assembler, something like:

Code: Select all

INIT-DP:  EQU   THERE

Storing the INIT-DP value in variable DP will be one of the things done in COLD, at boot-up. COLD of course is assembled or metacompiled by the assembler or metacompiler you're forming your Forth system on for the target to run.

I really do need to get my '02 and '816 Forth sources cleaned up for publication. They've been on my to-do list for years. The '816 one is closer to done. The '02 one will be more work.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
handyandy
Posts: 113
Joined: 14 Sep 2015
Location: Virginia USA

Re: ROMable Forth

Post by handyandy »

You can take a look at this: viewtopic.php?f=3&t=5226

It's the RSC Forth system for Rockwell's 6502. It was ROM based. There's some dump files I haven't gotten to completely disassembling yet.

Cheers,
Andy
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: ROMable Forth

Post by DerTrueForce »

ScotWS' Tali Forth 2 is ROMable, and if I remember correctly, it uses 24K of ROM space by default. This includes a certain allocation for user Forth code, and you could probably make that smaller if you find yourself running out of space, although I haven't tried.
JimBoyd
Posts: 931
Joined: 05 May 2017

Re:

Post by JimBoyd »

GARTHWILSON wrote:
Since the metacompiler itself was a black box, I could not get into it and fix it like you can in Forth. I figured out some work-arounds but they were running out of gas and I pretty much decided I'd have to re-write it for an assembler anyway even for my own use.
When I get Fleet Forth for the C64 finished, all the source files will be included ( even the metacompiler.) Not just on the C64 disk images, but also as ordinary text files for easier perusal. I'm not sure how long it will take. I'm just getting started on the most difficult part, writing the documentation!
whartung
Posts: 1004
Joined: 13 Dec 2003

Re: ROMable Forth

Post by whartung »

There's nothing stopping you from putting the base dictionary anywhere you want, in high mem for example, and then having the cold start routing weave in a do-nothing word in low memory that points to the end of the ROM dictionary, but resets HERE to be in a proper, RAM based area. All of the new words would define against that NOP marker, since the search is from the "top of dictionary" backwards.

There's nothing that says the dictionary needs to be contiguous in RAM as long as the pointers are set up properly.

I'd also probably tweak FORGET to be cognizant of the RAM/ROM barrier, since FENCE is simply ranged based. But that's a pretty minor tweak as well.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: ROMable Forth

Post by GARTHWILSON »

whartung wrote:
There's nothing stopping you from putting the base dictionary anywhere you want, in high mem for example, and then having the cold start routing weave in a do-nothing word in low memory that points to the end of the ROM dictionary, but resets HERE to be in a proper, RAM based area. All of the new words would define against that NOP marker, since the search is from the "top of dictionary" backwards.
You wouldn't even need the do-nothing word. Just store the INIT-DP constant in DP (the dictionary pointer, whose content is returned by HERE), and the same with LATEST, in COLD. The first time you CREATE a word in RAM (assuming you're compiling with headers), its link field will be filled in with the NFA of the last word defined in ROM, and LATEST gets updated. My INIT-DP is set at $300, even though ROM words start at $8000 and go up from there.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
SamCoVT
Posts: 344
Joined: 13 May 2018

Re: ROMable Forth

Post by SamCoVT »

DerTrueForce wrote:
ScotWS' Tali Forth 2 is ROMable, and if I remember correctly, it uses 24K of ROM space by default. This includes a certain allocation for user Forth code, and you could probably make that smaller if you find yourself running out of space, although I haven't tried.
If you have a 65C02, I'll give another vote for Tali Forth 2. It's specifically designed to be easy to port for new SBC users - you basically just need to implement init, getc, and putc routines (similar to getting ehBASIC up and running), and you can rearrange the memory map if you need to.

Tali2 is an STC Forth and it supports native compiling, which lends itself to respectable performance. The only thing Tali2 isn't is small. It will eat most of your 24K. It was designed for a 32K ROM with 8K left for the user. I run it on my own 65C02 SBC (32K RAM/32K ROM) and would be happy to help you get it running on yours. You can also run it in the py65mon simulator if you just want to try it out.

https://github.com/scotws/TaliForth2 and the instructions for trying it in py65mon are in the README.md file (which github displays automatically below the list of files).
Post Reply