用于解码指令序列的方法和设备的制作方法

文档序号:6409065阅读:229来源:国知局
专利名称:用于解码指令序列的方法和设备的制作方法
技术领域
本发明涉及一种方法和设备,用于把数据处理程序的至少两个指令的序列解码成为用来控制例如数字信号处理器等装置的数据路径的码字序列。
计算机体系结构包括由控制字控制的一条固定数据路径。此控制字由若干个部分组成,每个部分控制数据路径的一部分。这些部分可以包括多路复用器、寄存器地址、算术逻辑单元(ALU)或其它功能单元的操作码等等。通常,利用一个指令解码器或者利用微存储器,即直接包含控制字的一个存储器,发出的每个指令生成一个新的控制字,其中所述指令解码器把二进制格式的指令翻译成为相应的控制字。
当处理器执行循环功能时,相应的过程不但可以被解释为指令序列,而且可以被解释为在时间上被仿真的一个流水线电路。在这样一个流水线电路中,在每个时钟周期数据在数据流图的边缘下移,其中,曲线图边缘由寄存器实现。另一方面,数据流图可以由一个程序来实现,其中,按照由指令调度器确定的某一顺序来执行不同的操作。指令可以一个一个地执行,或者在处理器体系结构支持并行处理的情况下按照所包括的一些并行操作来执行。为了执行这些操作,处理器中各自的控制字在每个指令处将配置数据流图的一部分,而边缘由通用处理器寄存器来实现。
可是,嵌入式系统就功耗和面积方面的成本在很大程度上由程序存储所需的存储器来确定。与手工汇编代码相比,高级编译通常在代码规模方面导致一个恶化。为了把代码规模保持在可接受的界限之内,有效的指令编码和代码压缩是新型处理器核心设计中关键的一个重要因素。此外,关于程序不同部分的性能的不同约束的说明允许代码密度和性能之间的一个平衡。
文献US 5862384公开了一种装备有优化部分的编译器优化设备,所述优化部分被安排来基于更新的可变控制表中识别的更新变量来将循环不变的表达式转移到循环之外。这减少了执行语句的总数并导致处理的有效优化和加速的处理速度。
可是,诸如那些表示一个循环之类的某些指令序列,将导致一个具有固定部分和标准部分的控制字序列。虽然控制字的固定部分不变,但是在这样一个不变序列的执行时间所确定的大量周期期间,一个结构存储器环境被重新加载。这种时间代价导致降低的处理性能和增加的功耗。
因此,本发明的一个目的是提供一种用于编码指令序列的解码方法和设备,通过它能够获得一个增加的处理性能和降低的功耗。
此目的通过权利要求1中要求的方法以及通过权利要求20中要求的设备来实现。
因此,在固定电路实现和基于程序的执行实现两个极端之间的一种方式被提供来在进入循环之前配置数据流图的一部分,以使它在循环期间将被固定。这对应于固定数据路径部分,即固定控制字部分。因为这导致每个周期发出一个更窄的控制字,所以功耗和(微)代码规模二者都降低。此技术可以被认为是一种控制字提升(hoisting),在其中,编译器术语“提升”意味着把循环不变的控制信号(例如操作码,地址等等)移到循环之外。可是,由于指令调度表不改变,因此相对于编译器,此技术有一点点影响。只有各自码字序列(例如循环)内的指令的编码被影响。特别地,控制字的不变部分,即固定部分,不再出自指令解码器或微存储器,而是可以从其它地方得到,例如从一个单独的存储器中得到。作为一种替换方案,一个可重新配置硬件,例如嵌入式现场可编程门阵列(FPGA),可用于维护不变部分的布线。
由于在每个控制字中控制字的不变部分不再被多余复制的这个事实,则必要的微代码存储器规模降低了。
在专用存储器替换方案中,专用存储器可以被实现为一个查询表或一个按内容可寻址的存储器。可以在数据路径的多个功能单元之间共享专用存储器,或者多个专用存储器可以被分配给数据路径各自的功能单元。
此外,不变码字部分可用来寻址专用存储器,以便获得一个被用来控制数据路径的扩展了的新码字。这可以通过使用与原始码字序列相同的连接来达到。然后,可以经由一个多路复用功能来选择所述连接。
通过使用一个结构掩码,可以在码字中规定不变码字部分的比特位置。特别地,基于所述结构掩码可以控制一个控制字加载功能使得把所述码字比特引导到一个控制寄存器的适当位置。这可以通过使用结构掩码来达到,以便生成用于连接到控制寄存器的开关信号。专用存储器的规模可以对应于指令寄存器的规模。
在可重新配置硬件替换方案中,可以基于不变码字部分选择一个结构环境。此外,通过把不变控制的一部分嵌入到结构本身中,则可以降低控制映射到可重新配置硬件上的电路的控制比特数目。因此,码字的不变部分也同样可以被提升,减低控制映射到可重新配置硬件上的电路所需要的指令字宽度。此外,可以从至少一个指令中选择具有最大不变码字部分的那些指令,并且选定的指令可以用于映射到可重新配置硬件上。因此,可重新配置硬件被用于能够从提升中受益最多的那些指令或指令序列。
在从属权利要求中定义了其它有利的发展。
在下面,将参考附图基于优选实施例更详细地描述本发明,其中

