【UVM】寄存器模型

news2025/2/11 12:03:03

寄存器模型的优势

  1. sequence复用性高,方便对 DUT 中寄存器进行读写;
  2. 提供了后门访问方式,可以不耗时的获取寄存器的值;
  3. 可以很方便的对寄存器的 coverage 验证点的收集

寄存器模型基本概念

寄存器模型概念作用
uvm_reg_field寄存器模型中的最小单位
uvm_reg比uvm_reg_field高一个级别,一个寄存器中至少包含一个uvm_reg_field
uvm_reg_block比uvm_reg高一个级别,可以加入许多的uvm_reg,也可以加入其他的uvm_reg_block。一个寄存器模
型中至少包含一个uvm_reg_block。
uvm_reg_map

存储寄存器的偏移地址,并将其转换成可以访问的物理地址

在每个reg_block内部,至少有一个(通常也只有一个)uvm_reg_map。

uvm_reg_file用于区分不同的hdl路径

简单的寄存器模型

实例

  • uvm_reg:
class my_reg extends uvm_reg;
    rand uvm_reg_field data;
    `uvm_object_utils(my_reg)
    virtual function void build();
        data = uvm_reg_field::type_id::create("data");
        //parameter:    parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, individually accessible
        data.configure(this,  16,  0,  "RW",  1,   0,   1,    1,    0);
    endfunction
    function  new(input string name="my_reg");
        //parameter: name, size, has_coverage
        super.new(name, 16, UVM_NO_COVERAGE);
    endfunction
endclass
  • uvm_reg_block:
class my_regmodel extends uvm_reg_block;
    rand my_reg version;
    function void build();
        default_map = create_map("default_map", 0, 2, UVM_LITTLE_ENDIAN, 0);
        version = my_reg::type_id::create("version", , get_full_name());
        version.configure(this, null, "version");
        version.build();
        default_map.add_reg(version, 16'h47, "RW");
    endfunction
    `uvm_object_utils(my_regmodel)
    function new(input string name="my_regmodel");
        super.new(name, UVM_NO_COVERAGE);
    endfunction
endclass 

