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
@@ -3,18 +3,16 @@
3
3
  module Logicuit
4
4
  module Gates
5
5
  # NAND gate
6
- class Nand < Base
7
- tag :NAND
8
-
6
+ class Nand < DSL
9
7
  diagram <<~DIAGRAM
10
- (A)-|
8
+ (A)-| |
11
9
  |NAND|-(Y)
12
- (B)-|
10
+ (B)-| |
13
11
  DIAGRAM
14
12
 
15
- define_inputs :a, :b
13
+ inputs :a, :b
16
14
 
17
- define_outputs y: ->(a, b) { !(a && b) }
15
+ outputs y: -> { !(a && b) }
18
16
 
19
17
  truth_table <<~TRUTH_TABLE
20
18
  | A | B | Y |
@@ -3,16 +3,14 @@
3
3
  module Logicuit
4
4
  module Gates
5
5
  # NOT gate
6
- class Not < Base
7
- tag :NOT
8
-
6
+ class Not < DSL
9
7
  diagram <<~DIAGRAM
10
8
  (A)-|NOT|-(Y)
11
9
  DIAGRAM
12
10
 
13
- define_inputs :a
11
+ inputs :a
14
12
 
15
- define_outputs y: ->(a) { !a } # rubocop:disable Style/SymbolProc
13
+ outputs y: -> { !a }
16
14
 
17
15
  truth_table <<~TRUTH_TABLE
18
16
  | A | Y |
@@ -3,18 +3,16 @@
3
3
  module Logicuit
4
4
  module Gates
5
5
  # OR gate
6
- class Or < Base
7
- tag :OR
8
-
6
+ class Or < DSL
9
7
  diagram <<~DIAGRAM
10
- (A)-|
8
+ (A)-| |
11
9
  |OR|-(Y)
12
- (B)-|
10
+ (B)-| |
13
11
  DIAGRAM
14
12
 
15
- define_inputs :a, :b
13
+ inputs :a, :b
16
14
 
17
- define_outputs y: ->(a, b) { a || b }
15
+ outputs y: -> { a || b }
18
16
 
19
17
  truth_table <<~TRUTH_TABLE
20
18
  | A | B | Y |
@@ -3,18 +3,16 @@
3
3
  module Logicuit
4
4
  module Gates
5
5
  # XOR gate
6
- class Xor < Base
7
- tag :XOR
8
-
6
+ class Xor < DSL
9
7
  diagram <<~DIAGRAM
10
- (A)-|
8
+ (A)-| |
11
9
  |XOR|-(Y)
12
- (B)-|
10
+ (B)-| |
13
11
  DIAGRAM
14
12
 
15
- define_inputs :a, :b
13
+ inputs :a, :b
16
14
 
17
- define_outputs y: ->(a, b) { (a && !b) || (!a && b) }
15
+ outputs y: -> { (a && !b) || (!a && b) }
18
16
 
19
17
  truth_table <<~TRUTH_TABLE
20
18
  | A | B | Y |
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Logicuit module
4
+ module Logicuit
5
+ def self.run(circuit, hz: 1, noclear: false)
6
+ render = lambda {
7
+ system("clear") unless noclear
8
+ puts circuit
9
+ puts
10
+ puts "tick: #{Signals::Clock.tick_count}" if circuit.clock
11
+ puts "input: #{circuit.input_targets.join ","}?" if circuit.input_targets.any?
12
+ }
13
+
14
+ if circuit.clock && hz.nonzero?
15
+ Thread.new do
16
+ loop do
17
+ render.call
18
+ sleep 1.0 / hz
19
+ Signals::Clock.tick
20
+ end
21
+ end
22
+ else
23
+ render.call
24
+ end
25
+
26
+ while (input = gets.chomp)
27
+ key = input.to_sym
28
+ unless circuit.respond_to? key
29
+ if circuit.clock && hz.zero?
30
+ Signals::Clock.tick
31
+ render.call
32
+ end
33
+ next
34
+ end
35
+
36
+ signal = circuit.send(key)
37
+ if signal.current
38
+ signal.off
39
+ else
40
+ signal.on
41
+ end
42
+ render.call
43
+ end
44
+ end
45
+ end
@@ -5,36 +5,39 @@ module Logicuit
5
5
  # Clock
6
6
  class Clock
7
7
  def initialize
8
- @on_tick = []
8
+ @downstreams = []
9
9
  @tick_count = 0
10
10
  end
11
11
 
12
- attr_reader :on_tick, :tick_count
12
+ attr_reader :downstreams, :tick_count
13
13
 
14
14
  def tick
15
15
  @tick_count += 1
16
16
  # Call the `evaluate` method for all components.
