1 Star 1 Fork 0

RV少年 (RV4Kids) / RISC-V-CPU

 / 详情

好好使用 TOOL CHAIN。

待办的
拥有者
创建于  
2022-02-08 20:46

https://gitee.com/RV4Kids/RISC-V-CPU/blob/master/doc/riscv-toolchain-installation-usage.md

要在基础的框架上增加指令,只需要掌握号工具链,增加要增加的指令,然后编译成BIN的测试代码,再交由仿真系统测试。

评论 (71)

袁德俊 创建了任务

pi@pi-desktop:~/oscpu/projects/cpu/build_test$ ls

custom-output  emu  emu-compile  inst.bin  inst_diff.bin  non-output  top.vcd

riscv64-unknown-elf-objdump inst.bin -D -b binary -m riscv:rv64

inst.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:	00100093          	li	ra,1
   4:	00200093          	li	ra,2
   8:	00108093          	addi	ra,ra,1

riscv64-unknown-elf-objdump inst_diff.bin -D -b binary -m riscv:rv64

inst_diff.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:	00100093          	li	ra,1
   4:	00200093          	li	ra,2
   8:	00108093          	addi	ra,ra,1
   c:	0000006b          	0x6b

nano add2.S

.org 0x0
 	.global _start
_start:
	ori x1, x0, 0x210 # x1 = h210
	ori x2, x1, 0x021 # x2 = h231
	slli x3, x2, 1  # x3 = h462
	andi x4, x3, 0x568 # x4 = h460
	ori x5, x0, 0x68a # x5 = h68a

riscv64-unknown-elf-as add2.S -o add2.o -march=rv64i

ls
add2.o  custom-output  emu-compile  inst_diff.bin  top.vcd
add2.S  emu            inst.bin     non-output

riscv64-unknown-elf-ld add2.o -o add2.om

ls
add2.o   add2.S         emu          inst.bin       non-output
add2.om  custom-output  emu-compile  inst_diff.bin  top.vcd

riscv64-unknown-elf-objcopy -O binary add2.om add2.bin

ls
add2.bin  add2.om  custom-output  emu-compile  inst_diff.bin  top.vcd
add2.o    add2.S   emu            inst.bin     non-output

riscv64-unknown-elf-objdump add2.bin -D -b binary -m riscv:rv64

add2.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:	21006093          	ori	ra,zero,528
   4:	0210e113          	ori	sp,ra,33
   8:	00111193          	slli	gp,sp,0x1
   c:	5681f213          	andi	tp,gp,1384
  10:	68a06293          	ori	t0,zero,1674

用文本编辑器打开二进制文件 sample.bin ,以十六进制显示的内容如下,这正是 sample.S 文件中的 5 条指令汇编后的机器码:

9360 0021 13e1 1002 9311 1100 13f2 8156
9362 a068

RISC-V 寄存器的命名是什么含义?

	addi    ra,ra,1
#	.byte	0x6b
#	.byte	0x6e
	addi	x2,ra,2
	addi	x3,ra,3
	addi	x4,ra,4
	addi	x5,ra,5
	addi	x6,ra,6
	addi	x7,ra,7
	addi	x8,ra,8
	addi	x9,ra,9
	addi	x10,ra,10
	addi	x11,ra,11
	addi	x12,ra,12
	addi	x13,ra,13
	addi	x14,ra,14
	addi	x15,ra,15
	addi	x16,ra,16
	addi	x17,ra,17
	addi	x18,ra,18
	addi	x19,ra,19
	addi	x20,ra,20
	addi	x21,ra,21
	addi	x22,ra,22
	addi	x23,ra,23
	addi	x24,ra,24
	addi	x25,ra,25
	addi	x26,ra,26
	addi	x27,ra,27
	addi	x28,ra,28
	addi	x29,ra,29
	addi	x30,ra,30
	addi	x31,ra,31

add2.bin:     file format binary


Disassembly of section .data:

0000000000000000 <.data>:
   0:	00108093          	addi	ra,ra,1
   4:	00208113          	addi	sp,ra,2
   8:	00308193          	addi	gp,ra,3
   c:	00408213          	addi	tp,ra,4
  10:	00508293          	addi	t0,ra,5
  14:	00608313          	addi	t1,ra,6
  18:	00708393          	addi	t2,ra,7
  1c:	00808413          	addi	s0,ra,8
  20:	00908493          	addi	s1,ra,9
  24:	00a08513          	addi	a0,ra,10
  28:	00b08593          	addi	a1,ra,11
  2c:	00c08613          	addi	a2,ra,12
  30:	00d08693          	addi	a3,ra,13
  34:	00e08713          	addi	a4,ra,14
  38:	00f08793          	addi	a5,ra,15
  3c:	01008813          	addi	a6,ra,16
  40:	01108893          	addi	a7,ra,17
  44:	01208913          	addi	s2,ra,18
  48:	01308993          	addi	s3,ra,19
  4c:	01408a13          	addi	s4,ra,20
  50:	01508a93          	addi	s5,ra,21
  54:	01608b13          	addi	s6,ra,22
  58:	01708b93          	addi	s7,ra,23
  5c:	01808c13          	addi	s8,ra,24
  60:	01908c93          	addi	s9,ra,25
  64:	01a08d13          	addi	s10,ra,26
  68:	01b08d93          	addi	s11,ra,27
  6c:	01c08e13          	addi	t3,ra,28
  70:	01d08e93          	addi	t4,ra,29
  74:	01e08f13          	addi	t5,ra,30
  78:	01f08f93          	addi	t6,ra,31

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者
  • 赞同了回答2021-02-10 08:41

    一个自律的人有多可怕? 》 虎山行不行
    公众号:虎山行不行┊没有感情的码字机器┊反乌托邦的行尸走肉

    看见这题我就溜达进来了。 我知道自律现在是个褒义词,高度自律的话堪比封神。 于是乎我进来就想说一句“别太自律”喔各位老铁。会要命的。 我自己要是没有所谓“高度自律”的切身体会,我这么唠嗑会被各位乱棍打死是没跑的。 所以我先简单说说自己经历,再说说关于自律的看法。 自律的经历我就说健身,写文,两个方面。 先说健身。 我从初中开始泡拳馆…

    9030 赞同,1000 条评论

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者
  • 赞同了文章 2021-01-21 13:43

    Lockless Programming 兰新宇 talk is cheap

    说明:本文主要是汇总了以下的几篇文章,并经过了一定的加工和整理。

    正文 202 赞同 9 条评论

    包括spinlock, mutex在内的「锁」的机制会带来一些问题,比如需要持有两个锁,但加锁的顺序不对,就可能形成"A-B"类死锁,或者由于设计错误、持锁线程被抢占等原因,导致一个thread持锁时间太长。

    似乎「无锁编程」的概念可以解决上述的这些问题,但"lockless programming"本身是复杂的,需要深刻地理解它,才能从技术的角度获得预想的收益。来看下在实际的应用中,无锁编程都面临哪些挑战,以及如何应对。

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者
  • 赞同了文章 2020-10-03 16:22

    二十八画生征友:一起来通关6.S081/6.828吧~ 胡津铭 (技术垃圾,只会抱腿)

    (标题是一个危险的致敬)(赞同 610 评论 185)

    6.828 Operating System Engineering是MIT久负盛名的一门操作系统相关的课程。这门课程有多牛呢?举个例子,以陈海波老师为首的上海交通大学IPADS实验室可以说是国内最强的操作系统相关实验室之一,而陈海波老师等人在他们读博的时候(早在2005年左右)就完成了6.828课程的学习,甚至还以6.828的JOS系统为基础开发了Corey操作系统,并发表了一篇ODSI2008论文Corey: An operating system for many cores,该论文也是陈老师至今引用最高的论文。而后,IPADS老师也基于6.828的资源,在上海交通大学软件学院开设了多年操作系统课程。

    好的,那么我就先写到这里,感兴趣的同学请独立完成前两个Lab之后加群交流~ 群号为603579009,加群的时候请附上自己完成前两个Lab的github repo地址~~ 谢谢大家啦

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者
  • 赞同了回答 2019-06-23 22:25 ( 2674 赞同 257 评论)

    中美网络通讯的海底光缆大约有多少根?每根有多粗?

    JefferyWang (这世界有多么不给力,你就应该多么给自己力)

    这个之前有人利用wikipedia的数据和谷歌地图,做出了一幅互动式的世界海底光缆分布图。 目前中国大陆和美国连通的海底光缆主要有: 1. 跨太平洋快线(Trans-Pacific Express,简称TPE) 跨太平洋快线又称横太平洋快速海缆,为连接中国大陆、台湾、韩国、日本和美国的一条海底通信电缆。由中国电信、中国网通、…

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者
  • 赞同了回答 2018-02-23 07:02 (13.3万 赞同 5367 条评论)

    人是怎么废掉的? (曾加) 数学话题下的优秀答主

    沉溺于「轻易获得高成就感」的事情 :有意无意地寻求用很小付出获得很大「回报」的偏方,哪怕回报是虚拟的。这种行为会提升自己的「兴奋阈值」,让人越来越不容易拥有成就感,从而越来越依赖虚拟的成就感,陷入恶性循环。症状轻的: 沉溺游戏 (在虚拟世界中加快时间流逝的速度,使得「成功」来得更快)、 种马小说 (意淫人能轻易获得想要的东西);…

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者
  • 回答了问题2017-05-08 15:56

    私有云爆发,该不该意外? (肖宏辉)网络/OpenStack/SDN/NFV搬运工

    公有云不能完全取代私有云, 1,如果私有云成本更低或者相当,企业更愿意使用私有云。大部分企业没有这个实力让成本更低,因此大家才觉得公有云有发展。不过公司的CEO CTO 有时不甘心,还是想尝试一下。 2,对安全或其他有要求的企业部门,更倾向于自建或者委托别人搭建私有云。比如银行和政府部门不可能把核心业务放到公有云上。就算是…

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

5.4 RISC-V寄存器

肖宏辉

网络/OpenStack/SDN/NFV搬运工

我们之前看过了汇编语言和RISC-V的介绍。接下来我们看一下之后lab相关的内容。这部分的内容其实就是本节课的准备材料中的内容。

输入图片说明

你们现在对于这个表达应该都很熟悉了,这个表里面是RISC-V寄存器。寄存器是CPU或者处理器上,预先定义的可以用来存储数据的位置。寄存器之所以重要是因为汇编代码并不是在内存上执行,而是在寄存器上执行,也就是说,当我们在做add,sub时,我们是对寄存器进行操作。所以你们通常看到的汇编代码中的模式是,我们通过load将数据存放在寄存器中,这里的数据源可以是来自内存,也可以来自另一个寄存器。之后我们在寄存器上执行一些操作。如果我们对操作的结果关心的话,我们会将操作的结果store在某个地方。这里的目的地可能是内存中的某个地址,也可能是另一个寄存器。这就是通常使用寄存器的方法。

输入图片说明

寄存器是用来进行任何运算和数据读取的最快的方式,这就是为什么使用它们很重要,也是为什么我们更喜欢使用寄存器而不是内存。当我们调用函数时,你可以看到这里有a0 - a7寄存器。通常我们在谈到寄存器的时候,我们会用它们的ABI名字。不仅是因为这样描述更清晰和标准,同时也因为在写汇编代码的时候使用的也是ABI名字。第一列中的寄存器名字并不是超级重要,它唯一重要的场景是在RISC-V的Compressed Instruction中。基本上来说,RISC-V中通常的指令是64bit,但是在Compressed Instruction中指令是16bit。在Compressed Instruction中我们使用更少的寄存器,也就是x8 - x15寄存器。我猜你们可能会有疑问,为什么s1寄存器和其他的s寄存器是分开的,因为s1在Compressed Instruction是有效的,而s2-11却不是。除了Compressed Instruction,寄存器都是通过它们的ABI名字来引用。

a0到a7寄存器是用来作为函数的参数。如果一个函数有超过8个参数,我们就需要用内存了。从这里也可以看出,当可以使用寄存器的时候,我们不会使用内存,我们只在不得不使用内存的场景才使用它。

表单中的第4列,Saver列,当我们在讨论寄存器的时候也非常重要。它有两个可能的值Caller,Callee。我经常混淆这两个值,因为它们只差一个字母。我发现最简单的记住它们的方法是:

  • Caller Saved寄存器在函数调用的时候不会保存
  • Callee Saved寄存器在函数调用的时候会保存

输入图片说明

这里的意思是,一个Caller Saved寄存器可能被其他函数重写。假设我们在函数a中调用函数b,任何被函数a使用的并且是Caller Saved寄存器,调用函数b可能重写这些寄存器。我认为一个比较好的例子就是Return address寄存器(注,保存的是函数返回的地址),你可以看到ra寄存器是Caller Saved,这一点很重要,它导致了当函数a调用函数b的时侯,b会重写Return address。所以基本上来说,任何一个Caller Saved寄存器,作为调用方的函数要小心可能的数据可能的变化;任何一个Callee Saved寄存器,作为被调用方的函数要小心寄存器的值不会相应的变化。我经常会弄混这两者的区别,然后会到这张表来回顾它们。

如果你们还记得的话,所有的寄存器都是64bit,各种各样的数据类型都会被改造的可以放进这64bit中。比如说我们有一个32bit的整数,取决于整数是不是有符号的,会通过在前面补32个0或者1来使得这个整数变成64bit并存在这些寄存器中。

  • 学生提问:返回值可以放在a1寄存器吗?

    TA:这是个好问题。我认为理论上是可以的,如果一个函数的返回值是long long型,也就是128bit,我们可以把它放到一对寄存器中。这也同样适用于函数的参数。所以,如果返回值超过了一个寄存器的长度,也就是64bit,我们可以将返回值保存在a0和a1。但是如果你只将返回值放在a1寄存器,我认为会出错。

  • 学生提问:为什么寄存器不是连续的?比如为什么s1与其他的s寄存器是分开的?

    TA:我之前提到过,但是也只是我的猜想,我并不十分确定。因为s1寄存器在RISC-V的Compressed Instruction是可用的,所以它才被分开。

  • 学生提问:除了Stack Pointer和Frame Pointer,我不认为我们需要更多的Callee Saved寄存器。

    TA:s0 - s11都是Callee寄存器,我认为它们是提供给编译器而不是程序员使用。在一些特定的场景下,你会想要确保一些数据在函数调用之后仍然能够保存,这个时候编译器可以选择使用s寄存器。

发布于 2020-11-15 21:34

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

note_8590578

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

MIT6.S081 操作系统工程中文翻译

置顶内容

MIT6.S081(2020)翻译简介

肖宏辉(网络/OpenStack/SDN/NFV搬运工)

因为学习MIT6.824,偶然知道了MIT6.S081这门课程。MIT6.S081这门课程的标题是Operating System Engineering,主要讲的就是操作系统。授课教授是Robert Morris和Frans Kaashoek,两位都是非常出名的程序员。

课程是基于一个类似于Unix但是简单的多的教学操作系统XV6来讲解,虽然不是原汁原味的Linux,但是对于理解Linux的工作方式和结构是足够了。与MIT6.824一样的是,这门课程是全英文,甚至英文字幕都没有。对于国内的同学来说,如果英文没有足够好,很难较好的理解这门课程。因此我计划将这门课程翻译成中文文字版。我将在语句通顺的前提下,尽量还原课程的内容,希望可以帮助大家学习到这门课程。如果你的英语不是那么好,建议阅读完文字再去看视频相关的课程。

目前MIT的这门课还没有上完,按计划是在12月初完成,具体的内容可以参考【1】。每一节课都在80分钟左右,大概会有6-9个知识点,我会按照独立的知识点将每节课拆分成6-9个小节。


2021-04-24 更新:

今天终于把问答课以外的20节课程都翻译完了,总共大概有35万个字,花费时间大概在200个小时左右。

这门课程相比6.824来说更像是一个整体。6.824更多的是在理解和设计分布式系统时的一些技术和技巧,而6.S081介绍了Unix风格操作系统的各个方面(虽然这两个课没什么关系( ̄. ̄),但是因为是连着翻译的难免会有对比)。

实际中的操作系统会更加的复杂,但是通过这门课程的学习基本上可以对操作系统有一个全面的认识。经过翻译的过程,我自己也把之前的一些知识盲区补全了。这门课程虽然只是一个MIT的本科课程,但是我推荐给所有从事IT相关工作的同学,掌握了操作系统对于面试,debug,写代码都是有好处的。

最后,希望我的翻译可以帮助到你。

【1】https://pdos.csail.mit.edu/6.828/2020/schedule.html

如果

  • 你发现了翻译的错误,或者想把剩下几门课程的翻译补上,可以向关联的github提交PR
  • 你觉得我做的还不错,可以关注我的知乎,并给我一个点赞。
  • 你正在找一份工作,并且想与和我一样的工程师共事,请联系
    我:honghui_xiao@yeah.net
  • 还想学习其他MIT课程,我还做了一些其他的翻译:

声明

此次翻译纯属个人爱好,如果涉及到任何版权行为,请联系我,我将删除内容。文中所有内容,与本人现在,之前或者将来的雇佣公司无关,本人保留自省的权利,也就是说你看到的内容也不一定代表本人最新的认知和观点。

编辑于 2022-01-25 11:13

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

github 1.1k stars

About

No description, website, or topics provided.
Resources

  • Readme笔记
  • Stars 1.1k stars
  • Watchers 20 watching
  • Forks 182 forks
  • commits 390 ( 06f26f0 5 days ago )

SUMMARY.md

Table of contents

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

输入图片说明

Hong Hui Xiao/肖宏辉 huihongxiao

184 contributions in the last year

输入图片说明

Popular repositories

  • MIT6.S081
    Public
    1.1k
    183

  • MIT6.824
    Public
    7
    3

  • exercise
    Public
    5
    13

  • devstack.files
    Public
    Files to install devstack under GFW
    Vim script
    3
    11

  • Heat-CustomizeUI
    Public
    Python
    1

  • thor
    Public
    Forked from ivanallen/thor
    雷神项目,翻译 mit 6.824 2020
    11
    3

About

雷神项目,翻译 mit 6.824 2020

  • Resources
  • Readme
  • License GPL-2.0 License
  • Stars 482 stars
  • Watchers 18 watching
  • Forks 72 forks

README.md

thor

All Contributors

雷神项目,翻译 mit 6.824 2020

组织

QQ:1035287657

视频资源

快速开始

如何翻译

版权声明

本字幕版权属参与翻译的所有成员,严禁用作商业用途,一经发现,追究法律责任。

Contributors ✨

非常感谢这些可爱的同学:


zihe.liu

🖋

Fan Yang

🖋

Cyru1s

🖋

hoooga

🖋

Allen

🖋

fisheuler

📖

2014bduck

🖋

Laurel-rao

🐛

This project follows the all-contributors specification. Contributions of any kind welcome!

参考资料和工具

6.824 Distributed System

课程链接:https://pdos.csail.mit.edu/6.824/

系统方向非常好的一门课程,每堂课都讲一个新的分布式系统模型,没有教材,每堂课都是直接讲论文。老师是MIT PDOS的神牛Robert Morris (不错,这人就是当年因为发明蠕虫而蹲监然后回MIT当教授的神人)和Frans Kaashoek。这些分布式系统都是实际用在各个大公司里的系统,比如说Spark, GFS,PNUTS。当年我修这门课的时候感觉课程压力非常大,有期中期末考试,有lab作业,有reading work, 还有course project,但是整个课程设计得非常好。lab要用Golang实现,硬生生地学了门新的语言。

Frans Kaashoek团队

来自如雷贯耳的MIT CSAIL,主要研究方向包括操作系统,网络,编译器等,PDOS组的负责人之一,绝对的大佬,后面你会看到被他支配的恐惧感。该实验室大佬众多,超新星Nickolai Zeldovich、Adam Belay、Mit6.284的Robert Morris以及已故的图灵奖获得者、计算机密码发明者Fernando J. Corbató都是个组的,这里暂以他为代表。可以看下团队近期的文章,毕竟一个会议也就20来篇。另外,很多文章都出自其“徒子徒孙”的团队。

MIT经典课程“分布式系统”视频版上线!网友:终于来了非偷拍清晰版本

输入图片说明

来自MIT的经典课程, MIT的分布式系统课程,已经有20年历史,2000年就已经开设课程。当时讲授这门课的老师是Frans Kaashoek(ACM Fellow)和Robert Morris教授。现在,这门课程的讲授者,就只有Robert Morris教授一人了——长达20年教龄。

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

