View unanswered posts | View active topics It is currently Thu Mar 28, 2024 3:27 pm



Reply to topic  [ 138 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9, 10  Next
 FISA64 - 
Author Message

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
Got FMTK closer to running simple task switching. Running in the emulator the system is able to handle interrupts. however in real life it hangs. Got past missing startup tasks by fixing a couple of bugs in the compiler.
I found a way to get a decent screen refresh so the emulator runs fairly fast I'm not sure how it compares to the FPGA version, it looks about the same speed. The FPGA version runs at 16.667MHz.
Attachment:
File comment: FMTK in Emulator
FISA645.gif
FISA645.gif [ 35.79 KiB | Viewed 8318 times ]

_________________
Robert Finch http://www.finitron.ca


Thu Apr 16, 2015 12:07 pm
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
I scrapped the bounds registers that were added to FISA64 in favour of a simpler check instruction that uses only general purpose registers. I came up with a way of using the check instruction from 'C' source code by defining a "__check()" keyword. The check keyword takes a range bounding expression and converts it into a single 'chk' instruction. Usually it's an index into an array and lower bound is zero, and upper bound some integer constant. The chk instruction generates a bounds violation exception if the bounds have been exceeded, otherwise it's a nop operation.
At the moment the project is stuck on interrupt handling. The system seems to do recurring interrupts (timer driven) but it doesn't return to the monitor task. It loops around between processing another task and processing interrupts. It is supposed to sometimes run different tasks in other words the monitor.

_________________
Robert Finch http://www.finitron.ca


Sat Apr 18, 2015 7:56 am
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
The keyboard routines for the project have been updated with a 'C' language portion which is interrupt driven and buffers characters to whichever job has the input / output focus. It adds a new layer of complexity. Previously, the keyboard was directly accessed in a relatively simple fashion and was global in operation. The next step might be to implement the keyboard in a device driver fashion. It took some doing to get the emulation of the keyboard in the emulator good enough to do debugging. The emulator has more features to it now, and has been almost as much fun to play with as the real FPGA version.
Each job has a keyboard buffer from which it fetches keystrokes. The interrupt routine places the keystrokes directly into the jobs keyboard buffer. I suppose it acts like a custom dedicated message queue. It's unlike the Windows system which sends messages to window procedures for keystroke processing. The KeybdGetBufferedChar() routine returns the ascii equivalent of the scancode from the keyboard buffer.

I added an option to the 'C' compiler to produced mixed source code as comments in the assembler output. It's interesting to see what output the compiler generated for a given line of code. Hopefully it will make figuring out bugs in the compiler a little easier. I found one bug in the optimizer that causes zero extensions of values to be removed from the optimized code when it's not supposed to be. Since it's not a simple fix, I just inserted a typecast into 'C' code in the one location where it mattered which resolved the problem.

_________________
Robert Finch http://www.finitron.ca


Mon Apr 20, 2015 9:51 am
Profile WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
Good plan: Acorn's BBC Micro uses an interrupt to put keystrokes into an input buffer, and it really helps with typeahead and responsiveness. I suspect you need something to make sure an attention keypress (whether ^C or ESC) gets to the head of the buffer... or is somehow flagged to the application.


Mon Apr 20, 2015 10:03 am
Profile

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
Quote:
I suspect you need something to make sure an attention keypress (whether ^C or ESC) gets to the head of the buffer... or is somehow flagged to the application.

I hadn't thought of that yet. CTRL-C should probably abort the application. The CTRL-C could feed into the catch handler of the routine that is currently running, or rather the catch handling routine of the job/task with the I/O focus. In theory the stack would then be walked backwards until a CTRL-C handler is found, or if not found, the app would end up being aborted. I should probably allocate a few signalling type exceptions as standard exceptions. I have not yet tested the compiler's try-catch mechanism so opportunity abounds. The compiler uses a type numbering scheme to identify types. This is checked by catch handlers, so a CTRL-C would have to be some kind of type. The console output routines (printf()) should also probably check for a pause key. So much work to do, so many things to play with.
I really need to come up with some small apps to test the multi-tasking with. Right now there's just tasking between the IdleTask and the system monitor, which at the moment works.

_________________
Robert Finch http://www.finitron.ca


Mon Apr 20, 2015 11:42 pm
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
The following shows a CTRL-C handler in the IdleTask. When CTRL-C is pressed the message is displayed. :) The compiler stores the catch handler chain address in register 28 (the XLR). The value to assign the catch variable is stored in reg 1, the type of the value is stored in reg2. All that was needed to make the catch handler catch CTRL-C was to load the register image in the task's control block appropriately. Then the next time the task control block was restored (the next time the task is activated by the scheduler), the catch handler was invoked.
The CTRL-C exception is passed to all the tasks associated with a job (max of 8), so that all the tasks know to abort.

