This commit is contained in:
Miloslav Ciz 2025-02-21 19:30:36 +01:00
parent 580a061146
commit d8966a5bab
20 changed files with 1933 additions and 1891 deletions

18
cpu.md
View file

@ -2,21 +2,21 @@
WORK IN PROGRESS
Central processing unit (CPU, often just *processor*) is the main, most central part of a [computer](computer.md), the one that performs the computation by following the instructions of the main program; CPU can be seen as the computer's brain. It stands at the center of the computer design -- other parts, such as the main [memory](ram.md), [hard disk](hdd.md) and [input/output](io.md) devices like keyboard and monitor are present to serve the CPU, CPU is at the top and issues commands to everyone else. A CPU is normally composed of [ALU](alu.md) (arithmetic logic unit, the circuit performing calculations), CU ([control unit](control_unit.md), the circuit that directs the CPU's operation), a relatively small amount of memory (e.g. its registers, temporary buffers and [cache](cache.md), the main [RAM](ram.md) memory is NOT part of a CPU!) and possibly some other parts. A specific model of CPU is characterized by its [instruction set](isa.md) (ISA, e.g. [x86](x86.md) or [Arm](arm.md), which we mostly divide into [CISC](cisc.md) and [RISC](risc.md)), which determines the [machine code](machine_code.md) it will understand, then its [transistor](transistor.md) count (nowadays billions), operation [frequency](frequency.md) or **clock rate** (defining how many instructions per second it can execute, nowadays typically billions; the frequency can also be increased with [overclocking](overclocking.md)), number of cores (determining how many programs it can run in parallel) and also other parameters and "features" such as amount of cache memory, possible operation modes etcetc. We also often associate the CPU with some **number of [bits](bit.md)** (called e.g. *[word](word.md) size*) that's often connected to the data [bus](bus.md) width and the CPU's native integer size, i.e. for example a 16 bit CPU will likely have 16 bit integer registers, it will see the memory as a sequence of 16 bit words etc. (note the CPU can still do higher bit operations but they'll typically have to be emulated so they'll be slower, will take more instructions etc.) -- nowadays most mainstream CPUs are 64 bit (to allow ungodly amounts of RAM), but 32 or even 16 and 8 bits is usually enough for [good programs](lrs.md). CPU in form of a single small integrated circuit is called *microprocessor*. CPU is not to be confused with [MCU](mcu.md), a small single board computer which is composed of a CPU and other parts.
Central processing unit (CPU, often just *processor*) is the main central part of a [computer](computer.md), one that carries out computation by following instructions of the main [program](program.md), therefore it's colloquially likened to the computer's "brain". CPU stands at the center of computer design because other parts (such as the main [memory](ram.md), [hard disk](hdd.md) and [input/output](io.md) devices like keyboard and monitor) are present to serve the CPU, their master. CPU is normally composed of [ALU](alu.md) (arithmetic logic unit, the circuit performing calculations), CU ([control unit](control_unit.md), the circuit that directs the CPU's operation), a relatively small amount of memory (e.g. its registers, temporary buffers and [cache](cache.md), the main [RAM](ram.md) memory is NOT part of a CPU!) and possibly also other parts. A specific model of CPU is characterized by its [instruction set](isa.md) (ISA, e.g. [x86](x86.md) or [Arm](arm.md), which we mostly divide into [CISC](cisc.md) and [RISC](risc.md)) which subsequently determines the [machine code](machine_code.md) it will understand, then by its [transistor](transistor.md) count (nowadays billions), operation [frequency](frequency.md) or **clock rate** (defining how many instructions per second it executes, nowadays typically billions; the frequency can also be increased with [overclocking](overclocking.md)), number of cores (determining how many programs it can run in parallel) and also other parameters and "features" such as amount of [cache](cache.md) memory, possible operation modes etcetc. Very commonly we also associate a CPU with a **number of [bits](bit.md)** (called *[word](word.md) size* or something similar) that's often connected to the data [bus](bus.md) width and the CPU's native integer size, i.e. for example a 16 bit CPU will likely consist of 16 bit integer registers, it will see the memory as a sequence of 16 bit words, its memory addresses may be limited to 16 bits etc. (note that the CPU can still handle even wider words by emulating them with the native words, but this will suffer performance penalties) -- nowadays most mainstream CPUs are 64 bit (to allow ungodly amounts of RAM), but 32 or even 16 and 8 bits is usually enough for [good programs](lrs.md). CPU in form of a single small integrated circuit is called *microprocessor*. CPU is not to be [confused](often_confused.md) with [MCU](mcu.md), a small single board computer which is composed of a CPU and other parts.
CPU is meant for **general purpose computations**, i.e. it can execute anything reasonably fast but for some tasks, e.g. processing HD video, won't reach near optimum speed, which is why other specialized processing units such as [GPU](gpu.md)s (graphics processing unit) and sound cards exist. As a general [algorithm](algorithm.md) executing unit CPU is made for executing **linear** programs, i.e. a series of instructions that go one after another; even though CPUs nowadays typically have multiple cores thanks to which they can run several linear programs in parallel, their level of parallelism is still low, not nearly as great as that of a GPU for example. However CPUs are [good enough](good_enough.md) for most things and they are extremely fast nowadays, so a [suckless](suckless.md)/[LRS](lrs.md) program will likely choose to only rely on CPU, knowing CPU will be present in any computer and so that our program will be [portable](portability.md).
CPU is meant to perform **general purpose computation**, i.e. it can execute anything reasonably fast but won't reach near optimum speed at certain specialized tasks (e.g. processing HD video or [rendering 3D graphics](3d_rendering.md)), which is why other specialized processing units such as [GPU](gpu.md)s (graphics processing unit) and sound cards exist. Because CPU is a general [algorithm](algorithm.md) executing unit, it is made for running **linear** programs, i.e. a series of instructions that go one after another; even though today CPUs more often than not sport multiple cores and therefore the ability to run several linear programs in parallel, their level of parallelism is still low, not nearly in the same league as a GPU for example. CPUs are nonetheless [good enough](good_enough.md) for most tasks and nowadays reach astronomical speeds anyway, so a [suckless](suckless.md)/[LRS](lrs.md) program will likely choose to only rely on CPU, knowing it's safe to assume presence of this most essential part of a computer, and by that our program becomes more [portable](portability.md) and [future proof](future_proof.md).
Designs of CPUs differ, some may aim for very high performance while other ones may prefer low power consumption or low transistor count -- remember, a more complex CPU will require more [transistors](transistor.md) and will be more expensive! Of course it will also be harder to design, debug etc., so it may be better to [keep it simple](kiss.md) when designing a CPU. For this reason many CPUs, e.g. those in [embedded](embedded.md) [microcontrollers](mcu.md), intentionally lack cache, [microcode](microcode.md), multiple cores or even a complex instruction pipeline.
Designs of CPUs differ, some may aim to maximize performance while others prefer lower power consumption or low transistor count -- remember, a more complex CPU is more expensive because it requires more [transistors](transistor.md)! Of course it will also be harder to design, [debug](debugging.md) etc., so it may be better to [keep it simple](kiss.md) when designing a CPU. For this reason many CPUs, e.g. those in [embedded](embedded.md) [microcontrollers](mcu.md), intentionally lack cache, [microcode](microcode.md), multiple cores or even a complex instruction pipeline. Space technology for instance highly prefers reliability before performance.
**WATCH OUT**: [modern](modern.md) mainstream CPUs (i.e. basically the desktop ones, soon probably mobile ones too) are [shit](shit.md), they are hugely [consumerist](consumerism.md), [bloated](bloat.md) (they literally include shit like [GPU](gpu.md)s and whole [operating systems](os.md), e.g. Intel's [ME](me.md) runs [Minix](minix.md)) and have built-in antifeatures such as [backdoor](backdoor.md)s (post 2010 basically all Intel and AMD CPUs, see Intel [Management Engine](me.md) and AMD [PSP](psp.md)) that can't be disabled and that allow remote infiltration of your computer by the CPU manufacturer (on hardware level, no matter what operating system you run). You are much better off using a simple CPU if you can ([older](old.md), [embedded](embedded.md) etc.).
**WATCH OUT**: [modern](modern.md) mainstream CPUs (i.e. basically the ones in desktops and spyphones) are [shit](shit.md), they are hugely [consumerist](consumerism.md), [bloated](bloat.md) (they literally include shit like [GPU](gpu.md)s and whole [operating systems](os.md), e.g. Intel's [ME](me.md) runs [Minix](minix.md)) and have built-in antifeatures such as [backdoor](backdoor.md)s (post 2010 basically all Intel and AMD CPUs, see Intel [Management Engine](me.md) and AMD [PSP](psp.md)) that can't be disabled and that allow remote infiltration of your computer by the CPU manufacturer (on hardware level, no matter what operating system you run). You are much better off using a simple CPU if you can ([older](old.md), [embedded](embedded.md) etc.).
## Details
TODO: diagrams, modes, transistor count history ...
Let's take a look at how a typical CPU works. Remember that anything may differ between CPUs, you can think of doing things differently and many real world CPUs do. Also we may simplify some things here, real world CPUs are complicated as hell.
Let's take a look at how our average CPU operates. Indeed the techno world is diverse and so we mustn't forget nothing's set in [stone](rock.md), CPUs differ in many ways. We may also simplify some concepts a bit, real world CPUs are complicated as hell.
**What does a CPU really do?** Basically it just reads instructions from the memory (depending on specific computer architecture this may be [RAM](ram.md) or [ROM](rom.md)) and does what they say -- these instructions are super simple, often things like "add two numbers", "write a number to memory" and so on. The instructions themselves are just [binary](binary.md) data in memory and their format depends on each CPU, or its **[instruction set](isa.md)** (basically a very low level language it understands) -- each CPU, or rather a CPU family, may generally have a different instruction set, so a program in one instruction set can't be executed by a CPU that doesn't understand this instruction set. The whole binary program for the CPU is called **[machine code](machine_code.md)** and machine code corresponds to **[assembly](assembly.md) language** (basically a textual representation of the machine code, for better readability by humans) of the CPU (or better said its instruction set). So a CPU can be seen as a hardware [interpreter](interpreter.md) of specific machine code, machine code depends on the instruction set and programmer can create machine code by writing a program in assembly language (which is different for each instruction set) and then using an assembler to translate the program to machine code. Nowadays mostly two instruction sets are used: [x86](x86.md) and [Arm](arm.md), but there are also other ones, AND it's still not so simple because each instruction set gets some kind of updates and/or has some extensions that may or may not be supported by a specific CPU, so it's a bit messy. For example [IA-32](ia_32.md) and [x86_64](x86_64.md) are two different versions of the x86 ISA, one 32 bit and one 64 bit.
Firstly then the most pressing question: **what is it that a CPU really does?** Basically it just reads instructions from the memory (depending on specific computer architecture this may be [RAM](ram.md) or [ROM](rom.md)) and does what they say -- these instructions are super simple, often commands like "add two numbers", "write a number to memory" and so on. The instructions themselves are just [binary](binary.md) data in memory and their format depends on each CPU, or more precisely its **[instruction set](isa.md)** (basically a very low level language it understands) -- each CPU, or rather a CPU family, may generally have a different instruction set, so a program in one instruction set can't be executed by a CPU that doesn't understand this instruction set. The whole binary program for the CPU is called **[machine code](machine_code.md)** and machine code corresponds to **[assembly](assembly.md) language** (basically a textual representation of the machine code, for better readability by humans) of the CPU (or better said its instruction set). So a CPU can be seen as a hardware [interpreter](interpreter.md) of specific machine code, machine code depends on the instruction set and programmer can create machine code by writing a program in assembly language (which is different for each instruction set) and then using an assembler to translate the program to machine code. Nowadays mostly two instruction sets are used: [x86](x86.md) and [Arm](arm.md), but there are also other ones, AND it's still not so simple because each instruction set gets some kind of updates and/or has some extensions that may or may not be supported by a specific CPU, so it's a bit messy. For example [IA-32](ia_32.md) and [x86_64](x86_64.md) are two different versions of the x86 ISA, one 32 bit and one 64 bit.
The CPU has some internal state (we can see it as a [state machine](finite_state_machine.md)), i.e. it has a few internal variables, called **[registers](register.md)**; these are NOT variables in RAM but rather in the CPU itself, there is only a few of them (there may be let's say 32) but they are extremely fast. What exactly these registers are, what they are called, how many [bits](bit.md) they can hold and what their purpose is depends again on the instruction set architecture. However there are usually a few special registers, notably the **program counter** which holds the address of the currently executed instruction. After executing an instruction program counter is incremented so that in the nest step the next instruction will be executed, AND we can also modify program counter (sometimes directly, sometimes by specialized instructions) to jump between instruction to implement branching, loops, function calls etc.
@ -38,7 +38,7 @@ Mainstream consoomer CPUs nowadays have multiple **[cores](core.md)** so that ea
**[Interrupts](interrupt.md)** are an important concept for the CPU and for low level programming, they play a role e.g. in saving power -- high level programmers often don't know what interrupts are, to those interrupts can be likened to "event [callbacks](callback.md)". An interrupt happens on some kind of even, for example when a key is pressed, when timer ticks, when error occurred etc. (An interrupt can also be raised by the CPU itself, this is how operating system [syscalls](syscall.md) are often implemented). What kinds of interrupts there are depends on each CPU architecture (consult your datasheet) and one can usually configure which interrupts to enable and which "callbacks" to use for them -- this is often done through so called **[vector](vector.md) table**, a special area in memory that records addresses ("vectors") of routines (functions/subprograms) to be called on specified interrupts. When interrupt happens, the current program execution is paused and the CPU automatically jumps to the subroutine for handling the interrupt -- after returning from the subroutine the main program execution continues. Interrupts are contrasted with **[polling](polling.md)**, i.e. manually checking some state and handling things as part of the main program, e.g. executing an infinite loop in which we repeatedly check keyboard state until some key is pressed. However polling is inefficient, it wastes power by constantly performing computation just by waiting -- interrupts on the other hand are a hard wired functionality that just performs a task when it happens without any overhead of polling. Furthermore interrupts can make programming easier (you save many condition checks and memory reads) and mainly **interrupts allow CPU to go into sleep mode** and so save a lot of power. When a CPU doesn't have any computation to do, it can stop itself and go into waiting state, not executing any instructions -- however interrupts still work and when something happens, the CPU jumps back in to work. This is typically what the `sleep`/`wait` function in your programming language does -- it puts the CPU to sleep and sets a timer interrupt to wake up after given amount of time. As a programmer you should know that you should call this sleep/wait function in your main program loop to relieve the CPU -- if you don't, you will notice the **CPU utilization** (amount of time it is performing computations) will go to 100%, it will heat up, your computer starts spinning the fans and be noisy because you don't let it rest.
Frequently there are several **modes** of operation in a CPU which is typically meant for operating systems -- there will usually be some kind of privileged mode in which the CPU can do whatever it wants (this is the mode for the OS kernel) and a restricted mode in which there are restrictions, e.g. on which areas of memory can be accessed or which instructions can be used (this will be used for user program). Thanks to this a user program won't be able to crash the operating system, it will at worst crash itself. Most notably x86 CPUs have the *real mode* (addresses correspond to real, physical addresses) and *protected mode* (memory is [virtualized](virtual_memory.md), protected, addresses don't generally correspond to physical addresses).
Frequently there are several **modes** of operation in a CPU which is typically meant for [operating systems](os.md) -- there will usually be some kind of privileged mode in which the CPU can do whatever it wants (this is the mode for the OS kernel) and a restricted mode in which there are "restrictions", e.g. on which areas of memory can be accessed or which instructions can be used (this will be used for user program). Thanks to this a user program won't be able to crash the operating system, it will at worst crash itself. Most notably x86 CPUs have the *real mode* (addresses correspond to real, physical addresses) and *protected mode* (memory is [virtualized](virtual_memory.md), protected, addresses don't generally correspond to physical addresses).
A CPU may also have integrated some **[coprocessors](coprocessor.md)**, though sometimes coprocessors are really a separate chip. Coprocessors that may be inside the CPU include e.g. the FPU ([floating point](float.md) unit) or encryption coprocessor. Again, this will make the CPU a lot more expensive.
@ -87,5 +87,9 @@ TODO: add more, mark CPUs with ME, add features like MMX, FPU, ...
## See Also
- [GPU](gpu.md)
- [PPU](ppu.md)
- [FPU](fpu.md)
- [MCU](mcu.md)
- [ALU](alu.md)
- [WPU](wpu.md) (weird processing unit)
- [computer](computer.md)