Bluespec SytemVerilog 握手协议接口转换

01、引言

由于接口控制信号上的差异,要实现Bluespec SystemVerilog(BSV)生成的代码和外部Verilog代码之间的正确交互是一件比较麻烦同时容易出错的事情。在BSV中, 模块之间的交互都是基于Action或ActionValue这两类method完成。下图展示了使用BSV设计的某一模块的接口定义及其实际生成的硬件端口。由图可见,除了被显式地定义为函数输入参数或返回类型的数据信号外,每个method都隐含着一对控制信号,即en和rdy。

其中,rdy信号指示该方法已经准备好被调用,而当外部模块调用该方法时会拉高对应的en信号。en-rdy控制信号和AXI总线中valid-ready信号的作用类似,这两对信号都保证了当通信双方都准备好时才能完成一拍数据的传输。虽然完成的功能相同,但这两对信号在具体的实现机制上仍存在一定差异:

首先,en-rdy和valid-ready并不是一一对应的关系。对于某个模块,en永远是输入信号,而rdy永远是输出信号。而在valid-ready握手协议中,master端输出valid接收ready,而slave端输出ready接收valid。因此,这两对信号有如下表所示的对应关系:

masterslave
validrdyen
readyenrdy

其次,是控制信号之间依赖关系的差异。在BSV中,method的en信号依赖于rdy信号,具体来说一个method只有在其准备好(rdy为高)时才能被调用。下图展示了这一依赖关系在硬件上的具体实现,即输入的en信号需要和输出的rdy信号相与后传递给下一级。而在AXI协议中,为了避免产生死锁(通信双方都等待对方准备好后再响应),其明确规定:master输出的valid信号不能依赖于ready信号,即不能等待slave侧准备好后再发起请求;相反,slave端输出的ready信号可以依赖于输入的valid,即可以等待master发起请求后再作响应。

在大部分使用Verilog实现的电路中,我们都会基于valid-ready握手协议实现模块之间的交互。如果在一个项目中,我们需要将BSV生成的代码和基于Verilog的设计进行交互,通常还需要实现一个转换模块,来处理valid-ready和en-rdy控制信号之间的交互。

除了控制信号的差异外,BSV生成的Verilog代码还存在如下问题:如果在BSV中将多个相关的输入/输出信号封装在一个结构体,那么在生成的Verilog接口中所有封装在一起的字段都会合并成单个信号。例如,在BSV中使用AXI-Stream总线时,为了方便信号传递,通常会将总线上的信号封装成一个结构体后在方法之间传递:

typedef struct {Bit#(TMul#(keepWidth, 8)) tData;Bit#(keepWidth) tKeep;Bit#(usrWidth) tUser;Bool tLast;
} AxiStream#(numeric type keepWidth, numeric type usrWidth) deriving(Bits);interface AxiStreamExample;interface Put#(AxiStream#(8, 1)) axiStreamSlave;interface Get#(AxiStream#(8, 1)) axiStreamMaster;
endinterface

而在生成的Verilog代码中,结构体里定义的所有字段都合并到了axiStreamSlave_put/axiStreamMaster_get信号里:

module mkAxiStreamExample(CLK,RST_N,axiStreamSlave_put,EN_axiStreamSlave_put,RDY_axiStreamSlave_put,EN_axiStreamMaster_get,axiStreamMaster_get,RDY_axiStreamMaster_get
);

如果我们要将上述代码与其他Verilog模块交互,需要添加一个额外的模块对生成的mkAxiStreamExample进行封装。该模块需要完成两件事:

1)将合并的信号解析成每个独立的信号,

2)将en-rdy转换为valid-ready握手协议。

以Master端信号的封装为例,具体的实现代码如下:

