【Linux102】45-kernel/blk_drv/ramdisk.c


公粽号「专注Linux」,专注Linux内核开发

Linux102系列会详细讲解Linux0.11版本中的102个文件,本文讲解linux0.11的第45个文件【Linux102】45-kernel/blk_drv/ramdisk.c的文件源码。

1. ramdisk.c的主要作用

这是内存虚拟盘驱动程序,由 Theodore Ts’o 编制。
其含义为:

若在 linux/Makefile 文件中指定了 RAMDISK,则表示在引导启动盘上从第 256 磁盘块开始处会存放着根文件系统映像文件。

初始化时系统会在内存中划出一部分供虚拟盘操作使用,其大小由 RAMDISK 指定(千字节)。在进行正常的根文件系统加载之前,系统会执行 rd_load() 函数,试图从磁盘的第 257 块中读取根文件系统超级块。若成功,就把该根文件映像文件读到内存虚拟盘中,并把根文件系统设备标志 ROOT_DEV 设置为虚拟盘设备0x0101),否则退出 rd_load()·,系统继续从 别的设备上执行根文件加载操作。


2.源码用到的文件


文件名 作用
😉【Linux102】20-include/linux/kernel.h 本程序主要定义了内核中最常用的一些基础函数声明,是内核运行最基本保障,比如malloc、printk、free、tyy_write、panic等函数声明,这些函数具体的实现则分布在各个.c文件中。
😉【Linux102】21-include/asm/segment.h 本程序定义了一系列用于在 Linux 内核中访问用户空间内存内联函数,主要通过内嵌汇编操作段寄存器fs来实现内核与用户空间的数据交互。
😉【Linux102】24-include/linux/fs.h 这个文件(fs.h)是操作系统内核中文件系统模块的核心头文件,它的主要作用是定义文件系统实现所需的数据结构、常量、宏和函数接口,为整个文件系统的运作提供基础框架。
😉【Linux102】36-include/asm/system.h 该文件中定义了设置或修改描述符/中断门等嵌入式汇编宏。其中,函数 move_to_user_mode() 用于内核在初始化结束时 “切换”到初始进程(任务0)。所使用的方法是模拟中断调用返回过程,即利用指令iret运行初始任务0。
😉【Linux102】42-include/linux/config.h config.h 是一个配置文件,用于设置键盘布局和硬盘参数(备用)。设计目的:提供可配置的选项,适配不同的硬件环境。
😉【Linux102】40-kernel/blk_drv/blk.h 这是有关硬盘块设备参数的头文件,因为只用于块设备,所以与块设备代码放在同一个地方。其中主要定义了请求等待队列的数据结构request,用宏语句定义了电梯搜索算法,并对内核目前支持的虚拟盘硬盘软盘三种块设备,根据它们各自的主设备号分别设定了常数值。
😉【Linux102】47-include/string.h 声明了一系列标准的字符串操作函数和内存块操作函数。
😉【Linux102】46-include/asm/memory.h 基本功能: memcpy用于将一段连续内存(源地址src)中的n个字节,复制到另一段连续内存(目标地址dest)中,返回目标地址dest。

使用场景: 适用于需要高效复制内存数据的场景,例如数据缓冲区拷贝结构体复制内存块迁移等。但需注意:源地址和目标地址不能重叠(·重叠内存需用memmove)。

3.源码版

/*
 *  linux/kernel/blk_drv/ramdisk.c
 *
 *  Written by Theodore Ts'o, 12/2/91
 */

#include <string.h>

#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/memory.h>

#define MAJOR_NR 1
#include "blk.h"

char *rd_start;
int rd_length = 0;

