logicuit 0.2.0 → 0.3.1

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -2
  3. data/README.md +355 -18
  4. data/lib/logicuit/array_as_signal_group.rb +13 -0
  5. data/lib/logicuit/circuits/combinational/full_adder.rb +28 -30
  6. data/lib/logicuit/circuits/combinational/full_adder_4bit.rb +13 -28
  7. data/lib/logicuit/circuits/combinational/half_adder.rb +8 -10
  8. data/lib/logicuit/circuits/combinational/multiplexer_2to1.rb +7 -9
  9. data/lib/logicuit/circuits/combinational/multiplexer_4to1.rb +11 -15
  10. data/lib/logicuit/circuits/sequential/d_flip_flop.rb +3 -5
  11. data/lib/logicuit/circuits/{system_level/one_bit_cpu2.rb → sequential/one_bit_cpu.rb} +13 -15
  12. data/lib/logicuit/circuits/sequential/program_counter.rb +6 -8
  13. data/lib/logicuit/circuits/sequential/register_4bit.rb +12 -14
  14. data/lib/logicuit/circuits/{system_level/cpu_td4.rb → td4/cpu.rb} +34 -59
  15. data/lib/logicuit/circuits/{combinational → td4}/decoder.rb +9 -11
  16. data/lib/logicuit/circuits/{rom/timer.rb → td4/rom.rb} +9 -9
  17. data/lib/logicuit/{base.rb → dsl.rb} +63 -105
  18. data/lib/logicuit/gates/and.rb +5 -7
  19. data/lib/logicuit/gates/nand.rb +5 -7
  20. data/lib/logicuit/gates/not.rb +3 -5
  21. data/lib/logicuit/gates/or.rb +5 -7
  22. data/lib/logicuit/gates/xor.rb +5 -7
  23. data/lib/logicuit/runner.rb +45 -0
  24. data/lib/logicuit/signals/clock.rb +18 -15
  25. data/lib/logicuit/signals/signal.rb +29 -24
  26. data/lib/logicuit/signals/signal_group.rb +32 -0
  27. data/lib/logicuit/version.rb +1 -1
  28. data/lib/logicuit.rb +8 -6
  29. metadata +11 -9
  30. 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: a6288d2da83c42993610ba8212db59a1296ebf4724355c83f0c63f8605a228b6
4
- data.tar.gz: 7fcc0e76b0142332d46e93a8a841004de7943e8520ec196cf61c97253ab4321a
3
+ metadata.gz: 1a2841e79a0daf8046710c6bd43d8862a3d9f28f482ab2b9cac2886b271f571f
4
+ data.tar.gz: 679b263308e15b0da229573bfd7be5cf02c8e65bd98fb01753874afb3fe56413
5
5
  SHA512:
6
- metadata.gz: 6208894fad9df2006468189d4285e4d1be8b0ce46b0cc8419dbe26dc22c25baab5a9901faf0d29f592fc36cdb3888144e7ff55ca640be6c00e7c9780e56f2748
7
- data.tar.gz: 8050593dceea458a6275c9a90c638a4d01cbf23467103ea79756ff08a272585889e09a9beb802cae47b96158d8173744165311adfe671caf555f97d0d86d62a1
6
+ metadata.gz: 3e942269a9b55dad3f7efff1d68935f431952d0c3276d7d290461dabe84230f6d6d1d0eb2f307b6dd375c2d3b1261c8e2e7c72f1faa17db0de576cee9c37c0da
7
+ data.tar.gz: 3f1428cced00eee1798ea56dc9cfb169eb041b40bfc514a729d1cd3d67ce4b05d93ea633a9290c3ac22432aa1bfeb384e8de20cee59a0e463c582bf82be61ea4
data/.rubocop.yml CHANGED
@@ -14,11 +14,21 @@ 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
 
20
32
  plugins:
21
33
  - rubocop-minitest
22
-
23
- require:
24
34
  - rubocop-rake
data/README.md CHANGED
@@ -1,6 +1,49 @@
1
1
  # Logicuit
2
2
 