module mkAxiStreamExampleWrapper(input clk,input reset_n,output m_axis_tvalid,input  m_axis_tready,output m_axis_tlast,output m_axis_tuser,output [63:0] m_axis_tdata,output [ 7:0] m_axis_tkeep,
);mkAxiStreamExample axiStreamExampleInst (.CLK   (    clk),.RST_N (reset_n),.RDY_axiStreamMaster_get (m_axis_tvalid),.EN_axiStreamMaster_get  (m_axis_tvalid & m_axis_tready),.axiStreamMaster_get ({m_axis_tdata, m_axis_tkeep, m_axis_tuser, m_axis_tlast}));
endmodule

虽然上面展示的Verilog封装模块可以保证模块间正确的交互,但仍存在一些缺陷。首先,解析打包信号的方式与BSV中结构体的定义相关,如果结构的内容发生更改,封装模块解析出的结果就可能出错。其次,手动地处理en-rdy和valid-ready信号对之间的转换也容易出错。这些问题都降低了BSV项目的可维护性。

为了方便BSV和Verilog之间的交互,我们实现了blue-wrapper项目并提供了等同于上述Verilog封装的BSV实现,使得经过封装的BSV模块所生成的代码能够直接和其他Verilog模块进行交互。下文将介绍blue-wrapper的具体实现及其使用方式,主要包括三部分内容:

  • PipeOut/PipeIn接口的定义,对应代码实现见 src/SemiFifo.bsv
  • 基于PipeOut/PipeInGet/Put接口实现握手控制信号转换, 详细代码实现可见 src/BusConversion.bsv;
  • 控制信号转换的基础上,还需要对完成对数据信号的解析,blue-wrapper中分别提供了对AXI-Stream,AXI4-Lite和AXI4-Full等协议的支持;

下文将结合实际代码分别介绍这三部分的具体实现。

02、PipeOut/PipeIn接口

在基于valid-ready控制信号对的数据交互场景下,交互双方可分为Master和Slave。其中,Master端发起数据传输,可对应BSV中常用的Get接口,而Slave负责接收数据,因此可以对应BSV中的Put接口。除了Get/Put外,为了方便实现握手控制信号的转换,blue-wrapper中还额外定义了PipeOut/PipeIn接口,这两个接口分别封装了FIFOF接口出队侧(deq)和入队(enq)侧的方法,具体定义如下:

interface PipeIn#(type dType);method Action enq(dType data);method Bool   notFull();
endinterfaceinterface PipeOut#(type dType);method dType  first();method Action deq();method Bool   notEmpty();
endinterface

从实现功能的角度上看,PipeOut/PipeInGet/Put接口类似,都可分别实现数据的输出/输入。但对于Get/Put接口,其get/put方法所隐含的en-rdy控制信号在BSV中是无法访问的。而对于PipeOut/PipeIn接口,其将deq/enq方法对应的rdy信号分别通过notEmpty/notFull方法暴露出来,使得我们可以直接在BSV中对其进行访问,而这一点将极大地方便握手控制信号的转换。

03、握手控制信号转换

显式定义valid-ready信号

实现接口转换的第一步需要在interface中定义valid和ready信号对应的method,一方面使得生成的Verilog代码直接包含valid-ready信号对,另一方面方便我们在BSV中操纵这两个信号实现握手协议转换。在BSV中,一个方法的返回值对应Verilog的输出端口,而方法的输入参数对应输入端口,基于该原则,valid-ready协议的Master/Slave侧接口的BSV定义如下:

(* always_ready, always_enabled )
interface RawBusMaster#(type dType);( result = "data" ) method dType  data;( result = "valid"*) method Bool   valid;(* prefix = "" ) method Action ready(( port = "ready" ) Bool rdy);
endinterface( always_ready, always_enabled )
interface RawBusSlave#(type dType);( prefix = "" ) method Action validData(( port = "valid"   ) Bool valid,( port = "data"    ) dType data);( result = "ready" *) method Bool ready;
endinterface

上述代码中,编译属性“always_ready”和“always_enabled”消除了每个method隐含的en-rdy控制信号对。同时,我们可以通过设置输出method的“result”属性和每个输入参数的“port”属性来指定生成的Verilog中每个端口的具体名称。

en-rdy和valid-ready之间的转换