Code:
void IdleTask()
{
     int ii;
     __int32 *screen = (__int32 *)0xFFD00000;

     forever {
         try {
             ii++;
             if (getCPU()==0)
                 screen[57] = ii;
         }
         catch(static __exception ex=0) {
             if (ex==515) {
                 printf("IdleTask: CTRL-C pressed.\r\n");
             }
             else
                 throw ex;
         }
     }
}



The following bit of code is in the scheduler interrupt. It sets up the register image for a return to the catch handler and not the pre-empt code.
Code:
     // If an exception was flagged (eg CTRL-C) return to the catch handler
     // not the interrupted code.
     t = GetRunningTCBPtr();
     if (t->exception) {
         t->iregs[31] = t->iregs[28];   // set link register to catch handler
         t->iipc = t->iregs[28];        // and the PC register
         t->iregs[1] = t->exception;    // r1 = exception value
         t->exception = 0;
         t->iregs[2] = 24;              // r2 = exception type
     }

_________________
Robert Finch http://www.finitron.ca


Tue Apr 21, 2015 5:25 am
Profile WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
You remind me, if I remember correctly, that on DEC's VMS ^T caused the display of a line of status about the currently running task. That was quite a nice feature. In Unix, at least with a suitable shell, we have ^Z to stop (suspend) a process, which allows it to be restarted, killed or put into the background.

But the ability to interrupt or kill the current process is a good start!


Tue Apr 21, 2015 8:31 am
Profile

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
Quote:
^T caused the display of a line of status about the currently running task. That was quite a nice feature. In Unix, at least with a suitable shell, we have ^Z to stop (suspend) a process,

I know a way to do it, perhaps not the best way as if the program crashes one is out of luck. The compiler outputs a hidden default catch handler (provided exception handling is on which is the default) for every function. Code to trap for ^z or ^t could be placed in the default catch handler of the most outermost block of the program. (It would be too much to place it in every catch handler). Doing so would require a means to identify the most outermost block of a program so a new keyword could be added to do this. I'm thinking "__task".
FMTK uses exception codes 512 to 537 to represent control chars pressed on the keyboard. The first 512 codes are reserved to represent the processor interrupts. So for instance a bounds exception interrupt (487) could be passed to an exception handler for the running task. It's really a primitive signalling system. I should research how signal() works again.
Now to mutate the bootrom's monitor program into an operating system shell.

_________________
Robert Finch http://www.finitron.ca


Tue Apr 21, 2015 4:43 pm
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
Modified the compiler today to output global and static variable addresses as an offset from the global pointer register rather than as absolute addresses. Then rebuilt the whole system and got it working again. This is in preparation for loading and running programs at addresses known only at load time. The global pointer register acts a bit like the stack base pointer register, except for global variables. Data may now be repositioned anywhere in memory relatively easily. The offsets to the variable addresses remain the same while the global pointer may change from one instance of a program to another.

Also got a start at a shell. At the moment it only supports one command: the kill task command. There isn't much the system can do until other programs can be loaded. That means some sort of interface to external files is needed. I've been trying to get an SD card interface going but without any luck.

_________________
Robert Finch http://www.finitron.ca