步骤总结

  1. 从uvm_reg派生一个寄存器类:
    1. 声明build函数,并在其实例化uvm_reg_field类;

      build函数负责所有uvm_reg_field的实例化

    2. 调用configure函数,配置上述域

      configure字段的含义:
      参数一,是此域的父辈,也就是此域位于哪个寄存器中,即是 this;
      参数二,是此域的宽度;
      参数三,是此域的最低位在整个寄存器的位置,从0开始计数;
      参数四,表示此字段的存取方式,共支持25种;
      参数五,表示是否是易失的(volatile),这个参数一般不会使用;
      参数六,表示此域上电复位后的默认值;
      参数七,表示此域时都有复位;
      参数八,表示这个域是否可以随机化;
      参数九,表示这个域是否可以单独存取

  2. 在一个由reg_block派生的类中将上述寄存器配置:
    1. 声明一个build函数

      build函数作用:实现所有寄存器的实例化

    2. default_map实例化;

      调用 create_map 函数完成 default_map 的实例化,default_map = create_map(“default_map”, 0, 2, UVM_LITTLE_ENDIAN, 0)
      第一个参数,表示名字;
      第二个参数,表示该 reg block 的基地址;
      第三个参数,表示寄存器所映射到的总线的宽度(单位是 byte,不是 bit );
      第四个参数,表示大小端模式;
      第五个参数,表示该寄存器能否按 byte 寻址。

    3. 调用configure函数;

      configure ( uvm_reg_block blk_parent, uvm_reg_file regfile_parent = null, string hdl_path = "" )
      第一个参数,表示所在 reg block 的指针;
      第二个参数,表示 reg_file 指针;
      第三个参数,表示寄存器后面访问路径 - string 类型

    4. 调用build函数将域实例化;
    5. 将此寄存器加入default_map

      default_map.add_reg (version, 16'h47, "RW") ;
      第一个参数,表示要添加的寄存器名;
      第二个参数,表示地址;
      第三个参数,表示寄存器的读写属性。

复杂的寄存器模型

 实例

class global_blk extends uvm_reg_block;
  ...
endclass

class buf_blk extends uvm_reg_block;
  ...
endclass

class mac_blk extends uvm_reg_block;
  ...
endclass

class reg_model extends uvm_reg_block;

  rand global_blk gb_ins;
  rand buf_blk bb_ins;
  rand mac_blk mb_ins;

  virtual function void build();
    default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
    gb_ins = global_blk::type_id::create("gb_ins");
    gb_ins.configure(this, "");
    gb_ins.build();
    gb_ins.lock_model();
    default_map.add_submap(gb_ins.default_map, 16'h0);

    bb_ins = buf_blk::type_id::create("bb_ins");
    bb_ins.configure(this, "");
    bb_ins.build();
    bb_ins.lock_model();
    default_map.add_submap(bb_ins.default_map, 16'h1000);

    mb_ins = mac_blk::type_id::create("mb_ins");
    mb_ins.configure(this, "");
    mb_ins.build();
    mb_ins.lock_model();
    default_map.add_submap(mb_ins.default_map, 16'h2000);
  endfunction

  `uvm_object_utils(reg_model)

  function new(input string name="reg_model");
    super.new(name, UVM_NO_COVERAGE);
  endfunction

endclass

步骤总结

  •  第一步是先实例化子reg_block。

  • 第二步是调用子reg_block的configure函数(如果需要使用后门访问,则在这个函数中要说明子reg_block的路径,这个路径不是绝对路径,而是相对于父reg_block来说的路径)

  • 第三步是调用子reg_block的build函数。

  • 第四步是调用子reg_block的lock_model函数。

  • 第五步则是将子reg_block的default_map以子map的形式加入父reg_block的default_map中

寄存器模型中加入存储器

  • 存储器同样支持read/write/peek/poke进行读写,不过会额外多一个offset参数,表示存储器的哪个地址
/*从uvm_mem中派生存储器类,深度1024,宽度16*/
class my_memory extends uvm_mem;
   function new(string name="my_memory");
      super.new(name, 1024, 16);
   endfunction

   `uvm_object_utils(my_memory)
endclass

class reg_model extends uvm_reg_block;
   rand my_memory mm;

   virtual function void build();
      default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);

      mm = my_memory::type_id::create("mm", , get_full_name());
      mm.configure(this, "stat_blk.ram1024x16_inst.array");
      default_map.add_mem(mm, 'h100);
   endfunction
endclass

寄存器模型集成到环境

寄存器模型转换到总线上操作

  •  adapter的作用:
    • reg2bus:其作用为将寄存器模型通过sequence发出的uvm_reg_bus_op型的变量转换成bus_sequencer能够接受的形式,
    • bus2reg:其作用为当监测到总线上有操作时,它将收集来的transaction转换成寄存器模型能够接受的形式,以便寄存器模型能够更新相应的寄存器的值
class adapter extends uvm_reg_adapter;
    string tID = get_type_name();
    `uvm_object_utils(my_adapter)
    function new(string name="my_adapter");
        super.new(name);
    endfunction : new
    function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
        bus_transaction tr;
        tr = new("tr");
        tr.addr = rw.addr;
        tr.bus_op = (rw.kind == UVM_READ) BUS_RD: BUS_WR;
        if (tr.bus_op == BUS_WR)
            tr.wr_data = rw.data;
        return tr;
    endfunction : reg2bus
    function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
        bus_transaction tr;
        if(!$cast(tr, bus_item)) begin
            `uvm_fatal(tID,"Provided bus_item is not of the correct type. Expecting bus_trans action")
            return;
        end
        rw.kind = (tr.bus_op == BUS_RD) UVM_READ : UVM_WRITE;
        rw.addr = tr.addr;
        rw.byte_en = 'h3;
        rw.data = (tr.bus_op == BUS_RD) tr.rd_data : tr.wr_data;
        rw.status = UVM_IS_OK;
    endfunction : bus2reg
endclass : adapter

在验证平台中使用寄存器模型

 实例

  • base_test:加入REG_MODEL
class base_test extends uvm_test;
        my_env env;
        my_vsqr v_sqr;
        reg_model rm;
        adapter reg_sqr_adapter;
        …
    endclass
    function void base_test::build_phase(uvm_phase phase);
        super.build_phase(phase);
        env = my_env::type_id::create("env", this);
        v_sqr = my_vsqr::type_id::create("v_sqr", this);
        rm = reg_model::type_id::create("rm", this);
        rm.configure(null, "");
        rm.build();
        rm.lock_model();
        rm.reset();
        rm.set_hdl_path_root("top_tb.my_dut");
        reg_sqr_adapter = new("reg_sqr_adapter");
        env.p_rm = this.rm;
     endfunction
    function void base_test::connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        v_sqr.p_my_sqr = env.i_agt.sqr;
        v_sqr.p_bus_sqr = env.bus_agt.sqr;
        v_sqr.p_rm = this.rm;
        rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);
        rm.default_map.set_auto_predict(1);
    endfunction

步骤总结

  1. 定义 reg_model和reg_sqr_adapter;
  2. 在build_phase中将其实例化
  3. 配置reg_model

    第一是调用configure函数,其第一个参数是parent block,由于是最顶层的reg_block,因此填写null,第二个参数是后门访问路径
    第二是调用build函数,将所有的寄存器实例化。
    第三是调用lock_model函数,调用此函数后,reg_model中就不能再加入新的寄存器了
    第四是调用reset函数,如果不调用此函数,那么reg_model中所有寄存器的值都是0,调用此函数后,所有寄存器的值都将变为设置的复位值

  4. 在connect_phase中,通过set_sequencer函数设置adapter的bus_sequencer,并将default_map设置为自动预测状态

寄存器模型中的访问

前门访问

定义

  • 前门访问操作就是通过寄存器配置总线(如APB协议、OCP协议、I2C协议等)来对DUT进行操作。前门访问操作只有两种:读操作和写操作。

方法函数

  • read
    extern virtual task read(output uvm_status_e            status,
                             output uvm_reg_data_t          value,
                             input uvm_path_e               path = UVM_DEFAULT_PATH,
                             input uvm_reg_map              map = null,
                             input uvm_sequence_base        parent = null,
                             input int                      prior = -1,
                             input uvm_object               extension = null,
                             input string                   fname = "",
                             input int                      lineno = 0);
  • write
    extern virtual task write(output uvm_status_e           status,
                             input uvm_reg_data_t           value, 
                             input uvm_path_e               path = UVM_DEFAULT_PATH,
                             input uvm_reg_map              map = null,
                             input uvm_sequence_base        parent = null,
                             input int                      prior = -1,
                             input uvm_object               extension = null,
                             input string                   fname = "",
                             input int                      lineno = 0);
  • 参数说明:
    • 第一个是uvm_status_e型的变量,这是一个输出,用于表明操作是否成功;
    • 第二个是读/写的数值;
    • 第三个是读/写的方式,可选UVM_FRONTDOOR和UVM_BACKDOOR 

后门访问

定义

不消耗仿真时间(即$time打印的时间)而只消耗运行时间的操作为后门访问

实现方式

  1. 使用interface进行后门访问操作
  2. DPI+VPI实现后门访问
    函数作用
    uvm_hdl_read(string path, uvm_hdl_data_t value);后门读
    uvm_hdl_deposit(string path, uvm_hdl_data_t value);

    后门写

    可被信值覆盖

    uvm_hdl_force(string path, uvm_hdl_data_t value);

    force信号

    在release前不能被覆盖

    uvm_hdl_release(string path);release信号
    uvm_hdl_check_path(string path);检查HDL路径是否存在
    uvm_hdl_release_and_read(string path, uvm_hdl_data_t value);更新信号release后的值
    uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time);force某个信号为特定值之后一段时间后再释放
  3. 寄存器模型中的后门访问函数
  • 实现前提:设置好configure函数的第三个路径参数;设置好根路径hdl_root
    class reg_model extends uvm_reg_block;
        …
        virtual function void build();
            counter_high.configure(this, null, "counter[31:16]");
            counter_low.configure(this, null, "counter[15:0]");
        …
        endfunction
    …
    endclass
    
    function void base_test::build_phase(uvm_phase phase);
        rm = reg_model::type_id::create("rm", this);
        rm.configure(null, "");
        rm.build();
        rm.lock_model();
        rm.reset();
        rm.set_hdl_path_root("top_tb.my_dut");
    endfunction
  • UVM_BACKDOOR形式的read和write:会在进行操作时模仿DUT的行为
  • peek/pook:完全不管DUT的行为
task uvm_reg::poke(output uvm_status_e status,
                input uvm_reg_data_t value,
                input string kind = "",
                input uvm_sequence_base parent = null,
                input uvm_object extension = null,
                input string fname = "",
                input int lineno = 0);

task uvm_reg::peek(output uvm_status_e status,
                output uvm_reg_data_t value,
                input string kind = "",
                input uvm_sequence_base parent = null,
                input uvm_object extension = null,
                input string fname = "",
                input int lineno = 0);

前后门访问区别

区别前门访问后门访问
时间上由于是真实的物理操作,因此会 消耗仿真时间不消耗仿真时间
调试上任何前门访问都会 有波形文件,方便调试没有波形文件 的记录,调试难度增加
应用上能验证 总线协议本身 是否正确

大规模寄存器的 快速初始化

能够操作 只读寄存器

注入故障

寄存器模型对DUT的模拟

期望值与镜像值

  • 镜像值(mirrored value):与DUT保持同步的值
  • 期望值(desired value):期望DUT改变的值
/*设置期望值*/
p_sequencer.p_rm.invert.set(16'h1);
/*获取期望值*/
value = p_sequencer.p_rm.invert.get();
/*获取镜像值*/
value = p_sequencer.p_rm.invert.get_mirrored_value();
/*检查1镜像值和期望值是否一致,不一致则更新*/
p_sequencer.p_rm.invert.update(status,UVM_FRONTDOOR);

 常用操作及其对期望值和镜像值的影响

操作影响
read&write更新期望值和镜像值(二者相等)
peek&poke更新期望值和镜像值(二者相等)
get&set

set操作会更新期望值,但是镜像值不会改变

get操作会返回寄存器模型中当前寄存器的期望值

update检查寄存器的期望值和镜像值是否一致,如果不一致,那么就会将期望值写入DUT中,并且更新镜像值,使其与期望值一致
randomize

期望值将会变为随机出的数值,镜像值不会改变。一般和update一起使用

只有当configure时将其第八个参数设置为1时支持此功能

mirror更新期望值和镜像值
predict更新镜像值和期望值

寄存器模型的高级用法

  • auto predict:寄存器模型会更新寄存器的镜像值和期望值
    rm.default_map.set_auto_predict(1);
  • mirror:读取DUT中寄存器的值并将它们更新到寄存器模型;可以在uvm_reg和uvm_reg_block级别被调用
    task uvm_reg::mirror(output uvm_status_e status,
                         input uvm_check_e check = UVM_NO_CHECK,
                         input uvm_path_e path = UVM_DEFAULT_PATH,
                         …);
    //第二个参数可选:UVM_CHECK和UVM_NO_CHECK,代表若镜像值与期望值不一致,是否更新前给出错误提示
  • predict:更新镜像值,但是同时又不对DUT进行任何操作
    function bit uvm_reg::predict(uvm_reg_data_t value,
                                  uvm_reg_byte_en_t be=-1,
                                  uvm_predict_e kind=UVM_PREDICT_DIRECT,
                                  uvm_path_e path=UVM_FRONTDOOR,
                                 );
    //第一个参数表示要预测的值
    //第二个参数是byte_en,默认-1的意思是全部有效
    //第三个参数是预测的类型,可选参数:
    typedef enum {
        UVM_PREDICT_DIRECT,
        UVM_PREDICT_READ,
        UVM_PREDICT_WRITE
    } uvm_predict_e;
    //第四个参数是后门访问或者是前门访问
  • 扩展位宽
    /*扩展位宽*/
    `ifndef UVM_REG_DATA_WIDTH
    `define UVM_REG_DATA_WIDTH 64 `endif
    /*地址位宽*/
    `ifndef UVM_REG_ADDR_WIDTH
    `define UVM_REG_ADDR_WIDTH 64 `endif
    /*字选择信号的位宽*/
    `ifndef UVM_REG_BYTENABLE_WIDTH
    `define UVM_REG_BYTENABLE_WIDTH ((`UVM_REG_DATA_WIDTH-1)/8+1) `endif
  • get_root_blocks
  • get_reg_by_offset

寄存器模型内建sequence

内建reg测试seq:

  1. uvm_reg_hw_reset_seq:
    • 功能:检查reg_model中寄存器的复位值与实际RTL是否一致
    • 测试级别:uvm_reg_block/uvm_reg
    • 原理:
      • 先reset reg_modle 。将reg_modle中的镜像值和期望值复位
      • 判断是否在外部设置了哪些 reg_block /reg不需要进行 reset 测试
      • 对所有需要进行测试的 reg 通过前门的方式读回DUT的硬件值,再与 reg_model 的 mirror 值进行对比,如果不一致,证明DUT的硬件复位值与reg_modle 的寄存器复位值不一致
    • 使用方式:
      uvm_reg_hw_reset_seq hw_reset_seq; //声明
      
      hw_reset_seq = new("hw_reset_seq"); //例化
      hw_reset_seq.model = XXX_RAL.xxx_reg; //与要被检查的寄存器模型相连
      hw_reset_seq.start(null); //启动
      /*这些内建sequence本质上并没有放到某个具体的sequencer执行,它只是用了sequence执行时调用body()的机制而已,因而我们传递任何的参数给sequence的start()只需要满足参数类型需求就行了,具体传递的值是多少并不重要*/
      
      
    • 设置reg不测试:
      uvm_resource_db#(bit)::set({"REG::",regmodel.blk.get_full_name(),".*"},
                                 "NO_REG_TESTS", 1, this);
      uvm_resource_db#(bit)::set({"REG::",regmodel.blk.reg.get_full_name(),".*"},
                                 "NO_REG_HW_RESET_TEST", 1, this);
      //reg_block/reg均可使用NO_REG_TESTS和NO_REG_HW_RESET_TEST
      //NO_REG_TESTS和NO_REG_HW_RESET_TEST区别在于前者针对所有的内建sequence都排除,而NO_REG_HW_RESET_TEST仅仅针对的是uvm_reg_hw_reset_seq这一单一sequence
  2. uvm_reg_single_bit_bash_seq
    • 功能:通过前门读写实现对寄存器读写访问域每个bit的遍历操作
    • 测试级别:uvm_reg
    • 原理:对每个可读可写域分别写入1和0并读出后座比较
    • 设置reg不测试:
  3. uvm_reg_bit_bash_seq
    • 功能:通过前门读写实现对所有寄存器读写访问域每个bit的遍历操作
    • 测试级别:uvm_reg_block
    • 原理:对包含所有uvm_reg都执行 <uvm_reg_bit_bash_seq> 序列
    • 注意事项:仅支持RW类型,对于其他类型如RO,RC这些需要exclude掉
    • 设置reg不测试:
  4. uvm_reg_single_access_seq
    • 功能:用来检查寄存器映射的有效性
    • 测试级别:uvm_reg
    • 原理:先从前门写入寄存器,而后从后门读回值对比;然后反过来后门写入再用前门读回,确保得到的结果值与镜像值匹配
    • 注意事项:
      • 要求寄存器的hdl路径完成映射
      • 没有可用后门的寄存器,或者只包含只读字段的寄存器,或者字段具有未知访问策略的寄存器,都不能被测试
    • 设置reg不测试:
  5. uvm_reg_access_seq
    • 功能:检查寄存器的读写
    • 测试级别:uvm_reg_block
    • 原理:对包含所有uvm_reg都执行 <uvm_reg_single_access_seq> 序列,来验证一个块内所有寄存器的可访问性
    • 注意事项: 需要在配置ral时,添加寄存器的层级路径,方便seq找到后门。
      //二者地址拼接
      XXX_RAL.set_hdl_path_root("xxx")
      xxx.configure(this,"")
    • 设置reg不测试:

  6.  uvm_reg_share_access_seq
    • 功能:用来检查所有可能访问寄存器路径的有效性
    • 测试级别:uvm_reg
    • 原理:先在一个地址映射中写入共享寄存器,然后通过其他所有可读的地址映射以及后门接口读取它,确保得到的值与镜像值一致
    • 设置reg不测试:
  7. uvm_reg_mem_hdl_paths_seq
    • 功能:检查hdl路径正确性

内建mem测试seq:

  1. uvm_mem_single_walk_seq:
  2. uvm_mem_walk_seq:
  3. uvm_mem_single_access_seq:
    1. 注意事项:需要存储模型的hdl路径已经指定
  4. uvm_mem_access_seq:
    1. 功能:
    2. 设置mem不测试:
      uvm_resource_db#(bit)::set({"REG::",rm.get_full_name(),".*"}, "NO_REG_TESTS", 1, this);
      uvm_resource_db#(bit)::set({"REG::",rm.get_full_name(),".*"}, "NO_MEM_TESTS", 1, this);
      uvm_resource_db#(bit)::set({"REG::",rm.invert.get_full_name(),".*"},"NO_MEM_ACCESS_TEST", 1, this);
  5. uvm_mem_shared_access_seq:
  6. uvm_mem_mam:动态内存分配
    1.  uvm_mem_mam介绍 
    2. Memory Allocation Manager

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

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

相关文章

WordPress博客在fnOS环境下的极简搭建与公网地址配置指南

文章目录 前言1. Docker下载源设置2. Docker下载WordPress3. Docker部署Mysql数据库4. WordPress 参数设置5. 飞牛云安装Cpolar工具6. 固定Cpolar公网地址7. 修改WordPress配置文件8. 公网域名访问WordPress 前言 你是否曾经为搭建自己的网站而头疼不已&#xff1f;是不是觉得…

计算机毕业设计SpringBoot校园二手交易小程序 校园二手交易平台(websocket消息推送+云存储+双端+数据统计)(源码+文档+运行视频+讲解视频)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

2025年前端面试题~ 【前端面试】更新

前言 金三银四的招聘季即将来临&#xff0c;对于怀揣前端梦想的求职者而言&#xff0c;这是机遇与挑战并存的黄金时段。前端面试可不只是简单的问答&#xff0c;它是一场对综合能力的深度检验。面试官会从多个维度考量&#xff0c;比如扎实的 HTML、CSS 和 JavaScript 基础&…

从基础到人脸识别与目标检测

前言 从本文开始&#xff0c;我们将开始学习ROS机器视觉处理&#xff0c;刚开始先学习一部分外围的知识&#xff0c;为后续的人脸识别、目标跟踪和YOLOV5目标检测做准备工作。我采用的笔记本是联想拯救者游戏本&#xff0c;系统采用Ubuntu20.04&#xff0c;ROS采用noetic。 颜…

Photoshop自定义键盘快捷键

编辑 - 键盘快捷键 CtrlShiftAltK 把画笔工具改成Q , 橡皮擦改成W , 涂抹工具改成E , 增加和减小画笔大小A和S 偏好设置 - 透明度和色域 设置一样颜色 套索工具 可以自定义套选一片区域 Shiftf5 填充 CtrlU 可以改颜色/色相/饱和度 CtrlE 合并图层 CtrlShiftS 另存…

LSTM的介绍

网上一些描述LSTM文章看的云里雾里&#xff0c;只是介绍LSTM 的结构&#xff0c;并没有说明原理。我这里用通俗易懂的话来描述一下。 我们先来复习一些RNN的核心公式&#xff1a; h t t a n h ( W h h t − 1 W x x t b h ) h_t tanh(W_h h_{t-1} W_x x_t b_h) ht​tan…

C++ ——从C到C++

1、C的学习方法 &#xff08;1&#xff09;C知识点概念内容比较多&#xff0c;需要反复复习 &#xff08;2&#xff09;偏理论&#xff0c;有的内容不理解&#xff0c;可以先背下来&#xff0c;后续可能会理解更深 &#xff08;3&#xff09;学好编程要多练习&#xff0c;简…

AI技术填坑记2:标注系统

在问答中,通用大模型往往拥有不可控性,而在正常的业务系统里面,往往有自己的各种专门的术语和内容,标注系统可以对大量数据进行标记,确认大模型解答的结果符合设想。 一、总体思路 一个标注,一般分为模块、应用、提问词汇、标注值,其中,模块可以认为是一种应用分类;应…

【机器学习】超参数的选择,以kNN算法为例

分类准确度 一、摘要二、超参数的概念三、调参的方法四、实验搜索超参数五、扩展搜索范围六、考虑距离权重的kNN算法七、距离的计算方法及代码实现八、明可夫斯基距离的应用九、网格搜索超参数 一、摘要 本博文讲解了机器学习中的超参数问题&#xff0c;以K近邻算法为例&#…

哪吒闹海!SCI算法+分解组合+四模型原创对比首发!SGMD-FATA-Transformer-LSTM多变量时序预测

哪吒闹海&#xff01;SCI算法分解组合四模型原创对比首发&#xff01;SGMD-FATA-Transformer-LSTM多变量时序预测 目录 哪吒闹海&#xff01;SCI算法分解组合四模型原创对比首发&#xff01;SGMD-FATA-Transformer-LSTM多变量时序预测效果一览基本介绍程序设计参考资料 效果一览…

Django开发入门 – 3.用Django创建一个Web项目

Django开发入门 – 3.用Django创建一个Web项目 Build A Web Based Project With Django By JacksonML 本文简要介绍如何利用最新版Python 3.13.2来搭建Django环境&#xff0c;以及创建第一个Django Web应用项目&#xff0c;并能够运行Django Web服务器。 创建该Django项目需…

2025.2.8——二、Confusion1 SSTI模板注入|Jinja2模板

题目来源&#xff1a;攻防世界 Confusion1 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;查看网页源码信息 step 2&#xff1a;模板注入 step 3&#xff1a;构造payload&#xff0c;验证漏洞 step 4&#xff1a;已确认为SSTI漏洞中的Jinjia2…

【C语言标准库函数】标准输入输出函数详解[5]:格式化文件输入输出

目录 一、fprintf() 函数 1.1. 函数简介 1.2. fprintf使用场景 1.3. 注意事项 1.4. 示例 二、fscanf() 函数 2.1. 函数简介 2.2. fscanf使用场景 2.3. 注意事项 2.3. 示例 三、总结 在 C 语言中&#xff0c;格式化文件输入输出函数能够让我们以特定的格式对文件进行…

【详细版】DETR系列之Deformable DETR(2021 ICLR)

论文标题Deformable DETR: Deformable Transformers for End-to-End Object Detection论文作者Xizhou Zhu, Weijie Su, Lewei Lu, Bin Li, Xiaogang Wang, Jifeng Dai发表日期2021年03月01日GB引用> Xizhou Zhu, Weijie Su, Lewei Lu, et al. Deformable DETR: Deformable T…

c++----函数重载

目录标题 为什么会有函数重载函数重载的概念函数重载的例子第一个&#xff1a;参数的类型不同第二个&#xff1a;参数的个数不同第三种&#xff1a;类型的顺序不同函数重载的奇异性重载函数的底层原理有关函数重载的一个问题 为什么会有函数重载 大家在学c语言的时候有没有发现…

从云原生到 AI 原生,谈谈我经历的网关发展历程和趋势

作者&#xff1a;谢吉宝&#xff08;唐三&#xff09; 编者按&#xff1a; 云原生 API 网关系列教程即将推出&#xff0c;欢迎文末查看教程内容。本文整理自阿里云智能集团资深技术专家&#xff0c;云原生产品线中间件负责人谢吉宝&#xff08;唐三&#xff09; 在云栖大会的精…

多头自注意力中的多头作用及相关思考

文章目录 1. num_heads2. pytorch源码演算 1. num_heads 将矩阵的最后一维度进行按照num_heads的方式进行切割矩阵&#xff0c;具体表示如下&#xff1a; 2. pytorch源码演算 pytorch 代码 import torch import torch.nn as nn import torch.nn.functional as Ftorch.set…

常用的python库-安装与使用

常用的python库函数 yield关键字openslide库openslide库的安装-linuxopenslide的使用openslide对象的常用属性 cv2库numpy库ASAP库-multiresolutionimageinterface库ASAP库的安装ASAP库的使用 concurrent.futures.ThreadPoolExecutorxml.etree.ElementTree库skimage库PIL.Image…

对接DeepSeek

其实&#xff0c;整个对接过程很简单&#xff0c;就四步&#xff0c;获取key&#xff0c;找到接口文档&#xff0c;接口测试&#xff0c;代码对接。 获取 KEY https://platform.deepseek.com/transactions 直接付款就是了&#xff08;现在官网暂停充值2025年2月7日&#xff0…

ChatGPT提问技巧:行业热门应用提示词案例-文案写作

ChatGPT 作为强大的 AI 语言模型&#xff0c;已经成为文案写作的得力助手。但要让它写出真正符合你需求的文案&#xff0c;关键在于如何与它“沟通”&#xff0c;也就是如何设计提示词&#xff08;Prompt&#xff09;。以下是一些实用的提示词案例&#xff0c;帮助你解锁 ChatG…