输入图片说明

https://www.csail.mit.edu/person/robert-morris

Robert Morris

Professor

Robert Morris is a professor in MIT's EECS department and a member of the Computer Science and Artificial Intelligence Laboratory. He received a PhD from Harvard University for work on modeling and controlling networks with large numbers of competing connections. As a graduate student he helped design and build an ARPA-funded ATM switch with per-circuit hop-by-hop flow control. He led a mobile communication project which won a best student paper award from USENIX. He co-founded Viaweb, an e-commerce hosting service. His current interests include modular software-based routers, analysis of the aggregation behavior of Internet traffic, and scalable ad-hoc routing.

Related Links: Website https://pdos.csail.mit.edu/~rtm/

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

输入图片说明

Frans Kaashoek

Professor

In an ideal world, computers would work fast, never fail, and be free of security exploits. In our current reality, though, systems tend to fail or have security exploits due to bugs in the software, and people spend a tremendous amount of time and resources trying to find bugs and testing software. How, then, do we make software and systems more provably secure?

Professors Frans Kaashoek and Nickolai Zeldovich of MIT CSAIL are interested in building practical secure systems, from operating systems and hardware to programming languages and security analysis tools. Together, they co-lead with Professors Adam Belay, Henry Corrigan-Gibbs, and Robert Morris the Parallel and Distributed Operating Systems (PDOS) Group within CSAIL.

This vision for producing secure systems has a long history dating back to the 1960s, but in the last decade interest has been picking back up thanks to a tremendous improvement in verification technology that has enabled people to use verification practically for real-systems software. Previously, you could only use verification for toy programs, but now Prof. Kaashoek and Prof. Zeldovich are trying to figure out how to use that technology for serious software.

Their interest in security got them further into verification research. For example, in one of their past projects they found security bugs in Linux where the affected instruction sequences were only three or four lines of code. To the programmers, these lines of code appeared to be absolutely correct. As they investigated further, they realized that, due to undefined behavior, the lines were in fact incorrect, and the compiler would optimize them anyway, removing the security checks that those lines implemented.

This project raised the question: If not even experts could get a few lines of code correct or secure, then what tools or approaches could really convince them that a system is 100 percent, iron-clad secure? To answer this overarching question, they began to look into systems software verification for long-term solutions.

Infrastructure software for data centers powers many widely used cloud applications, and is therefore particularly important to be reliable and secure. Prof. Kaashoek and Prof. Zeldovich focus on the infrastructure of such systems. As an example, they implemented a provably correct crash-save file system, so that the file system’s data is still intact even if it crashes. In the past, systems have had ugs that can cause data to get lost, but their team developed a mathematical proof that eliminates this issue. Building on the file system, they also recently worked on a mail server that is concurrent and accepts email messages, and the team has been able to prove that no messages will get lost.

This research will ensure that eventually, important software will never crash and will be secure. In addition, programmers will be able to understand how the software operates more clearly because their systems will include more accurate specifications, allowing them to build better software.
Bio

Frans Kaashoek is the Charles Piper Professor in MIT's EECS department and a member of CSAIL, where he coleads the parallel and distributed operating systems (PDOS) group. He received his PhD from the Vrije Universiteit (Amsterdam, The Netherlands) for his work on group communication in the Amoeba distributed operating system. Frans is a member of the National Academy of Engineering and the American Academy of Arts and Sciences, the recipient of the ACM SIGOPS Mark Weiser award and the 2010 ACM Prize in Computing. He was a cofounder of Sightpath, Inc. and Mazu Networks, Inc.

Last updatedJul 21 '21

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

Project

Noria: a new data-flow system for web applications

输入图片说明

We're developing a flexible, high-performance storage architecture for database-backed applications, based on a dynamic set of queries specified by the developer which Soup automatically optimizes.

Noria is an attempt at designing a database specifically tailored for web applications, providing automatic caching, safe and effortless schema migrations, and native support for reactive use.

Noria observes that, by having developers provide the set of queries their application will make in advance, the database can be smarter about how to execute those queries. In particular, it can choose to pre-compute, and incrementally maintain, the results for queries. This allows Noria to answer those queries quickly, and essentially obviates the need for application caches.
Contact us

If you would like to contact us about our work, please refer to our members below and reach out to one of the group leads directly.

Last updated Oct 16 '18

Research Areas
Systems & Networking
Impact Areas
Big Data
Group
Parallel and Distributed Operating Systems

Related Links

Project page.
https://pdos.csail.mit.edu/noria

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

Research Group

Parallel and Distributed Operating Systems

输入图片说明

Map of the internet

We at PDOS build and investigate software systems for parallel and distributed environments.

We have conducted research in operating systems, multi-core scalability, security, networking, mobile computing, language and compiler design, and systems architecture, taking a pragmatic approach: we build high-performance, reliable, and working systems.

Contact us

If you would like to contact us about our work, please refer to our members below and reach out to one of the group leads directly.

Members

  • Kaashoek: Frans Kaashoek
  • Morris : Robert Morris
  • Zeldovich : Nickolai Zeldovich
  • Adam Belay headshot: Adam Belay
  • Malte Schwarzkopf :Malte Schwarzkopf
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

BING Robert Morris Frans Kaashoek Map of the internet

输入图片说明

输入图片说明

The ‘Morris Worm’ turns 30

输入图片说明

输入图片说明

The ‘Morris Worm’ turns 30, Dinesh Abeywickrama and Inoshi Ratnasekera explore the History of Computer Worms.

Morris Worm

On 02nd of November 1988, world’s first major malware attack on the internet called ‘Morris Worm’ was unleashed. Even though this was not the first worm, it was considered the first major attack, which was a wakeup call to internet security engineers to consider the risk of software bugs and start research and development of network security (Ivey, 2018; Marsan, 2008).

Robert Tappan Morris

At 22 years, while attending Cornell graduate university Robert Tappan Morris developed the worm that spread via internet.

Robert Tappan Morris (creator of the ‘Morris Worm’) was born in 1965 and his father was a computer scientist at Bell Labs, who helped design Multics and Unix; and later became the chief scientist at the National Computer Security Center, a division of the National Security Agency (NSA).

输入图片说明

Robert Tappan Morris, creator of ‘Morris worm’ in 2008

What / why was it?

Nowadays worms are very common on the internet, 30 years back Morris Worm had affected 6000 UNIX based systems. Before the security experts released patches 24hours later, the worm had affected and crashed 10 percent of internet usage. Rest of the networks were slow. Reports say Morris Worm is not only a worm attack, but also the first distributed DDoS attack (Vaughan-Nichols, 2018).

Morris worm can be considered as self-replicating software, which exploited common weakness of famous soft wares such as ‘Sendmail’ mail sending program, ‘Finger’ tool software help to find logged on users in system. Morris Worm, had exploited three weakness of internet to enter target networks and UNIX systems.

  1. Vulnerability in the debug mode of UNIX’s sendmail program
  2. A buffer overrun hole in the finger daemon protocol
  3. rexec/rsh network logins set up without passwords

Not only that but ‘Moris Worm’ was the first worm which used a list of popular passwords as a dictionary attack and used simple ‘Xoring’ encryption method to hide password and other strings (Ivey, 2018). According to the security experts, ‘Moris worm’ started from MIT computers and hid, back tracking by unlinking after affecting other networks on the internet. Even though the worm did not include malicious payload, worm caused serious damages to the infected systems as the infected systems tried to spread the worm. Because of this, infected networks slowed down and some systems, which depended on Sun OS, variant of Linux and Solaris, crashed due to the heavy load. At the same time, Morris had included sets of codes to spread fast and finally he had realized the worm was no longer in his control (Vaughan-Nichols, 2018). Out of control the worm started wave after wave of computer and system attacks.

Morris worm spread fast in 1988 when internet was small and people thought it was a very friendly place. Many other organizations, including the U.S. Department of Defense, had to unplug, internet cables to prevent worm infection (Marsan, 2008).

输入图片说明

Morris Worm Source Code

CERT

Because of the damages occurred by ‘Morris worm’ attack, an independent response team named CERT was created at Carnegie Mellon University, which was funded by the US Department of Defense’s Defense Advanced Research Projects Agency (DARPA). CERT security expert teams had to identify and address potential security threats, risks while consulting vendors, and independent security response teams around the world.

What happen to creator of ‘Morris’?

In 1991, Morris was sentenced to a three-year probation with 400 hours of community service and a $10,000 fine. Further, Morris was the first person who was tried and convicted of violating the 1986 Computer Fraud and Abuse Act.

After completing his sentence Morris founded two companies and one of his companies were sold to a search giant Yahoo Inc. Morris continued his computer network architectures at Massachusetts Institute of Technology as a professor (Ivey, 2018).

In 1988, when the worm was launched, there was not much commercial traffic or web sites in the internet. Since then, worm damages were limited to government agencies, universities and organizations that used internet networks to exchange e-mails and files.

Modern attackers

Today, crashing the internet is not profitable for attackers. Therefore modern cyber attackers are trickier when attacking systems, they gather information from affected computers, display ads etc.

‘Morris Worm’ made cyber security a legitimate topic among cyber security communities. In early days of computer security, only a few people worked on cyber security and all of them were cryptographers. After ‘Morris Worm’, security experts started to pay much more attention to cyber security as a field of study.

输入图片说明

Dinesh Abeywickrama Ph.D.(reading), MBCS, MBA, BCS

输入图片说明

**Inoshi Ratnasekera MBA, BS.c (Hons) **

References

Ivey, J.M., 2018. The Morris Worm Turns 30. [Online] Available at: https://www.globalknowledge.com/blog/2018/11/01/the-morris-worm-turns-25/ [Accessed 01 November 2018].

Marsan, C.D., 2008. Morris worm turns 20: Look what it’s done. [Online] Available at: https://www.networkworld.com/article/2268919/lan-wan/morris-worm-turns-20–look-what-it-sdone.html [Accessed 23 November 2018].

Vaughan-Nichols, J., 2018. The day computer security turned real: The Morris Worm turns 30. [Online] Available at: https://www.zdnet.com/article/the-day-computer-security-turned-real-the-morris-wormturns-30/ [Accessed 23 November 2018].