3
- logi(c cir)cuit -> logicuit
3
+ ```
4
+ ******* ******* *******
5
+ ********* ********* *********
6
+ *********** *********** ***********
7
+ ********* ********* *********
8
+ ******* ******* *******
9
+
10
+ +-----------------------------------------------+ OUT 0111
11
+ | | ADD A,0001
12
+ +--->|rg_a|(0111)----->| | | JNC 0001
13
+ | |1000| | | | ADD A,0001
14
+ | | | | > JNC 0011
15
+ +--->|rg_b|(0000)----->| |----------->| |---+ OUT 0110
16
+ | |0000| | | | | ADD A,0001
17
+ | |SEL| |ALU| JNC 0110
18
+ +--->| out| | in|--->| | | | ADD A,0001
19
+ | |0111| |0000| | | | im|--->| |--(0) JNC 1000
20
+ | | | |0011| OUT 0000
21
+ +--->| pc| (0000)--->| | OUT 0100
22
+ |0100| ADD A,0001
23
+ JNC 1010
24
+ OUT 1000
25
+ JMP 1111
26
+
27
+ tick: 48
28
+ input: in0,in1,in2,in3?
29
+ ```
30
+
31
+ From logic circuit to Logicuit — a playful portmanteau.
32
+
33
+ A Ruby-based logic circuit simulator featuring an internal DSL for building circuits.
34
+
35
+ ## Table of Contents
36
+
37
+ - [Installation](#installation)
38
+ - [DSL](#dsl)
39
+ - [Interactive Execution](#interactive-execution)
40
+ - [Assembling](#assembling)
41
+ - [SignalGroup](#signalgroup)
42
+ - [Sequential Circuits](#sequential-circuits)
43
+ - [Demo: Ramen Timer](#demo-ramen-timer)
44
+ - [Development](#development)
45
+ - [Contributing](#contributing)
46
+ - [License](#license)
4
47
 
5
48
  ## Installation
6
49
 
@@ -16,50 +59,344 @@ If bundler is not being used to manage dependencies, install the gem by executin
16
59
  gem install logicuit
17
60
  ```
18
61
 
19
- ## Usage
62
+ ## DSL
63
+
64
+ This library provides an internal DSL for defining logic circuits in a declarative and readable way.
65
+ You can define inputs, outputs, and even a visual diagram — all within a Ruby class.
66
+
67
+ Here is an example of a simple 2-input AND gate:
68
+
69
+ ```ruby
70
+ require "logicuit"
71
+
72
+ class MyAndGate < Logicuit::DSL
73
+ inputs :a, :b
74
+
75
+ outputs y: -> { a && b }
76
+
77
+ diagram <<~DIAGRAM
78
+ (A)-| |
79
+ |AND|-(Y)
80
+ (B)-| |
81
+ DIAGRAM
82
+ end
83
+
84
+ MyAndGate.run
85
+ ```
86
+
87
+ This defines:
88
+
89
+ - two inputs (`a` and `b`),
90
+ - one output (`y`) that returns the logical AND of the inputs,
91
+ - and an ASCII diagram that shows the structure of the gate.
92
+
93
+ ### Interactive execution
94
+
95
+ When you call `run`, the simulator enters an interactive mode.
96
+
97
+ At first, the circuit is evaluated with all inputs set to `0`, and drawn as an ASCII diagram:
20
98
 
21
- This is the code to create a Multiplexer with 2 inputs and 1 output:
99
+ ```
100
+ (0)-| |
101
+ |AND|-(0)
102
+ (0)-| |
22
103
 
104
+ input: a,b?
23
105
  ```
24
- require 'logicuit'
25
106
 
26
- class Multiplexer2to1 < Logicuit::Base
27
- tag :MY_MUX
107
+ To interact with the circuit, just type the name of an input — for example, `a` — and press Enter.
108
+ That input will toggle its value (`0 → 1` or `1 → 0`), and the diagram will be redrawn to reflect the new state.
109
+ You can keep toggling inputs this way to observe how the circuit reacts in real time.
110
+
111
+ To exit the simulator, simply press `Ctrl+C`.
112
+
113
+ ### Assembling circuits
114
+
115
+ In addition to defining simple gates declaratively, Logicuit also lets you assemble circuits from reusable components using the `assembling` block.
116
+
117
+ This approach gives you more control and expressiveness when building complex circuits.
118
+
119
+ Here's an example of a 2-to-1 multiplexer:
120
+
121
+ ```ruby
122
+ require "logicuit"
123
+
124
+ class MyMultiplexer < Logicuit::DSL
125
+ inputs :c0, :c1, :a
126
+
127
+ outputs :y
128
+
129
+ assembling do
130
+ and_gate1 = Logicuit::Gates::And.new
131
+ and_gate2 = Logicuit::Gates::And.new
132
+ not_gate = Logicuit::Gates::Not.new
133
+ or_gate = Logicuit::Gates::Or.new
134
+
135
+ c0 >> and_gate1.a
136
+ a >> not_gate.a
137
+ not_gate.y >> and_gate1.b
138
+
139
+ c1 >> and_gate2.a
140
+ a >> and_gate2.b
141
+
142
+ and_gate1.y >> or_gate.a
143
+ and_gate2.y >> or_gate.b
144
+ or_gate.y >> y
145
+ end
28
146
 
29
147
  diagram <<~DIAGRAM
30
- (C0)---------|
148
+ (C0)---------| |
31
149
  |AND|--+
32
- +-|NOT|-| +--|
150
+ +-|NOT|-| | +--| |
33
151
  | |OR|--(Y)
34
- (C1)---------| +--|
152
+ (C1)---------| | +--| |
35
153
  | |AND|--+
36
- (A)--+-------|
154
+ (A)--+-------| |
37
155
  DIAGRAM
156
+ end
157
+
158
+ MyMultiplexer.run
159
+ ```
160
+
161
+ ### Connection syntax
162
+
163
+ The `>>` operator is used to connect outputs to inputs, mimicking the direction of signal flow.
164
+
165
+ This allows the code to resemble the actual structure of the circuit, making it more intuitive to follow.
166
+
167
+ For example:
168
+
169
+ ```ruby
170
+ a >> not_gate.a
171
+ not_gate.y >> and_gate1.b
172
+ ```
173
+
174
+ can be read as:
175
+
176
+ *"Connect input `a` to the NOT gate's input. Then connect the NOT gate's output to one of the AND gate's inputs."*
177
+
178
+ ### Built-in gates
179
+
180
+ Logicuit includes several built-in logic gates, which you can use as components:
181
+
182
+ - `Logicuit::Gates::And`
183
+ - `Logicuit::Gates::Or`
184
+ - `Logicuit::Gates::Not`
185
+ - `Logicuit::Gates::Nand`
186
+ - `Logicuit::Gates::Xor`
187
+
188
+ These gates expose their input and output pins as attributes (`a`, `b`, `y`, etc.), which can be freely connected using `>>`.
189
+
190
+ ### Signal groups
191
+
192
+ When building larger circuits, it's common to connect one output to multiple inputs, or to connect multiple outputs to multiple inputs.
193
+
194
+ Logicuit provides a convenient way to express these kinds of connections using signal groups.
195
+
196
+ #### One-to-many connections
197
+
198
+ These two lines:
199
+
200
+ ```ruby
201
+ a >> xor_gate.a
202
+ a >> and_gate.a
203
+ ```
204
+
205
+ can be written more concisely as:
206
+
207
+ ```ruby
208
+ a >> [xor_gate.a, and_gate.a]
209
+ ```
210
+
211
+ The array on the right-hand side is treated as a signal group, and the connection is applied to each element.
38
212
 
39
- define_inputs :c0, :c1, :a
213
+ #### Many-to-many connections
40
214
 
41
- define_outputs y: ->(c0, c1, a) { (c0 && !a) || (c1 && a) }
215
+ You can also connect multiple outputs to multiple inputs at once by using the [] method to access signals by name:
216
+
217
+ ```ruby
218
+ pc.qa >> rom.a0
219
+ pc.qb >> rom.a1
220
+ pc.qc >> rom.a2
221
+ pc.qd >> rom.a3
222
+ ```
223
+
224
+ is equivalent to:
225
+
226
+ ```ruby
227
+ pc[:qa, :qb, :qc, :qd] >> rom[:a0, :a1, :a2, :a3]
228
+ ```
229
+
230
+ This `#[](*keys)` method returns a `SignalGroup` object — a Logicuit abstraction that makes it easier to handle groups of signals together.
231
+
232
+ > Note: The number of signals on both sides must match.
233
+
234
+ #### Connecting from different sources
235
+
236
+ What if you want to connect signals from multiple different components as a single group?
237
+
238
+ You can use `Logicuit::ArrayAsSignalGroup`, which adds signal group behavior to arrays:
239
+
240
+ ```ruby
241
+ using Logicuit::ArrayAsSignalGroup
242
+
243
+ assembling do
244
+ [register_a.qa, register_b.qa, in0] >> mux0[:c0, :c1, :c2]
42
245
  end
246
+ ```
247
+
248
+ This lets you treat a plain Ruby array as a `SignalGroup` and connect it to another group of inputs in one line.
249
+
250
+ ### Sequential circuits
251
+
252
+ 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.
253
+
254
+ For example, here’s a D flip-flop:
255
+
256
+ ```ruby
257
+ require "logicuit"
258
+
259
+ class MyDFlipFlop < Logicuit::DSL
260
+ inputs :d, clock: :ck
261
+
262
+ outputs q: -> { d }
263
+
264
+ diagram <<~DIAGRAM
265
+ (D)--| |--(Q)
266
+ |DFF|
267
+ (CK)-|> |
268
+ DIAGRAM
269
+ end
270
+
271
+ MyDFlipFlop.run
272
+ ```
273
+
274
+ #### Defining a sequential circuit
275
+
276
+ A circuit becomes sequential when the `inputs` declaration includes a keyword argument named `clock:`.
277
+ 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.
278
+
279
+ Once a clock is defined:
280
+
281
+ - The `outputs` lambdas will be evaluated on each clock tick, not continuously.
282
+ - A global singleton clock will drive the timing — you don’t need to define or manage the clock yourself.
283
+
284
+ #### Interactive execution with a clock
43
285
 
44
- Logicuit.run(:MY_MUX)
286
+ When a sequential circuit is run interactively, Logicuit enters clock mode. The clock ticks periodically, and the circuit is redrawn after each tick.
287
+
288
+ ```
289
+ (0)--| |--(0)
290
+ |DFF|
291
+ (CK)-|> |
292
+
293
+ tick: 2
294
+ input: d?
45
295
  ```
46
296
 
47
- you can execute a same circuit by the following as a one-liner:
297
+ You can still toggle inputs as before (e.g., type `d` and press Enter), but updates take effect on the next tick.
298
+
299
+ The number of elapsed ticks is shown as `tick: N`.
48
300
 
301
+ #### Clock speed
302
+
303
+ By default, the clock ticks at 1 Hz (once per second). You can change the frequency by passing the `hz:` option to `run`:
304
+
305
+ ```ruby
306
+ MyDFlipFlop.run(hz: 10)
49
307
  ```
50
- ruby -r ./lib/logicuit -e 'Logicuit.run(:mux)'
308
+
309
+ This will run the clock at 10 ticks per second — useful when simulating more complex circuits.
310
+
311
+ If you want full control, you can set `hz: 0` to disable automatic ticking.
312
+
313
+ In this mode, the clock only ticks when you press Enter, allowing you to step through the simulation manually:
314
+
315
+ ```ruby
316
+ MyDFlipFlop.run(hz: 0)
51
317
  ```
52
318
 
53
- you can similarly execute other circuits with the following commands:
319
+ This is useful for debugging or analyzing a circuit’s behavior step by step.
320
+
321
+ #### Combining sequential circuits with `assembling`
322
+
323
+ You can build sequential circuits out of smaller components using the `assembling` block, just like with combinational circuits.
324
+
325
+ Here’s an example of a 4-bit register that stores its input when the load signal `ld` is not active:
326
+
327
+ ```ruby
328
+ require "logicuit"
329
+
330
+ class MyRegister4bit < Logicuit::DSL
331
+ inputs :a, :b, :c, :d, :ld, clock: :ck
332
+
333
+ outputs :qa, :qb, :qc, :qd
54
334
 
335
+ assembling do
336
+ [[a, qa], [b, qb], [c, qc], [d, qd]].each do |input, output|
337
+ dff = Logicuit::Circuits::Sequential::DFlipFlop.new
338
+ mux = Logicuit::Circuits::Combinational::Multiplexer2to1.new
339
+ input >> mux.c0
340
+ dff.q >> mux.c1
341
+ ld >> mux.a
342
+ mux.y >> dff.d
343
+ dff.q >> output
344
+ end
345
+ end
346
+
347
+ diagram <<~DIAGRAM
348
+ +---------------------+
349
+ +-| | |
350
+ (A)-------|MUX|-------|DFF|---+---(QA)
351
+ +---| | +---| |
352
+ | |
353
+ | +---------------------+
354
+ | +-| | | |
355
+ (B)-------|MUX|-------|DFF|---+---(QB)
356
+ +---| | +---| |
357
+ | |
358
+ | +---------------------+
359
+ | +-| | | |
360
+ (C)-------|MUX|-------|DFF|---+---(QC)
361
+ +---| | +---| |
362
+ | |
363
+ | +---------------------+
364
+ | +-| | | |
365
+ (D)-------|MUX|-------|DFF|---+---(QD)
366
+ +---| | +---| |
367
+ (LD)--+ (CK)--+
368
+ DIAGRAM
369
+ end
370
+
371
+ MyRegister4bit.run
55
372
  ```
56
- ruby -r ./lib/logicuit -e 'Logicuit.run(:dff)'
373
+
374
+ #### Sequential detection
375
+
376
+ 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`.
377
+
378
+ 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:
379
+
380
+ ```ruby
381
+ inputs ..., clock: :ck
57
382
  ```
58
383
 
384
+ > 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.
385
+
386
+ ### Demo: Ramen Timer
387
+
388
+ Logicuit comes with a simple demo circuit — a working 4-bit CPU based on the TD4 architecture described in the book [CPUの創りかた](https://www.amazon.co.jp/dp/4839909865).
389
+
390
+ You can try it out by running:
391
+
59
392
  ```
60
- ruby -r ./lib/logicuit -e 'Logicuit.run(:one_bit_cpu)'
393
+ ruby -r logicuit -e 'Logicuit::Circuits::Td4::Cpu.run'
61
394
  ```
62
395
 
396
+ This launches a fully functional CPU simulation that counts down from a programmed value — perfect for timing your instant ramen 🍜
397
+
398
+ The TD4 CPU is built entirely from logic gates and flip-flops, assembled using Logicuit’s DSL. It’s a great demonstration of how small components can be combined to create a complete digital system.
399
+
63
400
  ## Development
64
401
 
65
402
  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 < Base
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
- define_inputs :cin, :a, :b
46
+ inputs :cin, :a, :b
49
47
 
50
- define_outputs s: ->(cin, a, b) { (!cin && !a && b) || (!cin && a && !b) || (cin && !a && !b) || (cin && a && b) },
51
- c: ->(cin, a, b) { (!cin && a && b) || (cin && !a && b) || (cin && a && !b) || (cin && a && b) }
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 < Base
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
- define_inputs :cin, :a0, :b0, :a1, :b1, :a2, :b2, :a3, :b3
20
+ inputs :cin, :a0, :b0, :a1, :b1, :a2, :b2, :a3, :b3
36
21
 
37
- define_outputs :s0, :s1, :s2, :s3, :c
22
+ outputs :s0, :s1, :s2, :s3, :c
38
23
 
39
- assembling do |cin, a0, b0, a1, b1, a2, b2, a3, b3, s0, s1, s2, s3, cout|
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 >> cout
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 < Base
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
- define_inputs :a, :b
18
+ inputs :a, :b
21
19
 
22
- define_outputs :c, :s
20
+ outputs :c, :s
23
21
 
24
- assembling do |a, b, c, s|
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 < Base
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
- define_inputs :c0, :c1, :a
18
+ inputs :c0, :c1, :a
21
19
 
22
- define_outputs y: ->(c0, c1, a) { (c0 && !a) || (c1 && a) }
20
+ outputs y: -> { (c0 && !a) || (c1 && a) }
23
21
 
24
22
  truth_table <<~TRUTH_TABLE
25
23
  | C0 | C1 | A | Y |