从C代码到RISC-V指令:手把手教你用交叉编译器生成测试用例

RISC-V芯片开发必备:手把手教你用riscv64-unknown-elf-gcc测试Chisel处理器 本文为RISC-V芯片开发者提供了一套完整的Chisel处理器验证方案。通过手把手教学,详细讲解了如何从源码构建riscv64-unknown-elf-gcc交叉编译工具链,并重点解决了裸机环境下的链接脚本与启动代码配置难题,最终实现将C语言程序编译为可直接加载到Chisel仿真环境的测试文件,打通了从高级语言到硬件执行的自动化验证闭环。 阅读详情

从C代码到RISC-V指令:手把手教你用交叉编译器生成测试用例

如果你正在设计自己的RISC-V处理器,无论是用于学术研究、教学实验,还是芯片公司的实际项目,一个绕不开的环节就是:如何高效地生成足够多、足够复杂的指令序列来验证你的硬件设计?手工编写十六进制机器码的日子已经过去了,那不仅效率低下,而且极易出错,难以覆盖复杂的控制流和数据交互场景。真正的工程实践,需要的是从我们熟悉的软件世界——比如C语言——直接“流淌”出精准的RISC-V指令流,灌入我们的硬件仿真或FPGA平台。

这正是交叉编译器的魔力所在。它像一座精心设计的桥梁,一端连接着x86或ARM架构的通用开发机(宿主机),另一端则瞄准了RISC-V这个目标架构。通过它,我们可以用高级语言描述测试意图,由编译器负责将其翻译、优化成目标处理器能理解的二进制语言。这个过程不仅解放了生产力,更使得测试用例的复杂度、覆盖度和可维护性得到了质的飞跃。本文就将聚焦于如何搭建并运用这套工具链,面向芯片开发工程师和体系结构学习者,展示从一行C代码开始,到生成可供你的RISC-V处理器加载执行的指令文件(如Intel HEX格式)的完整路径。我们会深入工具使用的细节,对比riscv64与riscv32架构下的编译差异,并分享一些在流程中避开常见“坑点”的实战经验。

1. 工具链基石:理解RISC-V交叉编译生态

在动手敲命令之前,有必要先厘清几个核心概念。所谓“交叉编译”,指的是在一个架构的平台上,生成能在另一个不同架构平台上运行的程序。对于我们而言,就是在常见的x86_64 Linux系统上,生成RISC-V架构的机器码。这背后依赖的是一套完整的工具链集合。

GNU工具链是这片生态中的主角,它并非一个单一工具,而是一个模块化协作的大家族。对于RISC-V,社区维护着riscv-gnu-toolchain这个官方项目。但正如许多初次尝试者所经历的,直接编译这个“全家桶”可能会因为网络、依赖或配置问题而充满挑战。一个更清晰、更可控的思路是“分而治之”,聚焦于最核心的两个组件:

  • riscv-binutils-gdb:这是二进制工具集。它包含了汇编器(as)、链接器(ld)、目标文件操作工具(objcopy, objdump)等。你可以把它理解为处理机器码“原材料”的车间。
  • riscv-gcc:这是编译器本身。它负责将C、C++等高级语言源代码,经过预处理、编译、汇编等阶段,生成目标文件(.o)。它需要调用binutils中的工具来完成最后阶段的组装。

两者的编译有明确的先后顺序:必须先成功编译并安装binutils,将其工具路径加入系统环境变量,然后再去编译gcc。因为gcc在编译过程中,会调用刚刚编好的、针对RISC-V的汇编器和链接器。

注意:除了从源码编译,对于许多快速上手或CI/CD场景,也可以考虑使用预编译好的工具链,例如SiFive提供的发布包或某些Linux发行版的包管理器。但自己编译能让你更透彻地理解组件关系,并允许你进行定制化配置(如指定目标ABI、架构扩展等)。

下表概括了工具链中的关键角色及其在测试用例生成流程中的作用:

工具名称 (示例)主要功能在流程中的产出
riscv64-unknown-elf-gccC编译器将 .c 源文件编译、汇编成 .o 目标文件
riscv64-unknown-elf-as汇编器将手写的 .S 汇编文件汇编成 .o 目标文件
riscv64-unknown-elf-ld链接器将一个或多个 .o 文件链接成可执行的 .elf 文件
riscv64-unknown-elf-objcopy目标文件格式转换将 .elf 文件转换为纯二进制的 .bin 文件
riscv64-unknown-elf-objdump反汇编与信息查看将 .elf 或 .bin 反汇编为汇编代码,查看段信息
自定义脚本或工具格式转换将 .bin 转换为仿真器或内存模型所需的 .hex 格式

2. 实战:从零构建你的RISC-V交叉编译器

理论清晰后,我们进入实战环节。以下步骤在Ubuntu 22.04 LTS上验证通过,其他Linux发行版可能需要微调包管理命令。

2.1 环境准备与依赖安装

首先,确保你的系统有足够的磁盘空间(建议至少10GB空闲)和内存。然后,通过apt安装所有必要的构建依赖。这一步至关重要,缺失的依赖会导致后续编译错误,而错误信息往往晦涩难懂,让人徒耗大量时间在错误的方向上排查。

sudo apt update
sudo apt install -y autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev \
gawk build-essential bison flex texinfo gperf libtool patchutils bc \
zlib1g-dev libexpat-dev ninja-build git

这里安装的包括:

  • 构建工具:autoconf, automake, libtool,用于生成配置脚本。
  • 编译器与基础库:gcc, g++, make, bison, flex,是编译GCC自身的前提。
  • 数学库:libmpc-dev, libmpfr-dev, libgmp-dev,GCC优化和代码生成所需。
  • 文档工具:texinfo,用于生成手册。

2.2 获取源码并编译Binutils

我们创建一个独立的工作目录,并分别获取binutils和gcc的源码。使用国内镜像可以显著提升克隆速度。

mkdir -p ~/riscv-toolchain-build
cd ~/riscv-toolchain-build

# 克隆 riscv-binutils-gdb (使用国内镜像)
git clone https://gitee.com/mirrors/riscv-binutils-gdb.git
cd riscv-binutils-gdb

接下来,我们采用“影子构建”(out-of-tree build)的方式,在单独的build目录中编译,以保持源码树的洁净。

# 创建安装目录和构建目录
sudo mkdir -p /opt/riscv
mkdir build
cd build

# 配置编译选项
../configure --prefix=/opt/riscv --target=riscv64-unknown-elf \
--disable-multilib --disable-gdb --disable-sim --disable-werror

解释一下关键配置选项:

  • --prefix=/opt/riscv:指定安装路径。/opt是存放第三方大型软件的常用位置。
  • --target=riscv64-unknown-elf:目标系统为riscv64架构,供应商unknown,运行在裸机环境(elf)。
  • --disable-multilib:禁用多库支持,简化编译。如果你需要同时支持rv32和rv64,则需要更复杂的配置。
  • --disable-gdb --disable-sim:我们不编译调试器gdb和模拟器,专注于核心工具链。

现在开始编译和安装。使用tee命令可以将编译输出同时显示在屏幕和保存到日志文件,便于后续排查问题。

# 编译,并将输出和错误都重定向到日志文件
make -j$(nproc) 2>&1 | tee build.log

# 安装到 /opt/riscv
sudo make install

安装成功后,将工具路径临时添加到当前shell的环境变量中,为下一步编译GCC做准备。

export PATH=/opt/riscv/bin:$PATH
# 验证 binutils 工具是否可用
which riscv64-unknown-elf-as
riscv64-unknown-elf-as --version

2.3 编译GCC(C编译器)

回到工作目录,获取并编译GCC。

cd ~/riscv-toolchain-build
git clone https://gitee.com/mirrors/riscv-gcc.git
cd riscv-gcc

同样创建构建目录并进行配置。注意,这里我们使用--with-newlib,这意味着我们将为裸机环境编译,使用newlib作为C标准库。对于处理器验证初期,我们通常不需要完整的Linux系统库。

mkdir build
cd build

../configure --prefix=/opt/riscv --target=riscv64-unknown-elf \
--enable-languages=c --disable-multilib --disable-shared --disable-threads \
--with-newlib --without-headers --with-system-zlib=no \
--with-arch=rv64imac --with-abi=lp64
  • --enable-languages=c:只编译C语言前端,足够生成测试用例。
  • --with-arch=rv64imac:指定目标架构为RV64IMAC,即64位基础整数指令集(I),乘法扩展(M),原子操作扩展(A)和压缩指令扩展(C)。请根据你的处理器实际支持的扩展进行调整。
  • --with-abi=lp64:指定应用二进制接口为lp64(long和pointer是64位)。

