Last visit was: Sat Jul 31, 2021 5:14 am
It is currently Sat Jul 31, 2021 5:14 am



 [ 87 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next
 CS01 
Author Message

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
This version of Tiny Basic is port from DSD9 which wasn’t completely debugged. I now have several versions of Tiny Basic, but they are all ultimately derived from Tiny Basic for the 68000. Tiny Basic for the 68k was a port of Palo Alto Tiny Basic found in Dr. Dobb’s Journal. Of course, the source code is considerably different now but the ideas remain the same.

Added several custom instructions to the core to support operating system functions. One function is implementing a bitmap of allocated memory pages. Searching and updating the page allocation map is time consuming and requires a couple of hundred lines of code. It’s a lot of bit fiddling which is hard to do without bitmap instructions. So, I turned it into a hardware function which is faster. It reduced the s lines of code to a single instruction.
Code:
 Alloc:
   sub         $sp,$sp,#16
   sw         $ra,[$sp]
   sw         $s1,4[$sp]            ; these regs must be saved
   sw         $s2,8[$sp]
   sw         $s3,12[$sp]
   ; First check if there are enough pages available in the system.
   add         $v0,$a0,#2047         ; v0 = round memory request
   srl         $v0,$v0,#11            ; v0 = convert to pages required
   lw         $t0,NPAGES            ; check number of pages available
   bleu      $v0,$t0,.enough
   mov         $v0,$x0                  ; not enough, return null
   bra         .noRun
.enough:
   ; There are enough pages, but is there a run long enough in map space?
   sw         $s2,$v0            ; save required # pages
   mov         $a0,$v0
   call      FindRun                  ; find a run of available slots
   beq         $v0,$x0,.noRun
   ; Now there are enough pages, and a run available, so allocate
   mov         $s1,$v0                  ; s1 = start of run
   lw         $s3,NPAGES            ; decrease number of pages available in system
   sub         $s3,$s3,$s2
   sw         $s3,NPAGES
   mov         $s3,$v0                  ; s3 = start of run
.0001:
   palloc   $v0                        ; allocate a page (cheat and use hardware)
   beq         $v0,$x0,.noRun
   mvmap      $x0,$v0,$s3            ; map the page
   add         $s3,$s3,#1            ; next bucket
   sub         $s2,$s2,#1
   bne         $s2,$x0,.0001
   sll         $v0,$s1,#11            ; v0 = virtual address of allocated mem.
.noRun:
   lw         $ra,[$sp]               ; restore saved regs
   lw         s1,4[$sp]
   lw         s2,8[$sp]
   lw         s3,12[$sp]
   add         $sp,$sp,#16
   ret


The FMTK start task operation wasn’t working correctly, but I managed to trace it to bad branch operations. On a hunch that it might be timing related, I inserted an extra stage after register fetch to give more time for register data to appear. And voila, it works now. The tools didn’t report any timing errors, but it seems like there is one. It’s running a fairly fast clock 50MHz and I’m not sure how good the PS is on the little circuit board.

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


Wed Jan 29, 2020 4:01 am WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1626
robfinch wrote:
This version of Tiny Basic is port from DSD9 which wasn’t completely debugged. I now have several versions of Tiny Basic, but they are all ultimately derived from Tiny Basic for the 68000. Tiny Basic for the 68k was a port of Palo Alto Tiny Basic found in Dr. Dobb’s Journal. Of course, the source code is considerably different now but the ideas remain the same.

Thanks!


Wed Jan 29, 2020 3:28 pm

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
More debugging of TinyBasic. Did some work on the expression processing which wasn’t working at all. Now it can at least evaluate expressions containing constant values. For some reason variables aren’t working in expressions yet. Expression processing was modified to return the type of a value in addition to the value. At some point it would be nice to support floating-point and strings.

I found the memory interface to the ram needed to be adjusted slightly. It was running @50MHz reading a byte of data each clock cycle. It switched to running @100MHz and reading a byte every other clock cycle. Performance is the same but reads are a bit more reliable now. Writes are actually faster than before due to the higher clock rate. The tools have two clock cycles to work with instead of one. The ram is incredibly fast 8ns. But it’s only a byte wide. For simplicity, 32-bit accesses are made to the ram so it required about 6 clocks for a read and about 20 clocks for a write.

I’m trying to get the FMTK task switcher running. It hangs on a task switch. The system insists that there are three tasks in the fourth ready queue. This is just plain wrong, there aren’t supposed to be any and I think it’s due to a memory write error when the heads and tails pointers are reset during system initialization. The process id is only a single nybble; the system allowing only 16 tasks for now.

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


Thu Jan 30, 2020 4:05 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
And more debugging.
Added instructions to move data between user and machine mode register sets. The FPGA supports 64-entry register files using the same resources as 32-entry files, so two 32-entry register sets are used with the machine mode indicator selecting between the two. This means when an exception occurs the registers don’t have to be saved because the machine mode register set is used instead of user mode register set.

We have task switching working with few glitches. Multiple TinyBasic tasks were kicked off from the monitor. The ‘S’ command in the monitor is used to switch tasks. In TinyBasic the ‘yield’ command is used to switch tasks. In theory yield can be used from within a basic program, but it hangs at the moment. There is no choice about what task is run next. It is simply what the scheduler decides to run which is usually the next ready task.

TinyBasic works much better now. Still not perfect but it seems to be able to evaluate expression with variables now, perform if / for / goto and print. I got hung up on the if statement for a while because the label to implement it was called ‘IF’. But IF is also a structured programming construct available in the assembler, so it got assembled as a value of zero, causing a null pointer issue.

Worked on the FMTK operating system code. I have yet to get this system fully working but I continually port it from one project to the next.

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


Fri Jan 31, 2020 4:10 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Wrote rtl code to handle mailboxes and messages all in hardware. It turned out the code was too large (about 20,000 LC’s) to fit into the FPGA. I wasn’t expecting it to be quite so large. So, shelved for now.
Wrote the message handling portion of FMTK in assembler.
For some reason the memory allocation function, which was working, now returns an error. I traced it to the hardware palloc function. I may be re-writing that portion of code in software too.

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


Sat Feb 01, 2020 4:23 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Added messaging capabilities to TinyBasic. They are implemented as functions so that the return status can be checked.
Code:
s = ALLOCMBX (x)   // allocates a mailbox and assigns the handle to x
s = SENDMSG (x, 1, 2, 3)   // sends a message comprised of the values 1,2,3 to the mailbox x
s = WAITMSG (x, a, b, c, 0)   // waits for a message and puts values in variables a,b,c

The FMTK messaging system supports messages composed of three words of information. If more information is needed then pointers to blocks of information must be used.

Got interrupts working. Getting interrupts working was just one step away from getting the environment call instruction working. Next to do is get the i/o focus setup working. Interrupts switched tasks from the TinyBasic task to the system task while TInyBasic was displaying the startup-banner. Using the ‘S’ command in the monitor switched back to TinyBasic at which point the timer interrupt switched back to the monitor again. So some way is needed to force the I/O to remain with a given task.

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


Sun Feb 02, 2020 3:56 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Got some I/O focus routines written so, back into the realm of writing device drivers.
Ran into the issue of access to serial buffers. The buffers need to be accessible to both interrupt routines and non-interrupt routines. But interrupt routines access memory in a flat fashion, whereas other routines are using mapped memory. So, the serial buffers are mapped into the address space along with other OS data. The first 64k of an address space is reserved for OS data. Currently it is mapped but I may hack this so that map cells aren’t used up to represent OS data.
Trying to get interrupt driven serial receive working with XON/XOFF flow control. I tried downloading a TinyBasic program but some of it was messed up due to the serial not being able to keep up therefore the need for XON/XOFF control.

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


Mon Feb 03, 2020 3:50 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Discovered there was a redundancy in the operating system functions. I had a call called “reschedule” to reschedule tasks. When optimizing the code a little bit I realized that the sleep() function could fall through into reschedule(). Then I realized the reason was they were basically the same function call. Calling sleep(0) was just the same as reschedule(). So I got rid of the reschedule() function.

Got interrupt driven serial receive to work, and the 33Hz tick interrupt working too. Hopefully the interrupt driven receive will provide greater bandwidth. Both the uart and via are setup as devices now. The messaging features of the OS are not being used by device drivers in the interest of performance.

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


Tue Feb 04, 2020 3:37 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Re-wrote parts of the OS. Converted a couple of the smaller routines into macros. Then found out I had to fix up the macro processing capability of the assembler. It was leaving pieces of the macro out.
Currently the OS is hanging when activating TinyBasic as a task. I’ve been working on it. It was activating TinyBasic just fine but not switching to it. So I changed the task code somewhat, now it’s broken at the moment.

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


Wed Feb 05, 2020 5:35 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Been working mostly on debugging OS software. For some reason the ready list and timeout list, which are linked lists, are getting screwed up. I can’t seem to figure it out. It’s simple linked list insertions and deletions with interrupts turned off. One slight complication is that handles (indexes) are being used rather than pointers. An example of the wonderful kind of code looked at:
Code:
 ;------------------------------------------------------------------------------
; Pop an entry off the timeout list. It is assumed the entry is popped when
; its timeout reached zero. Hence there is no adjustment of the following
; timeout made. Routine used only in the schedulerIRQ, so written as a macro.
;
; Parameters:
;      v0 = top timeout list
; Modifies:
;      v1,t0,t1,t2,t3
;   Returns:
;      v0 = timeout list entry tid
;------------------------------------------------------------------------------

macro mPopTimeoutList
   sll      $t0,$v0,#10                  ; tid to pointer
   lbu      $v1,TCBStatus[$t0]      ; no longer a waiting status
   and      $t1,$v1,#TS_WAITMSG      ; check if waiting for a message
   beqz   $t1,.noWait@
   mMbxRemoveTask                     ; remove task from mailbox list
.noWait@:
   and      $v1,$v1,#~(TS_WAITMSG|TS_TIMEOUT)
   stb      $v1,TCBStatus[$t0]
   ldw      $v1,TCBNext[$t0]         ; get next task on timeout list
   stw      $v1,TimeoutList            ; update list head
   ldi      $t1,#NR_TCB                  ; check valid handle
   bgeu   $v1,$t1,.done@
   ldi      $t1,#-1                        ;
   sll      $v1,$v1,#10                  ; v1 = tid to pointer
   stw      $t1,TCBPrev[$v1]         ; TimeoutList->prev = -1
.done@:
   ldi      $t1,#-1                        ; reset next and prev indexes
   stw      $t1,TCBNext[$t0]         ; on popped task
   stw      $t1,TCBPrev[$t0]
endm


Some custom instructions implemented in Finitron’s cpu:
The instructions are for operating system support.
MOV allowing the movement of register data between register sets. mov u:$v0,m:$v0 moves from the machine register set $v0 to the user register set $v0. There’s a separate register set for user and machine operating levels as it comes almost for free in an FPGA. The extra registers are there whether or not they are used.
MVSEG for moving to/from segment registers, works like the CSR instruction.
MVMAP for moving to/from simple page mapping registers again working like the CSR instruction.
PALLOC allocates a page of memory, memory usage tracked via hardware.
PFREE frees a previously allocated memory page.
PFI poll for interrupt. Takes the place of two or more instructions to enable then disable interrupts, without affecting the interrupt flag.

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


Fri Feb 07, 2020 4:51 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Changed the page mapping hardware slightly to use 1kB pages instead of 2kB pages. The smaller page size deemed better due to the restricted amount of memory in the system. It provides more pages at a finer granularity. There are now 512 mappable pages in the system as opposed to 256.

Got rid of the instruction to move between register sets and replaced it with a CSR to select which register set is used for each of Rd,Rs1,Rs2 and Rs3. This allows register set selection to be applied to any instruction as opposed to just the mov operation. This removed the special mov instructions during context switch and cut the number of instructions required in half.
The processor no longer automatically switches register sets on exceptions. Instead the CSR instruction must be used to switch register sets. Just a single instruction is required to switch register sets.

Still working out the bugs in software. Interestingly a program can still run, although not properly, if the address is misaligned by two.

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


Sat Feb 08, 2020 4:28 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
I’ve been busy implementing parts of the OS as custom instructions. There’s already memory allocation and freeing working. I tried setting up the ready list and had great success. Only about 60 LUTs required. Spurred on by potential success…
I tried setting up the timeout list to be managed in hardware. My first attempt mimicked the software linked-list approach. The resulting size was not too bad at about 2.2kLUTs. But too large for the target FPGA. Then I asked the question: Well, what if there was just a whole bunch of decrementers, one for each task? It would not be done that way in software and I figured it’d be more hardware than the linked-list approach. I did a quick calc. 16 x 32 bit decrementers = 512 LUTs. Hmm, it might be small enough. Then I thought hey, why have all the decrementers when one could do the trick if it was time multiplexed? Since the number of tasks is small, time-multiplexing the decrement wouldn’t be any worse that some other long running instruction. The result: 133LUTs. Small enough to use. It’ll take 16 clocks to do all the decrements, but with some clever system implementation that time should be hidden. Suppose the decrement cycle were triggered at the start of a timer ISR. It’d likely be done before the software got around to requiring access to the timeout values.
The human wayward means at arriving at logic solutions.

Ready / timeout list insertion and deletion software is now about ¼ the size. But it doesn’t work quite right yet. The monitor help menu displays then things start looping around in the OS.
Code:
 RemoveFromReadyList:
   ldi      $v1,#MAX_TID               ; check arg
   bgtu   $a0,$v1,.badTid
   rmvrdy   $a0                           ; cheat and use hardware
   sll      $t4,$a0,#LOG_TCBSZ      ; s1 = pointer to tcb
   ldb      $t0,TCBStatus[$t4]      ; set status no longer ready or running
   and      $t0,$t0,#~(TS_READY|TS_RUNNING)
   stb      $t0,TCBStatus[$t4]
   ret

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


Sun Feb 09, 2020 6:06 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Migrated CS01 to the NexysVideo board from the CModA7. I really wanted to see debug output on screen, along with implementing a larger system. Using a simple paged memory management unit there are 8192 pages that are 65kB in size on the NexysVideo version. The NV version also supports more tasks. I intend to use the system to debug the Femtiki (FMTK) operating system.

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


Mon Feb 10, 2020 3:44 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
The latest debugging nightmare was unexpected calls to the OS. For some reason or other the OS was being invoked at mysterious places. It then dawned on me that it might be interrupts that aren’t working correctly. Sure enough, when I upgraded the core to 64-bits I forgot to move the interrupt indicator to bit 63 from bit 31 of the cause register. Hardware interrupts were thus invoking the software handlers due to bad dispatching. This is one of the issues of having the same vector process both hardware and software interrupts.
The next issue was the device function table spacing. It needed to be modified to units of 8 bytes from 4 bytes for vectors.
Top level interrupt dispatch code:
Code:
;------------------------------------------------------------------------------
; Exception processing code starts here.
; As per the RISCV privilege spec, the MSB indicates an external interrupt.
; The system uses cause codes 32 to 63 for external devices. This cause code
; range is reserved in the RISCV spec.
;------------------------------------------------------------------------------
   code
   align   4
IRQRout:
   csrrs   $x0,#$800,#15         ; select machine regs
   ldi      $sp,#$20000000-8   ; setup machine mode stack pointer (top of ram)
   csrrw   $t0,#$342,$x0         ; get cause code
   blt      $t0,$x0,.isIRQ      ; irq or ecall?
   jmp      OSCALL                  ; goto operating system call dispatcher
.isIRQ:
   and      $t0,$t0,#31            ; interrupting device # is low order 5 bits of cause code
   sll      $t0,$t0,#8            ; 256 bytes per device func table
   add      $t0,$t0,#DVF_Base+22*8   ; load IRQ routine vector from device func table
   ldo      $t0,[$t0]
   beq      $t0,$x0,.noIRQ      ; make sure there's an address to go to
   jmp      [$t0]                     ; jump to the IRQ routine
.noIRQ:
   csrrc   $x0,#$800,#15         ; select user registers
   eret

I have yet to devise a way to hook into the interrupt system.

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


Tue Feb 11, 2020 3:32 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1442
Location: Canada
Added keyboard support. Somehow a bad OS call number is causing the OS to re-execute the dispatcher in an infinite loop. This makes it difficult to try and track down the issue. If I didn’t know better I’d say hardware interrupts were still screwy. It could be that an unimplemented instruction is being hit. A few assembler output errors have been found this way.

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


Wed Feb 12, 2020 1:31 pm WWW
 [ 87 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next

Who is online

Users browsing this forum: CCBot and 0 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

Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software