图1示出了根据第一优选实施例表示两个解码替换方案的示意图;图2示出了寄存器堆基于多路复用器的选择示例;图3示出了根据第一优选实施例表示从控制字的标准部分中简单切割分离一个结构部分的原理图;图4示出了根据第一优选实施例表示使用结构掩码和控制字加载器用于组合一个码字的结构部分和标准部分的原理图;图5示出了一个表示可被用于第一优选实施例中的控制字加载器体系结构的示意图;图6示出了可被用于根据图5的控制字加载器体系结构中的一个可编程交叉点开关示例;图7示出了根据第二优选实施例,表示基于固定控制字用于控制可重新配置寄存器堆的方法的示意图;和图8A和8B示出了可以用在第二优选实施例中的可重新配置逻辑单元的示意图。
作为数字信号处理器中的一个代码序列示例,现在将根据循环操作的解码和处理来描述优选实施例。根据优选实施例,在进入循环之前配置数据流图的一部分,以使它在循环期间将被固定。这对应于固定数据路径的一部分,即固定控制字的一些部分。
总的来说,为一个循环不变的数据流图固定控制字部分可能意味着固定功能单元和寄存器堆之间的连接;固定寄存器堆空间内的地址;固定功能单元的操作码。
与一个任意的循环不变的数据流图相关的控制字固定部分的生成发生在那个循环的代码生成或指令解码期间。然后,在循环执行期间,从一个本地指令解码器或微存储器中获取控制字的标准或可变部分。控制字的固定或不变部分被用来配置在该码字序列期间被固定的数据路径部分。
根据第一优选实施例,码字的固定部分从被实现为查询表或按内容可寻址的存储器(CAM)的专用存储块中获得。根据所考虑体系结构中的指令分层结构,专用存储块可以在处理器体系结构中被全局或局部地放置。
根据第二优选实施例,控制字的固定部分可用来固定提供于处理器体系结构中的可重新配置硬件或逻辑单元的可重新配置方面。
在下面,参考图1到6说明第一优选实施例的实现示例。
图1示出了利用用于放置专用存储块的以上两种可能方法的数字信号处理器体系结构的一部分示意图。正如在图1的左上部指出的,控制字10由一个标准或可变部分11以及一个固定或不变部分12组成。固定部分12在循环期间没有变化。如图1右上部所示,根据第一种方法,专用存储块26连接到第一功能单元群23的指令解码器24,第一功能单元群23连接一个寄存器堆21。寄存器堆21可以经由多路复用器22从互连线中访问。因此,在第一方法中,专用存储块26被全局放置,如此以使在许多功能单元群之间共享控制字的固定部分。应该指出还可以从解码器24中直接寻址寄存器堆21中的寄存器,而不必通过多路复用器22。此寻址部分将对应于控制字的固定部分12并将在循环期间保持不变。
根据在图1右下部表示的第二可能方法,专用存储块25被排列在一个给定功能单元群(例如功能单元群23)内并对其是特定的。同样,专用存储块25连接到功能单元群23的指令解码器24。控制字的固定部分12在两个方法中可以被编码(例如通过编译器或汇编器)以便缩短它的原始比特宽度。然后,它稍后在各自的专用存储块25、26中被扩展或解码为一个新的控制字,基于这个新的控制字,获得一个修改了的指令类型。
图2示出了能够由标准的和修改了的指令类型控制的寄存器堆21的示例。经由各自的专用存储块25、26,根据控制字10的标准部分11来获得标准指令类型,而根据控制字10的固定部分12来获得修改了的指令类型。特别地,在循环期间,由指令解码器24生成标准和修改了的指令类型,以便提供循环所需要的处理和寄存器功能。应当指出控制字10的固定部分12和标准部分11分别到标准和修改了的指令类型的变换未在图2中示出。为了降低总的实现成本,特别是布线,由各自的专用存储块25、26生成的这个新控制字可以使用与标准指令解码器24相同的到受控资源的连接。正如图2中所示,通过使用提供在寄存器堆21各自输入处的本地多路复用器,可以实现选择。因此,从控制字10的标准部分11和固定部分12中获得的两个控制信号都可用于控制寄存器堆21。
由于控制字10的循环不变或固定部分12与循环变化或标准部分11分开的这个事实,应用程序的每个循环本身将具有一个循环不变部分或结构。剩余部分在循环执行期间可以改变。这降低了必要的微代码存储器规模,因为在每个控制字中结构部分在循环内未被多余地复制。实际上,在循环执行期间并未变化的控制比特可以任意地分布在控制字上。然后一个问题是要在执行期间把适当的结构和标准比特从微代码存储器中载入指令解码器24处的控制寄存器的适当比特位置中,处理器数据路径的资源基于该适当的比特位置来控制。这可以通过为应用程序中的每个循环提供一个结构掩码而解决,结构掩码规定控制寄存器中的哪些比特位置是循环不变的,哪些不是。然后,在结构掩码的控制之下,控制字加载器将把结构部分中的比特引导到控制寄存器的适当位置。然后可以开始循环的执行。对于从标准部分11中导出的每个控制字,控制字加载器将把每个比特引导到它在控制寄存器中的适当位置,而不改变由专用存储块25或26定义的那个循环中预先载入的结构。
图3示出了表示在控制数据中的某些点中通过一个简单的切断而把结构部分与标准部分分离、简单生成控制数据的一个简图。根据图3,控制寄存器50被提供用来控制一条处理器数据路径41,其包括具有各自寄存器堆的两个算术逻辑单元(ALU)54和两个相乘/累加单元(MAC)53以及一个随机存取存储器(RAM)52。正如图3中所示,在循环执行期间没有改变的控制比特,即结构部分62的比特,被直接转移到控制寄存器50的对应部分,而储存在微代码存储器51中的控制数据的标准部分11在循环执行期间变化并被提供给控制寄存器50的剩余部分。虽然此简化情形能够由该体系结构强制实施并被编译器利用,但是代价是损失一些提升可能性,在通常的情况下,不能保证循环不变的比特在直线序列中全部彼此相邻,如图3所示。为了充分地利用控制字提升的可能性,需要一个更通用的解决方案。
因此,图4示出了一个通常的情况,在此,控制寄存器50中的出口(hatched)位置对应于循环不变的或结构比特。正如可以从图4中搜集的那样,在循环执行期间不变的控制比特任意地分布在控制寄存器50中的控制字上,而没有特定的次序。问题是要在循环执行期间把适当的结构和标准比特从微代码存储器51中载入控制寄存器的适当比特位置中。为了实现这一点,正如上面已经提到的,和图1的专用存储块25或26中的每个结构一起提供一个结构掩码61。当一个新的循环要被执行时,相应的结构掩码61被载入到控制字加载器64的结构掩码寄存器63中,正如结构掩码寄存器63定义的那样,其负责把控制数据从微代码存储器51中载入给控制寄存器50的适当位置去。然后可以开始循环的执行。对于标准部分11的每个控制数据,控制字加载器64将把每个比特引导到它在控制寄存器50中的适当位置,而不改变从专用存储块25或26中获得的预先载入的结构62。
应当指出结构掩码寄存器63中的零和一的模式不是控制信号,它仅仅只是规定控制字中的哪些比特位置是循环不变的,哪些不是。另一方面,循环结构62中的零和一实际上是将要控制处理器数据路径的控制信号,例如功能单元的操作码,寄存器地址,多路复用器选择输入等等。
图5示出了表示如图4所示的控制字加载器64的结构的示意图。正如图5中所示,程序计数器PC指向控制字10储存在微代码存储器51或指令存储器或缓存中的实际标准部分11。正如已经提到的,剩余的固定部分或结构被储存在专用存储块25或26中。因此,正常指令存储器或微代码存储器51只包含控制字10的标准部分。然后,新的结构在软件控制之下被载入到控制寄存器50中。可是,此载入功能未在图5中示出。专用存储块25或26中每个控制字的大小可以与处理器的指令寄存器50中的相同。这样,和每个结构62一起,对应于相应循环中的第一控制字或指令的标准部分11的比特还可以被储存在专用存储块25或26中。由于字大小相同这个事实,专用存储块25或26的字(结构)可以被直接载入处理器的指令寄存器中,完全绕过(by-passing)如图5所示提供在控制字加载器64中的可编程交叉点开关73。由此,循环的控制字的第一标准部分11被自动并行载入。
可编程交叉点开关73可以由多路复用器链路组成,每个多路复用器由出自掩码解释逻辑71中的一组比特控制。特别地,可编程交叉点开关73还可以具有可控制的三态缓存器,而所有个体多路复用器和缓冲控制比特的集合组成开关控制信号72。掩码解释逻辑71被安排来把结构掩码寄存器63的内容翻译成为开关控制信号72。掩码解释逻辑71的使用提供如下两个优点。首先,它从循环结构掩码61的语义学中把特定的开关体系结构去耦合。这例如实现保留与前一版本的二进制码兼容性的开关升级。其次,结构掩码寄存器63中的比特数目通常将比组成开关控制信号72的比特数目小得多,从而允许环形结构61所需存储器规模的降低。然而,该系统可以如此安排以使不提供循环结构掩码63和掩码解释逻辑71。然后,循环结构61的比特直接形成开关控制信号72。
正如前面提到的那样,在第一优选实施例中,结构掩码中零和一的模式编码控制字中的哪些比特位置是循环不变的,哪些不是。事实上,因为掩码解释逻辑71从开关体系结构中去耦合循环结构掩码的语义,所以编码结构掩码中信息的一些其它形式也同样能被使用,这可以减少储存该信息所要求的比特宽度。
可编程交叉点开关73可以被完全连接,而不必须这样。例如,标准部分11的第一比特可以被路由到控制寄存器50的任何比特位置,而标准部分11的第二比特位置不必可路由到控制寄存器50的第一比特位置。此外,标准部分11的第三比特位置不必可路由到控制寄存器50中的第一和第二比特位置等等。类似的推理可以被应用到更高阶比特。通过应用此推理,可以从交叉点开关73中物理上删除某些连接,因为它们从不被使用。
图6示出了一种简化情况的可编程交叉点开关73的实施例示例,在此简化情况中,从微代码存储器51中获得的指令的标准部分11只包括两个比特,而受控处理器数据路径需要控制寄存器50中的四比特控制字。因此,从微代码存储器51中获得的指令包括两个比特并且控制寄存器50包括四个比特。交叉点开关73的连接路径然后能够基于开关控制信号72经由多路复用器和三态缓存器而被控制。在目前的情况下,指令的左比特,即标准部分11,可以被交换到控制寄存器50的除了最右边的比特位置之外的所有比特位置,而指令的右比特可以被交换到控制寄存器50的除了最左边的比特位置之外的所有比特位置。
图7示出了根据第二优选实施例的一个解码体系结构的示意图,在此,控制字10的固定部分12被用来控制可重新配置寄存器堆31。由于可重新配置硬件资源的特定性质,更高灵活性是可以获得的,其可以被利用来进一步改善成本有效性。可被用于第二优选实施例中的一个可重新配置硬件单元示例是嵌入式FPGA。
当寄存器堆31被实现在可重新配置逻辑中时,全部资源被空间映射。通过结构存储器比特来实现对资源的控制。当一个新类型的数据流图要被执行时,结构存储器32载入一个新的结构环境。内部结构控制器33基于控制字10的固定部分12来考虑选择正确的结构环境。由于控制字10的固定部分对于若干周期被保留不变,所以与结构存储器环境的重新加载相关的潜在重新配置时间代价是无关重要的。
如果可重新配置寄存器堆31被安排来使用标准控制字,则结构环境必须被适合于它。
可重新配置寄存器堆31还包括基于结构存储器32中的比特状态而被控制的可配置逻辑阵列34。从而,可配置接口35可以被配置,以便提供期望的输入、输出和/或控制字。因此,不但到功能单元的连接而且例如寄存器堆21的深度都可以是可编程的。此外,在可重新配置逻辑中,实现诸如FIFO(先入先出)和堆栈之类的专门寄存器堆体系结构是可能的。由于类似FIFO和堆栈那样的结构所要求的简化的寻址方案,所以寻址寄存器堆所需要的控制字的标准部分11的大小可以减少颇大。
图8A示出了根据第二优选实施例的一个处理器体系结构,它具有一个处理器控制器40,用于控制一条数据路径,此数据路径包括处理器数据路径41和作为可重新配置硬件的FPGA块31。FPGA块31被安排用来实现一个由应用特定单元ASU和相关寄存器堆RF组成的电路。应用特定单元ASU以一种足够灵活的方式被构造以便允许它被使用在应用程序的不同循环内。
在如图8A所示的目前情况下,应用特定单元ASU和寄存器堆RF被安排用来加速应用程序的关键循环,并且对于被使用于所有关键循环中的FPGA块31,它们的体系结构足够灵活。应当指出不同循环可能需要应用特定单元ASU执行不同的操作,或者寻址它相关寄存器堆RF中的不同寄存器。为了允许此灵活性,相关寄存器堆RF和应用特定单元ASU的端口由处理器数据路径41中发出的指令或控制字比特控制。在图8A中,需要十二个控制比特用于分别对相关寄存器堆RF提供读地址、对相关寄存器堆RF提供写地址、以及对应用特定单元ASU提供操作码。
可是,这些控制参数中的许多在一个特定循环中不变化。因此,对于那个特定的循环或其它指令序列,不需要在指令字中提供十二个控制比特来控制映射到FPGA块31上的电路。因此,可以降低指令字宽度,从而节省指令存储器。
图8B说明了当循环的控制字的循环不变部分被提升时FPGA块31的结构。特别地,在一个特定循环内,应用特定单元ASU和相关寄存器堆RF之间的六个连接从不改变,因此这六个寄存器明显不必寻址。这把读地址的宽度从三个比特降低到一个比特。同时,在该特定的循环内只需要应用特定单元ASU的一个操作子集,因此它们各自操作码的某些比特在那个循环中是多余的,并且可以在FPGA结构本身中被布线。结果,现在在指令字中总共只需要七个比特(三个写地址比特,一个读地址比特以及三个操作码比特)来控制那个特定循环内的FPGA块31。
由于FPGA块31很灵活这个事实,映射到它上面的不同硬件结构可以被如此重新配置以便正确地解释数目减少的控制比特。在图8B中,例如,在此创建的相关寄存器堆RF的寄存器和应用特定单元ASU之间的点到点连接(由六个相应的箭头表示),相关寄存器堆RF的地址解码器多路复用器的规模被减少,并且应用特定单元ASU的内部结构被改变以便正确解释较小的3比特操作码。潜在地,通过去掉应用特定单元ASU中对应于在那个给定循环内从不执行的那些软电路部分,则可以使应用特定单元ASU本身更小。
因此,总的策略是限制指令字中可用于控制FPGA块31的比特数目,因而节省指令存储器。尽管有此减少,则通过使用提升概念,FPGA块31仍然可以被应用程序中的若干个不同的关键循环所使用。
另一总策略是调查应用程序中哪些关键循环具有最大循环不变部分并且能够从提升中受益最多。这些循环然后被选择,用于映射到诸如FPGA块31之类可以利用提升的可重新配置硬件单元上,而不是被映射到硬布线单元和处理器数据路径41剩余部分的寄存器堆上。
应当指出本发明不局限于上面说明的优选实施例,并且可用于任何处理器环境中,其中数据处理程序的至少两个指令的序列被解码成为用于控制数据路径的码字序列。特别地,所建议的提升概念可以用于被解码成具有易变和不变部分的码字序列的其它指令序列。优选实施例因此可以在所附权利要求的范围内变化。
权利要求
1.一种把数据处理程序的至少两个指令的序列解码成为用来控制数据路径的码字序列的方法,所述方法包括如下步骤a)分离所述码字序列中没有变化的不变码字部分;和b)使用所述不变码字部分来配置在所述码字序列期间被固定的所述数据路径的一部分。
2.根据权利要求1的方法,还包括使用所述分离的不变码字部分来寻址一个专用存储器的步骤。
3.根据权利要求2的方法,还包括步骤把所述专用存储器实现为查询表或可按内容寻址的存储器。
4.根据权利要求2或3的方法,还包括步骤在所述数据路径的多个功能单元之间共享所述专用存储器。
5.根据权利要求2到4任何一个的方法,还包括步骤提供分配给所述数据路径各自功能单元的多个专用存储器。
6.根据权利要求2到5任何一个的方法,还包括步骤把所述不变码字部分扩展为一个新的码字并使用所述新码字来控制所述数据路径。
7.根据权利要求6的方法,还包括步骤通过所述新码字使用与所述码字序列相同的连接来控制所述数据路径。
8.根据权利要求7的方法,还包括步骤经由多路复用功能来选择所述相同连接。
9.根据权利要求2到8任何一个的方法,还包括步骤使用一个结构掩码来规定控制字中所述不变码字部分的比特位置。
10.根据权利要求9的方法,其中所述结构掩码被编码。
11.根据权利要求10的方法,还包括步骤基于所述结构掩码来控制一个控制字加载功能使得把所述码字的比特引导到控制寄存器的适当位置。
12.根据权利要求10或11的方法,其中所述结构掩码是一种二进制模式。
13.根据权利要求12的方法,还包括步骤使用所述结构掩码来生成用于连接到所述控制寄存器的开关信号。
14.根据权利要求2到13任何一个的方法,还包括步骤选择所述专用存储器的规模对应于指令寄存器的规模。
15.根据权利要求1的方法,还包括步骤通过使用可重新配置硬件来配置所述数据路径的所述部分。
16.根据权利要求15的方法,还包括步骤基于所述不变码字部分来选择一个结构环境。
17.根据权利要求15或16的方法,还包括步骤根据所述码字序列所要求的结构来减少控制所述可重新配置硬件的控制比特数目。
18.根据权利要求15到17任何一个的方法,还包括步骤从所述至少两个指令的序列中选择具有最大不变码字部分的那些指令并使用所述选定的指令用于映射到所述可重新配置硬件上。
19.根据前面权利要求任一个的方法,其中所述至少两个指令的序列形成所述数据处理程序的一个循环体。
20.一种把数据处理程序的至少两个指令的序列解码成为用来控制数据路径的码字序列的设备,所述设备包括a)生成装置,用于独立地生成所述码字序列中没有变化的不变码字部分;和b)配置装置,用于接收所述不变码字部分并用于配置在所述码字序列期间被固定的所述数据路径的一部分。
21.根据权利要求20的设备,其中所述配置装置包括专用存储器装置,用于储存对应于所述不变码字部分的新控制字。
22.根据权利要求21的设备,其中所述配置装置还包括解码装置,用于把来自所述专用存储器装置中的所述新控制字解码成为控制数据路径的控制信号。
23.根据权利要求20的设备,还包括结构掩码寄存器,用于控制控制字加载装置,使得把所述码字序列的变码部分中的比特载入控制寄存器的适当比特位置中。
24.根据权利要求23的设备,其中所述控制字加载装置包括可编程的交叉点开关。
25.根据权利要求24的设备,其中所述控制字加载装置还包括连接到所述可编程交叉点开关和所述结构掩码寄存器的掩码解释逻辑。
26.根据权利要求20的设备,其中所述结构装置包括基于所述不变码字部分配置的可重新配置硬件装置。
全文摘要
本发明涉及一种用于把数据处理程序的至少两个指令的序列解码成为用来控制数据路径的码字序列的方法和设备,其中,在所述码字序列中没有改变的不变码字部分被独立地生成并用于配置在码字序列期间被固定的数据路径部分。因此,必要的微代码存储器规模可以被降低并且可以降低功耗。
文档编号G06F9/30GK1656444SQ03811413
公开日2005年8月17日 申请日期2003年4月25日 优先权日2002年5月22日
发明者A·奥古斯泰恩, K·莱坦-诺瓦克, B·德奥里维拉卡斯特鲁普佩 申请人:皇家飞利浦电子股份有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1