Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions 逻辑模拟器/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 逻辑模拟器

一个轻量级的 Python 逻辑门模拟器示例仓库,用于搭建、运行和测试简单的组合逻辑电路。

## 功能

- 支持 `AND`、`OR`、`NOT`、`XOR`、`NAND`、`NOR` 等常见逻辑门。
- 支持通过连线把逻辑门组合成电路。
- 提供半加器示例,便于快速验证模拟结果。

## 快速开始

```bash
python examples/half_adder.py
```

预期输出:

```text
A=0 B=0 -> SUM=0 CARRY=0
A=0 B=1 -> SUM=1 CARRY=0
A=1 B=0 -> SUM=1 CARRY=0
A=1 B=1 -> SUM=0 CARRY=1
```

## 目录结构

```text
逻辑模拟器/
├── README.md
├── examples/
│ └── half_adder.py
└── logic_simulator/
├── __init__.py
└── core.py
```
23 changes: 23 additions & 0 deletions 逻辑模拟器/examples/half_adder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Half-adder example built with the logic simulator."""

from pathlib import Path
import sys

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from logic_simulator import Circuit, and_gate, xor_gate


def build_half_adder() -> Circuit:
circuit = Circuit()
circuit.add_gate("sum", ["A", "B"], "SUM", xor_gate)
circuit.add_gate("carry", ["A", "B"], "CARRY", and_gate)
return circuit


if __name__ == "__main__":
half_adder = build_half_adder()
for a in (0, 1):
for b in (0, 1):
result = half_adder.run(A=a, B=b)
print(f"A={a} B={b} -> SUM={int(result['SUM'])} CARRY={int(result['CARRY'])}")
14 changes: 14 additions & 0 deletions 逻辑模拟器/logic_simulator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Tiny logic simulator package."""

from .core import Circuit, Gate, and_gate, nand_gate, nor_gate, not_gate, or_gate, xor_gate

__all__ = [
"Circuit",
"Gate",
"and_gate",
"nand_gate",
"nor_gate",
"not_gate",
"or_gate",
"xor_gate",
]
71 changes: 71 additions & 0 deletions 逻辑模拟器/logic_simulator/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""Core primitives for a tiny combinational logic simulator."""

from dataclasses import dataclass, field
from typing import Callable, Dict, Iterable, List

LogicFunction = Callable[..., bool]


def _to_bool(value: bool | int) -> bool:
"""Normalize an input value to a boolean signal."""
return bool(value)


def and_gate(*inputs: bool | int) -> bool:
return all(_to_bool(value) for value in inputs)


def or_gate(*inputs: bool | int) -> bool:
return any(_to_bool(value) for value in inputs)


def not_gate(input_value: bool | int) -> bool:
return not _to_bool(input_value)


def xor_gate(*inputs: bool | int) -> bool:
return sum(_to_bool(value) for value in inputs) % 2 == 1


def nand_gate(*inputs: bool | int) -> bool:
return not and_gate(*inputs)


def nor_gate(*inputs: bool | int) -> bool:
return not or_gate(*inputs)


@dataclass(frozen=True)
class Gate:
"""A named logic operation that reads input signal names and writes one output."""

name: str
inputs: List[str]
output: str
operation: LogicFunction

def evaluate(self, signals: Dict[str, bool]) -> bool:
values = [signals[input_name] for input_name in self.inputs]
return self.operation(*values)


@dataclass
class Circuit:
"""A simple acyclic combinational circuit."""

gates: List[Gate] = field(default_factory=list)

def add_gate(
self,
name: str,
inputs: Iterable[str],
output: str,
operation: LogicFunction,
) -> None:
self.gates.append(Gate(name, list(inputs), output, operation))

def run(self, **input_signals: bool | int) -> Dict[str, bool]:
signals = {name: _to_bool(value) for name, value in input_signals.items()}
for gate in self.gates:
signals[gate.output] = gate.evaluate(signals)
return signals