void do_rd_request(void)
{
   
   
    int len;
    char *addr;

    INIT_REQUEST;
    addr = rd_start + (CURRENT->sector << 9);
    len = CURRENT->nr_sectors << 9;
    if ((MINOR(CURRENT->dev) != 1) || (addr + len > rd_start + rd_length))
    {
   
   
        end_request(0);
        goto repeat;
    }
    if (CURRENT->cmd == WRITE)
    {
   
   
        (void)memcpy(addr,
                     CURRENT->buffer,
                     len);
    }
    else if (CURRENT->cmd == READ)
    {
   
   
        (void)memcpy(CURRENT->buffer,
                     addr,
                     len);
    }
    else
        panic("unknown ramdisk-command");
    end_request(1);
    goto repeat;
我正在编辑【verilog】代码,遇到了 【DRC MDRV-11 Multiple Driver Nets: Net «consto> has multiple drivers: inst1 _wr_tinst1 _rt write_bram/U0/inst_blk_mem_gen/gnbram.gnativebmg.native_blk_mem_gen/valid. cstr/ramloop[1].ram.riprim noinit ram/DEVICE_ 7SERIES NO _BMM _INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOADO(0]. inst1 _wr_It/inst1_t write bram/U0/inst blk_mem gen/gnbram.gnativebmg.native_ blk_mem _genvalid.cstr/ramloop{O].ram.r/prim_noinit ram/DEVICE 7SERIES.NO_EMM _INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOADO(11 inst1_wr_inst1_It write_bram/U0/inst blk_mem gen/gnbram.gnativebmg.native_blk mem gen/valid. cstr/ramloop[1].ram.r/prim _noinit ram/DEVICE_/SERIES NO_EMM _INFO.TRUE_DP. SIMPLE_PRIM36.ram/DOADO/1. inst1 _wr_Itinst1_it write bram/U0/inst blk _mem gen/gnbram.gnativebmg.native_ bIk_mem_genvalid.cstr/ramloopfO].ram.r/prim_noinit.ram/DEVICE_/SERIES.NO_EMM_INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOADO(2). inst1 _wr_It/inst1 rt write bram/U0/inst blk_mem _gen/gnbram.gnativebmg.native_ bik_mem genvalid.cstr/ramloop[1].ram.r/prim _noinit ram/DEVICE_7SERIESNO_EMM INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOADOIZI. inst1_wr_rinst1_t write_bram/U0/inst _blk_mem gen/gnbram.gnativebmg.native_blk _mem gen~valid.cstr/ramloop[OJ.ram.r/prim_noinit.ram/DEVICE_7SERIES.NO BMM _INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOAD0(3). inst1_wr_inst1_It write_ bram/U0/inst_blk_mem_gen/gnbram.gnativebmg.native_blk_mem_gen/valid.cstr/ramloop[1].ram.r/prim_noinitram/DEVICE_7SERIES.NO_BMM_INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOADO(3). inst1 _wr_inst1 it write_bram/U0/inst_blk_mem gen/gnbram.gnativebmg.native _blk_mem genvalid. cstr/ramloop{O].ram.r/prim_.noinitram/DEVICE_ 7SERIES.NO_BMM INFO.TRUE_DP.SIMPLE_ PRIM36.ram/DOADO(47. inst1 _wr_inst1_rt write bram/U0/inst bik_mem gen/gnbram.gnativebmg.native_blk_mem genvalid cstr/ramloopf1). ram.r/prim noinit.ram/DEVICE 7SERIES.NO_ EMM INFO.TRUE DP.SIMPLE PRIM36.ramDOADOHI inst1 wr_Itinst1 it write bram/U0/inst_blk_mem_gen/gnbram.gnativebmg.native_blk_mem_genvalid.cstr/ramloop/Oj.ram.r/prim_noinitram/DEVICE_7SERIES.NO_EMM_INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOAD0(5]. inst1 _wr Minst1 It write _bram/UO/inst_blk_mem_gen/gnbram.gnativebmg.native_bIk_memgenvalid.cstriramloop/1].ram.r/prim_noinitram/DEVICE_7SERIESNO_EMM_INFO.TRUE_DP.SIMPLE_PRIM36.ram/DOAD0(5]. An-tM NrHhnEtA Rrita hramnininat Hiklmam noninnhram anativ/ahma native hik mam nontalid retriramionnihtram rinrim InninitraminEVInE 7CERIECNA RUM INEA TRIIE} ,请帮我检查并改正错误点。我的原始代码如下
03-28
<think>好的,我现在需要帮助用户解决Verilog代码中的DRC MDRV-11错误,也就是多个驱动器驱动同一个网络的问题。首先,我需要理解用户提供的错误信息。从错误信息来看,多个实例驱动了同一个网络“consto”,具体涉及到不同的ramloop索引,比如ramloop[0]、ramloop[1]等,以及不同的DOADO端口位,如DOADO(0)、DOADO(1)等。 接下来,我需要分析用户提供的原始代码,但用户可能还没有给出代码。不过,根据常见的Verilog设计错误,这种情况通常发生在多个驱动程序同时写入同一个信号或存储器端口。特别是在使用双端口块存储器(True Dual Port RAM)时,如果两个端口同时写入同一个地址,可能会导致多驱动问题。 首先,我应该检查是否在代码的不同部分错误地实例化了多个块存储器(Block RAM)并连接到同一个输出信号。例如,可能在不同的always块或模块实例中,多个驱动器被连接到同一个输出端口,导致冲突。 另一个可能的原因是地址生成逻辑有问题。如果两个端口的地址信号在某种情况下重叠,导致同一时间两个端口都试图写入同一个存储位置,这也会触发多驱动错误。需要检查地址生成逻辑,确保两个端口的地址不会同时指向同一个位置。 此外,还要检查是否在组合逻辑中错误地赋值了同一个信号,比如在多个always块中对同一个寄存器变量进行赋值,或者在实例化模块时多次连接到同一个输出网络。 如果用户使用的是Xilinx的Block Memory Generator,需要确认配置是否正确,特别是是否设置为True Dual Port模式,并且每个端口有独立的控制信号。同时,检查是否有意外的端口连接,例如将两个端口的写使能同时激活,并且地址相同。 可能的解决步骤包括: 1. 检查所有实例化的存储器模块,确保每个输出信号只有一个驱动器。 2. 确认地址生成逻辑,避免两个端口同时写入同一地址。 3. 检查写使能信号,确保不会同时激活多个写操作到同一位置。 4. 如果使用多个块存储器实例,确保它们的输出通过适当的逻辑(如多路复用器)进行选择,而不是直接连接到同一网络。 最后,建议用户分享相关代码片段,特别是涉及块存储器实例化和连接的部分,以便更具体地定位问题并提供修正建议。</think>根据您提供的错误信息,这是一个典型的Verilog多驱动问题(Multiple Driver Nets)。以下是逐步分析和解决方案: ============================ 【问题定位】 1. 错误类型:DRC MDRV-11 2. 错误网络:`consto` 3. 根本原因:同一个信号被多个驱动源同时驱动 4. 关键线索:错误路径中反复出现`ramloop[0]/ramloop[1]`和`DOADO`端口,表明与双端口块存储器的连接冲突有关 ============================ 【常见错误场景】 1. 多实例冲突: - 不同存储器实例的`DOADO`输出直接连接到同一网络 - 例如同时使用`ramloop[0]`和`ramloop[1]`的输出到同一信号 2. 控制信号错误: ```verilog // 错误示例:两个always块驱动同一信号 always @(posedge clk) begin if (wea) dout <= ram[addr]; end always @(posedge clk) begin if (web) dout <= ram[addr]; // 冲突! end ``` 3. 存储器配置错误: - 使用Xilinx Block Memory Generator时: - ▢ True Dual Port模式未正确配置独立端口 - ▢ 两个端口的输出缓冲区未隔离 ============================ 【解决方案】 1. 隔离输出端口: ```verilog // 正确示例:使用独立输出寄存器 reg [31:0] dout_a, dout_b; always @(posedge clk) begin if (wea) dout_a <= ram[addra]; if (web) dout_b <= ram[addrb]; // 独立寄存器 end assign final_out = sel ? dout_a : dout_b; // 添加选择逻辑 ``` 2. 检查存储器实例化: ```verilog // 确保每个实例有独立输出 blk_mem_gen_0 ram0 ( .clka(clk), .addra(addra), .douta(dout0), // 独立输出信号 //... ); blk_mem_gen_1 ram1 ( .clka(clk), .addra(addra), .douta(dout1), // 独立输出信号 //... ); ``` 3. 关键配置检查: - 在Vivado Block Memory Generator中: - ✓ Port A Options → Enable Port A Output Registers - ✓ Port B Options → Enable Port B Output Registers - ✓ 勾选"Use Output Register"选项 ============================ 【验证步骤】 1. 运行`report_drc -ruledeck {MDRV-11}` 2. 使用网表查看器定位`consto`网络: - 右键选择"Mark Debug" - 在ILA中添加调试探针 3. 检查综合后的网表: - 确认每个DOADO端口只连接到一个负载 - 验证地址生成逻辑无重叠 建议提供具体涉及存储器读写的代码片段,我可以进一步帮助检查信号连接关系。该错误通常需要通过输出缓冲寄存器和地址隔离机制来解决。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值