UVM中打印信息的控制+内存分配算法+C语言fork()函数+使用uvm自带的reg做默认值检查+uvm_resource_db+ral手动更新+vim操作

news/2024/10/2 18:20:21

UVM中打印信息的控制

非uvm平台控制的module中的uvm info使用*号通配,而找不到对应的uvm_top,起始点不是harness/top。使用ID可以匹配到对应的信息。
https://blog.csdn.net/Bonnie_89/article/details/128897812

使用uvm_set_action,将某ID和某严重性的行为重载

  // +uvm_set_action=<comp>,<id>,<severity>,<action[|action]>// +uvm_set_action=uvm_test_top.env0.*,_ALL_,UVM_ERROR,UVM_NO_ACTION

行为有以下表示:

UVM_NO_ACTION - No action is taken
UVM_DISPLAY   - Sends the report to the standard output
UVM_LOG       - Sends the report to the file(s) for this (severity,id) pair
UVM_COUNT     - Counts the number of reports with the COUNT attribute. When this value reaches max_quit_count, the simulation terminates
UVM_EXIT      - Terminates the simulation immediately.
UVM_CALL_HOOK - Callback the report hook methods 
UVM_STOP      - Causes ~$stop~ to be executed, putting the simulation into interactive mode.
UVM_RM_RECORD - Sends the report to the recorder

默认的行为:

set_severity_action(UVM_INFO,    UVM_DISPLAY);
set_severity_action(UVM_WARNING, UVM_DISPLAY);
set_severity_action(UVM_ERROR,   UVM_DISPLAY | UVM_COUNT);
set_severity_action(UVM_FATAL,   UVM_DISPLAY | UVM_EXIT);

uvm_set_verbosity设置冗余度,可以使用某个phase,或时间

~+uvm_set_verbosity=<comp>,<id>,<verbosity>,<phase>~
~+uvm_set_verbosity=<comp>,<id>,<verbosity>,time,<time>~ <sim command> +uvm_set_verbosity=uvm_test_top.env0.agent1.*,_ALL_,UVM_FULL,time,800

phase不需要加_phase后缀,在uvm_runtime_phases.svh中,其定义的phase名称也是没有加_phase的。

class uvm_pre_shutdown_phase extends uvm_task_phase; virtual task exec_task(uvm_component comp, uvm_phase phase); comp.pre_shutdown_phase(phase); endtasklocal static uvm_pre_shutdown_phase m_inst; static const string type_name = "uvm_pre_shutdown_phase"; // Function: get// Returns the singleton phase handle static function uvm_pre_shutdown_phase get(); if(m_inst == null)m_inst = new; return m_inst; endfunctionprotected function new(string name="pre_shutdown"); super.new(name); endfunctionvirtual function string get_type_name(); return type_name; endfunction
endclass

重载严重度 uvm_set_severity

+uvm_set_severity=<comp>,<id>,<current severity>,<new severity>

内存分配算法

伙伴(Buddy)分配算法

伙伴分配算法的原理就是:将所有的空闲页框分组为 11 个块链表,每个块链表分别包含大小为 1,2,4,8,16,32,64,128,256,512 和 1024 个连续页的页块。最大可以申请 1024 个连续页,对应 4MB 大小的连续内存。假设需要申请 4 个页,但是长度为 4 个连续页块链表没有空闲的页块,伙伴系统会从连续 8 个框块的链表获取一个,并将其拆分为两个连续 4 个页块,取其中一个,另外一个放入连续 4 个页块的空闲链表中。释放的时候会检查,释放的这几个页前后的页框是否空闲,能否组成下一级长度的块。
https://bbs.huaweicloud.com/blogs/291867

cat /proc/buddyinfo #查看buddy分配结果

Slab 算法

将内核中经常使用的对象放到高速缓存中,并且由系统保持为初始的可利用状态。比如进程描述符,内核中会频繁对此数据进行申请和释放。Slab 内存分配器是对伙伴分配算法的补充,Slab 分配器为每一种对象建立高速缓存,通过将内存按使用对象不同再划分成不同大小的空间,应用于内核对象的缓存,内核对该对象的分配和释放均是在这块高速缓存中操作。每个kmem_cache 通常是一段连续的内存块,包含了三种类型的 slabs 链表:
● slabs_full:完全分配的 slab 链表
● slabs_partial:部分分配的 slab 链表
● slabs_empty:没有被分配对象的 slab 链表

cat /proc/slabinfo #查看slab内存信息

内核态和用户态

在内核态申请内存比在用户态申请内存要更为直接,它没有采用用户态那种延迟分配(通过缺页机制来反馈)内存技术。一旦有内核函数申请内存,那么就必须立刻满足该申请内存的请求,并且这个请求一定是正确合理的。相反,对于用户态申请内存的请求,内核总是尽量延后分配物理内存,用户进程总是先获得一个虚拟内存区的使用权,最终通过缺页异常获得一块真正的物理内存。

内核态分配函数kmalloc 和 vmalloc