在定义好包含valid-ready控制信号的interface后,下一步需要完成en-rdy到valid-ready握手控制信号的转换。blue-wrapper项目分别提供了两种不同的转换思路:

1. 将需要封装的PipeOut/PipeIn接口作为参数传入转换模块供valid/ready信号对应的method调用;

2. 将RawBusMaster/Slave接口分别封装成PipeIn/PipeOut接口供其他BSV模块调用;

基于第一种思路实现的转换模块包括: mkPipeOutToRawBusMaster/mkPipeInToRawBusSlave,以及mkGetToRawBusMaster和mkPutToRawBusSlave。以mkPipeOutToRawBusMaster为例,该模块接收PipeOut接口作为输入参数,并返回RawBusMaster接口,其中各个method的实现思路和具体代码如下:

  • valid: 对于Master端,其valid信号对应BSV中的rdy信号,而PipeOut接口通过notEmpty方法暴露出了deq方法对应的rdy,因此valid方法直接返回notEmpty的值;
  • data: 对应PipeOut接口的first方法;
  • ready: 作为方法输入参数传递的ready信号对应BSV中的en控制信号,该值为真时需要调用PipeOut接口的deq方法。由于在BSV中调用任意method,编译器都会自动保证上文提到的en-rdy的依赖关系,因此在调用deq方法时不需要额外检查其rdy信号来保证握手成功。
