Zynq MPSoC / RFSoC 动态配置 DIMM DDR

news2024/11/25 12:42:37

目录

  • 名词释义
  • 硬软件版本
  • Zynq MPSoC / RFSoC 动态 DDR 配置简介
  • 具体操作方法
    • PCW GUI 配置
    • 启用动态 DDR 配置功能
    • I2C 硬件要求
    • 根据硬件修改 FSBL
      • 初始化 I2C 控制器
      • 选择 I2C Mux 的 Slave
      • 读取 EEPROM 的第一页
      • 读取 EEPROM 的第二页
  • 调试
  • 参考文档

本文首发于 Josh Gao 的博客:https://josh-gao.top/posts/11cd1dc.html

对于 DIMM 拓扑的 DDR,通常可以使用 I2C 对搭载在 DIMM 上的 SPD EEPROM 进行读取后获得配置参数,然后对 DDR 控制器进行配置。

AMD Xilinx UG1085 的 Dynamic DDR Configuration 一节指出,当 DDR 控制器处于复位状态时,可以在运行时通过 FSBL 获取 DDR 参数并对 DDR 控制器进行初始化。

本文基于 Zynq RFSoC,对 PS 端的 SO-DIMM DDR 进行动态配置。

名词释义

  • BSP:Board Support Package,板级支持包
  • EEPROM:Electrically-Erasable Programmable Read-Only Memory,电子擦除式可复写只读存储器
  • FSBL:First Stage Bootloader,第一阶段引导加载程序
  • DDR DRAM:Double Data Rate Synchronous Dynamic Random-Access Memory,双倍数据率同步动态随机存取存储器
  • DIMM:Dual In-line Memory Modules,双列直插式存储模块
  • PCW:Processing System Configuration Wizard,处理系统配置向导
  • SO-DIMM:Small Outline Dual In-line Memory Modules,小外形双列直插式内存模块
  • SPD:Serial Presence Detect,串行存在检测

硬软件版本

硬软件型号/版本
FPGAZynq RFSoC XCZU48DR-2-FSVG1517-I
DDR4Micron MTA4ATF51264HZ-2G6E1
I2C MuxTI TCA9548APWR
Vivado2024.1
Vitis Classic2024.1

Zynq MPSoC / RFSoC 动态 DDR 配置简介

Zynq MPSoC / RFSoC 动态 DDR 配置具有如下特性:

  • 无需在 Vivado 中进行改动即可更换 DIMM,并使用动态 DDR 配置初始化 DDR;
  • 支持 DDR3 和 DDR4 DIMM;
  • 单一的 PetaLinux BSP 即可支持任何可安装的 DIMM 器件。

:动态 DDR 配置功能仅可用于 PS DIMM DDR,不支持颗粒 DDR。

具体操作方法

PCW GUI 配置

在使用动态 DDR 配置之前,需要在如图 1 的 Vivado 的 PCW GUI 中启用 DDR 控制器,且将“DDR Controller Options”部分设置为:

  • Memory Type:DDR4 或 DDR3
  • Components:UDIMM 或 RDIMM
  • ECC:Enabled 或 Disabled
  • Effective DRAM Bus Width:64 Bit

图 1. Zynq UltraScale+ MPSoC 配置 GUI

动态 DDR 配置将自动读取 SPD 表,并设置“DDR Memory Option”部分的所有参数,如下表。

OptionValue ExampleOptionValue Example
Speed Bin (Use Tooltip)DDR42133PDRAM IC Bus Width (per die)8 Bits
Cas Latency15DRAM Device Capacity(per die)4096 MBits
RAS to CAS Delay (Cycles)15Bank Group Address Count (Bits)2
Pre-charge Time (Cycles)15Bank Address Count (Bits)2
Cas Write Latency (Cycles)14Row Address Count (Bits)15
tRC (ns)46.5Column Address Count10
tRASmin (ns)33Dual Rank
tFAW (ns)21DDR Size (in hexa)0XFFFFFFFF (4GB)
Additive Latency (Cycles)0

而“Other Options”部分的所有值都需要用户根据需要设置,无法从 SPD 表中获得,如下表。

OptionValue ExampleOptionValue Example
Memory Address MapROW BANK COLPower Mode SettingsPower Down Enable
Data Mask and DBIDM NO DBIClock Stop
Address MirroringRefresh Mode Settings
2nd ClockLower-Power Auto Self-RefreshManual Normal
ParityTemp Controlled Refresh
2Tck Command Timing (2T)Max. Operating TemperatureNormal (0-85)
Fine Granularity Refresh Mode1x
Self-Refresh Abort