kmalloc 和 vmalloc 分别用于分配不同映射区的虚拟内存。vmalloc 分配的虚拟地址区间,位于 vmalloc_start 与 vmalloc_end 之间的动态内存映射区。一般用分配大块内存,释放内存对应于 vfree,分配的虚拟内存地址连续,物理地址上不一定连续。kmalloc() 所申请内存的线性地址与物理地址都是连续的。
image

用户态内存分配

用户态内存分配函数:
● alloca 是向栈申请内存,因此无需释放。
● malloc 所分配的内存空间未被初始化,调用 malloc 函数时,它沿 free_chuck_list 连接表寻找一个大到足以满足用户请求所需要的内存块。
● calloc 会将所分配的内存空间中的每一位都初始化为零。
● realloc 扩展现有内存空间大小。
○ 如果当前连续内存块足够 realloc 的话,只是将 p 所指向的空间扩大,并返回 p 的指针地址。这个时候 q 和 p 指向的地址是一样的。
○ 如果当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p 指向的内容 copy 到 q,返回 q。并将 p 所指向的内存空间删除。

用户进程内存分配示例

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>int main(void)
{char *s;unsigned long int i;s = strdup("test_memory");if (NULL == s) {fprintf(stderr, "Can't allocate mem with malloc.\n");return EXIT_FAILURE;}i = 0;while (s) {printf("[%lu] %s (%p)\n", i, s, (void *)s);sleep(1);i++;}return EXIT_SUCCESS;
}

在 Linux 操作系统中,可以通过 /proc/[pid]/mem 访问和修改进程的内存页,可以通过 /proc/[pid]/maps 看到进程当前已映射的内存区域。

cat /proc/18539/maps #查看栈空间起始地址

修改栈空间,以修改其它程序运行。
修改程序运行在内核态,而执行程序需要运行在用户态。

#!/usr/bin/env python3
'''
Locates and replaces the first occurrence of a string in the heap
of a processUsage: ./read_write_heap.py PID search_string replace_by_string
Where:
- PID is the pid of the target process
- search_string is the ASCII string you are looking to overwrite
- replace_by_string is the ASCII string you want to replacesearch_string with
'''import sysdef print_usage_and_exit():print('Usage: {} pid search write'.format(sys.argv[0]))sys.exit(1)# check usage
if len(sys.argv) != 4:print_usage_and_exit()# get the pid from args
pid = int(sys.argv[1])
if pid <= 0:print_usage_and_exit()
search_string = str(sys.argv[2])
if search_string  == "":print_usage_and_exit()
write_string = str(sys.argv[3])
if search_string  == "":print_usage_and_exit()# open the maps and mem files of the process
maps_filename = "/proc/{}/maps".format(pid)
print("[*] maps: {}".format(maps_filename))
mem_filename = "/proc/{}/mem".format(pid)
print("[*] mem: {}".format(mem_filename))# try opening the maps file
try:maps_file = open('/proc/{}/maps'.format(pid), 'r')
except IOError as e:print("[ERROR] Can not open file {}:".format(maps_filename))print("        I/O error({}): {}".format(e.errno, e.strerror))sys.exit(1)for line in maps_file:sline = line.split(' ')# check if we found the heapif sline[-1][:-1] != "[heap]":continueprint("[*] Found [heap]:")# parse lineaddr = sline[0]perm = sline[1]offset = sline[2]device = sline[3]inode = sline[4]pathname = sline[-1][:-1]print("\tpathname = {}".format(pathname))print("\taddresses = {}".format(addr))print("\tpermisions = {}".format(perm))print("\toffset = {}".format(offset))print("\tinode = {}".format(inode))# check if there is read and write permissionif perm[0] != 'r' or perm[1] != 'w':print("[*] {} does not have read/write permission".format(pathname))maps_file.close()exit(0)# get start and end of the heap in the virtual memoryaddr = addr.split("-")if len(addr) != 2: # never trust anyone, not even your OS :)print("[*] Wrong addr format")maps_file.close()exit(1)addr_start = int(addr[0], 16)addr_end = int(addr[1], 16)print("\tAddr start [{:x}] | end [{:x}]".format(addr_start, addr_end))# open and read memtry:mem_file = open(mem_filename, 'rb+')except IOError as e:print("[ERROR] Can not open file {}:".format(mem_filename))print("        I/O error({}): {}".format(e.errno, e.strerror))maps_file.close()exit(1)# read heapmem_file.seek(addr_start)heap = mem_file.read(addr_end - addr_start)# find stringtry:i = heap.index(bytes(search_string, "ASCII"))except Exception:print("Can't find '{}'".format(search_string))maps_file.close()mem_file.close()exit(0)print("[*] Found '{}' at {:x}".format(search_string, i))# write the new stringprint("[*] Writing '{}' at {:x}".format(write_string, addr_start + i))mem_file.seek(addr_start + i)mem_file.write(bytes(write_string, "ASCII"))# close filesmaps_file.close()mem_file.close()# there is only one heap in our examplebreak

C语言fork()函数

1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;

