将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
posted @ 2024-04-02 09:10  大浪淘沙、  阅读(10)  评论(0编辑  收藏  举报