一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

用于处理器仿真验证的大规模用例生成方法与流程

2021-11-24 21:16:00 来源:中国专利 TAG:


1.本发明涉及面向指令集的大规模测试用例生成方法,具体涉及用于处理器仿真验证的大规模测试用例生成方法。本发明的方法不仅限用于x86指令集程序,对于arm或risc

v等处理器指令集程序生成也可适用。


背景技术:

2.在处理器全片验证过程中需要结合实际程序进行测试,用于验证处理器全片环境下的正确性。直接通过已知程序运行的主要局限是只有尽可能多的程序测试才能覆盖处理器功能,此时处理器功能可视为透明。在具体测试中需要借助于验证环境,但是验证环境单位时间可测试的处理器周期数往往是受限的,导致直接通过大量已知程序的完整执行其耗时会无法接受。需要一种能够高效覆盖处理器主要功能点同时具有变化性的程序构造方法验证处理器内部组件在协同工作下的正确性。
3.目前开放的用于处理验证程序生成的工具如riscv

dv主要是面向精简指令集处理器。精简指令集指令格式相对固定,计算和访存指令划分清晰。对于x86类型的处理器,x86指令的描述要求有所不同,首先一条指令的格式可能具有多种,即格式存在复合可能;另外,指令功能上也会有同时涉及计算、访存等,即指令功能上存在复合可能。指令描述属于程序生成的底层部分,提供有效的描述可以带来程序生成描述的简化。在传统的测试用例生成方法中,一般验证程序用于处理器的全片验证,从初始指令开始运行,还原系统在所有程序都安装就绪下的运行状态,从而对应用程序和系统程序进行还原。验证程序一方面尽量体现实际系统程序运行的各种可能,同时能够以更高强度进行用户程序测试,从而快速确认处理器在一些极端程序行为下是否能够工作正常,形成对整个处理器整体以及处理器内部各个功能部件正确性的确认。此时,传统的系统程序和用户程序的配合运行过程会以一个验证程序形式无缝结合在一起,通过动态切换模拟不同特权级程序运行的效果。同时,也会进行一些简化从而将一些需要的指令片段融入到验证程序中,尽可能减少冗余的程序行为,使验证过程需要运行的指令数量可控。
4.每个验证程序需要具有一定变化性,从而具有能够碰撞到极端场景的能力。这里一般通过大规模测试用例生成批量形成所需的验证程序,通过这些验证程序确认目标处理器是否达到预期质量要求。
5.如图1所示,传统测试用例生成需要包括:指令格式描述、一般程序行为描述、运行环境初始化程序描述。其中,一般程序行为描述要通过指令格式描述来形成指令实例进而形成目标指令流片段。不同程序行为形成的指令流片段不尽相同。通过不同指令片段的混合形成更为复杂的测试程序。目前,程序构建过程中一般是从程序角度去进行程序行为还原,通过丰富的程序行为测试目标处理器的正确性。
6.在指令格式描述方面,精简指令集指令一条指令的指令格式相对固定,而对于x86指令,一条指令的指令格式可能会有多种。如果在描述指令行为的过程中再引入较多指令约束,会导致指令行为描述过于复杂。对于程序行为描述部分,一个问题在于一般难于评估
随机程序所覆盖的处理器内部功能,进而需要通过大量的随机生成来确保验证功能的覆盖,另一个问题是,合成后的指令流一般是相对固定的。虽然指令片段混合可以形成一些复杂场景,但这种相对确定的指令执行,会限制单独验证程序的验证能力。传统的程序生成方式下,对于多任务程序的测试往往需要生成用于每个任务的验证程序,从而通过不同处理器核绑定不同任务程序(如图2b所示)来改变负载。如此往往需要开销较高的多重生成,否则使用单个生成程序(如图2a所示)进行多核系统测试会使不同处理器核的执行过于相似,导致一些潜在出错场景无法显现。


技术实现要素:

7.本发明的目的在于提供一种用于处理器仿真验证的大规模测试用例生成方法,以简化复杂指令的描述,并使得验证场景丰富。
8.为了实现上述目的,本发明提供一种用于处理器仿真验证的大规模用例生成方法,包括:
9.s1:进行指令格式的正则化描述,得到经过描述的指令;
10.s2:利用经过描述的指令进行指令流描述和混合,得到目标指令流,该目标指令流为测试用例的主体部分,从而形成测试用例的测试阶段程序;
11.s3:进行程序运行基础描述,以形成测试用例的初始化阶段程序;
12.s4:进行用例描述,以生成测试用例配置;
13.s5:利用所述指令、测试用例的测试阶段程序、测试用例的初始化阶段程序和所述测试用例配置来生成测试用例。
14.其中,所述步骤s1包括:
15.s11:进行每个指令的指令名称描述;
16.s12:进行每个指令的操作数描述,以得到指令的初始格式;
17.s12包括:
18.s121:列出操作数的各种可能组合;
19.s122:对于给定的每一个操作数组合,均对该操作数组合的每个操作数的类型进行规定;
20.指令格式的初始格式如下:
21.<instr_name>[rmin]*
[0022]
其中,<instr_name>表示指令的指令名称,[rmin]表示一个操作数,每个操作数[rmin]的类型可以是r、m、i、n四个类型中的一个,*表示匹配0次或多次,即操作数可以有0个,1个,

