YSYX-PA0学习记录

写下PA0重新复盘PA0的完成过程,查漏补缺

1 Ubuntu的安装

由于之前使用的常常是windows系统,此处选择安装双系统,主要参考b站up阿杰的双系统安装教程,关键步骤如下:

  1. 使用rufus制作启动U盘;
  2. 磁盘分区尽量大一些;(如果选择方案二,根挂载点应当给到50GB以上)
  3. 注意系统的时间同步问题;

2 Ubuntu系统的配置

  1. 推荐安装一些常用软件:QQ,网易邮箱,Joplin,clash,onedrive,edge, sublime-text
1
dpkg -i *.deb
  1. 简洁的配置vim和sublime

3 Linux的学习探索

学习资源:Linux101HARLEY HAHN’S GUIDE TO UNIX AND LINUX计算机教育中缺失的一课C语言教程笨办法学Cdotfiles仓库

3.1 常用命令

  1. 软件安装:sudo apt install file or *.deb
  2. 帮助文档
    • 全面:man
    • 快速:tldr
  3. 文件操作
    • 查看:cat,less,head,tail
    • 复制:cp
    • 移动:mv
    • 删除:rm
    • 创建:mkdir,touch
    • 压缩:tar
    • 权限:chmod
    • 搜索:findfdlocate
1
2
3
4
5
6
7
8
# 查找所有名称为src的文件夹
find . -name src -type d
# 查找所有文件夹路径中包含test的python文件
find . -path '*/test/*.py' -type f
# 查找前一天修改的所有文件
find . -mtime -1
# 查找所有大小在500k至10M的tar.gz文件
find . -size +500k -size -10M -name '*.tar.gz'
  1. 重定向与管道
    • 覆盖:echo "Hello Linux!" > output_file
    • 追加:echo "Hello Linux!" >> output_file
      • 转义与不转义:echo "$foo" or echo '$foo'
    • 管道:|将符号左侧命令的stdout作为符号右侧命令的stdin
  2. 网络下载:wget,curl
  3. 文本处理
    • 统计:wc
    • 比较:diff file1 file2
    • 查找:grep
    • 替换:sed
    • 排序:sort
    • 正则表达式

3.2 Shell脚本

  1. 变量赋值:foo=bar
  2. 变量访问:$foo
  3. 字符串:转义"",原义''
  4. 通配符:
    • ?:匹配一个字符
    • *:匹配任意个字符
  5. 花括号:mv *{.py,.sh} folder
  6. 函数:
    1. 参数:
      • $0:脚本名
      • $1-$9:第1-9个参数
      • $@:所有参数
      • $#:参数个数
      • $?:前一个命令的返回值
      • $$:当前脚本的进程识别码
      • !!:完整的上一条命令
      • $_:上一条命令的最后一个参数
    2. 返回值:0:表示正常执行,反之出错
  7. 条件语句:
    • -z/-n :空/非空
    • -eq/-ne:相等/不等
    • -gt/-lt:大于/小于
    • -ge/-le:大于等于/小于等于
1
2
3
4
5
6
7
8
9
if condition1
then
# 代码块会在条件1为真时执行
elif condition2
then
# 代码块会在条件2为真时执行
else
# 如果前面的条件都不为真,执行此代码块
fi

3.3 Makefile简明教程

3.4 GDB

small tutorial

3.4.1 BUG:生成转储文件

  1. 生成可执行文件:gcc -ggdb test.c -o test.out
  2. 查看转储文件生成路径:cat /proc/sys/kernel/core_pattern
  3. 修改转储文件输出路径和输出文件名
1
2
3
4
5
6
7
8
9
10
11
12
// 控制core文件的文件名中是否添加pid作为扩展
echo "1" > /proc/sys/kernel/core_uses_pid
// 设置core文件的输出路径和输出文件名,这里我的路径是/home/boy/corefile,文件名就是后面的部分
echo "/home/your_path/core-%e-%p-%t"> /proc/sys/kernel/core_pattern
//参数说明
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加程序名
  1. 查看core file size:ulimit -a
  2. 修改core file size:ulimit -c unlimited
  3. 重新运行可执行文件:./test.out
  4. 注意:以上行为可能需要su权限,甚至gdb执行内核转储文件的操作也需要su权限。

3.4.2 基本操作

  1. su下使用gdb分析core dump:gdb ./test.out ./core.1341870.1000.8.test.out.1598867712
  2. Backstracing:bt
  3. Frame: f n
  4. List source code: list
  5. Print: p a
  6. watch expr:表达式发生变化时暂停运行
  7. awatch expr:表达式被访问、改变是暂停执行
  8. rwatch expr:表达式被访问时暂停执行

3.5 Tmux简明教程

3.6 Git简明教程

git
Learn Git Branching

3.7 C语言教程

