Add gates

This commit is contained in:
pjht 2018-07-09 16:24:50 -05:00
parent c0b1776d20
commit 1760655308
6 changed files with 168 additions and 2 deletions

21
and.rb Normal file
View File

@ -0,0 +1,21 @@
require_relative "gate.rb"
require_relative "port.rb"
# Represents an AND gate
class AndGate < Gate
# Called when inputs change.
# Calculates AND of all inputs and sets output port to that value.
# @param vals [Array<Integer>] List of values for connected ports.
def inputs_changed(vals)
andval=nil
vals.each do |val|
if andval==nil
andval=val
else
andval=andval&val
end
end
out.setval(andval)
end
end

22
gate.rb
View File

@ -41,6 +41,28 @@ class Gate
inputs_changed(vals)
end
# Test a truth table for a gate.
# @param table [Array<Array<Integer>>] The truth table,
# which is an array of entries. The last value in the entry is the expected output,
# the rest are the inputs to the ports.
def self.test_table(table)
ports=[]
(table[0].length-1).times do
ports.push Port.new(1)
end
gate=self.new(*ports)
table.each do |entry|
i=0
ports.each do |port|
port.setval(entry[i])
i+=1
end
return false if gate.out!=entry.last
end
return true
end
# Called when inputs change.
# @abstract Override this to implement a gate.
# @param vals [Array<Integer>] List of values for connected ports.
def inputs_changed(vals); raise NotImplementedError; end

30
not.rb Normal file
View File

@ -0,0 +1,30 @@
require_relative "gate.rb"
require_relative "port.rb"
# Represents a NOT gate
class NotGate < Gate
# (see Gate#initialize)
def initialize(*args)
@outmask=0
super
@outmask=(2**@width)-1
end
# Add a port to the gate. As this is a NOT gate, there may only be one port.
# @param (see Gate#add_input)
# @return [void]
def add_input(input_port)
if @inputs.length > 0 then
raise ArgumentError, "Cannot add multiple inputs to a NOT gate"
end
super
end
# Called when inputs change.
# Calculates NOT of input and sets output port to that value.
# @param vals [Array<Integer>] List of values for connected ports.
def inputs_changed(vals)
out.setval((~vals[0]) & @outmask)
end
end

20
or.rb Normal file
View File

@ -0,0 +1,20 @@
require_relative "gate.rb"
require_relative "port.rb"
# Represents an OR gate
class OrGate < Gate
# Called when inputs change.
# Calculates OR of all inputs and sets output port to that value.
def inputs_changed(vals)
orval=nil
vals.each do |val|
if orval==nil
orval=val
else
orval=orval|val
end
end
out.setval(orval)
end
end

View File

@ -1,6 +1,9 @@
require_relative "../gate.rb"
require_relative "../port.rb"
require_relative "../gate.rb"
require_relative "../not.rb"
require_relative "../and.rb"
require_relative "../or.rb"
require_relative "../xor.rb"
describe Gate do
let(:klass) do
Class.new(Gate) do
@ -31,4 +34,54 @@ describe Gate do
b.setval(10)
expect(gate.out.val).to eq(18)
end
context "NotGate" do
it "should NOT the input" do
table=[
[0,1],
[1,0]
]
ok=NotGate.test_table(table)
expect(ok).to eq true
end
end
context "AndGate" do
it "should AND together all inputs" do
table=[
[0,0,0],
[0,1,0],
[1,0,0],
[1,1,1],
]
ok=AndGate.test_table(table)
expect(ok).to eq true
end
end
context "OrGate" do
it "should OR together all inputs" do
table=[
[0,0,0],
[0,1,1],
[1,0,1],
[1,1,1],
]
ok=OrGate.test_table(table)
expect(ok).to eq true
end
end
context "XorGate" do
it "should XOR together all inputs" do
table=[
[0,0,0],
[0,1,1],
[1,0,1],
[1,1,0],
]
ok=XorGate.test_table(table)
expect(ok).to eq true
end
end
end

20
xor.rb Normal file
View File

@ -0,0 +1,20 @@
require_relative "gate.rb"
require_relative "port.rb"
# Represents an XOR gate
class XorGate < Gate
# Called when inputs change.
# Calculates XOR of all inputs and sets output port to that value.
def inputs_changed(vals)
xorval=nil
vals.each do |val|
if xorval==nil
xorval=val
else
xorval=xorval^val
end
end
out.setval(xorval)
end
end