8 个版本
0.1.7 | 2020年11月30日 |
---|---|
0.1.6 | 2020年11月30日 |
#97 在 模拟
每月22次下载
205KB
4K SLoC
logicsim
使用 Rust 抽象创建和模拟数字电路!
在 logicsim 中,您使用 GateGraphBuilder 创建和连接逻辑门,概念上,逻辑门被表示为具有到其他节点的依赖边的图中的节点。
输出由OutputHandles表示,允许您查询门的状态,并通过调用GateGraphBuilder::output创建。
一旦初始化了图,它就转换为不可修改的InitializedGateGraph。初始化过程优化了门图,以便可以安全地使用可能会生成大量常量或无用的门的表达抽象。所有常量和死门都将被优化掉,并且剩余的图将非常激进地简化。
零开销抽象!
示例
简单门。
let mut g = GateGraphBuilder::new();
// Providing each gate with a string name allows for great debugging.
// If you don't want them affecting performance, you can disable
// feature "debug_gates" and all of the strings will be optimized away.
let or = g.or2(ON, OFF, "or");
let or_output = g.output1(or, "or_output");
let and = g.and2(ON, OFF, "and");
let and_output = g.output1(and, "and_output");
let ig = &g.init();
// `b0()` accesses the 0th bit of the output.
// Outputs can have as many bits as you want
// and be accessed with methods like `u8()`, `char()` or `i128()`.
assert_eq!(or_output.b0(ig), true);
assert_eq!(and_output.b0(ig), false);
拉杆!
let l1 = g.lever("l1");
let l2 = g.lever("l2");
let or = g.or2(l1.bit(), l2.bit(), "or");
let or_output = g.output1(or, "or_output");
let and = g.and2(l1.bit(), l2.bit(), "and");
let and_output = g.output1(and, "and_output");
let ig = &mut g.init();
assert_eq!(or_output.b0(ig), false);
assert_eq!(and_output.b0(ig), false);
// `_stable` means that the graph will run until gate states
// have stopped changing. This might not be what you want
// if you have a circuit that never stabilizes like 3 not gates
// connected in a loop!
// See [InitializedGateGraph::run_until_stable].
ig.flip_lever_stable(l1);
assert_eq!(or_output.b0(ig), true);
assert_eq!(and_output.b0(ig), false);
ig.flip_lever_stable(l2);
assert_eq!(or_output.b0(ig), true);
assert_eq!(and_output.b0(ig), true);
let r = g.lever("l1");
let s = g.lever("l2");
let q = g.nor2(r.bit(), OFF, "q");
let nq = g.nor2(s.bit(), q, "nq");
let q_output = g.output1(q, "q");
let nq_output = g.output1(nq, "nq");
// `d1()` replaces the dependency at index 1 with nq.
// We used OFF as a placeholder above.
g.d1(q, nq);
let ig = &mut g.init();
// With latches, the initial state should be treated as undefined,
// so remember to always reset your latches at the beginning
// of the simulation.
ig.pulse_lever_stable(r);
assert_eq!(q_output.b0(ig), false);
assert_eq!(nq_output.b0(ig), true);
ig.pulse_lever_stable(s);
assert_eq!(q_output.b0(ig), true);
assert_eq!(nq_output.b0(ig), false);
ig.pulse_lever_stable(r);
assert_eq!(q_output.b0(ig), false);
assert_eq!(nq_output.b0(ig), true);
8 位计算机
在示例文件夹中,您可以找到一个非常简单的 8 位计算机,它是使用 Rust 的结构来创建模块化电路抽象所能够实现的事物的极佳展示。
您只需使用 3 个 shell 命令就可以玩它!(《假设您已经安装了 cargo》)。
git clone https://github.com/raycar5/logicsim
cd logicsim
cargo run --release --example computer greeter
内置电路
circuits
模块提供了许多有用的预构建通用组件,如
调试
目前有 2 个调试工具
探针
调用 GateGraphBuilder::probe 允许您创建探针,当任何位的状态在 tick 中发生变化时,将打印出所有提供的位的值及其名称。
示例
let mut g = GateGraphBuilder::new();
let l1 = g.lever("l1");
let l2 = g.lever("l2");
let or = g.xor2(l1.bit(), l2.bit(), "or");
let xor = g.xor2(l1.bit(), l2.bit(), "xor");
g.probe(&[or,xor],"or_xor");
let xor_output = g.output1(xor, "xor_output");
let ig = &mut g.init();
assert_eq!(xor_output.b0(ig), false);
ig.set_lever_stable(l1);
assert_eq!(xor_output.b0(ig), true);
ig.set_lever_stable(l2);
assert_eq!(xor_output.b0(ig), false);
ig.reset_lever_stable(l1);
assert_eq!(xor_output.b0(ig), true);
ig.reset_lever_stable(l2);
assert_eq!(xor_output.b0(ig), false);
在终端中,您将看到
or_xor: 3
or_xor: 1
or_xor: 3
or_xor: 0
.dot 文件
使用方法 InitializedGateGraph::dump_dot 您可以生成 .dot 文件,这些文件可以在许多不同的图形查看器中查看。我推荐 gephi,很多其他的无法处理 logicsim 生成的图形的大小。
例如,以下是 8 位计算机的图形表示
如果我们稍微放大一些,我们可以看到每个节点都标有它的名称,这可以帮助调试真正奇怪的错误。
下一步
- 更好的调试:我想有一个 gui,我可以在其中一次性看到许多输出,具有类似逻辑分析仪的功能,可能是基于网页的。
- 更彻底的优化测试和文档:我已经记录和测试了大量的公共 API 表面,但优化文件夹需要一些爱。
- RISC-V:我想通过实现 RISC-V 内核并在其中运行 Rust 程序来测试 logicsim 的极限!
- 编译:目前 logicsim 只是一个解释器,我可能尝试将其编译成直接编译电路到 Rust 或 x86_64。
- 综合:我旁边有一个很好的 FPGA 开发套件,如果我能将 logicsim 中构建的电路综合到其中,那将非常酷。
许可:MIT
依赖项
~3.5MB
~56K SLoC