开始编译GCC,这个过程比binutils耗时更长。

make -j$(nproc) 2>&1 | tee gcc_build.log
sudo make install

编译完成后,你可以永久性地将/opt/riscv/bin加入你的~/.bashrc或~/.zshrc文件中。

echo 'export PATH=/opt/riscv/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

现在,你的交叉编译器就绪了。可以运行riscv64-unknown-elf-gcc --version来庆祝一下。

3. 生成测试用例:从C源码到可加载的指令流

工具链就位,是时候让它为我们生产测试指令了。我们以一个简单的C程序为例,演示完整的流水线。

3.1 编写测试C代码

创建一个名为test.c的文件:

// test.c
int main() {
    volatile int a = 5;
    volatile int b = 3;
    volatile int c = 0;
    c = a + b; // 产生一条加法指令
    // 一个简单的循环,产生分支指令
    for (volatile int i = 0; i < 10; i++) {
        c += i;
    }
    return c;
}

使用volatile关键字是为了防止编译器将整个计算优化掉,确保生成我们期望的算术和内存访问指令。

3.2 编译、链接与转换

步骤1:编译为ELF可执行文件

riscv64-unknown-elf-gcc -march=rv64imac -mabi=lp64 -nostdlib -T link.ld -o test.elf test.c
  • -march和-mabi:与编译工具链时指定的架构和ABI保持一致。
  • -nostdlib:不链接标准库,因为我们是在裸机环境。
  • -T link.ld:指定链接脚本。这是裸机程序的关键! 链接脚本定义了程序各段(如代码段.text、数据段.data)在内存中的布局。一个极简的link.ld示例如下:
    /* link.ld */
    OUTPUT_ARCH( "riscv" )
    ENTRY( _start )
    
    SECTIONS
    {
      . = 0x80000000; /* 定义程序加载的起始地址,例如QEMU或你的处理器RAM起始地址 */
      .text : { *(.text) }
      .data : { *(.data) }
      .bss : { *(.bss) }
      _end = .;
    }
    
    你需要根据你的处理器内存映射来修改这个起始地址。

步骤2:生成反汇编文件(用于分析)

riscv64-unknown-elf-objdump -d test.elf > test.dump

打开test.dump,你就能看到由你的C代码生成的、人类可读的RISC-V汇编指令序列。这是验证编译器输出是否符合预期的直接方式。

步骤3:提取纯二进制镜像

riscv64-unknown-elf-objcopy -O binary test.elf test.bin

test.bin是纯粹的指令和数据二进制流,没有任何ELF头信息。许多硬件仿真器和FPGA加载工具需要这种格式。

步骤4:转换为HEX文件 最后,我们需要将二进制文件转换成Verilog/Chisel仿真中常用的Intel HEX或Verilog $readmemh支持的十六进制文本格式。这里用一个简单的Python脚本bin2hex.py来实现:

# bin2hex.py
import sys
with open(sys.argv[1], 'rb') as f:
    data = f.read()
with open(sys.argv[2], 'w') as f:
    for i, byte in enumerate(data):
        if i % 4 == 0 and i != 0:
            f.write('\n')
        f.write(f'{byte:02x}')

运行脚本:

python3 bin2hex.py test.bin test.hex

得到的test.hex文件,其内容就是一行行用十六进制表示的32位指令字,可以直接被你的处理器测试平台读取,加载到指令存储器中。

4. 深度对比:RV64与RV32编译结果差异

RISC-V的灵活性体现在对32位和64位架构的明确支持上。我们的工具链可以同时为目标编译。假设你已经按照类似步骤(修改--target为riscv32-unknown-elf,--with-arch=rv32imac,--with-abi=ilp32)编译好了32位版本的工具(前缀为riscv32-unknown-elf-),现在我们来观察差异。

使用同一个test.c文件,分别用64位和32位编译器编译(使用相同的裸机链接脚本概念,但地址空间可能需要调整):

# 64位编译
riscv64-unknown-elf-gcc -march=rv64imac -mabi=lp64 -nostdlib -T link64.ld -o test_rv64.elf test.c
riscv64-unknown-elf-objdump -d test_rv64.elf > test_rv64.dump

# 32位编译
riscv32-unknown-elf-gcc -march=rv32imac -mabi=ilp32 -nostdlib -T link32.ld -o test_rv32.elf test.c
riscv32-unknown-elf-objdump -d test_rv32.elf > test_rv32.dump

对比两个.dump文件,你会发现一些关键区别:

  1. 寄存器命名:最直观的区别。RV64使用x0-x31,但指令操作中,RV32的寄存器同样是x0-x31。寄存器名本身不区分,但指令的语义会区分。
  2. 指令后缀:对于某些指令,编译器可能会选择不同位宽的变体。例如,加载一个字,在RV64下可能是ld(加载双字,64位),而在RV32下是lw(加载字,32位)。但更常见的是,对于整数运算,RV32I和RV64I的基础整数指令集操作码是相同的(如add, sub, lw, sw),区别在于目标寄存器的位宽由架构隐式定义。一个add指令在RV32下操作32位,在RV64下操作64位(但低32位行为与RV32一致)。
  3. ABI与调用约定:-mabi=lp64与-mabi=ilp32影响了函数调用时参数如何传递(使用哪些寄存器)、栈帧对齐方式等。在简单的main函数中可能不明显,但在复杂函数调用中,生成的序言(prologue)和尾声(epilogue)代码会不同。
  4. 常量处理:对于超出立即数范围的常量,编译器生成的加载序列可能不同。RV32可能需要多条指令来构造一个64位常量,而RV64可能直接用lui和addi加载到64位寄存器的低32位,高32位进行符号扩展。

提示:在设计支持两种模式的处理器时,通过对比同一C代码在两种模式下的编译结果,可以很好地验证你的处理器在不同位宽下的控制逻辑和数据通路是否正确。例如,确保在RV32模式下,对x寄存器的高32位(如果存在)有正确的处理(如写操作时清零)。

5. 进阶技巧与问题排查

掌握了基本流程后,这里有一些提升效率和处理复杂情况的心得。

使用Makefile自动化流程 对于包含多个源文件、依赖库的复杂测试程序,手动敲命令太低效。一个简单的Makefile能管理整个构建过程:

# Makefile
CC = riscv64-unknown-elf-gcc
CFLAGS = -march=rv64imac -mabi=lp64 -nostdlib -O2 -I.
LDFLAGS = -T link.ld

SRCS = test.c helper.c
OBJS = $(SRCS:.c=.o)
TARGET = test.elf

all: $(TARGET) hex

$(TARGET): $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $^

%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<

hex: $(TARGET)
	riscv64-unknown-elf-objcopy -O binary $(TARGET) test.bin
	python3 bin2hex.py test.bin test.hex

dump: $(TARGET)
	riscv64-unknown-elf-objdump -d $(TARGET) > test.dump

clean:
	rm -f *.o *.elf *.bin *.hex *.dump

链接错误与内存布局 最常见的错误来自链接阶段,提示“未定义的引用”或“区域溢出”。检查:

  • 启动文件:裸机程序需要一个用汇编写的_start入口点,负责设置栈指针、清零BSS段,然后跳转到main。你可能需要自己编写或从示例中获取一个crt0.S文件,并将其一同编译链接。
  • 链接脚本地址:确保.text段的起始地址在你的处理器内存映射中是合法且可执行的地址。如果地址设置错误,生成的指令码被加载到错误位置,处理器无法正确取指。
  • 库依赖:如果使用了printf之类的函数,而你没有实现底层的_write等系统调用,链接会失败。对于处理器验证,建议先使用最简的、无需系统调用的代码。

调试生成的反汇编 当测试用例在处理器中运行结果不符合预期时,objdump生成的反汇编文件是你的第一手调试资料。

  1. 逐条核对指令:检查编译器生成的指令是否是你所期望的。例如,一个简单的加法是否被优化掉了?
  2. 检查控制流:查看jal, beq, bne等分支跳转指令的地址是否正确,循环结构是否被正确生成。
  3. 检查内存访问:lw, sw指令的地址计算是否正确,访问的地址是否对齐。

为特定处理器扩展定制 如果你的处理器实现了自定义指令或非标准扩展(例如,自定义的向量或DSP指令),标准的GCC无法识别。这时你需要:

  1. 使用内联汇编(inline assembly)在C代码中直接嵌入自定义指令的机器码。
  2. 或者,编写独立的汇编文件(.S)来使用这些指令,然后与C代码编译出的部分链接在一起。
  3. 更高级的做法是修改GCC的后端,添加对新指令的支持,但这属于工具链开发的范畴,难度较大。

整个流程走下来,最初手工构造指令的繁琐感会被这种“软件定义硬件测试”的流畅感所取代。你可能会发现,花在搭建和熟悉工具链上的时间,在后续海量测试用例的生成和迭代中得到了成倍的回报。更重要的是,这套方法将你的验证工作提升到了一个可编程、可系统化的层面,为处理器的功能验证和性能评估打下了坚实的基础。

从C语言代码到RV32I机器码:手把手教你用GCC和objdump理解RISC-V指令 本文详细介绍了如何从C语言代码转换为RV32I机器码,使用GCC和objdump工具深入理解RISC-V指令集。通过实践教程,开发者可以掌握RISC-V汇编和机器码的转换过程,优化代码并解决常见问题。 阅读详情

相关推荐

RISC-V 开发环境搭建及资料汇总

汇总RISC-V 学习资料,环境搭建过程,通过阅读本文章,一周入门RISC-V开发,不是问题

Only love Can resist the Long Years! 唯有热爱,可抵岁月漫长! 2120

配置riscv64-unknown-elf-gdb环境

这里我从https://mirror.iscas.ac.cn/riscv-toolchains/release/riscv-collab/riscv-gnu-toolchain/LatestRelease/或者。https://github.com/riscv-collab/riscv-gnu-toolchain/releases选择适合的版本下载,我下载的是riscv64-elf-ubuntu-18.04-nightly-2022.11.12-nightly.tar.gz。查看版本证明安装成功。

hushrush的博客 3347

芯片开发验证之RISC-V编译器:绕过构建的烦恼,直接用Arduino的

本文介绍了RISC-V交叉编译器的使用流程。通过Arduino可直接获取RISC-V编译器工具链,无需自行构建。演示了从C代码编译为汇编(.s)、目标文件(.o)、ELF可执行文件的过程,以及使用不同链接脚本生成二进制文件的方法。详细展示了使用objdump、xxd、od等工具分析生成文件的操作步骤,包括查看汇编指令、十六进制转储等。最后总结了RISC-V编译器工具链各组件功能,说明其在CPU开发验证中的关键作用——将程序转换为可被Chisel语言实现的CPU执行的二进制指令序列。

ChipCamp的博客---https://chipcamp.blog.youkuaiyun.com/ 1147

RISC-V 汇编语言

RISCV下的汇编、链接全过程

weixin_51409218的博客 2345

从C语言到RISC-V汇编:手把手教你用GCC和objdump看懂每一行代码

本文详细解析了如何从C语言代码转换为RISC-V汇编指令,通过GCC编译器和objdump工具进行逆向工程分析。从基础函数到复杂控制流,再到内存访问优化和调试实战,帮助开发者深入理解RISC-V架构的底层实现,掌握汇编指令与高级语言的对应关系。

weixin_30781107的博客 356

从C语言到RISC-V汇编:手把手教你用GCC和模拟器完成第一个斐波那契程序

本文详细介绍了如何从C语言编写斐波那契程序,通过GCC编译器转换为RISC-V汇编代码,并使用QEMU模拟器进行调试和优化。文章涵盖了环境搭建、代码转换、汇编解析、模拟执行和性能优化等实战内容,适合对RISC-V汇编和编译器技术感兴趣的开发者学习。

weixin_42116058的博客 260

RISC-V from scratch 5:机器模式

RISC-V from scratch 5:机器模式 接上一篇博客,我今天继续写 RISC-V from scratch 系列博客。原本我打算将该英文系列全部翻译成中文,但原作者貌似没有把这一系列完成就咕咕了,因此本文的内容是我自己实践的内容,以及一些自己的想法,放在这里同大家探讨,算是狗尾续貂,弥补遗憾。 简介 欢迎再次来到 RISC-V from scratch ,先快速回顾一下我们之前做过的内容,我们之前已经探索了很多与 RISC-V 及其生态相关的底层概念(例如编译、链接、原语运行时、汇编等)。具体

df12138的博客 2594

RISC-V riscv64-unknown-elf 编译C文件