在此总结此后遇到的所有与c语言相关的问题;
完成预学习部分的C语言题目

3.8 正则表达式

正则表达式基本规则.png

4 数字电路基础实验

南大数字逻辑与计算机组成课程实验

4.1 注意!

  1. 强烈建议初学者不要使用行为建模方式设计电路
  2. One-hot编码的状态机从一个状态到另一个状态的状态跳转速度非常快,而顺序二进制编码从一个状态跳转到另外一个状态需要较多次跳转,并且随着状态的增加,速度急剧下降。 在芯片受到干扰时,one-hot编码一般只能跳转到无效状态(如果跳到另一有效状态必须是当前为 1 的为变为 0 ,同时另外一位变成由 0 变为 1 ,这种可能性很小),因此one-hot编码的状态机稳定性高。CPLD多使用gray-code,而FPGA多使用one-hot 编码。对于触发器资源非常丰富的FPGA器件,使用one-hot是常用的。

Verilog一开始并不是为了设计可综合电路而提出的,它的本质是一门基于事件队列模型的电路建模语言。因此,行为建模很容易会让初学者偏离描述电路的初衷: 开发者需要看着电路图,心里想象电路的行为,然后转化成事件队列模型的思考方式,最后再用行为建模方式来描述电路的行为,综合器再来根据这样的描述推导出相应的电路。从这个过程来看,这不仅是没有必要的,而且还很容易引入错误:如果开发者心里本身就已经有电路图,直接描述它是最方便的,如果开发者心里本身就已经有电路图,而开发者对行为建模方式的理解所有偏差,可能会采用了错误的描述方式,从而设计出非预期的电路。如果开发者心里没有电路图,而是期望通过行为建模方式让综合器生成某种行为的电路,这就已经偏离“描述电路”的本质了。大部分同学非常容易犯这样的错误,把行为建模当作过程式的C语言来写,尝试把任意复杂的行为描述映射到电路,最终综合器只会生成出延迟大,面积大,功耗高的低质量电路。所以,直到大家掌握“描述电路”的思维而不被行为建模误导之前,我们强烈建议初学者远离行为建模方式,仅通过数据流建模和结构化建模方式直接描述电路。例如,上文关于if和always的说法从某种程度上来说是正确的,但下面的问题可以帮助大家测试自己是否已经掌握了Verilog的本质:

  • 在硬件描述语言中,“执行”的精确含义是什么?

答:在仿真器里是模拟电路;在综合器中综合电路;在时序电路中顺序执行,在并行电路中交互执行;

  • 是谁在执行Verilog的语句? 是电路,综合器,还是其它的?

答:在开发阶段,使用模拟器;在综合阶段,使用综合器;最后在电路上执行。

  • if的条件满足,就不执行else后的语句,这里的“不执行”又是什么意思? 和描述电路有什么联系?

都要描述;不执行指跳过执行。

  • 有“并发执行”,又有“顺序执行”,还有“任何一个变量发生变化就立即执行”,以及“在任何情况下都执行”,它们都是如何在设计出来的电路中体现的?

并联和串联的关系;顺序执行可以通过时序和寄存器实现;变化执行可以通过触发器(Flip-Flops)实现;

如果你无法对这些问题作出明确的回答,我们强烈建议你不要使用行为建模方式。如果你真的想弄懂它们,你需要阅读 Verilog标准手册 。

真正的描述电路 = 实例化 + 连线

  • 实例化:在电路板上放一个元件/模块,可以是一个门电路,或者是由门电路组成的模块
  • 连线:用导线将元件/模块的引脚正确地连起来

4.2 拓展

生成进位加法器
先行进位加法器(Carry Look-Ahead Adder,CLA)是一种加法器设计,旨在加快加法操作的速度,特别是在大规模加法操作中。与传统的Ripple Carry Adder相比,CLA具有更高的性能,因为它可以在不等待进位传递的情况下生成和处理进位。
CLA加法器的设计基于以下原理:

  1. 生成(G)和传播(P)信号:CLA加法器使用生成和传播信号来确定每个位的进位。生成信号(G)表示两个输入位相加时是否会生成进位(1表示生成,0表示不生成),而传播信号(P)表示输入位是否传播进位到该位(1表示传播,0表示不传播)。
  2. 进位生成:对于每一位i,进位生成(G_i)等于输入A_i和B_i相加的逻辑与(AND)操作。即:G_i = A_i & B_i。
  3. 进位传播:进位传播(P_i)等于输入A_i或B_i的逻辑或(OR)操作。即:P_i = A_i | B_i。
  4. 进位计算:CLA加法器使用生成(G)和传播(P)信号来计算每一位的进位。对于第一位(最低位),进位C0等于G0,然后每一位的进位C_i都通过以下等式计算:C_i = G_i + (P_i & C_(i-1))。