Intro:
- 绪论1:操作系统概述。
- 目的:模拟数字电路系统,这是当今的硬件基础。
代码Github分为两部分:
logisim.c
模拟 verilog 编程,输出A=1;B=0...
到管道中。seven_seg.py
将输出结果使用 ANSI 编码进行可视化展示。
这两部分的实施都比较巧妙。下面分别看一下这两段代码(略去了一部分不重要的部分)。
1. logisim.c
// 用 bool 和 struct 组成了 verilog 中最基础的 wire 和 reg 变量!
typedef bool wire; // Wires
typedef struct {
bool value;
wire *in, *out;
} reg; // Flip-flops
// Circuit constructs
#define CLOCK for (; ; END_CYCLE) // 时钟写成了死循环,END_CYCLE 负责写入文件流
#define END_CYCLE ({ end_cycle(); putchar('\n'); fflush(stdout); sleep(1); })
#define PRINT(X) printf(#X " = %d; ", X)
void end_cycle() {
PRINT(A);
...
}
#define NAND(X, Y) (!((X) && (Y))) // 逻辑操作
...
#define OR(X, Y) (NAND(NOT(X), NOT(Y)))
// Wire and register specification
wire X, Y, X1, Y1, A, B, C, D, E, F, G;
reg b1 = {.in = &X1, .out = &X}; // 指定输入输出
reg b0 = {.in = &Y1, .out = &Y};
int main() {
CLOCK {
// 数电部分
X1 = AND(NOT(X), Y);
...
*b1.out = b1.value;
}
}
整个代码需要对七段式数码管的数字电路有所了解。在C语法方面,使用 .in
语法直接对结构体进行初始化,.
语法自己之前没见识过,可以掌握一下。
2. seven_seg.py
# DISPLAY 便是待显示的 ANSI 字符序列
DISPLAY = '''
AAAAAAAAA
.....
DDDDDDDDD
'''
# STFW: ANSI Escape Code
CLEAR = '\033[2J\033[1;1f' # 清屏操作
BLOCK = { # 模拟屏幕显示的亮暗
0: '\033[37m░\033[0m',
1: '\033[31m█\033[0m',
}
for line in fileinput.input():
# Load "A=0; B=1; ..." to current context
exec(line) # 把每行输入都作为一条命令去执行,比如 A=0 就会定义一个变量 A
# Render the seven-segment display
pic = DISPLAY # 不能直接改
for seg in set(DISPLAY): # set 会去重
if seg.isalpha(): # 检查是否全部是字母
val = globals()[seg] # 0 or 1
pic = pic.replace(seg, BLOCK[val])
# Clear screen and display
print(CLEAR + pic)
原理上:把 DISPLAY
的 ABC...
根据输入流替换成 BLOCK
的明暗块。Python 语法方面,需要注意以下几点:
exec(line)
是把line
当做指令执行,这里会定义A=0;B=1...
等一系列变量;globals()
是获取所有全局变量,实际上就是获取line
中的ABC...
变量