启用动态 DDR 配置功能

要启用动态 DDR 配置功能,需要在 Vivado 中使用 TCL 命令将参数 CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN 置为 1:

set_property CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN 1 [get_bd_cells /zynq_ultra_ps_e]

这里的 zynq_ultra_ps_e 需要替换为实际 Block Design 中 Zynq UltraScale+ MPSoC IP 核的名称,如图 2。

图 2. Block Design 整体

然后重新生成 Output Products 即可(若除 PS 处理器外还有其他逻辑,则需要重新生成比特流)。FSBL 将会在启动过程中使用该参数,并执行动态 DDR 配置。

如果设置了上述参数却出现了如下警告,是因为 GUI 中 DDR 类型必须为 UDIMM 或 RDIMM,不能为 Component。

WARNING: [BD 41-721] Attempt to set value '1' on disabled parameter 'PSU_DYNAMIC_DDR_CONFIG_EN' of cell '/zynq_ultra_ps_e_0' > is ignored

I2C 硬件要求

由于动态 DDR 配置需要在 FSBL 中使用 I2C 读取 DDR SPD EEPROM 中的数据,而在 Xilinx 自动生成 FSBL 中,I2C 读取 DDR SPD EEPROM 的方式是固定的,因此若不想对生成的 FSBL 进行修改,则需要在硬件上适配 FSBL

Xilinx FSBL 使用 I2C1(1 号 I2C 控制器),借助一个 I2C Mux 与 SPD EEPROM 进行通信,使用的地址为:

  • I2C Mux 地址: 0x75
  • I2C Slave 地址: 0b1010001 (0x51)
  • SODIMM SA[2:0]: 0b001

从 Vivado 2019.1 开始,动态 DDR 配置对于所有使用 DIMM DDR 的 Zynq MPSoC / RFSoC 评估板均启用,在使用预置硬件配置时无需额外用户操作。

根据硬件修改 FSBL

若 I2C 硬件连接不满足上述要求,还可以按照实际连接关系修改 FSBL。FSBL 中使用 I2C 读取 DDR SPD EEPROM 的函数为 u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)

u32 XFsbl_DdrInit(void)
{
  // ...
  /* Get the Model Part Number from the SPD stored in EEPROM */
  Status = XFsbl_IicReadSpdEeprom(SpdData);
  if (Status != XFSBL_SUCCESS) {
    Status = XFSBL_FAILURE;
    goto END;
  }
  // ...
}

下面对函数进行拆解,结合注释可以更好理解操作的过程。

初始化 I2C 控制器

首先对 I2C 控制器 I2C1 进行初始化。值得一提的是,从 Vivado / Vitis 2023.2 版本开始,对设备进行寻址时,不再依赖于设备的 Device ID,而是直接使用基地址 Base Address,少了从 Device ID 到 Base Address 这一步操作,从开发的角度来看更为合理了。

若设计使用了 I2C 控制器 I2C0,则可以改为使用基地址 XPAR_I2C0_BASEADDR 或 Device ID XPAR_PSU_I2C_0_DEVICE_ID 来寻找设备。

static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
  // ...
  /* Lookup for I2C-1U device */
#ifdef SDT
  ConfigIic = XIicPs_LookupConfig(XPAR_I2C1_BASEADDR);
#else
  ConfigIic = XIicPs_LookupConfig(XPAR_PSU_I2C_1_DEVICE_ID);
#endif
  if (!ConfigIic) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /* Initialize the I2C device */
  Status = XIicPs_CfgInitialize(&IicInstance, ConfigIic,
      ConfigIic->BaseAddress);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /* Set the Serial Clock for I2C */
  Status = XIicPs_SetSClk(&IicInstance, XFSBL_IIC_SCLK_RATE);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }
  // ...
}

选择 I2C Mux 的 Slave

由于开发板搭载了较多 I2C 外设,而 Zynq MPSoC / RFSoC 的 I2C 控制器数量有限,因此需要通过 I2C Mux 来扩展所连 I2C Slave 的数量。

本板卡 I2C1 原理图如图 3,所用 I2C Mux 的型号为 TCA9548A,其地址配置方式如图 4,Slave 选择方式如图 5,这里均和评估板保持一致,因此可以与自动生成的 FSBL 兼容。

结合图 3 和图 4 可知 I2C Mux 的地址为 0x75,从图 3 中可知 PS DDR4 SODIMM 的 I2C 连接在了第 3 号 Slave 的位置,因此按照图 5 需要将 B3 置 1,也即需要向地址为 0x75 的 I2C Mux TCA9548A 的控制寄存器中写入 0x08