或多个,r为寄存器类型的操作数,m为内存类型的操作数、i为立即数类型的操作数,n表示类型为空。
[0023]
优选地,所述步骤s12还可以包括:对操作数类型进行范围限定,以提供操作数随机时的约束条件;
[0024]
采用如下形式对操作数类型进行范围限定:
[0025]
t(cons0,cons1,cons
i
,cons
n
‑1),
[0026]
其中,t为操作数类型声明t=r,m,i,其中r为寄存器类型的操作数,m为内存类型的操作数、i为立即数类型的操作数。上述表达式(cons0,cons1,cons
i
,cons
n
‑1)部分为类型t
的一个或多个约束。
[0027]
优选地,所述步骤s1还包括步骤s13:进行附加功能描述,以得到指令的扩展格式;
[0028]
所述指令的扩展形式为:
[0029]
<instr_name>[rminp]*
[0030]
其中,<instr>为指令名称,p为模式操作数,这里的p可展开为<prefix>[rmin]*<suffix>的形式,其中<prefix>为模式操作数的前缀部分,而<suffix>为模式操作数的后缀部分。
[0031]
优选地,所述步骤s2具体包括:
[0032]
s21:进行子指令流描述,所述子指令流面向处理器的待验证的功能点;
[0033]
s22:进行指令块切分描述;
[0034]
s23:进行指令块重定向描述,以使得指令块能够动态拼接;
[0035]
s24:对多个子指令流进行混合而得到目标指令流,目标指令流对应于验证场景,从而形成测试用例的主体部分;
[0036]
在所述测试用例被执行时,多个任务共用一测试用例组,并通过步骤s23的指令块重定向描述实现指令块动态拼接,使得不同的任务的目标指令流的程序代码能够一次生成并且差异化执行,以共享使用。
[0037]
在所述步骤s22中,所述主子指令流根据整体需要切分的指令块数量,在主子指令流内的多个随机位置加入标记,来标记指令块的开始和结束位置,从而实现指令块切分描述;
[0038]
在步骤s24中,在合成过程中,首先将其中一个子指令流与主子指令流混合而得到初始的目标指令流,随后各个子指令流逐个混合到该目标指令流中,以得到最终的目标指令流;
[0039]
待混合的子指令流包括分支指令流、循环指令流、函数调用指令流、乱序操作指令流、访存指令流、异常操作指令流、同步操作指令流的指令流中的至少一种。
[0040]
在使用所述访存指令流对共享数据进行访问时,各个任务允许共享使用缓存行,但是访问的只能是缓存行内的不同区域。
[0041]
优选地,所述步骤s3包括:
[0042]
s31:生成运行环境初始化的指令,该指令用于实现运行环境的初始化和加载,建立系统上下文;
[0043]
s32:生成用于指令块拼接的指令块拼接逻辑;
[0044]
s33:进行任务上下文初始化;
[0045]
s34:进行程序页表描述,所述程序页表描述用于形成多任务程序的所有任务的页表。
[0046]
优选地,在所述步骤s32中,所述指令块拼接逻辑为多任务共享的共享函数,该共享函数用于在测试用例进行指令块动态衔接时根据该共享函数来计算获取下一指令块的位置。
[0047]
优选地,在所述步骤s5中,在生成测试用例时,步骤s1所形成的指令、步骤s2形成的测试用例的测试阶段程序、步骤s3形成的测试用例的初始化阶段程序所需要的测试用例配置均由步骤s4的测试用例配置来提供和描述。
[0048]
本发明的大规模用例生成方法主要涉及复杂指令(如x86指令)与指令流描述解耦合下的指令描述方法和指令流描述方法,本发明通过指令与指令流描述的解耦合使得指令流描述中可以使用抽象指令进行指令流组织。在这种分层描述下,底层抽象指令可以使依据指令格式的指令随机单独于指令流的随机,从而带来程序模式描述的简化。
[0049]
另外,本发明通过正则表达式对复杂指令格式进行编程,以正则表达式约束目标指令的可能格式,支持复杂指令格式描述。
[0050]
本发明通过指令描述、指令流描述、程序描述、用例描述四个部分最终支持覆盖处理器目标功能的随机测试程序生成,并且通过进行用例描述,生成测试用例配置,提出目标场景的可配置,支持目标场景的参数化,实现精细场景控制下的随机测试用例生成。
[0051]
再者,本发明提出通过面向处理器的功能点的子指令流模式的混合来构建验证场景,使得验证场景非面向常规程序进行还原,在于更为直接地验证处理器目标功能;通过针对目标硬件功能的指令流描述,提供功能覆盖的直接对应,增加测试用例的验证针对性,可针对性地形成能够覆盖潜在验证场景的测试程序,并通过指令流混合使得验证场景丰富。
[0052]
区别于传统的通过不同程序行为模式指令流的直接混合形成最终程序的方式,本发明通过指令块切分描述和指令块重定向描述,提出了合成指令流经指令块切分后再衔接的动态合成方式,形成一种合成、切分、再合成的二次程序合成方式,如此,实现程序生成静态随机和动态随机的相结合。这样,在提高测试用例复杂性的同时可降低程序生成的开销,因为此时并不需要通过更多的静态随机来完成程序合成,降低了系统开销。
附图说明
[0053]
图1是现有的测试用例生成的流程图。
[0054]
图2a

图2b是现有的用于多核验证的测试用例生成的结构示意图,其中图2a示出了使用单个生成程序进行多核系统测试,图2b示出了使用不同的任务程序来进行多核系统测试。
[0055]
图3为根据本发明的一个实施例的用于处理器仿真验证的大规模用例生成方法的原理图。
[0056]
图4a

图4b为本发明的用于处理器仿真验证的大规模用例生成方法的动态指令拼接的原理图,其中,图4a示出了指令块切分描述,图4b示出了切分后的指令块的执行过程。
[0057]
图5示出了icachemiss和load_store_miss子指令流混合的配置示意图。
具体实施方式
[0058]
下面通过具体实施例和附图,对本发明做进一步详细说明。
[0059]
如图3所示,本发明的用于处理器仿真验证的大规模用例生成方法具体包括以下步骤:
[0060]
步骤s1:进行指令格式的正则化描述,得到经过描述的指令;由此,步骤s1的指令格式描述用于形成s2阶段指令流描述中的指令序列,实现了对指令格式编程的效果,能够实现复杂指令格式表示的简化,可以作为测试程序生成的基础,在下文的指令流描述的步骤中不必混合指令格式描述。
[0061]
所述步骤s1包括:
[0062]
步骤s11:进行每个指令的指令名称描述;
[0063]
其中,指令名称描述可以看作是指令的一种标识,并能一定程度体现指令功能。其中,对于复杂指令如x86指令,具有指令名称的指令可能是多种功能的融合,即一个指令名称可能对应于多个指令格式,例如,加法add指令可以是add eax,imm32的非访存形式也可以是带有访存操作的add r/m32,imm32形式。
[0064]
此外,指令允许根据功能不同划分为不同的指令子集(如写指令子集、读指令子集、算数指令子集、分支指令子集等),将指令划分成不同指令子集便于之后指令流随机从中进行指令挑选。这里的指令分组主要是从指令功能角度进行一定划分。
[0065]
步骤s12:进行每个指令的操作数描述,以得到指令的初始格式;
[0066]
其中,进行每个指令的操作数描述,是指对于每个指令的操作数个数和每个操作数的类型进行表示。
[0067]
在所述步骤s12中,在进行每个指令的操作数描述时,可增加每个指令在不同处理器模式下的操作数个数和每个操作数的类型的约束。
[0068]
所述步骤s12包括:步骤s121:列出操作数的各种可能组合。对于一个给定指令,操作数的数量以及每个操作数的类型允许发生变化,需要对于每种情况予以表示。步骤s122:对于给定的每一个操作数组合,均对该操作数组合的每个操作数的类型进行规定。
[0069]
其中,操作数具有寄存器类型、内存类型和立即数类型三个基本类型。这三个基本类型均可以限定为一般类型,如果一个操作数通过某个一般类型(例如,一般寄存器类型、一般内存类型、一般立即数类型)定义,则可以在后续的指令生成步骤中而非步骤s1中可以自动形成这个类型的一个具体表达。此外,如果存在多个操作数,多个操作数的类型允许彼此相同。
[0070]
指令格式的初始格式如下:
[0071]
<instr_name>[rmin]*
[0072]
其中,<instr_name>表示指令的指令名称,[rmin]表示一个操作数,每个操作数[rmin]的类型可以是r、m、i、n四个类型中的一个,*表示匹配0次或多次,即操作数可以有0个,1个,

