magenet

Monday, November 14, 2016

The MOS 6502, Part 2

Another important aspect we need to care of is the speed that the CPU reads the instructions at. The real hardware is ruled by a signal that pulses. This is called Clock. This signal is very important because in the majority of the systems all components are synchronized and can work together.

In an emulated system this signal doesn't exist really, but it's simulated by a repeated task that executes all the components of the system for a time unit. Something like:

1) Execute CPU.
2) Draw graphics.
3) Check the keyboard.
...
n) Other task.

Now, the program that emulates the CPU is called every n time units and executes a specific number of instructions. 

The instructions usually take a certain amount of time, measured in clock pulses. So for example a CPU can take 2 clock pulses to perform an addition. Or maybe 5 clock pulses to access the RAM and save a value. Every instruction take a certain amount of cycles. It's very important to count these cycles in order to keep the correct speed of the system that is emulated.

The Apple-1 was "Clocked" at 1,023 MHz, this means that in a second the system receives 1,023,000. So one pulse every 977 micro seconds. If we want to emulate this kind of speed we can't pretend that a micro controller executes the virtual CPU at this speed, we would need a very fast micro controller. What we need is to reduce the number of times the virtual CPU is executed, and let it execute more instructions at once.

So for example we can setup a repeated cycle that runs at 102,300 Hz, 1/10th of the original frequency:

Every 102,300
1) Execute 10 cycles of CPU.
2) ...
n) Other task.

We can keep track of the cycles executes with a simple global counter, and update it after each instruction executed.

Every 102,300
1) Execute 10 cycles of CPU:
     - Instruction 1: -2 clocks, still 8 to execute.
     - Instruction 2: -5 clocks, still 3 to execute.
     - Instruction 3: -5 clocks, Overflow, the counter goes negative -2 cycles

n) Other task.


In the previous call the virtual CPU has executed 2 clocks more than needed, so for the next call the two clocks are subtracted from the number of cycles to execute.

Every 102,300
1) Execute 10-2 cycles of CPU:
   ...

n) Other task.


It's very important to read the documentation of the system, and then the documentation of all the components that the system uses.

Thursday, November 3, 2016

The MOS 6502, Part 1

I won't dig to much deep into the architecture of this microprocessor, there is a lot of information over the Web, but I will discuss more about the way I implemented the "behavior" of the CPU in my Apple-1 emulator. If you want you can read more about this CPU on Wikipedia:

Wikipedia MOS 6502

Or you can find a lot of information, material, link and tutorial at:

www.6502.org

That said, the MOS 6502 is one of the most popular 8 bit processor used in the past, together with the Zilog Z80 dominated the market of the home/personal computers of the 70s/80s/90s.

From Wikipedia: The MOS 6502

From Wikipedia: The Zilog Z80


One of the most popular computer that was equipped with it is the Commodore 64, probably the most selling computer ever. Actually the CPU present in this computer was a 6510, but it's compatible and many sources say that this computer has a 6502, so we will assume it is so.

From Wikipedia: The Commodore 64.

One of the reasons why this CPU was so popular is because it's very simple but still powerful. Its architecture is simple, not many instructions, no complicated interfaces. A very good piece of hardware to use for building a computer around.

Like any other 8 bit CPU, the 6502 interfaces with the rest of the world through an address bus, and a data bus. All the informations are received and transmitted on the data bus, and all other chips are driven with the address bus.


The typical footprint of the 6502 shows the Address lines A0~A15 and the Data lines D0~D7. Then there are other very important lines that in a real hardware matters, such as the Phi0,1,2 lines used by the internal clock, or the NMI and INT that tell the CPU to perform specific tasks when the external hardware trigs it.  Software emulators, like mine, does everything inside a program so it's not necessary to replicate all those lines.

The emulation of a CPU is not that difficult. Every CPU performs tasks that are called by specific codes. These codes or Instructions are stored in the memory. So the CPU reads sequentially the codes and executes the program made of these codes. So, like a list of tasks, it starts from a specific point, and then it reads the codes and performs the task associated to that codes. Very simple.

We could abstract this behaviour with the following pseudo code:

START:
   Read next instruction.
   What is the code of the instruction?
      001: Do task 001
      002: Do task 002
      ...
      nnn; Do task nnn
   Go back to START


Of course it is a bit more complex than this example, but the idea is very simple. So it's a question of reading data from a memory, and performing instructions according to the value of the code read.

What we see from the footprint of the 6502 is that the address can be a 16 bit word, something like 0x1234, and Data can be an 8 bit byte, 0x12. So data is a value that can assume values from 0 to 255, while the address can assume values from 0 to 65535. This CPU can read 256 types of codes or instructions, from 65536 (0 included) different places or locations. Thus we now remember something of the old Commodore 64 :)

64 

It meant 64 Kbytes: 65536 / 1024 = 64

The Commodore 64 was sold saying that it had 64 KBytes of memory available, COOL, but not really true ;) Actually the 6502 CPU could handle 65536 locations of memory at startup but in the hardware the memory space is subdivided in different sections dedicated to different areas. So the real available memory to the user was less than 64KBytes.

Usually these kind of computers had a built in programming language, and several built in functionalities that were stored in  the memory space as Read Only Memory, or ROM. The real accessible memory, the Random Access Memory, or RAM, was reduced to 48, 32 or less KBytes.

What we need for our emulator is a program that reads and executes instructions in sequence from a ROM memory, and reads or stores data from/into a RAM memory :) In our emulator we don't have external memory chips so we will use the memory available in the microcontroller present in the board we are using.  I will discuss this later.