中国自主基础软件技术与应用丛书
书名:龙芯之光:自主可控处理器设计解析
ISBN:978-7-115-67646-7
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
主 编 余 菲
副 主 编 刘永新 温 泉 蔡致立
责任编辑 谢晓芳
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
本书基于LoongArch讲解SoC(System on Chip,单片系统)逻辑设计、逻辑综合、可测试性设计、物理设计和签核等。本书既有理论知识的拆解,又有具体设计实践的操作,对读者掌握处理器的设计很有帮助。
本书适合本科院校和高职院校集成电路专业的师生阅读,也可作为芯片工程师的参考书。
改革开放以来,我国信息产业主要建立在西方主导的两个信息技术体系之上。一个是x86体系,主要代表是Intel的CPU和微软的操作系统组合;另一个是ARM体系,主要代表是ARM的CPU和Android操作系统的组合。我国信息产业的根本出路是摆脱传统生产力的发展路径,构建独立于x86架构和ARM架构的新型信息技术体系与产业生态。其中,人才生态是自主信息技术体系和产业生态的根本。在我国的信息化教育中,应培养中小学生从Windows平台转移到国产教育平台。高职院校计算机专业主要基于国外技术平台教学生如何“用”计算机,不教学生怎么造计算机。这一现象也应该改变,培养计算机专业学生的立足点应该从如何“用计算机”向如何“造计算机”转移。
深圳职业技术大学的师生基于“百芯计划”开发的丽湖霸下BX2400 SoC正是上述理念的生动写照。作为龙芯中科技术股份有限公司向中国高校开放的LoongArch(龙芯架构)芯片实现资料的首批实践成果,丽湖霸下BX2400的诞生不仅展现了教学投片的技术可行性,还印证了产学研协同创新的巨大潜力。近年来,国内百余所高校基于LoongArch开展教学实践,从指令集理论到投片验证的全流程探索,让芯片设计从实验室走向产业的需求场景。这标志着中国集成电路教育正从“跟随式学习”迈向“自主创新培养”的新阶段。
本书基于LoongArch探讨芯片设计过程,对我国自主信息技术体系和产业生态建设的人才培养具有重要意义。本书以“全流程工程实践”为主线,系统梳理了LoongArch SoC设计的完整技术路径。
本书具有如下特色。
• 在架构方面,深度剖析LoongArch指令集的底层逻辑与特权机制。
• 在工具链方面,基于龙芯中科技术股份有限公司开放的IP核、工艺库及验证平台,提供标准化工程模板。
• 在案例方面,以丽湖霸下BX2400的时序收敛为切入点,演示教学资源约束下的投片实现。
本书在如下方面不断融合。
• 理论与实践:提供原理阐述与代码实现,同步提供测试向量与验证环境。
• 基础与进阶:覆盖指令集基础到时钟树综合、寄生参数提取等高阶内容。
• 自主与开放:以LoongArch为核心,兼容主流EDA工具链,满足多样化教学需求。
本书基于工业级流程进行讲述,可确保教学成果与产业需求无缝衔接;通过模块化案例拆分与标准化约束模板,降低实践门槛,提升工程训练效率。
本书聚焦“可落地、可复用、可扩展”的教学目标。通过系统学习本书,读者将掌握:
• LoongArch指令集的硬件实现方法;
• 基于标准单元库的SoC设计全流程;
• 工业级EDA工具链的协同使用方法;
• 芯片开发中的关键工程优化技巧。
期待本书能成为高校师生探索自主芯片设计的实用指南,助力更多青年学子在真实工程场景中成长,为中国集成电路行业的人才储备与技术突破持续注入动能。
胡伟武
2025年3月14日
在信息技术飞速发展的当下,自主可控的指令集架构成为保障信息安全的关键。LoongArch是龙芯中科技术股份有限公司完全自主研发的成果,从顶层规划到指令编码,均实现了独立设计,不依赖x86、ARM等传统架构。2021年,LoongArch下的中断模型被纳入ACPI(Advanced Configuration and Power Interface,高级配置和电源接口)规范,LoongArch成为继x86、ARM之后,第三种获得国际标准支持的CPU架构。这种架构融合了x86和ARM的主要特性,支持龙芯二进制翻译(Loongson Binary Translation,LBT)扩展,能够高效兼容二者的应用生态。这不仅可降低迁移成本,还不用支付架构授权费用,从源头保障信息安全,尤其适用于政务和能源等关键领域。
基于LoongArch的处理器已在电子政务、工业自动化等领域大量替代传统x86、ARM芯片,展现了其在实际应用中的强大潜力。
本书以基于LoongArch CPU内核的芯片设计为核心内容,通过丽湖霸下BX2400的开发过程,全面解析SoC设计的全过程。内容涵盖LoongArch的SoC逻辑设计、逻辑综合、可测试性设计、物理设计和签核,展现SoC从概念到投片的全过程。
目前,国内针对大规模数字集成电路设计的教材相对较少,本书具有较高的出版价值。
在学习本书之前,读者需要具备一定的基础,包括数字逻辑与数字电路基础、集成电路设计基本方法和流程的基础,以及Verilog语言和可编程逻辑器件设计的基础。在本书中,CPU内核的设计采用了龙芯中科技术股份有限公司的IP(Intellectual Property,知识产权),读者需要得到龙芯中科技术股份有限公司的授权才能使用该IP进行投片。
本书由深圳职业技术大学、龙芯中科技术股份有限公司和深圳芯火平台共同策划,由余菲担任主编,规划本书的整体结构,并审阅全书;由刘永新、温泉和蔡致立担任副主编,邀请高校教师、行业工程师共同对内容进行汇编、整理,并完成相关实践操作。希望本书能为集成电路设计领域的工程师、研究人员及相关专业师生提供参考,助力我国自主可控集成电路技术的发展与人才培养。
由于作者水平有限,书中难免存在不足之处,恳请读者批评指正。
作者
2025年3月1日
LoongArch是我国自主研发的核心技术,打破了国外技术(如ARM和x86)的垄断,实现了真正的本土研发和制造。LoongArch是在中国科学院计算技术研究所的支持下研发的,具有自主性、可定制性和良好的兼容性,能够满足国产芯片在高性能计算、嵌入式系统和工业控制等领域的需求。龙芯的独立指令集架构降低了我国对外国技术的依赖性,确保了国内的信息安全,避免了受限于外部技术的“卡脖子”问题。这对我国发展自主产业链和提高信息安全水平具有重要的意义。
单片系统(System on Chip,SoC)也称片上系统,指一个有专用目标的集成电路。其中包含完整的系统并嵌入软件的全部内容。同时,它也是一种技术,用于实现从确定系统功能开始到软硬件划分,再到完成设计的整个过程。根据中央处理器的复杂程度,通常有微控制器(Microcontroller Unit,MCU)/嵌入式处理器、移动处理器、通用处理器等类型。SoC包括中央处理器(Central Processing Unit,CPU)、总线、内存、定时器、外围接口等。
中央处理器是SoC负责读取指令、对指令译码并执行指令的核心部件。CPU的功能主要为处理指令、执行操作、控制时间、处理数据。在微处理器体系结构中,CPU是对微处理器的所有硬件资源进行控制、执行通用运算的核心硬件单元。微处理器系统中所有软件层的操作最终将通过指令集映射到CPU的操作。
对于CPU而言,影响性能的指标主要有CPU主频、CPU位宽、CPU缓存和CPU内核数等。CPU主频是指CPU的时钟频率,它直接决定了CPU的性能。CPU位宽指处理器一次能够处理的数据位数。通常情况下,CPU的位宽越高,CPU的运算速度就会越快。CPU缓存是在CPU内部用于存储指令和数据的存储空间。CPU内核数决定单位时间内CPU并行处理任务的能力。
通常来讲,CPU在结构上大致分为运算器、控制器和高速缓存等。
运算器是负责执行各种算术计算和逻辑操作的部件。运算器包括算术逻辑部件(Arithmetic and Logic Unit,ALU)、移位部件、浮点处理单元(Floating-Point Processing Unit,FPU)、向量运算部件、寄存器等。其中,复杂运算(如乘、除、开方及浮点运算)可用程序实现或由运算器实现。寄存器既可用于保存数据,也可用于保存地址。运算器还可用于设置条件码寄存器等专用寄存器。条件码寄存器用于保存当前运算结果的状态,如运算结果是正数、负数还是零,是否溢出等。
运算器经历了从简单到复杂的过程。最初的运算器只能完成简单的定点加减和基本逻辑运算,复杂运算(如乘、除)通过加减、移位指令构成的数学库完成;后来出现了硬件定点乘法器和除法器。在早期的微处理器中,浮点运算器以协处理器(如Intel 8087协处理器)的形式出现在计算机中,可以完成二进制浮点数的加、减、乘、除等运算,现代的通用微处理器则普遍包含完整的浮点运算部件。从20世纪90年代开始,微处理器中出现了单指令流多数据流(Single-Instruction Stream Multiple-Data Stream,SIMD)的向量运算器,部分处理器还实现了超越函数的硬件运算单元,支持正弦、余弦、指数和对数的计算。部分用于处理银行业务的计算机(如IBM Power系列)还实现了十进制定点数、浮点数的运算器。
随着晶体管集成度的不断提升,CPU中集成的运算器的数量持续增加。通常将具有相近属性的一类运算器组织在一起,构成一个运算单元。不同的CPU有不同的运算单元。有的CPU中,每个单元大而全;有的CPU中,每个单元的功能相对单一。CPU中包含的运算单元数量也从早期的单个逐渐增加到多个。由于运算单元都需要从寄存器中读取操作数,并把结果写回寄存器,因此CPU中运算单元的个数主要受限于寄存器堆的读写端口个数。运算单元一般按照定点、浮点、访存、向量等类型组织,也有混合的,如SIMD部件既能完成定点运算也能完成浮点运算,定点部件也可以完成访存地址计算等。
控制器是CPU中控制指令执行的核心部件。它规定指令的执行顺序,生成控制指令,控制运算器、存储器和其他部件的运行,并负责处理紧急情况产生的中断。控制器包含程序计数器和指令寄存器等。程序计数器存放当前执行的指令的地址,指令寄存器存放当前正在执行的指令。指令通过译码产生控制信号,用于控制运算器、存储器、I/O设备的工作以及后续指令的获取。为了获得高指令吞吐率,可以采用指令重叠执行的流水线技术,以及同时执行多条指令的超标量技术。当遇到执行时间较长或不具备条件的指令时,提前执行具备条件的后续指令(称为乱序执行)可以提高流水线效率。控制器还产生一定频率的时钟脉冲,用于计算机各组成部分的同步。
由于控制器和运算器紧密耦合,因此通常把控制器和运算器集成在一起,称为中央处理器,即CPU。随着芯片集成度的不断提高,除了控制器和运算器外,现代CPU常常还集成了其他部件,如高速缓存(cache)部件、内存控制器等。
计算机执行指令的一般过程如下。
从存储器取指令并对取回的指令进行译码,从存储器或寄存器读取执行指令所需要的操作数,执行指令,把执行结果写回存储器或寄存器。上述过程称为一个指令周期。计算机不断重复指令周期,直到完成程序的执行。关于体系结构的一个永恒主题就是不断缩短上述指令周期,从而提高计算机运行程序的效率。控制器对提高指令执行效率起着至关重要的作用。
现代CPU的控制器都通过指令流水线技术提高指令执行效率。指令流水线把一条指令的执行划分为若干阶段(如取指、译码、执行、访存、写回阶段)来减轻每个时钟周期的工作量,从而提高主频;同时允许多条指令的不同阶段重叠执行,以实现并行处理(如一条指令处于执行阶段,另一条指令处于译码阶段)。虽然同一条指令的执行时间没有变短,但是CPU在单位时间内执行的指令数增加了。
计算机中的取指部件、运算部件、访存部件都在流水线的调度下执行指令规定的具体操作。运算部件的个数和延时,访存部件的存储层次、容量和带宽,以及取指部件的转移猜测算法等是决定微架构性能的重要因素。
高速缓存是一种在主存储器和CPU之间,对程序员透明的快速小容量存储器,可用于提高存储器的有效传输率。高速缓存的主要作用是减少CPU访问内存的次数,从而提高系统的整体性能。高速缓存根据存储需求和性能优化目标分为指令高速缓存(Instruction Cache,I-Cache)和数据高速缓存(Data Cache,D-Cache),这是两种不同类型的高速缓存。
指令高速缓存主要用于存储程序指令,即CPU执行的操作代码。当一个程序运行时,它的指令需要被频繁访问,而直接从主存(内存或磁盘)中读取这些指令会非常慢。为了提高执行速度,CPU会将这些被频繁访问的指令存储在指令高速缓存中。
指令高速缓存的特点如下。
• 采用顺序访问模式,因为程序通常按顺序执行指令。
• 容量较小,因为指令通常是固定的,不像数据那样多变。
• 当程序改变(例如,通过编译或在运行过程中修改)时,需要刷新或替换指令高速缓存中的内容。
• 数据高速缓存主要用于存储程序运行中需要频繁访问的数据。与指令高速缓存不同,数据高速缓存中的数据是可变的,并且经常根据程序的需要进行读写操作。
数据高速缓存的特点如下。
• 采用随机访问模式,因为程序可能会根据需要读取或写入任何数据。
• 容量通常比指令高速缓存的容量大(因为数据的多样性)。
• 当修改数据时,数据高速缓存需要相应地更新这些数据,以保证CPU操作的正确性。
在多核处理器中,保持指令高速缓存和数据高速缓存的一致性是一个挑战。例如,当一个内核修改了数据时,其他内核需要知道这个修改以确保它们读取的数据是最新的。这通常通过高速缓存一致性协议实现,确保所有内核看到的高速缓存状态是一致的。在现代计算机体系结构中,除了L1高速缓存、L2高速缓存和L3高速缓存外,还有更高级的高速缓存策略和设计,如用于加速虚拟地址到物理地址转换的变换先行缓冲器(Translation Lookahead Buffer,TLB)。
指令高速缓存和数据高速缓存是互补的,各自优化不同类型的访问模式。了解它们的区别与作用对于深入理解计算机体系结构和优化程序性能至关重要。通过合理配置和使用这些高速缓存,可以显著提高系统的整体性能。
CPU内部包含的多个部件往往是由不同的公司生产的。为了让这些部件组合在一起后可以正常工作,必须制定一套大家共同遵守的规格和协议,这就是总线(或者接口)。总线是嵌入式系统中各种功能部件(运算器、控制器、内存等)之间传送信息的公共通信干线,它由总线控制器和导线组成。总线从源部件传送信息到一个或多个目的部件,导线连接一个源部件与一个或多个目的部件。总线控制线路负责对信息进行选择判优、分开发送,避免多个部件同时发送信息的矛盾,对传送的信息进行定时,防止信息丢失等。
按照功能,总线可以分为数据总线、地址总线和控制总线。它们分别用来传输数据、地址和控制信号。
按照总线的传输格式,总线可以分为串行总线和并行总线。它们分别用来串行、并行地传输数据。
按照时序控制方式,总线可以分为同步总线和异步总线。同步总线所连接的各部件使用同一个时钟,在规定的时钟节拍进行规定的总线操作来完成部件之间的信息交换。异步总线所连接的各部件没有统一的时钟,部件之间通过信号握手的方式进行,总线的操作时序不固定。
按照功能,总线可以分为片内总线、系统总线、通信总线等。片内总线指CPU内部的总线,它是CPU内部控制器、运算逻辑单元、寄存器等模块之间的公共连接线。系统总线指CPU、主存、I/O等大部件之间的信息传输线,它把这些部件连接起来从而构成计算机或嵌入式系统。通信总线用于计算机或嵌入式系统之间或者计算机或嵌入式系统与其他系统之间的信息传送,通信总线也称为外部总线。
ARM公司为高性能嵌入式系统定义了高级微控制器总线架构(Advanced Microcontroller Bus Architecture,AMBA)片上总线协议。这个协议定义了一系列系统总线协议,如高级高性能总线(Advanced High-Performance Bus,AHB)协议、高级外围总线(Advanced Peripheral Bus,APB)协议、高级可扩展接口(Advanced eXtensible Interface,AXI)协议、AXI一致性扩展(AXI Coherency Extension,ACE)协议、高级系统总线(Advanced System Bus,ASB)协议。
内存的读写速度对计算机整体的性能影响重大。为了提升CPU的访存性能,现代通用CPU都将内存控制器与CPU集成在同一芯片内,以降低平均访存延时。内存一般采用同步动态随机存储器(Synchronous Dynamic Random Access Memory,SDRAM)实现。SDRAM是一种与CPU内核同步的动态随机存储器(Dynamic Random Access Memory,DRAM)。这种同步随机存储器比传统的DRAM能够更高效地运行。SDRAM可以用突发的方式传输数据序列,提高访问连续内存地址的效率。
DRAM的基本存储单元由一个金属-氧化物-半导体场效应晶体管(Metal-Oxide-Semiconductor Field-Effect Transistor,MOSFET)和一个电容组成。这种结构的设计充分利用了电容能够存储电荷的特性,以及MOSFET作为开关控制电荷存取的能力。
作为开关元件,MOSFET在DRAM中负责控制对电容的充放电操作。当MOSFET导通时,允许电流通过,从而改变电容上的电荷量;当MOSFET截止时,切断电流,保持电容上的电荷状态不变。
作为存储元件,电容用于存储代表数据位(0或1)的电荷。若电容中有电荷,代表“1”;若没有电荷,代表“0”。然而,由于电容存在漏电现象,电容上的电荷会随时间逐渐流失,因此DRAM需要定期刷新以维持数据的正确性。
定时器在计算机系统的运行和控制中发挥着至关重要的作用。其本质是使用精准的时钟,通过硬件实现定时功能。定时器的核心是计数器。
在一般的CPU中,定时器可分为常规定时器、专用定时器和内核定时器等。常规定时器主要完成基本定时、通用定时和高级定时等功能;专用定时器为独立看门狗、窗口看门狗、实时时钟、低功耗定时器等实现专用的定时功能;内核定时器用于为内核系统定时。
介质访问控制器是一个重要组件,负责协调各种通信介质(如以太网、WiFi等)和管理数据传输,在微处理器中的作用主要体现在数据链路层。介质访问控制器的主要职责如下。
• 数据封装和解封装:介质访问控制器负责将上层数据封装成帧,包括添加目标MAC(Medium Access Control,介质访问控制)地址、源MAC地址和数据包类型等信息。当接收到数据帧时,它会进行解封装,提取出上层需要的数据。
• 帧同步和错误检测:介质访问控制器在发送数据前会进行循环冗余校验,确保数据的完整性。在接收数据时,也会进行循环冗余校验,如果校验失败,则会丢弃该帧。
• 地址处理:介质访问控制器处理源MAC地址和目标MAC地址,确保数据包能够正确发送到目标设备。
• 流量控制:对流量进行控制,确保网络中的数据传输不会过于拥挤,维持网络的稳定运行。
介质访问控制器一般用在以太网接口,与CPU、介质访问控制器和物理层接口共同组成以太网电路接口。介质访问控制器与物理层之间的交互是通过媒体独立接口(Media Independent Interface,MII)或精简媒体独立接口(Reduced Media Independent Interface,RMII)进行的。介质访问控制器通过这些接口与物理层通信,实现数据的发送和接收。物理层定义了数据传送与接收所需要的电信号、光信号、线路状态、时钟基准、数据编码和电路等,并向数据链路层的设备提供标准接口。物理层主要负责将数字信号转换为适合在物理介质上传输的电信号或光信号,并进行信号的放大、整形等处理,同时在接收端将物理介质上的信号转换为数字信号。
如果在存储器和I/O设备之间开辟一条数据通道,专门用于数据传输,就可以将处理器从数据搬运中解放出来。这种方式就是直接存储器访问(Direct Memory Access,DMA)方式。DMA方式在存储器和外围设备之间开辟直接的数据传送通道,数据传送由专门的硬件来控制。控制DMA数据传送的硬件被称为DMA控制器。使用DMA方式进行传输的一般过程如下。
(1)CPU为DMA请求预先分配一段地址空间。
(2)CPU设置DMA控制器的参数。这些参数包括设备标识、数据传送的方向、内存中用于数据传送的源地址或目标地址、传输的字节数量等。
(3)DMA控制器进行数据传输。DMA控制器发起对内存和设备的读写操作,控制数据传输。DMA传输相当于用I/O设备直接读写内存。
(4)DMA控制器向CPU发起一个中断,通知CPU数据传送的结果,包括成功或者失败及错误信息等。
(5)CPU处理完本次DMA请求,可以开始处理新的DMA请求。
DMA方式对于存在大量数据传输的高速设备是一个很好的选择。硬盘、网络设备、显示设备等普遍采用DMA方式。DMA控制器的功能可以很简单,也可以很复杂。例如,DMA控制器可以仅支持对一段连续地址空间的读写,也可以支持对多段地址空间的读写以及执行其他的I/O操作。不同的I/O设备的DMA方式各不相同,因此现代的I/O设备大多会实现专用的DMA控制器,用于自身的数据传输。一个计算机系统中通常包含多个DMA控制器,如特定设备专用的串行高级技术总线附属(Serial Advanced Technology Attachment,SATA)接口DMA控制器、USB接口DMA控制器等,以及通用的DMA控制器(用于可编程的源地址与目标地址之间的数据传输)。
外围接口是(也称为外围设备接口和外部接口)SoC的重要组成部分,起到信息传输和存储的作用。外围接口一般包含外围控制器和接口电路。外围控制器负责接口协议的实现,接口电路完成与外围设备的互连。下面介绍SoC的常用外围接口。
通用异步接收发送设备(Universal Asynchronous Receiver/Transmitter,UART)接口是一种常用的串行通信接口,主要用于异步通信。UART接口通过供电线(VCC)、地线(GND)、数据发送(TX)端口和数据接收(RX)端口实现通信。其中,GND连接保证两设备共地,TX端口连接RX端口,实现数据传输。
在串行通信中,数据通过一条线路或一根导线逐位传输。在双向通信中,使用两根导线进行连续的串行数据传输。
根据应用和系统要求,串行通信需要的电路和导线较少,可降低实现成本。
UART接口基于异步串行通信。发送端将数据写入移位寄存器,然后发送数据帧,数据帧由起始位、数据位、奇偶校验位和停止位组成。接收端通过内部时钟信号控制,在每个时钟脉冲采样接收到的信号状态。UART使用缓冲区存储接收的数据,并向CPU报告新数据的可用性。
安全数字输入输出(Secure Digital Input/Output,SDIO)接口是一种基于SD卡技术的扩展接口标准,其本质是对原有安全数字(Secure Digital,SD)存储标准的扩展,主要用于实现设备间的高效数据传输和多功能外围设备连接。
传统SD接口仅用于存储卡的读写,而SDIO接口在物理兼容SD卡插槽的基础上,增加了对输入输出设备的支持,允许设备通过同一接口实现数据传输与功能扩展。SDIO接口兼容之前的SD卡协议,定义了多种命令(如CMD5、CMD52、CMD53)来支持SDIO卡的使用。
SDIO设备通常被划分为多个功能单元,每个功能单元可被看作一个独立的外围设备,具有自己的寄存器和配置选项,主机可以通过发送特定的命令来选择和控制不同的功能单元,实现多样化的功能扩展。
I2C(Inter-Integrated Circuit,集成电路间)总线是由Philips公司开发的一种双向二线制同步串行总线。I2C是由串行数据线(Serial Data Line,SDA)和串行时钟线(Serial Clock Line,SCL)构成的串行总线,可发送和接收数据,用于实现两个器件之间的数据传输。
I2C总线基于主-从架构。主设备负责启动数据传输并产生时钟信号,从设备则根据主设备的指令进行数据的发送或接收。数据传输的方向取决于当前的数据传送方向,主设备可以发送数据给从设备,也可以接收从设备发送的数据。在这种模式下,主设备负责产生时钟信号并控制数据的传输过程。
I2C总线接口主要用于芯片间的通信。
PWM(Pulse Width Modulation,脉宽调制)的基本原理是通过改变信号的占空比来调节输出信号的有效功率。PWM接口是一种通过调节信号的脉冲宽度来控制功率传递的技术。它被广泛应用于各种电子设备,尤其是在电动机控制、亮度调节、音频输出、信号处理等方面。
串行外围接口(Serial Peripheral Interface,SPI)是一种广泛使用的同步串行通信协议接口,主要用于微控制器和各种外围设备之间的数据传输。SPI的作用如下。
• 同步数据传输:支持主设备和从设备之间的同步数据传输。
• 高速通信:相对于其他串行通信协议(如I2C),SPI提供更高的数据传输速率,适用于高速数据交换场景。
• 多设备连接:通过使用多个片选信号,SPI总线可以连接多个从设备。
SPI一般用作传感器接口、存储设备接口、显示屏接口和音频设备接口。SPI模块在嵌入式系统和电子产品中有广泛的应用,其高速和灵活的特点使其成为许多实时数据传输场景的首选。
通用输入输出(General-Purpose Input/Output,GPIO)接口广泛用于微控制器、嵌入式系统,用于与外围设备进行通信,通过引脚提供数字输入、数字输出、模拟输入、模拟输出等功能。
通用串行总线(Universal Serial Bus,USB)是一种连接计算机和外围设备的串口总线标准,也是一种输入输出接口的技术规范。USB接口广泛地应用于个人计算机和移动设备等通信产品。
处理器架构通俗来说就是计算机处理器的设计结构和组织方式。它决定了硬件如何执行软件指令,以及如何处理和存储数据。本节介绍指令、指令集架构和微架构。
指令是指示计算机执行某种操作的命令,由一串二进制代码组成。一条指令通常由操作码和地址码两部分组成:操作码指明该指令要完成的工作的类型或性质,如取数、做加法或输出数据等;地址码指明操作对象的内容和所在的存储单元地址。一般的软件程序需要转换为数量巨大的指令后才能在计算机上执行。一段程序通过编译翻译成汇编语言,然后通过汇编器翻译成机器码,这些机器码使用由0和1组成的机器语言表示。
指令集架构(Instruction Set Architecture,ISA)定义了CPU可以执行的机器指令集合,以及这些指令的编码方式。ISA是软件与硬件之间的接口,它决定了软件如何与CPU交互。因此指令集架构不仅决定了CPU的功能,还决定了指令的格式和CPU架构。指令集架构主要分为以下几类。
• 复杂指令集计算机(Complex Instruction Set Computer,CISC)架构:每条指令可执行多个操作。典型的CISC架构包括x86处理器(如Intel的Pentium系列)。其优点是代码编写简单,缺点是执行效率较低,适用于需要简单编程的应用场景,如家用和商用计算机。
• 精简指令集计算机(Reduced Instruction Set Computer,RISC)架构:架构的指令数目少且简单,执行效率高。ARM和PowerPC处理器采用典型的RISC架构。其优点是执行效率高,缺点是编程复杂度较高,适用于高性能计算和嵌入式系统。
• 显式并行指令计算(Explicitly Parallel Instruction Computing,EPIC)架构:通过并行执行多条指令提高性能,如Intel的Itanium处理器。其优点是性能强,缺点是复杂度高,适用于需要极高计算能力的应用场景。
• 超长指令字(Very Long Instruction Word,VLIW)架构:将多条指令合并为一个长指令字,提高并行度。其优点是并行度高,缺点是编程复杂,适用于需要大量并行计算的场景。
指令的功能由指令的操作码决定。根据功能,指令可分为四大类:第一类为运算指令,用于处理加减乘除、移位、逻辑运算等;第二类为访存指令,负责对存储器的读写;第三类是转移指令,用于控制程序的流向;第四类是特殊指令,用于操作系统的特定用途。
指令编码是将计算机指令转换成机器可识别的二进制代码的过程或结果。CISC架构的指令码长度可变,其编码也比较自由,可依据类似于哈夫曼(Huffman)编码的方式将操作码平均长度缩短。RISC架构的指令码长度固定,因此需要合理定义来保证各指令码能存放所需的操作码、寄存器号、立即数等元素。
图1-1直观地给出了RISC、CISC、VLIW架构的指令编码。
图1-1 RISC、CISC、VLIW架构的指令编码
MIPS公司开发的RISC架构有R型、I型和J型的指令,内部位域分配不同,但总长度均为32位。
以x86为代表的CISC架构中,指令是变化的,这意味着每条指令的长度并不固定。指令长度的变化主要取决于操作码、操作数和前缀。
VLIW架构通过将多个操作打包在单条宽指令中来实现并行处理。在这种架构中,每条指令通常包含多个微操作,这些微操作可以由硬件并行执行。这种设计旨在通过提高指令级并行处理的能力提高处理器的性能。
指令可访问的地址空间包括寄存器空间和系统内存空间。寄存器空间包括通用寄存器、专用寄存器和控制寄存器。寄存器空间通过指令中的寄存器号寻址,系统内存空间通过访存指令中的访存地址寻址。
通用寄存器是处理器中最常用的存储单元,在一个处理器周期内可以同时读取多条指令需要的多个寄存器的值。每套指令集里都定义了一定数量的通用寄存器供编译器进行充分的指令调度。针对浮点运算,通常还定义了浮点通用寄存器。
除了通用寄存器外,有的指令集还会定义一些专用寄存器,仅用于某些专用指令或专用功能。
不同指令集对系统内存空间的定义各不相同,广义的系统内存空间包括I/O空间和内存空间。x86指令集包含独立的I/O空间和内存空间,对这两部分空间的访问需要使用不同的指令:对内存空间使用一般的访存指令,对I/O空间使用专门的in/out指令。而MIPS、ARM、LoongArch等RISC指令集则通常不区分I/O空间和内存空间,把它们都映射到同一个系统内存空间,使用相同的load/store指令。处理器对I/O空间的访问不能经过高速缓存,因此在使用相同的load/store指令既访问I/O空间又访问内存空间的情况下,就需要定义load/store指令访问地址的存储访问类型。如MIPS指令集定义高速缓存一致性属性(Cache Coherency Attribute,CCA)——Uncached和Cached,二者分别用于I/O空间和内存空间的访问,ARM AArch64指令定义内存属性Device和Normal,二者分别对应I/O空间和内存空间的访问。存储访问类型通常根据访存地址范围来确定。
根据使用数据的方式,指令可分为栈型指令、累加器型指令和寄存器型指令。寄存器型指令又可以进一步分为寄存器-寄存器(register-register)型指令和寄存器-存储器(register-memory)型指令。
栈型指令又称零地址指令,其操作数都在栈顶,在运算指令中不需要指定操作数,默认对栈顶数据进行运算并将结果压回栈顶。
累加器型指令又称单地址指令,包含一个隐含操作数——累加器,另一个操作数在指令中指定,把结果写回累加器中。
在寄存器-存储器型指令中,每个操作数都由指令显式指定,操作数为寄存器和内存单元。
在寄存器-寄存器型指令中,每个操作数也由指令显式指定,但除了访存指令外的其他指令的操作数只能是寄存器。
表1-1给出了执行C=A+B的不同指令序列。其中,A、B、C为不同的内存地址,R1、R2等为通用寄存器。
表1-1 执行C=A+B的不同指令序列
栈型指令序列 |
累加器型指令序列 |
寄存器型指令序列 |
|
---|---|---|---|
寄存器-存储器型指令序列 |
寄存器-寄存器型指令序列 |
||
PUSH A |
LOAD A |
LOAD R1,A |
LOAD R1,A |
PUSH B |
ADD B |
ADD R1,B |
LOAD R2,B |
ADD |
STORE C |
STORE C,R1 |
ADD R3,R1,R2 |
POP C |
STORE C,R3 |
寻址方式指根据地址信息确定操作数位置的方式。表1-2列出了常用的寻址方式。
表1-2 常用的寻址方式
寻址方式 |
示例 |
说明 |
---|---|---|
寄存器寻址 |
ADD R1,R2 |
regs[R1]=regs[R1]+regs[R2] |
立即数寻址 |
ADD R1,#2 |
regs[R1]=regs[R1]+2 |
偏移量寻址 |
ADD R1,100(R2) |
regs[R1]=regs[R1]+mem[100+regs[R2]] |
寄存器间接寻址 |
ADD R1,(R2) |
regs[R1]=regs[R1]+mem[regs[R2]] |
变址寻址 |
ADD R1,(R2+R3) |
regs[R1]=regs[R1]+mem[regs[R2]+regs[R3]] |
绝对寻址 |
ADD R1,(100) |
regs[R1]=regs[R1]+mem[100] |
存储器间接寻址 |
ADD R1,@(R2) |
regs[R1]=regs[R1]+mem[mem[regs[R2]]] |
自增量寻址 |
ADD R1,(R2)+ |
regs[R1]=regs[R1]+mem[regs[R2]],regs[R2]=regs[R2]+d |
自减量寻址 |
ADD R1,−(R2) |
regs[R2]=regs[R2]−d,regs[R1]=regs[R1]+mem[regs[R2]] |
比例变址寻址 |
ADD R1,100(R2)(R3) |
regs[R1]=regs[R1]+mem[100+regs[R2]+regs[R3]*d] |
其中,数组mem[ ]表示存储器,数组regs[ ]表示寄存器,mem[regs[Rn]]表示以寄存器Rn的值作为存储器地址所访问的存储器值。
此外,还有很多其他寻址方式,但常用的寻址方式并不多。
偏移量寻址、立即数寻址和寄存器间接寻址是常用的寻址方式,而寄存器间接寻址相当于偏移量为0的偏移量寻址。因此,一个指令系统至少应支持寄存器寻址、立即数寻址和偏移量寻址。
经典的RISC指令集(如MIPS和Alpha)主要支持上述3种寻址方式,以兼顾硬件设计的简洁性和寻址计算的高效性。不过,随着工艺和设计水平的提升,现代商用RISC类指令集在逐步增加所支持的寻址方式以进一步提升代码密度。例如,64位的LoongArch指令集(简称LA64)就在支持寄存器寻址、立即数寻址和偏移量寻址的基础上还支持变址寻址方式。
在执行访存指令时,必须考虑访存地址是否对齐和指令系统是否支持不对齐访问。所谓对齐访问,是指对该数据的访问起始地址是其数据长度的整数倍。例如,要访问一个4字节的数,其起始地址必须是4的倍数。
对齐访问的硬件实现较简单。若支持不对齐访问,硬件需要完成数据的拆分和拼合。但若只支持对齐访问,又会使指令系统丧失一些灵活性。例如,字符串操作经常需要进行不对齐访问,若只支持对齐访问,就会让实现字符串操作变得复杂。以x86为代表的CISC架构的指令集通常支持不对齐访问,RISC架构的指令集在早期发展过程中为了简化硬件设计只支持对齐访问,对不对齐的地址访问将产生异常。
近些年来,随着工艺和设计水平的提升,越来越多的RISC架构的指令集开始支持不对齐访问以减轻软件优化的负担。
另一个与访存地址相关的问题是端(endian)问题。不同的机器可能使用大端模式或小端模式,这带来了严重的数据兼容性问题。Motorola公司的68000系列和IBM公司的System系列指令系统采用大端模式;x86、VAX和LoongArch等指令系统采用小端存储方式;ARM、SPARC和MIPS等指令系统同时支持大端、小端模式。
操作数常见的数据类型包括整数、实数、字符,数据长度包括1字节、2字节、4字节和8字节。x86指令集还包含专门的十进制类型BCD。表1-3给出了C语言整数类型与不同指令集中的名称和长度的关系。
表1-3 C语言整数类型与不同指令集中的名称和长度的关系
C语言整数类型 |
LA32指令集 |
LA64指令集 |
x86指令集 |
x86-64指令集 |
||||
---|---|---|---|---|---|---|---|---|
名称 |
长度/字节 |
名称 |
长度/字节 |
名称 |
长度/字节 |
名称 |
长度/字节 |
|
char |
Byte |
1 |
Byte |
1 |
Byte |
1 |
Byte |
1 |
short |
Halfword |
2 |
Halfword |
2 |
Word |
2 |
Word |
2 |
int |
Word |
4 |
Word |
4 |
Dword |
4 |
Dword |
4 |
long |
Dword |
4 |
Dword |
8 |
Dword |
4 |
Qword |
8 |
long long |
Dword |
8 |
Dword |
8 |
Qword |
8 |
Qword |
8 |
实数类型在计算机中表示为浮点类型,包括单精度浮点数和双精度浮点数。单精度浮点数的长度为4字节,双精度浮点数的长度为8字节。
在指令中数据类型有两种表示方法:一种是由指令操作码来区分不同类型,例如,加法指令包括定点加法指令、单精度浮点加法指令、双精度浮点加法指令;另一种是将不同类型的标记附在数据上,例如,加法使用统一的操作码,用专门的标记来标明加法操作的数据类型。
微架构(microarchitecture)又称为内部架构或处理器架构,是指实现ISA的处理器内部设计,包括数据路径、控制单元、寄存器、高速缓存和执行指令所需的其他硬件。通俗来讲,微架构就是处理器电路,即CPU内实现指令解析及算术逻辑运算等功能的电路设计架构。集成电路工程师在设计处理器时,会按照指令集规定的指令,设计具体的译码和运算电路来支持这些指令的运行。常见的微架构如表1-4所示。
表1-4 常见的微架构
微架构 |
类型 |
主要应用 |
---|---|---|
x86 |
CISC |
服务器、个人计算机 |
ARM |
RISC |
移动设备、嵌入式设备 |
RISC-V |
RISC |
高性能计算、嵌入式设备 |
PowerPC |
RISC |
数据中心、游戏主机 |
MIPS |
RISC |
处理器、嵌入式系统 |
LoongArch |
RISC |
服务器、个人计算机、嵌入式设备 |
一套相同的指令集可以由不同形式的电路实现,可以有不同的微架构。在设计一个微架构时,一般需要考虑很多问题,例如,处理器是否支持分支预测,流水线需要多少级,主频需要多高,高速缓存多大,需要几级高速缓存。根据不同的选项,可以基于一套指令集设计出不同的微架构。
以ARMv7指令集为例,基于该套指令集,针对不同的性能、功耗等需求,ARM公司设计了Cortex-A7、Cortex-A8、Cortex-A9s、Cortex-A15、Cortex-M7等微架构。基于一款相同的微架构,通过不同的配置,也可以设计不同的处理器类型。不同的SoC厂商获得ARM公司的Cortex-M7微架构授权后,基于该内核架构可以设计不同的SoC,并最终流向市场。
微架构一般也称为CPU内核。在一个ARM SoC上,把CPU内核和各种外围设备通过AMBA总线连接起来,构成一个微处理器。
指令集、微架构与处理器之间的关系如图1-2所示。
图1-2 指令集、微架构与处理器之间的关系
LoongArch是一种精简指令集计算机风格的指令系统架构。LoongArch具有RISC架构的典型特征。它的指令长度固定且编码格式规整,绝大多数指令只有两个源操作数和一个目的操作数,采用load/store架构,即仅有load/store访存指令可以访问内存,其他指令的操作对象是处理器核内部的寄存器或指令码中的立即数。
LoongArch分为32位和64位两个版本,分别称为LA32架构和LA64架构。LA64架构应用级向下二进制兼容LA32架构。“应用级向下二进制兼容”一方面是指采用LA32架构的应用软件的二进制可以直接运行在兼容LA64架构的机器上并获得相同的运行结果;另一方面是指这种向下二进制兼容仅限于应用软件,架构规范并不保证在兼容LA32架构的机器上运行的系统软件(如操作系统内核)的二进制直接在兼容LA64架构的机器上运行时始终获得相同的运行结果。
LoongArch采用基础部分加扩展部分的组织形式(见图1-3)。其中扩展部分包括二进制翻译扩展、向量扩展、高级向量扩展和虚拟化扩展。
图1-3 LoongArch的组织形式
LoongArch的基础部分包含非特权指令集和特权指令集两部分。其中,非特权指令集部分定义了常用的整数和浮点数指令,能够充分支持现有主流编译系统生成高效的目标代码。
LoongArch的虚拟化扩展部分为操作系统虚拟化提供硬件加速以提升性能。这部分涉及的基本上是特权资源,包括一些特权指令和控制状态寄存器,以及在异常、中断和存储管理等方面添加新的功能。
LoongArch的二进制翻译扩展部分用于提升跨指令系统二进制翻译在LoongArch平台上的执行效率,它在基础部分之上进行扩展,同样包含非特权指令集和特权指令集两部分。
向量扩展和高级向量扩展部分均采用SIMD指令来加快计算密集型应用的运行速度。两个扩展部分在指令功能上基本一致,区别在于向量扩展操作的向量位宽是128位,而高级向量扩展操作的向量位宽是256位。
对于一个兼容LoongArch的实现,架构中的基础部分必须实现,扩展部分可以选择实现,各扩展部分可以灵活选择。不过,当选择实现高级向量扩展时,必须同时实现向量扩展。除了将整个扩展部分作为可选项,在基础部分和扩展部分中还进一步包含了一些可选实现的功能子集。
图1-4给出了LoongArch指令集的编码格式。
32位的指令编码被划分为若干区域。按照不同的划分方式,共有9种典型的编码格式,即3种不含立即数的格式(2R类型、3R类型、4R类型)和6种包含立即数的格式(2RI8类型、2RI12类型、2RI14类型、2RI16类型、1RI21类型和I26类型)。
图1-4 LoongArch指令集的编码格式
rd、rj、rk和ra字段用于存放寄存器编号,通常rd表示目标寄存器,而rj、rk、ra表示源寄存器。
I××字段用于存放指令立即数,即在立即数寻址方式下指令中给出的数。指令中的立即数不仅可作为运算型指令的源操作数,还可作为load/store指令中相对于基地址的偏移量以及转移指令中转移目标的偏移量。