或多个,r为寄存器类型的操作数,m为内存类型的操作数、i为立即数类型的操作数,n表示类型为空。也就是说,如果一个指令无操作数则表示为一个具有一个类型为n的操作数的指令。
[0073]
此外,在所述步骤s12中,进行每个指令的操作数描述,并不限于对操作数个数和操作数类型(即r,m,i)的说明,因此,所述步骤s12还可以包括:对操作数类型进行范围限定,以提供操作数随机时的约束条件。例如,限制操作数可使用的具体范围或是限定操作数的使用只能在具体处理器模式中出现。
[0074]
为获得指令的操作数规范,采用如下形式对操作数类型进行范围限定:
[0075]
t(cons0,cons1,cons
i
,cons
n
‑1)
[0076]
其中,t为操作数类型声明t=r,m,i,其中r为寄存器类型的操作数,m为内存类型的操作数、i为立即数类型的操作数。上述表达式(cons0,cons1,cons
i
,cons
n
‑1)部分为类型t的一个或多个约束。对于每个约束cons
i
,cons
i
可以约束操作数位宽或约束操作数为指定寄存器。例如,add m(32)r(eax,ebx,ecx,edx)可以用于表示add指令的第一操作数限定在32位的宽度,第二个操作数限定为通用寄存器eax、ebx、ecx、edx中的一个。为了简化指令格式
的表示过程,引入了取反操作“^”。通过取反操作可以列举不允许的可能。例如,add m(^32)r(^eax)可以表示第一操作数使用32位以外的可能宽度,第二个操作数使用eax以外的可能寄存器。
[0077]
又例如,在步骤s12中,如果操作数规定为寄存器类型,则进行范围限定包括进一步规定可用寄存器范围,由此,不同的指令子集的各个指令的可用寄存器范围不同,相同的指令子集中各个指令的可用寄存器范围也可能随指令变化有所差异,另外,对于不同处理器模式(如32位和64位的指令格式)所对应的可用寄存器范围也会加以区分。例如,32位和64位的指令格式的可用寄存器范围会发生变化,比如,操作数的类型是r类型,如果配置为32位测试程序,那么指令生成时会自动生成指令使用32位寄存器,如果是64位,那么生成指令会扩展使用64位寄存器。
[0078]
此外,也可以将操作数的类型规定为一般类型(如寄存器类型),由此,一些额外的范围限定可以以隐式方式自动地在后续的步骤s3的程序生成阶段加入,以简化操作数的描述。一般寄存器类型是指步骤s1的指令格式描述阶段是以一般性角度,对指令在不同处理器模式下进行范围限定(如可用寄存器范围的限定);隐式方式是指提供大多数情况下可以默认方式进行的操作数限定,避免重复的进行限定描述,如访存类型操作数m,其各种可能形式(如[rax],[0xffff],[rax 0xffff]都是允许的)可以自动产生出,并不需要单独对每种情况进行描述,因为规范中对这一类操作数的形式有统一规定,因此,可用寄存器范围的约束以隐式方式加入是指使用默认规则产生可能形式的操作数。在步骤s3的程序生成阶段如果发现使用的是一般类型的操作数并且操作数类型没有任何附加的范围限定(如类型m、r、i这样的一般类型且无附加约束),则按默认规则在程序生成阶段随机产生一个可能形式的操作数。例如,如果操作数为一般寄存器类型,那么在32位程序生成时默认使用8/16/32位通用寄存器,而在64位程序生成时可自动扩大寄存器使用范围到8/16/32/64位,而在后续步骤中的指令生成阶段,如果一条指令存在多个一般寄存器类型的操作数,则可以自动生成不同位宽的寄存器类型的操作数的组合,避免在步骤s1指令格式描述的步骤中对不同位宽寄存器操作数组合进行单独说明。
[0079]
再比如说,内存类型操作数对于基址、缩放以及索引的描述也可以不用单独声明,即设置为一般内存类型的操作数来默认根据规范来生成各种可能组合。
[0080]
步骤s13:进行附加功能描述,以得到指令的扩展格式。
[0081]
对于附加功能描述部分,主要适用于对指令功能进行补充说明。附加功能描述用于对一个或多个操作数来进行前缀部分和后缀部分的包裹。这里的前缀部分和后缀部分的包裹主要起到约束作用,可将包裹的描述部分抽象成一个模式操作数p,进而允许指令的操作数描述以嵌套形式表达。
[0082]
这里的前缀部分和后缀部分的约束可以是功能约束、操作数个数约束、操作数类型约束等。其中,功能约束可以实现指令功能的具体化,例如,rep指令可以有多种形式,会使用rep stosw和rep stosd分别表示存储word或double word的字符串的处理。数量约束是指对于操作进行操作数个数的规定。比如times指令可以指定对于某个操作重复若干次,即times指令会同时给出数量约束和功能约束。操作数约束是指对于操作数进行附加限制。例如,对于访存操作不但需要对地址需进行表示,同时也需要对于地址对应的数据宽度进行附加说明,这样的附加说明可归为操作数类型约束。
[0083]
因此,为了提供附加功能描述,所述指令的扩展形式为:
[0084]
<instr_name>[rminp]*
[0085]
其中,<instr>为指令名称,p为模式操作数,这里的p可展开为<prefix>[rmin]*<suffix>的形式,其中<prefix>为模式操作数的前缀部分,而<suffix>为模式操作数的后缀部分。
[0086]
此外,考虑到步骤s11中,一个指令名称可能对应于多个指令格式,因此,为了能够统一表示指令的多种指令格式,并且对每种格式进行分别说明,每种指令格式可具有不同个数的操作数。此时,指令格式的扩展形式也可以表示扩展为:
[0087]
<instr_name>[rminp]*|[rminp]*
[0088]
其中,符号“|”为不同的指令格式之间的分割符。例如,<a>[r][r]|[i]表示指令名称a包括由带有两个寄存器类型的操作数组成的指令格式和一个只有立即数类型的操作数的指令格式。
[0089]
步骤s2:利用经过描述的指令进行指令流描述和混合,得到目标指令流,该目标指令流为测试用例的主体部分,从而形成测试用例的测试阶段程序;由此,指令流描述的步骤中不必混合指令格式描述。
[0090]
在步骤s1形成了每条指令的一般描述之后,在步骤s1中,需要能够把这些指令结合起来形成指令序列,进而构成期望程序行为。
[0091]
在本实施例中,所述步骤s2具体包括:
[0092]
步骤s21:进行子指令流描述,所述子指令流面向处理器的待验证的功能点;步骤s22:进行指令块切分描述,用于使得之后混合后形成的目标指令流能够切分形成多个指令块;步骤s23:进行指令块重定向描述,以使得指令块能够动态拼接;步骤s24:对多个子指令流进行混合而得到目标指令流,目标指令流对应于验证场景,从而形成测试用例的主体部分。
[0093]
在所述步骤s21中,将能够体现硬件一定行为模式的指令序列称为一个子指令流。子指令流的长短和其中的指令可以不是固定,通过步骤s21的行为约束来表示一个子指令流的指令构成。
[0094]
步骤s22中所进行的指令块切分描述,可以使得在之后的步骤中程序能够在运行阶段根据此处的指令块切分描述来切分为指令块再拼接来达到动态拼接效果,其中,运行阶段所实现的切分是指对子指令流混合后形成的合成指令流进行的整体切分,切分中需要尽量确保切分后得到的一个指令块内保留合成指令流的各个子指令流的行为模式。
[0095]
各个子指令流中存在一个主子指令流,在步骤s22中,所述主子指令流根据整体需要切分的指令块数量,在主子指令流内的多个随机位置加入标记,这些标记作为切分点来标记指令块的开始和结束位置,从而实现指令块切分描述。具体来说,这些切分点可以被跳转指令使用,在进行指令块拼接时就是根据这些标记进行跳转,从而实现运行中的动态拼接。同时,其它子指令流可以根据其行为模式限定来形成其它行为模式的随机指令序列,这些指令序列后续可以混入一或多个指令块中。
[0096]
此外,对于定长的指令块,一般也可以直接计算开始位置,从而动态拼接时即可通过计算获得一个切分点的可能位置来完成跳转,从而能够切换到下一个指令块,而不需要在步骤s22中加入标记作为切分点。
[0097]
这里,切分可以认为是一种指令块的划分(如上所述存在隐式方式划分和显式方式划分)。这里,并不需要一个专门的切分阶段,更多是指,确保能够对合成后的程序(即测试用例)进行指令块区分。具体的拼接动作是在程序运行过程中进行。拼接功能的相应指令部分,在程序合成阶段已经合成到测试用例当中,即利用本发明的用于处理器仿真验证的大规模用例生成方法所生成的测试用例可以在运行时自主完成内部指令块的动态拼接。
[0098]
在步骤s24中,将一个通过子指令流混合形成的目标指令流作为一个验证场景,来作为测试用例的主体。目标指令流是由表示一定行为特征的一个或多个子指令合成出来的具有复杂行为的指令流,目标指令流所对应的一个验证场景可实现对处理器一个或多个目标功能的验证,即可以覆盖多个功能点的验证,其验证的功能取决于待混合的子指令流有哪些子指令流(各子指令流可用于不同功能点的验证,不同类型的子指令流可以混合,比如跳转指令流和访存指令流可以混合在一起,如此可模拟访存过程中穿插跳转的场景)。验证场景的形成可通过下文步骤s4的测试用例配置生成不同但具有共性行为的同一个测试用例组的多个测试用例,用以覆盖处理器的内部功能。这些测试用例配置提供对子指令流的行为的随机约束。子指令流合成后的目标指令流可实现对于用户程序的模拟。
[0099]
在步骤s24中,在合成过程中,首先将其中一个子指令流与主子指令流混合而得到初始的目标指令流,随后各个子指令流逐个混合到该目标指令流中,以得到最终的目标指令流。其中,子指令流中的片段可区分为不可打断和可打断指令片段,不可打断的片段可等同于一条单一指令整体插入到目标指令流的可插入位置上;可打断片段中的每条指令可逐一插入到目标指令流的可插入位置上。这里需要保证插入后的指令顺序尽量还原指令流中的原始指令顺序。合成后的目标指令流由于在步骤s22中已经打入了指令块的开始和结束标记,因此之后的步骤s3中所提供的后续指令块计算逻辑中即可根据这些标记动态计算下一指令块的具体位置(如果指令块起始位置固定也可不通过标记直接进行计算)。
[0100]
在步骤s24中,待混合的子指令流包括分支指令流、循环指令流、函数调用指令流、乱序操作指令流、访存指令流、异常操作指令流、同步操作指令流等多种类型的指令流中的至少一种。对于分支指令流和访存指令流还可进行更进一步细分,形成特定分支指令流或者特定访存指令流。在步骤s24中,对多个子指令流进行混合的过程中,分支指令流中的多种特定分支指令流允许进行混合。访存指令流的混合过程也类似,并且特定访存指令流也可以和特定分支指令流进行混合。
[0101]
在本实施例中,对于非连续程序地址访问需要考虑多种跳转形式的存在,需要目标指令流来对通过直接跳转、间接跳转、循环操作以及通过call/ret建立的函数访问过程等进行实现(call/ret建立的函数访问过程与其它函数访问过程的不同在于需要借助堆栈完成)。为了形成不同跳转形式的模拟,需要形成特定分支指令流来作为目标指令流的一部分,每种特定分支指令流作为目标指令流的中的子指令流可以实现对处理器前端不同功能的验证。在本实施例中,在程序行为模拟中,对于非连续程序地址访问过程(即跳转过程),需要通过分支指令流的类型的子指令流插入到目标指令流的可插入位置来形成。
[0102]
在具有跳转功能的分支指令流之间则可以混合多种其它类型的子指令流中的指令,如计算指令流以及访存指令流的指令,以实现其他功能点的验证。另外,也可以混合具有异常行为的指令,从而验证在跳转和一些事件处理同时存在情况下的处理过程,验证处理器前端和后端交互下的处理器行为是否能够正常。例如,可通过混合前端验证的子指令
流和后端验证的子指令流形成混合的验证场景。
[0103]
子指令流进行混合而得到的目标指令流可以实现的功能点涉及处理器前端(包括指令长度解码,指令解码器、分支预测器、指令队列等)、后端(分配单元、重命名单元、乱序引擎、冲排序缓冲等)、缓存子系统(包括内存管理单元、内存排序缓冲,一级缓存、二级缓存、三级缓存、片内总线等)。通过子指令流的形成首先完成基础验证场景的覆盖,再通过子指令流混合扩展验证场景,这些扩展验证场景也将作为目标场景,目标场景可以看作是基础功能点验证的丰富。例如,目标指令流可以实现的功能点可以包括:较多跨指令缓存的缓存行的访问、分散在各个页面的指令的访问、对于指令数据的修改等等。通过这些功能点可以实现的验证包括:通过较多跨指令缓存的缓存行的访问可进行指令缓存缺失的相关功能验证;通过分散在各个页面的指令的访问,进而可以实现itlb(instruction translation look

aside buffer)缺失的相关功能验证;通过对于指令数据的修改,可以实现smc(self modifying code)功能的验证。
[0104]
其中,访存指令流主要用于模拟不同访存行为。访存结果的正确与否通过与功能模型的比对进行验证。功能模型可以认为是已有的,如(qemu),并且会在实际进行硬件测试验证阶段使用。
[0105]
一般读写指令流属于其中一种特定的访存指令流,一般读写指令流即随机产生读写指令,并且令读写指令的地址完全随机形成。为了简化读写结果的比对,内存数据的使用需避免任务间的影响。因此,将一般读写指令流的访问数据限定为位于非共享内存中,即每个任务使用的物理内存避免出现重叠。在这类特定的访存指令流生成的过程中,可以对读写比例进行约束,同时也可以对访存指令的生成强度进行限定。由于一般读写指令流的访问限定为对非共享内存的访问,这会令不同任务的存储空间隔离,因此不同任务的数据访问虚拟地址不会映射到相同物理地址,因而不必对虚拟地址进行限定。
[0106]
此外,访存指令流除了模拟对于任务私有数据的访问,另外也需要对于共享数据的访问进行模拟。当对于共享数据进行访问的过程中不同任务可能在非常相近的时间内对共享数据进行读写。这里读写顺序的控制对于待测处理器和功能模型来说可能会不同。功能模型结果并不和待测处理器的时序对应因此无法保证功能模型的读写顺序和待测处理器的完全吻合。
[0107]
为了实现共享操作时,用于对共享数据的访问进行模拟的访存指令流仍然能够正常和功能模型进行访问结果的比对,在使用所述访存指令流对共享数据进行访问时,本发明采用了一种缓存行内隔离技术。缓存行内隔离是指各个任务允许共享使用缓存行,但是访问的只能是缓存行内的不同区域。每个任务会分配缓存行内一个固定区域进行访问。要求各个任务分配的区域不存在重合,另外每个任务不会访问除分配区域外的区域。也就是说,即任务所需数据在缓存行内部具有按任务隔离效果。由于数据更新和数据获取来自同一个任务,因此每次读取的读取结果是确定的。这样,对于各个缓存行的任务绑定区域只会有所对应任务的数据更新,并且这个更新顺序是唯一的。更新顺序唯一是指每个任务可访问的空间是相互分开的,避免一个物理位置数据被超过一个任务访问。因为是被一个确定的任务更新且无更新冲突,因此更新顺序可以是确定的,或者说是唯一的。
[0108]
正常情况下,一个任务在对所分配的缓存行内的区域进行读取的过程中,得到的结果应该是该进程最后一次更新中所写入的内容。任一个缓存行会面对多个任务对缓存行
内不同区域的访问,并且其间也可能出现缓存行踢出的可能。如果缓存一致性维护并未保证整个缓存行是所有任务中最后一次更新时达到的状态,就可能出现一个任务在更新缓存行后所读到的是旧的数据。这里的缓存更新是多个任务对于一个共享缓存行共同作用的结果。本发明通过上文所述的每个任务会分配缓存行内一个固定区域进行访问,来保证整个缓存行中读取到的所有数据均是所有任务中最后一次更新时达到的状态。该隔离机制避免处理器提供的缓存一致性维护所得到的结果和功能模型(如qemu)所得到的结果出现差异,防止无法进行有效比对的情况出现。
[0109]
因此,用于对共享数据的访问进行模拟的访存指令流需要进行虚拟地址限定,考虑到不同任务虚拟地址有可能映射到相同物理地址(即存储空间不是隔离效果),需要通过虚拟地址限定来达到共享区域内数据访问按任务隔离的效果。用于对共享数据的访问进行模拟的访存指令流的形成主要是通过对访存地址和虚拟地址到物理地址映射进行限定,来实现任务私有或任务间共享数据的使用。
[0110]
此外,通过这样的地址限定也可以形成用于模拟跨缓存行或着跨内存页面的访存指令流,以验证处理器的跨缓存行跨页面数据访问是否能够正常,跨行和跨页操作的一致性维护往往会进行更多处理,因为同时涉及了不止一个缓存行数据的使用,对于跨页访问来说还会涉及多个地址映射的连续访问,也是验证过程的一个验证场景。除上述验证场景外,特定访存指令流还覆盖了缓存行缺失模拟以及缓存行踢出模拟。对于任务私有或共享内存的访问都可以进行读写比例控制,另外可同时控制读写访问强度。通过增加读写访问强度,可以提供如缓存子系统内部填充缓冲等的压力测试。
[0111]
在现有技术中,在多任务程序测试中,需要令目标指令流所对应的验证场景能够以多任务方式进行测试;多核处理器测试中需要提供多任务程序进行相应验证,任务数取决于处理器的逻辑核的数量,并且一般每个处理器核运行的任务需要具有差异性,即形成对于每个任务来说不同的目标指令流。本发明的方法主要通过生成相同程序并令不同任务的执行能够具有差异化的方式来避免为每个任务单独进行程序生成所带来的额外开销,提高测试用例生成的效率。具体在本发明的方法中,一个验证场景下的测试用例通过步骤s22的指令块切分描述(如图4a所示)以及步骤s23阶段提供的指令块重定向描述形成指令块动态拼接的基础,使得本发明的方法所生成的测试用例能够具有分块执行效果,保证了单一程序可产生出对于每个任务的不同的执行阶段的指令流(如图4b所示),因此不需要静态地为每个任务单独生成对应的目标指令流,避免静态方式多次分别形成各个任务的测试程序,进而在减少代码冗余的同时提高生成速度。这里,每个指令块是在步骤s24子指令流混合后形成的,其中含有覆盖验证场景所需的相应代码片段。分块执行的支持使得不同任务能够通过选择不同代码块执行形成不同的执行效果,与此同时,也能在达到预期验证需要的同时,避免为每个任务单独生成一套测试用例,而是多个任务共用一测试用例组。通过步骤s23的指令块重定向描述,使得在指令块执行完成后能够动态拼接下一指令块,即一个指令块结束执行后能转入下一指令块选择逻辑以随机选择下一个指令块,进而能够实现指令块动态拼接的效果,使得不同的任务的目标指令流的程序代码可以一次生成并且差异化执行,以共享使用。指令块动态拼接逻辑在s32阶段生成,对于不同任务来说是公共的。这里所述的动态拼接逻辑可以以规定的拼接模式进行或以随机拼接方式进行。在实际执行阶段通过动态拼接处理可令不同任务达到不同的拼接效果,最终达到不同任务执行过程的差异
化。目标指令流的程序代码共享主要通过设置不同任务的页表,将代码空间映射到一块相同物理位置。这里的任务页表生成部分通过后文的步骤s34完成。
[0112]
综上,步骤s2形成的目标指令流(即测试用例的主体)通过指令块动态拼接实现不同的拼接方式,一方面可以达到在已有的子指令流混合基础上进一步丰富程序行为的效果,另一方面提供了多任务程序差异化执行效果的支撑,有助于实现多任务程序的验证。
[0113]
由此,目前的指令流混合如riscv

