6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 01, 2024 3:41 am

All times are UTC




Post new topic Reply to topic  [ 36 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Wed Oct 10, 2018 5:34 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
I'm currently working on adding the Forth 2012 optional BLOCK word set to Tali Forth 2. I'm trying to determine if this can be done with a single 1K buffer, or if I need a second 1K buffer for interpreting during a LOAD. GForth seems to use a separate interpretation buffer, but my reading of the 2012 Forth standard makes me think I can get away with a single buffer.

Section 7.3.2 seems to list all of the things that might make a given buffer invalid. Because parsing and many of the block words are in the list, that seems to me to indicate that you can't use block words in a block. You can compile them into a new word definition, but you can't run them, with the exceptions of LOAD and THRU. Am I reading that correctly? I couldn't find it explicitly stated anywhere.

I understand that I will need to save the current input state at the beginning of LOAD and restore it (including calling BLOCK to bring the block back into the buffer if the original source was a block) once LOAD is done.

Has anyone else implemented this with only a single buffer, or am I missing something that would preclude using only a single buffer?


Top
 Profile  
Reply with quote  
PostPosted: Wed Oct 10, 2018 8:50 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
I think you'd want at least 2 buffers, simply to facilitate copying BLOCKs easily. You can always do it with external memory (i.e. memory managed by the application, rather than the system), but I think having at least 2 would be worthwhile.

With 2 buffers available, to copy a block you'd do something like:
Code:
: COPY-BLOCK ( from-block to-block )
    BUFFER           \ Get the buffer for to-block
    UPDATE           \ Mark it as dirty
    SWAP BLOCK       \ load from-block
    SWAP 1024 MOVE ; \ Copy data, data will be save when the buffer is flushed

With 1 buffer, that won't work.

You know what? This is really ambiguous.

The reason this is ambiguous, as written, is that it's possible for the system, to flush the updated buffer when BLOCK is called, and thus the buffer will not be marked as dirty after the copy.

This is better:
Code:
: COPY-BLOCK ( from-block to-block )
    SWAP BLOCK  \ Read in the source block
    SWAP BUFFER \ designate the buffer
    UPDATE      \ mark it as dirty
    1024 MOVE ; \ copy the data, data is saved when the buffer is flushed

This is more straightforward, and, interestingly, if you have a single buffer, this just may work. I don't know how MOVE is defined when the source and destination addressed are the same (it should just NOP).

You also need to make sure that BLOCK and BUFFER aren't aliased. Some systems have BUFFER simply call BLOCK.

The stock FIG Forth has 8 buffers, but they're only 128 bytes each.

As for the invalidation, I honestly don't know why terminal I/O should invalidate a buffer, unless there's some underlying redirection mechanism going on that could direct EMIT to a buffer. But, as I understand it, the only place that really happens is when the compiler is switched up between using the terminal buffer for input vs a block for input, and that's only for reading.

Ah, here it is:
Quote:
While the standard does not address multitasking per se, the items listed in 7.3.2 Block buffer regions that may render block-buffer addresses invalid are due to multitasking considerations.

The basic point is not that these words can corrupt a buffer, but rather these words are notable for allowing task switching (which can do anything).

So, that makes sense.

Anyway, I think you need "more than one" buffer, the system kind of breaks down if you don't have at least 2.

Playing 8 puzzle with one square isn't fun.


Top
 Profile  
Reply with quote  
PostPosted: Wed Oct 10, 2018 9:56 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 894
whartung wrote:
Code:
: COPY-BLOCK ( from-block to-block )
    SWAP BLOCK  \ Read in the source block
    SWAP BUFFER \ designate the buffer
    UPDATE      \ mark it as dirty
    1024 MOVE ; \ copy the data, data is saved when the buffer is flushed

This is more straightforward, and, interestingly, if you have a single buffer, this just may work. I don't know how MOVE is defined when the source and destination addressed are the same (it should just NOP).

Even if it doesn't NOP when the source and destination are the same, reading a memory location and writing the data back to the same location shouldn't be a problem.
Quote:
You also need to make sure that BLOCK and BUFFER aren't aliased. Some systems have BUFFER simply call BLOCK.

Definitely. For COPY to work with only one block buffer, BUFFER must never read from mass storage.
Quote:
The stock FIG Forth has 8 buffers, but they're only 128 bytes each.

The Forth-83 Standard specifies 1024 byte block buffers.
Quote:
As for the invalidation, I honestly don't know why terminal I/O should invalidate a buffer, unless there's some underlying redirection mechanism going on that could direct EMIT to a buffer. But, as I understand it, the only place that really happens is when the compiler is switched up between using the terminal buffer for input vs a block for input, and that's only for reading.

Ah, here it is:
Quote:
While the standard does not address multitasking per se, the items listed in 7.3.2 Block buffer regions that may render block-buffer addresses invalid are due to multitasking considerations.

The basic point is not that these words can corrupt a buffer, but rather these words are notable for allowing task switching (which can do anything).

So, that makes sense.

If the only tasks on your system are background tasks, task switching shouldn't be a problem. It's when a Forth system has more than one 'user task' where a block could be requested since any use of BLOCK or BUFFER can invalidate a buffer address returned by a prior use of BLOCK or BUFFER.
Quote:
Anyway, I think you need "more than one" buffer, the system kind of breaks down if you don't have at least 2.

Playing 8 puzzle with one square isn't fun.

A good idea. My system is a Forth-83 Standard system and normally has 4 buffers. They reside at the top of free RAM and the number of buffers can be changed while the system is running with:
Code:
n IS #BUF CONFIGURE

Where n is the number of block buffers desired.
If Tali Forth 2 doesn't support more that one user task ( only one person at a time running your hardware, only the 'main' task accessing blocks ) then you should be able to get by with one block buffer, but it might be prudent to implement your block support so the number of block buffers can be user configurable.


Top
 Profile  
Reply with quote  
PostPosted: Wed Oct 10, 2018 10:16 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
JimBoyd wrote:
whartung wrote:
The stock FIG Forth has 8 buffers, but they're only 128 bytes each.

The Forth-83 Standard specifies 1024 byte block buffers.

Quote:
A good idea. My system is a Forth-83 Standard system and normally has 4 buffers.

I simply mentioned the FIG numbers to potentially disassociate the size of buffers, from the size of Forth SCREENs.

With a 1K buffer, a buffer and screen are the same size (the Forth standard linked to above I think makes no mention of SCREENs, and may simply combine buffers and SCREENs).

With 8 128 buffers, the classic Fig system had half as much buffer memory as your system does with 4 buffers.

4K of buffer memory is kind of a lot on a 64K system. I mean, I guess, everything is a trade off, right?


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 11, 2018 12:54 am 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
Thank you, JimBoyd and whartung, for your thoughts. I was trying to use as little memory as possible, but I do agree that it makes sense to have at least 2 buffers. I'm trying to write to the Forth 2012 standard, so my buffers have to be 1024 bytes just like the blocks. Indeed, one screen is exactly 1 block and fits in exactly 1 buffer in that version. It makes things simpler for screens/blocks/buffers to all be the same size.

For my own personal use, I will likely only be using blocks to store forth code that can be LOADed at a later date. I'm hoping others who build their own 65C02 computers might consider using Tali Forth 2 instead of FIG Forth, so I'm also trying to write things more generically. In that vein, I think 2 buffers probably makes the most sense as a reasonable minimum.


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 9:09 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 894
whartung wrote:
With 8 128 buffers, the classic Fig system had half as much buffer memory as your system does with 4 buffers.

Wouldn't that be a quarter as much?
Quote:
4K of buffer memory is kind of a lot on a 64K system. I mean, I guess, everything is a trade off, right?

But my buffers reside at the top of RAM. I can change the number of buffers on the fly. If I need more memory I can type:
Code:
FLUSH
1 IS #BUF  CONFIGURE

This leaves me with one buffer and frees the memory used by three of the buffers. I just have to remember to flush the buffers to disk first.
I can also increase the number of buffers for some block manipulations that would benefit from more buffers, then reduce the number of buffers.
Code:
// Check the amount of free RAM.
FREE D.
// got enough for ten more buffers? Great!
FLUSH
DECIMAL 14 IS #BUF CONFIGURE
// Do block buffer intensive stuff like moving a group of blocks past another group of blocks.
// Then reclaim memory.
// Always remember to flush!
FLUSH 4 IS #BUF CONFIGURE
// 10K of RAM just reclaimed


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 9:15 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 894
SamCoVT wrote:
For my own personal use, I will likely only be using blocks to store forth code that can be LOADed at a later date. I'm hoping others who build their own 65C02 computers might consider using Tali Forth 2 instead of FIG Forth, so I'm also trying to write things more generically.

Why do some people assume that if a Forth isn't ANSI Forth, it is FIG Forth?
My Forth for the Commodore 64 is a Forth-83 Standard Forth.


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 9:26 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8534
Location: Southern California
I think the assumption, and probably correct, is that most people who get a Forth running on a 6502 start with the free and widely available FIG Forth source.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 9:58 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 894
GARTHWILSON wrote:
I think the assumption, and probably correct, is that most people who get a Forth running on a 6502 start with the free and widely available FIG Forth source.

I hadn't thought of that.
Back in the mid 90's I had two assemblers, the one that came with the Forth I was using and a primitive assembler I wrote in BASIC. Neither was suitable for writing an application from an assembly listing so when I first wrote my Forth for the C64 I went with metacompilation.


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 10:23 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
Fig Forth is pretty well documented, tops googles "6502 forth" results, and has a very simple assembly file, requiring little more than .ORG and .DS along with the opcode. No macros, no nothing.

I wrote my own assembler to assemble my copy.

Forth 83 is popular on the PC because of the ready availability of F83. The PC has a plethora of choices.

I still dabble with trying to port F83 to the 6502. If I can do that, then I can port it to the 65816. There was an Apple II port of F83, but I can't find any remnants of it.

I don't know of any public 65816 Forths running around out in the wild.


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 10:35 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 894
Back in the mid 90's, I didn't have internet. When did it start?
I didn't have a PC. The Commodore 64 was my computer. I found the 64Forth cartridge for the C64 in a used computer store back in 1991. That got me started in Forth. Later, I downloaded Blazin' Forth from a Commodore 64 Bulletin Board Service. Blazin' Forth was a Forth-83 Standard Forth.


Last edited by JimBoyd on Wed Jan 31, 2024 12:06 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 10:40 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 894
SamCoVT wrote:
I'm hoping others who build their own 65C02 computers might consider using Tali Forth 2 instead of FIG Forth

Under what license is Tali Forth 2 released?


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 12, 2018 11:12 pm 
Offline

Joined: Sun Jul 28, 2013 12:59 am
Posts: 235
Some time ago, I noticed that the ANSI Forth specification (or, well, the easily-available draft version) didn't appear to require an implementation have any valid block numbers, and if there are no valid block numbers then the implementation becomes trivial, which also means not having any block buffers.

I filed this concept in the category of "silly options for full conformance to the specification for the file-access word set."


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 13, 2018 8:33 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
JimBoyd wrote:
Code:
// Check the amount of free RAM.
FREE D.
// got enough for ten more buffers? Great!
FLUSH
DECIMAL 14 IS #BUF CONFIGURE
// Do block buffer intensive stuff like moving a group of blocks past another group of blocks.
// Then reclaim memory.
// Always remember to flush!
FLUSH 4 IS #BUF CONFIGURE
// 10K of RAM just reclaimed

That's pretty neat, JimBoyd. I don't think I want anything that complicated. I'm currently looking for the minimum required to edit screens and then load them later. I have it all working with one buffer now, but will probably go with more. It's nice and easy with just one, because there's only one to check!


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 13, 2018 8:48 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
JimBoyd wrote:
SamCoVT wrote:
For my own personal use, I will likely only be using blocks to store forth code that can be LOADed at a later date. I'm hoping others who build their own 65C02 computers might consider using Tali Forth 2 instead of FIG Forth, so I'm also trying to write things more generically.

Why do some people assume that if a Forth isn't ANSI Forth, it is FIG Forth?
My Forth for the Commodore 64 is a Forth-83 Standard Forth.


I'm aware that there are many forths for C64 and Atari computers, but Tali Forth 2 is not tied to a particular hardware. There are character input and output routines that you write, and off you go! It can be run in the py65mon emulator using the binary on GitHub, but I run it on my own single board computer (65C02 running at 4MHz with 32K ROM and 32K RAM and 65C22 and 65C51 ICs for I/O). I'm working on adding block support for a 128K I2C flash chip that I have.

I suppose the target audience would be people building their own 65C02 computers who want something more powerful or low-level than BASIC, but something more modern than FIG Forth. I found Tali Forth 2 after trying ehBASIC and FIG Forth on my machine, and I liked it enough that I'm now working to contribute to the project.

To answer your other question, Tali Forth 2 is released in the public domain.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 36 posts ]  Go to page 1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: