circuits 0.4.3 → 0.5.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 +8 -8
- data/lib/circuits/component/and.rb +7 -10
- data/lib/circuits/component/base.rb +114 -0
- data/lib/circuits/component/nand.rb +7 -10
- data/lib/circuits/component/nor.rb +7 -10
- data/lib/circuits/component/not.rb +7 -10
- data/lib/circuits/component/or.rb +7 -10
- data/lib/circuits/component/sr_nand.rb +12 -12
- data/lib/circuits/component/sr_nor.rb +8 -8
- data/lib/circuits/component/xnor.rb +7 -10
- data/lib/circuits/component/xor.rb +7 -10
- data/lib/circuits/version.rb +1 -1
- data/spec/unit/circuits/{component_spec.rb → component/base_spec.rb} +102 -114
- metadata +4 -4
- data/lib/circuits/component.rb +0 -121
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzIxYzBlMDM5ZmJjYjliOWZkODEwM2QxNGUwYmE5ZGIxMWZlYzFkZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
Y2E3NDYzMjVmMWY3OWI4MjliZmE5NTRlMTIyMDAwZTRmMGM5ZjNhZg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTJhMDdmNzE2ZDYyMjAzYjkyMGJlMmRkNmNhYjc4NTZhMzliYmM1MzZiNjdh
|
10
|
+
OGUwMzY2ZWM0OThjYTQyNDIwYTZmOWMxYTdlOTA3ODAwZDhiZjI2NmE0NjEy
|
11
|
+
ZTA1MDg2MTE4NmMyMWI2YTgzYzhjMzRiNmQzOTY4MGZhNTM5YjM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjM5YzM1OTE2MTZlZDc4ZjdlNDI1ODgzNTkxNmUxZWVjYjgyNGFkNDU4Yjlh
|
14
|
+
MTZiNjY0MDM5OGJlMzRiNjc0ZjU3YjM5MzU3NzM5ZWQyNDVmZTE2ZjRlYTdl
|
15
|
+
MDVhZjViYjc2MTlhNTc5ZWU1NGYzM2E5YzYzMGIxMDI5MmYyZDM=
|
@@ -1,22 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# Logical AND Operator
|
6
|
-
class And
|
7
|
-
|
6
|
+
class And < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@input_count = 2
|
9
|
+
@output_count = 1
|
10
|
+
super opts
|
11
|
+
end
|
8
12
|
|
9
13
|
# Sets the output to be the result of a logical AND of the inputs
|
10
14
|
def tick
|
11
15
|
outputs[0].set(inputs.map(&:get).inject(:&))
|
12
16
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def set_defaults
|
17
|
-
@input_count = 2
|
18
|
-
@output_count = 1
|
19
|
-
end
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'circuits/terminal/input'
|
2
|
+
require 'circuits/terminal/output'
|
3
|
+
|
4
|
+
module Circuits
|
5
|
+
# A component has a set of inputs an outputs. Every `tick` a componnent
|
6
|
+
# computes its outputs, but the componnent will wait for the `tock` before the
|
7
|
+
# componnent updates its own outputs
|
8
|
+
module Component
|
9
|
+
# Base class to extend
|
10
|
+
class Base
|
11
|
+
# Creates the Component with inputs and outputs
|
12
|
+
# @param opts [Hash] options to create the Component with
|
13
|
+
# @option opts [Array<Input>, FixNum] :inputs The array of inputs to use,
|
14
|
+
# or the number of inputs to create
|
15
|
+
def initialize(opts = {})
|
16
|
+
create_inputs opts
|
17
|
+
create_outputs opts
|
18
|
+
end
|
19
|
+
|
20
|
+
# Does the internal computation and sets the outputs
|
21
|
+
def tick
|
22
|
+
fail NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets all the outputs expose what was set in #tick
|
26
|
+
def tock
|
27
|
+
outputs.each(&:tock)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Gets the teminal assigned to the port
|
31
|
+
# @param port [Symbol] The symbol that represents the terminal
|
32
|
+
# @return [Input, Output] The terminal
|
33
|
+
def [](port)
|
34
|
+
p = port_mappings[port]
|
35
|
+
case p[:type]
|
36
|
+
when :input
|
37
|
+
inputs[p[:number]]
|
38
|
+
when :output
|
39
|
+
outputs[p[:number]]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Assigns to an input or output
|
44
|
+
# @param port [Symbol] The symbol that represents the terminal
|
45
|
+
# @param terminal [Input, Output] The terminal to assign
|
46
|
+
# @return [Input, Output] The terminal that was passed in
|
47
|
+
def []=(port, terminal)
|
48
|
+
p = port_mappings[port]
|
49
|
+
case p[:type]
|
50
|
+
when :input
|
51
|
+
inputs[p[:number]] = terminal
|
52
|
+
when :output
|
53
|
+
outputs[p[:number]] = terminal
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# the inputs of this component
|
58
|
+
attr_reader :inputs
|
59
|
+
|
60
|
+
# the outputs of this component
|
61
|
+
attr_reader :outputs
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def create_inputs(opts)
|
66
|
+
if opts[:inputs].class == Array
|
67
|
+
@inputs = opts[:inputs]
|
68
|
+
@input_count = @inputs.length
|
69
|
+
elsif opts[:inputs].class == Fixnum
|
70
|
+
@input_count = opts[:inputs]
|
71
|
+
end
|
72
|
+
@inputs ||= @input_count.times.collect { Circuits::Terminal::Input.new }
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_outputs(opts)
|
76
|
+
if opts[:outputs].class == Array
|
77
|
+
@outputs = opts[:outputs]
|
78
|
+
@output_count = @outputs.length
|
79
|
+
elsif opts[:outputs].class == Fixnum
|
80
|
+
@output_count = opts[:outputs]
|
81
|
+
end
|
82
|
+
@outputs ||= @output_count.times.collect do
|
83
|
+
Circuits::Terminal::Output.new
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def port_mappings
|
88
|
+
return @port_mappings unless @port_mappings.nil?
|
89
|
+
@port_mappings = {}
|
90
|
+
input_mappings.each { |x| @port_mappings.merge!(x) }
|
91
|
+
output_mappings.each { |x| @port_mappings.merge!(x) }
|
92
|
+
@port_mappings
|
93
|
+
end
|
94
|
+
|
95
|
+
def input_mappings
|
96
|
+
return [{ in: { type: :input, number: 0 } }] if @input_count == 1
|
97
|
+
@input_count.times.collect do |i|
|
98
|
+
{ num_to_port(i) => { type: :input, number: i } }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def output_mappings
|
103
|
+
return[{ out: { type: :output, number: 0 } }] if @output_count == 1
|
104
|
+
@output_count.times.collect do |i|
|
105
|
+
{ num_to_port(i + @input_count) => { type: :output, number: i } }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def num_to_port(i)
|
110
|
+
(i + 'a'.ord).chr.to_sym
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -1,22 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# Logical NAND Operator
|
6
|
-
class Nand
|
7
|
-
|
6
|
+
class Nand < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@input_count = 2
|
9
|
+
@output_count = 1
|
10
|
+
super opts
|
11
|
+
end
|
8
12
|
|
9
13
|
# Sets the output to be the result of a logical NAND of the inputs
|
10
14
|
def tick
|
11
15
|
outputs[0].set(!inputs.map(&:get).inject(:&))
|
12
16
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def set_defaults
|
17
|
-
@input_count = 2
|
18
|
-
@output_count = 1
|
19
|
-
end
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -1,22 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# Logical NOR Operator
|
6
|
-
class Nor
|
7
|
-
|
6
|
+
class Nor < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@input_count = 2
|
9
|
+
@output_count = 1
|
10
|
+
super opts
|
11
|
+
end
|
8
12
|
|
9
13
|
# Sets the output to be the result of a logical OR of the inputs
|
10
14
|
def tick
|
11
15
|
outputs[0].set(!inputs.map(&:get).inject(:|))
|
12
16
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def set_defaults
|
17
|
-
@input_count = 2
|
18
|
-
@output_count = 1
|
19
|
-
end
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -1,22 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# Logical NOT Operator
|
6
|
-
class Not
|
7
|
-
|
6
|
+
class Not < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@input_count = 1
|
9
|
+
@output_count = 1
|
10
|
+
super opts
|
11
|
+
end
|
8
12
|
|
9
13
|
# Sets the output to be the result of a logical NOT of the inputs
|
10
14
|
def tick
|
11
15
|
outputs[0].set(!inputs[0].get)
|
12
16
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def set_defaults
|
17
|
-
@input_count = 1
|
18
|
-
@output_count = 1
|
19
|
-
end
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -1,22 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# Logical OR Operator
|
6
|
-
class Or
|
7
|
-
|
6
|
+
class Or < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@input_count = 2
|
9
|
+
@output_count = 1
|
10
|
+
super opts
|
11
|
+
end
|
8
12
|
|
9
13
|
# Sets the output to be the result of a logical OR of the inputs
|
10
14
|
def tick
|
11
15
|
outputs[0].set(inputs.map(&:get).inject(:|))
|
12
16
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def set_defaults
|
17
|
-
@input_count = 2
|
18
|
-
@output_count = 1
|
19
|
-
end
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -1,14 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# SR NAND Latch
|
6
|
-
class SrNand
|
7
|
-
|
6
|
+
class SrNand < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
set_defaults
|
9
|
+
super opts
|
10
|
+
create_sub_components
|
11
|
+
link_sub_components
|
12
|
+
end
|
8
13
|
|
9
14
|
# Computes the outputs based on the inputs and previous state
|
10
15
|
def tick
|
11
|
-
|
16
|
+
update_sub_components
|
12
17
|
self[:q].set nand_1[:out].get
|
13
18
|
self[:not_q].set nand_2[:out].get
|
14
19
|
end
|
@@ -17,13 +22,13 @@ module Circuits
|
|
17
22
|
|
18
23
|
attr_reader :nand_1, :nand_2, :sub_components
|
19
24
|
|
20
|
-
def
|
25
|
+
def create_sub_components
|
21
26
|
@nand_1 = Nand.new
|
22
27
|
@nand_2 = Nand.new
|
23
28
|
@sub_components = [@nand_1, @nand_2]
|
24
29
|
end
|
25
30
|
|
26
|
-
def
|
31
|
+
def link_sub_components
|
27
32
|
nand_1[:a] = self[:not_s]
|
28
33
|
nand_2[:a] = self[:not_r]
|
29
34
|
nand_1[:b] = nand_2[:out]
|
@@ -41,12 +46,7 @@ module Circuits
|
|
41
46
|
}
|
42
47
|
end
|
43
48
|
|
44
|
-
def
|
45
|
-
create_internal_components
|
46
|
-
link_internal_components
|
47
|
-
end
|
48
|
-
|
49
|
-
def update_internal_components
|
49
|
+
def update_sub_components
|
50
50
|
2.times.each do
|
51
51
|
sub_components.each(&:tick)
|
52
52
|
sub_components.each(&:tock)
|
@@ -1,10 +1,15 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# SR NOR Latch
|
6
|
-
class SrNor
|
7
|
-
|
6
|
+
class SrNor < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
set_defaults
|
9
|
+
super opts
|
10
|
+
create_internal_components
|
11
|
+
link_internal_components
|
12
|
+
end
|
8
13
|
|
9
14
|
# Computes the outputs based on the inputs and previous state
|
10
15
|
def tick
|
@@ -41,11 +46,6 @@ module Circuits
|
|
41
46
|
}
|
42
47
|
end
|
43
48
|
|
44
|
-
def setup
|
45
|
-
create_internal_components
|
46
|
-
link_internal_components
|
47
|
-
end
|
48
|
-
|
49
49
|
def update_internal_components
|
50
50
|
2.times.each do
|
51
51
|
sub_components.each(&:tick)
|
@@ -1,22 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# Logical XNOR Operator
|
6
|
-
class Xnor
|
7
|
-
|
6
|
+
class Xnor < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@input_count = 2
|
9
|
+
@output_count = 1
|
10
|
+
super opts
|
11
|
+
end
|
8
12
|
|
9
13
|
# Sets the output to be the result of a logical XNOR of the inputs
|
10
14
|
def tick
|
11
15
|
outputs[0].set(!inputs.map(&:get).inject(:^))
|
12
16
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def set_defaults
|
17
|
-
@input_count = 2
|
18
|
-
@output_count = 1
|
19
|
-
end
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -1,22 +1,19 @@
|
|
1
|
-
require 'circuits/component'
|
1
|
+
require 'circuits/component/base'
|
2
2
|
|
3
3
|
module Circuits
|
4
4
|
module Component
|
5
5
|
# Logical XOR Operator
|
6
|
-
class Xor
|
7
|
-
|
6
|
+
class Xor < Base
|
7
|
+
def initialize(opts = {})
|
8
|
+
@input_count = 2
|
9
|
+
@output_count = 1
|
10
|
+
super opts
|
11
|
+
end
|
8
12
|
|
9
13
|
# Sets the output to be the result of a logical XOR of the inputs
|
10
14
|
def tick
|
11
15
|
outputs[0].set(inputs.map(&:get).inject(:^))
|
12
16
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def set_defaults
|
17
|
-
@input_count = 2
|
18
|
-
@output_count = 1
|
19
|
-
end
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
data/lib/circuits/version.rb
CHANGED
@@ -1,114 +1,102 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'circuits/component'
|
3
|
-
|
4
|
-
# Mock component to include Circuits::Component
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
describe '#
|
69
|
-
it '
|
70
|
-
expect
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
expect(subject[:
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
expect(subject[:d]).to eq(outputs[1])
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'when you do not override #set_defaults' do
|
110
|
-
it 'raises NotImplementedError' do
|
111
|
-
expect { MockComponent2.new }.to raise_error(NotImplementedError)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'circuits/component/base'
|
3
|
+
|
4
|
+
# Mock component to include Circuits::Component::Base
|
5
|
+
class MockComponent < Circuits::Component::Base
|
6
|
+
def initialize(opts = {})
|
7
|
+
@input_count = 1
|
8
|
+
@output_count = 1
|
9
|
+
super opts
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Circuits::Component::Base do
|
14
|
+
context 'when using defaults' do
|
15
|
+
subject { MockComponent.new }
|
16
|
+
|
17
|
+
it 'has one input' do
|
18
|
+
expect(subject.inputs.count).to eq(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has one output' do
|
22
|
+
expect(subject.outputs.count).to eq(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#[]=' do
|
26
|
+
let(:new_input) { double('new_input') }
|
27
|
+
let(:new_output) { double('new_output') }
|
28
|
+
|
29
|
+
before do
|
30
|
+
subject[:in] = new_input
|
31
|
+
subject[:out] = new_output
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'has the new input available as :in' do
|
35
|
+
expect(subject[:in]).to eq(new_input)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'has the new output available as :out' do
|
39
|
+
expect(subject[:out]).to eq(new_output)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when specifying input and output count' do
|
45
|
+
subject { MockComponent.new(inputs: 2, outputs: 2) }
|
46
|
+
|
47
|
+
it 'has one input' do
|
48
|
+
expect(subject.inputs.count).to eq(2)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'has one output' do
|
52
|
+
expect(subject.outputs.count).to eq(2)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when supplying inputs and outputs' do
|
57
|
+
let(:inputs) { [double('input')] }
|
58
|
+
let(:outputs) { [double('output')] }
|
59
|
+
|
60
|
+
subject { MockComponent.new(inputs: inputs, outputs: outputs) }
|
61
|
+
|
62
|
+
describe '#tick' do
|
63
|
+
it 'raises NotImplementedError' do
|
64
|
+
expect { subject.tick }.to raise_error(NotImplementedError)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#tock' do
|
69
|
+
it 'tocks the outputs' do
|
70
|
+
expect(outputs[0]).to receive(:tock)
|
71
|
+
subject.tock
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#[]' do
|
76
|
+
context 'one input and one output' do
|
77
|
+
it 'has the input available as :in' do
|
78
|
+
expect(subject[:in]).to eq(inputs[0])
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'has the output available as :out' do
|
82
|
+
expect(subject[:out]).to eq(outputs[0])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'two inputs and two outputs' do
|
87
|
+
let(:inputs) { [double('input_1'), double('input_2')] }
|
88
|
+
let(:outputs) { [double('output_1'), double('output_2')] }
|
89
|
+
|
90
|
+
it 'has the inputs available as :a and :b' do
|
91
|
+
expect(subject[:a]).to eq(inputs[0])
|
92
|
+
expect(subject[:b]).to eq(inputs[1])
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'has the outputs available as :c and :d' do
|
96
|
+
expect(subject[:c]).to eq(outputs[0])
|
97
|
+
expect(subject[:d]).to eq(outputs[1])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: circuits
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henry Muru Paenga
|
@@ -124,8 +124,8 @@ files:
|
|
124
124
|
- Rakefile
|
125
125
|
- circuits.gemspec
|
126
126
|
- lib/circuits.rb
|
127
|
-
- lib/circuits/component.rb
|
128
127
|
- lib/circuits/component/and.rb
|
128
|
+
- lib/circuits/component/base.rb
|
129
129
|
- lib/circuits/component/nand.rb
|
130
130
|
- lib/circuits/component/nor.rb
|
131
131
|
- lib/circuits/component/not.rb
|
@@ -140,6 +140,7 @@ files:
|
|
140
140
|
- lib/circuits/version.rb
|
141
141
|
- spec/spec_helper.rb
|
142
142
|
- spec/unit/circuits/component/and_spec.rb
|
143
|
+
- spec/unit/circuits/component/base_spec.rb
|
143
144
|
- spec/unit/circuits/component/nand_spec.rb
|
144
145
|
- spec/unit/circuits/component/nor_spec.rb
|
145
146
|
- spec/unit/circuits/component/not_spec.rb
|
@@ -148,7 +149,6 @@ files:
|
|
148
149
|
- spec/unit/circuits/component/sr_nor_spec.rb
|
149
150
|
- spec/unit/circuits/component/xnor_spec.rb
|
150
151
|
- spec/unit/circuits/component/xor_spec.rb
|
151
|
-
- spec/unit/circuits/component_spec.rb
|
152
152
|
- spec/unit/circuits/terminal/input_spec.rb
|
153
153
|
- spec/unit/circuits/terminal/output_spec.rb
|
154
154
|
homepage: https://github.com/meringu/circuits
|
@@ -178,6 +178,7 @@ summary: Express logical circuits in code
|
|
178
178
|
test_files:
|
179
179
|
- spec/spec_helper.rb
|
180
180
|
- spec/unit/circuits/component/and_spec.rb
|
181
|
+
- spec/unit/circuits/component/base_spec.rb
|
181
182
|
- spec/unit/circuits/component/nand_spec.rb
|
182
183
|
- spec/unit/circuits/component/nor_spec.rb
|
183
184
|
- spec/unit/circuits/component/not_spec.rb
|
@@ -186,6 +187,5 @@ test_files:
|
|
186
187
|
- spec/unit/circuits/component/sr_nor_spec.rb
|
187
188
|
- spec/unit/circuits/component/xnor_spec.rb
|
188
189
|
- spec/unit/circuits/component/xor_spec.rb
|
189
|
-
- spec/unit/circuits/component_spec.rb
|
190
190
|
- spec/unit/circuits/terminal/input_spec.rb
|
191
191
|
- spec/unit/circuits/terminal/output_spec.rb
|
data/lib/circuits/component.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'circuits/terminal/input'
|
2
|
-
require 'circuits/terminal/output'
|
3
|
-
|
4
|
-
module Circuits
|
5
|
-
# A component has a set of inputs an outputs. Every `tick` a componnent
|
6
|
-
# computes its outputs, but the componnent will wait for the `tock` before the
|
7
|
-
# componnent updates its own outputs
|
8
|
-
module Component
|
9
|
-
# Creates the Component with inputs and outputs
|
10
|
-
# @param opts [Hash] options to create the Component with
|
11
|
-
# @option opts [Array<Input>, FixNum] :inputs The array of inputs to use, or
|
12
|
-
# the number of inputs to create
|
13
|
-
def initialize(opts = {})
|
14
|
-
set_defaults
|
15
|
-
create_inputs opts
|
16
|
-
create_outputs opts
|
17
|
-
create_port_mappings
|
18
|
-
setup
|
19
|
-
end
|
20
|
-
|
21
|
-
# Does the internal computation and sets the outputs
|
22
|
-
def tick
|
23
|
-
fail NotImplementedError
|
24
|
-
end
|
25
|
-
|
26
|
-
# Sets all the outputs expose what was set in #tick
|
27
|
-
def tock
|
28
|
-
outputs.each(&:tock)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Gets the teminal assigned to the port
|
32
|
-
# @param port [Symbol] The symbol that represents the terminal
|
33
|
-
# @return [Input, Output] The terminal
|
34
|
-
def [](port)
|
35
|
-
p = @port_mappings[port]
|
36
|
-
case p[:type]
|
37
|
-
when :input
|
38
|
-
@inputs[p[:number]]
|
39
|
-
when :output
|
40
|
-
@outputs[p[:number]]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Assigns to an input or output
|
45
|
-
# @param port [Symbol] The symbol that represents the terminal
|
46
|
-
# @param terminal [Input, Output] The terminal to assign
|
47
|
-
# @return [Input, Output] The terminal that was passed in
|
48
|
-
def []=(port, terminal)
|
49
|
-
p = @port_mappings[port]
|
50
|
-
case p[:type]
|
51
|
-
when :input
|
52
|
-
@inputs[p[:number]] = terminal
|
53
|
-
when :output
|
54
|
-
@outputs[p[:number]] = terminal
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# the inputs of this component
|
59
|
-
attr_reader :inputs
|
60
|
-
|
61
|
-
# the outputs of this component
|
62
|
-
attr_reader :outputs
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def create_inputs(opts)
|
67
|
-
if opts[:inputs].class == Array
|
68
|
-
@inputs = opts[:inputs]
|
69
|
-
@input_count = @inputs.length
|
70
|
-
elsif opts[:inputs].class == Fixnum
|
71
|
-
@input_count = opts[:inputs]
|
72
|
-
end
|
73
|
-
@inputs ||= @input_count.times.collect { Circuits::Terminal::Input.new }
|
74
|
-
end
|
75
|
-
|
76
|
-
def create_outputs(opts)
|
77
|
-
if opts[:outputs].class == Array
|
78
|
-
@outputs = opts[:outputs]
|
79
|
-
@output_count = @outputs.length
|
80
|
-
elsif opts[:outputs].class == Fixnum
|
81
|
-
@output_count = opts[:outputs]
|
82
|
-
end
|
83
|
-
@outputs ||= @output_count.times.collect do
|
84
|
-
Circuits::Terminal::Output.new
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def create_port_mappings
|
89
|
-
return @port_mappings unless @port_mappings.nil?
|
90
|
-
@port_mappings = {}
|
91
|
-
input_mappings.each { |x| @port_mappings.merge!(x) }
|
92
|
-
output_mappings.each { |x| @port_mappings.merge!(x) }
|
93
|
-
@port_mappings
|
94
|
-
end
|
95
|
-
|
96
|
-
def input_mappings
|
97
|
-
return [{ in: { type: :input, number: 0 } }] if @input_count == 1
|
98
|
-
@input_count.times.collect do |i|
|
99
|
-
{ num_to_port(i) => { type: :input, number: i } }
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def output_mappings
|
104
|
-
return[{ out: { type: :output, number: 0 } }] if @output_count == 1
|
105
|
-
@output_count.times.collect do |i|
|
106
|
-
{ num_to_port(i + @input_count) => { type: :output, number: i } }
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def num_to_port(i)
|
111
|
-
(i + 'a'.ord).chr.to_sym
|
112
|
-
end
|
113
|
-
|
114
|
-
def set_defaults
|
115
|
-
fail NotImplementedError
|
116
|
-
end
|
117
|
-
|
118
|
-
def setup
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|