dv中提供的指令流混合主要面向表示程序模式的子指令流的混合,体现的是对程序行为的还原。本发明中的子指令流描述对传统描述进行了细分,通过指令块动态拼接实现不同的拼接方式,实现了动态随机,从而主要面向硬件功能的覆盖。
[0114]
步骤s2形成的是测试用例的主体所对应的目标指令流,这个目标指令流对应于一个或多个任务,从而形成了测试阶段程序,测试阶段程序是步骤s2形成的混合了子指令流的测试用例的主体部分。
[0115]
另外,由于任务本身需要初始化,即需要建立任务上下文,需要实现初始化阶段程序,使得任务运行在系统的运行环境之上,底层系统环境提供基础特性以及例如中断等一些基础功能,而这些基础环境功能的使用需要进行运行环境的初始化。最终生成的测试用例均包括初始化阶段程序和步骤s2所形成的测试阶段程序,因此,还需要包括步骤s3,来生成测试用例的初始化阶段程序,用于实现运行环境的初始化过程。每个测试用例在初始化阶段程序执行结束后会进入到测试阶段程序的入口位置。测试阶段程序的入口位置对于不同测试用例可能不同,但对于同一个测试用例来说,各个任务各自的测试用例使用相同的测试阶段程序的入口。每个任务的入口即作为测试用例的主体部分的测试阶段程序第一个指令块起始。测试阶段程序的入口位置对于不同测试用例组可能不同,但对于同一个测试用例组来说,同一个测试用例组的各个任务所对应的测试用例使用相同的测试阶段程序的入口。
[0116]
步骤s3:进行程序运行基础描述,以形成测试用例的初始化阶段程序;
[0117]
由此,步骤s3主要用于初始化阶段的相应指令片段生成,用于构建测试程序所需的基础运行环境。可以认为这个部分为系统软件部分,起到操作系统的作用,但功能比传统操作系统简单许多,旨在提供支撑用户程序运行的底层初始化。
[0118]
由于步骤s2形成覆盖测试功能点的测试程序主体,提供了面向测试功能点的子指令流的混合,并且支持上述的显示方式或隐式方式的指令块区分(每个指令块中可能具有多个子指令流的片段);步骤s3形成支撑测试程序运行的必要逻辑,提供了包括运行环境初始化以及任务公共的指令块拼接功能等。因此,如图1所示,s3对应测试用例的头的部分,s2提供测试用例的主体,两部分合成形成完整的测试用例,使得本发明的测试用例(即测试程序)在测试时无须运行在完整操作系统之上。
[0119]
其中,本发明利用一个测试用例生成工具来自动执行所述步骤s2和步骤s3(即生成测试用例的主体和头的步骤),从而利用测试用例生成工具自动生成了测试用例。所述测试用例生成工具用于自动构造完整的测试用例,允许处理器从第0条指令开始执行直到完成测试用例的完整测试,包括所有必要的初始化,覆盖系统软件和用户程序功能。测试用例生成工具比如可以是google面向risc

