-
-
Save mirichi/df54ed39ec1437d5aa9a to your computer and use it in GitHub Desktop.
ハードウェアシミュレータ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
HLHASH = {true=>"H", false=>"L", nil=>"nil"} | |
H = true | |
L = false | |
QUEUE = [] | |
# 出力ピン | |
class OutputPin | |
attr_accessor :output_objects | |
def initialize(v=nil) | |
@value = v | |
@output_objects = [] | |
end | |
# 出力をセットする | |
def set(v) | |
tmp = @value | |
@value = v | |
# 出力が変わったら通知先をキューに格納する | |
if tmp != v | |
@output_objects.each do |i| | |
QUEUE.push i | |
end | |
end | |
self | |
end | |
# 出力の取得 | |
def get | |
@value | |
end | |
# &演算子 | |
def &(dst) | |
tmp = AND.new | |
tmp.a = self | |
tmp.b = dst | |
tmp.o | |
end | |
# |演算子 | |
def |(dst) | |
tmp = OR.new | |
tmp.a = self | |
tmp.b = dst | |
tmp.o | |
end | |
# ~演算子 | |
def ~ | |
tmp = NOT.new | |
tmp.a = self | |
tmp.o | |
end | |
end | |
# 外部からの入力用配線 | |
class Line | |
attr_accessor :output_objects | |
def initialize | |
@o = OutputPin.new | |
@output_objects = [] | |
end | |
def d=(v) | |
@d = OutputPin.new(v) | |
QUEUE.push(self) | |
# キューが無くなるまでシミュレーション実行 | |
while QUEUE.size > 0 | |
QUEUE.shift.update | |
end | |
end | |
def o | |
@o | |
end | |
def update | |
@o.set(@d.get) | |
end | |
end | |
class Bus1 | |
def initialize | |
@o = OutputPin.new | |
end | |
def o | |
@o | |
end | |
def add(v) | |
v.connect_bus(self) | |
end | |
end | |
class Bus | |
def initialize(bit_width) | |
@bus = Array.new(bit_width){Bus1.new} | |
end | |
def o | |
@bus.map{|b|b.o} | |
end | |
def add(v) | |
@bus.zip(v) do |b, tsb| | |
tsb.connect_bus(b) | |
end | |
end | |
end | |
class ThreeStateBuffer1 | |
def d=(v) | |
v.output_objects << self | |
@d = v | |
end | |
def g=(v) | |
v.output_objects << self | |
@g = v | |
end | |
def update | |
@bus.o.set(@d.get) if @g and @g.get | |
end | |
def connect_bus(b) | |
@bus = b | |
end | |
end | |
class ThreeStateBuffer | |
def initialize(bit_width) | |
@tsb = Array.new(bit_width){ThreeStateBuffer1.new} | |
end | |
def d=(v) | |
@tsb.zip(v) do |tsb, o| | |
tsb.d = o | |
end | |
end | |
def g=(v) | |
@tsb.each do |tsb| | |
tsb.g = v | |
end | |
end | |
end | |
class ThreeStateBufferB1 | |
def d=(v) | |
v.output_objects << self | |
@d = v | |
end | |
def g=(v) | |
v.output_objects << self | |
@g = v | |
end | |
def update | |
@bus.o.set(@d.get) if @g and !@g.get | |
end | |
def connect_bus(b) | |
@bus = b | |
end | |
end | |
class ThreeStateBufferB | |
def initialize(bit_width) | |
@tsb = Array.new(bit_width){ThreeStateBufferB1.new} | |
end | |
def d=(v) | |
@tsb.zip(v) do |tsb, o| | |
tsb.d = o | |
end | |
end | |
def g=(v) | |
@tsb.each do |tsb| | |
tsb.g = v | |
end | |
end | |
end | |
# NANDゲート試作 | |
class NAND | |
def initialize | |
@o = OutputPin.new | |
@a = @b = OutputPin.new | |
end | |
def a=(v) | |
v.output_objects << self | |
@a = v | |
end | |
def b=(v) | |
v.output_objects << self | |
@b = v | |
end | |
def o | |
@o | |
end | |
def update | |
if @a.get != nil or @b.get != nil | |
@o.set(!(@a.get and @b.get)) | |
end | |
end | |
def inspect | |
"#{HLHASH[o.get]}" | |
end | |
end | |
# NOTゲート試作 | |
class NOT | |
def initialize | |
@nand = NAND.new | |
end | |
def a=(v) | |
@nand.a = v | |
@nand.b = v | |
end | |
def o | |
@nand.o | |
end | |
def inspect | |
"#{HLHASH[o.get]}" | |
end | |
end | |
class AND | |
def initialize | |
@nand = NAND.new | |
@not = NOT.new | |
@not.a = @nand.o | |
end | |
def a=(v) | |
@nand.a = v | |
end | |
def b=(v) | |
@nand.b = v | |
end | |
def o | |
@not.o | |
end | |
def inspect | |
"#{HLHASH[o.get]}" | |
end | |
end | |
class OR | |
def initialize | |
@nand = NAND.new | |
@not1 = NOT.new | |
@not2 = NOT.new | |
@nand.a = @not1.o | |
@nand.b = @not2.o | |
end | |
def a=(v) | |
@not1.a = v | |
end | |
def b=(v) | |
@not2.a = v | |
end | |
def o | |
@nand.o | |
end | |
def inspect | |
"#{HLHASH[o.get]}" | |
end | |
end | |
class XOR | |
def initialize | |
@and1 = AND.new | |
@and2 = AND.new | |
@not1 = NOT.new | |
@not2 = NOT.new | |
@or = OR.new | |
@and1.a = @not1.o | |
@and2.b = @not2.o | |
@or.a = @and1.o | |
@or.b = @and2.o | |
end | |
def a=(v) | |
@not1.a = v | |
@and2.a = v | |
end | |
def b=(v) | |
@not2.a = v | |
@and1.b = v | |
end | |
def o | |
@or.o | |
end | |
def inspect | |
"#{HLHASH[o.get]}" | |
end | |
end | |
class NAND3 | |
def initialize | |
@nand = NAND.new | |
@and = AND.new | |
@nand.a = @and.o | |
end | |
def a=(v) | |
@nand.b = v | |
end | |
def b=(v) | |
@and.a = v | |
end | |
def c=(v) | |
@and.b = v | |
end | |
def o | |
@nand.o | |
end | |
def inspect | |
"#{HLHASH[o.get]}" | |
end | |
end | |
class HarfAdder | |
def initialize | |
@and = AND.new | |
@xor = XOR.new | |
end | |
def a=(v) | |
@and.a = v | |
@xor.a = v | |
end | |
def b=(v) | |
@and.b = v | |
@xor.b = v | |
end | |
def s | |
@xor.o | |
end | |
def c | |
@and.o | |
end | |
def inspect | |
"#{HLHASH[c.get]}#{HLHASH[s.get]}" | |
end | |
end | |
class FullAdder | |
def initialize | |
@hadr1 = HarfAdder.new | |
@hadr2 = HarfAdder.new | |
@or = OR.new | |
@hadr2.a = @hadr1.s | |
@or.a = @hadr1.c | |
@or.b = @hadr2.c | |
end | |
def a=(v) | |
@hadr1.a = v | |
end | |
def b=(v) | |
@hadr1.b = v | |
end | |
def x=(v) | |
@hadr2.b = v | |
end | |
def s | |
@hadr2.s | |
end | |
def c | |
@or.o | |
end | |
def inspect | |
"#{HLHASH[c.get]}#{HLHASH[s.get]}" | |
end | |
end | |
class RSFF | |
def initialize | |
@not1 = NOT.new | |
@not2 = NOT.new | |
@nand1 = NAND.new | |
@nand2 = NAND.new | |
@nand1.a = @not1.o | |
@nand1.b = @nand2.o | |
@nand2.a = @not2.o | |
@nand2.b = @nand1.o | |
end | |
def s=(v) | |
@not1.a = v | |
end | |
def r=(v) | |
@not2.a = v | |
end | |
def q | |
@nand1.o | |
end | |
def qb | |
@nand2.o | |
end | |
def inspect | |
"q=#{HLHASH[q.get]}, qb=#{HLHASH[qb.get]}" | |
end | |
end | |
class DFF1 | |
def initialize | |
@not1 = NOT.new | |
@not2 = NOT.new | |
@nand1 = NAND.new | |
@nand2 = NAND.new | |
@nand3 = NAND.new | |
@nand4 = NAND.new | |
@nand5 = NAND.new | |
@nand6 = NAND.new | |
@nand7 = NAND.new | |
@nand8 = NAND.new | |
@reset1_and = AND.new | |
@reset1_not = NOT.new | |
@reset1_nand = NAND.new | |
@reset1_and.a = @nand2.o | |
@reset1_not.a = @nand1.o | |
@reset1_nand.a = @reset1_not.o | |
@reset2_and = AND.new | |
@reset2_not = NOT.new | |
@reset2_nand = NAND.new | |
@reset2_and.a = @nand6.o | |
@reset2_not.a = @nand5.o | |
@reset2_nand.a = @reset2_not.o | |
@not2.a = @not1.o | |
@nand1.b = @not1.o | |
@nand2.a = @nand1.o | |
@nand2.b = @not1.o | |
@nand3.a = @reset1_nand.o | |
@nand3.b = @nand4.o | |
@nand4.a = @nand3.o | |
@nand4.b = @reset1_and.o | |
@nand5.a = @nand3.o | |
@nand5.b = @not2.o | |
@nand6.a = @nand5.o | |
@nand6.b = @not2.o | |
@nand7.a = @reset2_nand.o | |
@nand7.b = @nand8.o | |
@nand8.a = @nand7.o | |
@nand8.b = @reset2_and.o | |
end | |
def d=(v) | |
@nand1.a = v | |
end | |
def clk=(v) | |
@not1.a = v | |
end | |
def clrb=(v) | |
@reset1_and.b = @reset1_nand.b = v | |
@reset2_and.b = @reset2_nand.b = v | |
end | |
def q | |
@nand7.o | |
end | |
def qb | |
@nand8.o | |
end | |
def inspect | |
"q=#{HLHASH[q.get]}, qb=#{HLHASH[qb.get]}" | |
end | |
end | |
class DFF | |
def initialize(bit_width) | |
@dff = Array.new(bit_width){DFF1.new} | |
end | |
def d=(v) | |
@dff.zip(v) do |dff, o| | |
dff.d = o | |
end | |
end | |
def clk=(v) | |
@dff.each do |dff| | |
dff.clk = v | |
end | |
end | |
def clrb=(v) | |
@dff.each do |dff| | |
dff.clrb = v | |
end | |
end | |
def q | |
@dff.map{|dff|dff.q} | |
end | |
def qb | |
@dff.map{|dff|dff.qb} | |
end | |
end | |
class JKFF | |
def initialize | |
@nand1 = NAND.new | |
@nand2 = NAND.new | |
@nand3 = NAND.new | |
@nand4 = NAND3.new | |
@nand5 = NAND3.new | |
@nand6 = NAND.new | |
@nand7 = NAND.new | |
@nand8 = NAND.new | |
@reset_and = AND.new | |
@reset_not = NOT.new | |
@reset_nand = NAND.new | |
@reset_and.a = @nand5.o | |
@reset_not.a = @nand4.o | |
@reset_nand.a = @reset_not.o | |
@nand1.a = @nand8.o | |
@nand2.b = @nand7.o | |
@nand3.a = @nand1.o | |
@nand3.b = @nand4.o | |
@nand4.a = @nand3.o | |
@nand4.c = @nand5.o | |
@nand5.a = @nand4.o | |
@nand5.c = @nand6.o | |
@nand6.a = @nand5.o | |
@nand6.b = @nand2.o | |
@nand7.a = @reset_nand.o # @nand.o | |
@nand7.b = @nand8.o | |
@nand8.a = @nand7.o | |
@nand8.b = @reset_and.o #@nand5.o | |
end | |
def j=(v) | |
@nand1.b = v | |
end | |
def k=(v) | |
@nand2.a = v | |
end | |
def clk=(v) | |
@nand4.b = v | |
@nand5.b = v | |
end | |
def clrb=(v) | |
@reset_and.b = @reset_nand.b = v | |
end | |
def q | |
@nand7.o | |
end | |
def qb | |
@nand8.o | |
end | |
def inspect | |
"#{HLHASH[q.get]}#{HLHASH[qb.get]}" | |
end | |
end | |
class TFF | |
def initialize | |
@jkff = JKFF.new | |
@jkff.j = @jkff.k = OutputPin.new(H) | |
end | |
def t=(v) | |
@jkff.clk = v | |
end | |
def clrb=(v) | |
@jkff.clrb = v | |
end | |
def q | |
@jkff.q | |
end | |
def qb | |
@jkff.qb | |
end | |
def inspect | |
"#{HLHASH[q.get]}#{HLHASH[qb.get]}" | |
end | |
end | |
class Counter4 | |
attr_accessor :dff3 | |
def initialize | |
@dff3 = DFF1.new | |
@dff2 = DFF1.new | |
@dff1 = DFF1.new | |
@dff0 = DFF1.new | |
@dff3.d = @dff3.qb | |
@dff2.d = @dff2.qb | |
@dff1.d = @dff1.qb | |
@dff0.d = @dff0.qb | |
@dff3.clk = @dff2.qb | |
@dff2.clk = @dff1.qb | |
@dff1.clk = @dff0.qb | |
end | |
def clk=(v) | |
@dff0.clk = v | |
end | |
def clrb=(v) | |
@dff3.clrb = v | |
@dff2.clrb = v | |
@dff1.clrb = v | |
@dff0.clrb = v | |
end | |
def o | |
[ | |
@dff3.q, | |
@dff2.q, | |
@dff1.q, | |
@dff0.q, | |
] | |
end | |
def inspect | |
"#{HLHASH[@dff3.q.get]}"+ | |
"#{HLHASH[@dff2.q.get]}"+ | |
"#{HLHASH[@dff1.q.get]}"+ | |
"#{HLHASH[@dff0.q.get]}" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment