【python脚本】ICer的脚本入门训练——gen_tc

简介: 【python脚本】ICer的脚本入门训练——gen_tc

前言

【python脚本】ICer的脚本入门训练——svn_back


上一篇博客的目的,是通过处理固定流程的事物来体现脚本的必要性。而后这篇博客的目的,是熟悉脚本里的一些基本的处理思路。


gen_tc是一个芯片前端验证很常见的脚本,作用是:


1.根据已有的tc生成新的tc文件;


2.修改内部关键字;


3.输出文件;


在这个过程中,我们需要涉及到的处理包括:吃命令行,遍历输入文件,正则匹配与替换,文件输出等过程,作为我第一个学习的脚本,几十行的内容简直最合适作为入门训练。


要求

假定目前我们有一个case,文件名为:sanity_case.sv,内容就是个普普通通的case如下:

`ifndef SANITY_CASE_SV
`define SANITY_CASE_SV
class sanity_case_seq extends my_sequence;
  extern function new(string name = "sanity_case_seq");
  extern virtual task body();
  `uvm_object_utils(sanity_case_seq)
endclass: sanity_case_seq
function sanity_case_seq::new(string name = "sanity_case_seq");
  super.new(name);
endfunction: new
task sanity_case_seq::body();
  repeat(10000) begin
    `uvm_do_with(my_tr, {my_tr.par_err == 0;})
  end
  #100;
endtask: body
class sanity_case extends base_test;
  extern function new(string name = "base_test", uvm_component parent=null);
  extern virtual function void build_phase(uvm_phase phase);
  `uvm_component_utils(sanity_case)
endclass: sanity_case
function sanity_case::new(string name = "base_test", uvm_component parent=null);
    super.new(name, parent);
endfunction: new
function void sanity_case::build_phase(uvm_phase phase);
  super.build_phase(phase);
  uvm_config_db #(uvm_object_wrapper)::set(
    this,
    "env.i_agt0.sqr.main_phase",
    "default_sequence",
    sanity_case_seq::type_id::get()
  );
    uvm_config_db #(uvm_object_wrapper)::set(
    this,
    "env.i_agt1.sqr.main_phase",
    "default_sequence",
    sanity_case_seq::type_id::get()
  );
endfunction: build_phase
`endif



那么我们要做的就是,编写一个脚本 gen_tc,在当前目录执行gen_tc sanity_case.v new_case.v之后,在当前目录生成新的文件new_case.v。


实操

1.新建文件gen_tc

键入以下内容作为初始:



之后修改文件属性为可执行属性chmod a+x gen_tc,然后你就会发现你的脚本绿了:



敲一下,确认可执行,然后继续下一步:



2.读取命令参数

gen_tc脚本要吃两个参数,一般处理参数有两种常用的方式:sys.argv数组和argparse库。使用argparse的典型方式,如下面的代码,具体功能我们不做探究:

import argparse
def input_args_proc():
    parser = argparse.ArgumentParser(description="argparse info")
    parser.add_argument('-o', action='store_true', default=False, help='open this script')
    result = parser.parse_args()
    if result.o == True:
        os.system("gvim %s" % __file__)
        sys.exit(0)


gen_tc的输入参数情况比较简单,两个参数必须输入,因此不需要使用argparse,直接使用sys.argv数组即可。比如目前的输入获取方式:

def input_sys():
    if len(sys.argv) > 2:
        from_tc = sys.argv[1]
        to_tc = sys.argv[2]
    else:
        print("Input error")
        sys.exit(0)
    return from_tc, to_tc


sys.argv[0]不要使用,那是脚本自身名称。在main函数中接受该函数的返回值,读取输入参数的操作就完成了。

from_tc, to_tc = input_sys()


3.读取并修改参考tc

可以通过以下的形式形式来读取文件:

def modify_tc(file):
    with open(file, "r") as handle:
        hd = handle.readlines()
        for line in hd:
            line = line.strip("\n")
            print(line)


读取文件后,在没一行内匹配“sanity_case”或“SANITY_CASE”关键字,并将其替换为“new_case”和“NEW_CASE”,而后将字符串暂存于数组中,作为函数返回值:

def modify_tc(frm, to):
    frm_key = re.sub("\.sv","",frm) #得到sanity_case.sv里的sanity_case
    frm_uc = frm_key.upper() #纯小写
    frm_lc = frm_key.lower() #纯大写,执行的时候把这块注释删了
    to_key  = re.sub("\.sv","",to)
    to_uc = to_key.upper()
    to_lc = to_key.lower()
    out_file = []
    with open(frm, "r") as handle:
        hd = handle.readlines()
        for line in hd:
            line = line.strip("\n")
            line = re.sub(frm_uc, to_uc, line)
            line = re.sub(frm_lc, to_lc, line)
            out_file.append(line)
    return out_file


main函数中接收返回值:

out_file = modify_tc(from_tc, to_tc)


4.输出文件

输出文件的函数比较固定:

def write_list(lst, out):
    with open(out, "w") as handle:
        for line in lst:
            handle.write(line+"\n")


在main中把out_file和to_tc作为参数传给该函数即可:

write_list(out_file, to_tc)


5.执行脚本

代码编写完成后,执行脚本,打开文件new_case.sv:


