logicuit 0.2.0 → 0.3.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -0
- data/README.md +300 -18
- data/lib/logicuit/array_as_signal_group.rb +13 -0
- data/lib/logicuit/circuits/combinational/full_adder.rb +28 -30
- data/lib/logicuit/circuits/combinational/full_adder_4bit.rb +13 -28
- data/lib/logicuit/circuits/combinational/half_adder.rb +8 -10
- data/lib/logicuit/circuits/combinational/multiplexer_2to1.rb +7 -9
- data/lib/logicuit/circuits/combinational/multiplexer_4to1.rb +11 -15
- data/lib/logicuit/circuits/sequential/d_flip_flop.rb +3 -5
- data/lib/logicuit/circuits/{system_level/one_bit_cpu2.rb → sequential/one_bit_cpu.rb} +13 -15
- data/lib/logicuit/circuits/sequential/program_counter.rb +6 -8
- data/lib/logicuit/circuits/sequential/register_4bit.rb +12 -14
- data/lib/logicuit/circuits/{system_level/cpu_td4.rb → td4/cpu.rb} +34 -59
- data/lib/logicuit/circuits/{combinational → td4}/decoder.rb +9 -11
- data/lib/logicuit/circuits/{rom/timer.rb → td4/rom.rb} +7 -5
- data/lib/logicuit/{base.rb → dsl.rb} +40 -107
- data/lib/logicuit/gates/and.rb +5 -7
- data/lib/logicuit/gates/nand.rb +5 -7
- data/lib/logicuit/gates/not.rb +3 -5
- data/lib/logicuit/gates/or.rb +5 -7
- data/lib/logicuit/gates/xor.rb +5 -7
- data/lib/logicuit/runner.rb +45 -0
- data/lib/logicuit/signals/clock.rb +18 -15
- data/lib/logicuit/signals/signal.rb +29 -24
- data/lib/logicuit/signals/signal_group.rb +26 -0
- data/lib/logicuit/version.rb +1 -1
- data/lib/logicuit.rb +8 -6
- metadata +10 -8
- data/lib/logicuit/circuits/system_level/one_bit_cpu.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51ce3fab568abef949848bf4f1cb8c8dbe3f0f80da773b9f6f48ea374e21c376
|
4
|
+
data.tar.gz: 787d8ae4a61d770bba76612b5a7ffffbee750dfe0d645dae4a89c57e130ecdc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28dcfd69c6f889c27283f46928dabcf178ba0113609f36895ab4e10642e36eff631070573946b5d5c7dd4ab06180d7b5649e524d855c977ab361d20675ece5b6
|
7
|
+
data.tar.gz: 4b253121ffffc6d0f06e53f07c23bde1bc371c91b2217ba91cfe46fd134376b0c2c0dac7146afad73d12f02a8a7fc1d0ad1242c85a11888a1b00434a63c5ceaf
|
data/.rubocop.yml
CHANGED
@@ -14,6 +14,18 @@ Layout/LineLength:
|
|
14
14
|
Style/NumericPredicate:
|
15
15
|
Enabled: false
|
16
16
|
|
17
|
+
Style/OptionalBooleanParameter:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
Style/SymbolProc:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Style/MultilineBlockChain:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Naming/MethodParameterName:
|
27
|
+
Enabled: false
|
28
|
+
|
17
29
|
Metrics:
|
18
30
|
Enabled: false
|
19
31
|
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Logicuit
|
2
2
|
|
3
|
-
|
3
|
+
From logic circuit to Logicuit — a playful portmanteau.
|
4
|
+
|
5
|
+
A Ruby-based logic circuit simulator featuring an internal DSL for building circuits.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -16,50 +18,330 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
16
18
|
gem install logicuit
|
17
19
|
```
|
18
20
|
|
19
|
-
##
|
21
|
+
## DSL
|
22
|
+
|
23
|
+
This library provides an internal DSL for defining logic circuits in a declarative and readable way.
|
24
|
+
You can define inputs, outputs, and even a visual diagram — all within a Ruby class.
|
25
|
+
|
26
|
+
Here is an example of a simple 2-input AND gate:
|
27
|
+
|
28
|
+
```
|
29
|
+
require "logicuit"
|
30
|
+
|
31
|
+
class MyAndGate < Logicuit::DSL
|
32
|
+
inputs :a, :b
|
20
33
|
|
21
|
-
|
34
|
+
outputs y: -> { a && b }
|
35
|
+
|
36
|
+
diagram <<~DIAGRAM
|
37
|
+
(A)-| |
|
38
|
+
|AND|-(Y)
|
39
|
+
(B)-| |
|
40
|
+
DIAGRAM
|
41
|
+
end
|
22
42
|
|
43
|
+
MyAndGate.run
|
23
44
|
```
|
24
|
-
require 'logicuit'
|
25
45
|
|
26
|
-
|
27
|
-
|
46
|
+
This defines:
|
47
|
+
|
48
|
+
- two inputs (`a` and `b`),
|
49
|
+
- one output (`y`) that returns the logical AND of the inputs,
|
50
|
+
- and an ASCII diagram that shows the structure of the gate.
|
51
|
+
|
52
|
+
### Interactive execution
|
53
|
+
|
54
|
+
When you call `run`, the simulator enters an interactive mode.
|
55
|
+
|
56
|
+
At first, the circuit is evaluated with all inputs set to `0`, and drawn as an ASCII diagram:
|
57
|
+
|
58
|
+
```
|
59
|
+
(0)-| |
|
60
|
+
|AND|-(0)
|
61
|
+
(0)-| |
|
62
|
+
|
63
|
+
input: a,b?
|
64
|
+
```
|
65
|
+
|
66
|
+
To interact with the circuit, just type the name of an input — for example, `a` — and press Enter.
|
67
|
+
That input will toggle its value (`0 → 1` or `1 → 0`), and the diagram will be redrawn to reflect the new state.
|
68
|
+
You can keep toggling inputs this way to observe how the circuit reacts in real time.
|
69
|
+
|
70
|
+
To exit the simulator, simply press `Ctrl+C`.
|
71
|
+
|
72
|
+
### Assembling circuits
|
73
|
+
|
74
|
+
In addition to defining simple gates declaratively, Logicuit also lets you assemble circuits from reusable components using the `assembling` block.
|
75
|
+
|
76
|
+
This approach gives you more control and expressiveness when building complex circuits.
|
77
|
+
|
78
|
+
Here's an example of a 2-to-1 multiplexer:
|
79
|
+
|
80
|
+
```
|
81
|
+
require "logicuit"
|
82
|
+
|
83
|
+
class MyMultiplexer < Logicuit::DSL
|
84
|
+
inputs :c0, :c1, :a
|
85
|
+
|
86
|
+
outputs :y
|
87
|
+
|
88
|
+
assembling do
|
89
|
+
and_gate1 = Logicuit::Gates::And.new
|
90
|
+
and_gate2 = Logicuit::Gates::And.new
|
91
|
+
not_gate = Logicuit::Gates::Not.new
|
92
|
+
or_gate = Logicuit::Gates::Or.new
|
93
|
+
|
94
|
+
c0 >> and_gate1.a
|
95
|
+
a >> not_gate.a
|
96
|
+
not_gate.y >> and_gate1.b
|
97
|
+
|
98
|
+
c1 >> and_gate2.a
|
99
|
+
a >> and_gate2.b
|
100
|
+
|
101
|
+
and_gate1.y >> or_gate.a
|
102
|
+
and_gate2.y >> or_gate.b
|
103
|
+
or_gate.y >> y
|
104
|
+
end
|
28
105
|
|
29
106
|
diagram <<~DIAGRAM
|
30
|
-
(C0)---------|
|
107
|
+
(C0)---------| |
|
31
108
|
|AND|--+
|
32
|
-
+-|NOT|-|
|
109
|
+
+-|NOT|-| | +--| |
|
33
110
|
| |OR|--(Y)
|
34
|
-
(C1)---------|
|
111
|
+
(C1)---------| | +--| |
|
35
112
|
| |AND|--+
|
36
|
-
(A)--+-------|
|
113
|
+
(A)--+-------| |
|
37
114
|
DIAGRAM
|
115
|
+
end
|
116
|
+
|
117
|
+
MyMultiplexer.run
|
118
|
+
```
|
119
|
+
|
120
|
+
### Connection syntax
|
121
|
+
|
122
|
+
The `>>` operator is used to connect outputs to inputs, mimicking the direction of signal flow.
|
123
|
+
|
124
|
+
This allows the code to resemble the actual structure of the circuit, making it more intuitive to follow.
|
125
|
+
|
126
|
+
For example:
|
127
|
+
|
128
|
+
```
|
129
|
+
a >> not_gate.a
|
130
|
+
not_gate.y >> and_gate1.b
|
131
|
+
```
|
132
|
+
|
133
|
+
can be read as:
|
134
|
+
|
135
|
+
*"Connect input `a` to the NOT gate's input. Then connect the NOT gate's output to one of the AND gate's inputs."*
|
136
|
+
|
137
|
+
### Built-in gates
|
138
|
+
|
139
|
+
Logicuit includes several built-in logic gates, which you can use as components:
|
140
|
+
|
141
|
+
- `Logicuit::Gates::And`
|
142
|
+
- `Logicuit::Gates::Or`
|
143
|
+
- `Logicuit::Gates::Not`
|
144
|
+
- `Logicuit::Gates::Nand`
|
145
|
+
- `Logicuit::Gates::Xor`
|
146
|
+
|
147
|
+
These gates expose their input and output pins as attributes (`a`, `b`, `y`, etc.), which can be freely connected using `>>`.
|
148
|
+
|
149
|
+
### Signal groups
|
150
|
+
|
151
|
+
When building larger circuits, it's common to connect one output to multiple inputs, or to connect multiple outputs to multiple inputs.
|
152
|
+
|
153
|
+
Logicuit provides a convenient way to express these kinds of connections using signal groups.
|
154
|
+
|
155
|
+
#### One-to-many connections
|
156
|
+
|
157
|
+
These two lines:
|
158
|
+
|
159
|
+
```
|
160
|
+
a >> xor_gate.a
|
161
|
+
a >> and_gate.a
|
162
|
+
```
|
163
|
+
|
164
|
+
can be written more concisely as:
|
165
|
+
|
166
|
+
```
|
167
|
+
a >> [xor_gate.a, and_gate.a]
|
168
|
+
```
|
169
|
+
|
170
|
+
The array on the right-hand side is treated as a signal group, and the connection is applied to each element.
|
171
|
+
|
172
|
+
#### Many-to-many connections
|
38
173
|
|
39
|
-
|
174
|
+
You can also connect multiple outputs to multiple inputs at once by using the [] method to access signals by name:
|
40
175
|
|
41
|
-
|
176
|
+
```
|
177
|
+
pc.qa >> rom.a0
|
178
|
+
pc.qb >> rom.a1
|
179
|
+
pc.qc >> rom.a2
|
180
|
+
pc.qd >> rom.a3
|
181
|
+
```
|
182
|
+
|
183
|
+
is equivalent to:
|
184
|
+
|
185
|
+
```
|
186
|
+
pc[:qa, :qb, :qc, :qd] >> rom[:a0, :a1, :a2, :a3]
|
187
|
+
```
|
188
|
+
|
189
|
+
This `#[](*keys)` method returns a `SignalGroup` object — a Logicuit abstraction that makes it easier to handle groups of signals together.
|
190
|
+
|
191
|
+
> Note: The number of signals on both sides must match.
|
192
|
+
|
193
|
+
#### Connecting from different sources
|
194
|
+
|
195
|
+
What if you want to connect signals from multiple different components as a single group?
|
196
|
+
|
197
|
+
You can use `Logicuit::ArrayAsSignalGroup`, which adds signal group behavior to arrays:
|
198
|
+
|
199
|
+
```
|
200
|
+
using Logicuit::ArrayAsSignalGroup
|
201
|
+
|
202
|
+
assembling do
|
203
|
+
[register_a.qa, register_b.qa, in0] >> mux0[:c0, :c1, :c2]
|
42
204
|
end
|
205
|
+
```
|
206
|
+
|
207
|
+
This lets you treat a plain Ruby array as a `SignalGroup` and connect it to another group of inputs in one line.
|
208
|
+
|
209
|
+
### Sequential circuits
|
210
|
+
|
211
|
+
In addition to combinational circuits, Logicuit also supports sequential circuits — circuits whose output depends not only on the current inputs, but also on past inputs.
|
212
|
+
|
213
|
+
For example, here’s a D flip-flop:
|
43
214
|
|
44
|
-
Logicuit.run(:MY_MUX)
|
45
215
|
```
|
216
|
+
require "logicuit"
|
217
|
+
|
218
|
+
class MyDFlipFlop < Logicuit::DSL
|
219
|
+
inputs :d, clock: :ck
|
46
220
|
|
47
|
-
|
221
|
+
outputs q: -> { d }
|
222
|
+
|
223
|
+
diagram <<~DIAGRAM
|
224
|
+
(D)--| |--(Q)
|
225
|
+
|DFF|
|
226
|
+
(CK)-|> |
|
227
|
+
DIAGRAM
|
228
|
+
end
|
48
229
|
|
230
|
+
MyDFlipFlop.run
|
49
231
|
```
|
50
|
-
|
232
|
+
|
233
|
+
#### Defining a sequential circuit
|
234
|
+
|
235
|
+
A circuit becomes sequential when the `inputs` declaration includes a keyword argument named `clock:`.
|
236
|
+
You can assign any name to the clock signal — in the above example, it's `:ck` — but the presence of the `clock:` keyword is what tells Logicuit to treat the circuit as sequential.
|
237
|
+
|
238
|
+
Once a clock is defined:
|
239
|
+
|
240
|
+
- The `outputs` lambdas will be evaluated on each clock tick, not continuously.
|
241
|
+
- A global singleton clock will drive the timing — you don’t need to define or manage the clock yourself.
|
242
|
+
|
243
|
+
#### Interactive execution with a clock
|
244
|
+
|
245
|
+
When a sequential circuit is run interactively, Logicuit enters clock mode. The clock ticks periodically, and the circuit is redrawn after each tick.
|
246
|
+
|
51
247
|
```
|
248
|
+
(0)--| |--(0)
|
249
|
+
|DFF|
|
250
|
+
(CK)-|> |
|
52
251
|
|
53
|
-
|
252
|
+
tick: 2
|
253
|
+
input: d?
|
254
|
+
```
|
255
|
+
|
256
|
+
You can still toggle inputs as before (e.g., type `d` and press Enter), but updates take effect on the next tick.
|
257
|
+
|
258
|
+
The number of elapsed ticks is shown as `tick: N`.
|
259
|
+
|
260
|
+
#### Clock speed
|
261
|
+
|
262
|
+
By default, the clock ticks at 1 Hz (once per second). You can change the frequency by passing the `hz:` option to `run`:
|
263
|
+
|
264
|
+
```
|
265
|
+
MyDFlipFlop.run(hz: 10)
|
266
|
+
```
|
267
|
+
|
268
|
+
This will run the clock at 10 ticks per second — useful when simulating more complex circuits.
|
269
|
+
|
270
|
+
If you want full control, you can set `hz: 0` to disable automatic ticking.
|
271
|
+
|
272
|
+
In this mode, the clock only ticks when you press Enter, allowing you to step through the simulation manually:
|
273
|
+
|
274
|
+
```
|
275
|
+
MyDFlipFlop.run(hz: 0)
|
276
|
+
```
|
277
|
+
|
278
|
+
This is useful for debugging or analyzing a circuit’s behavior step by step.
|
279
|
+
|
280
|
+
#### Combining sequential circuits with `assembling`
|
281
|
+
|
282
|
+
You can build sequential circuits out of smaller components using the `assembling` block, just like with combinational circuits.
|
283
|
+
|
284
|
+
Here’s an example of a 4-bit register that stores its input when the load signal `ld` is not active:
|
54
285
|
|
55
286
|
```
|
56
|
-
|
287
|
+
require "logicuit"
|
288
|
+
|
289
|
+
class MyRegister4bit < Logicuit::DSL
|
290
|
+
inputs :a, :b, :c, :d, :ld, clock: :ck
|
291
|
+
|
292
|
+
outputs :qa, :qb, :qc, :qd
|
293
|
+
|
294
|
+
assembling do
|
295
|
+
[[a, qa], [b, qb], [c, qc], [d, qd]].each do |input, output|
|
296
|
+
dff = Logicuit::Circuits::Sequential::DFlipFlop.new
|
297
|
+
mux = Logicuit::Circuits::Combinational::Multiplexer2to1.new
|
298
|
+
input >> mux.c0
|
299
|
+
dff.q >> mux.c1
|
300
|
+
ld >> mux.a
|
301
|
+
mux.y >> dff.d
|
302
|
+
dff.q >> output
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
diagram <<~DIAGRAM
|
307
|
+
+---------------------+
|
308
|
+
+-| | |
|
309
|
+
(A)-------|MUX|-------|DFF|---+---(QA)
|
310
|
+
+---| | +---| |
|
311
|
+
| |
|
312
|
+
| +---------------------+
|
313
|
+
| +-| | | |
|
314
|
+
(B)-------|MUX|-------|DFF|---+---(QB)
|
315
|
+
+---| | +---| |
|
316
|
+
| |
|
317
|
+
| +---------------------+
|
318
|
+
| +-| | | |
|
319
|
+
(C)-------|MUX|-------|DFF|---+---(QC)
|
320
|
+
+---| | +---| |
|
321
|
+
| |
|
322
|
+
| +---------------------+
|
323
|
+
| +-| | | |
|
324
|
+
(D)-------|MUX|-------|DFF|---+---(QD)
|
325
|
+
+---| | +---| |
|
326
|
+
(LD)--+ (CK)--+
|
327
|
+
DIAGRAM
|
328
|
+
end
|
329
|
+
|
330
|
+
MyRegister4bit.run
|
57
331
|
```
|
58
332
|
|
333
|
+
#### Sequential detection
|
334
|
+
|
335
|
+
If your circuit contains one or more sequential components (such as D flip-flops), Logicuit will treat the entire circuit as sequential, as long as you declare a clock input using the `clock:` keyword in `inputs`.
|
336
|
+
|
337
|
+
The clock signal is automatically connected to all internal sequential components. You don't need to wire it manually — just declare it at the top level:
|
338
|
+
|
59
339
|
```
|
60
|
-
|
340
|
+
inputs ..., clock: :ck
|
61
341
|
```
|
62
342
|
|
343
|
+
> Note: If you forget to declare a clock input, Logicuit won't know it's a sequential circuit — even if you include flip-flops internally. Always include `clock:` to enable timing.
|
344
|
+
|
63
345
|
## Development
|
64
346
|
|
65
347
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Logicuit module
|
4
|
+
module Logicuit
|
5
|
+
# Treats Array#>> as SignalGroup#>> for the purpose of connecting signals
|
6
|
+
module ArrayAsSignalGroup
|
7
|
+
refine Array do
|
8
|
+
def >>(other)
|
9
|
+
Signals::SignalGroup.new(*self).connects_to(other)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -4,51 +4,49 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Combinational
|
6
6
|
# FullAdder class
|
7
|
-
class FullAdder <
|
8
|
-
tag :FADD
|
9
|
-
|
7
|
+
class FullAdder < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
9
|
(Cin)---+-|NOT|-----+
|
12
10
|
| |
|
13
11
|
(A)---+---|NOT|---+ |
|
14
12
|
| | | |
|
15
|
-
(B)-+-----|NOT|-+ | +-|
|
13
|
+
(B)-+-----|NOT|-+ | +-| |
|
16
14
|
| | | | +---|AND|---+
|
17
|
-
+-----------------|
|
18
|
-
| | | | | | +-|
|
19
|
-
| | | | | +-|
|
20
|
-
| +---------------|AND|-----|
|
21
|
-
| | | +-----|
|
15
|
+
+-----------------| | |
|
16
|
+
| | | | | | +-| |
|
17
|
+
| | | | | +-| | | |
|
18
|
+
| +---------------|AND|-----| |
|
19
|
+
| | | +-----| | | |
|
22
20
|
| | | | | | |OR|-(S)
|
23
|
-
| | +-------------|
|
24
|
-
| | | | +---|AND|-----|
|
25
|
-
| | | +-----|
|
26
|
-
| | | | | | +-|
|
27
|
-
| | +-------------|
|
21
|
+
| | +-------------| | | |
|
22
|
+
| | | | +---|AND|-----| |
|
23
|
+
| | | +-----| | | |
|
24
|
+
| | | | | | +-| |
|
25
|
+
| | +-------------| | |
|
28
26
|
| +---------------|AND|---+
|
29
|
-
+-----------------|
|
27
|
+
+-----------------| |
|
30
28
|
| | | | | |
|
31
|
-
| | | | | +-|
|
29
|
+
| | | | | +-| |
|
32
30
|
| +---------------|AND|---+
|
33
|
-
+-----------------|
|
34
|
-
| | | | | +-|
|
35
|
-
| | +-------------|
|
36
|
-
| | | | +---|AND|-----|
|
37
|
-
+-----------------|
|
31
|
+
+-----------------| | |
|
32
|
+
| | | | | +-| |
|
33
|
+
| | +-------------| | | |
|
34
|
+
| | | | +---|AND|-----| |
|
35
|
+
+-----------------| | | |
|
38
36
|
| | | | |OR|-(C)
|
39
|
-
| | +-------------|
|
40
|
-
| +---------------|AND|-----|
|
41
|
-
| | | +-----|
|
42
|
-
| | | +-|
|
43
|
-
| | +-------------|
|
37
|
+
| | +-------------| | | |
|
38
|
+
| +---------------|AND|-----| |
|
39
|
+
| | | +-----| | | |
|
40
|
+
| | | +-| |
|
41
|
+
| | +-------------| | |
|
44
42
|
| +---------------|AND|---+
|
45
|
-
+-----------------|
|
43
|
+
+-----------------| |
|
46
44
|
DIAGRAM
|
47
45
|
|
48
|
-
|
46
|
+
inputs :cin, :a, :b
|
49
47
|
|
50
|
-
|
51
|
-
|
48
|
+
outputs s: -> { (!cin && !a && b) || (!cin && a && !b) || (cin && !a && !b) || (cin && a && b) },
|
49
|
+
c: -> { (!cin && a && b) || (cin && !a && b) || (cin && a && !b) || (cin && a && b) }
|
52
50
|
|
53
51
|
truth_table <<~TRUTH_TABLE
|
54
52
|
| Cin | A | B | C | S |
|
@@ -4,39 +4,24 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Combinational
|
6
6
|
# FullAdder class
|
7
|
-
class FullAdder4bit <
|
8
|
-
tag :FADD4
|
9
|
-
|
7
|
+
class FullAdder4bit < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
|
-
(Cin)-| |--(S0)
|
12
|
-
(A0)--|FADD|
|
13
|
-
(B0)--| |--+
|
14
|
-
|
15
|
-
|
16
|
-
|
|
17
|
-
+--| |--(S1)
|
18
|
-
(A1)--|FADD|
|
19
|
-
(B1)--| |--+
|
20
|
-
|
|
21
|
-
+----------+
|
9
|
+
(Cin)-| |--(S0) +--------| |--(S1)
|
10
|
+
(A0)--|FADD| | (A1)--|FADD|
|
11
|
+
(B0)--| |--------+ (B1)--| |--+
|
12
|
+
|
|
13
|
+
+---------------------------------+
|
22
14
|
|
|
23
|
-
+--| |--(S2)
|
24
|
-
(A2)--|FADD|
|
25
|
-
(B2)--|
|
26
|
-
|
|
27
|
-
+----------+
|
28
|
-
|
|
29
|
-
+--| |--(S3)
|
30
|
-
(A3)--|FADD|
|
31
|
-
(B3)--| |---(C)
|
32
|
-
|
15
|
+
+--| |--(S2) +--------| |--(S3)
|
16
|
+
(A2)--|FADD| | (A3)--|FADD|
|
17
|
+
(B2)--| |--------+ (B3)--| |---(C)
|
33
18
|
DIAGRAM
|
34
19
|
|
35
|
-
|
20
|
+
inputs :cin, :a0, :b0, :a1, :b1, :a2, :b2, :a3, :b3
|
36
21
|
|
37
|
-
|
22
|
+
outputs :s0, :s1, :s2, :s3, :c
|
38
23
|
|
39
|
-
assembling do
|
24
|
+
assembling do
|
40
25
|
[[a0, b0, s0], [a1, b1, s1], [a2, b2, s2], [a3, b3, s3]].reduce(cin) do |c, sigs|
|
41
26
|
a, b, s = sigs
|
42
27
|
full_addr = Combinational::FullAdder.new
|
@@ -45,7 +30,7 @@ module Logicuit
|
|
45
30
|
b >> full_addr.b
|
46
31
|
full_addr.s >> s
|
47
32
|
full_addr.c
|
48
|
-
end >>
|
33
|
+
end >> c
|
49
34
|
end
|
50
35
|
end
|
51
36
|
end
|
@@ -4,24 +4,22 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Combinational
|
6
6
|
# HalfAdder class
|
7
|
-
class HalfAdder <
|
8
|
-
tag :HADD
|
9
|
-
|
7
|
+
class HalfAdder < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
|
-
(A)---+-|
|
9
|
+
(A)---+-| |
|
12
10
|
| |XOR|-(S)
|
13
|
-
(B)-+---|
|
11
|
+
(B)-+---| |
|
14
12
|
| |
|
15
|
-
| +-|
|
13
|
+
| +-| |
|
16
14
|
| |AND|-(C)
|
17
|
-
+---|
|
15
|
+
+---| |
|
18
16
|
DIAGRAM
|
19
17
|
|
20
|
-
|
18
|
+
inputs :a, :b
|
21
19
|
|
22
|
-
|
20
|
+
outputs :c, :s
|
23
21
|
|
24
|
-
assembling do
|
22
|
+
assembling do
|
25
23
|
xor_gate = Gates::Xor.new
|
26
24
|
and_gate = Gates::And.new
|
27
25
|
|
@@ -4,22 +4,20 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Combinational
|
6
6
|
# A Multiplexer with 2 inputs and 1 output
|
7
|
-
class Multiplexer2to1 <
|
8
|
-
tag :MUX, :MUX2, :MUX2to1
|
9
|
-
|
7
|
+
class Multiplexer2to1 < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
|
-
(C0)---------|
|
9
|
+
(C0)---------| |
|
12
10
|
|AND|--+
|
13
|
-
+-|NOT|-|
|
11
|
+
+-|NOT|-| | +--| |
|
14
12
|
| |OR|--(Y)
|
15
|
-
(C1)---------|
|
13
|
+
(C1)---------| | +--| |
|
16
14
|
| |AND|--+
|
17
|
-
(A)--+-------|
|
15
|
+
(A)--+-------| |
|
18
16
|
DIAGRAM
|
19
17
|
|
20
|
-
|
18
|
+
inputs :c0, :c1, :a
|
21
19
|
|
22
|
-
|
20
|
+
outputs y: -> { (c0 && !a) || (c1 && a) }
|
23
21
|
|
24
22
|
truth_table <<~TRUTH_TABLE
|
25
23
|
| C0 | C1 | A | Y |
|
@@ -4,36 +4,32 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Combinational
|
6
6
|
# A Multiplexer with 4 inputs and 1 output
|
7
|
-
class Multiplexer4to1 <
|
8
|
-
tag :MUX4, :MUX4TO1
|
9
|
-
|
7
|
+
class Multiplexer4to1 < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
|
-
(C0)---------------|
|
9
|
+
(C0)---------------| |
|
12
10
|
+---|AND|---+
|
13
|
-
| +-|
|
11
|
+
| +-| | |
|
14
12
|
| | |
|
15
|
-
(C1)---------------|
|
13
|
+
(C1)---------------| | +-|
|
16
14
|
+---|AND|-+ |
|
17
|
-
+-----------|
|
15
|
+
+-----------| | +---|
|
18
16
|
| | | |OR|--(Y)
|
19
|
-
(C2)---------------|
|
17
|
+
(C2)---------------| | +---|
|
20
18
|
+-------------|AND|-+ |
|
21
|
-
| | | +-|
|
19
|
+
| | | +-| | +-|
|
22
20
|
| | | | |
|
23
|
-
(C3)---------------|
|
21
|
+
(C3)---------------| | |
|
24
22
|
+-------------|AND|---+
|
25
|
-
| +-----------|
|
23
|
+
| +-----------| |
|
26
24
|
| | | |
|
27
25
|
(B)--+---|NOT|-+ |
|
28
26
|
| |
|
29
27
|
(A)----+-|NOT|---+
|
30
28
|
DIAGRAM
|
31
29
|
|
32
|
-
|
30
|
+
inputs :c0, :c1, :c2, :c3, :b, :a
|
33
31
|
|
34
|
-
|
35
|
-
(c0 && !b && !a) || (c1 && !b && a) || (c2 && b && !a) || (c3 && b && a)
|
36
|
-
}
|
32
|
+
outputs y: -> { (c0 && !b && !a) || (c1 && !b && a) || (c2 && b && !a) || (c3 && b && a) }
|
37
33
|
|
38
34
|
truth_table <<~TRUTH_TABLE
|
39
35
|
| B | A | C0 | C1 | C2 | C3 | Y |
|
@@ -4,18 +4,16 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Sequential
|
6
6
|
# D Flip-Flop
|
7
|
-
class DFlipFlop <
|
8
|
-
tag :DFF
|
9
|
-
|
7
|
+
class DFlipFlop < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
9
|
(D)--| |--(Q)
|
12
10
|
|DFF|
|
13
11
|
(CK)-|> |
|
14
12
|
DIAGRAM
|
15
13
|
|
16
|
-
|
14
|
+
inputs :d, clock: :ck
|
17
15
|
|
18
|
-
|
16
|
+
outputs q: -> { d }
|
19
17
|
|
20
18
|
truth_table <<~TRUTH_TABLE
|
21
19
|
| CK | D | Q |
|