Wed Apr 22, 2015 4:41 am
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
In 17 thousand lines of code the only set instruction that was used was a SEQ which got used only three times. I expected the compiler to be able use the set instructions more often. I guess not. So the set instructions are going to be dropped from the design. Also, looking at the design, the constant building opcode could be improved. There is room in the instruction set to capture more constant bits if the constant building instruction (IMM prefix) is spread out over several instructions. This would allow encoding some larger constants into fewer instructions. Currently up to 40 bits can be encoded with a single constant prefix when combined with the following instruction. This would change to 43 bits (three additional bits). Since it really only matters when referencing enormous data structures over 40 bits in size, i'm not sure I'll bother changing it now.

_________________
Robert Finch http://www.finitron.ca


Wed Apr 22, 2015 3:03 pm
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
After having dropped the SET instructions, floating point ops were added. Floating point cores supplied by the FPGA vendor were used, and integrated into the core. The assembler, compiler, and emulator all had to be modified to support floating point. Currently floating point is being tested in the emulator. There is a separate bank of 32, 64 bit floating point registers in the FISA64 ISA. Floating point standard used is IEEE754 compatible with a few exceptions.
An early sample test routine is shown below with the associated generated FP assembly code.
Code:
int test(double a, double b)
{
    double c;
    int d,e;

    if (a < b)
        return -1;
    else if (a==b)
        return 0;
    else
        return 1;
    c = e - a * b + d;
}


Code:
                      code
                      align   16                   
                   public code test_:
000000 15 EF 21 00                subui   sp,sp,#16
000004 E7 ED 01 00                push    bp
000008 02 BF 01 1A                mov     bp,sp
00000C 15 EF 31 00                subui   sp,sp,#24
000010 D1 3D 30 00                lfd     fp3,24[bp]
000014 D1 4D 40 00                lfd     fp4,32[bp]
000018 AA 31 08 02                fcmp    r3,fp3,fp4
00001C BD 31 0A 00                bge     r3,test_2
000020 0A 10 FE FF                ldi     r1,#-1
                   test_4:
000024 82 ED 01 1A                mov     sp,bp
000028 57 BF 11 00                pop     bp
00002C 37 FF 21 00                rtl     #16
                   test_2:
000030 D1 3D 30 00                lfd     fp3,24[bp]
000034 D1 4D 40 00                lfd     fp4,32[bp]
000038 AA 31 08 02                fcmp    r3,fp3,fp4
00003C BD 11 06 00                bne     r3,test_5
000040 0A 10 00 00                ldi     r1,#0
000044 3A FC FF FF                bra     test_4
                   test_5:
000048 0A 10 02 00                ldi     r1,#1
00004C 3A FB FF FF                bra     test_4
                   test_6:
                   test_3:
000050 C6 5D D0 FF                lw      r5,-24[bp]
000054 D1 5D 30 00                lfd     fp5,24[bp]
000058 D1 6D 40 00                lfd     fp6,32[bp]
00005C AB 42 0C 02                fmul    fp4,fp5,fp6
000060 02 62 10 CC                mv2fix   r6,fp4
000064 82 42 0C 2A                subu    r4,r5,r6
000068 C6 5D E0 FF                lw      r5,-16[bp]
00006C 02 32 0A 28                addu    r3,r4,r5
000070 82 31 10 3A                mv2flt   fp3,r3
000074 F1 3D F0 FF                sfd     fp3,-8[bp]
000078 BA F5 FF FF                bra     test_4
                   endpublic

_________________
Robert Finch http://www.finitron.ca


Fri Apr 24, 2015 11:47 am
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
Added a bunch of instructions that are only 16 bits wide in order to help with code density. It can really help code size with smaller routines (see example below). Overall code size for the ROM was reduced by about 12% using these instructions. The only cost is increased complexity. The instructions include: PUSH/POP registers, RTS and RTL, register-register MOV, ADD quick immediate, LDI load quick immediate, BEQ/BNE branches and a number of control instructions. Had to modify the operation of the instruction cache and pc to make them work. The PC can now be aligned on a two byte boundary instead of a four byte one.
Having trouble at the moment getting the FPGA version working. It displays the startup message then hangs somewhere initializing FMTK. It seems to work in the emulator though. The emulator has a minor glitch to it where a carriage return character gets missed printing a startup message. Haven't tracked down the bug yet.