riscv64-unknown-elf 为 RISC-V指令集的交叉编译工具 以下环境在Liunx ubuntu x86_64 环境下进行,下面示例以生成32位文件为目标来操作使用。 screen // watch IO infos screen /dev/ttyACM0 115200 compile riscv64-unknown-elf-gcc, RISC-V platform's riscv tool-chain. // complie 64-bit fi...

简单同学 6871

编译玄铁处理器RISC-V指令测试用例

解压Xuantie-900-gcc-elf-newlib-x86_64-V2.0.3-20210806.tar.gz后,编译器位于Xuantie-900-gcc-elf-newlib-x86_64-V2.0.3\bin\riscv64-unknown-elf-gcc路径。执行此命令,就会使用riscv64-unknown-elf-gcc来编译RISC-V测试用例源码,若没有报错,则表示编译成功。由于配置文件和make时,默认使用csh,而不是bash,因此需要安装这个csh。编译ISA_THEAD用例。

百里杨的博客 2319

riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar.gz

riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar

Win10如何使用BC3.1精简版

Win10如何使用BC3.1精简版 使用Borland C++3.1 学习μC/OS—Ⅱ几乎是现在的普遍做法,但是由于Win10系统不能直接使用BC3.1,所以需要用到DOSBox。 1、解压bc3.1精简版压缩包,本文将BC3.1文件夹复制在D盘下,DOSBOX按照默认路径安装。下图为两者安装目录图示: 2、修改DOSBOX的配置文件,找到DOSBox文件安装路径,记事本方式打开DOSBox 0.74-3 Options.bat文件,在此文件末尾添加: MOUNT C D:\BC//意为把D:\BC目录

qq_45547236的博客 2378

【C语言与RISC-V架构深度整合】:从零生成定制化指令集的5大核心步骤

掌握C语言与RISC-V架构协同开发,详解从零实现定制化指令集生成的五大步骤,涵盖编译器适配、指令扩展设计与仿真验证,适用于嵌入式系统与高性能计算场景,提升硬件效率与编程灵活性,值得收藏。

FastDebug的博客 1074

STM32F1的USB接口-自定义HID

设置USB VID:1155 PID :22352。

chilian12321的博客 839

RISC-V处理器设计(五)—— 在 RISC-V 处理器上运行 C 程序

前面我们使用 verilog 完成了一个 risc-v cpu 的设计,但 cpu 最终也是为了程序服务的,不能执行程序的 cpu 没有任何意义。所以这一节我们要研究如何在自己设计的 cpu 上运行 C 程序。

欢迎一起交流问题! 6397

奈曼-皮尔逊准则

