代码路径
main函数
def_main():parser=argparse.ArgumentParser()parser.add_argument('--op',type=Ops,choices=Ops,required=True)parser.add_argument('--dir-metadata',type=pathlib.Path,required=True)parser.add_argument('--dir-out',type=pathlib.Path,required=False)parser.add_argument('--args-list',type=str,required=False)parser.add_argument('--field',type=str,required=False)args=parser.parse_args()ifargs.op==Ops.CREATE:if(pathlib.Path(args.dir_metadata)/'metadata.pickle').exists():logger.error("Build metadata already exists, not recreating from scratch.")returnmd=RegressionMetadata.arg_list_initializer(dir_metadata=args.dir_metadata,dir_out=args.dir_out,git_commit=get_git_revision_hash(),args_list=args.args_list)md._get_ibex_metadata()md.tests_and_counts=md.get_tests_and_counts()ifnotmd.tests_and_counts:raiseRuntimeError("md.tests_and_counts is empty, cannot get TEST.SEED strings.")fortest,count,testtypeinmd.tests_and_counts:fortestseedinrange(md.seed,md.seed+count):tds_str=f"{test}.{testseed}"trr=TestRunResult(passed=None,failure_message=None,testtype=testtype,testdotseed=tds_str,testname=test,seed=testseed,rtl_simulator=md.simulator,iss_cosim=md.iss,dir_test=md.dir_tests/tds_str,metadata_pickle_file=md.pickle_file,pickle_file=md.dir_metadata/(tds_str+".pickle"),yaml_file=md.dir_tests/tds_str/'trr.yaml')iftesttype==TestType.DIRECTED:trr.directed_data=(next(filter(lambdai:i['test']==test,directed_test_schema.import_model(md.directed_test_data).get('tests'))))md.tests_pickle_files.append(trr.pickle_file)trr.export(write_yaml=True)md.export(write_yaml=True)ifargs.op==Ops.PRINT_FIELD:md=RegressionMetadata.construct_from_metadata_dir(args.dir_metadata)if(args.field=='riscvdv_tds'):tds_list=[]fortest,count,testtypeinmd.tests_and_counts:fortestseedinrange(md.seed,md.seed+count):iftesttype==TestType.RISCVDV:tds_list.append(f"{test}.{testseed}")print(" ".join(tds_list))returnif(args.field=='directed_tds'):tds_list=[]fortest,count,testtypeinmd.tests_and_counts:fortestseedinrange(md.seed,md.seed+count):iftesttype==TestType.DIRECTED:tds_list.append(f"{test}.{testseed}")print(" ".join(tds_list))returnvalue=getattr(md,args.field)ifvalueisNone:raiseRuntimeError("Field requested is not present or not set in the regression metadata object")logger.debug(f"Returning value of field{args.field}as{value}")print(str(value))main函数在metadata.py文件中解析命令行参数并基于指定的操作执行相应任务。以下是其主要步骤:
解析命令行参数:
--op: 指定操作类型,值为Ops枚举中的一个(CREATE或PRINT_FIELD)。--dir-metadata: 指定存储构建元数据的目录。--dir-out: 可选参数,指定回归构建和测试进行的目录。--args-list: 可选参数,输入形式为'KEY=VALUE KEY2=VALUE2'的字符串。--field: 可选参数,当操作为PRINT_FIELD时指定要打印的字段。
执行操作:
CREATE:
- 检查
metadata.pickle文件是否已存在,若存在则记录错误信息并退出。 - 调用
RegressionMetadata.arg_list_initializer初始化元数据对象,传入必要参数。 - 调用
_get_ibex_metadata获取更多派生的 Ibex 特定元数据。 - 调用
get_tests_and_counts设置要使用的测试及其计数。 - 将每个测试对象保存到磁盘并将其路径添加到
tests_pickle_files列表中。 - 将新建的
RegressionMetadata对象导出保存到磁盘。
- 检查
PRINT_FIELD:
- 调用
RegressionMetadata.construct_from_metadata_dir从元数据目录构造元数据对象。 - 根据
--field参数打印相应字段的值。如果字段包含测试的列表,则分别处理并打印测试的test.seed字符串。
- 调用
CREATE操作
这部分代码是main函数中的一个分支,用于处理CREATE操作。这段代码的主要功能是根据传入的参数创建一个新的元数据对象,并设置相关的回归测试配置。详细分析如下:
检查现有元数据:
- 检查
metadata.pickle文件是否存在于--dir-metadata指定的目录中。如果存在,记录错误信息并返回,不会重新创建元数据。
- 检查
初始化元数据对象:
- 调用
RegressionMetadata.arg_list_initializer方法,传入dir_metadata、dir_out、git_commit和args_list参数,初始化一个新的RegressionMetadata对象。 git_commit通过get_git_revision_hash方法获取当前的 Git 提交哈希值。args_list是一个'KEY=VALUE KEY2=VALUE2'形式的字符串,用于传递初始化参数。
- 调用
获取 Ibex 特定的元数据:
- 调用
md._get_ibex_metadata方法,获取更多派生的 Ibex 特定元数据。
- 调用
设置测试和计数:
- 调用
md.get_tests_and_counts方法,解析riscv-dv和directed-test结构化数据(例如testlist.yaml和directed_testlist.yaml),设置要运行的测试及其计数。 - 如果
md.tests_and_counts为空,抛出运行时错误。
- 调用
设置每个测试的元数据对象:
- 遍历
md.tests_and_counts中的测试和计数,为每个测试创建一个TestRunResult对象。 - 对于每个测试的每个计数,生成
test.seed字符串(例如test.1、test.2等)。 - 初始化
TestRunResult对象,传入相关参数,包括测试类型、测试名称、种子、模拟器、协同仿真等。 - 如果测试类型是
DIRECTED,从directed_test_schema中获取构建命令所需的数据。 - 将每个
TestRunResult对象的路径添加到md.tests_pickle_files列表中。 - 将
TestRunResult对象导出到磁盘。
- 遍历
导出元数据对象:
- 调用
md.export方法,将新的RegressionMetadata对象导出保存到磁盘。
- 调用
ifargs.op==Ops.CREATE:if(pathlib.Path(args.dir_metadata)/'metadata.pickle').exists():logger.error("Build metadata already exists, not recreating from scratch.")returnmd=RegressionMetadata.arg_list_initializer(dir_metadata=args.dir_metadata,dir_out=args.dir_out,git_commit=get_git_revision_hash(),args_list=args.args_list)md._get_ibex_metadata()md.tests_and_counts=md.get_tests_and_counts()ifnotmd.tests_and_counts:raiseRuntimeError("md.tests_and_counts is empty, cannot get TEST.SEED strings.")fortest,count,testtypeinmd.tests_and_counts:fortestseedinrange(md.seed,md.seed+count):tds_str=f"{test}.{testseed}"trr=TestRunResult(passed=None,failure_message=None,testtype=testtype,testdotseed=tds_str,testname=test,seed=testseed,rtl_simulator=md.simulator,iss_cosim=md.iss,dir_test=md.dir_tests/tds_str,metadata_pickle_file=md.pickle_file,pickle_file=md.dir_metadata/(tds_str+".pickle"),yaml_file=md.dir_tests/tds_str/'trr.yaml')iftesttype==TestType.DIRECTED:trr.directed_data=(next(filter(lambdai:i['test']==test,directed_test_schema.import_model(md.directed_test_data).get('tests'))))md.tests_pickle_files.append(trr.pickle_file)trr.export(write_yaml=True)md.export(write_yaml=True)PRINT_FIELD操作
这段代码处理PRINT_FIELD操作,用于从构建元数据对象中打印特定字段的值。详细分析如下:
构建元数据对象:
- 调用
RegressionMetadata.construct_from_metadata_dir方法,从--dir-metadata指定的目录中构建元数据对象md。
- 调用
处理特殊字段:
- 检查
--field参数是否为riscvdv_tds或directed_tds。 - 如果是
riscvdv_tds,遍历md.tests_and_counts列表,筛选出TestType.RISCVDV类型的测试,并生成test.seed字符串(例如test.1、test.2等)。将这些字符串组成的列表打印出来。 - 如果是
directed_tds,类似地,筛选出TestType.DIRECTED类型的测试,并生成test.seed字符串,打印出来。
- 检查
获取并打印字段值:
- 使用
getattr函数获取md对象中指定字段的值。 - 如果值为
None,抛出运行时错误,提示该字段不存在或未设置。 - 记录调试信息,打印字段值。
- 使用
ifargs.op==Ops.PRINT_FIELD:md=RegressionMetadata.construct_from_metadata_dir(args.dir_metadata)if(args.field=='riscvdv_tds'):tds_list=[]fortest,count,testtypeinmd.tests_and_counts:fortestseedinrange(md.seed,md.seed+count):iftesttype==TestType.RISCVDV:tds_list.append(f"{test}.{testseed}")print(" ".join(tds_list))returnif(args.field=='directed_tds'):tds_list=[]fortest,count,testtypeinmd.tests_and_counts:fortestseedinrange(md.seed,md.seed+count):iftesttype==TestType.DIRECTED:tds_list.append(f"{test}.{testseed}")print(" ".join(tds_list))returnvalue=getattr(md,args.field)ifvalueisNone:raiseRuntimeError("Field requested is not present or not set in the regression metadata object")logger.debug(f"Returning value of field{args.field}as{value}")print(str(value))RegressionMetadata
RegressionMetadata类用于管理和存储与 Ibex 核心回归测试相关的元数据。这个类包含了多个属性和方法,以下是详细解释:
类的属性:
dir_out和dir_metadata:输出目录和元数据目录路径。git_commit:Git 提交哈希。creation_datetime:创建时间。pickle_file和yaml_file:存储元数据的文件路径。raw_args_str和raw_args_dict:构造函数传入的参数字符串和字典。seed、waves、cov、cosim、simulator、iss、test、verbose、iterations、signature_addr、ibex_config、dut_cov_rtl_path:构建和测试相关的配置参数。tests_and_counts:测试和迭代次数的列表。isa_ibex和isa_iss:ISA 配置。run_rtl_timeout_s:RTL 运行超时时间。- 各种文件路径:如
ibex_configs、ibex_riscvdv_simulator_yaml、ibex_riscvdv_customtarget、ibex_riscvdv_testlist等。 - 构建日志和命令:如
riscvdv_build_log、riscvdv_build_stdout、riscvdv_build_cmds等。 - 环境变量:
environment_variables。 - 各种项目目录:如
ibex_root、riscvdv_root、ot_lowrisc_ip等。
类的方法:
__post_init__:初始化后设置相关路径和环境变量。_setup_directories:设置目录变量。_get_ibex_metadata:获取 Ibex 配置参数。arg_list_initializer:从输入字符串初始化字段,返回一个RegressionMetadata对象。construct_from_metadata_dir:从元数据目录构造元数据对象。get_tests_and_counts:获取测试和迭代次数的列表。process_riscvdv_testlist:从 riscvdv 测试列表提取测试信息。process_directed_testlist:从定向测试列表提取测试信息。
使用场景:
- 在
_main()函数中,根据命令行参数执行创建新元数据或打印特定字段的操作。 - 通过
arg_list_initializer方法从参数字符串创建元数据对象。 - 通过
_get_ibex_metadata方法获取 Ibex 的特定配置。 - 通过
get_tests_and_counts方法设置要运行的测试列表。
这个类集中管理与回归测试相关的所有元数据,确保构建过程中的各个配置和测试参数能够被正确初始化和使用。
main函数中的CREATE分支数据流
main函数中的CREATE分支主要用于创建新的元数据对象并将其导出到磁盘。以下是详细的步骤分析:
解析命令行参数:
- 使用
argparse模块解析命令行参数,其中包括操作类型(--op)、元数据目录(--dir-metadata)、输出目录(--dir-out)和参数列表(--args-list)。
- 使用
检查元数据文件是否存在:
- 如果元数据文件
metadata.pickle已经存在,则输出错误信息并终止操作,避免重复创建。
- 如果元数据文件
初始化元数据对象:
- 调用
RegressionMetadata.arg_list_initializer方法,从参数列表初始化元数据对象。该方法将参数字符串解析成键值对,并根据类定义中的字段类型进行类型转换。 - 初始化后的对象包含构建和测试的所有配置参数。
- 调用
获取 Ibex 配置:
- 调用
md._get_ibex_metadata()方法,获取 Ibex 的特定配置参数,并进行必要的检查(如迭代次数和种子值的合法性)。
- 调用
设置测试和迭代次数:
- 调用
md.get_tests_and_counts()方法,解析 riscvdv 和定向测试的测试列表,生成测试名称和迭代次数的列表。
- 调用
初始化每个测试的元数据对象:
- 对于每个测试和对应的迭代次数,生成
TestRunResult对象,包含测试的详细信息(如测试类型、种子值、仿真器等)。 - 如果是定向测试,从定向测试 yaml 文件中获取测试数据。
- 将每个测试的元数据对象路径保存到
md.tests_pickle_files列表中,并将对象导出到磁盘。
- 对于每个测试和对应的迭代次数,生成
导出元数据对象:
- 最后,将整个
RegressionMetadata对象导出到磁盘,保存为 pickle 和 yaml 文件。
- 最后,将整个
通过上述步骤,CREATE分支确保了所有构建和测试的元数据能够被正确初始化和存储,为后续的回归测试提供必要的配置和数据支持。