sirc 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sirc-0.1.0/PKG-INFO +24 -0
- sirc-0.1.0/README.md +1 -0
- sirc-0.1.0/pyproject.toml +31 -0
- sirc-0.1.0/setup.cfg +4 -0
- sirc-0.1.0/src/sirc/__init__.py +0 -0
- sirc-0.1.0/src/sirc/core/__init__.py +0 -0
- sirc-0.1.0/src/sirc/core/device.py +134 -0
- sirc-0.1.0/src/sirc/core/device.pyi +24 -0
- sirc-0.1.0/src/sirc/core/logic.py +143 -0
- sirc-0.1.0/src/sirc/core/logic.pyi +19 -0
- sirc-0.1.0/src/sirc/core/node.py +117 -0
- sirc-0.1.0/src/sirc/core/node.pyi +15 -0
- sirc-0.1.0/src/sirc/core/transistor.py +122 -0
- sirc-0.1.0/src/sirc/core/transistor.pyi +20 -0
- sirc-0.1.0/src/sirc/simulator/__init__.py +0 -0
- sirc-0.1.0/src/sirc/simulator/device.py +238 -0
- sirc-0.1.0/src/sirc/simulator/device.pyi +22 -0
- sirc-0.1.0/src/sirc.egg-info/PKG-INFO +24 -0
- sirc-0.1.0/src/sirc.egg-info/SOURCES.txt +20 -0
- sirc-0.1.0/src/sirc.egg-info/dependency_links.txt +1 -0
- sirc-0.1.0/src/sirc.egg-info/requires.txt +7 -0
- sirc-0.1.0/src/sirc.egg-info/top_level.txt +1 -0
sirc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sirc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: SIRC - Digital Logic and Circuit Simulation Engine
|
|
5
|
+
Author-email: CRISvsGAME <cris@crisvsgame.com>
|
|
6
|
+
Maintainer-email: CRISvsGAME <cris@crisvsgame.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Repository, https://github.com/CRISvsGAME/sirc.git
|
|
9
|
+
Keywords: digital logic,circuit simulation,simulation engine
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: build; extra == "dev"
|
|
19
|
+
Requires-Dist: mypy; extra == "dev"
|
|
20
|
+
Requires-Dist: pylint; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest; extra == "dev"
|
|
22
|
+
Requires-Dist: twine; extra == "dev"
|
|
23
|
+
|
|
24
|
+
# SIRC
|
sirc-0.1.0/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# SIRC
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sirc"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
dependencies = []
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
authors = [{name = "CRISvsGAME", email = "cris@crisvsgame.com"}]
|
|
11
|
+
maintainers = [{name = "CRISvsGAME", email = "cris@crisvsgame.com"}]
|
|
12
|
+
description = "SIRC - Digital Logic and Circuit Simulation Engine"
|
|
13
|
+
readme = "README.md"
|
|
14
|
+
license = "MIT"
|
|
15
|
+
keywords = ["digital logic", "circuit simulation", "simulation engine"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python",
|
|
21
|
+
"Topic :: Scientific/Engineering",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
dev = ["build", "mypy", "pylint", "pytest", "twine"]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Repository = "https://github.com/CRISvsGAME/sirc.git"
|
|
29
|
+
|
|
30
|
+
[tool.pylint]
|
|
31
|
+
ignore-patterns = [".*\\.pyi"]
|
sirc-0.1.0/setup.cfg
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SIRC Core Device Module.
|
|
3
|
+
|
|
4
|
+
Defines the LogicDevice base class and several common logic devices: VDD, GND,
|
|
5
|
+
Input, Probe, and Port. A LogicDevice owns exactly one terminal Node and may
|
|
6
|
+
drive a single LogicValue onto that Node. LogicDevices do not perform any logic
|
|
7
|
+
resolution. The Simulator handles all evaluation and propagation.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
from abc import ABC
|
|
12
|
+
from sirc.core.logic import LogicValue
|
|
13
|
+
from sirc.core.node import Node
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LogicDevice(ABC):
|
|
17
|
+
"""
|
|
18
|
+
Abstract class for single-terminal logic devices.
|
|
19
|
+
|
|
20
|
+
Each LogicDevice owns one Node and may drive one LogicValue onto it. This
|
|
21
|
+
class defines only structural information. The Simulator is responsible for
|
|
22
|
+
injecting driver values and resolving all electrical behaviour.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
__slots__ = ("_node", "_value")
|
|
26
|
+
|
|
27
|
+
def __init__(self) -> None:
|
|
28
|
+
"""Create a new LogicDevice with a terminal Node and default Z value."""
|
|
29
|
+
self._node = Node()
|
|
30
|
+
self._value = LogicValue.Z
|
|
31
|
+
|
|
32
|
+
# --------------------------------------------------------------------------
|
|
33
|
+
# Properties
|
|
34
|
+
# --------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def terminal(self) -> Node:
|
|
38
|
+
"""Return the terminal Node of this LogicDevice."""
|
|
39
|
+
return self._node
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def value(self) -> LogicValue:
|
|
43
|
+
"""Return the LogicValue driven by this LogicDevice."""
|
|
44
|
+
return self._value
|
|
45
|
+
|
|
46
|
+
# --------------------------------------------------------------------------
|
|
47
|
+
# Debug Representation
|
|
48
|
+
# --------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
def __repr__(self) -> str:
|
|
51
|
+
"""Return a debug representation of this LogicDevice."""
|
|
52
|
+
cls = self.__class__.__name__
|
|
53
|
+
return f"<{cls} value={self.value!r} terminal={self.terminal!r}>"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ------------------------------------------------------------------------------
|
|
57
|
+
# Power Rail
|
|
58
|
+
# ------------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class VDD(LogicDevice):
|
|
62
|
+
"""
|
|
63
|
+
Logic "1" power rail device.
|
|
64
|
+
|
|
65
|
+
This device permanently drives its terminal Node with LogicValue.ONE.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self) -> None:
|
|
69
|
+
super().__init__()
|
|
70
|
+
self._value = LogicValue.ONE
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# ------------------------------------------------------------------------------
|
|
74
|
+
# Ground Rail
|
|
75
|
+
# ------------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class GND(LogicDevice):
|
|
79
|
+
"""
|
|
80
|
+
Logic "0" ground rail device.
|
|
81
|
+
|
|
82
|
+
This device permanently drives its terminal Node with LogicValue.ZERO.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
def __init__(self) -> None:
|
|
86
|
+
super().__init__()
|
|
87
|
+
self._value = LogicValue.ZERO
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# ------------------------------------------------------------------------------
|
|
91
|
+
# Input Device
|
|
92
|
+
# ------------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class Input(LogicDevice):
|
|
96
|
+
"""
|
|
97
|
+
Logic signal input device.
|
|
98
|
+
|
|
99
|
+
This device allows external setting of its driven LogicValue.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def set_value(self, value: LogicValue) -> None:
|
|
103
|
+
"""Set the LogicValue driven by this Input device."""
|
|
104
|
+
self._value = value
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# ------------------------------------------------------------------------------
|
|
108
|
+
# Probe Device
|
|
109
|
+
# ------------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class Probe(LogicDevice):
|
|
113
|
+
"""
|
|
114
|
+
Logic signal probe device.
|
|
115
|
+
|
|
116
|
+
This device allows sampling of the LogicValue present on its terminal Node.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
def sample(self) -> LogicValue:
|
|
120
|
+
"""Return the current resolved LogicValue of the terminal Node."""
|
|
121
|
+
return self._node.value
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ------------------------------------------------------------------------------
|
|
125
|
+
# Port Device
|
|
126
|
+
# ------------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class Port(LogicDevice):
|
|
130
|
+
"""
|
|
131
|
+
Logic signal port device.
|
|
132
|
+
|
|
133
|
+
This device is a passive connection point for linking circuit Nodes.
|
|
134
|
+
"""
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from sirc.core.logic import LogicValue as LogicValue
|
|
3
|
+
from sirc.core.node import Node as Node
|
|
4
|
+
|
|
5
|
+
class LogicDevice(ABC):
|
|
6
|
+
def __init__(self) -> None: ...
|
|
7
|
+
@property
|
|
8
|
+
def terminal(self) -> Node: ...
|
|
9
|
+
@property
|
|
10
|
+
def value(self) -> LogicValue: ...
|
|
11
|
+
|
|
12
|
+
class VDD(LogicDevice):
|
|
13
|
+
def __init__(self) -> None: ...
|
|
14
|
+
|
|
15
|
+
class GND(LogicDevice):
|
|
16
|
+
def __init__(self) -> None: ...
|
|
17
|
+
|
|
18
|
+
class Input(LogicDevice):
|
|
19
|
+
def set_value(self, value: LogicValue) -> None: ...
|
|
20
|
+
|
|
21
|
+
class Probe(LogicDevice):
|
|
22
|
+
def sample(self) -> LogicValue: ...
|
|
23
|
+
|
|
24
|
+
class Port(LogicDevice): ...
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SIRC Core Logic Module.
|
|
3
|
+
|
|
4
|
+
Defines the four-state digital logic values used throughout the SIRC simulation
|
|
5
|
+
engine. The logic rules follow the four-state resolution semantics defined by
|
|
6
|
+
IEEE 1800-2023, but the terminology used here follows SIRC conventions.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
from enum import Enum, unique
|
|
11
|
+
from typing import Iterable
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@unique
|
|
15
|
+
class LogicValue(Enum):
|
|
16
|
+
"""
|
|
17
|
+
Four-state digital logic value used by Nodes and drivers in SIRC.
|
|
18
|
+
|
|
19
|
+
Values:
|
|
20
|
+
ZERO (0) -> logical low
|
|
21
|
+
ONE (1) -> logical high
|
|
22
|
+
X -> unknown or conflicting value
|
|
23
|
+
Z -> undriven or high-impedance value
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
ZERO = "0"
|
|
27
|
+
ONE = "1"
|
|
28
|
+
X = "X"
|
|
29
|
+
Z = "Z"
|
|
30
|
+
|
|
31
|
+
# --------------------------------------------------------------------------
|
|
32
|
+
# Helper Properties
|
|
33
|
+
# --------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def is_zero(self) -> bool:
|
|
37
|
+
"""Return True if this value is ZERO."""
|
|
38
|
+
return self is LogicValue.ZERO
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def is_one(self) -> bool:
|
|
42
|
+
"""Return True if this value is ONE."""
|
|
43
|
+
return self is LogicValue.ONE
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def is_x(self) -> bool:
|
|
47
|
+
"""Return True if this value is unknown (X)."""
|
|
48
|
+
return self is LogicValue.X
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def is_z(self) -> bool:
|
|
52
|
+
"""Return True if this value is high-impedance (Z)."""
|
|
53
|
+
return self is LogicValue.Z
|
|
54
|
+
|
|
55
|
+
# --------------------------------------------------------------------------
|
|
56
|
+
# Two-Driver Resolution
|
|
57
|
+
# --------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
def resolve(self, other: LogicValue) -> LogicValue:
|
|
60
|
+
"""
|
|
61
|
+
Resolve two driver values into a single LogicValue.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
other: The second LogicValue driving the same Node.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
LogicValue: The resolved value.
|
|
68
|
+
|
|
69
|
+
Resolution Table (N = Node):
|
|
70
|
+
N | 0 | 1 | X | Z
|
|
71
|
+
---+---+---+---+---
|
|
72
|
+
0 | 0 | X | X | 0
|
|
73
|
+
---+---+---+---+---
|
|
74
|
+
1 | X | 1 | X | 1
|
|
75
|
+
---+---+---+---+---
|
|
76
|
+
X | X | X | X | X
|
|
77
|
+
---+---+---+---+---
|
|
78
|
+
Z | 0 | 1 | X | Z
|
|
79
|
+
"""
|
|
80
|
+
result = self
|
|
81
|
+
|
|
82
|
+
if self is not other:
|
|
83
|
+
|
|
84
|
+
if self.is_x or other.is_x:
|
|
85
|
+
result = LogicValue.X
|
|
86
|
+
|
|
87
|
+
elif self.is_z and other.is_z:
|
|
88
|
+
result = LogicValue.Z
|
|
89
|
+
|
|
90
|
+
elif (self.is_zero and other.is_one) or (self.is_one and other.is_zero):
|
|
91
|
+
result = LogicValue.X
|
|
92
|
+
|
|
93
|
+
elif self.is_z:
|
|
94
|
+
result = other
|
|
95
|
+
|
|
96
|
+
elif other.is_z:
|
|
97
|
+
result = self
|
|
98
|
+
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
# --------------------------------------------------------------------------
|
|
102
|
+
# Multi-Driver Resolution
|
|
103
|
+
# --------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def resolve_all(values: Iterable[LogicValue]) -> LogicValue:
|
|
107
|
+
"""
|
|
108
|
+
Resolve multiple driver values into a single LogicValue.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
values: Iterable of LogicValue instances.
|
|
112
|
+
|
|
113
|
+
Raises:
|
|
114
|
+
ValueError: If no values are provided.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
LogicValue: The resolved value.
|
|
118
|
+
"""
|
|
119
|
+
iterator = iter(values)
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
result = next(iterator)
|
|
123
|
+
except StopIteration as e:
|
|
124
|
+
raise ValueError("resolve_all() requires at least one LogicValue.") from e
|
|
125
|
+
|
|
126
|
+
for value in iterator:
|
|
127
|
+
result = result.resolve(value)
|
|
128
|
+
if result.is_x:
|
|
129
|
+
return LogicValue.X
|
|
130
|
+
|
|
131
|
+
return result
|
|
132
|
+
|
|
133
|
+
# --------------------------------------------------------------------------
|
|
134
|
+
# Display Helpers
|
|
135
|
+
# --------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
def __str__(self) -> str:
|
|
138
|
+
"""Return compact string form ('0', '1', 'X', 'Z')."""
|
|
139
|
+
return self.value
|
|
140
|
+
|
|
141
|
+
def __repr__(self) -> str:
|
|
142
|
+
"""Return readable debug representation."""
|
|
143
|
+
return f"LogicValue.{self.name}"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Iterable
|
|
3
|
+
|
|
4
|
+
class LogicValue(Enum):
|
|
5
|
+
ZERO = '0'
|
|
6
|
+
ONE = '1'
|
|
7
|
+
X = 'X'
|
|
8
|
+
Z = 'Z'
|
|
9
|
+
@property
|
|
10
|
+
def is_zero(self) -> bool: ...
|
|
11
|
+
@property
|
|
12
|
+
def is_one(self) -> bool: ...
|
|
13
|
+
@property
|
|
14
|
+
def is_x(self) -> bool: ...
|
|
15
|
+
@property
|
|
16
|
+
def is_z(self) -> bool: ...
|
|
17
|
+
def resolve(self, other: LogicValue) -> LogicValue: ...
|
|
18
|
+
@staticmethod
|
|
19
|
+
def resolve_all(values: Iterable[LogicValue]) -> LogicValue: ...
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SIRC Core Node Module.
|
|
3
|
+
|
|
4
|
+
Defines the Node class used by the SIRC simulation engine. Nodes represent
|
|
5
|
+
logical connection points in the circuit. Multiple Nodes may be connected,
|
|
6
|
+
forming an electrical group that collectively resolves a single LogicValue.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
from sirc.core.logic import LogicValue
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Node:
|
|
14
|
+
"""
|
|
15
|
+
A Node is a passive logical connection point in the SIRC circuit model.
|
|
16
|
+
|
|
17
|
+
It may hold zero or more driver LogicValues and may be directly connected
|
|
18
|
+
to other Nodes. A Node performs no resolution or computation by itself;
|
|
19
|
+
all evaluation and propagation are handled entirely by the Simulator.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__slots__ = ("_drivers", "_connections", "_value")
|
|
23
|
+
|
|
24
|
+
def __init__(self) -> None:
|
|
25
|
+
"""Create an isolated Node with no drivers and a default Z value."""
|
|
26
|
+
self._drivers: list[LogicValue] = []
|
|
27
|
+
self._connections: set[Node] = set()
|
|
28
|
+
self._value: LogicValue = LogicValue.Z
|
|
29
|
+
|
|
30
|
+
# --------------------------------------------------------------------------
|
|
31
|
+
# Value Handling (Simulator-Controlled)
|
|
32
|
+
# --------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
def set_resolved_value(self, value: LogicValue) -> None:
|
|
35
|
+
"""
|
|
36
|
+
Set the resolved LogicValue of this Node.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
value: The resolved LogicValue to set.
|
|
40
|
+
"""
|
|
41
|
+
self._value = value
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def value(self) -> LogicValue:
|
|
45
|
+
"""Return the current resolved LogicValue of this Node."""
|
|
46
|
+
return self._value
|
|
47
|
+
|
|
48
|
+
# --------------------------------------------------------------------------
|
|
49
|
+
# Driver Management
|
|
50
|
+
# --------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
def add_driver(self, value: LogicValue) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Add a driver LogicValue to this Node.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
value: The LogicValue driving this Node.
|
|
58
|
+
"""
|
|
59
|
+
self._drivers.append(value)
|
|
60
|
+
|
|
61
|
+
def clear_drivers(self) -> None:
|
|
62
|
+
"""Remove all driver LogicValues from this Node."""
|
|
63
|
+
self._drivers.clear()
|
|
64
|
+
|
|
65
|
+
def get_drivers(self) -> tuple[LogicValue, ...]:
|
|
66
|
+
"""Return all driver LogicValues as an immutable tuple."""
|
|
67
|
+
return tuple(self._drivers)
|
|
68
|
+
|
|
69
|
+
# --------------------------------------------------------------------------
|
|
70
|
+
# Connectivity
|
|
71
|
+
# --------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
def add_connection(self, other: Node) -> None:
|
|
74
|
+
"""INTERNAL USE ONLY: Add a direct connection to another Node."""
|
|
75
|
+
self._connections.add(other)
|
|
76
|
+
|
|
77
|
+
def remove_connection(self, other: Node) -> None:
|
|
78
|
+
"""INTERNAL USE ONLY: Remove a direct connection to another Node."""
|
|
79
|
+
self._connections.discard(other)
|
|
80
|
+
|
|
81
|
+
def connect(self, other: Node) -> None:
|
|
82
|
+
"""
|
|
83
|
+
Create a bidirectional connection between this Node and another.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
other: The Node to connect to.
|
|
87
|
+
"""
|
|
88
|
+
if self is other:
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
self.add_connection(other)
|
|
92
|
+
other.add_connection(self)
|
|
93
|
+
|
|
94
|
+
def disconnect(self, other: Node) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Remove the bidirectional connection between this Node and another.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
other: The Node to disconnect from.
|
|
100
|
+
"""
|
|
101
|
+
if self is other:
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
self.remove_connection(other)
|
|
105
|
+
other.remove_connection(self)
|
|
106
|
+
|
|
107
|
+
def get_connections(self) -> tuple[Node, ...]:
|
|
108
|
+
"""Return all directly connected Nodes as an immutable tuple."""
|
|
109
|
+
return tuple(self._connections)
|
|
110
|
+
|
|
111
|
+
# --------------------------------------------------------------------------
|
|
112
|
+
# Debug Representation
|
|
113
|
+
# --------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
def __repr__(self) -> str:
|
|
116
|
+
"""Return a debug representation of this Node."""
|
|
117
|
+
return f"<Node value={self._value!r} drivers={tuple(self._drivers)!r}>"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from sirc.core.logic import LogicValue as LogicValue
|
|
2
|
+
|
|
3
|
+
class Node:
|
|
4
|
+
def __init__(self) -> None: ...
|
|
5
|
+
def set_resolved_value(self, value: LogicValue) -> None: ...
|
|
6
|
+
@property
|
|
7
|
+
def value(self) -> LogicValue: ...
|
|
8
|
+
def add_driver(self, value: LogicValue) -> None: ...
|
|
9
|
+
def clear_drivers(self) -> None: ...
|
|
10
|
+
def get_drivers(self) -> tuple[LogicValue, ...]: ...
|
|
11
|
+
def add_connection(self, other: Node) -> None: ...
|
|
12
|
+
def remove_connection(self, other: Node) -> None: ...
|
|
13
|
+
def connect(self, other: Node) -> None: ...
|
|
14
|
+
def disconnect(self, other: Node) -> None: ...
|
|
15
|
+
def get_connections(self) -> tuple[Node, ...]: ...
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SIRC Core Transistor Module.
|
|
3
|
+
|
|
4
|
+
Defines the abstract Transistor class and its NMOS and PMOS implementations. A
|
|
5
|
+
Transistor is a three-terminal digital switch with gate, source, and drain
|
|
6
|
+
Nodes. Transistors do not resolve logic or perform any electrical computation;
|
|
7
|
+
the Simulator evaluates each device's conduction state based on its gate value.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from sirc.core.logic import LogicValue
|
|
13
|
+
from sirc.core.node import Node
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Transistor(ABC):
|
|
17
|
+
"""
|
|
18
|
+
Abstract class for three-terminal transistor devices.
|
|
19
|
+
|
|
20
|
+
Each Transistor contains:
|
|
21
|
+
- gate : Node controlling conduction
|
|
22
|
+
- source: One side of the controlled channel
|
|
23
|
+
- drain : The other side of the controlled channel
|
|
24
|
+
|
|
25
|
+
This class defines only structural information and simple access helpers.
|
|
26
|
+
Device-specific conduction rules are implemented by subclasses. All logic
|
|
27
|
+
evaluation and node-group management is performed entirely by the Simulator.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
__slots__ = ("gate", "source", "drain")
|
|
31
|
+
|
|
32
|
+
def __init__(self) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Create a new transistor with dedicated gate, source, and drain Nodes.
|
|
35
|
+
All Nodes begin in high-impedance (Z) state with no drivers. These Nodes
|
|
36
|
+
belong exclusively to this device and are never shared.
|
|
37
|
+
"""
|
|
38
|
+
self.gate: Node = Node()
|
|
39
|
+
self.source: Node = Node()
|
|
40
|
+
self.drain: Node = Node()
|
|
41
|
+
|
|
42
|
+
# --------------------------------------------------------------------------
|
|
43
|
+
# Abstract Methods
|
|
44
|
+
# --------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def is_conducting(self) -> bool:
|
|
48
|
+
"""
|
|
49
|
+
Return True if this transistor is currently conducting.
|
|
50
|
+
|
|
51
|
+
A conducting transistor forms an electrical path between its source and
|
|
52
|
+
drain. The Simulator uses this result to determine whether the two Nodes
|
|
53
|
+
should be treated as members of the same node-group.
|
|
54
|
+
"""
|
|
55
|
+
raise NotImplementedError("Must be implemented by subclasses.")
|
|
56
|
+
|
|
57
|
+
# --------------------------------------------------------------------------
|
|
58
|
+
# Public Methods
|
|
59
|
+
# --------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
def terminals(self) -> tuple[Node, Node, Node]:
|
|
62
|
+
"""
|
|
63
|
+
Return a tuple of (gate, source, drain) Nodes.
|
|
64
|
+
|
|
65
|
+
Used by the Simulator for registration and structural traversal.
|
|
66
|
+
"""
|
|
67
|
+
return (self.gate, self.source, self.drain)
|
|
68
|
+
|
|
69
|
+
def conduction_nodes(self) -> tuple[Node, Node]:
|
|
70
|
+
"""
|
|
71
|
+
Return the (source, drain) Nodes involved in conduction.
|
|
72
|
+
|
|
73
|
+
Used by the Simulator when establishing or removing connectivity.
|
|
74
|
+
"""
|
|
75
|
+
return (self.source, self.drain)
|
|
76
|
+
|
|
77
|
+
# --------------------------------------------------------------------------
|
|
78
|
+
# Debug Representation
|
|
79
|
+
# --------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
def __repr__(self) -> str:
|
|
82
|
+
"""Return a debug representation of this Transistor."""
|
|
83
|
+
name = self.__class__.__name__
|
|
84
|
+
return f"<{name} gate={self.gate} source={self.source} drain={self.drain}>"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ------------------------------------------------------------------------------
|
|
88
|
+
# NMOS Transistor Implementation
|
|
89
|
+
# ------------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class NMOS(Transistor):
|
|
93
|
+
"""
|
|
94
|
+
NMOS transistor device.
|
|
95
|
+
|
|
96
|
+
Conduction Rule:
|
|
97
|
+
- Conducts when the gate value is LogicValue.ONE.
|
|
98
|
+
- Non-conducting for ZERO, X, or Z.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def is_conducting(self) -> bool:
|
|
102
|
+
g = self.gate.value
|
|
103
|
+
return g is LogicValue.ONE
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# ------------------------------------------------------------------------------
|
|
107
|
+
# PMOS Transistor Implementation
|
|
108
|
+
# ------------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class PMOS(Transistor):
|
|
112
|
+
"""
|
|
113
|
+
PMOS transistor device.
|
|
114
|
+
|
|
115
|
+
Conduction Rule:
|
|
116
|
+
- Conducts when the gate value is LogicValue.ZERO.
|
|
117
|
+
- Non-conducting for ONE, X, or Z.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
def is_conducting(self) -> bool:
|
|
121
|
+
g = self.gate.value
|
|
122
|
+
return g is LogicValue.ZERO
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from sirc.core.logic import LogicValue as LogicValue
|
|
4
|
+
from sirc.core.node import Node as Node
|
|
5
|
+
|
|
6
|
+
class Transistor(ABC, metaclass=abc.ABCMeta):
|
|
7
|
+
gate: Node
|
|
8
|
+
source: Node
|
|
9
|
+
drain: Node
|
|
10
|
+
def __init__(self) -> None: ...
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def is_conducting(self) -> bool: ...
|
|
13
|
+
def terminals(self) -> tuple[Node, Node, Node]: ...
|
|
14
|
+
def conduction_nodes(self) -> tuple[Node, Node]: ...
|
|
15
|
+
|
|
16
|
+
class NMOS(Transistor):
|
|
17
|
+
def is_conducting(self) -> bool: ...
|
|
18
|
+
|
|
19
|
+
class PMOS(Transistor):
|
|
20
|
+
def is_conducting(self) -> bool: ...
|
|
File without changes
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SIRC Device Simulator Module.
|
|
3
|
+
|
|
4
|
+
Provides the DeviceSimulator class, responsible for evaluating a circuit
|
|
5
|
+
composed of Nodes, LogicDevices, and Transistors. The simulator performs
|
|
6
|
+
fixed-point iteration to resolve driver values, establish dynamic conduction
|
|
7
|
+
paths, and propagate LogicValues across connected node-groups.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
from typing import Iterable
|
|
12
|
+
from sirc.core.logic import LogicValue
|
|
13
|
+
from sirc.core.node import Node
|
|
14
|
+
from sirc.core.device import LogicDevice
|
|
15
|
+
from sirc.core.transistor import Transistor
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DeviceSimulator:
|
|
19
|
+
"""
|
|
20
|
+
Simulator for evaluating SIRC logic devices and transistors.
|
|
21
|
+
|
|
22
|
+
The DeviceSimulator maintains registered devices, transistors, and nodes.
|
|
23
|
+
Each tick clears drivers, applies device outputs, resolves node-groups via
|
|
24
|
+
DFS, and updates dynamic connectivity created by transistor conduction.
|
|
25
|
+
Fixed-point iteration continues until the circuit reaches a stable state.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self) -> None:
|
|
29
|
+
"""SIRC"""
|
|
30
|
+
self.devices: set[LogicDevice] = set()
|
|
31
|
+
self.transistors: set[Transistor] = set()
|
|
32
|
+
self.nodes: set[Node] = set()
|
|
33
|
+
|
|
34
|
+
# --------------------------------------------------------------------------
|
|
35
|
+
# Device Registration
|
|
36
|
+
# --------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
def register_device(self, device: LogicDevice) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Register a LogicDevice and its terminal Node with the simulator.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
device: The LogicDevice to register.
|
|
44
|
+
"""
|
|
45
|
+
self.devices.add(device)
|
|
46
|
+
self.nodes.add(device.terminal)
|
|
47
|
+
|
|
48
|
+
def register_devices(self, devices: Iterable[LogicDevice]) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Register multiple LogicDevices and terminal Nodes with the simulator.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
devices: An iterable of LogicDevices to register.
|
|
54
|
+
"""
|
|
55
|
+
for device in devices:
|
|
56
|
+
self.register_device(device)
|
|
57
|
+
|
|
58
|
+
def register_transistor(self, transistor: Transistor) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Register a Transistor and its terminal Nodes with the simulator.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
transistor: The Transistor to register.
|
|
64
|
+
"""
|
|
65
|
+
self.transistors.add(transistor)
|
|
66
|
+
self.nodes.update(transistor.terminals())
|
|
67
|
+
|
|
68
|
+
def register_transistors(self, transistors: Iterable[Transistor]) -> None:
|
|
69
|
+
"""
|
|
70
|
+
Register multiple Transistors and terminal Nodes with the simulator.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
transistors: An iterable of Transistors to register.
|
|
74
|
+
"""
|
|
75
|
+
for transistor in transistors:
|
|
76
|
+
self.register_transistor(transistor)
|
|
77
|
+
|
|
78
|
+
def unregister_device(self, device: LogicDevice) -> None:
|
|
79
|
+
"""
|
|
80
|
+
Unregister a LogicDevice and its terminal Node from the simulator.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
device: The LogicDevice to unregister.
|
|
84
|
+
"""
|
|
85
|
+
self.devices.discard(device)
|
|
86
|
+
self.nodes.discard(device.terminal)
|
|
87
|
+
|
|
88
|
+
def unregister_devices(self, devices: Iterable[LogicDevice]) -> None:
|
|
89
|
+
"""
|
|
90
|
+
Unregister multiple LogicDevices and terminal Nodes from the simulator.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
devices: An iterable of LogicDevices to unregister.
|
|
94
|
+
"""
|
|
95
|
+
for device in devices:
|
|
96
|
+
self.unregister_device(device)
|
|
97
|
+
|
|
98
|
+
def unregister_transistor(self, transistor: Transistor) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Unregister a Transistor and its terminal Nodes from the simulator.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
transistor: The Transistor to unregister.
|
|
104
|
+
"""
|
|
105
|
+
self.transistors.discard(transistor)
|
|
106
|
+
self.nodes.difference_update(transistor.terminals())
|
|
107
|
+
|
|
108
|
+
def unregister_transistors(self, transistors: Iterable[Transistor]) -> None:
|
|
109
|
+
"""
|
|
110
|
+
Unregister multiple Transistors and terminal Nodes from the simulator.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
transistors: An iterable of Transistors to unregister.
|
|
114
|
+
"""
|
|
115
|
+
for transistor in transistors:
|
|
116
|
+
self.unregister_transistor(transistor)
|
|
117
|
+
|
|
118
|
+
# --------------------------------------------------------------------------
|
|
119
|
+
# Logical Connection
|
|
120
|
+
# --------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
def connect(self, a: Node, b: Node) -> None:
|
|
123
|
+
"""
|
|
124
|
+
Create a bidirectional connection between two Nodes.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
a: The first Node.
|
|
128
|
+
b: The second Node.
|
|
129
|
+
"""
|
|
130
|
+
a.connect(b)
|
|
131
|
+
|
|
132
|
+
def disconnect(self, a: Node, b: Node) -> None:
|
|
133
|
+
"""
|
|
134
|
+
Remove the bidirectional connection between two Nodes.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
a: The first Node.
|
|
138
|
+
b: The second Node.
|
|
139
|
+
"""
|
|
140
|
+
a.disconnect(b)
|
|
141
|
+
|
|
142
|
+
# --------------------------------------------------------------------------
|
|
143
|
+
# Simulation Execution
|
|
144
|
+
# --------------------------------------------------------------------------
|
|
145
|
+
|
|
146
|
+
def _dfs(self, collection: Iterable[Node]) -> list[set[Node]]:
|
|
147
|
+
"""
|
|
148
|
+
Perform depth-first search to identify connected node-groups.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
collection: Iterable of Nodes to explore.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
List of sets, each containing Nodes in a connected group.
|
|
155
|
+
"""
|
|
156
|
+
visited: set[Node] = set()
|
|
157
|
+
stack: list[Node] = []
|
|
158
|
+
groups: list[set[Node]] = []
|
|
159
|
+
|
|
160
|
+
for start in collection:
|
|
161
|
+
if start in visited:
|
|
162
|
+
continue
|
|
163
|
+
|
|
164
|
+
stack.append(start)
|
|
165
|
+
group: set[Node] = set()
|
|
166
|
+
|
|
167
|
+
while stack:
|
|
168
|
+
node = stack.pop()
|
|
169
|
+
|
|
170
|
+
if node in visited:
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
visited.add(node)
|
|
174
|
+
group.add(node)
|
|
175
|
+
|
|
176
|
+
for neighbor in node.get_connections():
|
|
177
|
+
if neighbor not in visited:
|
|
178
|
+
stack.append(neighbor)
|
|
179
|
+
|
|
180
|
+
groups.append(group)
|
|
181
|
+
|
|
182
|
+
return groups
|
|
183
|
+
|
|
184
|
+
def _resolve_groups(self, groups: list[set[Node]]) -> None:
|
|
185
|
+
"""
|
|
186
|
+
Resolve LogicValues for each connected node-group.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
groups: List of node-groups to resolve.
|
|
190
|
+
"""
|
|
191
|
+
for group in groups:
|
|
192
|
+
drivers: list[LogicValue] = [LogicValue.Z]
|
|
193
|
+
|
|
194
|
+
for node in group:
|
|
195
|
+
drivers.extend(node.get_drivers())
|
|
196
|
+
|
|
197
|
+
resolved_value: LogicValue = LogicValue.resolve_all(drivers)
|
|
198
|
+
|
|
199
|
+
for node in group:
|
|
200
|
+
node.set_resolved_value(resolved_value)
|
|
201
|
+
|
|
202
|
+
def tick(self) -> None:
|
|
203
|
+
"""
|
|
204
|
+
Execute a simulation tick to update device states and connectivity.
|
|
205
|
+
|
|
206
|
+
This method performs the following steps:
|
|
207
|
+
1. Clears all Node drivers.
|
|
208
|
+
2. Applies LogicDevice outputs to their terminal Nodes.
|
|
209
|
+
3. Repeatedly:
|
|
210
|
+
a. Identifies connected node-groups via DFS.
|
|
211
|
+
b. Resolves LogicValues for each group.
|
|
212
|
+
c. Updates transistor conduction paths.
|
|
213
|
+
4. Continues until a fixed-point state is reached.
|
|
214
|
+
"""
|
|
215
|
+
for node in self.nodes:
|
|
216
|
+
node.clear_drivers()
|
|
217
|
+
|
|
218
|
+
for device in self.devices:
|
|
219
|
+
device.terminal.add_driver(device.value)
|
|
220
|
+
|
|
221
|
+
while True:
|
|
222
|
+
groups = self._dfs(self.nodes)
|
|
223
|
+
self._resolve_groups(groups)
|
|
224
|
+
fixed_point = True
|
|
225
|
+
|
|
226
|
+
for transistor in self.transistors:
|
|
227
|
+
a, b = transistor.conduction_nodes()
|
|
228
|
+
if transistor.is_conducting():
|
|
229
|
+
if a not in b.get_connections():
|
|
230
|
+
transistor.source.connect(transistor.drain)
|
|
231
|
+
fixed_point = False
|
|
232
|
+
else:
|
|
233
|
+
if a in b.get_connections():
|
|
234
|
+
transistor.source.disconnect(transistor.drain)
|
|
235
|
+
fixed_point = False
|
|
236
|
+
|
|
237
|
+
if fixed_point:
|
|
238
|
+
break
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from sirc.core.device import LogicDevice as LogicDevice
|
|
2
|
+
from sirc.core.logic import LogicValue as LogicValue
|
|
3
|
+
from sirc.core.node import Node as Node
|
|
4
|
+
from sirc.core.transistor import Transistor as Transistor
|
|
5
|
+
from typing import Iterable
|
|
6
|
+
|
|
7
|
+
class DeviceSimulator:
|
|
8
|
+
devices: set[LogicDevice]
|
|
9
|
+
transistors: set[Transistor]
|
|
10
|
+
nodes: set[Node]
|
|
11
|
+
def __init__(self) -> None: ...
|
|
12
|
+
def register_device(self, device: LogicDevice) -> None: ...
|
|
13
|
+
def register_devices(self, devices: Iterable[LogicDevice]) -> None: ...
|
|
14
|
+
def register_transistor(self, transistor: Transistor) -> None: ...
|
|
15
|
+
def register_transistors(self, transistors: Iterable[Transistor]) -> None: ...
|
|
16
|
+
def unregister_device(self, device: LogicDevice) -> None: ...
|
|
17
|
+
def unregister_devices(self, devices: Iterable[LogicDevice]) -> None: ...
|
|
18
|
+
def unregister_transistor(self, transistor: Transistor) -> None: ...
|
|
19
|
+
def unregister_transistors(self, transistors: Iterable[Transistor]) -> None: ...
|
|
20
|
+
def connect(self, a: Node, b: Node) -> None: ...
|
|
21
|
+
def disconnect(self, a: Node, b: Node) -> None: ...
|
|
22
|
+
def tick(self) -> None: ...
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sirc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: SIRC - Digital Logic and Circuit Simulation Engine
|
|
5
|
+
Author-email: CRISvsGAME <cris@crisvsgame.com>
|
|
6
|
+
Maintainer-email: CRISvsGAME <cris@crisvsgame.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Repository, https://github.com/CRISvsGAME/sirc.git
|
|
9
|
+
Keywords: digital logic,circuit simulation,simulation engine
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: build; extra == "dev"
|
|
19
|
+
Requires-Dist: mypy; extra == "dev"
|
|
20
|
+
Requires-Dist: pylint; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest; extra == "dev"
|
|
22
|
+
Requires-Dist: twine; extra == "dev"
|
|
23
|
+
|
|
24
|
+
# SIRC
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/sirc/__init__.py
|
|
4
|
+
src/sirc.egg-info/PKG-INFO
|
|
5
|
+
src/sirc.egg-info/SOURCES.txt
|
|
6
|
+
src/sirc.egg-info/dependency_links.txt
|
|
7
|
+
src/sirc.egg-info/requires.txt
|
|
8
|
+
src/sirc.egg-info/top_level.txt
|
|
9
|
+
src/sirc/core/__init__.py
|
|
10
|
+
src/sirc/core/device.py
|
|
11
|
+
src/sirc/core/device.pyi
|
|
12
|
+
src/sirc/core/logic.py
|
|
13
|
+
src/sirc/core/logic.pyi
|
|
14
|
+
src/sirc/core/node.py
|
|
15
|
+
src/sirc/core/node.pyi
|
|
16
|
+
src/sirc/core/transistor.py
|
|
17
|
+
src/sirc/core/transistor.pyi
|
|
18
|
+
src/sirc/simulator/__init__.py
|
|
19
|
+
src/sirc/simulator/device.py
|
|
20
|
+
src/sirc/simulator/device.pyi
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sirc
|