diff --git a/lib/rcircuit/splitter.rb b/lib/rcircuit/splitter.rb new file mode 100644 index 0000000..de29963 --- /dev/null +++ b/lib/rcircuit/splitter.rb @@ -0,0 +1,36 @@ +## Outputs a specified subset of the bits from an input port +class Splitter < Device + # @param port [Port] A the splitter input port + # @param bits [Integer,Array,Range] The bits from the input port that are output by the splitter + # @return [void] + def initialize(port, bits) + if bits.is_a?(Integer) + width = 1 + @bitlist = [bits] + elsif bits.is_a?(Array) + width = bits.size + @bitlist = bits.reverse #store in MSB order + elsif bits.is_a?(Range) + width = bits.size + @bitlist = bits.to_a.reverse #store in MSB order + else + raise ArgumentError.new("bits argument must be of type Integer, Array , or Range") + end + @bits = bits + add_output("out", width) + port.add_callback { |val| on_change(val) } + on_change(port.val) + end + + private + # Called when there is a change to inputs + def on_change(input_val) + outval = 0 + @bitlist.each do |bit| + outval *= 2 + outval += ((input_val >> bit) & 1) + end + out.setval(outval) + end + +end diff --git a/spec/splitter_spec.rb b/spec/splitter_spec.rb new file mode 100644 index 0000000..2e21842 --- /dev/null +++ b/spec/splitter_spec.rb @@ -0,0 +1,18 @@ +describe Splitter do + it "should extract bits from an input port" do + inp = Port.new(8) + splitter = Splitter.new(inp, [1,6]) + inp.setval(0x03) + expect(splitter.out.val).to eq 1 + inp.setval(0x18) + expect(splitter.out.val).to eq 0 + inp.setval(0xC0) + expect(splitter.out.val).to eq 2 + inp.setval(0xF3) + expect(splitter.out.val).to eq 3 + #test port indexing + expect(inp[7].val).to eq 1 + expect(inp[4..7].val).to eq 15 + expect(inp[2,3,4].val).to eq 4 + end +end