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.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -2
- data/README.md +355 -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} +9 -9
- data/lib/logicuit/{base.rb → dsl.rb} +63 -105
- 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 +32 -0
- data/lib/logicuit/version.rb +1 -1
- data/lib/logicuit.rb +8 -6
- metadata +11 -9
- data/lib/logicuit/circuits/system_level/one_bit_cpu.rb +0 -41
@@ -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 |
|
@@ -2,38 +2,36 @@
|
|
2
2
|
|
3
3
|
module Logicuit
|
4
4
|
module Circuits
|
5
|
-
module
|
5
|
+
module Sequential
|
6
6
|
# 1 bit CPU with a Multiplexer
|
7
7
|
# Input A is H, MOV A,A
|
8
8
|
# Input A is L, NOT A
|
9
|
-
class
|
10
|
-
tag :ONE_BIT_CPU2
|
11
|
-
|
9
|
+
class OneBitCpu < DSL
|
12
10
|
diagram <<~DIAGRAM
|
13
|
-
|
14
|
-
|
|
15
|
-
+----|
|
16
|
-
|DFF|
|
17
|
-
(CK)-|> |
|
18
|
-
|
19
|
-
|
11
|
+
+-----------------------------+
|
12
|
+
| |
|
13
|
+
+----| |---+---------| | |
|
14
|
+
|DFF| | | | |
|
15
|
+
(CK)-|> | +--|NOT|--|MUX|--+--(Y)
|
16
|
+
| |
|
17
|
+
(A)--| |
|
20
18
|
DIAGRAM
|
21
19
|
|
22
|
-
|
20
|
+
inputs :a, clock: :ck
|
23
21
|
|
24
|
-
|
22
|
+
outputs :y
|
25
23
|
|
26
|
-
assembling do
|
24
|
+
assembling do
|
27
25
|
dff = Sequential::DFlipFlop.new
|
28
26
|
not_gate = Gates::Not.new
|
29
27
|
mux = Combinational::Multiplexer2to1.new
|
30
28
|
|
31
|
-
dff.q >> y
|
32
29
|
dff.q >> mux.c0
|
33
30
|
dff.q >> not_gate.a
|
34
31
|
not_gate.y >> mux.c1
|
35
32
|
a >> mux.a
|
36
33
|
mux.y >> dff.d
|
34
|
+
mux.y >> y
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
@@ -4,23 +4,21 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Sequential
|
6
6
|
# Program Counter
|
7
|
-
class ProgramCounter <
|
8
|
-
tag :PC
|
9
|
-
|
7
|
+
class ProgramCounter < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
9
|
(A)---| |---(QA)
|
12
10
|
(B)---| |---(QB)
|
13
11
|
(C)---|PC|---(QC)
|
14
12
|
(D)---| |---(QD)
|
15
|
-
(LD)--|
|
13
|
+
(LD)--| |
|
16
14
|
DIAGRAM
|
17
15
|
|
18
|
-
|
16
|
+
inputs :a, :b, :c, :d, :ld, clock: :ck
|
19
17
|
|
20
|
-
|
18
|
+
outputs :qa, :qb, :qc, :qd
|
21
19
|
|
22
|
-
assembling do
|
23
|
-
#
|
20
|
+
assembling do
|
21
|
+
# inputs :cin, :a0, :b0, :a1, :b1, :a2, :b2, :a3, :b3
|
24
22
|
fadd = Combinational::FullAdder4bit.new(0, 0, 1, 0, 0, 0, 0, 0, 0)
|
25
23
|
|
26
24
|
[[a, qa, :a0, :s0], [b, qb, :a1, :s1], [c, qc, :a2, :s2],
|
@@ -4,37 +4,35 @@ module Logicuit
|
|
4
4
|
module Circuits
|
5
5
|
module Sequential
|
6
6
|
# 4 bit register
|
7
|
-
class Register4bit <
|
8
|
-
tag :REG4
|
9
|
-
|
7
|
+
class Register4bit < DSL
|
10
8
|
diagram <<~DIAGRAM
|
11
9
|
+---------------------+
|
12
|
-
+-|
|
10
|
+
+-| | |
|
13
11
|
(A)-------|MUX|-------|DFF|---+---(QA)
|
14
|
-
+---|
|
12
|
+
+---| | +---| |
|
15
13
|
| |
|
16
14
|
| +---------------------+
|
17
|
-
| +-|
|
15
|
+
| +-| | | |
|
18
16
|
(B)-------|MUX|-------|DFF|---+---(QB)
|
19
|
-
+---|
|
17
|
+
+---| | +---| |
|
20
18
|
| |
|
21
19
|
| +---------------------+
|
22
|
-
| +-|
|
20
|
+
| +-| | | |
|
23
21
|
(C)-------|MUX|-------|DFF|---+---(QC)
|
24
|
-
+---|
|
22
|
+
+---| | +---| |
|
25
23
|
| |
|
26
24
|
| +---------------------+
|
27
|
-
| +-|
|
25
|
+
| +-| | | |
|
28
26
|
(D)-------|MUX|-------|DFF|---+---(QD)
|
29
|
-
+---|
|
27
|
+
+---| | +---| |
|
30
28
|
(LD)--+ (CK)--+
|
31
29
|
DIAGRAM
|
32
30
|
|
33
|
-
|
31
|
+
inputs :a, :b, :c, :d, :ld, clock: :ck
|
34
32
|
|
35
|
-
|
33
|
+
outputs :qa, :qb, :qc, :qd
|
36
34
|
|
37
|
-
assembling do
|
35
|
+
assembling do
|
38
36
|
[[a, qa], [b, qb], [c, qc], [d, qd]].each do |input, output|
|
39
37
|
dff = Sequential::DFlipFlop.new
|
40
38
|
mux = Combinational::Multiplexer2to1.new
|
@@ -2,68 +2,43 @@
|
|
2
2
|
|
3
3
|
module Logicuit
|
4
4
|
module Circuits
|
5
|
-
module
|
6
|
-
# TD4
|
7
|
-
class
|
8
|
-
|
5
|
+
module Td4
|
6
|
+
# TD4 CPU
|
7
|
+
class Cpu < DSL
|
8
|
+
using Logicuit::ArrayAsSignalGroup
|
9
9
|
|
10
|
-
|
10
|
+
inputs :in0, :in1, :in2, :in3, clock: :ck
|
11
11
|
|
12
|
-
|
12
|
+
outputs :led1, :led2, :led3, :led4
|
13
13
|
|
14
|
-
assembling do
|
15
|
-
register_a = Sequential::Register4bit.new
|
16
|
-
register_b = Sequential::Register4bit.new
|
17
|
-
register_c = Sequential::Register4bit.new
|
14
|
+
assembling do
|
15
|
+
register_a, register_b, register_c = (:a..:c).map { Sequential::Register4bit.new }
|
18
16
|
pc = Sequential::ProgramCounter.new
|
19
|
-
rom = Rom
|
20
|
-
dec =
|
21
|
-
mux0 = Combinational::Multiplexer4to1.new
|
22
|
-
mux1 = Combinational::Multiplexer4to1.new
|
23
|
-
mux2 = Combinational::Multiplexer4to1.new
|
24
|
-
mux3 = Combinational::Multiplexer4to1.new
|
17
|
+
rom = Rom.new
|
18
|
+
dec = Decoder.new
|
19
|
+
mux0, mux1, mux2, mux3 = (0..3).map { Combinational::Multiplexer4to1.new }
|
25
20
|
alu = Combinational::FullAdder4bit.new
|
26
21
|
dff = Sequential::DFlipFlop.new
|
27
22
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
alu.send(sel) >> pc.send(reg)
|
33
|
-
end
|
23
|
+
alu.s0 >> [register_a.a, register_b.a, register_c.a, pc.a]
|
24
|
+
alu.s1 >> [register_a.b, register_b.b, register_c.b, pc.b]
|
25
|
+
alu.s2 >> [register_a.c, register_b.c, register_c.c, pc.c]
|
26
|
+
alu.s3 >> [register_a.d, register_b.d, register_c.d, pc.d]
|
34
27
|
alu.c >> dff.d
|
35
28
|
|
36
|
-
[
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
mux.y >> alu.send(alu_in)
|
44
|
-
end
|
29
|
+
[register_a.qa, register_b.qa, in0] >> mux0[:c0, :c1, :c2]
|
30
|
+
[register_a.qb, register_b.qb, in1] >> mux1[:c0, :c1, :c2]
|
31
|
+
[register_a.qc, register_b.qc, in2] >> mux2[:c0, :c1, :c2]
|
32
|
+
[register_a.qd, register_b.qd, in3] >> mux3[:c0, :c1, :c2]
|
33
|
+
dec.sel_a >> [mux0.a, mux1.a, mux2.a, mux3.a]
|
34
|
+
dec.sel_b >> [mux0.b, mux1.b, mux2.b, mux3.b]
|
35
|
+
[mux0.y, mux1.y, mux2.y, mux3.y] >> [alu.a0, alu.a1, alu.a2, alu.a3]
|
45
36
|
|
46
|
-
register_c
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
pc.qa >> rom.a0
|
52
|
-
pc.qb >> rom.a1
|
53
|
-
pc.qc >> rom.a2
|
54
|
-
pc.qd >> rom.a3
|
55
|
-
rom.d0 >> alu.b0
|
56
|
-
rom.d1 >> alu.b1
|
57
|
-
rom.d2 >> alu.b2
|
58
|
-
rom.d3 >> alu.b3
|
59
|
-
rom.d4 >> dec.op0
|
60
|
-
rom.d5 >> dec.op1
|
61
|
-
rom.d6 >> dec.op2
|
62
|
-
rom.d7 >> dec.op3
|
63
|
-
dec.ld0 >> register_a.ld
|
64
|
-
dec.ld1 >> register_b.ld
|
65
|
-
dec.ld2 >> register_c.ld
|
66
|
-
dec.ld3 >> pc.ld
|
37
|
+
register_c[:qa, :qb, :qc, :qd] >> [led4, led3, led2, led1]
|
38
|
+
pc[:qa, :qb, :qc, :qd] >> rom[:a0, :a1, :a2, :a3]
|
39
|
+
rom[:d0, :d1, :d2, :d3] >> alu[:b0, :b1, :b2, :b3]
|
40
|
+
rom[:d4, :d5, :d6, :d7] >> dec[:op0, :op1, :op2, :op3]
|
41
|
+
dec[:ld0, :ld1, :ld2, :ld3] >> [register_a.ld, register_b.ld, register_c.ld, pc.ld]
|
67
42
|
dff.q >> dec.c_flag
|
68
43
|
|
69
44
|
[register_a, register_b, pc, rom, dec]
|
@@ -74,14 +49,14 @@ module Logicuit
|
|
74
49
|
p_b = "(#{@b || "0000"})"
|
75
50
|
|
76
51
|
register_a, register_b, pc, rom, dec = components
|
77
|
-
@a = a =
|
78
|
-
@b = b =
|
79
|
-
p =
|
80
|
-
o =
|
81
|
-
i =
|
82
|
-
m =
|
52
|
+
@a = a = register_a[:qd, :qc, :qb, :qa].to_s
|
53
|
+
@b = b = register_b[:qd, :qc, :qb, :qa].to_s
|
54
|
+
p = pc[:qd, :qc, :qb, :qa]
|
55
|
+
o = self[:led1, :led2, :led3, :led4]
|
56
|
+
i = self[:in3, :in2, :in1, :in0]
|
57
|
+
m = rom[:d3, :d2, :d1, :d0]
|
83
58
|
c = "-(#{dec.c_flag})"
|
84
|
-
loc = p.to_i(2)
|
59
|
+
loc = p.to_s.to_i(2)
|
85
60
|
|
86
61
|
l1 = led1.current ? "*" : " "
|
87
62
|
l2 = led2.current ? "*" : " "
|
@@ -2,19 +2,17 @@
|
|
2
2
|
|
3
3
|
module Logicuit
|
4
4
|
module Circuits
|
5
|
-
module
|
5
|
+
module Td4
|
6
6
|
# Decoder class
|
7
|
-
class Decoder <
|
8
|
-
|
7
|
+
class Decoder < DSL
|
8
|
+
inputs :op3, :op2, :op1, :op0, :c_flag
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
ld2: ->(op3, op2, _, _, _) { !op3 || op2 },
|
17
|
-
ld3: ->(op3, op2, _, op0, c_flag) { !op3 || !op2 || (!op0 && c_flag) }
|
10
|
+
outputs sel_b: -> { op1 },
|
11
|
+
sel_a: -> { op3 || op0 },
|
12
|
+
ld0: -> { op3 || op2 },
|
13
|
+
ld1: -> { op3 || !op2 },
|
14
|
+
ld2: -> { !op3 || op2 },
|
15
|
+
ld3: -> { !op3 || !op2 || (!op0 && c_flag) }
|
18
16
|
|
19
17
|
truth_table <<~TRUTH_TABLE
|
20
18
|
| OP3 | OP2 | OP1 | OP0 | C_FLAG | SEL_B | SEL_A | LD0 | LD1 | LD2 | LD3 |
|
@@ -2,15 +2,17 @@
|
|
2
2
|
|
3
3
|
module Logicuit
|
4
4
|
module Circuits
|
5
|
-
module
|
6
|
-
#
|
7
|
-
class
|
8
|
-
|
5
|
+
module Td4
|
6
|
+
# Timer
|
7
|
+
class Rom < DSL
|
8
|
+
inputs :a3, :a2, :a1, :a0
|
9
9
|
|
10
|
-
|
10
|
+
outputs :d7, :d6, :d5, :d4, :d3, :d2, :d1, :d0
|
11
11
|
|
12
12
|
def evaluate
|
13
|
-
|
13
|
+
return unless initialized
|
14
|
+
|
15
|
+
output = case self[:a3, :a2, :a1, :a0].to_s
|
14
16
|
in "0000" then "10110111"
|
15
17
|
in "0001" then "00000001"
|
16
18
|
in "0010" then "11100001"
|
@@ -28,9 +30,7 @@ module Logicuit
|
|
28
30
|
in "1110" then "10111000"
|
29
31
|
in "1111" then "11111111"
|
30
32
|
end
|
31
|
-
|
32
|
-
v == "1" ? o.on : o.off
|
33
|
-
end
|
33
|
+
self[:d7, :d6, :d5, :d4, :d3, :d2, :d1, :d0].set output
|
34
34
|
end
|
35
35
|
|
36
36
|
truth_table <<~TRUTH_TABLE
|
@@ -3,79 +3,61 @@
|
|
3
3
|
# Logicuit module
|
4
4
|
module Logicuit
|
5
5
|
# base class for all gates and circuits
|
6
|
-
class
|
7
|
-
def self.tag(*tags)
|
8
|
-
tags.each do |tag|
|
9
|
-
registry[tag] = self
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
@@registry = {} # rubocop:disable Style/ClassVars
|
14
|
-
|
15
|
-
def self.registry
|
16
|
-
@@registry
|
17
|
-
end
|
18
|
-
|
6
|
+
class DSL
|
19
7
|
def initialize(*args)
|
20
8
|
@input_targets = []
|
9
|
+
@inputs_as_bool_struct = nil
|
21
10
|
@output_targets = []
|
22
11
|
@clock = false
|
23
12
|
@components = []
|
24
|
-
|
25
|
-
|
26
|
-
assembling
|
27
|
-
|
13
|
+
inputs(*args)
|
14
|
+
outputs
|
15
|
+
assembling
|
16
|
+
@initialized = true
|
17
|
+
evaluate
|
28
18
|
end
|
29
19
|
|
20
|
+
def inputs(*args); end
|
21
|
+
def outputs; end
|
22
|
+
def assembling; end
|
30
23
|
def evaluate(*args); end
|
31
24
|
|
32
|
-
attr_reader :input_targets, :output_targets, :clock, :components
|
25
|
+
attr_reader :input_targets, :output_targets, :clock, :components, :initialized
|
33
26
|
|
34
|
-
def self.
|
27
|
+
def self.inputs(*args, **kwargs)
|
35
28
|
# define getter methods for inputs
|
36
|
-
args
|
37
|
-
define_method(input) do
|
38
|
-
instance_variable_get("@#{input}")
|
39
|
-
end
|
40
|
-
end
|
29
|
+
attr_reader(*args)
|
41
30
|
|
42
31
|
# define initializer for inputs
|
43
|
-
define_method(:
|
44
|
-
|
32
|
+
define_method(:inputs) do |*instance_method_args|
|
33
|
+
@clock = true if kwargs&.key?(:clock)
|
45
34
|
args.each_with_index do |input, index|
|
46
35
|
signal = Signals::Signal.new(instance_method_args[index] == 1)
|
47
|
-
signal
|
36
|
+
signal >> self unless clock
|
48
37
|
instance_variable_set("@#{input}", signal)
|
49
38
|
@input_targets << input
|
50
39
|
end
|
51
|
-
Signals::Clock
|
40
|
+
Signals::Clock >> self if clock
|
41
|
+
@inputs_as_bool_struct = Struct.new(*@input_targets)
|
52
42
|
end
|
43
|
+
end
|
53
44
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
signal.on
|
62
|
-
else
|
63
|
-
signal.off
|
64
|
-
end
|
65
|
-
end
|
45
|
+
def [](*keys)
|
46
|
+
if keys.size == 1
|
47
|
+
send(keys.first)
|
48
|
+
elsif keys.size > 1
|
49
|
+
Signals::SignalGroup.new(*(keys.map { |key| send(key) }))
|
50
|
+
else
|
51
|
+
raise ArgumentError, "Invalid number of arguments"
|
66
52
|
end
|
67
53
|
end
|
68
54
|
|
69
|
-
def self.
|
55
|
+
def self.outputs(*args, **kwargs)
|
70
56
|
# define getter methods for outputs
|
71
|
-
(args + kwargs.keys)
|
72
|
-
define_method(output) do
|
73
|
-
instance_variable_get("@#{output}")
|
74
|
-
end
|
75
|
-
end
|
57
|
+
attr_reader(*(args + kwargs.keys))
|
76
58
|
|
77
59
|
# define initializer for outputs
|
78
|
-
define_method(:
|
60
|
+
define_method(:outputs) do
|
79
61
|
(args + kwargs.keys).each do |output|
|
80
62
|
instance_variable_set("@#{output}", Signals::Signal.new(false))
|
81
63
|
@output_targets << output
|
@@ -86,6 +68,8 @@ module Logicuit
|
|
86
68
|
return if kwargs.empty?
|
87
69
|
|
88
70
|
define_method(:evaluate) do |*override_args|
|
71
|
+
return unless initialized
|
72
|
+
|
89
73
|
kwargs.each do |output, evaluator|
|
90
74
|
signal = instance_variable_get("@#{output}")
|
91
75
|
e_args = if override_args.empty?
|
@@ -95,7 +79,7 @@ module Logicuit
|
|
95
79
|
else
|
96
80
|
override_args
|
97
81
|
end
|
98
|
-
if
|
82
|
+
if @inputs_as_bool_struct.new(*e_args).instance_exec(&evaluator)
|
99
83
|
signal.on
|
100
84
|
else
|
101
85
|
signal.off
|
@@ -104,13 +88,10 @@ module Logicuit
|
|
104
88
|
end
|
105
89
|
end
|
106
90
|
|
107
|
-
def self.assembling
|
91
|
+
def self.assembling(&block)
|
108
92
|
define_method(:assembling) do
|
109
|
-
|
110
|
-
|
111
|
-
end) || []).each do |component|
|
112
|
-
@components << component
|
113
|
-
end
|
93
|
+
ret = instance_eval(&block)
|
94
|
+
ret.each { @components << _1 } if ret.is_a?(Array)
|
114
95
|
end
|
115
96
|
end
|
116
97
|
|
@@ -147,12 +128,12 @@ module Logicuit
|
|
147
128
|
[:ref, v.to_sym]
|
148
129
|
end
|
149
130
|
end
|
150
|
-
end.select do |values|
|
131
|
+
end.select do |values|
|
151
132
|
headers.size == values.size
|
152
|
-
end.map do |values|
|
133
|
+
end.map do |values|
|
153
134
|
array = [values]
|
154
|
-
while array.any? {
|
155
|
-
target_index = array.find_index {
|
135
|
+
while array.any? { _1.any? { |v| v == :any } }
|
136
|
+
target_index = array.find_index { _1.any? { |v| v == :any } }
|
156
137
|
target = array[target_index]
|
157
138
|
prop_index = target.find_index { |v| v == :any }
|
158
139
|
array.delete_at(target_index)
|
@@ -163,63 +144,40 @@ module Logicuit
|
|
163
144
|
end)
|
164
145
|
end
|
165
146
|
array
|
166
|
-
end.flatten!(1).map do |values|
|
147
|
+
end.flatten!(1).map do |values|
|
167
148
|
headers.zip(values).to_h
|
168
149
|
end
|
169
150
|
table
|
170
151
|
end
|
171
152
|
end
|
172
|
-
end
|
173
153
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
system("clear") unless noclear
|
179
|
-
puts circuit
|
180
|
-
puts
|
181
|
-
puts "tick: #{Signals::Clock.tick_count}" if circuit.clock
|
182
|
-
if circuit.respond_to?(:instructions)
|
183
|
-
puts "instructions: #{circuit.instructions.join "|"}"
|
184
|
-
elsif circuit.input_targets.any?
|
185
|
-
puts "input: #{circuit.input_targets.join ","}?"
|
186
|
-
end
|
187
|
-
}
|
188
|
-
|
189
|
-
if circuit.clock && hz.nonzero?
|
190
|
-
Thread.new do
|
191
|
-
loop do
|
192
|
-
render.call
|
193
|
-
sleep 1.0 / hz
|
194
|
-
Signals::Clock.tick
|
195
|
-
end
|
196
|
-
end
|
197
|
-
else
|
198
|
-
render.call
|
199
|
-
end
|
154
|
+
def self.verify_against_truth_table
|
155
|
+
new.truth_table.each do |row|
|
156
|
+
args = row.values_at(*new.input_targets).map { _1 ? 1 : 0 }
|
157
|
+
subject = new(*args)
|
200
158
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
if
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
next
|
213
|
-
end
|
159
|
+
previous_values = row.reject do |_k, v|
|
160
|
+
v == :clock
|
161
|
+
end.keys.reduce({}) { |acc, key| acc.merge(key => subject.send(key).current) }
|
162
|
+
|
163
|
+
Signals::Clock.tick if row.values.find :clock
|
164
|
+
|
165
|
+
row.each do |key, value|
|
166
|
+
next if value == :clock
|
167
|
+
|
168
|
+
if value.is_a?(Array) && value.first == :ref
|
169
|
+
expected = previous_values[value.last]
|
214
170
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
signal.on
|
171
|
+
raise "#{self}.new(#{args.join(", ")}).#{key} should be #{expected}" unless expected == subject.send(key).current
|
172
|
+
else
|
173
|
+
raise "#{self}.new(#{args.join(", ")}).#{key} should be #{value}" unless value == subject.send(key).current
|
174
|
+
end
|
220
175
|
end
|
221
|
-
render.call # rubocop:disable Style/IdenticalConditionalBranches
|
222
176
|
end
|
223
177
|
end
|
178
|
+
|
179
|
+
def self.run(opts = {})
|
180
|
+
::Logicuit.run(new, **opts)
|
181
|
+
end
|
224
182
|
end
|
225
183
|
end
|
data/lib/logicuit/gates/and.rb
CHANGED
@@ -3,18 +3,16 @@
|
|
3
3
|
module Logicuit
|
4
4
|
module Gates
|
5
5
|
# AND gate
|
6
|
-
class And <
|
7
|
-
tag :AND
|
8
|
-
|
6
|
+
class And < DSL
|
9
7
|
diagram <<~DIAGRAM
|
10
|
-
(A)-|
|
8
|
+
(A)-| |
|
11
9
|
|AND|-(Y)
|
12
|
-
(B)-|
|
10
|
+
(B)-| |
|
13
11
|
DIAGRAM
|
14
12
|
|
15
|
-
|
13
|
+
inputs :a, :b
|
16
14
|
|
17
|
-
|
15
|
+
outputs y: -> { a && b }
|
18
16
|
|
19
17
|
truth_table <<~TRUTH_TABLE
|
20
18
|
| A | B | Y |
|