Skip to content

Instantly share code, notes, and snippets.

@mirichi
Created June 12, 2015 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mirichi/df54ed39ec1437d5aa9a to your computer and use it in GitHub Desktop.
Save mirichi/df54ed39ec1437d5aa9a to your computer and use it in GitHub Desktop.
ハードウェアシミュレータ
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