当前位置: 首页 > article >正文

【UVM】寄存器模型

寄存器模型的优势

  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 accessibledata.configure(this,  16,  0,  "RW",  1,   0,   1,    1,    0);endfunctionfunction  new(input string name="my_reg");//parameter: name, size, has_coveragesuper.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;...
endclassclass buf_blk extends uvm_reg_block;...
endclassclass mac_blk extends uvm_reg_block;...
endclassclass 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);endfunctionendclass

步骤总结

  •  第一步是先实例化子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)
endclassclass 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 : newfunction 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 : reg2busfunction 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;endrw.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;…endclassfunction 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;endfunctionfunction 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
    …
    endclassfunction 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

相关文章:

【UVM】寄存器模型

寄存器模型的优势 sequence复用性高&#xff0c;方便对 DUT 中寄存器进行读写&#xff1b;提供了后门访问方式&#xff0c;可以不耗时的获取寄存器的值&#xff1b;可以很方便的对寄存器的 coverage 验证点的收集 寄存器模型基本概念 寄存器模型概念作用uvm_reg_field寄存器模…...

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 基础&…...

深入 JVM 虚拟机:字符串常量池演变与 intern() 方法工作原理解析

🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 仓库主页: GitCode︱ Gitee ︱ Github 💖 欢迎点赞 👍 收藏 ⭐评论 📝 如有错误敬请纠正! 前言 在 Java 开发中,字符串常量池(String Constant…...

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

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

Java内存模型,内存屏障是干嘛的?

目录 Java 内存模型(Java Memory Model,JMM) 1. 定义和目的 2. 内存结构 3. 三大特性 4. happens-before 原则 内存屏障(Memory Barrier) 1. 定义和作用 2. 分类 3. 在 Java 中的应用 Java 内存模型(Java Memory Model, JMM) 1. 核心概念 2. 内存交互规则 …...

rdian是一个结构体,pdian=^Rdian,list泛型做什么用?

不明白不让编译的原因&#xff0c;记录下之遇到注意原油。 var mylist:TList<string>; mylist1:TList<Pdian>; mydian:Pdian; i:Integer; mylist2:TList<Rdian>; mydian2:rdian; arr:array of Rdian; begin mylist:TList…...

Photoshop自定义键盘快捷键

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

C++智能指针的使用

文章目录 智能指针的使用和原理智能指针的使用场景RAII和智能指针C标准库智能指针的使用 智能指针的使用和原理 智能指针的使用场景 1. 下面的程序中&#xff0c;new了以后&#xff0c;我们也delete了&#xff0c;但是因为抛异常导致后面的delete没有得到执行&#xff0c;所以…...

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;格式化文件输入输出函数能够让我们以特定的格式对文件进行…...

【故障处理】 - 12C ADG备库密码文件的MD5值不断变化

【故障处理】 - 12C ADG备库密码文件的MD5值不断变化 一、概述二、报错原因&#xff1a;三、处理过程 一、概述 12C版本以后&#xff0c;密码文件的MD5值会持续变化。 二、报错原因&#xff1a; Oracle 数据库软件版本12.2 开始&#xff0c;当以具有管理权限的用户身份执行与数…...

【LeetCode Hot100 多维动态规划】最小路径和、最长回文子串、最长公共子序列、编辑距离

多维动态规划 机器人路径问题思路代码实现 最小路径和问题动态规划思路状态转移方程边界条件 代码实现 最长回文子串思路代码实现 最长公共子序列&#xff08;LCS&#xff09;题目描述解决方案 —— 动态规划1. 状态定义2. 状态转移方程3. 初始化4. 代码实现 编辑距离&#xff…...

【PG】DROP TABLE ... CASCADE

问题 ERROR: cannot drop table wx_user_tag because other objects depend on it DETAIL: default value for column id of table wx_user_tag depends on sequence wx_user_tag_id_seq HINT: Use DROP … CASCADE to drop the dependent objects too. 解决 这个错误消息表…...

青少年编程与数学 02-009 Django 5 Web 编程 04课题、应用创建

青少年编程与数学 02-009 Django 5 Web 编程 04课题、应用创建 一、项目及应用创建 Django 项目创建 Django 应用配置和测试 二、数据库的设置步骤 1: 创建 Django 项目步骤 2: 配置数据库PostgreSQLMySQL 步骤 3: 安装必要的数据库驱动步骤 4: 进行数据库迁移步骤 5: 创建应用…...

速度超越DeepSeek!Le Chat 1100tok/s闪电回答,ChatGPT 4o和DeepSeek R1被秒杀?

2023年&#xff0c;当全球科技界还在ChatGPT引发的AI狂潮中沉浮时&#xff0c;一场来自欧洲的"静默革命"正悄然改变游戏规则。法国人工智能公司Mistral AI推出的聊天机器人Le Chat以"比ChatGPT快10倍"的惊人宣言震动业界&#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; 在云栖大会的精…...

前端开发中,如何判断一个元素是否在可视区域中?

在前端开发中&#xff0c;判断一个元素是否在可视区域中是一个常见的需求&#xff0c;比如实现懒加载图片、无限滚动加载更多内容等功能。下面我将详细阐述这个问题。 一、判断元素是否在可视区域的方法 1. 使用 getBoundingClientRect 方法 getBoundingClientRect 方法返回…...

【干活分享】2025年可以免费问答的一些GPT网站-deepseek等免费gpt

2025年已经到来&#xff0c;大家也都陆续回归到忙碌的工作中。在新的一年里&#xff0c;如何更高效地完成工作任务&#xff0c;提升工作效率&#xff0c;是很多人关心的问题。今天&#xff0c;就为大家分享一些实用性很强的GPT网站&#xff0c;帮助大家在工作中事半功倍。 Dee…...

使用Redis实现业务信息缓存(缓存详解,缓存更新策略,缓存三大问题)

一、什么是缓存? 缓存是一种高效的数据存储方式,它通过将数据保存在内存中来提供快速的读写访问。这种机制特别适用于需要高速数据访问的应用场景,如网站、应用程序和服务。在处理大量数据和高并发请求时, 缓存能显著提高性能和用户体验。 Redis就是一款常用的缓存中间件。…...

ORB-SLAM3源码的学习:Atlas.cc②: Atlas:: CreateNewMap创建新地图

前言 简单总结一下地图是何时创建的&#xff1a; 构建slam系统时还没有地图就需要创建&#xff0c;当时间戳不对劲时影响数据的同步时需要创建&#xff0c;当跟踪的第一和第二阶段都为失败时都要分别创建&#xff0c;且满足一定要求的地图会保留作为非活跃地图。 1.创建新地…...