module mkPipeOutToRawBusMaster#(PipeOut#(dType) pipe
)(RawBusMaster#(dType));RWire#(dType) dataW <- mkRWire;Wire#(Bool) readyW <- mkBypassWire;rule passWire if (pipe.notEmpty);dataW.wset(pipe.first);endrulerule passReady if (readyW);pipe.deq;endrulemethod Bool valid = pipe.notEmpty;method dType data = fromMaybe(?, dataW.wget);method Action ready(Bool rdy);readyW <= rdy;endmethod
endmodule

对于PipeIn到RawBusSlave的转换,其实现的原理和Master端类似,具体代码如下:

module mkPipeInToRawBusSlave#(PipeIn#(dType) pipe
)(RawBusSlave#(dType));Wire#(Bool)  validW <- mkBypassWire;Wire#(dType) dataW <- mkBypassWire;rule passData if (validW);pipe.enq(dataW);endrulemethod Action validData(Bool valid, dType data);validW <= valid;dataW <= data;endmethodmethod Bool ready = pipe.notFull;
endmodule

对于Get/Put接口,由于在BSV中无法直接访问get/put方法的rdy信号,直接进行转换无法提取出master输出的valid信号以及slave输出的ready信号。因此,在blue-wrapper的实现中我们通过添加一个额外的FIFOF模块作为媒介,将Get/Put接口转换成PipeOut/PipeIn接口后,调用上面展示的两个模块实现控制信号的转换,以Get接口为例,具体的代码实现如下:

module mkGetToRawBusMaster#(Get#(dType) get
)(RawBusMaster#(dType));FIFOF#(dType) fifo <- mkFIFOF;mkConnection(get, toPut(fifo));let rawBus <- mkPipeOutToRawBusMaster(convertFifoToPipeOut(fifo));return rawBus;
endmodule

第二种实现思路对应代码中的:mkRawBusMasterToPut/mkRawBusMasterToGet,以及mkRawBusMasterToPipeIn/mkRawBusMasterToPipeOut四个模块。这种转换方式分别用PipeIn/PipeOutPut/Get接口封装RawBusMaster/RawBusSlave接口对于其他BSV模块,可以通过PipeIn/Put接口将数据传入转换模块然后从RawBusMaster发送出去,同时可以通过PipeOut/Get接口获取从RawBusSlave上接收到的数据。这种实现方式和BSV提供的BVI接口类似。以master侧为例,具体的转换实现如下:

首先,我们需要定义RawBusMasterToPipeIn接口,其由两个子接口RawBusMasterPipeIn组成,其中PipeIn用于封装RawBusMaster使其可供其他BSV模块调用。

对于RawBusMaster接口,其实现代码主要是在进行信号的传递, 从validData中取出valid和data方法的返回值,并将ready方法的输入参数传递给readyW

对于PipeIn接口, notFull方法返回readyW的值,enq方法将传入的参数写入validData。同时为了保证握手成功,enq方法需要被readyW所守卫(guarded), 即当输入的ready信号为高时,才可调用enq方法传入数据。

interface RawBusMasterToPipeIn#(type dType);interface RawBusMaster#(dType) rawBus;interface PipeIn#(dType) pipe;
endinterfacemodule mkRawBusMasterToPipeIn(RawBusMasterToPipeIn#(dType));RWire#(dType) validData <- mkRWire;Wire#(Bool) readyW <- mkBypassWire;interface RawBusMaster rawBus;method Bool valid = isValid(validData.wget);method dType data = fromMaybe(?, validData.wget);method Action ready(Bool rdy);readyW <= rdy;endmethodendinterfaceinterface PipeIn pipe;method Bool notFull = readyW;method Action enq(dType data) if (readyW);validData.wset(data);endmethodendinterface
endmodule

对于Get/Put接口,也可以使用上述方法对RawBusSlave/RawBusMaster接口进行封装,其实现的关键点都是要为get和put方法设置正确的守卫信号以保证握手成功.

死锁问题

为了避免master和slave之间互相等待而产生死锁,AXI文档中规定master不能等待slave侧拉高ready后再输出有效的valid和data,但允许slave侧在master拉高valid之后再置ready为高。在BSV中对于每个method,en只有在rdy信号拉高后才能拉高。由于en-rdy和valid-ready不同的依赖关系,在交互的过程中就有可能导致双方产生死锁。下文将主要针对上面提到的两种封装方法,分析其是否会引入死锁问题。

  • 第一种封装方式相当于是在转换模块中调用传入的PipeOut/PipeIn接口的方法。在BSV中调用任何方法,编译器都会自动地为en添加对于rdy的依赖,具体的en-rdy和valid-ready间的交互可以由下图所示。其中,en-rdy之间的依赖关系如红色虚线所示。当Slave侧为Verilog实现时,valid和ready之间可能存在如黑色虚线所示的依赖关系。由图可知,这两种依赖关系同向因此不会产生死锁。

  • 第二种封装方式类似于BSV提供的BVI接口,其将Verilog信号封装成BSV中的method供其他模块调用。同样的,对于这些method,BSV会给en信号添加对rdy的依赖,如下图红色虚线所示。而基于Verilog实现的Slave端口,其valid-ready之间可能存在如黑色虚线所示的依赖关系。由图可见,en-rdy和valid-ready之间正好形成了一个死锁环路,即master端等待ready拉高后输出有效的valid,而slave等待master输出有效valid后再拉高ready。因此,在使用mkRawBusMasterToPipeOut转换模块时需要保证所对接的slave侧Verilog实现中不存在ready对valid的依赖。

04、信号解析

完成控制信号的转换后,我们已经实现了可生成valid-ready控制信号的RawBusMaster#(dType)RawBusSlave#(dType)接口但是,如果dType是用户定义的struct结构体,则生成的Verilog会将struct中的所有字段打包到一个信号中。因此,我们仍然需要在BSV中将结构体的每个字段解析为单独的信号,以生成直接可用的Verilog代码。blue-wrapper分别提供了针对AXI-Stream, AXI4-Lite以及AXI4-Full三种总线协议的信号解析实现。以Master端的AXI-Stream接口为例,其信号解析代码如下:

(*always_ready, always_enabled*)
interface RawAxiStreamMaster#(numeric type dataWidth, numeric type usrWidth);(* result = "tvalid" *) method Bool tValid;(* result = "tdata"  *) method Bit#(dataWidth) tData;(* result = "tkeep"  *) method Bit#(keepWidth) tKeep;(* result = "tlast"  *) method Bool tLast;(* result = "tuser"  *) method Bit#(usrWidth) tUser;(* always_enabled, prefix = "" *) method Action tReady((* port="tready" *) Bool ready);
endinterfacemodule mkPipeOutToRawAxiStreamMaster#(PipeOut#(AxiStream#(dataWidth, usrWidth)) pipe
)(RawAxiStreamMaster#(dataWidth, usrWidth));let rawBus <- mkPipeOutToRawBusMaster(pipe);return convertRawBusToRawAxiStreamMaster(rawBus);interface RawAxiStreamMaster;method Bool tValid = rawBus.valid;method Bit#(dataWidth) tData = rawBus.data.tData;method Bit#(keepWidth) tKeep = rawBus.data.tKeep;method Bool tLast = rawBus.data.tLast;method Bit#(usrWidth) tUser = rawBus.data.tUser;method Action tReady(Bool rdy);rawBus.ready(rdy);endmethodendinterface
endmodule

除了使用blue-wrapper中提供的三种常用总线接口的转换模块外,用户也可以仿照上述代码为自定义的接口实现对应的转换模块,具体的实现步骤如下:

  • 首先,需要实现自定义Verilog接口对应的BSV接口。其中,每个输出信号都需要独立定义成一个method,每个输入信号都需定义成Action方法的一个输入参数;
  • 使用使用上文的介绍的握手控制信号转换模块将Get/PutPipeOut/PipeIn转换成RawBusMaster/RawBusSlave;
  • 在得到RawBusMaster/RawBusSlave后将结构体中的字段和对应的method相连。

05、总结

对于BSV生成的硬件代码,其接口通常是基于en-rdy控制信号进行交互,而使用Verilog设计时,我们通常采用valid-ready信号对实现模块之间的交互。由于控制信号上的差异,将BSV生成的代码和Verilog设计进行交互通常需要额外的转换模块。针对该问题,blue-wrapper项目为BSV代码实现了相应的封装模块,使得封装后生成的Verilog代码能够直接和外部的Verilog代码进行交互。本文主要介绍了blue-wrapper背后的实现原理,具体包括: 定义PipeOut/PipeIn接口以提取出rdy信号;两种不同的握手控制信号转换的思路;以及解析struct结构体为每个字段生成独立的信号等三部分内容。

06、相关链接

Flute:

https://github.com/bluespec/Flute/tree/master/src_Testbench/Fabrics/AXI4_Lite

Blue-AXI:

https://github.com/esa-tu-darmstadt/BlueAXI

bsc-contrib: 

https://github.com/B-Lang-org/bsc-contrib/tree/main

欢迎大家关注和支持blue-crc项目,GitHub仓库地址:

https://github.com/datenlord/blue-crc

07、往期推荐

基于BSV的高性能并行CRC硬件电路生成器

达坦科技(DatenLord)专注下一代云计算——“天空计算”的基础设施技术,致力于拓宽云计算的边界。达坦科技打造的新一代开源跨云存储平台DatenLord,通过软硬件深度融合的方式打通云间壁垒,实现数据高效跨云访问,建立海量异地、异构数据的统一存储访问机制,为云上应用提供高性能安全存储支持。以满足不同行业客户对海量数据跨云、跨数据中心高性能访问的需求。

公众号:达坦科技DatenLord

DatenLord官网

https://datenlord.github.io/zh-cn/

知乎账号:

达坦科技DatenLord - 知乎

B站

https://space.bilibili.com/2017027518

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

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

相关文章

【JavaEE】HTML

JavaWeb HTML 超文本标记语言 超文本&#xff1a;文本、声音、图片、视频、表格、连接标记&#xff1a;有许许多多的标签组成 vscode开发工具搭建 因为我使用的IDEA是社区版&#xff0c;代码高亮补全缩进都有些问题&#xff0c;使用vscode是最好的选择~ 安装 Visual Stu…

聊聊并发编程——并发容器和阻塞队列

目录 一.ConcurrentHashMap 1.为什么要使用ConcurrentHashMap&#xff1f; 2.ConcurrentHashMap的类图 3.ConcurrentHashMap的结构图 二.阻塞队列 Java中的7个阻塞队列 ArrayBlockingQueue&#xff1a;一个由数组结构组成的有界阻塞队列。 LinkedBlockingQueue&#xf…

FPGA 图像缩放 千兆网 UDP 网络视频传输,基于RTL8211 PHY实现,提供工程和QT上位机源码加技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐UDP视频传输--无缩放FPGA图像缩放方案我这里已有的以太网方案 3、设计思路框架视频源选择ADV7611 解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 UDP协议栈UDP视频数据组包U…

Flink中的状态一致性

1.概念 一致性其实就是结果的正确性。对于分布式系统而言&#xff0c;从不同节点读取时总能得到相同的值&#xff1b;而对于事务而言&#xff0c;是要求提交更新操作后&#xff0c;能够读取到新的数据。 有状态的流处理&#xff0c;内部每个算子任务都可以有自己的状态。对于流…

Source Insight 工具栏图标功能介绍

这篇文章并不介绍 Source Insight 的具体使用方法&#xff0c;这类教程网上有很多&#xff0c;这里只分析 Souce Insight 工具栏图标的功能。 文章目录 Source Insight 简介Souce Insight 工具栏文件操作新建&#xff08;CtrlN&#xff09;打开&#xff08;CtrlO&#xff09;保…

Java 实现遍历一个文件夹,文件夹有100万数据,获取到修改时间在2天之内的数据

目录 1 需求2 实现1&#xff08;第一种方法&#xff09;2 实现2 &#xff08;推荐使用这个&#xff0c;快&#xff09;3 实现3&#xff08;推荐&#xff09; 1 需求 现在有一个文件夹&#xff0c;里面会一直存数据&#xff0c;动态的存数据&#xff0c;之后可能会达到100万&am…

【PyTorch实战演练】使用Cifar10数据集训练LeNet5网络并实现图像分类(附代码)

文章目录 0. 前言1. Cifar10数据集1.1 Cifar10数据集下载1.2 Cifar10数据集解析 2. LeNet5网络2.1 LeNet5的网络结构2.2 基于PyTorch的LeNet5网络编码 3. LeNet5网络训练及输出验证3.1 LeNet5网络训练3.2 LeNet5网络验证 4. 完整代码4.1 训练代码4.1 验证代码 0. 前言 按照国际…

紫光同创FPGA图像视频采集系统,基于OV7725实现,提供工程源码和技术支持

目录 1、前言免责声明 2、设计思路框架视频源选择OV7725摄像头配置及采集动态彩条HDMA图像缓存输入输出视频HDMA缓冲FIFOHDMA控制模块HDMI输出 3、PDS工程详解4、上板调试验证并演示准备工作静态演示动态演示 5、福利&#xff1a;工程源码获取 紫光同创FPGA图像视频采集系统&am…

mysql面试题7:MySQL事务原理是什么?MySQL事务的隔离级别有哪些?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:MySQL事务原理是什么? MySQL事务的原理是基于ACID(原子性、一致性、隔离性、持久性)特性来实现的,具体原理如下: Atomicity(原子性):事务…

给奶牛做直播之三

​一、前言 上一篇给牛奶做直播之二 主要讲用RTMP搭建点播服务器&#xff0c;整了半天直播还没上场&#xff0c;今天不讲太多理论的玩意&#xff0c;奶牛今天放假了也不出场&#xff0c;就由本人亲自上场来个直播首秀&#xff0c;见下图&#xff0c;如果有兴趣的话&#xff0…

YOLOV8-DET转ONNX和RKNN

目录 1. 前言 2.环境配置 (1) RK3588开发板Python环境 (2) PC转onnx和rknn的环境 3.PT模型转onnx 4. ONNX模型转RKNN 6.测试结果 1. 前言 yolov8就不介绍了&#xff0c;详细的请见YOLOV8详细对比&#xff0c;本文章注重实际的使用&#xff0c;从拿到yolov8的pt检测模型&…

施耐德电气:勾勒未来工业愿景,赋能中国市场

9月19日&#xff0c;第23届中国国际工业博览会&#xff08;简称“工博会”&#xff09;在上海隆重召开。作为全球能源管理和自动化领域的数字化转型专家&#xff0c;施耐德电气在工博会现场全方位展现了自身对未来工业的全新视野与深刻见解&#xff0c;不仅展示了其贯通企业设计…

字节一面:深拷贝浅拷贝的区别?如何实现一个深拷贝?

前言 最近博主在字节面试中遇到这样一个面试题&#xff0c;这个问题也是前端面试的高频问题&#xff0c;我们经常需要对后端返回的数据进行处理才能渲染到页面上&#xff0c;一般我们会讲数据进行拷贝&#xff0c;在副本对象里进行处理&#xff0c;以免玷污原始数据&#xff0c…

arduino - UNO-R3,mega2560-R3,NUCLEO-H723ZG的arduino引脚定义区别

文章目录 arduino - UNO-R3,mega2560-R3,NUCLEO-H723ZG的引脚定义区别概述笔记NUCLEO-H723ZGmega2560-R3UNO-R3经过比对, 这2个板子(NUCLEO-H723ZG, mega2560-R3)都是和UNO-R3的arduino引脚定义一样的.mega2560-r3和NUCLEO-H723ZG的区别补充arduino uno r3的纯数字IO和模拟IO作…

uniapp iOS离线打包——原生工程配置

uniapp iOS离线打包&#xff0c;如何配置项目工程&#xff1f; 文章目录 uniapp iOS离线打包&#xff0c;如何配置项目工程&#xff1f;工程配置效果图DebugRelease 配置工程配置 Appkey应用图标模块及三方SDK配置未配置模块错误配置模块TIP: App iOS 离线打包 前提&#xff1a…

Linux服务器安装Anaconda 配置远程jupyter lab使用虚拟环境

参考的博客&#xff1a; Linux服务器安装Anaconda 并配置远程jupyter lab anaconda配置远程访问jupyter&#xff0c;并创建虚拟环境 理解和创建&#xff1a;Anaconda、Jupyterlab、虚拟环境、Kernel 下边是正文了。 https://www.anaconda.com/download是官网网址&#xff0c;可…

华为云云耀云服务器L实例评测|云耀云服务器L实例部署Linux管理面板mdserver-web

华为云云耀云服务器L实例评测&#xff5c;云耀云服务器L实例部署Linux管理面板mdserver-webl 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点 二、mdserver-web介绍2.1 mdserver-web简介2.2 mdserver-web特点2.3 主要插件介绍 三、本次实践介绍…

机器学习之单层神经网络的训练:增量规则(Delta Rule)

文章目录 权重的调整单层神经网络使用delta规则的训练过程 神经网络以权值的形式存储信息,根据给定的信息来修改权值的系统方法称为学习规则。由于训练是神经网络系统地存储信息的唯一途径&#xff0c;因此学习规则是神经网络研究中的一个重要组成部分 权重的调整 &#xff08…

iPhone数据丢失怎么办?9 佳免费 iPhone 数据恢复软件可收藏

您是否知道有多种原因可能导致 iPhone 上存储的数据永久丢失&#xff1f;然而&#xff0c;使用一些最好的免费 iPhone 数据恢复软件&#xff0c;您仍然可以恢复它。 由于我们几乎总是保存手机上的所有内容&#xff08;从联系人到媒体文件&#xff09;&#xff0c;因此 iPhone …

CDH 6.3.2升级Flink到1.17.1版本

CDH&#xff1a;6.3.2 原来的Flink&#xff1a;1.12 要升级的Flink&#xff1a;1.17.1 操作系统&#xff1a;CentOS Linux 7 一、Flink1.17编译 build.sh文件&#xff1a; #!/bin/bash set -x set -e set -vFLINK_URLsed /^FLINK_URL/!d;s/.*// flink-parcel.properties FLI…