首页/文章/ 详情

CPU core原理-01

9月前浏览7710

1CPU core原理

1.1CPU与SOC的区别

传统意义上面的CPU是指运算执行单元,不包含外部设备的接口,也就是一个CPU core,外部接口非常简单,仅仅是一个高速总线和一些异常(中断)接口,内部集成了cache/MMU等硬件模块。

SOC是一个core并集成了若干外部设备接口。通常包含内存控制器,串口,硬盘控制器,localbus控制器等等。这些集 合在一起就是一个SOC。

广义上的CPU与SOC是完全等同的。

我们平时用的大部份PowerPC其实都是一个SOC,但也有不是的,比如7457,这个芯片就只是一个CPU core,外部通过桥片实现和其它控制器,与intel的CPU类似,intel比较老的CPU也仅仅是一个core,内存控制器等都是在南北桥上面实现的。

本文的主要工作就是集中在狭义的CPU,也就是core上面。


1.2CPU分类

8位/16位/32位机是什么意思?

每一个core运行的基础就是指令集,指令的长度就是core的位数。

8位core最多有256条指令,16位最多的64K条指令,32位则是4G

但实际上,各种core能用的指令的总个数远少于上面的数字。

我们以powerPC的add指令为例说明


Bits

Value

说明

0-5

31

Bit0-5,22-30共同组成指令

6-10

RT

目的寄存器

11-15

RA

寄存器A的ID

16-20

RB

寄存器B的ID

21

OE

Overflow exception,运算溢出时是否触发异常(中断)。

22-30

266

Bit0-5,22-30共同组成指令

31

Rc

用于比较的控制位,在这个例子中无视

对于一个加法,A + B = C,有三个被 操作的数,在一个指令里面需要说明要操作哪些数。也就是对于这种有三个操作数的指令,操作数本身就占用了15bit,那么用于区分指令的bit远没有达到32bit.

实际上面,不带操作对向的指应是非常少的,只有少量的特殊指令是无操作数的。

因为硬件设计这么做最简单,事实上面是有的CPU支持可变长超长指令的,但PowerPC是不支持的

但这从core设计的角度上来讲,就需要考虑更多的情况,例如预取,cache等问题

而定长的指令是最简单的。


1.2.1CPU中的cache


数据和指令的差别。

数据和指令在PowerPC上面是分为两种cache的,data cache和instruction cache.

为什么这么设计?如果两者混合不是利用率更高么?

比如我们一般把数据缓冲关掉,运行效率也就低几倍,但指令缓冲一关,速度慢的就是几十倍。所以分开设计更容易保证代码cache的命中率。

代码被CPU正常获取是每一个指令周期有效的必要条件,数据cache的重要性不如代码cache。


1.2.2CPU的数据长度

CPU的数据的长度是多变的,PowerPC的load(将外部数据装载入寄存器)和store(将寄存器装入外部存储器)的指令有8bit/16bit/32bit以及64bit(浮点指令)


1.3汇编简要说明

因为指令是32位的,所以对于指令而言,是不可能用一条指令做到从某个地址把某个数据

int a, b, c

func()

{

a=b+c;

}

a,b,c是三个全局变量,对于一个程序而言,这三个变量是存放在三个不同的地址上面的。

c语言a=b+c只有一句,但对于汇编而言是不可能一句话搞定的。为什么?

因为一条指令只有32bit,对于32位的操作系统而言,一个地址的编码就是32bit的,怎么可能通过一个指令完成所有的操作呢?

所以实际工作的代码是这样的

ADDR_a, ADDR_b, ADDR_c分别是a/b/c三个变量在内存中的地址,这是一个常量。因为链接后一定会给a/b/c三个变量分配一个固定的地址。

Reg0 = ADDR_a    //现在reg0里面就放了ADDR_a这个地址

reg1 = load(reg0) //将reg0指向的地址的数据装到reg1中,reg1也就是a的值

Reg0 = ADDR_b     //现在reg0里面就放了ADDR_b这个地址

Reg2 = load(reg0) //将reg0指向的地址的数据装到reg2中,reg2也就是b的值

Reg2 = reg1 + reg2 //计算reg1 + reg2的内容

reg 0 = ADDR_c

store(reg2, reg0)  //将reg2的内容存到reg0的地址当中。

仅仅是一个全局变量的加法,就涉及到这么多的指令,这上面是有几句话是用一条代码搞不定的。那就是regx = ADDR_x,因为ADDR_x是32bit的

实际的代码是这么写的

(LO)regx = LO(ADDR_a),低16位装到regx的低16bit中

(HI)regx = HI(ADDR_a),高16位装到regx的高16bit中


仅仅是c代码中最简单的一个加法,就需要好几条指令才能完成。


这就是代码优化存在的意思,但实际上面,由于代码是可以并行处理的。运行的速度会比这快。并不代表做这么一个加法就需要十几个指令周期,而且编译器本身也会做些优化。否则C语言写的代码的运行效率太低了。


1.3.1代码/指令的存放

刚才我们看到了ADDR_x这些地址,ADDR_x指向的地址是怎么分配的呢?实际运行的那些指令又是如何存放的呢?


代码段的概念和分配

首先我们需要了解CPU的发展历史

最初的CPU的ram是非常小的。但是小内存也是可以做很多事的。很多单片机只有512B的内存,但依然可以做很多事,比较外面挂个LCD做做显示,AD信号采集。

对于大多数程序,运行过程中少量的RAM就够用了。但是代码不行,比如我们写了1万句a=b+c

这个代码只需要12B的ram(每个变量是32位,4Bytes)和几十上百K的代码。

代码的大小远远大于数据。而且代码有一个特性,通常代码是不需要修改的。

所以老的CPU和单片机,代码都是放在ROM上面的,只有通过仿真器或ISP等烧写工具才能更新代码。而数据则不同,数据是要随时改变的,必须放到RAM当中。这怎么办?

所有最早的CPU开发者规定了几个段,必要的有代码段和数据段。通常这两者是不会混杂在一起的,分在不同的地址空间当中。像单片机上面,代码段和数据段就离的很远,前者在ROM空间当中,后者在RAM空间当中。

core从代码段获取代码,从数据段获取数据。不管怎么讲,对core而言都是地址空间中的不同的地址。所以代码段就在RAM当中也是可行的。如何部署完全是根据不同的CPU的特性和要求来的。比如我们的kboot,代码段就是放在flash当中的。而数据段是放到SRAM当中。而vxworks的代码段和数据段都放在内存当中。

PowrPC的RAM很大,放的下代码,所以vxworks代码段和地址段都在内存当中有着更好的运行效率。


至于其它的什么.bss段,还有.debug段,就无所谓了,都是因为某些原因创建的。实际上面对于CPU运行,有了代码段和数据段就可以工作了。



来源:Trent带你学硬件
UG芯片CST控制
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2024-03-01
最近编辑:9月前
Trent硬件设计
签名征集中
获赞 13粉丝 9文章 46课程 0
点赞
收藏
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