将wavedrom图转换为excel+UVM使用双顶层环境+慎用casex和casez使用case inside+shell命令行自动补全+操作系统的分段机制+ASID的功能+查看CPU信息
将wavedrom图转换为excel
原理上是先转换为json,然后写入到excel中。
import csv import json import pandas as pd content = [] with open("source.txt") as f: c = f.read() c = c.replace("reg", "\"reg\"").replace("bits", "\"bits\"").replace("name", "\"name\"").replace( "'", "\"").replace("config", "\"config\"").replace("lanes", "\"lanes\"").replace( "hspace", "\"hspace\"").replace("fontsize", "\"fontsize\"").replace("attr","\"attr\"") data = json.loads(c)["reg"] # 创建DataFrame df = pd.DataFrame(data) new_df = pd.DataFrame() for index, row in df.iterrows(): if row['bits'] > 1: # 根据bits的值复制行 for _ in range(row['bits'] - 1): new_df = pd.concat([new_df, pd.DataFrame([pd.Series()])], ignore_index=True) new_df = pd.concat([new_df, pd.DataFrame([row])], ignore_index=True) else: new_df = pd.concat([new_df, pd.DataFrame([row])], ignore_index=True) # 重置索引 new_df.reset_index(drop=True, inplace=True) df = new_df.iloc[::-1, :] df = df.T df.iloc[[0, 1]] = df.iloc[[1, 0]] # 使用pandas的ExcelWriter和openpyxl引擎 with pd.ExcelWriter("output.xlsx", engine='openpyxl') as writer: df.to_excel(writer, index=False) # 获取workbook和worksheet对象 workbook = writer.book worksheet = writer.sheets['Sheet1'] # 根据bits的值设置跨列 row_num = 2 # 从Excel的第二行开始(第一行是标题) bits_all = 0 for item in data[::-1]: bits = item['bits'] # 如果bits大于1,则合并单元格 bits_offset = bits_all % 64 if bits > 1: worksheet.merge_cells( start_row=row_num, start_column=1 + bits_offset, end_row=row_num, end_column=bits + bits_offset) bits_all += bits if bits_all > 64: row_num += 1
UVM使用双顶层环境
前述
uvm组件是动态变化的,
在build phase之前(initial 部分,且存在于run_test之前的initial)调用的uvm_top.print_topology()函数,则显示的内容为空。
在build phase之前(initial 部分,且存在于run_test之后的initial)调用的uvm_top.print_topology()函数,则显示的内容只有uvm_test_top。
在elaboration phase,uvm_top.print_topology()函数,则显示的内容是完整的topo。
原理
双顶层或者是说多顶层,本质是将uvm_top(uvm_root的唯一实例指针)下挂载额外的一个组件。第一个组件是通过+UVM_TESTNAME或者run_test的时候指定参数进行的挂载,而额外的一个组件是通过create_component_by_name手动挂载。
因此可以实现多个用例同时运行,由uvm_top统一调度。
实现
uvm_coreservice_t coreservice = uvm_coreservice_t::get(); uvm_factory fact = coreservice.get_factory(); fact.create_component_by_name(testname,"","other_test_top",uvm_top);
参考
实现机制:
http://www.lujun.org.cn/?p=4271
https://blog.csdn.net/weiqi7777/article/details/88219191
通过uvm_top.find获取某个组件:
https://www.cnblogs.com/csjt/p/15560173.html
https://zhuanlan.zhihu.com/p/659753287
慎用casex和casez使用case inside
ase、casex、casez都是可综合的,不过在case中综合电路无法解析x/z/?,会将其认为不关心
https://www.wenhui.space/docs/08-ic-design/rtl-coding/about-verilog-case/
casez treats ‘z’ as dont care
casex treats ‘z’ & ‘x’ as dont care
以case x为例,不只是 case_item 的“z”和 “x”, case_expression 中的“z”和“x”也会被看作“don't care”。因此容易出现混淆。
https://zhuanlan.zhihu.com/p/460286149
假设仿真时输入的 irq 为 3'b00x,casex 将最低位的 x 看作通配符,所以会匹配 case_item 3'b??1,所以 int0=1。
always @(irq) begin {int2, int1, int0} = 3'b000; casex (irq) 3'b1?? : int2 = 1'b1; 3'b?1? : int1 = 1'b1; 3'b??1 : int0 = 1'b1; default: {int2, int1, int0} = 3'b000; endcase end
case...inside 不会把 case_expression 中的“z”和“x”看作“don't care”,因而进一步使得仿真结果和综合后的结果可以匹配上。在此例中,假如 irq 为 3'b00x,那么 case...inside 便会匹配 default 选项。
always @(irq) begin {int2, int1, int0} = 3'b000; case (irq) inside 3'b1?? : int2 = 1'b1; 3'b?1? : int1 = 1'b1; 3'b??1 : int0 = 1'b1; default: {int2, int1, int0} = 3'b000; endcase end
shell命令行自动补全
https://blog.csdn.net/iEearth/article/details/52703598
inux.51yip.com/search/compgen
compgen
最常用的选项是-W,通过-W参数指定空格分隔的单词列表。
compgen -W 'hi hello how world' h hi hello how function _test() > { > echo "aabc" > } $ complete -F _test test 再输入以下命令按补全: test x<Tab> 得到 test xaabc
function autotab() { echo "function autotab called $@" } autotab_list=("aa" "bb" "cc" "dd" "123") function _autotab() { local cur COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" COMPREPLY=( $(compgen -W "${autotab_list[*]}" -- ${cur}) ) return 0 } complete -F _autotab autotab
执行命令autotab时,如果命令未输完,按下Tab键就会补全这个命令,而且还会显示或补全一些参数
操作系统的分段机制
linux内存的管理有:段式存储、页式存储、段页式存储。
ASID的功能
ASID的核心作用是索引于TLB,是TLB存在以后出现的概念。ASID在使用层面上是和PPN相匹配,不同进程的某个进程上,ASID相同,PPN多个。ASID用于在TLB层面区分不同的进程,以在相同的VA进行缓存查找翻译的时候使用。
当两个进程带有ASID不同但是基地址PPN相同,使用相同VA进行访问,最终两个进程通过该PPN获取到的是相同的PA。
当两个进程带有ASID相同但是基地址PPN不同,使用相同VA进行访问,最终两个进程通过不同的PPN获取到的是不同的PA。
当两个进程带有ASID不同且基地址PPN不同,使用相同VA进行访问,最终两个进程通过不同的PPN获取到的是不同的PA。这个情况需要ASID生效才可以。如果ASID是无效,那么TLB在存储VA和PA的映射关系上,只能存储一组,将导致第一个进程拿到PPN后,建立的VA和PA的映射关系被第二个进程使用,从而导致错误。
当进程P1执行VA1映射得到PA1,进程P2执行VA2映射得到PA2,再次回到进程P1,cache命中情况下VA1仍然映射得到PA1。
ASID本质用于防止TLB的误命中,而PPN直接作为Tag索引则位宽过大,引入ASID和PPN对应。
当发送请求带着不同的ASID,相同的VA,则前后都会miss。获取两套翻译结果。
查看CPU信息
/proc/cpuinfo里显示的cpu_cores是每个插槽的实际物理cpu个数。
或者使用lscpu命令查看
https://www.cnblogs.com/badboy200800/p/10606405.html
Architecture: x86_64 #架构,这里指64位处理器 CPU op-mode(s): 32-bit, 64-bit #运行方式 Byte Order: Little Endian #字节顺序,这里指小端法 CPU(s): 48 #服务器上CPU的逻辑核总数 On-line CPU(s) list: 0-47 #服务器上在线的CPU逻辑核总数(有时因为CPU过热可能会暂停某些CPU) Thread(s) per core: 2 #每个物理核超线程数(大于1则为超线程) Core(s) per socket: 6 #每个插槽的物理核数(每颗CPU物理核数) Socket(s): 4 #服务器上CPU插槽数 (一般为CPU总数) NUMA node(s): 8 #非统一内存访问节点 Vendor ID: AuthenticAMD #cpu厂商ID CPU family: 21 #CPU系列 Model: 1 #CPU型号编号 Model name: AMD Opteron 6234 @ 2.40GHz #CPU型号名称 Stepping: 2 #步进 CPU MHz: 2400.66 #cpu主频 BogoMIPS: 4799.42 Hypervisor vendor: AMD-V #虚拟化架构 Virtualization type: full #cpu支持的虚拟化技术 L1d cache: 16K #一级缓存,dcahce用于缓存数据 L1i cache: 64K #一级缓存,icahce用于缓存指令 L2 cache: 2408K #二级缓存 L3 cache: 6144K #三级缓存,缓存速度上 L1 > L2 > L3 > DDR(内存,理论速度几十g每秒) NUMA node0 CPU(s): 0,4,8,12,16,20 #逻辑CPU和NUMA节点映射 NUMA node1 CPU(s): 24,18,32,36,40,44 NUMA node2 CPU(s): 1,5,9,13,17,21 NUMA node3 CPU(s): 25,29,33,37,41,45 NUMA node4 CPU(s): 2,6,10,14,18,22 NUMA node5 CPU(s): 26,30,34,38,42,46 NUMA node6 CPU(s): 27,31,35,39,43,47 NUMA node7 CPU(s): 3,7,11,15,19,23
Le vent se lève! . . . il faut tenter de vivre!
Le vent se lève! . . . il faut tenter de vivre!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步