/*linux下:*/#include <stdio.h>
#include <unistd.h>int main() {pid_t pid;pid = fork();if(pid  == 0) //返回子进程{printf("child pid: %d\n", getpid());} else {printf("pid: %d\n", pid);//父进程中返回子进程的pidprintf("father pid: %d\n", getpid());}
}

输出:父子进程在第8行之后同时执行。

pid: 5989
father pid: 5988
child pid: 5989

使用uvm自带的reg做默认值检查

继承uvm_reg_hw_reset_seq,然后在pre_body中设定model即可。
此外还有读写函数uvm_reg_bit_bash_seq。
https://blog.csdn.net/weixin_39662684/article/details/110133060

uvm_resource_db

https://www.cnblogs.com/csjt/p/15556969.html
uvm_resource_db虽然也是一种用来共享数据的类,但是层次关系在该类中没有作用; 与uvm_config_db相比,尽管uvm_resource_db也有内建的数据库,可以通过字符串或类型来索引配置数据,但缺点是层次的缺失和因此带来的自顶向下的配置覆盖关系的缺失.
(2.1) uvm_resource_db采用的是”last write wins”,即对同一配置,最后的写入有效;
(2.2) uvm_config_db采用的是”parent wins + last write wins”(假设在env中已经有配置,而test的级别高于env).
(3) uvm_config_db与uvm_resource_db共享同一套database; 因此可能会出现通过uvm_config_db::set()往database中存入信息,但用uvm_resource_db::read_by_name()从database中读取信息;

uvm_resource_db#(type)::set("scope", "name", value, accessor);
//path=scope+name, default value of accessor is null;
uvm_resource_db#(int)::set("test", "loop_cnt", 10, this);

https://www.cnblogs.com/csjt/p/15556136.html
使用.get_full_name()的方法对REG::设定值,以忽略测试的位置。设定的Lable根据UVM源码获取,如:(最低粒度是uvm_reg,无法将单独的域区分开)

uvm_resource_db#(bit)::set({"REG::",rm.reg.get_full_name()},"NO_REG_BIT_BASH_TEST", 1, this
)

ral手动更新

对ral的map设置set_auto_predict(0)
编写更新函数,读取时候使用get_mirrored_value
写入的时候使用predict,
https://east1203.github.io/2020/06/06/Verification/UVM/UVM——关于RAL的一些方法/

vim操作

<>:g/^/m 0 # vim倒序
%          # 匹配的括号前后切换
^          # 移动到行首非空字符位置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/44772.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

闲话 24.6.13

sif闲话 感觉写的有点长了,当半个社论发了吧( 没啥想写的闲话啊! 今日推歌:所以我放走了那天的流星 by 不鱼_P feat. 星尘 Minus Stabilized Interval Free 对两个正整数 \(l,r\),本文使用 \([l, r]\) 表示 \(\{x\in \mathbb N \mid l\le x \le r\}\)。 对排列 \(\pi = (\…

千万级流量冲击下,如何保证极致性能

1 简要介绍 随着互联网的快速发展,网络应用的流量规模不断攀升,特别是在电商大促、明星直播、重大赛事、头条热搜等热点事件中,秒级100w请求成为了常态。在这样的流量冲击下,如何确保系统稳定、高效地处理每一个请求,为用户提供极致的体验,成为了技术团队面临的重要挑战。…

SAP:SALV刷新按钮事件

SAP ECC6 SALV刷新按钮事件的实现SAP SALV刷新事件 1、主程序*&---------------------------------------------------------------------* *& Report Z17_04 *& *&---------------------------------------------------------------------* *& 全屏Clas…

解决github中一个新手著名问题

问题的引入 首先新手在初学git的时候,会先git init,然后config一些配置,之后链接远程仓库的时候,十分有可能碰到一个报错:ERROR: Permission to yixianshen-reserved/learning-repo.git denied to yiquanfeng. fatal: Could not read from remote repository. Please make…

dotnet 基于 DirectML 控制台运行 Phi-3 模型

本文将和大家介绍如何在 C# dotnet 里面的控制台应用里面,使用 DirectML 将 Phi-3 模型在本地运行起来在微软的 Microsoft Build 2024 大会上介绍了 Phi-3 模型,这是一个 small language models (SLMs) 本地小语言模型。简单说就是一个可以在用户设备上运行的模型,据说能和 …

PyQT5之计数器控件QSpinBox

import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import *class spindemo(QWidget):def __init__(self, parent=None):super(spindemo, self).__init__(parent)#设置标题与初始大小self.setWindowTitle(SpinBox 例子)self.resize(300,1…

PyQT5之滑块控件QSlider

import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import *class QSliderDemo(QWidget):def __init__(self):super(QSliderDemo, self).__init__()self.initUI()def initUI(self):self.setWindowTitle(滑块控件演示) # 创建窗口标题sel…

[转帖]见识一下SQL Server隐式转换处理的不同

https://cloud.tencent.com/developer/article/1873328 隐式转换(Implicit Conversion)就像他的名字一样,是个隐秘、不容易被发现的问题,但归根结底,还是设计开发中未遵守相关的规范,或者说是不良的设计开发习惯所导致的。 如果在条件中的字段和变量类型不一致,数据库会按…