New here, but not to Forth or the 6502s
New here, but not to Forth or the 6502s
Forth seems to be quite active here on the 6502 forum, perhaps that's because Forth is being used where it is used best IMO, in controlling hardware.
I've used Forth ever since the 80's when I first decided that the R6511AQ would the CPU in my new POS terminal design. I already knew about Forth from having played with it on Apple IIs but when I say play, I mean that I was writing useful software but having fun. I didn't want the chip with the Forth built-in so I purchased and hacked the ROMs. After designing suitable hardware I was up and running in no time with my POS terminal software even though this was probably the first time I had written any large application in Forth or handled 6502 assembler. I went on to using 65816s and writing Forths for that and also Mitsubishi's single-chip version based on that, the M37702 which I used in many industrial designs for most of the 90's.
But single-chip micros in the 90's never really had Flash or much RAM so unfortunately I ended up using MSP430s and then LPC2148 ARM chips having written Forths for these too. The LPC2148 is still being used in product to this day running my Forth (which also came 2nd in the Circuit Cellar Philips ARM Design Contest in 2005).
Since then I have mainly used the Parallax Propeller although initially I didn't use Forth for this chip and the Forths that were available were not good enough for commercial use. All that changed in 2012 when I finally decided what the heck, I need more speed and more code in the same amount of memory, how hard could it be to write a Forth for this chip? So Tachyon Forth was born and went through new versions over the years while being deployed in commercial product until I finally stopped at V5.4. That's because I had developed Tachyon on the successor to the Propeller, dubbed the P2, whereas the original Prop is now referred to as the P1. Although I have had Tachyon running on the P2 in various forms on FPGA for several years, it was only last year that engineering samples were made with my Tachyon (now called TAQOZ) embedded in mask ROM. Production quantities of this very very cool chip will be available in the next few months. I can play back audio, images, and even video from FAT32 SD cards, and that's just the start.
So I have lots and lots of code for Forth and the 6502/65816/M37702 etc and just thought I'd introduce myself to this very active and interesting forum, and maybe I might even dig out some of my old 65xx boards and plug them in. Maybe I might even port Tachyon across as well and have some fun there too.
I've used Forth ever since the 80's when I first decided that the R6511AQ would the CPU in my new POS terminal design. I already knew about Forth from having played with it on Apple IIs but when I say play, I mean that I was writing useful software but having fun. I didn't want the chip with the Forth built-in so I purchased and hacked the ROMs. After designing suitable hardware I was up and running in no time with my POS terminal software even though this was probably the first time I had written any large application in Forth or handled 6502 assembler. I went on to using 65816s and writing Forths for that and also Mitsubishi's single-chip version based on that, the M37702 which I used in many industrial designs for most of the 90's.
But single-chip micros in the 90's never really had Flash or much RAM so unfortunately I ended up using MSP430s and then LPC2148 ARM chips having written Forths for these too. The LPC2148 is still being used in product to this day running my Forth (which also came 2nd in the Circuit Cellar Philips ARM Design Contest in 2005).
Since then I have mainly used the Parallax Propeller although initially I didn't use Forth for this chip and the Forths that were available were not good enough for commercial use. All that changed in 2012 when I finally decided what the heck, I need more speed and more code in the same amount of memory, how hard could it be to write a Forth for this chip? So Tachyon Forth was born and went through new versions over the years while being deployed in commercial product until I finally stopped at V5.4. That's because I had developed Tachyon on the successor to the Propeller, dubbed the P2, whereas the original Prop is now referred to as the P1. Although I have had Tachyon running on the P2 in various forms on FPGA for several years, it was only last year that engineering samples were made with my Tachyon (now called TAQOZ) embedded in mask ROM. Production quantities of this very very cool chip will be available in the next few months. I can play back audio, images, and even video from FAT32 SD cards, and that's just the start.
So I have lots and lots of code for Forth and the 6502/65816/M37702 etc and just thought I'd introduce myself to this very active and interesting forum, and maybe I might even dig out some of my old 65xx boards and plug them in. Maybe I might even port Tachyon across as well and have some fun there too.
Re: New here, but not to Forth or the 6502s
pbj wrote:
maybe I might even dig out some of my old 65xx boards and plug them in.
Welcome, pbj -- it's a very interesting introduction you've written, and I can see there'll be lots to talk about with the members here. I'll be looking forward to hearing more from you.
cheers
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
https://laughtonelectronics.com/Arcana/ ... mmary.html
Re: New here, but not to Forth or the 6502s
One of the aspects of Tachyon has been that it primarily compiles interactive text input word by word and runs this temporary code on end of line. So there are no special print words etc and I can just as easily write a quick one-liner complete with DO LOOP IF THEN etc that runs fast as compiled code like this:
$80 $20 DO I EMIT LOOP
My first few versions of Tachyon were all bytecode based but then I moved to 16-bit wordcode based instructions that mostly were addresses but there were a range of addresses that are used for encoding instructions such as conditional branches and short literals etc. Which reminds me, DO is an actual instruction (there is no (DO) ) and it pushes the IP onto a dedicated loop stack so that that LOOP can read this address directly from the loop stack. The loop index I is available in words called from the DO LOOP.
There are lots of design decisions that make Tachyon fast and compact so it will be interesting to see how I can implement it on the 65816/M37702 perhaps as a 16-bit wordcode with 32-bit wide stack as standard.
$80 $20 DO I EMIT LOOP
My first few versions of Tachyon were all bytecode based but then I moved to 16-bit wordcode based instructions that mostly were addresses but there were a range of addresses that are used for encoding instructions such as conditional branches and short literals etc. Which reminds me, DO is an actual instruction (there is no (DO) ) and it pushes the IP onto a dedicated loop stack so that that LOOP can read this address directly from the loop stack. The loop index I is available in words called from the DO LOOP.
There are lots of design decisions that make Tachyon fast and compact so it will be interesting to see how I can implement it on the 65816/M37702 perhaps as a 16-bit wordcode with 32-bit wide stack as standard.
Re: New here, but not to Forth or the 6502s
Welcome.
I assume the temporary code is compiled somewhere other than the dictionary. That would be handy for building tables, or other structures, without defining support words.
Does it support ?LEAVE and LEAVE ?
pbj wrote:
One of the aspects of Tachyon has been that it primarily compiles interactive text input word by word and runs this temporary code on end of line. So there are no special print words etc and I can just as easily write a quick one-liner complete with DO LOOP IF THEN etc that runs fast as compiled code like this:
$80 $20 DO I EMIT LOOP
$80 $20 DO I EMIT LOOP
Code: Select all
CREATE SOMETABLE
HEX
10 0 DO I C, LOOP
Quote:
Which reminds me, DO is an actual instruction (there is no (DO) ) and it pushes the IP onto a dedicated loop stack so that that LOOP can read this address directly from the loop stack. The loop index I is available in words called from the DO LOOP.
Re: New here, but not to Forth or the 6502s
Tachyon compiles temporary code at the end of the code dictionary while words are stored end to end in the word dictionary while variables occupy data space. So code definitions can cascade into the next and names can be removed selectively while you can ERASE all variables and buffers in the data area without impacting code or dictionary.
As for LEAVE all it does is adjust the index to the limit so that it leaves on the next loop. (come to think of it I could just adjust the limit instead and still access the index after it leaves the loop). The separate loop stack will never interfere with code addresses stored on the return stack which otherwise would not crash gently (recoverable). Not an option on fail-soft software.
Console output testing LEAVE, disjointed DO I LOOP, code vs word dictionary vs data space.
BTW, Since tables are used so often I have a special word that can preallocate space if needed or just tack on data. Being a table it resides in code space.
Here is a table of 16 byte values using the more unobtrusive and readable | instead of the C, (still use , for 32-bit longs)
But sometimes I define a forgettable helper stub to build a table in which case I just preallocate.
TACHYON does not try to be ANS compatible which might be fine for PCs but the embedded world needs far more flexibility.
Default base is always decimal with % # $ prefix to force binary, decimal, hex. The # in the prompt is the current decimal base.
EDIT: After posting this I revisited my kernel code and streamlined it a bit more. Now FOR NEXT and DO LOOP etc use the same stack structure so they can even be intermixed. FOR NEXT seems a bit redundant now since DO LOOP runs just as fast but FOR is equivalent to a 0 DO which means a FOR NEXT loop supports an incrementing I index. A loop takes 32 cycles or 107ns @300MHz.
It will be interesting to see how I implement that on the 65816.
As for LEAVE all it does is adjust the index to the limit so that it leaves on the next loop. (come to think of it I could just adjust the limit instead and still access the index after it leaves the loop). The separate loop stack will never interfere with code addresses stored on the return stack which otherwise would not crash gently (recoverable). Not an option on fail-soft software.
Console output testing LEAVE, disjointed DO I LOOP, code vs word dictionary vs data space.
Code: Select all
TAQOZ# $80 $20 DO I EMIT I 'D' = IF LEAVE THEN LOOP --- !"#$%&'()*+,-./0123456789:;<=>?@ABCD ok
TAQOZ# : IEMIT I EMIT LOOP ; --- ok
TAQOZ# $80 $20 DO IEMIT --- !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ok
TAQOZ# ' IEMIT .L --- $0000_5BAA ok
TAQOZ# NFA' IEMIT .L --- $0000_DFA3 ok
TAQOZ# 4 longs samples --- ok
TAQOZ# 32 bytes inbuf --- ok
TAQOZ# samples 48 erase --- ok
TAQOZ# samples 48 DUMP ---
0001_2343: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................'
0001_2353: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................'
0001_2363: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' okHere is a table of 16 byte values using the more unobtrusive and readable | instead of the C, (still use , for 32-bit longs)
Code: Select all
0 TABLE ma 0 | 1 | 5 | 10 | 25 | 35 | 60 | 100 | 1 | 5 | 10 | 25 | 35 | 45 | 80 | 200 |
TAQOZ# ma 16 DUMP ---
05BC0: 00 01 05 0A 19 23 3C 64 01 05 0A 19 23 2D 50 C8 '.....#<d....#-P.' ok
Code: Select all
100 7 * TABLE FONT5X7Default base is always decimal with % # $ prefix to force binary, decimal, hex. The # in the prompt is the current decimal base.
EDIT: After posting this I revisited my kernel code and streamlined it a bit more. Now FOR NEXT and DO LOOP etc use the same stack structure so they can even be intermixed. FOR NEXT seems a bit redundant now since DO LOOP runs just as fast but FOR is equivalent to a 0 DO which means a FOR NEXT loop supports an incrementing I index. A loop takes 32 cycles or 107ns @300MHz.
Code: Select all
TAQOZ# 1,000,000 LAP FOR NEXT LAP .LAP --- 32,000,096 cycles= 106,666,986ns @300MHz ok
TAQOZ# 1,000,000 0 LAP DO LOOP LAP .LAP --- 32,000,105 cycles= 106,667,016ns @300MHz okRe: New here, but not to Forth or the 6502s
pbj wrote:
As for LEAVE all it does is adjust the index to the limit so that it leaves on the next loop.
- GARTHWILSON
- Forum Moderator
- Posts: 8774
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: New here, but not to Forth or the 6502s
JimBoyd wrote:
At the same time, the behavior of LEAVE was changed to leave the loop immediately ( and discard the loop parameters)
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: New here, but not to Forth or the 6502s
GARTHWILSON wrote:
I added a flag LOOP_LEAVE in mine which you can test later to see if the loop finished the normal way or was aborted
Quote:
unloop removes the loop limit, index, and exit address from the stack and must be followed (although not necessarily immediately) by EXIT.
Code: Select all
<SET UP THE LOOP>
?DO
<TEST SOMETHING>
IF DROP I UNLOOP
ELSE
CS-ROT CS-ROT
LOOP
<DO THIS ONLY IF LOOP COMPLETES>
THEN
<ALWAYS DO THIS PART> ;
Code: Select all
<SET UP THE LOOP>
?DO
<TEST SOMETHING>
IF DROP I UNLOOP
ELSE
CS>A
LOOP
<DO THIS ONLY IF LOOP COMPLETES>
A>CS
THEN
<ALWAYS DO THIS PART> ;
Re: New here, but not to Forth or the 6502s
I'm aware of different ways that loops can be handled and I have never really had a need for anything special beyond using a dummy result value before I enter the loop that is modified by any LEAVE condition. I do have the equivalent of an UNLOOP which I never use but I'm thinking of just making this EXIT at the same time but then again since DO and LOOP are actual runtime words I can still jump over them with IF like this:
So maybe that is useful as it is.
The index crossing the limit is a better test which I have implemented before in my 65816 Forths IIRC and I could make it strict I guess but I'm trying to think where I need it.
Code: Select all
TAQOZ# : LOOPING 0 100 0 DO I 5 = IF 1+ UNLOOP ELSE I . SPACE LOOP THEN . ; --- ok
TAQOZ# LOOPING --- 0 1 2 3 4 1 ok
TAQOZ# SEE LOOPING
E086: pub LOOPING
5D1C: F800 0
5D1E: F864 100 $0064 d
5D20: F800 0
5D22: 010D DO
5D24: 0103 I
5D26: F805 5
5D28: 00B6 =
5D2A: FC03 IF $5D32
5D2C: 0087 1+
5D2E: 0121 UNLOOP
5D30: 5D3B ELSE $5D3A
5D32: 0103 I
5D34: 1AFA .
5D36: 1220 SPACE
5D38: 011D LOOP
THEN
5D3A: 1AFB . ;
32 bytes
--- ok
The index crossing the limit is a better test which I have implemented before in my 65816 Forths IIRC and I could make it strict I guess but I'm trying to think where I need it.
- GARTHWILSON
- Forum Moderator
- Posts: 8774
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: New here, but not to Forth or the 6502s
We've had a few conversations about deviating from "official" Forth standards; so without repeating them, I'll refer to this post and the ones around it, and this post. Deviating from standards seems to give people more reason to turn up their noses at Forth; so I try to stick with what's standard as far as is convenient, but I don't hold back from doing my own thing when it works out better particularly for the 65xx. The C crowd's insistence on conforming to C standards seems to be a barrier to getting better C performance for the 6502. On another 6502 forum, I have suggested certain improvements, and the answer I get is that "the standards don't allow that." My answer is, "So??"
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: New here, but not to Forth or the 6502s
Forth is the ugly word on other forums whereas on a Forth forum it is "standards" believe it or not! So I just say yeah, standards are great .... for the majority of tasks on the majority of larger systems such as PCs. After all, the standards are PC centric yet the embedded world has its own demands and constraints, and the standards would only hobble a Forth embedded system, making it effectively unusable.
Embedded apps require that it just works 24/7 and without the memory and processing power of a PC, so it has to be efficient in whatever it does. If it does not do it you can't upgrade "the PC" and your product fails. Tachyon is there to make the supplier and the customer happy, not the standards people poking keys on their PCs.
The inventor of Forth writes his own standards, he does what needs to be done, which is also how Forth was invented. Forth will never be a language for the unwashed masses or education that requires strong typing and syntax to teach and grade. Those who grok it will use it. New processor architectures, new Forths! I started out primarily from a hardware background and so I really appreciate the ability to interact with the hardware down to the bare silicon.
Embedded apps require that it just works 24/7 and without the memory and processing power of a PC, so it has to be efficient in whatever it does. If it does not do it you can't upgrade "the PC" and your product fails. Tachyon is there to make the supplier and the customer happy, not the standards people poking keys on their PCs.
The inventor of Forth writes his own standards, he does what needs to be done, which is also how Forth was invented. Forth will never be a language for the unwashed masses or education that requires strong typing and syntax to teach and grade. Those who grok it will use it. New processor architectures, new Forths! I started out primarily from a hardware background and so I really appreciate the ability to interact with the hardware down to the bare silicon.
Re: New here, but not to Forth or the 6502s
GARTHWILSON wrote:
The C crowd's insistence on conforming to C standards seems to be a barrier to getting better C performance for the 6502. On another 6502 forum, I have suggested certain improvements, and the answer I get is that "the standards don't allow that." My answer is, "So??"
Unfortunately for architectures like the 6502, C-style stack-based languages are not very efficient.
Re: New here, but not to Forth or the 6502s
pbj wrote:
Forth is the ugly word on other forums whereas on a Forth forum it is "standards" believe it or not!
Quote:
So I just say yeah, standards are great .... for the majority of tasks on the majority of larger systems such as PCs. After all, the standards are PC centric yet the embedded world has its own demands and constraints, and the standards would only hobble a Forth embedded system, making it effectively unusable.
Re: New here, but not to Forth or the 6502s
JimBoyd wrote:
I assume the temporary code is compiled somewhere other than the dictionary. That would be handy for building tables, or other structures, without defining support words.
Code: Select all
CREATE SOMETABLE
HEX
10 0 DO I C, LOOP
I've since realized another way to build that table using evaluate and modifying >IN .
Code: Select all
0 " DUP C, 1+ DUP 10 = >IN !" COUNT EVALUATE DROP
Note: In Fleet Forth, any value of >IN greater than, or equal to, the size of the text source will end interpretation, or in this case, string evaluation.
the Forth word " (quote) either compiles a string into a colon definition or, if interpreting, stores the string in PAD and returns the address of PAD.
Re: New here, but not to Forth or the 6502s
Sorry. I got intent on a complex problem. The previous version can only build a table of about eighty bytes before WORD's work area at HERE collides with the string that used to be at PAD. Your mileage may vary.
Here is a better version of how to fill a table.
Code: Select all
CREATE SOMETABLE
B/BUF 2* ALLOT
: FILL.TABLE
B/BUF 0
DO
I DUP 2* SOMETABLE + !
LOOP ;
FILL.TABLE
FORGET FILL.TABLE
Or for the Ansi crowd.
Code: Select all
CREATE SOMETABLE
B/BUF 2* ALLOT
MARKER FORGET.ME
: FILL.TABLE
B/BUF 0
DO
I DUP 2* SOMETABLE + !
LOOP ;
FILL.TABLE
FORGET.ME