v处理器的测试用例生成工具riscv

dv(参见https://github.com/google/riscv

dv)。
[0120]
所述步骤s3具体包括:
[0121]
步骤s31:生成运行环境初始化的指令;该指令用于实现运行环境的初始化和加载,建立系统上下文;
[0122]
步骤s32:进行指令块的动态拼接描述,即生成用于指令块拼接的指令块拼接逻辑;
[0123]
步骤s33:进行任务上下文初始化,即,通过控制寄存器来进行系统特性设置、任务页表绑定、架构寄存器初始化、指令块拼接初始化等;
[0124]
步骤s34:进行程序页表描述,所述程序页表描述用于形成多任务程序的所有任务的页表。
[0125]
由此,步骤s31用于初始化应用环境,建立系统上下文;步骤s32提供指令块动态拼接中的一些公共功能(例如拼接功能),提供类似于共享库的使用效果,并且通过步骤s32的指令块拼接描述,可以实现指令块的动态组装,进而形成丰富的测试用例。而步骤s33通过任务初始化,完成了任务上下文中的非页表的部分的初始化;步骤s34通过程序页表描述,完成了任务上下文中的页表部分的初始化,因此步骤s33和步骤s34共同完成了任务上下文的初始化,提供任务启动前任务的必要准备工作。
[0126]
由此,本发明的用于处理器仿真验证的大规模用例生成方法通过步骤s31的运行环境初始化建立系统上下文,通过步骤s33的任务初始化和步骤s34的页表初始化建立任务上下文,从而实现了初始化阶段程序。该初始化阶段程序用于实现运行环境的初始化过程,即建立系统上下文和任务上下文,形成系统执行环境和应用执行环境;并且通过步骤s32的指令块拼接描述,可以实现指令块的动态组装,进而形成丰富的测试用例。
[0127]
在步骤s3中,程序描述通过保证系统上下文、任务上下文和应用上下文的有效,从而能够生成完整的测试程序来执行目标指令流。
[0128]
在步骤s31中,通过运行环境的初始化并通过相应指令完成运行环境所需数据的加载,能够实现系统上下文的建立。系统上下文包括了全局描述符表、局部描述符表、中断描述符表等系统信息。由此,在建立供程序运行的运行环境后,可提供指令块切分支持下所需要具有的全局描述符表以及局部描述符表,进而能够实现不同代码段以及数据段的切换;通过中断描述符表,可以建立中断服务程序注册。在步骤s31中,需要通过一段运行环境初始化的指令来加载程序中预设的全局描述符表(其中全局描述符表包括程序执行中涉及的各个指令段的描述符信息)。在步骤s33和步骤s34中,任务上下文包括了用于任务描述的部分,包括了任务的tss结构(即非页表部分)和与任务对应的页表信息(即页表部分)等。任务的tss结构通过tss结构描述符在全局描述表中注册。在处理器开启分页后,每个任务需要绑定对应的页表信息,从而实现虚拟地址到物理地址的映射。页表通常是系统软件维护,建立用户需要的物理空间。所建立的地址映射关系,处理器内部的内存管理单元(mmu)也可提供自动的查找获取,从而在指令的执行过程中确定内存访问的具体物理位置。
[0129]
也就是说,步骤s3用于形成测试用例的程序头,这部分程序头的指令主要提供初始化功能。所述步骤s31包括:全局描述符表初始化、局部描述符表初始化、中断描述符表初始化、中断处理程序初始化、全局描述符表加载、局部描述符表加载、中断描述符表加载、不同内存类型区间的指定(通过mtrr)。所述步骤s33中,任务初始化包括tss初始化。所述步骤s34包括任务的页表信息的初始化。
1.由此,本发明所生成的每个测试用例在运行时,步骤s3的初始化阶段程序执行结束后会进入到测试阶段程序的入口位置,测试用例在运行过程中,进入测试程序入口就是进入了用户空间程序的执行,各任务根据各自的指令流进行执行,这一部分属于用户空间程序(即步骤s2形成的测试阶段程序)执行的部分。此外,在执行中出现异常时会自动切换到系统程序处理(即步骤s3形成的初始化阶段程序),在中断处理结束后会通过中断返回继续用户空间程序的执行。在任务执行中如果出现错误或异常,则系统程序会进行介入。如访存指令处理中,当出现缺页异常时,通过中断描述符标中注册的缺页处理程序可以完成对应任务缺失页表项的动态建立,进而模拟用户程序和系统程序穿插的效果。
[0130]
在所述步骤s32中,用于指令块拼接的指令块拼接逻辑为多任务共享的共享函数,该共享函数用于在测试用例进行指令块动态衔接时根据该共享函数来计算获取下一指令块的位置。在本实施例中,这里的共享函数存在有多种形态,用于形成不同的程序行为模式,另外也起到模拟共享函数库使用的效果。例如,在指令块拼接过程以顺序方式或以随机方式进行指令块拼接会具有不同的程序行为,实际应用中,共享函数可相应扩展,使得指令块拼接方式可根据需要进行扩展。
[0131]
共享函数可以认为是类似于一个随机函数,但是除随机方式外,该共享函数也可能是提供确定方式的指令块选择。
[0132]
在本发明中,由于步骤s32的指令块动态拼接的引入,具体使用的指令块会不断变化。在步骤s32中,加入动态拼接的描述,从而进一步支持拼接逻辑的可变化,使得在步骤s32的执行过程中动态选择相应的指令片段。也就是说,步骤s2的指令流描述阶段合成出的目标指令流是对每个任务来说相同的代码,只是每个任务在步骤s32中会利用整个目标指令流的代码的不同部分。
[0133]
由此,对于最终生成的测试用例来说,该测试用例在运行时可以自发地利用步骤s32提供的指令流拼接逻辑进行自动化的指令块动态拼接过程。因为拼接过程不断调整程序行为,因此测试程序验证场景可得到进一步丰富。具体来说,每个任务的指令流是动态形成的,在完成当前的指令块的处理时,每个任务会随机选择下一个指令块。并且,通过在步骤s32中,加入任务扰动因子,保证了即便两个任务挑选到相同的指令块后,下一个处理的指令块每个任务会有所不同。在进行指令块动态拼接的随机处理过程中,往往需要通过一个随机数生成过程,这里需要保证程序的确定性从而使得验证发现错误后可以复现,同时也需要具有随机效果。一个方法是采用伪随机方式进行随机数生成保证随机数生成的确定性。这里需要避免每个任务以确定的方式生成相同的随机数,进而导致不同程序根据该随机数产生了相同的后续行为。本发明使用了扰动因子来影响随机数的生成,具体来说这个扰动因子就是每个任务的任务标识,从而可以通过不同的扰动因子使得不同任务的产生的随机数序列发生改变。扰动因子不进行单独描述或配置,可以认为对于每个任务是固定的。在本实施例中,该扰动因子即为任务标识。扰动因子设置在步骤s2生成的代码片段中,如果需要随机选择指令块,这个随机选择的计算过程通过加入此扰动因子确保每个任务的指令块选择是不同的。
[0134]
对于步骤s32提供的指令块拼接逻辑,最终所实现的拼接功能主要有三种形式:1)对于定长指令块可直接进行指令块位置计算并完成跳转,所切换到的指令块可随机选择;2)对于非定长指令块,借助显式的指令块起始位置标记完成跳转,所切换到的指令块可随
机选择;3)固定指令块的切换,支持顺序指令块切换,并可循环。
[0135]
为了实现多任务程序运行的支持,一些线程独立的状态需要能够任务各自维护。在步骤s33中,通过tss初始化可指定任务各自的栈空间(即任务私有空间)(栈空间的初始化归属于tss的初始化)。利用这些私有空间可以进行每个任务执行状态维护,如每个任务的跳转跟踪计数是独立进行的,这个计数正是存放在任务私有空间当中。另外,在步骤s34中,通过构造页表可以实现任务共享状态存储空间的形成,通过将不同任务的存储空间映射到共同物理位置完成。该任务共享状态存储空间和前述的一般数据共享模拟有所不同(例如,与上文的共享缓存行不同),主要存放一些任务间的公共信息,如指令片段位置信息,并且这部空间在初始化完成后并不需要进行修改。
[0136]
步骤s4:进行用例描述,以生成测试用例配置;
[0137]
步骤s5:利用所述指令、测试用例的测试阶段程序、测试用例的初始化阶段程序和所述测试用例配置来生成测试用例。
[0138]
在所述步骤s5中,在生成测试用例时,步骤s1所形成的指令、步骤s2形成的测试用例的测试阶段程序、步骤s3形成的测试用例的初始化阶段程序所需要的测试用例配置均由步骤s4的测试用例配置提供和描述。
[0139]
在步骤s4中,生成同一个测试用例组的不同的测试用例时,可以通过所述步骤s4中的同一个测试用例配置进行描述,即允许根据同一测试用例组的模版随机产生出具有相似行为模式但有所变化的多个不同的测试用例。
[0140]
如上文所述,测试用例对应的完整的测试用例组可利用测试用例生成工具来执行步骤s2和步骤s3,从而自动生成。
[0141]
在所述步骤s5中,通过s4测试用例配置中的主体约束条件以及s2中的指令流描述产生出测试用例的主体;并通过s4测试用例配置中的运行环境约束条件形成s3中的测试用例的程序头,来生成测试用例。以上两部分(测试用例的主体、程序头)生成的总和形成完整的测试用例。s4步骤的测试用例配置实际是一种测试用例的约束,程序生成按照测试用例确定的验证目标(即所需的程序功能点)进行随机用例生成。
[0142]
在步骤s4中,所述测试用例配置,包括:测试用例由哪些子指令流组成,以及各个子指令流的形成参数(如图5所示)。各个子指令流的形成参数包括了各子指令流打开关闭的信息以及子指令流自身属性的一些设置。
[0143]
如图5所示,在本实施例中,对处理器前端、乱序、访存子系统的测试用例进行了分类说明,形成对于处理器子系统的针对性测试。由于子指令流是根据处理器验证点形成的,这些子指令流模式包括处理器前端(包括指令长度解码,指令解码器、分支预测器、指令队列等)、后端(分配单元、重命名单元、乱序引擎、冲排序缓冲等)、缓存子系统(包括内存管理单元、内存排序缓冲,一级缓存、二级缓存、三级缓存、片内总线等)几个大类。用于每个大类验证的子指令流组合形成了相应的测试用例组,从而可以通过测试用例组的测试用例针对性的对处理器局部功能进行验证。为了进一步达到全片测试效果,这些测试用例可以进一步混合形成全片测试用例模版。目前测试用例的模版中的基础的测试用例配置说明其能够用于32位或者64位运行环境当中,另外这些基础的测试用例配置说明可以迁移从单核双线程测试迁移到多核多线程测试(如图5中tasks=2为单核双线程配置,可以配置形成更多任务的测试)。
[0144]
综上,本发明的大规模用例生成方法主要涉及复杂指令(如x86指令)与指令流描述解耦合下的指令描述方法和指令流描述方法,这种解耦合使得指令流描述中可以使用抽象指令进行指令流组织。在这种分层描述下,底层抽象指令可以使依据指令格式的指令随机单独于指令流的随机,从而带来程序模式描述的简化。
[0145]
另外,本发明通过正则表达式对复杂指令格式进行编程,以正则表达式约束目标指令的可能格式,支持复杂指令格式描述。
[0146]
本发明通过指令描述、指令流描述、程序描述、用例描述四个部分最终支持覆盖处理器目标功能的随机测试程序生成,并且通过进行用例描述,生成测试用例配置,提出目标场景的可配置,支持目标场景的参数化,实现精细场景控制下的随机测试用例生成。
[0147]
再者,本发明提出通过面向处理器的功能点的子指令流模式的混合来构建验证场景,使得验证场景非面向常规程序进行还原,在于更为直接地验证处理器目标功能;通过针对目标硬件功能的指令流描述,提供功能覆盖的直接对应,增加测试用例的验证针对性,可针对性地形成能够覆盖潜在验证场景的测试程序,并通过指令流混合使得验证场景丰富。
[0148]
区别于传统的通过不同程序行为模式指令流的直接混合形成最终程序的方式,本发明通过指令块切分描述和指令块重定向描述,提出了合成指令流经指令块切分后再衔接的动态合成方式,形成一种合成、切分、再合成的二次程序合成方式,如此,实现程序生成静态随机和动态随机的相结合。这样,在提高测试用例复杂性的同时可降低程序生成的开销,因为此时并不需要通过更多的静态随机来完成程序合成,降低了系统开销。
[0149]
本发明未详细阐述部分属于本领域技术人员的公知技术。
[0150]
以上所述,仅为本发明中的具体实施方式,但本发明的保护范围并不局限于此,任何熟悉该技术的人在本发明所揭露的技术范围内,可理解想到的变换或替换,都应涵盖在本发明的包含范围之内,因此,本发明的保护范围应该以权利要求书的保护范围为准。
再多了解一些

本文用于企业家、创业者技术爱好者查询,结果仅供参考。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献