17
- # However, the input argument values should be bound to the values at the time `on_tick` is called.
18
- @on_tick.map do |component|
17
+ # However, the input argument values should be bound to the values at the time `tick` is called.
18
+ @downstreams.map do |component|
19
19
  args = component.input_targets.map { |input| component.instance_variable_get("@#{input}").current }
20
20
  -> { component.evaluate(*args) }
21
21
  end.each(&:call)
22
22
  end
23
23
 
24
- def self.instance
25
- @instance ||= new
26
- end
24
+ class << self
25
+ def instance
26
+ @instance ||= new
27
+ end
27
28
 
28
- def self.on_tick
29
- instance.on_tick
30
- end
29
+ def connects_to(component)
30
+ instance.downstreams << component
31
+ end
32
+ alias >> connects_to
31
33
 
32
- def self.tick
33
- instance.tick
34
- end
34
+ def tick
35
+ instance.tick
36
+ end
35
37
 
36
- def self.tick_count
37
- instance.tick_count
38
+ def tick_count
39
+ instance.tick_count
40
+ end
38
41
  end
39
42
  end
40
43
  end
@@ -4,49 +4,54 @@ module Logicuit
4
4
  module Signals
5
5
  # Signal
6
6
  class Signal
7
- def initialize(current = false) # rubocop:disable Style/OptionalBooleanParameter
7
+ def initialize(current = false)
8
8
  @current = current
9
- @connected_by = nil
10
- @on_change = []
9
+ @downstreams = []
11
10
  end
12
11
 
13
- attr_reader :current, :on_change
14
- attr_accessor :connected_by
12
+ attr_reader :current
15
13
 
16
14
  def on
17
- changed = @current.!
15
+ return if @current
16
+
18
17
  @current = true
19
- @on_change.each(&:evaluate) if changed
20
- self
18
+ propagate_current
21
19
  end
22
20
 
23
21
  def off
24
- changed = @current
25
- @current = false
26
- @on_change.each(&:evaluate) if changed
27
- self
28
- end
22
+ return unless @current
29
23
 
30
- def toggle
31
- @current ? off : on
24
+ @current = false
25
+ propagate_current
32
26
  end
33
27
 
34
28
  def connects_to(other)
35
- other.connected_by = self
36
- other.evaluate
37
- on_change << other
29
+ if other.is_a? Array
30
+ @downstreams.concat(other)
31
+ elsif other.is_a? Signals::SignalGroup
32
+ @downstreams.concat(other.signals)
33
+ else
34
+ @downstreams << other
35
+ end
36
+ propagate_current
38
37
  end
39
38
  alias >> connects_to
40
39
 
41
- def evaluate
42
- return if @connected_by.nil?
43
-
44
- @connected_by.current ? on : off
45
- end
46
-
47
40
  def to_s
48
41
  current ? "1" : "0"
49
42
  end
43
+
44
+ private
45
+
46
+ def propagate_current
47
+ @downstreams.each do |downstream|
48
+ if downstream.is_a?(Signal)
49
+ current ? downstream.on : downstream.off
50
+ elsif downstream.respond_to?(:evaluate)
51
+ downstream.evaluate
52
+ end
53
+ end
54
+ end
50
55
  end
51
56
  end
52
57
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Logicuit
4
+ module Signals
5
+ # Signal Group
6
+ class SignalGroup
7
+ def initialize(*signals)
8
+ @signals = signals
9
+ end
10
+
11
+ def signals
12
+ @signals.dup
13
+ end
14
+
15
+ def connects_to(others)
16
+ others = others.signals if others.is_a?(SignalGroup)
17
+ @signals.zip(others).each { _1 >> _2 unless _1.nil? || _2.nil? }
18
+ end
19
+ alias >> connects_to
20
+
21
+ def to_s
22
+ signals.map { _1.current ? "1" : "0" }.join
23
+ end
24
+
25
+ def set(vals)
26
+ vals.split("").zip(signals).each do |v, o|
27
+ v == "1" ? o.on : o.off
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Logicuit
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/logicuit.rb CHANGED
@@ -1,24 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "logicuit/version"
4
- require_relative "logicuit/base"
4
+ require_relative "logicuit/dsl"
5
+ require_relative "logicuit/array_as_signal_group"
6
+ require_relative "logicuit/runner"
5
7
  require_relative "logicuit/gates/and"
6
8
  require_relative "logicuit/gates/or"
7
9
  require_relative "logicuit/gates/not"
8
10
  require_relative "logicuit/gates/nand"
9
11
  require_relative "logicuit/gates/xor"
10
12
  require_relative "logicuit/signals/signal"
13
+ require_relative "logicuit/signals/signal_group"
11
14
  require_relative "logicuit/signals/clock"
12
15
  require_relative "logicuit/circuits/combinational/multiplexer_2to1"
13
16
  require_relative "logicuit/circuits/combinational/multiplexer_4to1"
14
17
  require_relative "logicuit/circuits/combinational/half_adder"
15
18
  require_relative "logicuit/circuits/combinational/full_adder"
16
19
  require_relative "logicuit/circuits/combinational/full_adder_4bit"
17
- require_relative "logicuit/circuits/combinational/decoder"
18
- require_relative "logicuit/circuits/rom/timer"
19
20
  require_relative "logicuit/circuits/sequential/d_flip_flop"
20
21
  require_relative "logicuit/circuits/sequential/register_4bit"
21
22
  require_relative "logicuit/circuits/sequential/program_counter"
22
- require_relative "logicuit/circuits/system_level/one_bit_cpu"
23
- require_relative "logicuit/circuits/system_level/one_bit_cpu2"
24
- require_relative "logicuit/circuits/system_level/cpu_td4"
23
+ require_relative "logicuit/circuits/sequential/one_bit_cpu"
24
+ require_relative "logicuit/circuits/td4/cpu"
25
+ require_relative "logicuit/circuits/td4/decoder"
26
+ require_relative "logicuit/circuits/td4/rom"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logicuit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koji NAKAMURA
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-10 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: logi(c cir)cuit -> logicuit
13
13
  email:
@@ -21,27 +21,29 @@ files:
21
21
  - README.md
22
22
  - Rakefile
23
23
  - lib/logicuit.rb
24
- - lib/logicuit/base.rb
25
- - lib/logicuit/circuits/combinational/decoder.rb
24
+ - lib/logicuit/array_as_signal_group.rb
26
25
  - lib/logicuit/circuits/combinational/full_adder.rb
27
26
  - lib/logicuit/circuits/combinational/full_adder_4bit.rb
28
27
  - lib/logicuit/circuits/combinational/half_adder.rb
29
28
  - lib/logicuit/circuits/combinational/multiplexer_2to1.rb
30
29
  - lib/logicuit/circuits/combinational/multiplexer_4to1.rb
31
- - lib/logicuit/circuits/rom/timer.rb
32
30
  - lib/logicuit/circuits/sequential/d_flip_flop.rb
31
+ - lib/logicuit/circuits/sequential/one_bit_cpu.rb
33
32
  - lib/logicuit/circuits/sequential/program_counter.rb
34
33
  - lib/logicuit/circuits/sequential/register_4bit.rb
35
- - lib/logicuit/circuits/system_level/cpu_td4.rb
36
- - lib/logicuit/circuits/system_level/one_bit_cpu.rb
37
- - lib/logicuit/circuits/system_level/one_bit_cpu2.rb
34
+ - lib/logicuit/circuits/td4/cpu.rb
35
+ - lib/logicuit/circuits/td4/decoder.rb
36
+ - lib/logicuit/circuits/td4/rom.rb
37
+ - lib/logicuit/dsl.rb
38
38
  - lib/logicuit/gates/and.rb
39
39
  - lib/logicuit/gates/nand.rb
40
40
  - lib/logicuit/gates/not.rb
41
41
  - lib/logicuit/gates/or.rb
42
42
  - lib/logicuit/gates/xor.rb
43
+ - lib/logicuit/runner.rb
43
44
  - lib/logicuit/signals/clock.rb
44
45
  - lib/logicuit/signals/signal.rb
46
+ - lib/logicuit/signals/signal_group.rb
45
47
  - lib/logicuit/version.rb
46
48
  - sig/logicuit.rbs
47
49
  homepage: https://github.com/kozy4324/logicuit
@@ -66,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
68
  - !ruby/object:Gem::Version
67
69
  version: '0'
68
70
  requirements: []
69
- rubygems_version: 3.6.5
71
+ rubygems_version: 3.6.7
70
72
  specification_version: 4
71
73
  summary: logi(c cir)cuit -> logicuit
72
74
  test_files: []
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Logicuit
4
- module Circuits
5
- module SystemLevel
6
- # 1 bit CPU
7
- class OneBitCpu < Base
8
- tag :ONE_BIT_CPU
9
-
10
- diagram <<~DIAGRAM
11
- +-------------+
12
- | |
13
- +-|NOT|-| |-+-(Y)
14
- |DFF|
15
- (CK)-|> |
16
- DIAGRAM
17
-
18
- define_inputs clock: :ck
19
-
20
- define_outputs :y
21
-
22
- assembling do |y|
23
- dff = Sequential::DFlipFlop.new
24
- not_gate = Gates::Not.new
25
-
26
- dff.q >> not_gate.a
27
- not_gate.y >> dff.d
28
-
29
- dff.q >> y
30
- end
31
-
32
- truth_table <<~TRUTH_TABLE
33
- | CK | prev Y | Y |
34
- | -- | ------ | - |
35
- | ^ | 0 | 1 |
36
- | ^ | 1 | 0 |
37
- TRUTH_TABLE
38
- end
39
- end
40
- end
41
- end