Last visit was: Sat Oct 31, 2026 12:37 pm
|
It is currently Sat Oct 31, 2026 12:37 pm
|
rf68000 - 68k similar core
| Author |
Message |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Still stuck trying to process characters in the monitor program using PostMsg() and WaitMsg() OS calls. According to screen displays, PostMsg() gets called every time a key is pressed on the keyboard, great! And WaitMsg() (or rather CheckMsg() ATM) is being called in loop. Yet, the keystroke message does not make it to the system monitor. Instead, things crash at address $00000ABA with an invalid opcode. The CPU gets there from jumping to the zero address due to a NULL pointer, then it starts incrementing from the zero address until it hits an instruction it cannot process, which is at $00000ABA. So, I know roughly what is happening, and have yet to determine the cause. Not sure how a NULL pointer makes it into the program counter. A NULL pointer as a data address makes more sense.
Decided to start work on Qupls5 for a bit.
Qupls5 is going to have fewer registers (16) and one memory operand per instruction (like the 68000). Qupls5 will have 96-bit wide registers to support triple precision floats and capabilities pointers. Integer ops only work on the lower 64-bits though. Addresses are 48-bit. Instructions are only 32-bit with additional instruction words for constants and the like. The work is mostly specs ATM.
_________________Robert Finch http://www.finitron.ca
|
| Thu Mar 05, 2026 1:55 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Went all gung-ho a couple of nights ago coding the 68851 emulation. Got a lot of it coded. About 700 LOC. It is quite a sophisticated beast as MMUs go. Some of the status results for the PTEST instruction need to be coded yet.
Went to add transparent translation registers to the MMU then recalled that the 68030 MMU had them. So, a ‘030 compatible transparent translation registers were added. I think this will make the MMU compatible with the MMU in the 68030.
Decided to scrap the work I did on Qupls5. Worked on enhancements for a 64-bit mode 68000 instead.
Started working on Qupls6. Back to 32-regs and 32-bit instructions. Planning on having 128-bit registers. But processing will be on 64-bits at a time. Kinda like the way the Z80 or 68k process data. The registers will be arranged as low-half, high-half in the register file. Halves stacked vertically in the register file. This is because the BRAM is better used deep rather than wide. The 128-bit registers are to operate with larger FP values and capabilities.
An instruction like ADD.H Rd,Rs1,Rs2 (add hexi-byte values) will need to run through the ALU twice, once for each of the lower and upper half of a register.
_________________Robert Finch http://www.finitron.ca
|
| Wed Mar 11, 2026 4:05 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Worked a bit on another older project today, the Butterfly. The Butterfly project is a small pipelined CPU that executes most instructions in a single clock cycle. It is only 32-bit so I was re-writing it to have 128-bit registers. The idea was to use it implementing the MMU and 128-bit registers are convenient for loading descriptors. But I eventually decided not to go that route. Made a pretty memory map for the rf68000 SoC. Contemplating how to use multiple graphics accelerators together in the same project. I think each one needs its own dedicated memory to perform well. Considering using 340x192 graphics mode (subset of 1366x768) and RGB444 resolution. That way multiple screens (one for each graphics accelerator) can fit into the BRAM. The trick is how to merge all the results together. It is not too bad if the results do not overlap. The drawings could be sorted according to z-depth and handed to graphics accelerators processing a particular z-range. Farthest away z would be copied to a master screen buffer first, then closer results would be copied overtop - the painter’s algorithm. Still stuck on a NULL pointer issue in the OS. But I have tracked it down further. Attachment: rf68000SoC.png
You do not have the required permissions to view the files attached to this post.
_________________Robert Finch http://www.finitron.ca
|
| Sun Mar 15, 2026 4:54 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
A JSR (a0) with a NULL pointer is one failing point. Fortunately, that instruction is not used very often. It is used only three times in the boot ROM. Unfortunately, I cannot see how it could be getting a NULL pointer, but I put in NULL pointer checks anyway. The code is loading address pointers from tables. Entries that are not used are stubbed out (they are not NULL). The one spot where it is used is in the I/O TRAP routine (TRAP #0). Since this routine gets called for every I/O operation, it is called literally thousands of times during startup. Why it would fail in one case is a mystery. The second use of JSR (a0) is similar – the TRAP #15 which tries to emulate the TRAP #15 in other systems. Once again, this routine is called successfully many times. The last use in the boot ROM is for a generic IRQ routine. This routine is not used.
The indirect subroutine call is also used by device drivers in the command processor.
From a software perspective this looks like a hardware error of some sort.
From a hardware perspective this looks like a software error of some sort.
Found a software issue in the keyboard interrupt. For some reason I decided to protect things using a blocking semaphore. The issue was that the semaphore lock logic temporarily enables interrupts in a loop. It must or the system could hang waiting for a semaphore to be released with interrupts disabled. With interrupts enabled and a level sensitive keyboard interrupt, the keyboard interrupt would activate again, recursively, and eventually overflow the stack. Also overwriting BIOS variables. I simply updated the semaphore logic to use non-blocking semaphores which run with interrupts disabled.
The system works a bit better but still responds with an ‘illegal opcode’ message over and over again, indicating it is getting to invalid code. Something is still amiss.
_________________Robert Finch http://www.finitron.ca
|
| Mon Mar 16, 2026 3:22 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Modified the keyboard interrupt to save and restore registers in a piecemeal fashion as opposed to all at once at the beginning and end of the routine. This was to reduce the dynamic instruction count (save clock cycles) and reduce stack space used in cases where the interrupt was not a keyboard interrupt. Code is slightly larger, but this is not 1980 size limitations.
Stripped out the scan-code checking in the ISR for CTRL-C and ALT-tab. Then put it back in later. These are also processed by the KeybdTranslate() routine which is called by the App to translate keyboard scan codes. I thought it could be moved out of the ISR, but then realized that if the app crashed or just decided not to test for keystrokes, there would be no ALT-tab or CTRL-C functionality.
Also removed the LED updates, this was redundant as there is a screen indicator as well.
Made some progress on the looping ‘illegal opcode’ issue.
Found a hardware issue with the SoC NIC (network interface circuit). It was sending all memory requests across the network, including local ones. There would be no ACK cycle on the network for a local request, which turned out to be generally okay, except that when there was a long sequence of local accesses without any global accesses, a bus error would be signaled on the network since it thought there was a global timeout. So, a bus error was intermittently signaled to the CPU depending on what was going on. It was found after a MOVEM instruction which took some cycles to complete. The bus error routine just spits out ‘bus error’ and drops back into the monitor, aborting the current operation.
The next hardware issue was the state stack would underflow. A bus error was just jumping directly to the TRAP code, basically a no-no since it is called as a routine from elsewhere. The underflow popped a zero off the stack which is an illegal state. Illegal states were jumping to the RESET. The RESET state had bug in it in that if it were reached other than by external reset, it would execute a different trap, possibly the previous trap executed.
Found another software issue. Mailbox handles (all the FMTK handles) are short integers (16-bit). But in the boot rom code a long word was being loaded for the handle. Because the CPU is big-endian the low order 16-bit would not be correct. The handle would never match what it was supposed to, so no messages would get delivered.
The boot rom commands still do not work yet, it hangs at the ‘$’ prompt now. At least the illegal opcode error is gone.
A great day for catching bugs.
_________________Robert Finch http://www.finitron.ca
|
| Thu Mar 19, 2026 2:53 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Slowly moving the core closer to 68020+ operation. Modified the core to add an additional stack pointer. The core now has three stack pointers and three modes like the 68020 and above. User/App, supervisor and interrupt modes. The ISRs were modified to make use of the interrupt stack pointer.
Also added a global interrupt enable flag. It works like this: on power on reset, all interrupts, including NMI, are disabled until the first update of the status register. This prevents a spurious interrupt from interrupting the startup sequence.
Changed the way interrupts are masked off when an interrupt occurs. There was a ‘MOVE.W #$2700,SR’ at the start of every interrupt routine to disable interrupts. So, the processor now just automatically masks all interrupts when entering an ISR. This is slightly different than the 68000 which automatically sets the interrupt mask level to the same level as the interrupt. If it is desired to allow interrupts to occur during the ISR it is now necessary to modify the SR accordingly. NMIs will still override the ISR.
Expanding the number of interrupts supported by the CPU is under consideration. It would work by using currently unused bits in the SR. Two bits from the CCR plus a bit in the SR would add three more bits, allowing a 64-level interrupt system. Another bit stolen from the CCR part of the SR would also indicate 64-bit mode is active.
With the additional stack pointer and the mode flag (mf in the SR), the system is busted down to not clearing the screen even. It does set a LED on power-up.
Found another hardware bug. When the SR was modified programmatically (AND, OR, EOR, MOVE), the stack pointer selection was not changing to reflect the selected stack in the new SR value.
_________________Robert Finch http://www.finitron.ca
|
| Fri Mar 20, 2026 5:11 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Well, I managed to get things working again up to the screen clearing, and the devices initializing, but after that it hangs. I do not have a lot of confidence about how things are working, as the fix was to simply shuffle some code around without making other changes. AFAIK it should not make a difference, but it does. I wonder if there is a timing bug in the SoC network or something similar. This could take some digging to track down.
_________________Robert Finch http://www.finitron.ca
|
| Mon Mar 23, 2026 3:40 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Back onto the 68k project. The last state it was in, the boot was hanging after devices were discovered.
Time to tackle bugs one at a time.
The first thing noticed was the device-name was missing for the text video controller. The boot screen reports “Found <blank> at F0020000”, where <blank> is supposed to be the 16-character device name. Nothing was obvious in the device setup code, but all the drivers were recompiled anyway.
Next, a look at the code for the hardware of the text controller revealed that it was always using a 64-bit version of the device discovery black box. It was improved to use either the 64-bit or 32-bit version. The text controller was made somewhat generic so it could be adapted easily for either 32-bit or 64-bit operation.
Next, there was an issue building the system where the frame buffer had errors. The frame buffer was in the process of being converted from a FTA bus back to a WISHBONE bus version and the conversion was not complete. To fix this enough of the frame buffer signals were adapted to allow synthesis to run. The frame buffer probably does not work, but it is not needed yet.
During the boot ROM build, the OS SendMsg() and WaitMsg() calls were messed up in the test startup. The parameters had been changed to be just a pointer to a message block instead of three independent long words for the message. But several places were missed where this change was not made. This caused compiles to fail in a couple of places.
It had been a while since the FPGA board was fired up, and the video cable was missing – used for something else. So that had to be retrieved and attached to the proper ports.
_________________Robert Finch http://www.finitron.ca
|
| Sun Sep 27, 2026 1:59 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
I was stumped for a while. It was determined that the bootup was crashing at the first subroutine call made in the ‘C’ code. The assembler listing was reviewed, and it was revealed that the BSR instruction opcode was being used with a long-word displacement even though a JSR was specified. I believe this was an enhancement made to the BSR instruction for 68020 at later processors and likely an optimization option in the assembler. It turned out that long word displacements were not supported with RTL code.
_________________Robert Finch http://www.finitron.ca
|
| Mon Sep 28, 2026 5:55 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Having fixed the RTL code to support long branch displacements, it still did not work. It looks like it could be a bug in the assembler but I really doubt it. The following snapshot shows what is loaded into the immediate buffer of the CPU for a long branch to subroutine instruction ($61FF). The absolute address ($6D74) of the target is being loaded instead of the relative displacement. AFAIK only the displacement (relative address) should be loaded into the buffer. The trick is to figure out how the absolute address is loaded. Is it coming from the binary for the ROM, or is it a bug in the processor? The relocation record in the object file shows it as ‘PC’ – PC relative which is correct. I am trying to track the displacement down in the binary file, but it is complicated. After a few minor tweaks, the bootup is now hanging with a bus error. “Bus Error at $FFFF8C90”.
You do not have the required permissions to view the files attached to this post.
_________________Robert Finch http://www.finitron.ca
|
| Tue Sep 29, 2026 1:06 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Removed some of the state transitions to the WAIT_NACK state to reduce the number of clock cycles required to execute some instructions. All WAIT_NACK does is wait for the ack_i signal to go low indicated the end of a memory access. In many cases this test could be done at the previous state.
A while ago most of the status register flags updates were moved to the IFETCH stage causing flag updates to take place when the next instruction is fetched (pipeling the operations), which shaves a cycle off instruction execution time in some cases. Some of the remaining flag updates not being done at the IFETCH stage were moved there to make things more consistent.
Still stuck on long branch to subroutines. Now the PC is being loaded with the displacement value instead of the sum of the PC and displacement. This is not the way it is in the RTL code. The code looks correct, but dumping the PC from the running FPGA is not. Next step is to dump intermediate values. It looks like things are not synthesizing correctly for some reason. The effective address variable ‘ea’ is heavily used in the core. It is updated in many places including for subroutine calls, and it may be just too heavily loaded.
Found what appears to be a bug in the JSR instruction, according to the RTL code it is loading a long word from the destination address before jumping to it. This is unnecessary and a performance issue. This bug found by inspection when comparing JSR to JMP. The task used to compute the effective address exits by jumping to a state defined as a parameter to the task. For JSR this was defined as FETCH_LWORD, for JMP this is defined as FETCH_NOP_LWORD, the difference being that one does an actual data fetch and the second does not. They both leave the ‘ea’ variable pointing to the destination address.
_________________Robert Finch http://www.finitron.ca
|
| Thu Oct 01, 2026 5:30 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Added an enumeration for the address mode to make the code a little cleaner. The code was just using numbers and it was not obvious what the address mode was.
_________________Robert Finch http://www.finitron.ca
|
| Sun Oct 04, 2026 7:49 am |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
In the original rf68000, the result busses were triplicated with a separate bus for byte, word and long word operations. Results were then muxed into the register file. This was done to get the best performance at the time, but resulted in the duplication of logic. This was changed to a single result bus and the duplicate logic removed. The register file mux was removed. This made virtually no difference to the size of the core, but the code may be simpler. I guess synthesis was able to determine that the duplicate logic operations could be merged together.
_________________Robert Finch http://www.finitron.ca
|
| Mon Oct 05, 2026 1:42 am |
|
 |
|
BigEd
Joined: Wed Jan 09, 2013 6:54 pm Posts: 1898
|
Was there any measurable change to performance with that?
|
| Mon Oct 05, 2026 1:31 pm |
|
 |
|
robfinch
Joined: Sat Feb 02, 2013 9:40 am Posts: 2537 Location: Canada
|
Quote: Was there any measurable change to performance with that? There is no significant difference in the timing when the system is built. But just building the system does not indicate the FMAX stayed the same. The core has so many features now (FPU, MMU, 020 ops) that I would guess the FMAX has dropped. It used to be about 80 MHz. I should really synthesize the core with different options and see what the timing is like.
_________________Robert Finch http://www.finitron.ca
|
| Tue Oct 06, 2026 3:13 am |
|
Who is online |
Users browsing this forum: Amazonbot, Chrome-11x-bots, claudebot, ExaSearchBot and 26 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
|
|