`ifndef NEW_CASE_SV
`define NEW_CASE_SV
class new_case_seq extends my_sequence;
  extern function new(string name = "new_case_seq");
  extern virtual task body();
  `uvm_object_utils(new_case_seq)
endclass: new_case_seq
function new_case_seq::new(string name = "new_case_seq");
  super.new(name);
endfunction: new
task new_case_seq::body();
  repeat(10000) begin
    `uvm_do_with(my_tr, {my_tr.par_err == 0;})
  end
  #100;
endtask: body
class new_case extends base_test;
  extern function new(string name = "base_test", uvm_component parent=null);
  extern virtual function void build_phase(uvm_phase phase);
  `uvm_component_utils(new_case)
endclass: new_case
function new_case::new(string name = "base_test", uvm_component parent=null);
    super.new(name, parent);
endfunction: new
function void new_case::build_phase(uvm_phase phase);
  super.build_phase(phase);
  uvm_config_db #(uvm_object_wrapper)::set(
    this,
    "env.i_agt0.sqr.main_phase",
    "default_sequence",
    new_case_seq::type_id::get()
  );
    uvm_config_db #(uvm_object_wrapper)::set(
    this,
    "env.i_agt1.sqr.main_phase",
    "default_sequence",
    new_case_seq::type_id::get()
  );
endfunction: build_phase
`endif


相关文章
|
10天前
|
缓存 算法 数据处理
Python入门:9.递归函数和高阶函数
在 Python 编程中,函数是核心组成部分之一。递归函数和高阶函数是 Python 中两个非常重要的特性。递归函数帮助我们以更直观的方式处理重复性问题,而高阶函数通过函数作为参数或返回值,为代码增添了极大的灵活性和优雅性。无论是实现复杂的算法还是处理数据流,这些工具都在开发者的工具箱中扮演着重要角色。本文将从概念入手,逐步带你掌握递归函数、匿名函数(lambda)以及高阶函数的核心要领和应用技巧。
Python入门:9.递归函数和高阶函数
|
10天前
|
开发者 Python
Python入门:8.Python中的函数
### 引言 在编写程序时,函数是一种强大的工具。它们可以将代码逻辑模块化,减少重复代码的编写,并提高程序的可读性和可维护性。无论是初学者还是资深开发者,深入理解函数的使用和设计都是编写高质量代码的基础。本文将从基础概念开始,逐步讲解 Python 中的函数及其高级特性。
Python入门:8.Python中的函数
|
10天前
|
存储 索引 Python
Python入门:6.深入解析Python中的序列
在 Python 中,**序列**是一种有序的数据结构,广泛应用于数据存储、操作和处理。序列的一个显著特点是支持通过**索引**访问数据。常见的序列类型包括字符串(`str`)、列表(`list`)和元组(`tuple`)。这些序列各有特点,既可以存储简单的字符,也可以存储复杂的对象。 为了帮助初学者掌握 Python 中的序列操作,本文将围绕**字符串**、**列表**和**元组**这三种序列类型,详细介绍其定义、常用方法和具体示例。
Python入门:6.深入解析Python中的序列
|
10天前
|
存储 SQL 索引
Python入门:7.Pythond的内置容器
Python 提供了强大的内置容器(container)类型,用于存储和操作数据。容器是 Python 数据结构的核心部分,理解它们对于写出高效、可读的代码至关重要。在这篇博客中,我们将详细介绍 Python 的五种主要内置容器:字符串(str)、列表(list)、元组(tuple)、字典(dict)和集合(set)。
Python入门:7.Pythond的内置容器
|
2月前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
2月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
2月前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
128 80
|
1月前
|
存储 缓存 Java
Python高性能编程:五种核心优化技术的原理与Python代码
Python在高性能应用场景中常因执行速度不及C、C++等编译型语言而受质疑,但通过合理利用标准库的优化特性,如`__slots__`机制、列表推导式、`@lru_cache`装饰器和生成器等,可以显著提升代码效率。本文详细介绍了这些实用的性能优化技术,帮助开发者在不牺牲代码质量的前提下提高程序性能。实验数据表明,这些优化方法能在内存使用和计算效率方面带来显著改进,适用于大规模数据处理、递归计算等场景。
71 5
Python高性能编程:五种核心优化技术的原理与Python代码
|
3月前
|
存储 索引 Python
Python编程数据结构的深入理解
深入理解 Python 中的数据结构是提高编程能力的重要途径。通过合理选择和使用数据结构,可以提高程序的效率和质量
176 59
|
2月前
|
Python
[oeasy]python055_python编程_容易出现的问题_函数名的重新赋值_print_int
本文介绍了Python编程中容易出现的问题,特别是函数名、类名和模块名的重新赋值。通过具体示例展示了将内建函数(如`print`、`int`、`max`)或模块名(如`os`)重新赋值为其他类型后,会导致原有功能失效。例如,将`print`赋值为整数后,无法再用其输出内容;将`int`赋值为整数后,无法再进行类型转换。重新赋值后,这些名称失去了原有的功能,可能导致程序错误。总结指出,已有的函数名、类名和模块名不适合覆盖赋新值,否则会失去原有功能。如果需要使用类似的变量名,建议采用其他命名方式以避免冲突。
56 14

热门文章

最新文章