I2C Mux 原理图

图 4. TCA9548A 地址配置


图 5. TCA9548A Slave选择

按照上述分析,下面的代码就不难理解了,首先向地址为 XFSBL_MUX_ADDR(默认为 0x75)的 I2C Mux 写入选通配置 0x08,然后从同样的地址回读,验证配置是否正确。

  • 若设计中没有使用到 I2C Mux,而是直接将 I2C 控制器连接到了 DIMM,则可以删去这部分代码;
  • 若设计中 I2C Mux 地址不同,则可以修改 XFSBL_MUX_ADDR 的宏定义;
  • 若设计中 I2C Mux 连接的 Slave 不同,可以修改 I2C 发送的 TxArray
static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
  // ...
  /*
   * Configure I2C Mux to select DDR4 SODIMM Slave
   * 0x08U - Enable DDR4 SODIMM module
   */
  TxArray = 0x08U;
  XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U, XFSBL_MUX_ADDR);

  /*
   * Wait until bus is idle to start another transfer.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /*
   * Get Configuration to confirm the selection of the slave
   * device.
   */
  Status = XIicPs_MasterRecvPolled(&IicInstance, SpdData, 1U,
      XFSBL_MUX_ADDR);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }
  /*
   * Wait until bus is idle to start another transfer.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }
  // ...
}

读取 EEPROM 的第一页

配置完 I2C Mux 后,即可开始读取 SPD EEPROM 中的内容了。图 6 给出了 EEPROM 支持的指令表,由于 EEPROM 一次读的最大长度为一页,也即一个 Page,因此需要分两次对其中的两个 Page 进行读取。


图 6. DDR4 SPD EEPROM 指令表

首先设置 Page Address 为 0,也即向地址 0x36 中写入 0x00,表示从 Page 0 中进行读取,一次读取 256 Byte。

通常 SPD EEPROM 的 Page 选择地址是固定的,如果 Page Address 0 的地址有变更,修改 XFSBL_SODIMM_CONTROL_ADDR_LOW 的宏定义即可。

static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
  // ...
  /*
   * Set SODIMM control address to enable access to lower
   * EEPROM page (0U to 255U Bytes).
   * 0x00U - Enable Read of Lower Page from EEPROM
   */
  TxArray = 0x00U;
  XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
      XFSBL_SODIMM_CONTROL_ADDR_LOW);
  /*
   * Wait until bus is idle to start another transfer.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /*
   * Configure SODIMM Slave address to select starting address of the
   * read bytes.
   * 0x00U - Set starting byte address of read Lowe Page from EEPROM
   * This will result in to starting address of 0x149U (0x100U + 0x49U) in
   * the EEPROM.
   */
  TxArray = 0x00U;
  XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
      XFSBL_SODIMM_SLAVE_ADDR);
  /*
   * Wait until bus is idle to start another transfer.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /*
   * Receive the Data of 256U Bytes from SPD EEPROM via I2C.
   */
  Status = XIicPs_MasterRecvPolled(&IicInstance, SpdData, 256U,
      XFSBL_SODIMM_SLAVE_ADDR);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /*
   * Wait until bus is idle.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }
  // ...
}

读取 EEPROM 的第二页

然后设置 Page Address 为 1,也即向地址 0x37 中写入 0x00,表示从 Page 0 中进行读取,一次读取 256 Byte。

通常 SPD EEPROM 的 Page 选择地址是固定的,如果 Page Address 1 的地址有变更,修改 XFSBL_SODIMM_CONTROL_ADDR_HIGH 的宏定义即可。

static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
  // ...
  /*
   * Set SODIMM control address to enable access to upper
   * EEPROM page (256U to 511U Bytes).
   * 0x01U - Enable Read of Upper Page from EEPROM
   */
  TxArray = 0x01U;
  XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
      XFSBL_SODIMM_CONTROL_ADDR_HIGH);
  /*
   * Wait until bus is idle to start another transfer.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /*
   * Configure SODIMM Slave address to select starting address of the
   * read bytes.
   * 0x00U - Set starting byte address of read Upper Page from EEPROM
   * This will result in to starting address of 0x149U (0x100U + 0x49U) in
   * the EEPROM.
   */
  TxArray = 0x00U;
  XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
      XFSBL_SODIMM_SLAVE_ADDR);
  /*
   * Wait until bus is idle to start another transfer.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /*
   * Receive the Data of 256U Bytes from SPD EEPROM via I2C.
   */
  Status = XIicPs_MasterRecvPolled(&IicInstance, &SpdData[256U], 256U,
      XFSBL_SODIMM_SLAVE_ADDR);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }

  /*
   * Wait until bus is idle.
   */
  Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
      XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
  if (Status != XST_SUCCESS) {
    UStatus = XFSBL_FAILURE;
    goto END;
  }
  // ...
}

调试

配置完成后可以实测了,这里对 FSBL 进行 Debug,观察整个读写的过程。在单独调试 FSBL 的时候,可以不勾选“Program FPGA”和“Initialize using FSBL”,如图 7。


图 7. Debug 配置

将断点设置在函数 XFsbl_IicReadSpdEeprom() 被调用的地方。


图 8.  函数断点

观察 I2C Mux 回读的数据。回读的数据存储在 SpdData 数组中,可以观察到数组的第 0 个字节为 0x08,与写入的数据一致。


图 9. I2C Mux 回读

然后观察 I2C EEPROM 回读的数据,并与 Micron 给出的 MTA4ATF51264HZ-2G6E1 的 SPD 数据进行对比,可以观察到数据是一致的。


图 10. I2C EEPROM 回读

最后,XFsbl_DdrInit() 函数的剩余部分会完成 DDR 参数的解析与 DDR 控制器的初始化。

参考文档

75768 - Zynq MPSoC Dynamic DDR Configuration Support for DIMM Devices

SPD I2c Address for DDR4 SODIMM

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

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

相关文章

自动化测试小技巧之Airtest-Selenium和Excel的无缝协作

一、前言 之前在问卷以及Q群上有同学有提出过能否将网页上的一些数据通过Airtest去导出生成一份Excel,那么我们今天一起讨论一下,我们应该如何去实现,以及当我们获取的数据类型不同的时候,获取的方式该怎么随之调整? …

实现在父盒子中点击生成子盒子并识别父盒子边界不溢出

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</…

高级运维工程师讲述银河麒麟V10SP1服务器加固删除snmp服务引起keeplived莫名连带删除引起生产事故实战

高级运维工程师讲述银河麒麟V10SP1服务器加固删除snmp服务引起keeplived莫名连带删除引起生产事故实战 一、核实操作系统信息 uname -a Linux localhost.localdomain 4.19.90-23.8.v2101.ky10.x86_64 #1 SMP Mon May 17 17:08:34 CST 2021 x86_64 x86_64 x86_64 GNU/Linuxcat…

【AMBA】APB总线的个人学习记录(一):理论知识

精通APB (Advanced Peripheral Bus) 总线设计通常意味着你不仅理解其基础概念&#xff0c;而且能够在实际的硬件设计中灵活运用APB总线&#xff0c;解决复杂问题&#xff0c;并优化设计。以下是一些关键点&#xff0c;当你掌握这些方面时&#xff0c;可以说你对APB总线设计有了…

004-GeoGebra基础篇-GeoGebra的布局

注意&#xff0c;为保证大家的GeoGebra的学习顺利从基础、中级到高级的过度&#xff0c;本教程笔记有此要求&#xff1a; 必须使用英文版GeoGebra&#xff08;虽说GeoGebra也支持汉字写算式&#xff0c;但强烈不建议&#xff0c;因为一个英文翻译过来的中文真是五花八门&#…

网店管家婆与金蝶云星空对接集成往来单位查询接口打通客户新增

网店管家婆与金蝶云星空对接集成往来单位查询接口打通客户新增 对接系统网店管家婆 目前网上管家婆已服务超十万家海内外企业级用户&#xff0c;覆盖了服装配饰、食品酒水、数码3C、美妆日护、医疗保健、母婴用品、五金工具等等行业。 对接系统&#xff1a;金蝶云星空 金蝶K/3C…

如何高效管理TikTok账号?TK矩阵防关联测评养号引流系统揭秘

TK矩阵防关联测评自养号系统是为TikTok&#xff08;TK&#xff09;平台设计的&#xff0c;旨在帮助卖家实现多账号管理、防关联以及自动化测评和养号的功能。该系统通过一系列的技术手段和创新功能&#xff0c;为跨境电商运营者提供了强大的支持。 系统核心优势 1. 全球真实环…

5000字深入讲解:企业数字化转型优先从哪个板块开始?

很多企业都知道数字化转型重要&#xff0c;但不知道应该怎样入手&#xff0c;分哪些阶段。以下引用国内领先数字化服务商 织信Informat 的数字化转型方法论材料&#xff0c;且看看他们是如何看待数字化转型的&#xff1f;数字化转型应该从哪先开始&#xff1f;如何做&#xff1…

一个好玩的 AI 产品,一起来玩儿梗

欢迎贡献你的扎心梗图&#xff1a; - 万物皆可meme介绍&#xff1a;https://hqexj12b0g.feishu.cn/wiki/space/7385353047184375810 - 任何人都可以编辑的玩梗集&#xff1a;https://hqexj12b0g.feishu.cn/wiki/

Redis-Bitmap位图及其常用命令详解

1.Redis概述 2.Bitmap Bitmap 是 Redis 中的一种数据结构&#xff0c;用于表示位图&#xff08;bit array&#xff09;。 它通常用于处理大规模数据集中每个元素的状态&#xff0c;比如用户的在线/离线状态&#xff08;每个用户对应一个位&#xff0c;表示在线&#xff08;1&a…

【课程总结】Day12:YOLO的深入了解

前言 在【课程总结】Day11&#xff08;下&#xff09;&#xff1a;YOLO的入门使用一节中&#xff0c;我们已经了解YOLO的使用方法&#xff0c;使用过程非常简单&#xff0c;训练时只需要三行代码&#xff1a;引入YOLO&#xff0c;构建模型&#xff0c;训练模型&#xff1b;预测…

分类预测 | PSO-PNN基于粒子群算法优化概率神经网络的数据分类预测(Matlab)

分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别 目录 分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.PSO-PNN基于粒子群算法优化概率神经网络的数据…

SQLite:一个极简使用教程

SQLite是一个轻量级的、文件系统基础的数据库&#xff0c;它被设计为配置简单、易于部署。SQLite数据库存储在一个单一的磁盘文件中&#xff0c;这意味着数据库的创建和维护都非常简单。 1. SQLite特点 轻量级&#xff1a;SQLite不需要一个独立的服务器进程。它是一个嵌入式SQ…

Steam夏促遇到社区打不开、社区进不去的处理措施一览

在Steam夏促中&#xff0c;绝大部分Steam游戏都会有折扣优惠&#xff0c;包括一些3A大作在夏促中也会降价售卖&#xff0c;玩家可以低价购买到自己心仪的游戏。不少玩家进入Steam社区查看游戏评价时遇到社区打不开、社区进不去的情况&#xff0c;不知道怎么解决&#xff0c;下面…

Pycharm一些问题解决办法

研究生期间遇到关于Pycharm一些问题报错以及解决办法的汇总 ModuleNotFoundError: No module named sklearn’ 安装机器学习库&#xff0c;需要注意报错的sklearn是scikit-learn缩写。 pip install scikit-learnPyCharm 导包提示 unresolved reference 描述&#xff1a;模块…

React小记(五)_Hooks入门到进阶

React 16.8 版本 类组件 和 函数组件 两种组件共存&#xff0c;到目前 React 18 版本&#xff0c;官方已经不在推荐使用类组件&#xff0c;在函数组件中 hooks 是必不可少的&#xff0c;它允许我们函数组件像类组件一样可以使用组件的状态&#xff0c;并模拟组件的生命周期等一…

新手向导:掌握Axure RP的第一步

其实很多时候&#xff0c;我们很容易把教程做得太复杂&#xff0c;让学生失去重点被复杂的理论吓到。入门基础的时候只需要先弄清楚两个核心内容&#xff0c;学起来就容易多了:一是简单了解这个软件&#xff0c;二是学习这个软件的基本操作。所以如果你问我什么是好的 Axure RP…

chrome 配置允许跨域

目录 1.Chrome跨域插件配置 1.1启动插件 1.2. 设置本地调试跨域 2 Firefox跨域插件 2.1. 安装插件 CORS Everywhere 2.2. 启动插件 3 工具下载链接 1.Chrome跨域插件配置 使用chrome插件“Allow CORS: Access-Control-Allow-origin ”来解决跨域问题。 点击pin图标&…

小语言模型SLM 百科全书

想象一下这样一个世界&#xff1a;智能助手不再驻留在云端&#xff0c;而是驻留在你的手机上&#xff0c;无缝理解你的需求并以闪电般的速度做出响应。这不是科幻小说&#xff1b;这是小型语言模型 (SLM) 的前景&#xff0c;这是一个快速发展的领域&#xff0c;有可能改变我们与…

倒装COB封装技术与常规SMD封装技术差异对比

倒装COB显示屏与常规SMD LED显示屏一个很大的差异点就是在于封装工艺的不同&#xff0c;COB&#xff08;Chip on Board&#xff09;封装和SMD&#xff08;Surface Mounted Device&#xff09;封装是LED显示屏领域中两种常见的技术&#xff0c;所表现出来的差异主要在于封装结构…