logicuit 0.3.1 → 0.3.2
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 +3 -0
- data/README.md +94 -2
- data/Rakefile +12 -1
- data/Steepfile +6 -0
- data/lib/logicuit/array_as_signal_group.rb +1 -1
- data/lib/logicuit/circuits/combinational/full_adder.rb +6 -2
- data/lib/logicuit/circuits/combinational/full_adder_4bit.rb +6 -0
- data/lib/logicuit/circuits/combinational/half_adder.rb +4 -0
- data/lib/logicuit/circuits/combinational/multiplexer_2to1.rb +5 -1
- data/lib/logicuit/circuits/combinational/multiplexer_4to1.rb +5 -1
- data/lib/logicuit/circuits/sequential/d_flip_flop.rb +4 -0
- data/lib/logicuit/circuits/sequential/one_bit_cpu.rb +4 -0
- data/lib/logicuit/circuits/sequential/program_counter.rb +10 -4
- data/lib/logicuit/circuits/sequential/register_4bit.rb +6 -0
- data/lib/logicuit/circuits/td4/cpu.rb +11 -2
- data/lib/logicuit/circuits/td4/decoder.rb +9 -5
- data/lib/logicuit/circuits/td4/rom.rb +4 -0
- data/lib/logicuit/dsl.rb +21 -17
- data/lib/logicuit/gates/and.rb +5 -1
- data/lib/logicuit/gates/nand.rb +5 -1
- data/lib/logicuit/gates/not.rb +4 -0
- data/lib/logicuit/gates/or.rb +5 -1
- data/lib/logicuit/gates/xor.rb +5 -1
- data/lib/logicuit/runner.rb +1 -1
- data/lib/logicuit/signals/clock.rb +1 -1
- data/lib/logicuit/signals/signal.rb +12 -0
- data/lib/logicuit/signals/signal_group.rb +1 -1
- data/lib/logicuit/version.rb +1 -1
- data/sig/generated/logicuit/circuits/combinational/full_adder.rbs +20 -0
- data/sig/generated/logicuit/circuits/combinational/full_adder_4bit.rbs +38 -0
- data/sig/generated/logicuit/circuits/combinational/half_adder.rbs +18 -0
- data/sig/generated/logicuit/circuits/combinational/multiplexer_2to1.rbs +18 -0
- data/sig/generated/logicuit/circuits/combinational/multiplexer_4to1.rbs +24 -0
- data/sig/generated/logicuit/circuits/sequential/d_flip_flop.rbs +14 -0
- data/sig/generated/logicuit/circuits/sequential/one_bit_cpu.rbs +16 -0
- data/sig/generated/logicuit/circuits/sequential/program_counter.rbs +28 -0
- data/sig/generated/logicuit/circuits/sequential/register_4bit.rbs +28 -0
- data/sig/generated/logicuit/circuits/td4/cpu.rbs +28 -0
- data/sig/generated/logicuit/circuits/td4/decoder.rbs +32 -0
- data/sig/generated/logicuit/circuits/td4/rom.rbs +36 -0
- data/sig/generated/logicuit/gates/and.rbs +14 -0
- data/sig/generated/logicuit/gates/nand.rbs +14 -0
- data/sig/generated/logicuit/gates/not.rbs +12 -0
- data/sig/generated/logicuit/gates/or.rbs +14 -0
- data/sig/generated/logicuit/gates/xor.rbs +14 -0
- data/sig/logicuit/array_as_signal_group.rbs +11 -0
- data/sig/logicuit/dsl.rbs +35 -0
- data/sig/logicuit/runner.rbs +4 -0
- data/sig/logicuit/signals/clock.rbs +30 -0
- data/sig/logicuit/signals/signal.rbs +32 -0
- data/sig/logicuit/signals/signal_group.rbs +20 -0
- data/sig/logicuit/version.rbs +3 -0
- metadata +26 -2
- data/sig/logicuit.rbs +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ab72694854386c09ba2b86561b6f71f96ea150cbc75384cac6b367a1ef77678
|
4
|
+
data.tar.gz: 033acc2d10c17e90f32dae9af915e92fd81064c88ff8174842821676b5d11fa4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7468f876cf9c462bd2b39b170c309fd9d35408c2dae2d45c7229376254c0d9d8586573fd607f046ddee1d226fb5f6137e8c722dee1e9d36735d204605be5ed2
|
7
|
+
data.tar.gz: 021dc78f8bc9bc7f62b12572d9ec553f916ff66fac568268c8502c9de46d9b836ba14c49a042f33ebec517eccea9661489e92628c6c1cbf64d96f90a3b046ce4
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -40,6 +40,7 @@ A Ruby-based logic circuit simulator featuring an internal DSL for building circ
|
|
40
40
|
- [Assembling](#assembling)
|
41
41
|
- [SignalGroup](#signalgroup)
|
42
42
|
- [Sequential Circuits](#sequential-circuits)
|
43
|
+
- [Truth Table Verification](#truth-table-verification)
|
43
44
|
- [Demo: Ramen Timer](#demo-ramen-timer)
|
44
45
|
- [Development](#development)
|
45
46
|
- [Contributing](#contributing)
|
@@ -72,7 +73,7 @@ require "logicuit"
|
|
72
73
|
class MyAndGate < Logicuit::DSL
|
73
74
|
inputs :a, :b
|
74
75
|
|
75
|
-
outputs y: -> { a
|
76
|
+
outputs y: -> { a & b }
|
76
77
|
|
77
78
|
diagram <<~DIAGRAM
|
78
79
|
(A)-| |
|
@@ -90,6 +91,19 @@ This defines:
|
|
90
91
|
- one output (`y`) that returns the logical AND of the inputs,
|
91
92
|
- and an ASCII diagram that shows the structure of the gate.
|
92
93
|
|
94
|
+
### About signals and logical operations
|
95
|
+
|
96
|
+
Inputs and outputs in Logicuit are not plain booleans — they are instances of the `Logicuit::Signals::Signal` class.
|
97
|
+
The `Signal` class provides methods like `&`, `|`, and `!` to represent logical AND, OR, and NOT operations, respectively.
|
98
|
+
|
99
|
+
For example:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
outputs y: -> { (a & b) | !a }
|
103
|
+
```
|
104
|
+
|
105
|
+
This allows logic expressions to look natural and circuit-like while supporting chaining and composition.
|
106
|
+
|
93
107
|
### Interactive execution
|
94
108
|
|
95
109
|
When you call `run`, the simulator enters an interactive mode.
|
@@ -383,7 +397,85 @@ inputs ..., clock: :ck
|
|
383
397
|
|
384
398
|
> 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
399
|
|
386
|
-
|
400
|
+
## Truth Table Verification
|
401
|
+
|
402
|
+
You can attach a truth table to your circuit class using the `#truth_table`. The truth table should be written in Markdown table format.
|
403
|
+
|
404
|
+
```ruby
|
405
|
+
require "logicuit"
|
406
|
+
|
407
|
+
class MyAndGate < Logicuit::DSL
|
408
|
+
inputs :a, :b
|
409
|
+
|
410
|
+
outputs y: -> { a & b }
|
411
|
+
|
412
|
+
diagram <<~DIAGRAM
|
413
|
+
(A)-| |
|
414
|
+
|AND|-(Y)
|
415
|
+
(B)-| |
|
416
|
+
DIAGRAM
|
417
|
+
|
418
|
+
truth_table <<~TRUTH_TABLE
|
419
|
+
| A | B | Y |
|
420
|
+
| - | - | - |
|
421
|
+
| 0 | 0 | 0 |
|
422
|
+
| 1 | 0 | 0 |
|
423
|
+
| 0 | 1 | 0 |
|
424
|
+
| 1 | 1 | 1 |
|
425
|
+
TRUTH_TABLE
|
426
|
+
end
|
427
|
+
|
428
|
+
MyAndGate.verify_against_truth_table
|
429
|
+
```
|
430
|
+
|
431
|
+
The `#verify_against_truth_table` method evaluates the circuit for each row of the truth table and checks whether the outputs match the expected values.
|
432
|
+
|
433
|
+
If the behavior of the circuit doesn't match the truth table, you'll see an error like this:
|
434
|
+
|
435
|
+
```
|
436
|
+
MyAndGate.new(0, 1).y should be 0 (RuntimeError)
|
437
|
+
```
|
438
|
+
|
439
|
+
This feature is useful for validating your logic circuits against formal truth tables as part of development or testing workflows.
|
440
|
+
|
441
|
+
### Verifying sequential circuits
|
442
|
+
|
443
|
+
Sequential circuits can also be verified using truth tables. When verifying a sequential circuit, the symbol `^` represents the rising edge of the clock.
|
444
|
+
|
445
|
+
Here’s an example for a D flip-flop:
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
class MyDFlipFlop < Logicuit::DSL
|
449
|
+
inputs :d, clock: :ck
|
450
|
+
|
451
|
+
outputs q: -> { d }
|
452
|
+
|
453
|
+
diagram <<~DIAGRAM
|
454
|
+
(D)--| |--(Q)
|
455
|
+
|DFF|
|
456
|
+
(CK)-|> |
|
457
|
+
DIAGRAM
|
458
|
+
|
459
|
+
truth_table <<~TRUTH_TABLE
|
460
|
+
| CK | D | Q |
|
461
|
+
| -- | - | - |
|
462
|
+
| ^ | 0 | 0 |
|
463
|
+
| ^ | 1 | 1 |
|
464
|
+
TRUTH_TABLE
|
465
|
+
end
|
466
|
+
|
467
|
+
MyDFlipFlop.verify_against_truth_table
|
468
|
+
```
|
469
|
+
|
470
|
+
In this table:
|
471
|
+
|
472
|
+
- The `CK` column uses `^` to indicate a clock tick.
|
473
|
+
- The circuit is initialized with the given inputs, then the clock is ticked once.
|
474
|
+
- The outputs are evaluated immediately after the tick and compared against the expected values.
|
475
|
+
|
476
|
+
This mechanism makes it easy to specify and verify the behavior of memory elements and registers.
|
477
|
+
|
478
|
+
## Demo: Ramen Timer
|
387
479
|
|
388
480
|
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
481
|
|
data/Rakefile
CHANGED
@@ -9,4 +9,15 @@ require "rubocop/rake_task"
|
|
9
9
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
12
|
-
|
12
|
+
require "steep/rake_task"
|
13
|
+
Steep::RakeTask.new do |t|
|
14
|
+
t.check.severity_level = :error
|
15
|
+
t.watch.verbose
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Generate rbs files from inline comments"
|
19
|
+
task "rbs-inline" do
|
20
|
+
sh "rbs-inline --output lib"
|
21
|
+
end
|
22
|
+
|
23
|
+
task default: %i[test rubocop rbs-inline steep]
|
data/Steepfile
ADDED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Combinational
|
@@ -43,10 +45,12 @@ module Logicuit
|
|
43
45
|
+-----------------| |
|
44
46
|
DIAGRAM
|
45
47
|
|
48
|
+
attr_reader :cin, :a, :b, :s, :c #: Signals::Signal
|
49
|
+
|
46
50
|
inputs :cin, :a, :b
|
47
51
|
|
48
|
-
outputs s: -> { (!cin
|
49
|
-
c: -> { (!cin
|
52
|
+
outputs s: -> { (!cin & !a & b) | (!cin & a & !b) | (cin & !a & !b) | (cin & a & b) },
|
53
|
+
c: -> { (!cin & a & b) | (cin & !a & b) | (cin & a & !b) | (cin & a & b) }
|
50
54
|
|
51
55
|
truth_table <<~TRUTH_TABLE
|
52
56
|
| Cin | A | B | C | S |
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Combinational
|
@@ -17,6 +19,8 @@ module Logicuit
|
|
17
19
|
(B2)--| |--------+ (B3)--| |---(C)
|
18
20
|
DIAGRAM
|
19
21
|
|
22
|
+
attr_reader :cin, :a0, :b0, :a1, :b1, :a2, :b2, :a3, :b3, :s0, :s1, :s2, :s3, :c #: Signals::Signal
|
23
|
+
|
20
24
|
inputs :cin, :a0, :b0, :a1, :b1, :a2, :b2, :a3, :b3
|
21
25
|
|
22
26
|
outputs :s0, :s1, :s2, :s3, :c
|
@@ -25,6 +29,8 @@ module Logicuit
|
|
25
29
|
[[a0, b0, s0], [a1, b1, s1], [a2, b2, s2], [a3, b3, s3]].reduce(cin) do |c, sigs|
|
26
30
|
a, b, s = sigs
|
27
31
|
full_addr = Combinational::FullAdder.new
|
32
|
+
next full_addr.c if a.nil? || b.nil? || s.nil? # avoid rbs error and rubocop error...
|
33
|
+
|
28
34
|
c >> full_addr.cin
|
29
35
|
a >> full_addr.a
|
30
36
|
b >> full_addr.b
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Combinational
|
@@ -15,6 +17,8 @@ module Logicuit
|
|
15
17
|
+---| |
|
16
18
|
DIAGRAM
|
17
19
|
|
20
|
+
attr_reader :a, :b, :c, :s #: Signals::Signal
|
21
|
+
|
18
22
|
inputs :a, :b
|
19
23
|
|
20
24
|
outputs :c, :s
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Combinational
|
@@ -15,9 +17,11 @@ module Logicuit
|
|
15
17
|
(A)--+-------| |
|
16
18
|
DIAGRAM
|
17
19
|
|
20
|
+
attr_reader :c0, :c1, :a, :y #: Signals::Signal
|
21
|
+
|
18
22
|
inputs :c0, :c1, :a
|
19
23
|
|
20
|
-
outputs y: -> { (c0
|
24
|
+
outputs y: -> { (c0 & !a) | (c1 & a) }
|
21
25
|
|
22
26
|
truth_table <<~TRUTH_TABLE
|
23
27
|
| C0 | C1 | A | Y |
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Combinational
|
@@ -27,9 +29,11 @@ module Logicuit
|
|
27
29
|
(A)----+-|NOT|---+
|
28
30
|
DIAGRAM
|
29
31
|
|
32
|
+
attr_reader :c0, :c1, :c2, :c3, :b, :a, :y #: Signals::Signal
|
33
|
+
|
30
34
|
inputs :c0, :c1, :c2, :c3, :b, :a
|
31
35
|
|
32
|
-
outputs y: -> { (c0
|
36
|
+
outputs y: -> { (c0 & !b & !a) | (c1 & !b & a) | (c2 & b & !a) | (c3 & b & a) }
|
33
37
|
|
34
38
|
truth_table <<~TRUTH_TABLE
|
35
39
|
| B | A | C0 | C1 | C2 | C3 | Y |
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Sequential
|
@@ -11,6 +13,8 @@ module Logicuit
|
|
11
13
|
(CK)-|> |
|
12
14
|
DIAGRAM
|
13
15
|
|
16
|
+
attr_reader :d, :q #: Signals::Signal
|
17
|
+
|
14
18
|
inputs :d, clock: :ck
|
15
19
|
|
16
20
|
outputs q: -> { d }
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Sequential
|
@@ -17,6 +19,8 @@ module Logicuit
|
|
17
19
|
(A)--| |
|
18
20
|
DIAGRAM
|
19
21
|
|
22
|
+
attr_reader :a, :y #: Signals::Signal
|
23
|
+
|
20
24
|
inputs :a, clock: :ck
|
21
25
|
|
22
26
|
outputs :y
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Sequential
|
@@ -13,6 +15,8 @@ module Logicuit
|
|
13
15
|
(LD)--| |
|
14
16
|
DIAGRAM
|
15
17
|
|
18
|
+
attr_reader :a, :b, :c, :d, :ld, :qa, :qb, :qc, :qd #: Signals::Signal
|
19
|
+
|
16
20
|
inputs :a, :b, :c, :d, :ld, clock: :ck
|
17
21
|
|
18
22
|
outputs :qa, :qb, :qc, :qd
|
@@ -21,13 +25,15 @@ module Logicuit
|
|
21
25
|
# inputs :cin, :a0, :b0, :a1, :b1, :a2, :b2, :a3, :b3
|
22
26
|
fadd = Combinational::FullAdder4bit.new(0, 0, 1, 0, 0, 0, 0, 0, 0)
|
23
27
|
|
24
|
-
[[a, qa,
|
25
|
-
[d, qd,
|
28
|
+
[[a, qa, fadd.a0, fadd.s0], [b, qb, fadd.a1, fadd.s1], [c, qc, fadd.a2, fadd.s2],
|
29
|
+
[d, qd, fadd.a3, fadd.s3]].each do |input, output, fadd_in, fadd_out|
|
30
|
+
next if input.nil? || output.nil? || fadd_in.nil? || fadd_out.nil?
|
31
|
+
|
26
32
|
dff = Sequential::DFlipFlop.new
|
27
33
|
mux = Combinational::Multiplexer2to1.new
|
28
34
|
input >> mux.c0
|
29
|
-
dff.q >>
|
30
|
-
|
35
|
+
dff.q >> fadd_in
|
36
|
+
fadd_out >> mux.c1
|
31
37
|
ld >> mux.a
|
32
38
|
mux.y >> dff.d
|
33
39
|
dff.q >> output
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Sequential
|
@@ -28,12 +30,16 @@ module Logicuit
|
|
28
30
|
(LD)--+ (CK)--+
|
29
31
|
DIAGRAM
|
30
32
|
|
33
|
+
attr_reader :a, :b, :c, :d, :ld, :qa, :qb, :qc, :qd #: Signals::Signal
|
34
|
+
|
31
35
|
inputs :a, :b, :c, :d, :ld, clock: :ck
|
32
36
|
|
33
37
|
outputs :qa, :qb, :qc, :qd
|
34
38
|
|
35
39
|
assembling do
|
36
40
|
[[a, qa], [b, qb], [c, qc], [d, qd]].each do |input, output|
|
41
|
+
next if input.nil? || output.nil?
|
42
|
+
|
37
43
|
dff = Sequential::DFlipFlop.new
|
38
44
|
mux = Combinational::Multiplexer2to1.new
|
39
45
|
input >> mux.c0
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Td4
|
@@ -7,16 +9,23 @@ module Logicuit
|
|
7
9
|
class Cpu < DSL
|
8
10
|
using Logicuit::ArrayAsSignalGroup
|
9
11
|
|
12
|
+
attr_reader :in0, :in1, :in2, :in3, :led1, :led2, :led3, :led4
|
13
|
+
|
10
14
|
inputs :in0, :in1, :in2, :in3, clock: :ck
|
11
15
|
|
12
16
|
outputs :led1, :led2, :led3, :led4
|
13
17
|
|
14
18
|
assembling do
|
15
|
-
register_a
|
19
|
+
register_a = Sequential::Register4bit.new
|
20
|
+
register_b = Sequential::Register4bit.new
|
21
|
+
register_c = Sequential::Register4bit.new
|
16
22
|
pc = Sequential::ProgramCounter.new
|
17
23
|
rom = Rom.new
|
18
24
|
dec = Decoder.new
|
19
|
-
mux0
|
25
|
+
mux0 = Combinational::Multiplexer4to1.new
|
26
|
+
mux1 = Combinational::Multiplexer4to1.new
|
27
|
+
mux2 = Combinational::Multiplexer4to1.new
|
28
|
+
mux3 = Combinational::Multiplexer4to1.new
|
20
29
|
alu = Combinational::FullAdder4bit.new
|
21
30
|
dff = Sequential::DFlipFlop.new
|
22
31
|
|
@@ -1,18 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Td4
|
6
8
|
# Decoder class
|
7
9
|
class Decoder < DSL
|
10
|
+
attr_reader :op3, :op2, :op1, :op0, :c_flag, :sel_b, :sel_a, :ld0, :ld1, :ld2, :ld3 #: Signals::Signal
|
11
|
+
|
8
12
|
inputs :op3, :op2, :op1, :op0, :c_flag
|
9
13
|
|
10
14
|
outputs sel_b: -> { op1 },
|
11
|
-
sel_a: -> { op3
|
12
|
-
ld0: -> { op3
|
13
|
-
ld1: -> { op3
|
14
|
-
ld2: -> { !op3
|
15
|
-
ld3: -> { !op3
|
15
|
+
sel_a: -> { op3 | op0 },
|
16
|
+
ld0: -> { op3 | op2 },
|
17
|
+
ld1: -> { op3 | !op2 },
|
18
|
+
ld2: -> { !op3 | op2 },
|
19
|
+
ld3: -> { !op3 | !op2 | (!op0 & c_flag) }
|
16
20
|
|
17
21
|
truth_table <<~TRUTH_TABLE
|
18
22
|
| OP3 | OP2 | OP1 | OP0 | C_FLAG | SEL_B | SEL_A | LD0 | LD1 | LD2 | LD3 |
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Circuits
|
5
7
|
module Td4
|
6
8
|
# Timer
|
7
9
|
class Rom < DSL
|
10
|
+
attr_reader :a3, :a2, :a1, :a0, :d7, :d6, :d5, :d4, :d3, :d2, :d1, :d0 #: Signals::Signal
|
11
|
+
|
8
12
|
inputs :a3, :a2, :a1, :a0
|
9
13
|
|
10
14
|
outputs :d7, :d6, :d5, :d4, :d3, :d2, :d1, :d0
|
data/lib/logicuit/dsl.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# steep:ignore:start
|
4
|
+
|
3
5
|
# Logicuit module
|
4
6
|
module Logicuit
|
5
7
|
# base class for all gates and circuits
|
@@ -26,7 +28,9 @@ module Logicuit
|
|
26
28
|
|
27
29
|
def self.inputs(*args, **kwargs)
|
28
30
|
# define getter methods for inputs
|
29
|
-
|
31
|
+
args.each do |arg|
|
32
|
+
attr_reader(arg) unless instance_methods.include?(arg)
|
33
|
+
end
|
30
34
|
|
31
35
|
# define initializer for inputs
|
32
36
|
define_method(:inputs) do |*instance_method_args|
|
@@ -54,7 +58,9 @@ module Logicuit
|
|
54
58
|
|
55
59
|
def self.outputs(*args, **kwargs)
|
56
60
|
# define getter methods for outputs
|
57
|
-
|
61
|
+
(args + kwargs.keys).each do |arg|
|
62
|
+
attr_reader(arg) unless instance_methods.include?(arg)
|
63
|
+
end
|
58
64
|
|
59
65
|
# define initializer for outputs
|
60
66
|
define_method(:outputs) do
|
@@ -71,19 +77,13 @@ module Logicuit
|
|
71
77
|
return unless initialized
|
72
78
|
|
73
79
|
kwargs.each do |output, evaluator|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
if @inputs_as_bool_struct.new(*e_args).instance_exec(&evaluator)
|
83
|
-
signal.on
|
84
|
-
else
|
85
|
-
signal.off
|
86
|
-
end
|
80
|
+
ret = if override_args.empty?
|
81
|
+
instance_exec(&evaluator)
|
82
|
+
else
|
83
|
+
o = @inputs_as_bool_struct.new(*override_args)
|
84
|
+
o.instance_exec(&evaluator)
|
85
|
+
end
|
86
|
+
send(output).send(ret.current ? :on : :off)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -134,6 +134,8 @@ module Logicuit
|
|
134
134
|
array = [values]
|
135
135
|
while array.any? { _1.any? { |v| v == :any } }
|
136
136
|
target_index = array.find_index { _1.any? { |v| v == :any } }
|
137
|
+
next if target_index.nil? # avoid rbs error...
|
138
|
+
|
137
139
|
target = array[target_index]
|
138
140
|
prop_index = target.find_index { |v| v == :any }
|
139
141
|
array.delete_at(target_index)
|
@@ -168,9 +170,9 @@ module Logicuit
|
|
168
170
|
if value.is_a?(Array) && value.first == :ref
|
169
171
|
expected = previous_values[value.last]
|
170
172
|
|
171
|
-
raise "#{self}.new(#{args.join(", ")}).#{key} should be #{expected}" unless expected == subject.send(key).current
|
173
|
+
raise "#{self}.new(#{args.join(", ")}).#{key} should be #{expected ? 1 : 0}" unless expected == subject.send(key).current
|
172
174
|
else
|
173
|
-
raise "#{self}.new(#{args.join(", ")}).#{key} should be #{value}" unless value == subject.send(key).current
|
175
|
+
raise "#{self}.new(#{args.join(", ")}).#{key} should be #{value ? 1 : 0}" unless value == subject.send(key).current
|
174
176
|
end
|
175
177
|
end
|
176
178
|
end
|
@@ -181,3 +183,5 @@ module Logicuit
|
|
181
183
|
end
|
182
184
|
end
|
183
185
|
end
|
186
|
+
|
187
|
+
# steep:ignore:end
|
data/lib/logicuit/gates/and.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Gates
|
5
7
|
# AND gate
|
@@ -10,9 +12,11 @@ module Logicuit
|
|
10
12
|
(B)-| |
|
11
13
|
DIAGRAM
|
12
14
|
|
15
|
+
attr_reader :a, :b, :y #: Signals::Signal
|
16
|
+
|
13
17
|
inputs :a, :b
|
14
18
|
|
15
|
-
outputs y: -> { a
|
19
|
+
outputs y: -> { a & b }
|
16
20
|
|
17
21
|
truth_table <<~TRUTH_TABLE
|
18
22
|
| A | B | Y |
|
data/lib/logicuit/gates/nand.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Gates
|
5
7
|
# NAND gate
|
@@ -10,9 +12,11 @@ module Logicuit
|
|
10
12
|
(B)-| |
|
11
13
|
DIAGRAM
|
12
14
|
|
15
|
+
attr_reader :a, :b, :y #: Signals::Signal
|
16
|
+
|
13
17
|
inputs :a, :b
|
14
18
|
|
15
|
-
outputs y: -> { !(a
|
19
|
+
outputs y: -> { !(a & b) }
|
16
20
|
|
17
21
|
truth_table <<~TRUTH_TABLE
|
18
22
|
| A | B | Y |
|
data/lib/logicuit/gates/not.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Gates
|
5
7
|
# NOT gate
|
@@ -8,6 +10,8 @@ module Logicuit
|
|
8
10
|
(A)-|NOT|-(Y)
|
9
11
|
DIAGRAM
|
10
12
|
|
13
|
+
attr_reader :a, :y #: Signals::Signal
|
14
|
+
|
11
15
|
inputs :a
|
12
16
|
|
13
17
|
outputs y: -> { !a }
|
data/lib/logicuit/gates/or.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Gates
|
5
7
|
# OR gate
|
@@ -10,9 +12,11 @@ module Logicuit
|
|
10
12
|
(B)-| |
|
11
13
|
DIAGRAM
|
12
14
|
|
15
|
+
attr_reader :a, :b, :y #: Signals::Signal
|
16
|
+
|
13
17
|
inputs :a, :b
|
14
18
|
|
15
|
-
outputs y: -> { a
|
19
|
+
outputs y: -> { a | b }
|
16
20
|
|
17
21
|
truth_table <<~TRUTH_TABLE
|
18
22
|
| A | B | Y |
|
data/lib/logicuit/gates/xor.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Logicuit
|
4
6
|
module Gates
|
5
7
|
# XOR gate
|
@@ -10,9 +12,11 @@ module Logicuit
|
|
10
12
|
(B)-| |
|
11
13
|
DIAGRAM
|
12
14
|
|
15
|
+
attr_reader :a, :b, :y #: Signals::Signal
|
16
|
+
|
13
17
|
inputs :a, :b
|
14
18
|
|
15
|
-
outputs y: -> { (a
|
19
|
+
outputs y: -> { (a & !b) | (!a & b) }
|
16
20
|
|
17
21
|
truth_table <<~TRUTH_TABLE
|
18
22
|
| A | B | Y |
|
data/lib/logicuit/runner.rb
CHANGED
@@ -16,7 +16,7 @@ module Logicuit
|
|
16
16
|
# Call the `evaluate` method for all components.
|
17
17
|
# However, the input argument values should be bound to the values at the time `tick` is called.
|
18
18
|
@downstreams.map do |component|
|
19
|
-
args = component.input_targets.map { |input| component.
|
19
|
+
args = component.input_targets.map { |input| Signal.new(component.send(input).current) }
|
20
20
|
-> { component.evaluate(*args) }
|
21
21
|
end.each(&:call)
|
22
22
|
end
|