Skip to content

Instantly share code, notes, and snippets.

@mirichi
Created June 12, 2015 14:28
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/f8c905444f69076db1ee to your computer and use it in GitHub Desktop.
Save mirichi/f8c905444f69076db1ee to your computer and use it in GitHub Desktop.
mov命令でdeadbeefする回路最新
require './hsim'
# 単純なバッファ
class Buffer1
def initialize
@not1 = NOT.new
@not2 = NOT.new
@not1.a = @not2.o
end
def d=(v)
@not2.a = v
end
def o
@not1.o
end
end
# 単純なバッファの塊
class Buffer
def initialize(bit_width)
@buf = Array.new(bit_width){Buffer1.new}
end
def d=(v)
@buf.zip(v) do |buf, o|
buf.d = o
end
end
def o
@buf.map{|b|b.o}
end
end
# 1bitデータ2つを1bitで選択するマルチプレクサ(スリーステートバッファ版)
class Mux1_1
def initialize
@tsb0 = ThreeStateBufferB1.new
@tsb1 = ThreeStateBuffer1.new
@bus = Bus1.new
@bus.add(@tsb0)
@bus.add(@tsb1)
end
def s=(v)
@tsb0.g = @tsb1.g = v
end
def d0=(v)
@tsb0.d = v
end
def d1=(v)
@tsb1.d = v
end
def o
@bus.o
end
def inspect
"#{HLHASH[@bus.o.get]}"
end
end
# n bitデータ2つを1bitで選択するマルチプレクサ
class Mux1_n
def initialize(bit_width)
@mux = Array.new(bit_width){Mux1_1.new}
end
def s=(v)
@mux.each do |m|
m.s = v
end
end
def d=(v)
@mux.zip(*v) do |m, d0, d1|
m.d0 = d0
m.d1 = d1
end
end
def o
@mux.map{|m|m.o}
end
end
# n bitデータをn bitで選択するマルチプレクサ
class Mux
def initialize(select_bit_width, data_bit_width)
# 作成
@mux = Array.new(select_bit_width){|i| Array.new(2**i){Mux1_n.new(data_bit_width)}}
@buf = Buffer.new(select_bit_width)
# 選択線接続
@mux.zip(@buf.o).each do |ary, b|
ary.each do |m|
m.s = b
end
end
# データ線接続
if select_bit_width > 1
(1...select_bit_width).each do |i|
@mux[i-1].each.with_index do |m, j|
m.d = [@mux[i][j * 2].o, @mux[i][j * 2 + 1].o]
end
end
end
end
def s=(v)
@buf.d = v
end
def d=(v)
@mux.last.each.with_index do |m, i|
m.d = [v[i * 2], v[i * 2 + 1]]
end
end
def o
@mux[0][0].o
end
end
# ROM
class ROM
def initialize(select_bit_width, data_bit_width)
@mux = Mux.new(select_bit_width, data_bit_width)
@tsb = Array.new(data_bit_width){ThreeStateBuffer1.new}
@not = NOT.new
@tsb.each.with_index do |tsb, i|
tsb.d = @mux.o[i]
tsb.g = @not.o
end
end
# アドレス線
def a=(v)
@mux.s = v
end
# チップセレクト
def csb=(v)
@not.a = v
end
# 保持データの接続
def d=(v)
@mux.d = v
end
# 出力(スリーステートバッファ)
def o
@tsb
end
end
# n bitの入力から2**n bitのどれかを選択してHにするセレクタ
class Selector
def initialize(bit_width)
@buf = Buffer.new(bit_width)
tmp = NOT.new
tmp.a = @buf.o[0]
@o = [@buf.o[0], tmp.o]
if bit_width > 1
(bit_width-1).times do |i|
tmp = NOT.new
tmp.a = @buf.o[i+1]
bary = [@buf.o[i+1]]*(@o.size) + [tmp.o]*(@o.size)
@o = @o * 2
@o = @o.zip(bary).map do |o, b|
a = AND.new
a.a = o
a.b = b
a.o
end
end
end
end
def s=(v)
@buf.d = v.reverse
end
def o
@o
end
end
# レジスタ
class Register
def initialize(bit_width)
@dff = DFF.new(bit_width)
@mux = Mux1_n.new(bit_width)
@dff.d = @mux.o
end
def clk=(v)
@dff.clk = v
end
def d=(v)
@mux.d = [self.o, v]
end
# writeが1
def rw=(v)
@mux.s = v
end
def clrb=(v)
@dff.clrb = v
end
def o
@dff.q
end
end
_vcc = Line.new
_gnd = Line.new
vcc = _vcc.o
gnd = _gnd.o
# ROM
rom = ROM.new(3, 8) # アドレス線3本、データ線8本
rom.d = [
[gnd, gnd, vcc, vcc, gnd, vcc, gnd, gnd], # mov a, 0xd
[gnd, gnd, vcc, vcc, vcc, gnd, gnd, vcc], # mov b, 0xe
[gnd, gnd, vcc, gnd, vcc, gnd, vcc, gnd], # mov c, 0xa
[gnd, gnd, vcc, vcc, gnd, vcc, vcc, vcc], # mov d, 0xd
[gnd, gnd, vcc, gnd, vcc, vcc, gnd, gnd], # mov a, 0xb
[gnd, gnd, vcc, vcc, vcc, gnd, gnd, vcc], # mov b, 0xe
[gnd, gnd, vcc, vcc, vcc, gnd, vcc, gnd], # mov c, 0xe
[gnd, gnd, vcc, vcc, vcc, vcc, vcc, vcc] # mov d, 0xf
]
# データバス
bus = Bus.new(8)
# クロックとクリアの入力線
clk = Line.new
clrb = Line.new
# 4bitカウンタ
c4 = Counter4.new
c4.clk = clk.o
c4.clrb = clrb.o
# ROMにカウンタの値を接続
rom.a = [c4.o[1], c4.o[2], c4.o[3]]
rom.csb = c4.o[0]
# ROMの出力はThreeStateBufferなのでBusオブジェクトにaddする
bus.add rom.o
# 4bitレジスタabcd作成
rega = Register.new(4)
regb = Register.new(4)
regc = Register.new(4)
regd = Register.new(4)
rega.clk = regb.clk = regc.clk = regd.clk = clk.o
rega.clrb = regb.clrb = regc.clrb = regd.clrb = clrb.o
# レジスタに書き込みする値はROM内の命令のbit5〜bit2
# 配列の添え字とbit番号が食い違うのが今の悩み
rega.d = regb.d = regc.d = regd.d = [bus.o[2], bus.o[3], bus.o[4], bus.o[5]]
# 2bitセレクタ
sel = Selector.new(2)
# セレクタの入力はROM内の命令のbit1〜bit0
sel.s = [bus.o[6], bus.o[7]]
# セレクタの出力はレジスタのrwに繋ぐ
rega.rw = sel.o[3]
regb.rw = sel.o[2]
regc.rw = sel.o[1]
regd.rw = sel.o[0]
_vcc.d = H
_gnd.d = L
# 簡易ロジックアナライザ
require 'dxruby'
module LogicAnalyzer
@@probes = []
def self.probes
@@probes
end
class Probe < Struct.new(:name, :outpin)
end
def self.analyze(&b)
f = Fiber.new(&b)
buf = []
# 実行
while f.resume(:la) != :la
tmp = []
@@probes.each do |pr|
tmp.push(pr.outpin.get)
end
buf.push(tmp)
end
image = Image.new(640, 480)
size = 480 / @@probes.size
font = Font.new(size)
x = @@probes.map{|v|font.get_width(v.name)}.max + 15
# 画像作成
@@probes.each.with_index do |pr, i|
image.draw_font(10, i * size, pr.name, font)
tmp = false
buf.each.with_index do |b, j|
if tmp != b[i]
image.line(j * 10 + x, i * size + 8, j * 10 + x, i * size + size - 1, C_WHITE)
end
image.line(j * 10 + x, i * size + (b[i] ? 8 : size - 1), j * 10 + x + 10, i * size + (b[i] ? 8 : size - 1), C_WHITE)
tmp = b[i]
end
end
Window.loop do
Window.draw(0, 0, image)
break if Input.key_push?(K_ESCAPE)
end
end
end
# プローブ接続
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("clk", clk.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b0", bus.o[7])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b1", bus.o[6])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b2", bus.o[5])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b3", bus.o[4])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b4", bus.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b5", bus.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b0", rega.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b1", rega.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b2", rega.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b3", rega.o[0])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b0", regb.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b1", regb.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b2", regb.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b3", regb.o[0])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b0", regc.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b1", regc.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b2", regc.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b3", regc.o[0])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b0", regd.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b1", regd.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b2", regd.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b3", regd.o[0])
# アナライズ
LogicAnalyzer.analyze do
clk.d = L
clrb.d = H
clrb.d = L
clrb.d = H
Fiber.yield
9.times do
clk.d = L
Fiber.yield
clk.d = H
Fiber.yield
end
:la
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment