Page 1 of 5
Help on fig-FORTH 1.0 Bring Up
Posted: Tue Dec 09, 2014 4:34 am
by MichaelM
Looking for some help in bringing up fig-FORTH on my M65C02A core. Think that I've got the latest code base from the repository. Have modified it to connect to the I/O routines in the monitor, and removed the jsr trace and jsr tcolon calls. Display the prompt, but after that it just seems to hang.
Any suggestions in debugging this would be appreciated. I am a complete newbie with FORTH and don't have anything to go on in trying the determine what may be awry with the current program. The embedded trace seems to go South, so I read through the listing and used the monitor to patch the two calls noted above.
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Tue Dec 09, 2014 5:18 am
by barrym95838
It seems that enso was able to post at least the binary of a version to run cleanly on his chochi
here, but it looks like you were present in that thread as well, so I may be just blowing smoke up your you-know-what by mentioning it.
Mike
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Tue Dec 09, 2014 5:53 am
by GARTHWILSON
If it displayed the prompt, that's a lot. It shows most of the basic stuff is working. When I was getting mine going, I just took a lot of iterations of putting software probes in at various places to see if it got there before crashing, and to see what was in various registers and variables at that point. It's tedious but you get there. When you get to where it can interpret and compile, you'll have the interactiveness to debug stuff much more easily. Good luck.
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Tue Dec 09, 2014 4:10 pm
by Brad R
If it displayed the prompt, that's a lot. It shows most of the basic stuff is working.
Indeed! At that point you have character output, a few stack and arithmetic operations, and a looping or branching operation working. I think the next thing I'd check is if character input (KEY and ?TERMINAL) works correctly.
When I am bringing up Forth on a new CPU, my first test is to output a character
in assembly language at the end of the reset initialization code. That verifies that the processor is running and that I have configured at least some of the I/O correctly. My second test is to write an assembly language loop that reads a character, modifies it (usually by adding one), and outputs that modified character.
Next I test the Forth threading mechanism and basic control structures, by having the reset code launch this Forth thread:
BEGIN KEY 1+ EMIT AGAIN . That verifies that Forth threading is working, character I/O is working, the stack is working (since it's used to pass and modify the character), and the unconditional branch is working.
At that point I usually write some very simple words to output hex numbers -- not using Forth's "." which requires a lot of primitives to be working -- so I can display diagnostic output. And I start working my way through COLD to see where it fails.
Given that your system has already reached the startup prompt, I think I'd instrument the word QUERY to make sure it is receiving and correctly storing characters. If QUERY correctly returns a line of text, the next word to investigate is probably INTERPRET (I may be misremembering the actual fig-Forth word name here). For example, you can verify that it correctly parses a word of text, and correctly finds that word in the dictionary. (Problems with FIND are not uncommon.)
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Tue Dec 09, 2014 8:48 pm
by MichaelM
Thanks all for your responses. Will take your recommendations and observations and make an attempt to move past the point where I found myself late last night. If I don't have any success, will attempt to capture some of the built in trace and post that later to see if anyone has any additional suggestions.
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Wed Dec 10, 2014 4:20 am
by MichaelM
I made a change to one of the built-in trace functions to mask off the msb when using putch to print the ASCII character word name. That cleaned up the trace into an intelligible display. I did remove an extra space in the sign on message, but did not adjust the length so the IP got out of synch and it crashed. I patched it to the correct length, and it continued past the printing of the sign on message.
It appears to be crashing in INTERPRET in the word -FIND.
Looking at the code, and looking for a clue.
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Wed Dec 10, 2014 1:42 pm
by Brad R
Random thoughts: check that the user variables CURRENT and CONTEXT are correctly initialized. And make sure that the first word in the Forth dictionary has a zero link (to terminate the linked list).
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Wed Dec 10, 2014 3:41 pm
by MichaelM
Brad:
Thanks for the additional hint. Will pursue this tack later tonight. What would you consider the correct initialization for these two variables?
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Wed Dec 10, 2014 4:00 pm
by Brad R
Ack. I'd have to dig out my fig-Forth books to answer that. If I recall correctly, each one should point somewhere in the data field of a VOCABULARY word, which in turn holds a link to the last (most recent) word in that particular dictionary chain. But my memory on this is weak.
A useful, if voluminous, diagnostic: -FIND compares the parsed text string with the name field of a word in the dictionary. One thing to do is, inside the loop, print the name field address of each word before it is compared. You should see a string of addresses running down to the first word in the dictionary. If it keeps going after that, you don't have a properly null-terminated list. If it just goes all over the map, you probably have an invalid CONTEXT or CURRENT. -FIND will keep following dictionary links forever until it encounters a zero link, or finds a matching word name.
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Wed Dec 10, 2014 4:41 pm
by Dr Jefyll
inside the loop, print the name field address of each word before it is compared
With FIG Forth,
-FIND calls
(FIND) -- that's the actual search loop. As Brad suggests, get inside the loop -- let it run 3 or 4 iterations
then stop it to see what it's doing. It should be following the link chain backwards through the dictionary -- ie,
MON ->
VLIST ->
TRIAD ->
INDEX ->
LIST ->
? ->
. ->
.R etc.
Check also that the example string -- what the loop is comparing each successive dictionary name with -- is correctly located at the address provided.
-- Jeff
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Wed Dec 10, 2014 6:43 pm
by MichaelM
Brad/Jeff:
If I remember correctly, in -FIND, first word executed was BL which is followed by :WORD. It is at this point that the VM crashes and returns to the SBC2 OS Lite monitor. Funny thing is that the SBC2 OS Lite monitor prints out the registers and PC is shown to be 0x0000.
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Sat Dec 13, 2014 1:17 am
by MichaelM
I've been working with the fig-FORTH source from the archives. In my limited experience with it, I would have to say that something is not quite right with the source.
For example, I could not find where X was initialized any where before the first call. Next, several constants in the initialization code just did not appear to be right. The number of elements in the initialization data were more than the value loaded into Y for transferring the block from program memory to the user area.
Thus, I have made a few changes to the initialization code:
Code: Select all
;
; equates giving memory assignments, machine
; registers, and disk parameters.
;
ssize =128 ; sector size in bytes
nbuf =8 ; number of buffers desired in ram
; (ssize*nbuf >= 1024 bytes)
sectr =800 ; sector per drive
; forcing high drive to zero
sectl =1600 ; sector limit for two drives
; of 800 per drive.
bmag =(ssize+4)*nbuf ; total buffer magnitude, in bytes
; expressed by (ssize+4)*nbuf
;
bos =$48 ; bottom of data stack, in zero-page.
tos =$B6 ; top of data stack, in zero-page.
n =tos+8 ; scratch workspace.
ip =n+8 ; interpretive pointer.
w =ip+3 ; code field pointer.
up =w+2 ; user area pointer.
xsave =up+2 ; temporary for x register.
;
tibx =$3F00 ; terminal input buffer of 84 bytes.
orig =$0400 ; origin of forth's dictionary.
mem =$3F00 ; top of assigned memory+1 byte.
uarea =mem-128 ; 128 bytes of user area
darea =uarea-bmag ; disk buffer space.
;
BACKSPACE =$08 ; backspace character (Default: $7F)
;
; monitor calls for terminal support
;
putch =$f82d ; output one ascii char. to term.
getch =$f818 ; input one ascii char. to term.
putcrlf =$f8a2 ; terminal return and line feed.
;
; monitor routines needed to trace.
;
putblank =$f8d5 ; print one blank
puthex2 =$f8b3 ; print accum as two hex numbers
;
getkey =$f8e8 ; wait for keystroke, no data returned
;
xw =$40 ; scratch reg. to next code field add
np =$42 ; scratch reg. pointing to name field
;
;
;
; from darea downward to the top of the dictionary is free
; space where the user's applications are compiled.
;
; boot up parameters. this area provides jump vectors
; to boot up code, and parameters describing the system.
;
code
ds orig+2
;
; user cold entry point
enter nop ; vector to cold entry
jmp (cold) ;
reentr nop ; user warm entry point
jmp warm ; vector to warm entry
initblk dw $0004 ; 6502 in radix-36
dw $5ed2 ;
dw ntop ; name address of mon
dw BACKSPACE ; backspace character
up_init dw uarea ; initial user area
psp_ini dw tos ; initial top of stack
rsp_ini dw $1ff ; initial top of return stack
dw tibx ; initial terminal input buffer
;
dw 31 ; initial name field width
dw 0 ; 0=nod disk, 1=disk
dw top ; initial fence address
dw top ; initial top of dictionary
dw vl0 ; initial vocabulary link ptr.
initend =*
initlen =initend-initblk-1 ;; Added symbolic constants, mam, 14L12
rsp_off =rsp_ini-initblk
psp_off =psp_ini-initblk
I labeled some of the elements of the initialization data block and created a few additional labels for offsets and initialization block length. I also applied a couple of mods to the COLD start word.
Code: Select all
;
; cold
; screen 55 line 1
;
L2423 db $84,'COL',$c4
dw L2406 ; Link to abort
cold dw *+2
lda initblk ; from cold start area, added constant
sta forth+6
lda initblk+1 ;; added constant, mam, 14L12
sta forth+7
ldy #initlen ;; added constant, mam, 14L12
bne L2433
warm ldy #initlen-6 ;; added constant, mam, 14L12
L2433 ldx psp_ini ;; added to initialize parameter SP
stx xsave ;; mam, 14L12
lda up_init ;; added reference to label, mam, 14L12
sta up
lda up_init+1 ;; added reference to label, mam, 14L12
sta up+1
L2437 lda initblk,y ;; added label to initialize data block
sta (up),y
dey
bpl L2437
lda #hi abort ; actuaLLy #>(abort+2)
sta ip+1
lda #lo abort+2
sta ip
cld
lda #$6c
sta w-1
jmp (rpsto) ; and off we go !
;; changed to jmp (abs), mam, 14L12
At label L2433, I placed two instructions to initialize the parameter/data stack pointer X and the xsave zero page location. I also incorporated some symbolic labels to remove some of the magic numbers that seemed to have been incorrect. I also changed the jmp rpsto+2 instruction to jmp (rpsto) just to see if still worked. This change should be backed out if running with a 6502 processor or FPGA core. I also changed RP!, rpsto, by making the offset to the rsp initialization value a symbolic constant instead of the magic number 8 which was not correct for the given initialization data block I found in the source.
Code: Select all
;
; rp!
; screen 26 line 8
;
L522 db $83,'RP',$a1
dw L511 ; link to sp!
rpsto dw *+2
stx xsave ; load return stack pointer (machine
ldy #rsp_off ; stack pointer) from silent user
lda (up),y ; variable r0
tax
txs
ldx xsave
jmp next
With the preceding changes I can now get to a prompt and get the ? when I enter a CR. The following is a capture of the terminal session:
Code: Select all
65C02 Monitor Lite v5.1.5 (7-Dec-14) Ready
>0402G
fig-FORTH 1.0a
?
?
65C02 Monitor Lite v5.1.5 (7-Dec-14) Ready
>0000.01FF
0000 - 00 00 B6 00 06 01 B6 00 - 00 00 20 20 20 20 20 20
0010 - 20 20 20 20 20 20 20 20 - 20 20 20 20 20 20 20 20
0020 - 20 20 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0030 - 00 0A 3E 01 17 FC 00 01 - 00 00 3A 00 FF 01 00 00
0040 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0050 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0060 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0070 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0080 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0090 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
00A0 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
00B0 - 00 00 00 00 00 00 00 00 - 00 20 00 00 00 04 00 00
00C0 - 00 00 40 40 2C 00 63 0F - 6C E3 06 80 3E 06 00 00
00D0 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
00E0 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
00F0 - 00 00 00 00 00 00 00 00 - F9 11 FA 11 FA 11 00 00
0100 - 22 18 F8 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0110 - 00 00 00 00 30 BA 42 BA - F8 20 72 FA AE F9 0A 00
0120 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0130 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0140 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0150 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0160 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0170 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0180 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0190 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
01A0 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
01B0 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
01C0 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
01D0 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
01E0 - 00 00 00 00 00 00 00 00 - 00 00 00 20 21 18 FE 11
01F0 - FE A4 0E 14 10 12 2B 18 - B6 00 06 01 D1 0F 14 14
>
In locations 0100:0102 is a feature of the M65C02A core which writes to these locations the PSW, PCL, and PCH when Reset is applied to the core. In the case provided above, the core was reset while polling the getch() of the monitor.
I will try further tests later using Brad's suggested test sequence. Would be interested in any additional suggested Forth console tests.
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Sat Dec 13, 2014 12:35 pm
by Brad R
Once you have it accepting console input, the first three tests are:
1. empty line (which you have done)
2. single Forth word (such as DUP)
3. a number (such as 5)
The fact that empty line is returning "?" suggests a problem within INTERPRET and its termination condition. I vaguely recall that fig-Forth requires a null character to be appended to the input line. (I really need to dig out my fig-Forth references.) One thing to try is something like 50 EMIT <CR> (with a space before the <CR>). If it prints "2 ?" then it's parsing words from the text ok, but failing at end-of-line.
If empty line works ok, and numbers work ok but finding a Forth word does not, the most likely problem is the dictionary search (perhaps the name comparison routine, or a problem with your Forth word headers). If you can find a Forth word, but a number fails, the most likely problem is in the number conversion word (perhaps named CONVERT).
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Sun Dec 14, 2014 3:39 pm
by Martin_H
This conversation inspired me to try FigForth. I've downloaded the source and with a few tweaks got it assembling under Tass. One thought occurred to me though.
If I put this in the ROM how does the FORTH dictionary access RAM? Or does FigForth need to be in RAM to allow the dictionary the source defines to expand into RAM as new words are defined?
Re: Help on fig-FORTH 1.0 Bring Up
Posted: Sun Dec 14, 2014 4:24 pm
by scotws
If I put this in the ROM how does the FORTH dictionary access RAM? Or does FigForth need to be in RAM to allow the dictionary the source defines to expand into RAM as new words are defined?
Right. Forth has a pointer to the last entry in the Dictionary, which is in ROM when you start out. When you define a new word, it is placed in RAM, with the pointer to that entry -- at this point, the Dictionary crosses the RAM/ROM border. Then, Forth remembers where the new last entry lives, so the next word gets chained to that.
Just remember that fig Forth is an ancient dialect by now -- befitting a 6502 machine, if you will, but a lot of the modern examples will not work.