奈曼-皮尔逊准则 如果各个假设的先验概率P(Hi)(i=0,1)P(H_i)(i=0,1)P(Hi​)(i=0,1)已知,并且每种判决的代价函数已知,这时,可以用贝叶斯准则进行判决。 如果进一步假设正确判决不付出的代价,而错误判决代价相同,即c00=c11=0,c01=c10=1c_{00}=c_{11}=0,c_{01}=c_{10}=1c00​=c11​=0,c01​=c10​=1,这时可以用最小平均错误概率准则进行判决。 在不知道先验概率P(Hi)(i=0,1)P(H_i)(i=0,1)P(Hi​)(

little_soldier的专栏 1万+

【瑞芯微px30】【RTL8363】【一】驱动移植-网卡驱动概述

linux rtl8363驱动移植

weixin_34799243的博客 1181

12|QEMU:支持RISC-V的QEMU如何构建?

因此,我们需要用宿主机编译器A,编译出一个编译器B,这个编译器B是本地平台上的可执行程序。说得再具体点,你可以把编译器B看作是。

sucaiwa的博客 2794

【STK】手把手教你利用STK进行导弹和反导仿真02 - STK/MMT模块01 导弹任务分析工具概述

种工具:导弹设计工具(Missile Design Tool,MDT )、导弹飞行工具(Missile Flight Tool,截弹,或者用内置拦截弹编辑器创建的个性化的拦截弹, IFT 能够对 ―一对一 ‖动能拦截。导设置系统参数, 并对其有效性进行验证, 画性能图,保证该设计是可行的。(SAIC)公司联合开发研制,极大扩展了 STK 原有的导弹对象的功能,能够精确仿真。IFT 能够对拦截飞机、 导弹、卫星等目标进行仿真和分析。(2)推进系统参数,包括推力,比冲,秒流量,推力持续时间,喷嘴出口面积,

weixin_44184852的博客 1881

使用riscv-tests进行指令测试(一)

riscv-tests,是用于验证RISC-V处理器实现,是否符合其指令集架构规范的一组测试程序。具体来说,riscv-tests目录包含isa、debug、mt和benchmarks的测试文件、底层相关驱动以及编译的文件,用于测试RISC-V CPU的实现。其中,benchmark测试,包含一些业内公认的C代码测试集;而ISA测试,则包含定向指令测试,如机器/用户/监督者模式下I/A/C/D/F/M类型的指令测试。

百里杨的博客 7409

Aurix TC3xx系列MCU ADC模块简介(一)

简单介绍英飞凌Aurix TC3xx系列单片机ADC模块的特点及内部结构。

m0_38045338的博客 6362

【PHP面试题29】什么是PHP-FPM?它与PHP和Nginx有什么关系

PHP面试专区。计划将全覆盖PHP开发领域所有的面试题,对标资深工程师/架构师序列,欢迎大家提前关注锁定。PHP-FPM(FastCGI Process Manager)是PHP的FastCGI进程管理器,它是PHP 5.3.3及更高版本的一部分。它通过为每个请求分配一个独立的进程来提高PHP脚本的执行效率和性能,并且可以与Web服务器(如Nginx、Apache等)进行通信。PHP-FPM是PHP的FastCGI进程管理器,它通过为每个请求分配一个独立的进程来提高PHP脚本的执行效率和性能。

黑夜开发者的博客 1479

Layui layer 弹层:打开、管理、关干净的完整流程

Layui 的 layer 弹层是通用弹窗组件:确认删除、成功提示、加载动画、把整页塞进 iframe,一行 alert / confirm / msg / load 就能弹出来,自带遮罩、入场动画和层级管理,不用自己写 z-index 逻辑。 什么时候该用?页面内的轻量交互:提示、确认、次要页面预览,它最省事。什么时候不该用?弹窗里要塞完整表单工作台,或者项目里已有另一套弹窗体系——两体系并存

gitblog_00124的博客 1039

YOLO11涨点优化:SPPF原创自研创新 | SPPF创新结构,重新设计全局平均池化层和全局最大池化层,增强全局视角信息和不同尺度大小的特征

SPPF_improve利用全局平均池化层和全局最大池化层,加入一些全局背景信息和边缘信息,从而获取全局视角信息并减轻不同尺度大小所带来的影响

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1870

手把手教你扩展RISC-V指令集:基于C语言的AI加速器设计全攻略(仅限专业人士)

掌握C语言实现RISC-V AI加速器指令扩展方法,解决AI计算性能瓶颈。适用于边缘计算与深度学习场景,通过定制指令提升能效比。详解编译器适配与硬件协同设计,显著加速神经网络推理。专业开发者必备指南,值得收藏。

FuncTide的博客 936

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

手把手教你构建GCC交叉编译器,RISC-V嵌入式开发从此不再难!

掌握C语言RISC-V编译工具链构建方法,轻松开启嵌入式开发。本文手把手教你打造GCC交叉编译器,适用于RISC-V架构移植与裸机程序开发,无需依赖第三方工具链。编译自动化、环境配置清晰,大幅降低入门门槛,值得收藏。

QuickProceed的博客 1024

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

13|小试牛刀:跑通RISC-V平台的HelloWorld程序

你好,我是LMOS。在上一课中,我们一起约定了主环境,安装了编译工具和依赖库,构建了交叉编译RISC-V工具链。今天我们继续构建RISC-V版的模拟器QEMU(代码你可以从下载),让它成为“定制款”,更匹配我们的学习需要。为此,我们需要设置好主环境的环境变量,安装好VSCode及其插件,这样才能实现编辑、编译、运行、调试RISC-V程序的一体化、自动化。话不多说,我们开始吧。

sucaiwa的博客 2706

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: ChatGPT也能当数据助手?3种让大模型稳定输出JSON的实战技巧
下一篇: 如何用GPT-3.5和理杏仁API实现智能金融数据查询(附完整代码)
git9versioner
博客等级 码龄4年 75粉丝 1650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值