Code:
                   LockBIOS:
010C20 B1 0F              push    lr
010C22 B1 00              push    r1
010C24 31 01              push    r2
010C26 B1 01              push    r3
010C28 65 E0 FF FF        push    #-1       ; try forever
010C2C 7C 18 00 00        pea     BIOS_sema
010C30 65 E0 61 07
010C34 39 53 18 00        bsr     LockSemaphore_    ; call library routine
010C38 B1 21              pop     r3
010C3A 31 21              pop     r2
010C3C B1 20              pop     r1
010C3E B0 00              rts

_________________
Robert Finch http://www.finitron.ca


Sun Apr 26, 2015 6:14 pm
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
The code size for the ROM is now about 20% smaller than an 32 bit only word size would allow. It's averaging about 25.5 bits per instruction. A couple of 16 bit instructions were added which are instructions referencing data on the stack relative to the BP register. By making the BP register implied in the instruction and compressing the displacement constant the size of the instruction could be reduced to 16 bits from 32.
A couple of bugs in hardware (due to changes to support 16 bit instructions) have been worked out, and now the FPGA version works the same as the emulator. It boots to the shell prompt now but the shell commands don't seem to work at the moment. Since the problem is the same in both the emulator and the FPGA version, I'm convinced it's a software bug.
Keyboard code was changed to wait for an interrupt message rather than looping ceaselessly. The task is now in theory suspended allowing other tasks to run while waiting for keyboard input. It seems to work, either it does or it's completely non-working. The code is in place, but perhaps it isn't executed, I've yet to determine.

_________________
Robert Finch http://www.finitron.ca


Thu Apr 30, 2015 5:06 am
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
The test system has sprouted a graphics accelerator. A heavily modified version of the openrisc graphics accelerator (ORGFX) available from opencores.org is in the process of being incorporated into the system. It doesn't work perfectly yet, but it's on the way. For some reason it seems to want to draw everything beginning in the top left corner of the screen and drawing triangles doesn't work yet. It took me forever to figure out that the graphics co-ordinates are fixed point numbers with a 16 bit fractional part to them. Initially when specifying the co-ordinates I assumed they'd be whole numbers. This resulted in nothing displayed on the screen. After some investigation and actually studying the examples I was able to figure it out. The orgfx core was modified to support "weird" graphics modes and pixels packed on bit boundaries. By weird I mean WXGA modes scaled by divisor factors.
Attachment:
File comment: ORGFX on FISA64
FISA64orgxc.jpg
FISA64orgxc.jpg [ 25.95 KiB | Viewed 8199 times ]

The test system doesn't have enough memory bandwidth to support a full resolution WXGA mode screen. Plus I wanted 12 bit pixels packed into 128 bit bundles as a display unit. Hence lots of mods. Displayed above is a 340x256 (1/3 of 1366x768) with 12 bits per pixel mode.

_________________
Robert Finch http://www.finitron.ca


Tue May 05, 2015 11:40 am
Profile WWW
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
Good stuff, Rob! And thanks for posting the image -- it makes a refreshing addition to the visuals on the forum. Maybe you could post a photograph of your test system, too.

Quote:
The orgfx core was modified to support "weird" graphics modes and pixels packed on bit boundaries. By weird I mean WXGA modes scaled by divisor factors.
If the the original orgfx core used pixels not packed on bit boundaries, were there unused bits, then, used as padding to reach a byte boundary? And can you elaborate on the divisor factor, please?

BTW, you and others here may find the TMS34010 a source of some interesting ideas. This combined CPU/GPU chip is a bit addressable 32-bit processor. Ie: every address is capable of specifying an exact bit. (For word-wise operations, the LS address bits are zero.) It also can do X-Y addressing of pixels.
http://en.wikipedia.org/wiki/TMS34010

-- Jeff

_________________
http://LaughtonElectronics.com


Thu May 07, 2015 2:13 pm
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 138 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9, 10  Next

Who is online

Users browsing this forum: SemrushBot and 8 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:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software