数字IC验证23912--寄存器模型

news2024/11/28 12:45:13

文章目录

  • 寄存器模型的集成
    • 总线UVC的实现
    • 总线UVC的示例
    • Adapter的实现
    • Adapter的集成
  • 访问方式
    • 前门访问
    • 后门访问

寄存器模型的集成

在这里插入图片描述

总线UVC的实现

  • MCDF访问寄存器的总线接口时序较为简单。控制寄存器接口首先需要在每一个时钟解析cmd。
  • 当cmd为写指令时,即需要把数据cmd_data_in写入到cmd_addr对应的寄存器中。
  • 当cmd为读指令时,即需要从cmd_addr对应的寄存器中读取数据,在下一个周期,cmd_addr对应的寄存器数据被输送至cmd_data_out接口。
  • 我们给出一段8位地址线,32位数据线的总线UVC实现代码。

总线UVC的示例

class mcdf_bus_trans extends uvm_sequence_item;
	rand bit[1:0] cmd;
	rand bit[7:0] addr;
	rand bit[31:0] wdata;
	bit[31:0] rdata;
	'uvm_object_utils_begin (mcdf_bus_trans)
	.......
	'uvm_object_utils_end
endclass
class mcdf_bus_sequencer extends uvm_sequencer;
	virtual mcdf_if vif;
	'uvm_component_utils (mcdf_bus_sequencer)
	...
	function void build phase (uvm_phase phase) ;
		if ( ! uvm_config_db# (virtual mcdf_if) : :get(this, "","vif", vif) ) begin
			'uvm_error("GETVIF", "no virtual interface is assigned")
		end
	endfunction
endclass

class mcdf bus_monitor extends uvm_monitor;
	virtual mcdf_if vif ;
	uvm _analysis _port # (mcdf_bus_trans) ap;
	'uvm_component_utils (mcdf bus_monitor)
	...
	function void build_phase (uvm phase phase) ;
		if (!uvm_config_db#(virtual mcdf_if) : :get(this, "","vif", vif)) begin
			'uvm_error("GETVIF", "no virtual interface is assigned" )
		end
		ap = new ("ap" , this);
	endfunction
	task run_ phase(uvm phase phase);
		forever begin
			mon_trans();
		end
	endtask
	task mon_trans ();
		mcdf_bus_trans t;
		@(posedge vif.clk) ;
		if(vif.cmd ==`WR工TE) begin
			t = new();
			t.cmd =`WRITE;t.addr = vif.addr;
			t.wdata = vif.wdata ;ap . write(t) ;
		end
		else if (vif .cmd ==`READ) begin
			t = new () ;
			t.cmd = `READ ;
			t.addr = vif.addr ;
			fork
				begin
					@(posedge vif.clk);
					#10ps ;
					t.rdata = vif.rdata;
					ap.write (t) ;
				end
			join_none
		end
	endtask
endclass: mcdf_bus_monitor

class mcdf_bus_driver extends uvm_driver;
	virtual mcdf_if vif;
	'uvm_component_utils (mcdf_bus_driver)
	...
	function void build phase(uvm phase phase) ;
		if (!uvm_config_db# (virtual mcdf_if)::get(this, "","vif", vif)) begin
			'uvm_error( "GETVIF", "no virtual interface is assigned" )
		end
	endfunction
	task run phase (uvm_phase phase);
		REQ tmp ;
		mcdf bus_trans req, rsp;
		reset_listener () ;
		forever begin
			seq_item_port.get_next_item ( tmp) ;
			void' ($cast(req, tmp)) ;
			uvm_info("DRV",$sformatf ("got a item \n %s", req.sprint() ),UVM_LOW)
			void' ($cast(rsp, req.clone())) ;
			rsp.set_sequence_id(req.get_sequence_id() ) ;
			rsp.set_transaction_id(req.get_transaction_id() );
			drive_bus (rsp) ;
			seq_item port.item_done(rsp) ;
			uvm_info( "DRV",$sformatf( "sent a item \n %s",rsp.sprint()),UVM_LOW)
		end
	endtask
	task drive_ read(mcdf bus_trans t);
		@(posedge vif.clk);
		vif .cmd <= t.emd;vif.addr <= t.addr ;e(posedge vif.clk);
		#10ps;
		t.rdata = vif.rdata;
	endtask
	task drive_idle (bit is_sync =0) ;
		if(is_sync) e(posedge vif.clk) ;
		vif.cmd <= 'h0 ;
		vif.addr <= 'h0 ;vif.wdata <= 'h0;
	endtask
endclass

示例囊括了mdf_bus_agent的所有组件:sequence item、sequencer、driver、monitor和agent。我们对这些代码的部分实现给出解释:

  • mcdf_bus_trans包括了可随机化的数据成员cmd、addr、wdata和不可随机化的rdata。rdata之所以没有声明为rand类型,是因为它应从总线读出或者观察,不应随机化。
  • mcdf_bus_monitor会观测总线,其后通过analysis port写出到目标analysis组件,在本节中它稍后将连接到uvm_reg_predictor.
  • mcdf_bus_driver主要实现了总线驱动和复位功能,通过模块化的方法reset_listener()、drive_bus()、drive_write()、drive_read()和drive_idle()可以解析三种命令模式IDLE、WRITE和READ,并且在READ模式下,将读回的数据通过item_done(rsp)写回到sequencer和sequence—侧。建议读者在通过clone()命令创建RSP对象后,通过set_sequence_id()和 set_transaction_id()两个函数保证REQ和RSP的中保留的ID信息一致。

Adapter的实现

在具备了MCDF总线UVC之后,需要实现adapter。每一个总线对应的adapter所完成的桥接功能即是在uvm_reg _bus_op和总线transaction之间的转换。用户在开发某一个总线adapter类型时,需要实现下面几点:

  • uvm_reg_bus_op与总线transaction中各自的数据映射。
  • 实现reg2bus()和bus2reg()两个函数,这两个函数即实现了两种transaction的数据映射。
  • 如果总线支持byte访问,可以使能supports_byte_enable;如果总线UVC要返回response数据,则应当使能provides_responses。在本例中,mcdf_bus_driver在读数时会将读回的数据填入到RSP并返回至sequencer,因此需要在adapter中使能provides_responses。由此使得bus2reg()函数调用时得到的数据是总线返回时的transaction,但读者需要注意如果总线UVC不支持返回RSP(没有调用put_response(RSP)或者item_done(RSP)),那么不应该置此位,否则adapter将会使得验证环境挂起。默认情况下,上述的两个成员的复位值都是0.
class reg2mcdf_adapter extends uvm_reg_adapter;
	`uvm_object_utils(reg2mcdf_adapter)
	function new (string name = "mcdf_bus_trans" );
		super.new (name) ;
		provides_responses = 1;
	endfunction
	function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op  rw);
		mcdf _bus_trans t = mcdf_bus_trans : : type_id : :create ("t") ;
		t.cmd = (rw.kind == UVM_WRITE)?`WRITE : ‘READ;
		t.addr = rw .addr ;
		t.wdata = rw.data;
		return t;
	endfunction
	function void bus2reg(uvm_sequence_item bus_item,ref uvm_reg_bus_op rw);
		mcdf_bus_trans t;
		if (!$cast(t, busmitem)) begin
			'uvm_ fatal( "Nor_MCDF_BUs_TYPE", "Provided bus_item is not of the correct type")
			return;
		end
		rw. kind = (t.cmd ==`WRITE) ? UVM_WRITE : UVM_READ;
		rw . addr = t.addr ;
		rw.data = (t.cmd ==`WRITE) ? t.wdata : t.rdata;
		rw.status = UVM_IS_OK;
	endfunction
endclass

关于uvm_reg_bus_op 有以下几个属性:
在这里插入图片描述

  • 该类在构建函数中使能了provide_responses,这是因为mcdf_bus_driver在发起总线访问之后会将RSP一并返回至sequencer。
  • reg2bus()完成的桥接场景是,如果用户在寄存器级别做了操作,那么寄存器级别操作的信息uvm_reg_bus_op会被记录,同时调用uvm_reg_adapter:reg2bus()函数。
  • 在完成了将uvm_reg_bus_op的信息映射到mcdf_bus_trans之后,函数将mcdf_bus_trans实例返回。而在返回mcdf_bus_trans之后,该实例将通过mcdf_bus_sequencer传入到mcdf_bus_driver。这里的transaction传输是后台隐式调用的,不需要读者自己发起。
  • 寄存器无论读写,都应当知道总线操作后的状态返回,对于读操作时,也需要知道总线返回的读数据,因此uvm_reg_adapter::bus2reg()即是从mcdf_bus_driver()将数据写回至mcdf_bus_sequencer,而一直保持监听的reg2mcdf_adapter一旦从sequencer获取了RSP (mcdf_bus_trans)之后,就将自动调用bus2reg()函数。
  • bus2reg()函数的功能与reg2bus()相反,完成了从mcdf_bus_trans到uvm_reg_bus_op的内容映射。在完成映射之后,更新的uvm_reg_bus_op数据最终返回至寄存器操作场景层。
  • 对于寄存器操作,无论读操作还是写操作,都需要经历调用reg2bus(),继而发起总线事务,而在完成事务发回反馈之后,又需要调用bus2reg(),将总线的数据返回至寄存器操作层面。

Adapter的集成

在具备了寄存器模型mcdf_rgm、总线UVC mcdf_bus_agent和桥接reg2mcdf_adapter之后,就需要考虑如何将adapter集成到验证环境中去:。

  • 对于mcdf_rgm的集成,我们倾向于顶层传递的方式,即最终从test层传入寄存器模型句柄。这种方式有利于验证环境mcdf_bus_env的闭合性,在后期不同test如果要对rgm做不同的配置,都可以在顶层例化,而后通过uvm_config_db来传递。
  • 寄存器模型在创建之后,还需要显式调用build()函数。需要注意uvm_reg_block是uvm_object类型,因此其预定义的build()函数并不会自动执行,还需要单独调用。
  • 在还没集成predictor之前,我们采用了auto prediction的方式,因此调用了函数set_auto_predict()。
  • 在顶层环境的connect阶段中,需要将寄存器模型的map组件与bus_sequencer和adapter连接。这么做的必要性在于将map (寄存器信息)、sequencer(总线侧激励驱动和adapter(寄存器级别和硬件总线级别的桥接关联在一起。也只有通过这一步,adapter的桥接功能才可以工作。
class mcdf_bus_env extends uvm_env;
	mcdf_bus_agent agent;
	mcdf_rgm rgm ;
	reg2mcdf_adapter reg2mcdf ;
	'uvm_component_utils (mcdf_bus_env)
	...
	function void build_ phase(uvm _phase phase) ;
		agent = mcdf_bus_agent : : type_id : : create ( "agent", this) ;
		if(!uvm_config_db# (mcdf_rgm): :get(this,"","rgm",rgm)) begin
			'uvm_info( "GETRGM","no top-down RGM handle is assigned",UVM_LOW)
			rgm = mcdf_rgm : : type_id: : create ("rgm" , this) ;
			'uvm_info("NEWRGM","created rgm instance locally",UVM_IOW)
		end
		rgm . build() ;
		rgm . map.set_auto_predict() ;
		reg2mcdf = reg2mcdf_adapter : : type_id: : create ( "reg2mcdf" );
  	endfunction
	function void connect _phase (uvm phase phase) ;
		rgm.map.set_sequencer (agent.sequencer, reg2mcdf);
	endfunction
endclass

访问方式

利用寄存器模型,我们可以更方便地对寄存器做操作。我们分成两种访问寄存器的方式,即前门访问(front-door)和后门访问(back-door)。

  • 前门访问,顾名思义指的是在寄存器模型上做的读写操作,最终会通过总线UVC来实现总线上的物理时序访问,因此是真实的物理操作。
  • 后门访问,指的是利用UVM DPI (uvm_hdl_read()、uvm_hdl_deposit()),将寄存器的操作直接作用到DUT内的寄存器变量,而不通过物理总线访问。

前门访问

  • 接下来前门访问的示例中的sequence继承于uvm_reg _sequence.uvm_reg_sequence除了具备一般uvm_sequence的预定义方法外,还具有跟寄存器操作相关的方法。
  • 在对寄存器操作的示例中,用户可以看到两种方式:
    ·第一种即uvm_reg:read()/write()。在传递时,用户需要注意将参数path指定为UVM_FRONTDOOR。uvm_reg:read()/write()方法可传入的参数较多,除了status和value两个参数需要传入,其它参数如果不指定,可采用默认值。
    ·第二种即uvm_reg_sequence:read_reg()/write_reg()。在使用时,也需要将path指定为UVM_FRONTDOOR。
class mcdf_example_seq extends uvm_reg_sequence ;
	mcdf_rgm rgm ;
	`uvm_object_utils (mcdf_example_seq)
	'uvm_declare_p_sequencer (mcdf_bus_sequencer)
	...
	task body ( ) ;
		uvm_status_e status ;uvm_reg_data_t data ;
		if (!uvm_config_db#(mcdf_rgm) : : get(null,get_full_name(),"rgm",rgm)) begin
			'uvm_error ("GETRGM","no top-down RGM handle is assigned")
		end
		//register model access write()/read()
		rgm. chn10_ctrl_reg.read (status,data,UVM_FRONTDOOR,parent(this));
		rgm.chn10_ctrl_reg.write(status,'h11,UVM_FRONTDOOR,parent(this));
		rgm. chn10_ctrl_reg.read (status,data,uVM_FRONTDOOR,.parent(this));
		//pre-defined methods access
		read_reg (rgm. chnl1_ctrl_reg,status, data,uVM_FRONTDOOR);
		write_reg (rgm. chnl1_ctrl_reg, status,'h22,uVM_PRONTDOOR);
		read_reg (rgm.chnl1_ctrl_reg,status,data,UVM_FRONTDOOR);
	endtask
endclass

后门访问

  • 在进行后门访问时,用户首先需要确保寄存器模型在建立时,是否将各个寄存器映射到了DUT一侧的HDL路径。
  • 下面的例码即实现了寄存器模型与DUT各个寄存器的路径映射:
class mcdf_rgm extends uvm_reg_block ;
... //寄存器成员和map声明
	virtual function build() ;
	...//寄存器成员和map创建
	  //关联寄存器模型和HDL
	add_hdl_path ( "reg_backdoor_access.dut") ;
	chn10_ctrl_reg.add_hdl path_slice($sformatf ("regs[%0d] ",‘SLVO_Rm_REG),0,32);
	chnll_ctrl_reg.add_hdl_path_slice($sformatf ( "regs[%0d]",‘sLV1_RW_REG),0,32);
	chn12_ctrl_reg.add_hdl _path_slice($sformatf("regs[%0d] ",‘SLV2_RW_REG),0,32);
	chn10_stat_reg.add_hdl_path_slice($sformatf ( "regs[%0d]",‘SLVo_R_REG ),0,32);
	chnll_stat_reg.add_hdl_path_slice($sformatf ("regs[%0d] ",‘SLV1_R_REG ),0,32);
	chn12_stat_reg.add_hdl path_slice($sformatf ( "regs[%0d]",‘SIV2_R_REG ) ,0,32);
	lock_model () ;
	endfunction
endclass
  • 示例中通过uvm_reg_blockadd_hdl_path(),将寄存器模型关联到了DUT一端,而通过uvm_reg:add_hdl_path_slice完成了将寄存器模型各个寄存器成员与HDL一侧的地址映射。
  • 另外,寄存器模型build()函数最后以lock_model()结尾,该函数的功能是结束地址映射关系,并且保证模型不会被其它用户修改。
  • 在寄存器模型完成了HDL路径映射后,我们才可以利用uvm_reg或者uvm_reg_sequence自带的方法进行后门访问。后门访问也有几类方法提供:
    . uvm_reg:read()/write(),在调用该方法时需要注明UVM_BACKDOOR的访问方式。
    . uvm_reg_sequenceread_reg()/write_reg(),在使用时也需要注明UVM_BACKDOOR的访问方式。
    ·另外,uvm reg::peek()/poke()两个方法,也分别对应了读取寄存器(peek)和修改寄存器(poke)两种操作,而用户无需指定访问方式尾UVM_BACKDOOR,因为这两个方法本来就只针对于后门访问。
class mcdf_example_seq extends uvm_reg_sequence ;
	mcdf_rgm rgm ;
	'uvm_object_utils (mcdf_example_seq)
	'uvm_declare _p_sequencer(mcdf_bus_sequencer)
	task body () ;
		uvm status_e status ;uvm _reg_data_t data ;
		uvm_status_e status ;uvm_reg_data_t data;
		if (!uvm_config_db# (madf_rgm) : : get(null,get_full_name (), "rgm",rgm)) begin
			'uvm_error("GETRGM","no top-down RGM handle is assigned")
		end
		//register model access write ( ) /read()
		rgm.chn10_ctrl_reg.read (status,data,UVM_BACKDOOR,parent(this)) ;
		rgm. chn10_ctrl_reg.write(status,'h11,,UVM_BACKDOOR,parent (this) );
		rgm. chn10_ctrl_reg.read (status,data,UVM_BACKDOOR,.parent(this) );
		//register model access poke( ) /peed ()
		rgm. chnl1_ctrl_reg.peek (status,data,.parent (this));
		rgm. chnl1_ctrl_reg.poke (status, 'h22,.parent(this));
		rgm. chnl1_ctrl_reg.peek (status, data,.parent(this));
		//pre-defined methods read_reg()/write_reg ()
		read_reg (rgm.chn12_ctrl_reg,status,data,UVM_BACKDOOR);
		write_reg (rgm.chn12_ctrl_reg,status,'h22,UVM_BACKDOOR);
		read_reg (rgm.chn12_ctrl_reg,status,data,UVM_BACKDOOR);
		//pre-defined methods peek _reg ()/poke_reg()
		peek_reg (rgm.chnl2_ctr1_reg, status, data);
		poke_reg (rgm.chnl2_ctrl_reg, status, 'h33);
		peek_reg (rgm. chnl2_ctrl_reg, status, data) ;

在这里插入图片描述

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

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

相关文章

Linux安装mysql8.0.34(图文详细教程2023)

安装mysql数据库目录2023-09-13更新 1. 下载mysql数据库2. 安装3. mysql启动4. 进入数据库修改密码 以下是root用户操作&#xff0c; 非root用户&#xff0c;命令前请添加sudo 1. 下载mysql数据库 下载地址&#xff1a; https://dev.mysql.com/downloads/mysql/ 获取下载链接&…

OPENCV进行图像修复

API # -*- coding:utf-8 -*- """ 作者:794919561 日期:2023/9/14 """ import cv2 import numpy as npimg = cv2.imread("F:\\learnOpenCV\\openCVLearning\\pictures\\Lena.jpg") mask = cv2.imread

移动测试之语音识别功能如何测试?

移动测试之语音识别功能如何测试&#xff1f; 要知道语音识别功能如何测试&#xff0c;我们先了解智能产品语音交互流程&#xff1a; 所以&#xff0c;要进行测试的话&#xff0c;我们需要从以下几个维度来准备测试点&#xff1a; 基础功能测试&#xff1a; 1、声纹的录入&…

不定积分的概念和性质

目录 原函数 不定积分 不定积分的几何意义 原函数的存在定理 不定积分的性质 不定积分是微积分的一个关键部分&#xff0c;它涉及到一个函数的不定积分的计算。不定积分可以理解为求一个函数的原函数&#xff0c;也被称为反导数。原函数是一个函数&#xff0c;使得该函数的…

MongoDB-1入门介绍

NoSQL NoSQL(NoSQL Not Only SQL)&#xff0c;意即反SQL运动&#xff0c;指的是非关系型的数据库 优点 1、对数据库高并发读写。 2、对海量数据的高效率存储和访问。 3、对数据库的高可扩展性和高可用性。 弱点&#xff1a; 1、数据库事务一致性需求 2、数据库的写实时性…

多模态图像合成与编辑

由于信息在现实世界中以多种形式存在&#xff0c;多模态信息之间的有效交互和融合对于计算机视觉和深度学习研究中多模态数据的创建和感知起着关键作用。多模态图像合成与编辑由于具有强大的多模态信息交互建模能力&#xff0c;成为近年来的研究热点。多模态引导不是为网络训练…

点云从入门到精通技术详解100篇-从全局到局部的三维点云细节差异分析

目录 前言 国内外研究现状 细节差异分析相关研究 三维点云的相似性相关研究 存在的问题 三维点云对比的相关技术 2.1 三维点云的采集设备 2.2三维点云的存储格式 2.3三维点云的空间变换 2.4三维点云相似度分析 2.4.1点云特征的提取 2.4.2特征相似度计算 本文篇幅较长&#xff0…

解决java.util.NoSuchElementException

解决java.util.NoSuchElementException 解决java.util.NoSuchElementException摘要引言正文1. 了解异常的根本原因2. 避免不正确的索引3. 处理空集合4. 使用迭代器时要小心5. 异常处理 总结参考资料 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客&#x1f466;&…

博客-三更草堂

博客-三更草堂 后台分类页面修改&#xff0c;添加状态修改接口 ① …前端工程\sg-vue-admin\src\api\content\category.js 文件中添加新接口 // 修改分类状态 export function changeCategoryStatus(id, status) {const data {id,status}return request({url: /content/cat…

【编程实践】使用pcl提取给定点云的三维边界点

1 执行结果 原始点云可视化 搜索半径设置为0.1m 搜索半径设置为0.05m 2 代码实现 // boundary#include <pcl/point_types.h> #include <pcl/features/normal_3d.h> #include <pcl/features/boundary.h> #include <pcl/io/file_io.h> #include &l…

面对 HR 的空窗期提问,你会如何回答?

原文链接 面对 HR 的空窗期提问&#xff0c;你会如何回答&#xff1f; 你是否有过这样的经历&#xff0c;在一段时间内&#xff0c;你离开了工作岗位&#xff0c;或者在寻找新的工作机会&#xff0c;这段时间我们称之为“空窗期”。 对于这段时间&#xff0c;我们该如何看待&…

idea中的debug界面上没有进入方法的红色按钮

问题描述&#xff1a; 这里缺少进入系统方法的红色按钮。 问题解决方法&#xff1a; 在上面图片红框范围内右键点击进入。 点击号 搜索 ‘force’ 添加即可完成 上下拖动即可调整界面按钮顺序

I2C总线协议

什么是I2C I2C&#xff08;Inter-Integrated Circuit&#xff09;&#xff0c;也可以叫IIC、I2C&#xff0c;译作集成电路总线&#xff0c;是两线式串行通信总线&#xff0c;用于设备间的通讯等&#xff0c;标准情况下最高传送速率达100Kbps。顾名思义&#xff0c;I2C通讯只需…

如何用示波器测量放电波形

示波器那么重要&#xff0c;你确定不进来看看&#xff1f;_哔哩哔哩_bilibili 5分钟搞明白示波器的 带宽 采样率 存储深度_哔哩哔哩_bilibili 年轻人的第一台示波器选手持还是台式&#xff1f;_哔哩哔哩_bilibili 以示波器为例&#xff0c;测量某设备波形。 1、开机&#xff…

在Excel中使用SQL

说明: Excel中许多函数虽然能代替SQL的功能&#xff0c;但是比起SQL&#xff0c;还是有一些逊色&#xff0c;特意做了这个教程&#xff0c;主要有: 分组统计&#xff0c;Excel中用数据透视表&#xff0c;SQL中用Group By去重&#xff0c;Excel中可以用条件标识功能(开始->条…

Lyft 计划开源人工智能算法测试工具

共享租车公司 Lyft 投入大量时间和资源开发工具来测试机器学习算法&#xff0c;近日 Lyft 宣布将向公众开源这些工具。正式投入生产环境之前&#xff0c;一款机器学习算法的测试和更替非常耗费时间&#xff0c;Lyft 开发的测试工具&#xff0c;是属于一种模拟器&#xff0c;能够…

LLM 03-大模型的有害性

LLM 03-大模型的有害性 3.1 引言1 在这次内容中&#xff0c;我们将开始探讨大型语言模型的有害性&#xff08;危害&#xff09;。在这门课程中&#xff0c;我们将涵盖几种这些危害: 性能差异社会偏见和刻板印象有害信息虚假信息 另外在之后的课程中会讲述其他更多层面的危害…

内存管理机制

aCoral内存管理机制 aCoral内存管理机制在伙伴系统基础上&#xff0c;采用了位图法方式提高内存分配和回收速度的确定性&#xff0c;更能满足系统实时性的需求。 aCoral内存管理机制分为两级&#xff0c;上一级采用改进的伙伴系统&#xff0c;负责确定要分配的内存的大小&…

莫比乌斯召回系统介绍

当前召回系统只能召回相关性高的广告&#xff0c;但不能保证该广告变现能力强。莫比乌斯做了如下两点创新&#xff1a; 在召回阶段&#xff0c;引入CPM等业务指标作为召回依据在召回阶段&#xff0c;引入CTR模型&#xff0c;从而召回更多相关性高且变现能力强的广告 参考 百度…

【ROS】Ubuntu20.04+ROS Noetic 配置PX4-v1.12.2和Gazebo11联合仿真环境【教程】

【ROS】Ubuntu20.04ROS Noetic 配置PX4-v-v1.12.2和Gazebo11联合仿真环境【教程】 文章目录 【ROS】Ubuntu20.04ROS Noetic 配置PX4-v-v1.12.2和Gazebo11联合仿真环境【教程】0. 安装UbuntuROS1. 安装依赖2. 安装QGC地面站3. 配置PX4-v1.12.23.1 安装PX43.2 测试PX4是否成功安装…