Title Intro
1.1 课程内容简介 大家好,欢迎来到6.S081 --- 操作系统这门课程。我的名字叫Robert,我会与Frans一起讲这门课。David,Nicholas会作为这门课程的助教。在我们在线授课的过程中,请尽情提问。你可以直接语音打断我,或者通过聊天窗口提问,我们工作人员会关注聊天窗口。顺便说一下,我们也会通过视频录制这门课程,之后我们会…
1.2 操作系统结构 过去几十年,人们将一些分层的设计思想加入到操作系统中,并运行的很好。我将会为你列出操作系统经典的组织结构,这个组织结构同时也是这门课程的主要内容,这里的组织结构对于操作系统来说还是挺常见的。 这里实际上就是操作系统内部组成,当我想到这里的组织结构时,我首先会想到用一个矩形表示一个计算机,这个计算机有一些硬件资源,我会将它…
1.3 Why Hard and Interesting 我还想说一下为什么我认为学习操作系统是挑战和乐趣并存的?以及为什么我们需要专门针对操作系统设置一门课程? 学习操作系统比较难的一个原因是,内核的编程环境比较困难。当你在编写、修改,扩展内核,或者写一个新的操作系统内核时,你实际上在提供一个基础设施让别人来运行他们的程序。当程序员在写普通的应用程序时,应用程序下面都是操作系…
1.4 课程结构和资源 接下来,我将花几分钟来介绍6.s081这门课程的结构,之后我们再来介绍具体的技术内容。 课程有一个网站,可以通过google查询6.s081找到。网站上会有课程的计划,lab的内容,课程结构的信息,例如最后是怎么打分的。 另一个资源是Piazza,它主要用来做两件事情,第一件是人们可以在上面咨询有关lab的问题,助教们会尝…
1.5 read, write, exit系统调用 接下来,我将讨论对于应用程序来说,系统调用长成什么样。因为系统调用是操作系统提供的服务的接口,所以系统调用长什么样,应用程序期望从系统调用得到什么返回,系统调用是怎么工作的,这些还是挺重要的。你会在第一个lab中使用我们在这里介绍的系统调用,并且在后续的lab中,扩展并提升这些系统调用的内部实现。 我接下来会展示一些简单…
1.6 open系统调用 前面,copy代码假设文件描述符已经设置好了。但是一般情况下,我们需要能创建文件描述符,最直接的创建文件描述符的方法是open系统调用。下面是一个叫做open的源代码,它使用了open系统调用。 学生提问:字节流是什么意思? Robert教授:我。。。我的意思是,如果一个文件包含了一些字节,假设包含了数百万个字节,你触发了…
1.7 Shell 我说了很多XV6的长的很像Unix的Shell,相对图形化用户接口来说,这里的Shell通常也是人们说的命令行接口。如果你还没有用过Shell,Shell是一种对于Unix系统管理来说非常有用的接口,它提供了很多工具来管理文件,编写程序,编写脚本。你之前看过我演示一些Shell的功能,通常来说,当你输入内容时,你是在告…
1.8 fork系统调用 下一个我想查看的例子叫做fork。fork会创建一个新的进程,下面是使用fork的一个简单用例。 在第12行,我们调用了fork。fork会拷贝当前进程的内存,并创建一个新的进程,这里的内存包含了进程的指令和数据。之后,我们就有了两个拥有完全一样内存的进程。fork系统调用在两个进程中都会返回,在原始的进程中,fork系…
1.9 exec, wait系统调用 在接下来我展示的一个例子中,会使用echo,echo是一个非常简单的命令,它接收任何你传递给它的输入,并将输入写到输出。 我为你们准备了一个文件名为exec的代码, 代码会执行exec系统调用,这个系统调用会从指定的文件中读取并加载指令,并替代当前调用进程的指令。从某种程度上来说,这样相当于丢弃了调用进程的内存,并开始执行…
1.10 I/O Redirect 最后一个例子,我想展示一下将所有这些工具结合在一起,来实现I/O重定向。 我们之前讲过,Shell提供了方便的I/O重定向工具。如果我运行下面的指令, Shell会将echo的输出送到文件out。之后我们可以运行cat指令,并将out文件作为输入, 我们可以看到保存在out文件中的内容就是echo指令的输出。 Shell之所以…
Title Intro
3.1 上一节课回顾 这节课的内容是操作系统的组织结构。今天我们主要讨论4个话题: Isolation。隔离性是设计操作系统组织结构的驱动力。 Kernel和User mode。这两种模式用来隔离操作系统内核和用户应用程序。 System calls。系统调用是你的应用程序能够转换到内核执行的基本方法,这样你的用户态应用程序才能使用内核服务。 最后…
3.2 操作系统隔离性(isolation) 我们首先来简单的介绍一下隔离性(isolation),以及介绍为什么它很重要,为什么我们需要关心它? 这里的核心思想相对来说比较简单。我们在用户空间有多个应用程序,例如Shell,echo,find。但是,如果你通过Shell运行你们的Prime代码(lab1中的一个部分)时,假设你们的代码出现了问题,Shell不应该会…
3.3 操作系统防御性(Defensive) 现在我们有一个操作系统,并且有一些应用程序正在运行。这里有一件事情需要考虑:操作系统应该具有防御性(Defensive)。 当你在做内核开发时,这是一种你需要熟悉的重要思想。操作系统需要确保所有的组件都能工作,所以它需要做好准备抵御来自应用程序的攻击。如果说应用程序无意或者恶意的向系统调用传入一些错误的参数就会导致操作系…
3.4 硬件对于强隔离的支持 硬件对于强隔离的支持包括了:user/kernle mode和虚拟内存。 首先,我们来看一下user/kernel mode,这里会以尽可能全局的视角来介绍,有很多重要的细节在这节课中都不会涉及。为了支持user/kernel mode,处理器会有两种操作模式,第一种是user mode,第二种是kernel mode。…
3.5 User/Kernel mode切换 我们可以认为user/kernel mode是分隔用户空间和内核空间的边界,用户空间运行的程序运行在user mode,内核空间的程序运行在kernel mode。操作系统位于内核空间。 你们应该将这张图记在你们的脑子中。但是基于我们已经介绍的内容,这张图有点太过严格了。因为我们用矩形包括了一个程序的所有部分,但是这里没…
3.6 宏内核 vs 微内核 (Monolithic Kernel vs Micro Kernel) 现在,我们有了一种方法,可以通过系统调用或者说ECALL指令,将控制权从应用程序转到操作系统中。之后内核负责实现具体的功能并检查参数以确保不会被一些坏的参数所欺骗。所以内核有时候也被称为可被信任的计算空间(Trusted Computing Base),在一些安全的术语中也被称为TCB。 基本上来说,要被称为TCB,内核…
3.7 编译运行kernel 接下来我会切换到代码介绍,来看一下XV6是如何工作的。 首先,我们来看一下代码结构,你们或许已经看过了。代码主要有三个部分组成: 第一个是kernel。我们可以ls kernel的内容,里面包含了基本上所有的内核文件。因为XV6是一个宏内核结构,这里所有的文件会被编译成一个叫做kernel的二进制文件,然后这个二进制文件会…
3.8 QEMU QEMU表现的就像一个真正的计算机一样。当你想到QEMU时,你不应该认为它是一个C程序,你应该把它想成是下图,一个真正的主板。 图中是一个我办公室中的RISC-V主板,它可以启动一个XV6。当你通过QEMU来运行你的内核时,你应该认为你的内核是运行在这样一个主板之上。主板有一个开关,一个RISC-V处理器,有支持外设的空…
3.9 XV6 启动过程 接下来,我会系统的介绍XV6,让你们对XV6的结构有个大概的了解。在后面的课程,我们会涉及到更多的细节。 首先,我会启动QEMU,并打开gdb。本质上来说QEMU内部有一个gdb server,当我们启动之后,QEMU会等待gdb客户端连接。 我会在我的计算机上再启动一个gdb客户端,这里是一个RISC-V 64位Linu…
Title Intro
4.1 Lec04内容简介 今天的主题是虚拟内存(Virtual Memory)。具体来说,我们会介绍页表(page tables)。在后面的课程中,我们还会介绍虚拟内存相关的其他内容。 首先,我们会从一些问答开始今天的课程。我想问你们还记得课程6.004和课程6.033中虚拟内存的内容吗?我先来说一下我自己对于虚拟内存或者页表的认知吧。当我还是个…
4.2 地址空间(Address Spaces) 在课程最开始的回答中,很多同学都提到了,创造虚拟内存的一个出发点是你可以通过它实现隔离性。如果你正确的设置了page table,并且通过代码对它进行正确的管理,那么原则上你可以实现强隔离。所以,我们先来回顾一下,我们期望从隔离性中得到什么样的效果。 在我们一个常出现的图中,我们有一些用户应用程序比如说Shell,cat…
4.3 页表(Page Table) 我们如何能够实现地址空间呢?或者说如何在一个物理内存上,创建不同的地址空间? 最常见的方法,同时也是非常灵活的一种方法就是使用页表(Page Tables)。页表是在硬件中通过处理器和内存管理单元(Memory Management Unit)实现。所以,在你们的脑海中,应该有这么一张图:CPU正在执行指令,例如sd $…
4.4 页表缓存(Translation Lookaside Buffer) 如果我们回想一下page table的结构,你可以发现,当处理器从内存加载或者存储数据时,基本上都要做3次内存查找,第一次在最高级的page directory,第二次在中间级的page directory,最后一次在最低级的page directory。所以对于一个虚拟内存地址的寻址,需要读三次内存,这里代价有点高。…
4.5 Kernel Page Table 接下来,我们看一下在XV6中,page table是如何工作的?首先我们来看一下kernel page的分布。下图就是内核中地址的对应关系,左边是内核的虚拟地址空间,右边上半部分是物理内存或者说是DRAM,右边下半部分是I/O设备。接下来我会首先介绍右半部分,然后再介绍左半部分。 图中的右半部分的结构完全由硬件设计者决定…
4.6 kvminit 函数 接下来,让我们看一看代码,我认为很多东西都会因此变得更加清晰。 首先,我们来做一个的常规操作,启动我们的XV6,这里QEMU实现了主板,同时我们打开gdb。 上一次我们看了boot的流程,我们跟到了main函数。main函数中调用的一个函数是kvminit(3.9),这个函数会设置好kernel的地址空间。kvminit的…
4.7 kvminithart 函数 之后,kvminit函数返回了,在main函数中,我们运行到了kvminithart函数。 这个函数首先设置了SATP寄存器,kernel_pagetable变量来自于kvminit第一行。所以这里实际上是内核告诉MMU来使用刚刚设置好的page table。当这里这条指令执行之后,下一个指令的地址会发生什么? 在这条指令…
4.8 walk 函数 学生提问:我对于walk函数有个问题,从代码看它返回了最高级page table的PTE,但是它是怎么工作的呢?(注,应该是学生理解有误,walk函数模拟了MMU,返回的是va对应的最低级page table的PTE) Frans教授:这个函数会返回page table的PTE,而内核可以读写PTE。我来画个图,首先我们…
Title Intro
5.1 C程序到汇编程序的转换 (00:00 - 05:25 在讨论syscall lab,没有什么实质内容故跳过) 今天的课程,我们会稍微讨论C语言转换到汇编语言的过程,以及处理器相关的内容。今天的课程更多偏向的是实际应用,或者至少我们的目标是这样。所以这节课的目标是让你们熟悉RISC-V处理器,汇编语言,以及RISC-V的calling conve…
5.2 RISC-V vs x86 你们将会注意到,我们在这节课中反复会提到了RISC-V汇编。这一点很重要,因为汇编语言有很多种(注,因为不同的处理器指令集不一样,而汇编语言中都是一条条指令,所以不同处理器对应的汇编语言必然不一样)。如果你使用RISC-V,你不太能将Linux运行在上面。相应的,大多数现代计算机都运行在x86和x86-64处理器上。x…
5.3 gdb和汇编代码执行 接下来我们来看一些真实的汇编代码。 图中的代码,上半部分的注释是对应的C代码,这是个简单的函数,它累加了从1到n的所有数字,并返回结果。下半部分是可以编译出的最简单的汇编代码。如果你在你自己的计算机编写同样的C代码并编译,你得到的极有可能是差别较大的汇编代码。这里有很多原因,有一些原因我们之后会讲,有一些原因是因为编译器…
5.4 RISC-V寄存器 我们之前看过了汇编语言和RISC-V的介绍。接下来我们看一下之后lab相关的内容。这部分的内容其实就是本节课的准备材料中的内容。 你们现在对于这个表达应该都很熟悉了,这个表里面是RISC-V寄存器。寄存器是CPU或者处理器上,预先定义的可以用来存储数据的位置。寄存器之所以重要是因为汇编代码并不是在内存上执行,而是在寄存器…
5.5 Stack 接下来我们讨论一下栈,stack。栈之所以很重要的原因是,它使得我们的函数变得有组织,且能够正常返回。 下面是一个非常简单的栈的结构图,其中每一个区域都是一个Stack Frame,每执行一次函数调用就会产生一个Stack Frame。 每一次我们调用一个函数,函数都会为自己创建一个Stack Frame,并且只给自己用。…
5.6 Struct 今天我想讨论的最后一个话题是struct,stuct非常重要并且在课程的实验中会经常出现。我会稍微介绍一下struct在内存中的结构是怎样。基本上来说,struct在内存中是一段连续的地址,如果我们有一个struct,并且有f1,f2,f3三个字段。 当我们创建这样一个struct时,内存中相应的字段会彼此相邻。你可以认…
Title Intro
6.1 Trap机制 今天我想讨论一下,程序运行是如何完成用户空间和内核空间的切换。每当 程序执行系统调用 程序出现了类似page fault、运算时除以0的错误 一个设备触发了中断使得当前程序运行需要响应内核设备驱动 都会发生这样的切换 。 这里用户空间和内核空间的切换通常被称为trap,而trap涉及了许多小心的设计和重要的细节,这些细节对于实现…
6.2 Trap代码执行流程 我首先会简单介绍一下trap代码的执行流程,但是这节课大部分时间都会通过gdb来跟踪代码是如何通过trap进入到内核空间,这里会涉及到很多的细节。为了帮助你提前了解接下来的内容,我们会跟踪如何在Shell中调用write系统调用。从Shell的角度来说,这就是个Shell代码中的C函数调用,但是实际上,write通过执…
6.3 ECALL指令之前的状态 接下来,我将切换到gdb的世界中。 大家可以看我共享的屏幕,我们将要跟踪一个XV6的系统调用,也就是Shell将它的提示信息通过write系统调用走到操作系统再输出到console的过程。你们可以看到,用户代码sh.c初始了这一切。 上图中选中的行,是一个write系统调用,它将“$ ”写入到文件描述符2。接下来我将打开…
6.4 ECALL指令之后的状态 现在我执行ecall指令, 第一个问题,执行完了ecall之后我们现在在哪?我们可以打印程序计数器(Program Counter)来查看。 可以看到程序计数器的值变化了,之前我们的程序计数器还在一个很小的地址0xde6,但是现在在一个大得多的地址。 我们还可以查看page table,我通过在QEMU中执行info mem…
6.5 uservec函数 回到XV6和RISC-V,现在程序位于trampoline page的起始,也是uservec函数的起始。我们现在需要做的第一件事情就是保存寄存器的内容。在RISC-V上,如果不能使用寄存器,基本上不能做任何事情。所以,对于保存这些寄存器,我们有什么样的选择呢? 在一些其他的机器中,我们或许直接就将32个寄存器中的内容写…
6.6 usertrap函数 usertrap函数是位于trap.c文件的一个函数。 既然我们已经运行在C代码中,接下来,我在gdb中输入tui enable打开对于C代码的展示。 我们现在在一个更加正常的世界中,我们正在运行C代码,应该会更容易理解。我们仍然会读写一些有趣的控制寄存器,但是环境比起汇编语言来说会少了很多晦涩。 有很多原因都可以让程序运行…
6.7 usertrapret函数 usertrap函数的最后调用了usertrapret函数,来设置好我之前说过的,在返回到用户空间之前内核要做的工作。我们可以查看这个函数的内容。 它首先关闭了中断。我们之前在系统调用的过程中是打开了中断的,这里关闭中断是因为我们将要更新STVEC寄存器来指向用户空间的trap处理代码,而之前在内核中的时候,我们指向的是…
6.8 userret函数 现在程序执行又到了trampoline代码。 第一步是切换page table。在执行csrw satp, a1之前,page table应该还是巨大的kernel page table。这条指令会将user page table(在usertrapret中作为第二个参数传递给了这里的userret函数,所以存在a1寄存…
Title Intro
8.1 Page Fault Basics 今天的课程内容是page fault,以及通过page fault可以实现的一些列虚拟内存功能。这里相关的功能有: lazy allocation,这是下一个lab的内容 copy-on-write fork demand paging memory mapped files 你懂的,几乎所有稍微正经的操作系统都实现了这些功能。…
8.2 Lazy page allocation 我们首先来看一下内存allocation,或者更具体的说sbrk。sbrk是XV6提供的系统调用,它使得用户应用程序能扩大自己的heap。当一个应用程序启动的时候,sbrk指向的是heap的最底端,同时也是stack的最顶端。这个位置通过代表进程的数据结构中的sz字段表示,这里以p->sz表示。 当调用sbrk时,…
8.3 Zero Fill On Demand 接下来我将讨论基于page fault和page table可以做的一些其他酷的事情。另一个简单但是使用的非常频繁的功能是zero-fill-on-demand。 当你查看一个用户程序的地址空间时,存在text区域,data区域,同时还有一个BSS区域(注,BSS区域包含了未被初始化或者初始化为0的全局或者静态变量)。当…
8.4 Copy On Write Fork 下一个是一个非常常见的优化,许多操作系统都实现了它,同时它也是后面一个实验的内容。这就是copy-on-write fork,有时也称为COW fork。 当Shell处理指令时,它会通过fork创建一个子进程。fork会创建一个Shell进程的拷贝,所以这时我们有一个父进程(原来的Shell)和一个子进程。Shell的…
8.5 Demand Paging 接下来我们将介绍Demand paging。这是另一个非常流行的功能,许多操作系统都实现了它。 我们回到exec,在未修改的XV6中,操作系统会加载程序内存的text,data区域,并且以eager的方式将这些区域加载进page table。 但是根据我们在lazy allocation和zero-filled on de…
8.6 Memory Mapped Files 这节课最后要讨论的内容,也是后面的一个实验,就是memory mapped files。这里的核心思想是,将完整或者部分文件加载到内存中,这样就可以通过内存地址相关的load或者store指令来操纵文件。为了支持这个功能,一个现代的操作系统会提供一个叫做mmap的系统调用。这个系统调用会接收一个虚拟内存地址(VA),长…
Title Intro
9.1 真实操作系统内存使用情况 (00:00 - 03:32 在对前两个lab提问,与内容无关故跳过) 今天课程的内容是中断。但是在具体介绍中断之前,我想先回顾一下上周一些有趣的内容。因为上周的课程主要是讲内存,我们收到了很多内存相关的问题。我想先讨论一下内存是如何被真实的操作系统(而不是像XV6这样的教学操作系统)所使用。 下图是一台Athena计算机…
9.2 Interrupt硬件部分 今天课程的主要内容是中断。中断对应的场景很简单,就是硬件想要得到操作系统的关注。例如网卡收到了一个packet,网卡会生成一个中断;用户通过键盘按下了一个按键,键盘会产生一个中断。操作系统需要做的是,保存当前的工作,处理中断,处理完成之后再恢复之前的工作。这里的保存和恢复工作,与我们之前看到的系统调用过程(注,详见le…
9.3 设备驱动概述 通常来说,管理设备的代码称为驱动,所有的驱动都在内核中。我们今天要看的是UART设备的驱动,代码在uart.c文件中。如果我们查看代码的结构,我们可以发现大部分驱动都分为两个部分,bottom/top。 bottom部分通常是Interrupt handler。当一个中断送到了CPU,并且CPU设置接收这个中断,CPU会…
9.4 在XV6中设置中断 当XV6启动时,Shell会输出提示符“$ ”,如果我们在键盘上输入ls,最终可以看到“$ ls”。我们接下来通过研究Console是如何显示出“$ ls”,来看一下设备中断是如何工作的。 实际上“$ ”和“ls”还不太一样,“$ ”是Shell程序的输出,而“ls”是用户通过键盘输入之后再显示出来的。 对于“$ ”来说,…
9.5 UART驱动的top部分 接下来我想看一下如何从Shell程序输出提示符“$ ”到Console。首先我们看init.c中的main函数,这是系统启动后运行的第一个进程。 首先这个进程的main函数创建了一个代表Console的设备。这里通过mknod操作创建了console设备。因为这是第一个打开的文件,所以这里的文件描述符0。之后通过dup创…
9.6 UART驱动的bottom部分 在我们向Console输出字符时,如果发生了中断,RISC-V会做什么操作?我们之前已经在SSTATUS寄存器中打开了中断,所以处理器会被中断。假设键盘生成了一个中断并且发向了PLIC,PLIC会将中断路由给一个特定的CPU核,并且如果这个CPU核设置了SIE寄存器的E bit(注,针对外部中断的bit位),那么会发生…
9.7 Interrupt相关的并发 接下来我们讨论一下与中断相关的并发,并发加大了中断编程的难度。这里的并发包括以下几个方面: 设备与CPU是并行运行的。例如当UART向Console发送字符的时候,CPU会返回执行Shell,而Shell可能会再执行一次系统调用,向buffer中写入另一个字符,这些都是在并行的执行。这里的并行称为producer-con…
9.8 UART读取键盘输入 在UART的另一侧,会有类似的事情发生,有时Shell会调用read从键盘中读取字符。 在read系统调用的底层,会调用fileread函数。在这个函数中,如果读取的文件类型是设备,会调用相应设备的read函数。 在我们的例子中,read函数就是console.c文件中的consoleread函数。 这里与UART类似,也…
9.9 Interrupt的演进 最后我想介绍一下Interrupt在最近几十年的演进。当Unix刚被开发出来的时候,Interrupt处理还是很快的。这使得硬件可以很简单,当外设有数据需要处理时,硬件可以中断CPU的执行,并让CPU处理硬件的数据。 而现在,中断相对处理器来说变慢了。从前面的介绍可以看出来这一点,需要很多步骤才能真正的处理中断数据。如果…
Title Intro
10.1 为什么要使用锁? (00:00 - 01:33)是上一个lab的抽查问答,与内容无关故跳过。 今天的课程的内容是锁。这节课偏向于理论介绍,并且或许会与其他课程中有关锁的内容有些重合,不过这节课更关注在内核和操作系统中使用的锁。 首先,我们来看一下为什么我们需要锁?故事要从应用程序想要使用多个CPU核开始。使用多个CPU核可以带来性能的提升,…
10.2 锁如何避免race condition? 首先你们在脑海里应该有多个CPU核在运行,比如说CPU0在运行指令,CPU1也在运行指令,这两个CPU核都连接到同一个内存上。在前面的代码中,数据freelist位于内存中,它里面记录了2个内存page。假设两个CPU核在相同的时间调用kfree。 kfree函数接收一个物理地址pa作为参数,freelist是个单链表,…
10.3 什么时候使用锁? 很明显,锁限制了并发性,也限制了性能。那这带来了一个问题,什么时候才必须要加锁呢?我这里会给你们一个非常保守同时也是非常简单的规则:如果两个进程访问了一个共享的数据结构,并且其中一个进程会更新共享的数据结构,那么就需要对于这个共享的数据结构加锁。 这是个保守的规则,如果一个数据结构可以被多个进程访问,其中一个进程会更新这…
10.4 锁的特性和死锁 通常锁有三种作用,理解它们可以帮助你更好的理解锁。 锁可以避免丢失更新。如果你回想我们之前在kalloc.c中的例子,丢失更新是指我们丢失了对于某个内存page在kfree函数中的更新。如果没有锁,在出现race condition的时候,内存page不会被加到freelist中。但是加上锁之后,我们就不会丢失这里的更新…
10.5 锁与性能 我们前面已经看过了两类锁带来的挑战,一个是死锁,另一个是破坏了程序的模块化。这一部分来看看第三个挑战,也就是锁与性能之间的权衡。我们前面已经提过几次锁对性能的影响,但是因为这部分太重要了,我们再来详细的看一下。 基本上来说,如果你想获得更高的性能,你需要拆分数据结构和锁。如果你只有一个big kernel lock,那么…
10.6 XV6中UART模块对于锁的使用 接下来我们看一下XV6的代码,通过代码来理解锁是如何在XV6中工作的。我们首先查看一下uart.c,在上节课介绍中断的时候我们提到了这里的锁,现在我们具体的来看一下。因为现在我们对锁更加的了解了,接下来将展示一些更有趣的细节。 从代码上看UART只有一个锁。 所以你可以认为对于UART模块来说,现在是一个coarse-gr…
10.7 自旋锁(Spin lock)的实现(一) 接下来我们看一下如何实现自旋锁。锁的特性就是只有一个进程可以获取锁,在任何时间点都不能有超过一个锁的持有者。我们接下来看一下锁是如何确保这里的特性。 我们先来看一个有问题的锁的实现,这样我们才能更好的理解这里的挑战是什么。实现锁的主要难点在于锁的acquire接口,在acquire里面有一个死循环,循环中判断锁对象的lo…
10.8 自旋锁(Spin lock)的实现(二) 有关spin lock的实现,有3个细节我想介绍一下。 首先,有很多同学提问说为什么release函数中不直接使用一个store指令将锁的locked字段写为0?有人想回答一下为什么吗? 学生回答:因为其他的处理器可能会向locked字段写入1,或者写入0。。。 是的,可能有两个处理器或者两个CPU同时在向locked字段写…
Title Intro
11.1 线程(Thread)概述 我们今天的课程会讨论线程以及XV6如何实现线程切换。今天这节课与之前介绍的系统调用,Interrupt,page table和锁的课程一样,都是有关XV6底层实现的课程。今天我们将讨论XV6如何在多个线程之间完成切换。 为什么计算机需要运行多线程?可以归结为以下原因: 首先,人们希望他们的计算机在同一时间不是只执行一个任务…
11.2 XV6线程调度 实现内核中的线程系统存在以下挑战: 第一个是如何实现线程间的切换。这里停止一个线程的运行并启动另一个线程的过程通常被称为线程调度(Scheduling)。我们将会看到XV6为每个CPU核都创建了一个线程调度器(Scheduler)。 第二个挑战是,当你想要实际实现从一个线程切换到另一个线程时,你需要保存并恢复线程的状态,所…
11.3 XV6线程切换(一) 接下来我将通过两张图来介绍XV6中的线程切换是如何实现的,其中一张图是简单的,另一张图包含了更多的细节,这一小节先看简单的图。 我们或许会运行多个用户空间进程,例如C compiler(CC),LS,Shell,它们或许会,也或许不会想要同时运行。在用户空间,每个进程有自己的内存,对于我们这节课来说,我们更关心的是每个进…
11.4 XV6线程切换(二) 实际的线程切换流程会复杂的多。 假设我们有进程P1正在运行,进程P2是RUNABLE当前并不在运行。假设在XV6中我们有2个CPU核,这意味着在硬件层面我们有CPU0和CPU1。 我们从一个正在运行的用户空间进程切换到另一个RUNABLE但是还没有运行的用户空间进程的更完整的故事是: 首先与我之前介绍的一样,一个定时器中断强…
11.5 XV6进程切换示例程序 接下来,我们切换到代码并展示一下刚刚介绍的内容。我们先来看一下proc.h中的proc结构体,从结构体中我们可以看到很多之前介绍的内容。 首先是保存了用户空间线程寄存器的trapframe字段 其次是保存了内核线程寄存器的context字段 还有保存了当前进程的内核栈的kstack字段,这是进程在内核中执行时保存函数调用的位…
11.6 XV6线程切换 --- yield/sched函数 回到devintr函数返回到usertrap函数中的位置。在gdb里面输入几次step走到yield函数的调用。yield函数是整个线程切换的第一步,下面是yield函数的内容: yield函数只做了几件事情,它首先获取了进程的锁。实际上,在锁释放之前,进程的状态会变得不一致,例如,yield将要将进程的状态改为RUNA…
11.7 XV6线程切换 --- switch函数 switch函数会将当前的内核线程的寄存器保存到p->context中。switch函数的另一个参数c->context,c表示当前CPU的结构体。CPU结构体中的context保存了当前CPU核的调度器线程的寄存器。所以switch函数在保存完当前内核线程的内核寄存器之后,就会恢复当前CPU核的调度器线程…
11.8 XV6线程切换 --- scheduler函数 来看一下scheduler的完整代码, 现在我们正运行在CPU拥有的调度器线程中,并且我们正好在之前调用switch函数的返回状态。之前调度器线程调用switch是因为想要运行pid为3的进程,也就是刚刚被中断的spin程序。 虽然pid为3的spin进程也调用了switch函数,但是那个switch并不是当前返回的这个s…
11.9 XV6线程第一次调用switch函数 (注,首先是学生提问Linux内一个进程多个线程的实现方式,因为在XV6中,一个进程只有一个用户线程) 学生提问:操作系统都带了线程的实现,如果想要在多个CPU上运行一个进程内的多个线程,那需要通过操作系统来处理而不是用户空间代码,是吧?那这里的线程切换是怎么工作的?是每个线程都与进程一样了吗?操作系统还会遍历所有存在的…
Title Intro
13.1 线程切换过程中锁的限制 今天这节课中,首先我们会花几分钟来重温一下上节课,也就是线程切换的内容,因为有些内容对于这节课来说还挺重要的。之后我们大部分时间都会讨论coordination,XV6通过Sleep&Wakeup实现了coordination。最后我们会讨论lost wake-up的问题。 首先是上节课的回顾。在XV6中,任何时…
13.2 Sleep&Wakeup 接口 接下来看一下通过Sleep&Wakeup实现Coordination。 我们听过很多关于锁的介绍,锁可以使得线程本身不必关心其他线程的具体实现。我们为共享的数据增加锁,这样就不用担心其他线程也使用了相同的数据,因为锁可以确保对于数据的操作是依次发生的。 当你在写一个线程的代码时,有些场景需要等待一些特定的事件,或者…
13.3 Lost wakeup 在解释sleep函数为什么需要一个锁使用作为参数传入之前,我们先来看看假设我们有了一个更简单的不带锁作为参数的sleep函数,会有什么样的结果。这里的结果就是lost wakeup。 假设sleep只是接收任意的sleep channel作为唯一的参数。它其实不能正常工作,我们称这个sleep实现为broken_slee…
13.4 如何避免Lost wakeup 现在我们的目标是消灭掉lost wakeup。这可以通过消除下面的窗口时间来实现。 首先我们必须要释放uart_tx_lock锁,因为中断需要获取这个锁,但是我们又不能在释放锁和进程将自己标记为SLEEPING之间留有窗口。这样中断处理程序中的wakeup才能看到SLEEPING状态的进程,并将其唤醒,进而我们才可以避免…
13.5 Pipe中的sleep 和wakeup 前面我们介绍了在UART的驱动中,如何使用sleep和wakeup才能避免lost wakeup。前面这个特定的场景中,sleep等待的condition是发生了中断并且硬件准备好了传输下一个字符。在一些其他场景,内核代码会调用sleep函数并等待其他的线程完成某些事情。这些场景从概念上来说与我们介绍之前的场景没有什么…
13.6 exit系统调用 接下来,我想讨论一下XV6面临的一个与Sleep&Wakeup相关的挑战,也就是如何关闭一个进程。每个进程最终都需要退出,我们需要清除进程的状态,释放栈。在XV6中,一个进程如果退出的话,我们需要释放用户内存,释放page table,释放trapframe对象,将进程在进程表单中标为REUSABLE,这些都是…
13.7 wait系统调用 通过Unix的exit和wait系统调用的说明,我们可以知道如果一个进程exit了,并且它的父进程调用了wait系统调用,父进程的wait会返回。wait函数的返回表明当前进程的一个子进程退出了。所以接下来我们看一下wait系统调用的实现。 它里面包含了一个大的循环。当一个进程调用了wait系统调用,它会扫描进程表单,找…
13.8 kill系统调用 最后我想看的是kill系统调用。Unix中的一个进程可以将另一个进程的ID传递给kill系统调用,并让另一个进程停止运行。如果我们不够小心的话,kill一个还在内核执行代码的进程,会有一些我几分钟前介绍过的风险,比如我们想要杀掉的进程的内核线程还在更新一些数据,比如说更新文件系统,创建一个文件。如果这样的话,我们不能就…
Title Intro
14.1 Why Interesting 今天介绍的是文件系统。实际上我们会花三节课的时间来学习文件系统。前两节课基于XV6来做介绍,第三节课基于Linux来做介绍。实际上,这将是有关XV6的最后一个话题,在这周之后我们就讲完了XV6。 对于文件系统,你们都知道它并使用过它。它是操作系统中除了shell以外最常见的用户接口。所以我们希望通过这几节课来理解:文件系…
14.2 File system实现概述 为了理解文件系统必须提供什么能力,让我们再看一下一些与文件系统相关的基础系统调用。从这些系统调用接口,我们将可以推断出有关文件系统实现的一些细节,这些系统调用我们在之前的课程已经看过了。首先让我们来看一个简单的场景,假设我们创建了文件“x/y”,或者说在目录x中创建了文件y,同时我们需要提供一些标志位,现在我们还太关心…
14.3 How file system uses disk 接下来,我将简单的介绍最底层,也即是存储设备。实际中有非常非常多不同类型的存储设备,这些设备的区别在于性能,容量,数据保存的期限等。其中两种最常见,并且你们应该也挺熟悉的是SSD和HDD。这两类存储虽然有着不同的性能,但是都在合理的成本上提供了大量的存储空间。SSD通常是0.1到1毫秒的访问时间,而HDD通常是在10毫…
14.4 inode 接下来我们看一下磁盘上存储的inode究竟是什么?首先我们前面已经看过了,这是一个64字节的数据结构。 通常来说它有一个type字段,表明inode是文件还是目录。 nlink字段,也就是link计数器,用来跟踪究竟有多少文件名指向了当前的inode。 size字段,表明了文件数据有多少个字节。 不同文件系统中的表达方式可能不…
14.5 File system工作示例 接下来我们看一下实际中,XV6的文件系统是如何工作的,这部分内容对于下一个lab是有帮助的。 首先我会启动XV6,这里有件事情我想指出。启动XV6的过程中,调用了makefs指令,来创建一个文件系统。 所以makefs创建了一个全新的磁盘镜像,在这个磁盘镜像中包含了我们在指令中传入的一些文件。makefs为你创建了一个包含…
14.6 XV6创建inode代码展示 接下来我们通过查看XV6中的代码,更进一步的了解文件系统。因为我们前面已经分配了inode,我们先来看一下这是如何发生的。sysfile.c中包含了所有与文件系统相关的函数,分配inode发生在sys_open函数中,这个函数会负责创建文件。 在sys_open函数中,会调用create函数。 create函数中首先会解析…
14.7 Sleep Lock block cache使用的是sleep lock。sleep lock区别于一个常规的spinlock。我们先看来一下sleep lock。 首先是acquiresleep函数,它用来获取sleep lock。函数里首先获取了一个普通的spinlock,这是与sleep lock关联在一起的一个锁。之后,如果sleep…
Title Intro
15.1 File system crash概述 (00:00 - 06:23,是在对Lock lab提问,与本节课无关故略过) 今天的课程是有关文件系统中的Crash safety。这里的Crash safety并不是一个通用的解决方案,而是只关注一个特定的问题的解决方案,也就是crash或者电力故障可能会导致在磁盘上的文件系统处于不一致或者不正确状态的问题。当我说不…
15.2 File system crash示例 为了更清晰的理解这里的风险,让我们看一些基于XV6的例子,并看一下哪里可能出错。我们在上节课介绍了XV6有一个非常简单的文件系统和磁盘数据的排布方式。 在super block之后就是log block,我们今天主要介绍的就是log block。log block之后是inode block,每个block可能包含了多个…
15.3 File system logging 我们这节课要讨论的针对文件系统crash之后的问题的解决方案,其实就是logging。这是来自于数据库的一种解决方案。它有一些好的属性: 首先,它可以确保文件系统的系统调用是原子性的。比如你调用create/write系统调用,这些系统调用的效果是要么完全出现,要么完全不出现,这样就避免了一个系统调用只有部分写磁盘操作出…
15.4 log_write函数 接下来让我们看一些代码来帮助我们理解这里是怎么工作的。前面我提过事务(transaction),也就是我们不应该在所有的写操作完成之前写入commit record。这意味着文件系统操作必须表明事务的开始和结束。在XV6中,以创建文件的sys_open为例(在sysfile.c文件中)每个文件系统操作,都有begin_…
15.5 end_op函数 接下来我们看看位于log.c中的end_op函数中会发生什么? 可以看到,即使是这么简单的一个文件系统也有一些微秒的复杂之处,代码的最开始就是一些复杂情况的处理(注,15.8有这部分的解释)。我直接跳到正常且简单情况的代码。在简单情况下,没有其他的文件系统操作正在处理中。这部分代码非常简单直观,首先调用了commit函数…
15.6 File system recovering 接下来我们看一下发生在XV6的启动过程中的文件系统的恢复流程。当系统crash并重启了,在XV6启动过程中做的一件事情就是调用initlog函数。 initlog基本上就是调用recover_from_log函数。 recover_from_log先调用read_head函数从磁盘中读取header,之后调用install…
15.7 Log写磁盘流程 我已经在bwrite函数中加了一个print语句。bwrite函数是block cache中实际写磁盘的函数,所以我们将会看到实际写磁盘的记录。在上节课(Lec 14)我将print语句放在了log_write中,log_write只能代表文件系统操作的记录,并不能代表实际写磁盘的记录。我们这里会像上节课一样执行ech…
15.8 File system challenges 前面说到XV6的文件系统有一定的复杂性,接下来我将介绍一下三个复杂的地方或者也可以认为是三个挑战。 第一个是cache eviction。假设transaction还在进行中,我们刚刚更新了block 45,正要更新下一个block,而整个buffer cache都满了并且决定撤回block 45。在buffer cac…
Title Intro
16.1 Why logging 今天这节课也是讲解文件系统的logging,这节课讲的是Linux中的广泛使用的ext3文件系统所使用的logging系统,同时我们也会讨论在高性能文件系统中添加log需要面对的一些问题。首先我会花几分钟来回顾一下,为什么我们要学习logging。 之所以我们认为logging很重要,是因为这是一个巨大的成功和重要的思想…
16.2 XV6 File system logging回顾 首先来回顾一下XV6的logging系统。我们有一个磁盘用来存储XV6的文件系统,你可以认为磁盘分为了两个部分: 首先是文件系统目录的树结构,以root目录为根节点,往下可能有其他的目录,我们可以认为目录结构就是一个树状的数据结构。假设root目录下有两个子目录D1和D2,D1目录下有两个文件F1和F2,每个文件又包含了…
16.3 ext3 file system log format ext3文件系统就是基于今天要阅读的论文,再加上几年的开发得到的,并且ext3也曾经广泛的应用过。ext3是针对之前一种的文件系统(ext2)logging方案的修改,所以ext3就是在几乎不改变之前的ext2文件系统的前提下,在其上增加一层logging系统。所以某种程度来说,logging是一个容易升级的模块。 ex…
16.4 ext3如何提升性能 ext3通过3种方式提升了性能: 首先,它提供了异步的(asynchronous)系统调用,也就是说系统调用在写入到磁盘之前就返回了,系统调用只会更新缓存在内存中的block,并不用等待写磁盘操作。不过它可能会等待读磁盘。 第二,它提供了批量执行(batching)的能力,可以将多个系统调用打包成一个transaction…
16.5 ext3文件系统调用格式 接下来我们大概过一下Linux中的文件系统调用,并介绍抽象上每个系统调用的结构。 在Linux的文件系统中,我们需要每个系统调用都表明一些列写操作的开始和结束。实际上在任何transaction系统中,都需要明确的表示开始和结束,这样之间的所有内容都是原子的。所以系统调用中会调用start函数。ext3需要知道当前正在进…
16.6 ext3 transaction commit步骤 基于上面的系统调用的结构,接下来我将介绍commit transaction完整的步骤。每隔5秒,文件系统都会commit当前的open transaction,下面是commit transaction涉及到的步骤: 首先需要阻止新的系统调用。当我们正在commit一个transaction时,我们不会想要有新增的系统…
16.7 ext3 file system恢复过程 为了简化重启时恢复软件的工作,当决定释放某段log空间时,文件系统会更新super block中的指针将其指向当前最早的transaction的起始位置。 之后如果crash并重启,恢复软件会读取super block,并找到log的起始位置。所以如果crash了,内存中的所有数据都会消失,例如文件系统中记录的哪些blo…
16.8 为什么新transaction需要等前一个transaction中系统调用执行完成 以上就是ext3中相对来说直观的部分。实际上还有一些棘手的细节我想讨论一下。之前我提到过,ext3中存在一个open transaction,但是当ext3决定要关闭该transaction时,它需要等待该transaction中的所有系统调用都结束,之后才能开始新的transaction。假设我们现在有transac…
16.9 ext3总结 最后我希望同学们记住的有关logging和ext3的是: log是为了保证多个步骤的写磁盘操作具备原子性。在发生crash时,要么这些写操作都发生,要么都不发生。这是logging的主要作用。 logging的正确性由write ahead rule来保证。你们将会在故障恢复相关的业务中经常看到write ahead ru…
Title Intro
17.1 应用程序使用虚拟内存所需要的特性 今天的话题是用户应用程序使用的虚拟内存,它主要是受这篇1991年的论文的启发。 首先,你们已经知道了,操作系统内核以非常灵活的方式使用了虚拟内存Page Table。你们已经通过Lazy Allocation Lab,Copy on Write Lab,以及XV6中的各种内存实现了解到了这一点。而今天论文中的核心观点是,…
17.2 支持应用程序使用虚拟内存的系统调用 第一个或许也是最重要的一个,是一个叫做mmap的系统调用。它接收某个对象,并将其映射到调用者的地址空间中。举个例子,如果你想映射一个文件,那么你需要将文件描述符传递给mmap系统调用。mmap系统调用有许多令人眼花缭乱的参数(注,mmap的具体说明可以参考man page): 第一个参数是一个你想映射到的特定地址,如果传…
17.3 虚拟内存系统如何支持用户应用程序 有关实现,有两个方面较为有趣。 第一个是虚拟内存系统为了支持这里的特性,具体会发生什么?这里我们只会讨论最重要的部分,并且它也与即将开始的mmap lab有一点相关,因为在mmap lab中你们将要做类似的事情。在现代的Unix系统中,地址空间是由硬件Page Table来体现的,在Page Table中包含了地址翻译。…
17.4 构建大的缓存表 接下来,我将通过介绍几个例子来看一下如何使用之前介绍的内容。我会从一个非常简单的例子开始,之后我们会看一下Garbage Collector,因为很多同学都问了Garbage Collector的问题,所以GC是一个可以深入探讨的好话题。 首先我想讨论的是一个非常简单的应用,它甚至都没有在论文中提到,但它却是展示这节课的…
17.5 Baker's Real-Time Copying Garbage Collector 接下来我会讨论另一个例子,也就是Garbage Collector(注,后面将Garbage Collector和Garbage Collection都简称为GC),并且我也收到了很多有关Garbage Collector的问题。 GC是指编程语言替程序员完成内存释放,这样程序员就不用像在C语言中一样调用free来释放内…
17.6 使用虚拟内存特性的GC 论文中介绍,如果拥有了前面提到的虚拟内存特性,你可以使用虚拟内存来减少指针检查的损耗,并且以几乎零成本的代价来并行运行GC。这里的基本思想是将heap内存中from和to空间,再做一次划分,每一个部分包含scanned,unscanned两个区域。在程序启动,或者刚刚完成了from和to空间的切换时,整个空间都是uns…
17.7 使用虚拟内存特性的GC代码展示 为了更清晰的说明上一节的内容,我这里有个针对论文中方法的简单实现,我可以肯定它包含了一些bug,因为我并没有认真的测试它。 首先,应用程序使用的API包括了new和readptr。 readptr会检查指针是否位于from空间,如果是的话,那么它指向的对象需要被拷贝。当然,当我们使用虚拟内存时,这里的readptr成本会比…
Title Intro
18.1 Monolithic kernel 今天我主要会讨论微内核(Mircro kernel)。 我们来看一下为什么人们会研究微内核?微内核是人们在思考操作系统内核应该做什么事情的过程中设计出来的。比如说XV6是一个Unix系统,它按照Unix风格提供了各种功能,并提供了Unix系统调用。实现一个Unix系统就是我们设计XV6的目标。但是一个完全值得思考的问题是…
18.2 Micro kernel 有关微内核的很多思想可以回溯到计算机的发展历史中。微内核从1980年代中后期开始就是一个非常热门的研究课题,它是指一种通用的方法或者概念,它并不特指任何特定的产品。有很多人遵循微内核的设计思想并构建了操作系统,但是这些项目中的每一个具体的操作系统都与另一个非常不一样。 微内核的核心就是实现了IPC(Inter-Proce…
18.3 Why micro kernel? 人们构建微内核的动机是什么? 其中一个动机你可能不常看到,这就是审美(注,原话是sense of aesthetic)。我认为很多人都觉得像Linux内核这样大的复杂的程序并不十分优雅。我们肯定可以构建一些小得多且专注的多的设计,而不是这样一个巨大的拥有各种随机特性的集合体。所以从审美角度来说,我们必然可以做的比大的内核…
18.4 L4 micro kernel 今天要讨论的论文,有许多有关L4微内核的内容。这是今天论文作者开发和使用的一种微内核。L4必然不是最早的微内核,但是从1980年代开始,它是最早一批可以工作的微内核之一,并且它非常能展现微内核是如何工作的。在许多年里面它一直都有活跃的开发和演进。如果你查看Wikipedia,L4有15-20个变种,有一些从1980年代…
18.5 Improving IPC by Kernel Design 接下来我们讨论微内核里面一个非常重要的问题:IPC的速度。首先让我展示一个非常简单,但是也非常慢的设计。这个设计基于Unix Pipe。我之所以介绍这种方法,是因为一些早期的微内核以一种类似的方式实现的IPC,而这种方式实际上很慢。 假设我们有两个进程,P1和P2,P1想要给P2发送消息。这里该怎么工作呢?一种可能是使用…
18.6 Run Linux on top of L4 micro kernel 前一节对于IPC的优化使得人们开始认真考虑使用微内核替代monolithic kernel。然而,这里仍然有个问题,即使IPC很快了,操作系统的剩余部分从哪里去获取?现在的微内核大概只有一个完整操作系统的百分之几,我们该怎么处理操作系统剩下的部分?这个问题通常会在一些有着相对较少资源的学校研究项目中被问到,我们需要从某…
18.7 L4 Linux性能分析 你应该问自己:通过论文可以学到有关微内核的什么内容呢? 对于我们来说,论文中有很多有趣的有关微内核是如何运行,有关Linux是如何运行的小的知识点,以及你该如何设计这么一个系统。但是论文并没有回答这个问题:微内核是不是一个好的设计?论文只是讨论了微内核是否有足够的性能以值得使用。 论文之所以讨论这个内容的原因是,在论文发表…
Title Intro
19.1 Why Virtual Machine? 今天讨论的话题是虚拟机。今天的内容包含三个部分: 第一个部分是Trap and Emulate,这部分会介绍如何在RISC-V或者QEMU上构建属于自己的Virtual Machine Monitor(注,有些场合也称为Hypervisor)。 第二部分会描述最近在硬件上对于虚拟化的支持。 最后是讨论一下今天的论文,它使用了…
19.2 Trap-and-Emulate --- Trap 我们该如何构建我们自己的VMM呢?一种实现方式是完全通过软件来实现,你可以想象写一个类似QEMU的软件,这个软件读取包含了XV6内核指令的文件,查看每一条指令并模拟RISC-V的状态,这里的状态包括了通过软件模拟32个寄存器。你的软件读取每条指令,确定指令类型,再将指令应用到通过软件模拟的32个寄存器和控制寄存器中。实…
19.3 Trap-and-Emulate --- Emulate VMM会为每一个Guest维护一套虚拟状态信息。所以VMM里面会维护虚拟的STVEC寄存器,虚拟的SEPC寄存器以及其他所有的privileged寄存器。当Guest操作系统运行指令需要读取某个privileged寄存器时,首先会通过trap走到VMM,因为在用户空间读取privileged寄存器是非法的。之后VMM会…
19.4 Trap-and-Emulate --- Page Table 有关Trap and Emulate的实现还有两个重要的部分,一个是Page Table,另一个是外部设备。 Page Table包含了两个部分,第一个部分是Guest操作系统在很多时候会修改SATP寄存器(注,SATP寄存器是物理内存中包含了Page Table的地址,详见4.3),当然这会变成一个trap走到VMM,…
19.5 Trap-and-Emulate --- Devices 接下来我们来看Trap and Emulate的最后一个部分,也就是虚拟机的外部设备。外部设备是指,一个普通的操作系统期望能有一个磁盘用来存储文件系统,或者是期望有一个网卡,甚至对于XV6来说期望有一个UART设备来与console交互,或者期望有一张声卡,一个显卡,键盘鼠标等等各种各样的东西。所以我们我们的虚拟机方案…
19.6 硬件对虚拟机的支持 接下来我将讨论硬件对于虚拟机的支持,这里特指的就是Intel的VT-x。为什么Intel和其他的硬件厂商会为虚拟机提供直接的硬件支持呢? 首先虚拟机应用的非常广泛,硬件厂商的大量客户都在使用虚拟机 其次,我们刚刚描述的Trap and Emulate虚拟机方案中,经常会涉及到大量高成本的trap,所以这种方案性能并不特别好…
19.7 Dune: Safe User-level Access to Privileged CPU Features 今天要讨论的论文利用了上一节介绍的硬件对于虚拟机的支持,但是却将其用作其他的用途,这是这篇论文的有趣之处,它利用了这种完全是为了虚拟机而设计的硬件,但是却用来做一些与虚拟机完全无关的事情。从一个全局的视角来看这篇论文的内容,它想要实现的是普通的进程。所以现在我们的场景是在一个Linux而不是VMM中,但是我们又用到了硬…
Title Intro
20.1 C语言实现操作系统的优劣势 今天我们要讨论使用高级编程语言实现操作系统的优点和代价。今天课程的内容主要是我们之前写的一篇论文,论文作者包括了Robert和我,以及一个主要作者Cody Cutler,他是这门课程的一个TA。我通常不会讨论我们自己写的论文,但是因为这篇论文与课程内容相关,所以它在这。今天我们会用一些PPT,而不是在白板上讲解这节课。…
20.10 Should one use HLL for a new kernel? 最后我想讨论我们在最开始问过的一个问题,你应该在一个新内核中使用高级编程语言吗? 与其直接回答这个问题,我在这页有一些我们的结论和一些考虑。或许你们该回退一步,并问自己,你们更喜欢哪种方式?你们是喜欢像在实验中用C写XV6,还是喜欢使用类似Golang的高级编程语言。更具体的说,你们更想避免哪类Bug?或许在这节课的过程…
20.2 高级编程语言实现操作系统的优劣势 高级编程语言吸引人的一个原因是它提供了memory-safety,所以上一节中CVEs提到的所有Bugs,都将不再存在。要么当它们发生时程序运行时会检查数组是否越界,如果越界了就panic;要么高级编程语言不允许你写出引起Bug的代码,所以这些问题完全不可能出现。 当然,高级编程语言还有一些其他的优点: 首先是Type s…
20.3 高级编程语言选择 --- Golang 接下来我们看一下对比方法,图中左边是Biscuit,这是一个我们为了论文专门用Golang写的内核,它以大概类似的方式提供了Linux中系统调用的子集。Biscuit和Linux的系统调用有相同的参数和相同的调用方式。并且我们在内核之上运行的是相同的应用程序,这里的应用程序是NGINX,这是一个web server,这…
20.4 Biscuit 接下来我将对Biscuit稍作介绍,包括了Biscuit是如何工作的,以及在实现中遇到的问题。其中有些问题是预期内的,有些问题不在预期之内。 就像Linux和XV6一样,Biscuit是经典的monolithic kernel。所以它也有用户空间和内核空间,用户空间程序可能是你的编译器gcc,或者论文中主要用到的webs…
20.5 Heap exhaustion 让我们讨论一下Heap耗尽问题,我不会像论文一样深入讨论,但是至少会演示问题是什么。 假设蓝色的矩形是内核,内核会有一个heap,它会从其中申请动态内存。在XV6中,我们并没有这样一个heap,我们在内核中没有内存分配器,所有内存都是静态分配的。但是任何其他的内核中,都会有heap,所以你在内核中可以调用malloc和f…
20.6 Heap exhaustion solution Biscuit的解决方案非常直观,当应用程序执行系统调用,例如read,fork时,在系统调用的最开始,跳转到内核之前,它会先调用reserve函数,reserve函数会保留足够的内存以运行系统调用。所以reserve会保留足够这个系统调用使用的空闲内存,以使得系统调用总是能成功。所以一旦系统调用被执行,且保留了足够的…
20.7 Evaluation: HLL benefits Biscuit的实现与其他内核,例如XV6,非常相似,除了Biscuit比XV6性能要高的多。Biscuit采用了很多Linux内核的优化和聪明的设计: 我们对于内核文本采用了大页,以避免TLB的代价 我们有针对每个CPU的网卡队列,这样可以避免CPU核之间同步 我们有RCU实现了不需要读锁的Directory Cache…
20.8 Evaluation: HLL performance cost(1) 以上是6个问题,我应该不会全部介绍,因为我想在课程的最后留些时间来回顾我们在本节课开始时提出的问题。 以上就是测试环境,Biscuit运行在裸金属之上,所以我们的测试是在物理服务器而不是QEMU之上。我们使用了三个应用程序来做性能测试,它们分别是,Webserver,K/V store,Mail server bench…
20.9 Evaluation: HLL performance cost(2) 接下来稍微介绍GC pause。Go的GC是一个带有短暂pause的并发GC,它在一段非常短的时间内停止程序运行来执行write barrier,之后再恢复应用程序的运行,同时GC也会完成自己的工作。Go的GC也是递增的,就像我们在Lec17中介绍过的一样,每次调用new都会做一些GC的工作。所以每次GC做一些工作的时…
Title Intro
21.1计算机网络概述 今天我想讨论一下Networking以及它与操作系统的关联。今天这节课的很多内容都与最后一个lab,也就是构建一个网卡驱动相关。在这节课,我们首先会大概看一下操作系统中网络相关的软件会有什么样的结构,之后我们会讨论今天的论文Livelock。Livelock展示了在设计网络协议栈时可能会出现的有趣的陷阱。 首先,让我通过…
21.2 二层网络 --- Ethernet 让我从最底层开始,我们先来看一下一个以太网packet的结构是什么。当两个主机非常靠近时,或许是通过相同的线缆连接,或许连接在同一个wifi网络,或许连接到同一个以太网交换机。当局域网中的两个主机彼此间要通信时,最底层的协议是以太网协议。你可以认为Host1通过以太网将Frame发送给Host2。Frame是以太网中用…
21.3 二/三层地址转换 --- ARP 下一个与以太网通信相关的协议是ARP。在以太网层面,每个主机都有一个以太网地址。但是为了能在互联网上通信,你需要有32bit的IP地址。为什么需要IP地址呢?因为IP地址有额外的含义。IP地址的高位bit包含了在整个互联网中,这个packet的目的地在哪。所以IP地址的高位bit对应的是网络号,虽然实际上要更复杂一些,…
21.4 三层网络 --- Internet Ethernet header足够在一个局域网中将packet发送到一个host。如果你想在局域网发送一个IP packet,那么你可以使用ARP获得以太网地址。但是IP协议更加的通用,IP协议能帮助你向互联网上任意位置发送packet。下图是一个IP packet的header,你们可以在lab配套的代码中的net.…
21.5 四层网络 --- UDP IP header足够让一个packet传输到互联网上的任意一个主机,但是我们希望做的更好一些。每一个主机都运行了大量需要使用网络的应用程序,所以我们需要有一种方式能区分一个packet应该传递给目的主机的哪一个应用程序,而IP header明显不包含这种区分方式。有一些其他的协议完成了这里的区分工作,其中一个是TCP…
21.6 网络协议栈(Network Stack) 与packet的协议和格式对应的是运行在主机上的网络协议栈。人们有各种各样的方式来组织网络软件,接下来我会介绍最典型的,并且至少我认为是最标准的组织方式。 假设我们现在在运行Linux或者XV6,我们有一些应用程序比如浏览器,DNS服务器。这些应用程序使用socket API打开了socket layer的文件描述符。S…
21.7 Ring Buffer 对于今天的论文,了解packet的控制流程是如何工作的还是比较重要,这里的控制流程与前一节介绍的分层网络协议栈还不太一样。 有关网络协议栈,通常会有多个独立的actor会处理packet,解析packet并生成输出。出于各种各样的原因,这些不同的actor之间是解耦的,这样它们可以并发的运行,并且连接不同的packet队…
21.8 Receive Livelock 接下来我们看一下今天的论文。因为我们已经介绍了很多论文相关的背景知识,我们直接来看一下论文的图1。我们之后根据论文中的图来开展讨论。 这张图是一个路由器的性能图。这是一个有两张网卡的路由器,它的工作是从一个网卡接收packet,再从另一个网卡送出 。X轴是接收速率,也就是接收端网卡的收到packet的速率。Y轴是发送速率…
21.9 如何解决Livelock 论文作者对于Livelock提出了一种解决方法。这种解决方法的最直接结果就是,当packet的输入速率达到了5000pps,随着输入速率的增加,转发性能维持在5000pps。 曲线后半部分的水平是一种完美的non-livelock性能曲线。之所以是水平的,是因为受CPU的限制,最多只能处理5000pps的转发。 在这个解决…
Title Intro
22.1 Meltdown发生的背景 今天讲的是Meltdown,之所以我会读这篇论文,是因为我们在讲解如何设计内核时总是会提到安全。内核提供安全性的方法是隔离,用户程序不能读取内核的数据,用户程序也不能读取其他用户程序的数据。我们在操作系统中用来实现隔离的具体技术是硬件中的User/Supervisor mode,硬件中的Page Table,以及精心设…
22.2 Speculative execution(1) 首先来看Speculative execution(预测执行),这里也有一个示例代码。 现在我并没有讨论安全性,Speculative execution是一种用来提升CPU性能的技术,所以这是CPU使用的一些优化技巧。假设我们在运行这里的代码: 在r0寄存器保存了一个内存地址,地址可能是有效的也可能是无效的,这取决于我代…
22.3 Speculative execution(2) 如果r0中的内存地址是无效的,且在Page Table中完全没有映射关系,那么我也不知道会发生什么。如果r0中的内存地址在Page Table中存在映射关系,只是现在权限不够,比如说pte_u标志位为0,那么Intel的CPU会加载内存地址对应的数据,并存储在r2寄存器的临时版本中。之后r2寄存器的临时版本可以被代码第…
22.4 CPU caches 接下来我将介绍Micro-Architectural的另一个部分,也就是缓存。我知道大家都知道CPU有cache,但是缓存或多或少应该是也透明的。让我画个图描述一下cache,因为我认为cache与Meltdown最相关。 首先,你有CPU核,这是CPU的一部分,它会解析指令,它包含了寄存器,它有加法单元,除法单元等等。…
22.5 Flush and Reload 为什么Cache与Meltdown相关呢?接下来我将讨论一下论文中使用Cache的主要方法。论文中讨论了这种叫做Flush and Reload的技术,这个技术回答了一个问题:一段特定的代码是否使用了特定内存地址的数据?这个技术本身并不是一个直接的安全漏洞,因为它只能基于你有权限的内存地址工作。 所以如果你是用户代码,你…
22.6 Meltdown Attack 接下来让我们回到Meltdown。 这段代码比22.1里面的代码更加完整,这里是一个更完整的Meltdown攻击代码,这里我们增加了Flush and Reload代码。 首先我们声明了一个buffer,现在我们只需要从内核中窃取1个bit的数据,我们会将这个bit乘以4096,所以我们希望下面的Flush and Rel…
22.7 Meltdown Fix 我最后想讨论的是Meltdown的修复,你们实际已经接触了一些了。当论文发表的时候,它获取了很多的关注。实际中还有另一篇论文,也是由这篇论文的部分作者参与完成,另一篇论文讨论了一种使用了CPU内一种叫做Spectre的不同的预测执行的不同攻击方法。这一对论文的同时出现让人非常兴奋( ̄▽ ̄)"。 所以人们现在发现危…
Title Intro
23.1 使用锁带来的问题 今天的话题是如何在多核CPU计算机上获得好的性能,这是一个非常有趣,深入且令人着迷的话题。今天我们只会涉及这个话题的很小的一个部分,也就是在面对内核中需要频繁读但是不需要频繁写的共享数据时,如何获得更好的性能。在不同的场景下有不同的方法可以在多核CPU的机器上获得更好的性能,我们今天要看的是Linux的RCU,它对于需…
23.2 读写锁 (Read-Write Lock) 这种锁被称为读写锁(Read-Write Lock),它的接口相比spinlock略显复杂。如果只是想要读取数据,那么可以调用r_lock,将锁作为参数传入,同样的还会有个r_unlock,数据的读取者使用这些接口。数据的写入者调用w_lock和w_unlock接口。 这里的语义是,要么你可以有多个数据的读取者获取了读锁…
23.3 RCU实现(1) - 基本实现 一种可能的解决方案是:数据读取者完全不使用锁。在有些场景数据读取者可以直接读数据,只有数据的写入者才需要锁。我们接下来快速的看一下能不能让数据读取者在不上锁的时候直接读取链表。假设我们有个链表,链表元素中存的数据是字符串,我们将读取链表中的数据。如果没有数据的写入者,那么不会有任何问题。 接下来我们看一下存在数据写入者时…
23.4 RCU实现(2) - Memory barrier 在前一部分介绍的方法中,存在一个问题。在前一部分中,如果要更新E2的内容,需要先创建一个E2‘ 并设置好它的内容,然后将E2’ 的next指针指向E3,最后才会将E1的next指针指向E2’。 你们或许还记得在XV6中曾经介绍过(注,详见10.8),许多计算机中都不存在“之后”或者“然后”这回事,通常来说所有的编译器和许…
23.5 RCU实现(3) - 读写规则 前面有同学也提到过,数据写入者会将E1的next指针从指向旧的E2切换到指向新的E2‘,但是可能有数据读取者在切换之前读到了旧的E2,并且仍然在查看旧的E2。我们需要在某个时候释放旧的E2,但是最好不要在某些数据读取者还在读的时候释放。所以我们需要等待最后一个数据读取者读完旧的E2,然后才能释放旧的E2。这就是RCU需…
23.6 RCU用例代码 为了巩固前面介绍的内容,接下来看一段使用了RCU的简单代码。上半段是读取被RCU保护的链表 ,下半段代码是替换链表的第一个元素。 数据读取位于rcu_read_lock和rcu_read_unlock之间,这两个函数几乎不做任何事情。rcu_read_lock会设置一个标志位,表明如果发生了定时器中断,请不要执行cont…
23.7 RCU总结 你们应该已经看到了RCU并不是广泛通用的,你不能把所有使用spinlock并且性能很差的场景转化成使用 RCU,并获得更好的性能。主要的原因是RCU完全帮不到写操作,甚至会让写操作更慢,只有当读操作远远多于写操作时才有可能应用RCU。因为RCU有这样的限制:代码不能在sleep的时候持有指针指向被RCU保护的数据,所以…
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

5.4 RISC-V寄存器笔记

肖宏辉(网络/OpenStack/SDN/NFV搬运工)

我们之前看过了汇编语言和RISC-V的介绍。接下来我们看一下之后lab相关的内容。这部分的内容其实就是本节课的准备材料中的内容。

输入图片说明

你们现在对于这个表达应该都很熟悉了,这个表里面是RISC-V寄存器。寄存器是CPU或者处理器上,预先定义的可以用来存储数据的位置。寄存器之所以重要是因为汇编代码并不是在内存上执行,而是在寄存器上执行,也就是说,当我们在做add,sub时,我们是对寄存器进行操作。所以你们通常看到的汇编代码中的模式是,我们通过load将数据存放在寄存器中,这里的数据源可以是来自内存,也可以来自另一个寄存器。之后我们在寄存器上执行一些操作。如果我们对操作的结果关心的话,我们会将操作的结果store在某个地方。这里的目的地可能是内存中的某个地址,也可能是另一个寄存器。这就是通常使用寄存器的方法。

输入图片说明

寄存器是用来进行任何运算和数据读取的最快的方式,这就是为什么使用它们很重要,也是为什么我们更喜欢使用寄存器而不是内存。当我们调用函数时,你可以看到这里有a0 - a7寄存器。通常我们在谈到寄存器的时候,我们会用它们的ABI名字。不仅是因为这样描述更清晰和标准,同时也因为在写汇编代码的时候使用的也是ABI名字。第一列中的寄存器名字并不是超级重要,它唯一重要的场景是在RISC-V的Compressed Instruction中。基本上来说,RISC-V中通常的指令是64bit,但是在Compressed Instruction中指令是16bit。在Compressed Instruction中我们使用更少的寄存器,也就是x8 - x15寄存器。我猜你们可能会有疑问,为什么s1寄存器和其他的s寄存器是分开的,因为s1在Compressed Instruction是有效的,而s2-11却不是。除了Compressed Instruction,寄存器都是通过它们的ABI名字来引用。

a0到a7寄存器是用来作为函数的参数。如果一个函数有超过8个参数,我们就需要用内存了。从这里也可以看出,当可以使用寄存器的时候,我们不会使用内存,我们只在不得不使用内存的场景才使用它。

表单中的第4列,Saver列,当我们在讨论寄存器的时候也非常重要。它有两个可能的值Caller,Callee。我经常混淆这两个值,因为它们只差一个字母。我发现最简单的记住它们的方法是:

  • Caller Saved寄存器在函数调用的时候不会保存
  • Callee Saved寄存器在函数调用的时候会保存

输入图片说明

这里的意思是,一个Caller Saved寄存器可能被其他函数重写。假设我们在函数a中调用函数b,任何被函数a使用的并且是Caller Saved寄存器,调用函数b可能重写这些寄存器。我认为一个比较好的例子就是Return address寄存器(注,保存的是函数返回的地址),你可以看到ra寄存器是Caller Saved,这一点很重要,它导致了当函数a调用函数b的时侯,b会重写Return address。所以基本上来说,任何一个Caller Saved寄存器,作为调用方的函数要小心可能的数据可能的变化;任何一个Callee Saved寄存器,作为被调用方的函数要小心寄存器的值不会相应的变化。我经常会弄混这两者的区别,然后会到这张表来回顾它们。

如果你们还记得的话,所有的寄存器都是64bit,各种各样的数据类型都会被改造的可以放进这64bit中。比如说我们有一个32bit的整数,取决于整数是不是有符号的,会通过在前面补32个0或者1来使得这个整数变成64bit并存在这些寄存器中。

  • 学生提问:返回值可以放在a1寄存器吗?

    TA:这是个好问题。我认为理论上是可以的,如果一个函数的返回值是long long型,也就是128bit,我们可以把它放到一对寄存器中。这也同样适用于函数的参数。所以,如果返回值超过了一个寄存器的长度,也就是64bit,我们可以将返回值保存在a0和a1。但是如果你只将返回值放在a1寄存器,我认为会出错。

  • 学生提问:为什么寄存器不是连续的?比如为什么s1与其他的s寄存器是分开的?

    TA:我之前提到过,但是也只是我的猜想,我并不十分确定。因为s1寄存器在RISC-V的Compressed Instruction是可用的,所以它才被分开。

  • 学生提问:除了Stack Pointer和Frame Pointer,我不认为我们需要更多的Callee Saved寄存器。

    TA:s0 - s11都是Callee寄存器,我认为它们是提供给编译器而不是程序员使用。在一些特定的场景下,你会想要确保一些数据在函数调用之后仍然能够保存,这个时候编译器可以选择使用s寄存器。

发布于 2020-11-15 21:34

肖宏辉​ (网络/OpenStack/SDN/NFV搬运工) 【笔记

  • 知乎首页摘要:

    • 居住地 : 现居北京
    • 所在行业 : 计算机软件
    • 职业经历 : 字节跳动(ByteDance)| VMware(威睿)| 华为 | IBM
    • 教育经历 : 中国科学院大学
    • 个人简介 : 瞎折腾

    什么是知乎众裁官,如何成为众裁官?

  • 赞同了回答2021-02-10 08:41 《 一个自律的人有多可怕? 》 虎山行不行

    看见这题我就溜达进来了。 我知道自律现在是个褒义词,高度自律的话堪比封神。 于是乎我进来就想说一句“别太自律”喔各位老铁。会要命的。 我自己要是没有所谓“高度自律”的切身体会,我这么唠嗑会被各位乱棍打死是没跑的。 所以我先简单说说自己经历,再说说关于自律的看法。 自律的经历我就说健身,写文,两个方面。 先说健身。 我从初中开始泡拳馆…

  • 赞同了文章 2021-01-21 13:43 Lockless Programming 兰新宇 talk is cheap

    说明:本文主要是汇总了以下的几篇文章,并经过了一定的加工和整理。

    正文 202 赞同 9 条评论

    包括spinlock, mutex在内的「锁」的机制会带来一些问题,比如需要持有两个锁,但加锁的顺序不对,就可能形成"A-B"类死锁,或者由于设计错误、持锁线程被抢占等原因,导致一个thread持锁时间太长。

    似乎「无锁编程」的概念可以解决上述的这些问题,但"lockless programming"本身是复杂的,需要深刻地理解它,才能从技术的角度获得预想的收益。来看下在实际的应用中,无锁编程都面临哪些挑战,以及如何应对。

  • 赞同了文章 2020-10-03 16:22 二十八画生征友:一起来通关6.S081/6.828吧~ 胡津铭

    6.828 Operating System Engineering是MIT久负盛名的一门操作系统相关的课程。这门课程有多牛呢?举个例子,以陈海波老师为首的上海交通大学IPADS实验室可以说是国内最强的操作系统相关实验室之一,而陈海波老师等人在他们读博的时候(早在2005年左右)就完成了6.828课程的学习,甚至还以6.828的JOS系统为基础开发了Corey操作系统,并发表了一篇ODSI2008论文Corey: An operating system for many cores,该论文也是陈老师至今引用最高的论文。而后,IPADS老师也基于6.828的资源,在上海交通大学软件学院开设了多年操作系统课程。

    好的,那么我就先写到这里,感兴趣的同学请独立完成前两个Lab之后加群交流~ 群号为603579009,加群的时候请附上自己完成前两个Lab的github repo地址~~ 谢谢大家啦

  • 赞同了回答 2019-06-23 22:25 ( 2674 赞同 257 评论)

    中美网络通讯的海底光缆大约有多少根?每根有多粗?

    这个之前有人利用wikipedia的数据和谷歌地图,做出了一幅互动式的世界海底光缆分布图。 目前中国大陆和美国连通的海底光缆主要有: 1. 跨太平洋快线(Trans-Pacific Express,简称TPE) 跨太平洋快线又称横太平洋快速海缆,为连接中国大陆、台湾、韩国、日本和美国的一条海底通信电缆。由中国电信、中国网通、…

  • 赞同了回答 2018-02-23 07:02 (13.3万 赞同 5367 条评论) 人是怎么废掉的? (曾加) 数学话题下的优秀答主

    沉溺于「轻易获得高成就感」的事情 :有意无意地寻求用很小付出获得很大「回报」的偏方,哪怕回报是虚拟的。这种行为会提升自己的「兴奋阈值」,让人越来越不容易拥有成就感,从而越来越依赖虚拟的成就感,陷入恶性循环。症状轻的: 沉溺游戏 (在虚拟世界中加快时间流逝的速度,使得「成功」来得更快)、 种马小说 (意淫人能轻易获得想要的东西);…

  • 回答了问题2017-05-08 15:56

    私有云爆发,该不该意外? (肖宏辉)

    公有云不能完全取代私有云, 1,如果私有云成本更低或者相当,企业更愿意使用私有云。大部分企业没有这个实力让成本更低,因此大家才觉得公有云有发展。不过公司的CEO CTO 有时不甘心,还是想尝试一下。 2,对安全或其他有要求的企业部门,更倾向于自建或者委托别人搭建私有云。比如银行和政府部门不可能把核心业务放到公有云上。就算是…

MIT6.S081 操作系统工程中文翻译笔记

置顶内容

MIT6.S081(2020)翻译简介

肖宏辉(网络/OpenStack/SDN/NFV搬运工)

因为学习MIT6.824,偶然知道了MIT6.S081这门课程。MIT6.S081这门课程的标题是Operating System Engineering,主要讲的就是操作系统。授课教授是Robert Morris和Frans Kaashoek,两位都是非常出名的程序员。

课程是基于一个类似于Unix但是简单的多的教学操作系统XV6来讲解,虽然不是原汁原味的Linux,但是对于理解Linux的工作方式和结构是足够了。与MIT6.824一样的是,这门课程是全英文,甚至英文字幕都没有。对于国内的同学来说,如果英文没有足够好,很难较好的理解这门课程。因此我计划将这门课程翻译成中文文字版。我将在语句通顺的前提下,尽量还原课程的内容,希望可以帮助大家学习到这门课程。如果你的英语不是那么好,建议阅读完文字再去看视频相关的课程。

目前MIT的这门课还没有上完,按计划是在12月初完成,具体的内容可以参考【1】。每一节课都在80分钟左右,大概会有6-9个知识点,我会按照独立的知识点将每节课拆分成6-9个小节。


2021-04-24 更新:

今天终于把问答课以外的20节课程都翻译完了,总共大概有35万个字,花费时间大概在200个小时左右。

这门课程相比6.824来说更像是一个整体。6.824更多的是在理解和设计分布式系统时的一些技术和技巧,而6.S081介绍了Unix风格操作系统的各个方面(虽然这两个课没什么关系( ̄. ̄),但是因为是连着翻译的难免会有对比)。

实际中的操作系统会更加的复杂,但是通过这门课程的学习基本上可以对操作系统有一个全面的认识。经过翻译的过程,我自己也把之前的一些知识盲区补全了。这门课程虽然只是一个MIT的本科课程,但是我推荐给所有从事IT相关工作的同学,掌握了操作系统对于面试,debug,写代码都是有好处的。

最后,希望我的翻译可以帮助到你。

【1】https://pdos.csail.mit.edu/6.828/2020/schedule.html

如果

  • 你发现了翻译的错误,或者想把剩下几门课程的翻译补上,可以向关联的github提交PR
  • 你觉得我做的还不错,可以关注我的知乎,并给我一个点赞。
  • 你正在找一份工作,并且想与和我一样的工程师共事,请联系
    我:honghui_xiao@yeah.net
  • 还想学习其他MIT课程,我还做了一些其他的翻译:

声明

此次翻译纯属个人爱好,如果涉及到任何版权行为,请联系我,我将删除内容。文中所有内容,与本人现在,之前或者将来的雇佣公司无关,本人保留自省的权利,也就是说你看到的内容也不一定代表本人最新的认知和观点。

编辑于 2022-01-25 11:13

github 1.1k stars

About

No description, website, or topics provided.
Resources

  • Readme笔记
  • Stars 1.1k stars
  • Watchers 20 watching
  • Forks 182 forks
  • commits 390 ( 06f26f0 5 days ago )

SUMMARY.md

Table of contents

课程摘要:

Title Intro
1.1 课程内容简介 大家好,欢迎来到6.S081 --- 操作系统这门课程。我的名字叫Robert,我会与Frans一起讲这门课。David,Nicholas会作为这门课程的助教。在我们在线授课的过程中,请尽情提问。你可以直接语音打断我,或者通过聊天窗口提问,我们工作人员会关注聊天窗口。顺便说一下,我们也会通过视频录制这门课程,之后我们会…
1.2 操作系统结构 过去几十年,人们将一些分层的设计思想加入到操作系统中,并运行的很好。我将会为你列出操作系统经典的组织结构,这个组织结构同时也是这门课程的主要内容,这里的组织结构对于操作系统来说还是挺常见的。 这里实际上就是操作系统内部组成,当我想到这里的组织结构时,我首先会想到用一个矩形表示一个计算机,这个计算机有一些硬件资源,我会将它…
1.3 Why Hard and Interesting 我还想说一下为什么我认为学习操作系统是挑战和乐趣并存的?以及为什么我们需要专门针对操作系统设置一门课程? 学习操作系统比较难的一个原因是,内核的编程环境比较困难。当你在编写、修改,扩展内核,或者写一个新的操作系统内核时,你实际上在提供一个基础设施让别人来运行他们的程序。当程序员在写普通的应用程序时,应用程序下面都是操作系…
1.4 课程结构和资源 接下来,我将花几分钟来介绍6.s081这门课程的结构,之后我们再来介绍具体的技术内容。 课程有一个网站,可以通过google查询6.s081找到。网站上会有课程的计划,lab的内容,课程结构的信息,例如最后是怎么打分的。 另一个资源是Piazza,它主要用来做两件事情,第一件是人们可以在上面咨询有关lab的问题,助教们会尝…
1.5 read, write, exit系统调用 接下来,我将讨论对于应用程序来说,系统调用长成什么样。因为系统调用是操作系统提供的服务的接口,所以系统调用长什么样,应用程序期望从系统调用得到什么返回,系统调用是怎么工作的,这些还是挺重要的。你会在第一个lab中使用我们在这里介绍的系统调用,并且在后续的lab中,扩展并提升这些系统调用的内部实现。 我接下来会展示一些简单…
1.6 open系统调用 前面,copy代码假设文件描述符已经设置好了。但是一般情况下,我们需要能创建文件描述符,最直接的创建文件描述符的方法是open系统调用。下面是一个叫做open的源代码,它使用了open系统调用。 学生提问:字节流是什么意思? Robert教授:我。。。我的意思是,如果一个文件包含了一些字节,假设包含了数百万个字节,你触发了…
1.7 Shell 我说了很多XV6的长的很像Unix的Shell,相对图形化用户接口来说,这里的Shell通常也是人们说的命令行接口。如果你还没有用过Shell,Shell是一种对于Unix系统管理来说非常有用的接口,它提供了很多工具来管理文件,编写程序,编写脚本。你之前看过我演示一些Shell的功能,通常来说,当你输入内容时,你是在告…
1.8 fork系统调用 下一个我想查看的例子叫做fork。fork会创建一个新的进程,下面是使用fork的一个简单用例。 在第12行,我们调用了fork。fork会拷贝当前进程的内存,并创建一个新的进程,这里的内存包含了进程的指令和数据。之后,我们就有了两个拥有完全一样内存的进程。fork系统调用在两个进程中都会返回,在原始的进程中,fork系…
1.9 exec, wait系统调用 在接下来我展示的一个例子中,会使用echo,echo是一个非常简单的命令,它接收任何你传递给它的输入,并将输入写到输出。 我为你们准备了一个文件名为exec的代码, 代码会执行exec系统调用,这个系统调用会从指定的文件中读取并加载指令,并替代当前调用进程的指令。从某种程度上来说,这样相当于丢弃了调用进程的内存,并开始执行…
1.10 I/O Redirect 最后一个例子,我想展示一下将所有这些工具结合在一起,来实现I/O重定向。 我们之前讲过,Shell提供了方便的I/O重定向工具。如果我运行下面的指令, Shell会将echo的输出送到文件out。之后我们可以运行cat指令,并将out文件作为输入, 我们可以看到保存在out文件中的内容就是echo指令的输出。 Shell之所以…

Hong Hui Xiao/肖宏辉 huihongxiao GITHUB homepage

6.824 Distributed System

课程链接:https://pdos.csail.mit.edu/6.824/

系统方向非常好的一门课程,每堂课都讲一个新的分布式系统模型,没有教材,每堂课都是直接讲论文。老师是MIT PDOS的神牛Robert Morris (不错,这人就是当年因为发明蠕虫而蹲监然后回MIT当教授的神人)和Frans Kaashoek。这些分布式系统都是实际用在各个大公司里的系统,比如说Spark, GFS,PNUTS。当年我修这门课的时候感觉课程压力非常大,有期中期末考试,有lab作业,有reading work, 还有course project,但是整个课程设计得非常好。lab要用Golang实现,硬生生地学了门新的语言。

Frans Kaashoek团队

来自如雷贯耳的MIT CSAIL,主要研究方向包括操作系统,网络,编译器等,PDOS组的负责人之一,绝对的大佬,后面你会看到被他支配的恐惧感。该实验室大佬众多,超新星Nickolai Zeldovich、Adam Belay、Mit6.284的Robert Morris以及已故的图灵奖获得者、计算机密码发明者Fernando J. Corbató都是个组的,这里暂以他为代表。可以看下团队近期的文章,毕竟一个会议也就20来篇。另外,很多文章都出自其“徒子徒孙”的团队。

MIT经典课程“分布式系统”视频版上线!网友:终于来了非偷拍清晰版本

来自MIT的经典课程, MIT的分布式系统课程,已经有20年历史,2000年就已经开设课程。当时讲授这门课的老师是Frans Kaashoek(ACM Fellow)和Robert Morris教授。现在,这门课程的讲授者,就只有Robert Morris教授一人了——长达20年教龄。

‘Morris Worm’ turns 30

输入图片说明

The ‘Morris Worm’ turns 30, Dinesh Abeywickrama and Inoshi Ratnasekera explore the History of Computer Worms.

Morris Worm

On 02nd of November 1988, world’s first major malware attack on the internet called ‘Morris Worm’ was unleashed. Even though this was not the first worm, it was considered the first major attack, which was a wakeup call to internet security engineers to consider the risk of software bugs and start research and development of network security (Ivey, 2018; Marsan, 2008).

Robert Tappan Morris

At 22 years, while attending Cornell graduate university Robert Tappan Morris developed the worm that spread via internet.

Robert Tappan Morris (creator of the ‘Morris Worm’) was born in 1965 and his father was a computer scientist at Bell Labs, who helped design Multics and Unix; and later became the chief scientist at the National Computer Security Center, a division of the National Security Agency (NSA).

Robert Tappan Morris, creator of ‘Morris worm’ in 2008

What / why was it?

Nowadays worms are very common on the internet, 30 years back Morris Worm had affected 6000 UNIX based systems. Before the security experts released patches 24hours later, the worm had affected and crashed 10 percent of internet usage. Rest of the networks were slow. Reports say Morris Worm is not only a worm attack, but also the first distributed DDoS attack (Vaughan-Nichols, 2018).

Morris worm can be considered as self-replicating software, which exploited common weakness of famous soft wares such as ‘Sendmail’ mail sending program, ‘Finger’ tool software help to find logged on users in system. Morris Worm, had exploited three weakness of internet to enter target networks and UNIX systems.

  1. Vulnerability in the debug mode of UNIX’s sendmail program
  2. A buffer overrun hole in the finger daemon protocol
  3. rexec/rsh network logins set up without passwords

Not only that but ‘Moris Worm’ was the first worm which used a list of popular passwords as a dictionary attack and used simple ‘Xoring’ encryption method to hide password and other strings (Ivey, 2018). According to the security experts, ‘Moris worm’ started from MIT computers and hid, back tracking by unlinking after affecting other networks on the internet. Even though the worm did not include malicious payload, worm caused serious damages to the infected systems as the infected systems tried to spread the worm. Because of this, infected networks slowed down and some systems, which depended on Sun OS, variant of Linux and Solaris, crashed due to the heavy load. At the same time, Morris had included sets of codes to spread fast and finally he had realized the worm was no longer in his control (Vaughan-Nichols, 2018). Out of control the worm started wave after wave of computer and system attacks.

Morris worm spread fast in 1988 when internet was small and people thought it was a very friendly place. Many other organizations, including the U.S. Department of Defense, had to unplug, internet cables to prevent worm infection (Marsan, 2008).

输入图片说明

Morris Worm Source Code

CERT

Because of the damages occurred by ‘Morris worm’ attack, an independent response team named CERT was created at Carnegie Mellon University, which was funded by the US Department of Defense’s Defense Advanced Research Projects Agency (DARPA). CERT security expert teams had to identify and address potential security threats, risks while consulting vendors, and independent security response teams around the world.

What happen to creator of ‘Morris’?

In 1991, Morris was sentenced to a three-year probation with 400 hours of community service and a $10,000 fine. Further, Morris was the first person who was tried and convicted of violating the 1986 Computer Fraud and Abuse Act.

After completing his sentence Morris founded two companies and one of his companies were sold to a search giant Yahoo Inc. Morris continued his computer network architectures at Massachusetts Institute of Technology as a professor (Ivey, 2018).

In 1988, when the worm was launched, there was not much commercial traffic or web sites in the internet. Since then, worm damages were limited to government agencies, universities and organizations that used internet networks to exchange e-mails and files.

Modern attackers

Today, crashing the internet is not profitable for attackers. Therefore modern cyber attackers are trickier when attacking systems, they gather information from affected computers, display ads etc.

‘Morris Worm’ made cyber security a legitimate topic among cyber security communities. In early days of computer security, only a few people worked on cyber security and all of them were cryptographers. After ‘Morris Worm’, security experts started to pay much more attention to cyber security as a field of study.

Dinesh Abeywickrama Ph.D.(reading), MBCS, MBA, BCS

**Inoshi Ratnasekera MBA, BS.c (Hons) **

References

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

Title:

  • MIT PDOS Frans Kaashoek Robert Morris
  • 6.S081 Operating System Engineering
  • 6.824 Distributed System
  • ‘Morris Worm’ turns 30

Contents:

  • 5.4 RISC-V 寄存器
  • 肖宏辉​ 知乎首页
  • MIT6.S081 操作系统工程中文翻译
    • github 1.1k stars
    • SUMMARY.md Table of contents
    • 课程摘要:1.-27.
  • Hong Hui Xiao GITHUB homepage
  • 6.824 Distributed System
  • ‘Morris Worm’ turns 30
  • 其他学习笔记

刚刚发布的 RISC-V Instruction Set LuckyDoku Extendsion (RISC-V Luckies) v0.1.69石榴派 寒假集训 的重要成果,而这个春节后诞生的成果,其学习过程的花絮同样精彩,因为,它挖掘出了一个宝藏,MIT 的热门网课,是从头数理自己计算机体系知识的宝贵资源,同时,挖掘出了它们的译者。刚看 一生一芯 的三期视频时,就曾扫过 MIT 分布式系统课,除了弹幕各种膜拜,其实并没有那么强烈的学习动力,直到寒假课程的契机到来,确定学习方案,竟然是 MIT 操作系统工程的一篇 RISC-V 资料。机缘就是这么奇妙 :pray:

开篇提纲就是学习线索,一路展开,直到挖掘出 MIT 大神 Robert Morris,世界首个 计算机 Worm 就是他的杰作,自行脑补,这可是30多年前的过往啊。真真地知道,我们缺少的太多太多,无论发展多快,都无法弥补我们的不足,这就是不争的事实。唯有学习,学习,再学习啦。快快随我畅游在这知识的海洋里吧,满足感,获得感,充实在心 :pray:

using t1-t6

000000000000000 <.data>:
   0:	00000093          	li	ra,0
   4:	00108313          	addi	t1,ra,1
   8:	00230393          	addi	t2,t1,2
   c:	00138e13          	addi	t3,t2,1
  10:	002e0e93          	addi	t4,t3,2
  14:	001e8f13          	addi	t5,t4,1
  18:	002f0f93          	addi	t6,t5,2

	case (op2)
		0: begin rd_data = lucky1(); end
//		1: begin rd_data = 17; end
		1: begin rd_data = op1; end
//		2: begin rd_data = 34; end
		2: begin rd_data = op1+1; end
//		3: begin rd_data = 51; end
//		4: begin rd_data = 68; end
//		default: begin rd_data = `ZERO_WORD; end
	endcase
    //function entity
    function [63:0]	lucky1;
//    function [N-1:0]     data_rvs ;
//            input     [N-1:0] data_in ;
//            parameter         MASK = 32'h3 ;
//            integer           k ;
            begin
//                for(k=0; k<N; k=k+1) begin
//                    data_rvs[N-k-1]  = data_in[k] ;  
//                end
		lucky1 = 64'h123456;
            end
    endfunction

create random lucky6 number

    //function entity
    function [63:0]	lucky1;
//    function [N-1:0]     data_rvs ;
//            input     [N-1:0] data_in ;
//            parameter         MASK = 32'h3 ;
            integer           k;
            integer		i[0:5],i2[0:5];
            integer		j;
            begin
//                for(k=0; k<N; k=k+1) begin
//                    data_rvs[N-k-1]  = data_in[k] ;  
//                end
//		lucky1 = 64'h123456;
		k = $random( 32'h123456 );
//		k = 1+{$random( 32'h123456 )}%(6-1+1);
		for ( j=0; j<6; j=j+1 )
		begin
			i2[j] = 1+{k}%(6-1+1);
			k = $random( k )*$random( i2[j] );
		end
		for ( j=0; j<6; j=j+1 )
			i[j] = i2[j];
			
		k = i[0]*32'h100000 
		  + i[1]*32'h10000
		  + i[2]*32'h1000
		  + i[3]*32'h100
		  + i[4]*32'h10
		  + i[5]*32'h1;
		lucky1 = {32'h0,k};
            end
    endfunction

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

361245

    //function entity
    function [63:0]	lucky1;
//    function [N-1:0]     data_rvs ;
//            input     [N-1:0] data_in ;
//            parameter         MASK = 32'h3 ;
            integer           k,k2;
            integer		i[0:5],	i2[0:5];
            integer		j, j2;
            begin
//                for(k=0; k<N; k=k+1) begin
//                    data_rvs[N-k-1]  = data_in[k] ;  
//                end
//		lucky1 = 64'h123456;
		k = $random( 32'h123456 );
//		k = 1+{$random( 32'h123456 )}%(6-1+1);
		for ( j=1; j<=6; j=j+1 )
			i[j-1] = j;
		// i[0:5] = {1,2,3,4,5,6}
		for ( j=0; j<6; j=j+1 )
		begin
			j2 = {k}%(6-j-1+1);
			i2[j] = i[j2];
			k = $random( k )*$random( i2[j] );
			// delete the old number.
			for ( k2=j2; k2<6-1; k2=k2+1 )
				i[k2] = i[k2+1];
		end
			
		k = i2[0]*32'h100000 
		  + i2[1]*32'h10000
		  + i2[2]*32'h1000
		  + i2[3]*32'h100
		  + i2[4]*32'h10
		  + i2[5]*32'h1;
		lucky1 = {32'h0,k};
            end
    endfunction

输入图片说明

functurn lucky2(op1)

	case (op2)
		0: begin rd_data = lucky1(); end
//		1: begin rd_data = 17; end
		1: begin rd_data = op1; end
//		2: begin rd_data = 34; end
		2: begin rd_data = lucky2(op1); end
//		3: begin rd_data = 51; end
//		4: begin rd_data = 68; end
//		default: begin rd_data = `ZERO_WORD; end
	endcase
	  		end
//	  `INST_LUCKY:
	  default:
	     begin rd_data = `ZERO_WORD; end
	endcase
  end
//  			end
end

    //function entity
    function [63:0]	lucky2;
            input     [63:0] data_in ;
            begin
		lucky2 = data_in + 1;
            end
    endfunction
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

361245 -> 245361

    //function entity
    function [63:0]	lucky2;
            input     [63:0] data_in ;
            begin
		lucky2 = data_in & 64'hfff;
		lucky2 = lucky2 * 64'h1000;
		lucky2 = lucky2 + data_in / 64'h1000;;
            end
    endfunction

输入图片说明

361245 -> rand3 -> 452163

    //function entity
    function [63:0]	lucky2;
            input     [63:0] data_in ;
            begin
		lucky2 = rand3( data_in & 64'hfff );
		lucky2 = lucky2 * 64'h1000;
		lucky2 = lucky2 + rand3( data_in / 64'h1000 );
            end
    endfunction

    //function entity
    function [63:0]	rand3;
            input     [63:0] data_in ;

	// 创造一个3个字符的随机序列
            integer           k,k2;
            integer		i[0:2],	i2[0:2];
            integer		j, j2;
            begin
		k = $random( data_in[31:0] );
		for ( j=1; j<=3; j=j+1 )
			i[j-1] = j;
		// i[0:2] = {1,2,3}
		for ( j=0; j<3; j=j+1 )
		begin
			j2 = {k}%(3-j-1+1);
			i2[j] = i[j2]-1;
			k = $random( k )*$random( i2[j] );
			// delete the old number.
			for ( k2=j2; k2<3-1; k2=k2+1 )
				i[k2] = i[k2+1];
		end
			
		for ( j=0; j<3; j=j+1 )
		begin
			case (i2[j]) 
			0: begin k = {28'h0,data_in[3:0]}; end
			1: begin k = {28'h0,data_in[7:4]}; end
			2: begin k = {28'h0,data_in[11:8]}; end
			endcase
			i2[j] = k;
		end
			
		k = i2[0]*32'h100
		  + i2[1]*32'h10
		  + i2[2]*32'h1;
		  
		rand3 = {32'h0,k};
            end
    endfunction

输入图片说明

add rd, rs1, rs2

lucky4 move lowbits to highbits.

0000000000000000 <.data>:
   0:	50000093          	li	ra,1280
   4:	00908093          	addi	ra,ra,9
   8:	001082b3          	add	t0,ra,ra
   c:	69900093          	li	ra,1689
  10:	00108313          	addi	t1,ra,1
  14:	00230393          	addi	t2,t1,2
  18:	00430293          	addi	t0,t1,4
  1c:	00728e33          	add	t3,t0,t2
  20:	002e0e93          	addi	t4,t3,2
  24:	003e8f13          	addi	t5,t4,3
  28:	002f0f93          	addi	t6,t5,2

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

输入图片说明

defines.v

`define INST_ADD 8'h12

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

输入图片说明

id_stage.v

// add

wire inst_add =   ~opcode[2] & ~opcode[3] & opcode[4] & opcode[5] & ~opcode[6]
                 & ~func3[0] & ~func3[1] & ~func3[2];
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

输入图片说明

exe_stage.v

// move low bits to high bits.
		4: begin rd_data = { op1[31:0],32'h0 }; end

	  `INST_ADD:	begin
			rd_data = op1 + op2;
	  		end

两行转两宫

0000000000000000 <.data>:
   0:	50000093          	li	ra,1280
   4:	00908093          	addi	ra,ra,9
   8:	001082b3          	add	t0,ra,ra
   c:	69900093          	li	ra,1689
  10:	00108313          	addi	t1,ra,1
  14:	00230393          	addi	t2,t1,2
  18:	00430293          	addi	t0,t1,4
  1c:	00728e33          	add	t3,t0,t2
  20:	005e0e93          	addi	t4,t3,5
  24:	003e8f13          	addi	t5,t4,3
  28:	002f0f93          	addi	t6,t5,2

输入图片说明

删除6个数字中已经有的数字

    //function entity
    function [63:0]	sixothers;
            input     [31:0] had;
            integer	i,j;
            integer	six[0:5];
            integer	j6[0:5];
            begin
            	for (i=0;i<6;i=i+1)
            		six[i] = i+1;
            	j6[0] = { 28'h0, had[3:0] };
            	j6[1] = { 28'h0, had[7:4] };
            	j6[2] = { 28'h0, had[11:8] };
            	j6[3] = { 28'h0, had[15:12] };
            	j6[4] = { 28'h0, had[19:16] };
            	j6[5] = { 28'h0, had[23:20] };
            		
            	for (i=0;i<6;i=i+1)
            		if ( j6[i] > 0 ) six[j6[i]-1] = 0;

		// adding debug info.
            	for (i=0;i<6;i=i+1)
            		j6[i] = six[i];

		for(j=6;j>0;j=j-1)
            	begin
            		if ( six[j-1] == 0 )
            		begin
            			for (i=j-1;i<6-1;i=i+1)
            			begin
	            			six[i] = six[i+1];
            			end
            			six[5] = 0;
            		end
            	end
            	
            	sixothers = { 8'h0, 
            		  j6[5][3:0],
            		  j6[4][3:0],
            		  j6[3][3:0],
            		  j6[2][3:0],
            		  j6[1][3:0],
            		  j6[0][3:0],
            			8'h0,
            		  six[5][3:0],
            		  six[4][3:0],
            		  six[3][3:0],
            		  six[2][3:0],
            		  six[1][3:0],
            		  six[0][3:0] };
            end
    endfunction

输入图片说明

4个字符的乱序

    //function entity
    function [63:0]	rand4;
            input     [63:0] data_in ;

	// 创造一个4个字符的随机序列
            integer           k,k2;
            integer		i[0:3],	i2[0:3];
            integer		j, j2;
            begin
		k = $random();
		for ( j=1; j<=4; j=j+1 )
			i[j-1] = j;
		// i[0:3] = {1,2,3,4}
		for ( j=0; j<4; j=j+1 )
		begin
			j2 = {k}%(4-j-1+1);
			i2[j] = i[j2]-1;
			k = $random();
			// delete the old number.
			for ( k2=j2; k2<4-1; k2=k2+1 )
				i[k2] = i[k2+1];
		end
			
		for ( j=0; j<4; j=j+1 )
		begin
			i[j] = i2[j];
			case (i2[j]) 
			0: begin k = {28'h0,data_in[3:0]}; end
			1: begin k = {28'h0,data_in[7:4]}; end
			2: begin k = {28'h0,data_in[11:8]}; end
			3: begin k = {28'h0,data_in[15:12]}; end
			endcase
			i2[j] = k;
		end
			
		k =  i[0]*32'h10000000
		  +  i[1]*32'h1000000
		  +  i[2]*32'h100000
		  +  i[3]*32'h10000
		  + i2[0]*32'h1000
		  + i2[1]*32'h100
		  + i2[2]*32'h10
		  + i2[3]*32'h1;
		  
		rand4 = {32'h0,k};
            end
    endfunction

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

6541, 2013, 5146 中间的 2013 是调试信息。

输入图片说明

下面是调试代码,

输入图片说明

放在了8字的高4位。

		k =  i[0]*32'h10000000
		  +  i[1]*32'h1000000
		  +  i[2]*32'h100000
		  +  i[3]*32'h10000
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

主程序流程,用于 三宫 的前两个字符的产生

    //function entity
    function [63:0]	luckyGong3;
            input     [63:0] ln1and2;
            integer	gong3;
            begin
            	// 
            	luckyGong3 = lines2gongs(ln1and2);
            	gong3 = luckyGong3[63:32];
            	luckyGong3 = sixothers( 
            		{24'h0, gong3[23:20], gong3[11:8]} );
            	gong3 = luckyGong3[31:0];
            	luckyGong3 = luckySelect( { 32'h0, gong3}, 2 );
            	luckyGong3 = { gong3, luckyGong3[31:0] };
            end
    endfunction

通用程序,计算字符串长度 luckyLength

    //function entity
    function [31:0]	luckyLength;
            input     [63:0] data_in ;
            begin
            
            if ( data_in[3:0] == 0 )
            	luckyLength = 0;
            else
            if ( data_in[7:4] == 0 )
            	luckyLength = 1;
            else
            if ( data_in[11:8] == 0 )
            	luckyLength = 2;
            else
            if ( data_in[15:12] == 0 )
            	luckyLength = 3;
            else
            if ( data_in[19:16] == 0 )
            	luckyLength = 4;
            else
            if ( data_in[23:20] == 0 )
            	luckyLength = 5;
            else
            if ( data_in[27:24] == 0 )
            	luckyLength = 6;
	    else
	    	luckyLength = -1;            
            end
    endfunction

未完成的 从3或者4个字符中 挑选少几个 字符,将会是 2个。

    //function entity
    function [63:0]	luckySelect;
            input     [63:0] data_in ;
            input     [8:0] sel;
            integer	len;
            begin
            
            len = luckyLength( data_in );
            case (len)
            	4:	begin luckySelect = rand4( data_in ); end
            	3:	begin luckySelect = rand3( data_in ); end
	        default: begin luckySelect = -1; end
            endcase
            
            end
    endfunction

4个字符中 挑选 2个。

输入图片说明

            case (sel)
            	1:	begin luckySelect = { 60'h0, luckySelect[3:0] }; end
            	2:	begin luckySelect = { 56'h0, luckySelect[7:0] }; end
            	3:	begin luckySelect = { 52'h0, luckySelect[11:0] }; end
            	4:	begin luckySelect = { 48'h0, luckySelect[15:0] }; end
            	default: begin luckySelect = -1; end
            endcase

输入图片说明

gong3 的第2对数字,从另外3个里选。

(不能是46,也不能是宫1的2列的65)

输入图片说明

    //function entity
    function [63:0]	luckyGong3;
            input     [63:0] ln1and2;
            integer	gong3;
            integer	gong1;
            begin
            	// 
            	luckyGong3 = lines2gongs(ln1and2);
            	gong1 = luckyGong3[63:32];
            	luckyGong3 = sixothers( 
            		{24'h0, gong1[23:20], gong1[11:8]} );
            	gong3 = luckyGong3[31:0];
            	luckyGong3 = luckySelect( { 32'h0, gong3}, 2 );
            	luckyGong3 = { gong3, luckyGong3[31:0] };

		// next 2 number other than 4.
		gong3 = luckyGong3[31:0];
            	luckyGong3 = sixothers( 
            		{16'h0, gong3[7:0], gong1[19:16], gong1[7:4]} );
            		
            	// put to correct position
            	
            	luckyGong3 = { luckyGong3[31:0], 
            			8'h0, gong3[7:4], 8'h0,
            			      gong3[3:0], 8'h0 };	
            end
    endfunction

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

选好了,12, 并放在了正确的位置上。

输入图片说明

		bk2[1] = luckyGong3[63:32];
		bk2[0] = luckyGong3[31:0];
		// select 2 of 3.
		luckyGong3 = luckySelect( { 32'h0, luckyGong3[63:32] }, 2 );
		gong3 = luckyGong3[31:0];
	//	luckyGong3 = { bk2[1], bk2[0] };
		
		luckyGong3 = { 8'h0, gong3[7:0], bk2[1][15:0], 
            			8'h0, bk2[0][23:20], gong3[7:4], 4'h0,
            			      bk2[0][11:8], gong3[3:0], 4'h0 };	
		//		luckyGong3[47:32], bk2[0] };
            	//		8'h0, bk2[0][7:4], 8'h0,
            	//		      bk2[0][3:0], 8'h0 };	

GONG3 完成 (带调试信息)

输入图片说明

    //function entity
    function [63:0]	luckyGong3;
            input     [63:0] ln1and2;
            integer	gong3, gong1, i, k;
            integer	bk2[0:1];
            begin
            	// 
            	luckyGong3 = lines2gongs(ln1and2);
            	gong1 = luckyGong3[63:32];
            	luckyGong3 = sixothers( 
            		{24'h0, gong1[23:20], gong1[11:8]} );
            	gong3 = luckyGong3[31:0];
            	luckyGong3 = luckySelect( { 32'h0, gong3}, 2 );
            	luckyGong3 = { gong3, luckyGong3[31:0] };

		// next 2 number other than 4.
		gong3 = luckyGong3[31:0];
            	luckyGong3 = sixothers( 
            		{16'h0, gong3[7:0], gong1[19:16], gong1[7:4]} );
            		
            	// put to correct position
            	
            	luckyGong3 = { luckyGong3[31:0], 
            			8'h0, gong3[7:4], 8'h0,
            			      gong3[3:0], 8'h0 };	
            			      
		bk2[1] = luckyGong3[63:32];
		bk2[0] = luckyGong3[31:0];
		// select 2 of 3.
		luckyGong3 = luckySelect( { 32'h0, luckyGong3[63:32] }, 2 );
		gong3 = luckyGong3[31:0];
	//	luckyGong3 = { bk2[1], bk2[0] };
		
		luckyGong3 = { 8'h0, gong3[7:0], bk2[1][15:0], 
            			8'h0, bk2[0][23:20], gong3[7:4], 4'h0,
            			      bk2[0][11:8], gong3[3:0], 4'h0 };	
		//		luckyGong3[47:32], bk2[0] };
            	//		8'h0, bk2[0][7:4], 8'h0,
            	//		      bk2[0][3:0], 8'h0 };	
            	
		bk2[1] = luckyGong3[63:32];
		bk2[0] = luckyGong3[31:0];
		
//            	luckyGong3 = luckySelect( { 40'h0, luckyGong3[23:16],
//            				      luckyGong3[11:4],
//            				      gong1[15:12], gong1[3:0]
//            				       }, 2 );
//		gong3 = luckyGong3[31:0];
//		luckyGong3 = { bk2[1], gong3[7:0], 

		gong3 = { 8'h0, luckyGong3[23:16],
            				      luckyGong3[11:4],
            				      gong1[15:12], gong1[3:0]
            				       };
		luckyGong3 = sixothers( gong3 );
		gong3 = luckyGong3[31:0];
		
//		luckyGong3 = { gong3[7:0], bk2[1][23:0], 8'h0,
//				       bk2[0][23:16], gong3[3:0],
//            			       bk2[0][11:4], gong3[7:4] };	

//		i = gong3;
//		k = 1+{$random()}%(2-1+1);
		if ( gong1[23:20] > 3 ) k = 2;
		else			k = 1;
		
//		luckyGong3 = { luckyGong3[31:0], k };
//		luckyGong3 = { gong3[7:0], bk2[1][23:0], 8'h0,
//		luckyGong3 = { gong3[7:0], bk2[1][23:0], k[7:0],
//				       bk2[0][23:16], gong3[3:0],
//            			       bk2[0][11:4], gong3[7:4] };	
		
		if ( k == 1 )
		luckyGong3 = { gong3[7:0], bk2[1][23:0], 8'h0,
				       bk2[0][23:16], gong3[3:0],
            			       bk2[0][11:4], gong3[7:4] };	
            	else
		luckyGong3 = { gong3[7:0], bk2[1][23:0], 8'h0,
				       bk2[0][23:16], gong3[7:4],
            			       bk2[0][11:4], gong3[3:0] };	

            end
    endfunction

计算 宫4 使用 宫3和宫2

        addi    t1,ra,1         # rand line1
        addi    t2,t1,2         # rand ln2 using line1 to init.

        addi    t0,t1,4         # move low32 to high32
        add     t3,t0,t2        # mix line1 and line2
        addi    t4,t3,5         # using ln1&2 init gong3

        addi    t0,t3,7         # convert 2 lines to 2 gongs
        addi    ra,t0,6         # ra = gong2
        addi    t4,t4,4         # move gong3 to t4 high32
        add     t4,t4,ra        # mix gong3 and gong2 to t4
        addi    t4,t4,8         # rand gong4 with gong3 and gong2

0000000000000000 <.data>:
   0:	50000093          	li	ra,1280
   4:	00908093          	addi	ra,ra,9
   8:	001082b3          	add	t0,ra,ra
   c:	69900093          	li	ra,1689
  10:	00108313          	addi	t1,ra,1
  14:	00230393          	addi	t2,t1,2
  18:	00430293          	addi	t0,t1,4
  1c:	00728e33          	add	t3,t0,t2
  20:	005e0e93          	addi	t4,t3,5
  24:	007e0293          	addi	t0,t3,7
  28:	00628093          	addi	ra,t0,6
  2c:	004e8e93          	addi	t4,t4,4
  30:	001e8eb3          	add	t4,t4,ra
  34:	008e8e93          	addi	t4,t4,8
  38:	003e8f13          	addi	t5,t4,3
  3c:	002f0f93          	addi	t6,t5,2

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

取得 低 32位, addi imm = 6;

6: begin rd_data = { 32'h0, op1[31:0] }; end
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

两行转变成两宫 addi imm = 7;

		7: begin rd_data = lines2gongs(op1); end

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

修改一个BUG,早期 BITS 合成语法问题。

    //function entity
    function [63:0]	lines2gongs;
            input     [63:0] ln1and2;
            integer	ln1, ln2;
            begin
            	ln1 = ln1and2[63:32];
            	ln2 = ln1and2[31:0];
            	
            	// 
            	lines2gongs = { 8'h0,ln1[23:12],ln2[23:12],
            		      	8'h0,ln1[11:0],ln2[11:0] };	
            end
    endfunction

测试成功,如期实现,操作数准备,准备开始 GONG4 的生成, addi, imm=8

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

准备好了,luckyGong4

    //function entity
    function [63:0]	luckyGong4;
            input     [63:0] ln1and2;
            integer	gong3, gong1, i, k;
            integer	bk2[0:1];
            begin
            	luckyGong4 = { ln1and2[31:0], ln1and2[63:32] };
            end
    endfunction
361 425
254 163

513
426

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

GONG4 ling3 's 3 numbers 642

输入图片说明

    //function entity
    function [63:0]	luckyGong4;
            input     [63:0] ln1and2;
            integer	gong3, gong1, i, j, k;
            integer	bk2[0:1];
            begin
            	gong3 = { 12'h0, ln1and2[55:44], ln1and2[23:20], ln1and2[11:8] };
            	luckyGong4 = luckySolve1( { 32'h0, gong3 } );
            	i = { 28'h0, luckyGong4[3:0] };
            	luckyGong4 = { luckyGong4[63:32], 8'h0, luckyGong4[3:0], 20'h0 };

            	gong3 = { 8'h0, ln1and2[55:44], i[3:0], ln1and2[19:16], ln1and2[7:4] };
            	luckyGong4 = luckySolve1( { 32'h0, gong3 } );
//            	luckyGong4 = { luckyGong4[31:0], gong3 };
		j = luckyGong4[31:0];
            	luckyGong4 = { gong3, 8'h0, i[3:0], j[3:0], 16'h0 };
            	
            	gong3 = { 4'h0, ln1and2[55:44], i[3:0], j[3:0], ln1and2[15:12], ln1and2[3:0] };
            	luckyGong4 = luckySolve1( { 32'h0, gong3 } );
            	k = luckyGong4[31:0];
            	luckyGong4 = { gong3, 8'h0, i[3:0], j[3:0], k[3:0], 12'h0 };
            	
            end
    endfunction
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

GONG4 ling4 's 3 numbers 351

输入图片说明

输入图片说明

输入图片说明

361 425
254 163

513 642
426 351
            	line3 = { 20'h0, luckyGong4[23:12] };
            	// line4.
            	gong3 = { 12'h0, line3[11:0], ln1and2[23:20], ln1and2[11:8] };
            	luckyGong4 = luckySolve1( { 32'h0, gong3 } );
            	i = { 28'h0, luckyGong4[3:0] };
            	luckyGong4 = { luckyGong4[63:32], 8'h0, line3[11:0], luckyGong4[3:0], 8'h0 };
            	
            	// 此处肯能有BUG,RAND返回的数字有可能和第6列冲突。
            	gong3 = { 8'h0, line3[11:0], i[3:0], ln1and2[19:16], ln1and2[7:4] };
            	luckyGong4 = luckySolve1( { 32'h0, gong3 } );
//            	luckyGong4 = { luckyGong4[31:0], gong3 };
		j = luckyGong4[31:0];
            	luckyGong4 = { gong3, 8'h0, line3[11:0], i[3:0], j[3:0], 4'h0 };
            	
            	gong3 = { 12'h0, line3[11:0], i[3:0], j[3:0] };
            	luckyGong4 = sixothers( gong3 );
//            	luckyGong4 = { luckyGong4[31:0], gong3 };
            	k = luckyGong4[31:0];
            	luckyGong4 = { gong3, 8'h0, line3[11:0], i[3:0], j[3:0], k[3:0] };
           	
            end
    endfunction

convert 2 gongs 2 lines

       addi    t3,t4,4         # t3 high32 = gong4
        add     t0,t3,t5        # t0 = { gong4 , gong3 }
        addi    t4,t0,10        # 2 gongs to 2 lines with 43
                                # 11 2gongs to 2lings with 34.
        addi    t3,t4,12        # move high32 to low32.
        addi    t4,t4,6         # musk low32.


 3c:	004e8e13          	addi	t3,t4,4
  40:	01ee02b3          	add	t0,t3,t5
  44:	00a28e93          	addi	t4,t0,10
  48:	00ce8e13          	addi	t3,t4,12
  4c:	006e8e93          	addi	t4,t4,6

		// 00,642351,00,513426 -> 513642,426351
		10: begin rd_data = { 8'h0, op1[23:12], op1[55:44],
				      8'h0, op1[11:0], op1[43:32] }; end 
		// 00,513426,00,642351 -> 513642,426351
		11: begin rd_data = { 8'h0, op1[55:44], op1[23:12], 
				      8'h0, op1[43:32], op1[11:0] }; end 
		12: begin rd_data = { 32'h0, op1[63:32] }; end

输入图片说明

361 425
254 163

513 642	
426 351	

get gongs from lines.

nano add2.S

        addi    t0,t1,4         # t1 to t0 high32
        addi    ra,t2,6         # t2 to ra low23
        add     ra,ra,t0        # ra = line1&2
        addi    t5,ra,7         # t5 = gong1&2

        addi    t0,t3,4         # t3 to t0 high32
        addi    ra,t4,6         # t4 to ra low23
        add     ra,ra,t0        # ra = line3&4
        addi    t6,ra,7         # t6 = gong3&4

./b.sh

  50:	00430293          	addi	t0,t1,4
  54:	00638093          	addi	ra,t2,6
  58:	005080b3          	add	ra,ra,t0
  5c:	00708f13          	addi	t5,ra,7
  60:	004e0293          	addi	t0,t3,4
  64:	006e8093          	addi	ra,t4,6
  68:	005080b3          	add	ra,ra,t0
  6c:	00708f93          	addi	t6,ra,7

../../../build.sh -b -t rvcpu.v -s

make: 进入目录“/home/pi/oscpu/projects/cpu/build_test/emu-compile”
make: 对“default”无需做任何事。
make: 离开目录“/home/pi/oscpu/projects/cpu/build_test/emu-compile”
Simulating...
Please enter your filename~
add2.bin

gtkwave add2.gtkw


GTKWave Analyzer v3.3.104 (w)1999-2020 BSI

[0] start time.
[999] end time.


输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

exchange gong1&2 and gong3&4 to gong13&24

        addi    t0,t5,12        # t0 = gong1
        addi    ra,t6,12        # ra = gong3
        addi    t0,t0,4         # t0 high32 = gong1.
        add     ra,t0,ra        # ra = gong1&3

        addi    t0,t5,6         # t0 = gong2

        addi    t5,ra,6         # backup ra low32 to t5 high32.
        addi    ra,ra,12        # move ra high32 to low32.
        addi    ra,ra,4         # move low32 to high32.
        add     t5,t5,ra        # t5 = gong1&3

        addi    ra,t6,6         # ra = gong4
        addi    t0,t0,4         # t0 high32 = gong2.
        add     t6,t0,ra        # t6 = gong2&4
  70:	00cf0293          	addi	t0,t5,12
  74:	00cf8093          	addi	ra,t6,12
  78:	00428293          	addi	t0,t0,4
  7c:	001280b3          	add	ra,t0,ra
  80:	006f0293          	addi	t0,t5,6
  84:	00608f13          	addi	t5,ra,6
  88:	00c08093          	addi	ra,ra,12
  8c:	00408093          	addi	ra,ra,4
  90:	001f0f33          	add	t5,t5,ra
  94:	006f8093          	addi	ra,t6,6
  98:	00428293          	addi	t0,t0,4
  9c:	00128fb3          	add	t6,t0,ra

输入图片说明

生成宫5的两个数字,再计算宫6.

        #
        # create gong5 col1 2rands
        #

        addi    ra,t5,13        # rand 2 char. set highest 2 8bits.
        add     t0,t6,ra        # mix 2numbers and gong2&4
        addi    ra,t0,14        # caculate gong6 first.

  a0:	00df0093          	addi	ra,t5,13
  a4:	001f82b3          	add	t0,t6,ra
  a8:	00e28093          	addi	ra,t0,14

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

mix 2numbers and gong2&4

		// gong5&gong6
		
		13: begin rd_data = luckyGong5(op1); end
		14: begin rd_data = op1; end
    //function entity
    function [63:0]	luckyGong5;
            input     [63:0] gong1and3;
            integer	gong3, gong1, i, j, k;
            integer	line3, line4;
            begin
            
            gong1 = gong1and3[63:32];
            gong3 = gong1and3[31:0];
            
            luckyGong5 = sixothers( {16'h0, gong1[23:20], gong1[11:8],
            				    gong3[23:20], gong3[11:8] } );

	    k = ( gong1[15:12] > 3 ) ? 1 : 2;
	    luckyGong5 = { k, luckyGong5[31:0] }; 		

	    if ( k==2 )
	    luckyGong5 = { luckyGong5[3:0], luckyGong5[7:4], 56'h0 }; 		
	    else
	    luckyGong5 = { luckyGong5[7:4], luckyGong5[3:0], 56'h0 }; 		
	    	     		               
            end
   endfunction

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

succes got gong6 16,236,514

    //function entity
    function [63:0]	luckyGong6;
            input     [63:0] gong2and4;
            integer	gong5, gong3, gong1, i, j, k;
            integer	line5, line6;
            integer	col[0:2];
            begin
            
	    col[0] = { 16'h0,
	               gong2and4[55:52], gong2and4[43:40],
		       gong2and4[23:20], gong2and4[11:8] };
	    col[1] = { 16'h0,
	               gong2and4[51:48], gong2and4[39:36],
		       gong2and4[19:16], gong2and4[7:4] };
	    col[2] = { 16'h0,
	               gong2and4[47:44], gong2and4[35:32],
		       gong2and4[15:12], gong2and4[3:0] };

            // gongs 2 cols success.
//            luckyGong6 = { gong2and4[63:56], 
//            		   col[0][15:0], 4'h0, col[1][15:0], 4'h0, col[2][15:0] };

            for (i=0;i<3;i=i+1)
            begin
            	luckyGong6 = luckyGong6col( gong2and4[63:56], col[i][15:0] );
            	col[i] = luckyGong6[31:0];
            end
            
            luckyGong6 = { 32'h0, col[0][31:24], 
            		   col[0][7:4], col[1][7:4], col[2][7:4],
            		   col[0][3:0], col[1][3:0], col[2][3:0] };

            end
   endfunction


	function [63:0]   luckyGong6col;
		input 	[7:0] gong2and4;
		input	[15:0] col;
		integer		i,j,k;
		begin
		
		luckyGong6col = sixothers( {8'h0, gong2and4, col } );
            				   
            	if ( luckyGong6col[7:4] == 0 )
            	begin
            	
            	i = { 28'h0, luckyGong6col[3:0] };
            	luckyGong6col = sixothers( {12'h0, i[3:0], col } );
		if ( luckyGong6col[3:0] == gong2and4[7:4] )
			begin
			luckyGong6col = { 32'h0, gong2and4, col, i[3:0], luckyGong6col[3:0] };
			end		
		else
		if ( luckyGong6col[3:0] == gong2and4[3:0] )
			begin
			luckyGong6col = { 32'h0, gong2and4, col, luckyGong6col[3:0], i[3:0] };
			end		
            	end
            	else
            	begin
            		if ( gong2and4[7:4] > gong2and4[3:0] )
			luckyGong6col = { 32'h0, gong2and4, col, luckyGong6col[7:0] };
			else
			luckyGong6col = { 32'h0, gong2and4, col, luckyGong6col[3:0],
								 luckyGong6col[7:4] };
            	end
            				    
		
		end
	endfunction

输入图片说明

gong52 final.

        addi    t0,t5,15        # gong1&3 to 32bits high.
        add     ra,t0,ra        # prepare for gong52.
        addi    t0,ra,16        # gong5&6 final.

        addi    ra,t0,11        # 2gongs to 2lings 34
        addi    t5,ra,12        # high32 to low32
        addi    t6,ra,6         # low32 to low32

        #
        # final finished.
        #

  ac:	00ff0293          	addi	t0,t5,15
  b0:	001280b3          	add	ra,t0,ra
  b4:	01008293          	addi	t0,ra,16
  b8:	00b28093          	addi	ra,t0,11
  bc:	00c08f13          	addi	t5,ra,12
  c0:	00608f93          	addi	t6,ra,6

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

宫52 与准备 IMM

		// gong52 prepare 00361254-00513426 -> 12543426
		15: begin rd_data = { op1[47:32], op1[15:0], 32'h0 }; end
		// gong52
		16: begin rd_data = op1; end

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

发现了一个BUG,修正了:prepare 00361254-00513426 -> 61541326

		// gong52 prepare 00361254-00513426 -> 61541326
		15: begin rd_data = { op1[51:44], op1[39:32], 
				      op1[19:12], op1[7:0], 32'h0 }; end
		// gong52
		16: begin rd_data = luckyGong52(op1); end

final success 1st verilog creating luckydoku was borned.

输入图片说明

    //function entity
    function [31:0]	FiveOnlyOne;
    	    input	[19:0] five;
    	    integer	in[0:4], one, i, j;
    	    begin
    	    in[0] = { 28'h0, five[3:0] };
    	    in[1] = { 28'h0, five[7:4] };
    	    in[2] = { 28'h0, five[11:8] };
    	    in[3] = { 28'h0, five[15:12] };
    	    in[4] = { 28'h0, five[19:16] };


    	    for (i=0;i<6;i=i+1)
    	    	begin
    	    	one = 0;
    	    	for (j=0;j<5;j=j+1)
    	    		begin
    	    		if ( i+1 == in[j] )
    	    			one = 1;
    	    		end
    	    	if ( one == 0 )
    	    		begin
    	    		one = i+1;
    	    		i = 6;
    	    		end
    	    	end
    	    
    	    FiveOnlyOne = one;
            end
    endfunction

    //function entity
    function [63:0]	luckyGong52;
            input     [63:0] gong1and3;
            integer	gong5, gong6, gong1, i, j, k, l;
            integer	lns[0:7];
            integer	col[0:1];
            begin

	    gong6 = gong1and3[31:0];
	    gong1and3 = { 12'h0, gong1and3[63:56], 4'h0, gong1and3[55:48],
	    		  12'h0, gong1and3[47:40], 4'h0, gong1and3[39:32] };
	    col[0] = { 16'h0,
	               gong1and3[51:48], gong1and3[39:36],
		       gong1and3[19:16], gong1and3[7:4] };
	    col[1] = { 16'h0,
	               gong1and3[47:44], gong1and3[35:32],
		       gong1and3[15:12], gong1and3[3:0] };

            // gongs 2 cols success.
            luckyGong52 = { col[0][15:0], col[1][15:0],
            		    gong6[31:28], gong6[11:0], gong6[27:12] };
            		    
      	    // delete duplicate number.
      	    lns[0] = { 28'h0, luckyGong52[31:28] };
      	    lns[1] = { 28'h0, luckyGong52[27:24] };
      	    lns[2] = { 28'h0, luckyGong52[23:20] };
      	    lns[3] = { 28'h0, luckyGong52[19:16] };
      	    lns[4] = { 28'h0, luckyGong52[15:12] };
      	    lns[5] = { 28'h0, luckyGong52[11:8] };
      	    lns[6] = { 28'h0, luckyGong52[7:4] };
      	    lns[7] = { 28'h0, luckyGong52[3:0] };
      	    
      	    for (i=0; i<8; i=i+4)
      	    	begin
      	    	for (j=i; j<i+3; j=j+1)
      	    		begin
      	    		if ( lns[j+1] == lns[i] )
      	    			begin
      	    			lns[j+1] = 0;
	      	    		if ( j > i )
//	      	    			lns[j+1] = j-i;
	      	    			for(k=j;k>i;k=k-1)
	      	    			begin
	      	    				lns[k+1]=lns[k];
	      	    			end
	      	    		end
      	    		end
      	    	end
      	    	
	    luckyGong52 = { luckyGong52[63:32], 8'h0, lns[2][3:0],lns[3][3:0],
	    					8'h0, lns[6][3:0],lns[7][3:0] };
//	    		    lns[0][3:0],lns[1][3:0],lns[2][3:0],lns[3][3:0],
//	    		    lns[4][3:0],lns[5][3:0],lns[6][3:0],lns[7][3:0] };

	    i = {8'h0, luckyGong52[63:48], lns[2][3:0],lns[3][3:0] };
	    k = {8'h0, luckyGong52[47:32], lns[2][3:0],lns[3][3:0] };
	    				// lns[6][3:0],lns[7][3:0] };
	    luckyGong52 = sixothers(i);
	    j = luckyGong52[31:0];
	    i = { 4'h0, j[3:0], i[23:0] };

	    luckyGong52 = sixothers(k);
	    l = luckyGong52[31:0];
	    k = { 4'h0, l[3:0], k[23:0] };

	    luckyGong52 = { i, k };
	    i = { 8'h0, luckyGong52[63:40] };
	    k = { 8'h0, luckyGong52[31:8] };

	    j = FiveOnlyOne( luckyGong52[59:40] );
	    l = FiveOnlyOne( luckyGong52[27:8] );
	    
/*	    luckyGong52 = sixothers(i);
	    j = luckyGong52[31:0];
	    luckyGong52 = sixothers(k);
	    l = luckyGong52[31:0];
*/	    	    
	    luckyGong52 = { 4'h0, j[3:0], 4'h0, i[19:0], 
	    		    4'h0, l[3:0], 4'h0, k[19:0] };


//	    gong1and3 = sixothers( {8'h0, luckyGong52[63:48], lns[2][3:0],lns[3][3:0] } );
//	    i = gong1and3[31:0];
//	    gong1and3 = sixothers( {12'h0, luckyGong52[63:48], i[3:0] } );
//	    j = gong1and3[31:0];
/*
	    gong1and3 = sixothers( {8'h0, luckyGong52[47:32], lns[6][3:0],lns[7][3:0] } );
	    k = gong1and3[31:0];
	    gong1and3 = sixothers( {12'h0, luckyGong52[47:32], k[3:0] } );
	    l = gong1and3[31:0];

	    luckyGong52 = { k[3:0], 4'h0, luckyGong52[47:32], lns[6][3:0],lns[7][3:0],
	    		    l[3:0], 8'h0, luckyGong52[47:32], k[3:0] };
*/	    
//	    luckyGong52 = { luckyGong52[63:32], j[3:0], i[3:0],
//	    					lns[2][3:0],lns[3][3:0],
//	    					l[3:0], k[3:0],
//	    					lns[6][3:0],lns[7][3:0] };

	    gong5 = { 8'h0, gong6[31:28], j[3:0], l[3:0],
	    		    gong6[27:24], i[19:16], k[19:16] };
	    luckyGong52 = { gong5, 8'h0, gong6[23:0] };

            end
   endfunction
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

尽管这期间出现过,编译器故障,

虽然编辑通过,但编译时间明显超过通常(详细看注释掉的代码)
重新写了一遍逻辑,也就是两个函数功能相同,就正常拉。

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

the result. :pray:

361 425
254 163

513 642	
426 351	

145 236
632 514
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

前面的LUCKY能量检测,只有 5,

微调了随机策略,重新生成了一个

输入图片说明

能量值提升到 8,已经相当完美拉

361 425
254 163

513 642	
426 351	

632 514
145 236
5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

6h25161364633513 5d263421352563

用上石榴派手工补上一道题,就可以交付啦!

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

输入图片说明

create .lud files. named Lucky5ysyx.lud

袁德俊 修改了描述
袁德俊 修改了描述

可以制作展示内容了 最好莫过于修改一个 LUCKYDOKU 的在线编辑界面的背景(支持一个动图版)

制作展示内容

输入图片说明

输入图片说明

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

5. Kazam

如果你对命令行不太舒服,而你只想要一个简单的屏幕录像机,可以截屏你的屏幕自由区域,选择Kazam。UI 非常简单而直观。与 GNOME 不同,您只需点击一个复选框来切换音频录制。它支持录音从麦克风以及扬声器。

Kazam 还允许您使用帧速率和视频编解码器进行一些自定义。它支持 RAW、无损 JPEG、WEBM、H.264 视频编解码器。Kazam 是专为极简用户和只需要一点点功能的人而构建的。

下载命令:

sudo apt install kazam
kazam-minimal-screen-recorder-for-linux

输入图片说明

什么好?

最小 UI 和自定义屏幕录制选项
可自定义帧速率和视频编解码器
什么不是?

没有修改分辨率、音频服务器等的选项

5631341 yuandj 1624973227 袁德俊 拥有者
回复 袁德俊 拥有者

RECORD GIF

输入图片说明

sudo add-apt-repository ppa:peek-developers/stable
sudo apt-get update
sudo apt-get install peek

神奇存在,录制了半天,只有 28.8K,只有一个鼠标有移动来移动去。果断删除

补上 RISCV 造芯的一块儿准备工作 TOOL CHAIN (实验课)

要在基础的框架上增加指令,只需要掌握好工具链,增加要增加的指令,然后编译成BIN的测试代码,再交由仿真系统测试。

这句话是阅读完 riscv-toolchain-installation-usage.md 之后的 “顿悟”,也是确定以下开发方案的关键信息。选用同架构的 I 型指令,来模拟 数独计算的扩展指令,可以免去改造工具链的工序,使用现有的模拟环境,验证新设计的扩展指令的效果。

语法格式和 addi rd,rs1,imm 完全相同,opcode 可以调整,保留字 lucky,六宫标准数独的加速指令共 16 条,通过改变 imm 实现,简要释意如下:

	     1689: 依据特定初始值,随机产生一个1-6的乱序队列;
		1: 复制 rs1 到 rd;
		2: 依据 op1 做初始值,随机产生一个1-6的乱序队列;
		3: 依据 保存在 op1 中的第一行数字,计算第2行数独数列;
		4: 将 op1 的 32位 低操作数 复制到 rd 的高32位;
		6: 将 op1 的 高32位 操作数 复制到 rd 的低32位;
		5: 根据 宫1和宫2,计算 宫3;每个宫是 2x3 的阵列;
		7: 将两行数字,转变成2宫数字;64 位由两个32位数组合成,高32是LN1;
		8: 计算宫4, 使用宫2和宫3;分别有 op1 高32和低32表示;
		10: 将宫4,宫3,转变成 行3,行4;
		11: 将宫3,宫4,转变成 行3,行4;
		12: 将高32位,变成高32为零的64位整数;
		13: 根据宫1宫3, 计算宫5的 列1的两个数字;
		14: 根据宫5的两个数字,计算宫6,不唯一的随机产生;
		15: 将宫1和宫3的列2列3合并成一个32位数;
		16: 利用列2列3以及宫6, 完成宫5最后4个数字;

以下是从 addi 示例框架,完成以上数独扩展指令的编码过程摘要:

幸运数独是基于六宫数独的特殊题型,以九道题为一组整体呈现。通常他们的答案完全一样,或有例外。这9道题的题面图形有着吉祥如意的寓意。因为特殊,所以需要更多算力,以便能更快地找到答案,并需要快速地验证是否满足特殊的条件。通常9道题答案全部一致,表示能量值最大,也就预示着解题人更容易获得好运。而出题人无论是否使用算力帮忙,分享给朋友时都是都会寄语美好祝福,手留余香的。该游戏由来自中国的一位社区志愿者袁德俊和他的学生们共同设计而成,他们有一个共同的愿望就是:祈愿全世界孩子健康快乐!

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(1)
5631341 yuandj 1624973227
1
https://gitee.com/RV4Kids/RISC-V-CPU.git
git@gitee.com:RV4Kids/RISC-V-CPU.git
RV4Kids
RISC-V-CPU
RISC-V-CPU

搜索帮助

344bd9b3 5694891 D2dac590 5694891