-
-
Save mirichi/233fc39c2f4e971aa86b to your computer and use it in GitHub Desktop.
deadbeefを順にA~Dレジスタに書き込む命令をROMに書いたコード
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
require './hsim' | |
# 1bitデータ2つを1bitで選択するマルチプレクサ(スリーステートバッファ版) | |
class Mux1_1 | |
def initialize | |
@tsb1 = ThreeStateBuffer.new | |
@tsb2 = ThreeStateBuffer.new | |
@bus = Bus.new | |
@not = NOT.new | |
@bus.add(@tsb1) | |
@bus.add(@tsb2) | |
@tsb1.g = @not.o | |
end | |
def s=(v) | |
@not.a = @tsb2.g = v | |
end | |
def d0=(v) | |
@tsb1.d = v | |
end | |
def d1=(v) | |
@tsb2.d = v | |
end | |
def o | |
@bus.o | |
end | |
def inspect | |
"#{HLHASH[@bus.o.get]}" | |
end | |
end | |
# 4bitデータ2つを1bitで選択するマルチプレクサ | |
class Mux1_4 | |
def initialize | |
@mux3 = Mux1_1.new | |
@mux2 = Mux1_1.new | |
@mux1 = Mux1_1.new | |
@mux0 = Mux1_1.new | |
end | |
def s=(v) | |
@mux3.s = v | |
@mux2.s = v | |
@mux1.s = v | |
@mux0.s = v | |
end | |
def d0=(v) | |
@mux3.d0 = v[0] | |
@mux2.d0 = v[1] | |
@mux1.d0 = v[2] | |
@mux0.d0 = v[3] | |
end | |
def d1=(v) | |
@mux3.d1 = v[0] | |
@mux2.d1 = v[1] | |
@mux1.d1 = v[2] | |
@mux0.d1 = v[3] | |
end | |
def o | |
[ | |
@mux3.o, | |
@mux2.o, | |
@mux1.o, | |
@mux0.o | |
] | |
end | |
def inspect | |
"#{HLHASH[@mux3.o.get]}"+ | |
"#{HLHASH[@mux2.o.get]}"+ | |
"#{HLHASH[@mux1.o.get]}"+ | |
"#{HLHASH[@mux0.o.get]}" | |
end | |
end | |
# 8bitデータ2つを1bitで選択するマルチプレクサ | |
class Mux1_8 | |
def initialize | |
@mux7 = Mux1_1.new | |
@mux6 = Mux1_1.new | |
@mux5 = Mux1_1.new | |
@mux4 = Mux1_1.new | |
@mux3 = Mux1_1.new | |
@mux2 = Mux1_1.new | |
@mux1 = Mux1_1.new | |
@mux0 = Mux1_1.new | |
end | |
def s=(v) | |
@mux7.s = v | |
@mux6.s = v | |
@mux5.s = v | |
@mux4.s = v | |
@mux3.s = v | |
@mux2.s = v | |
@mux1.s = v | |
@mux0.s = v | |
end | |
def d0=(v) | |
@mux7.d0 = v[0] | |
@mux6.d0 = v[1] | |
@mux5.d0 = v[2] | |
@mux4.d0 = v[3] | |
@mux3.d0 = v[4] | |
@mux2.d0 = v[5] | |
@mux1.d0 = v[6] | |
@mux0.d0 = v[7] | |
end | |
def d1=(v) | |
@mux7.d1 = v[0] | |
@mux6.d1 = v[1] | |
@mux5.d1 = v[2] | |
@mux4.d1 = v[3] | |
@mux3.d1 = v[4] | |
@mux2.d1 = v[5] | |
@mux1.d1 = v[6] | |
@mux0.d1 = v[7] | |
end | |
def o | |
[ | |
@mux7.o, | |
@mux6.o, | |
@mux5.o, | |
@mux4.o, | |
@mux3.o, | |
@mux2.o, | |
@mux1.o, | |
@mux0.o | |
] | |
end | |
def inspect | |
"#{HLHASH[@mux7.o.get]}"+ | |
"#{HLHASH[@mux6.o.get]}"+ | |
"#{HLHASH[@mux5.o.get]}"+ | |
"#{HLHASH[@mux4.o.get]}"+ | |
"#{HLHASH[@mux3.o.get]}"+ | |
"#{HLHASH[@mux2.o.get]}"+ | |
"#{HLHASH[@mux1.o.get]}"+ | |
"#{HLHASH[@mux0.o.get]}" | |
end | |
end | |
# 8bitデータ4つを2bitで選択するマルチプレクサ | |
class Mux2_8 | |
def initialize | |
@mux0 = Mux1_8.new | |
@mux1 = Mux1_8.new | |
@mux2 = Mux1_8.new | |
@mux2.d0 = @mux0.o | |
@mux2.d1 = @mux1.o | |
end | |
def s=(v) | |
@mux0.s = v[1] | |
@mux1.s = v[1] | |
@mux2.s = v[0] | |
end | |
def d0=(v) | |
@mux0.d0 = v | |
end | |
def d1=(v) | |
@mux0.d1 = v | |
end | |
def d2=(v) | |
@mux1.d0 = v | |
end | |
def d3=(v) | |
@mux1.d1 = v | |
end | |
def o | |
@mux2.o | |
end | |
def inspect | |
"#{HLHASH[@mux2.o[0].get]}"+ | |
"#{HLHASH[@mux2.o[1].get]}"+ | |
"#{HLHASH[@mux2.o[2].get]}"+ | |
"#{HLHASH[@mux2.o[3].get]}" | |
end | |
end | |
# 8bit*4の容量を持つROM | |
class ROM32bit | |
def initialize | |
@mux = Mux2_8.new | |
@tsb7 = ThreeStateBuffer.new | |
@tsb6 = ThreeStateBuffer.new | |
@tsb5 = ThreeStateBuffer.new | |
@tsb4 = ThreeStateBuffer.new | |
@tsb3 = ThreeStateBuffer.new | |
@tsb2 = ThreeStateBuffer.new | |
@tsb1 = ThreeStateBuffer.new | |
@tsb0 = ThreeStateBuffer.new | |
@not = NOT.new | |
@tsb7.d = @mux.o[0] | |
@tsb6.d = @mux.o[1] | |
@tsb5.d = @mux.o[2] | |
@tsb4.d = @mux.o[3] | |
@tsb3.d = @mux.o[4] | |
@tsb2.d = @mux.o[5] | |
@tsb1.d = @mux.o[6] | |
@tsb0.d = @mux.o[7] | |
@tsb7.g = @not.o | |
@tsb6.g = @not.o | |
@tsb5.g = @not.o | |
@tsb4.g = @not.o | |
@tsb3.g = @not.o | |
@tsb2.g = @not.o | |
@tsb1.g = @not.o | |
@tsb0.g = @not.o | |
end | |
# アドレス線(2本) | |
def a=(v) | |
@mux.s = [v[0], v[1]] | |
end | |
# チップセレクト | |
def csb=(v) | |
@not.a = v | |
end | |
# 保持データの接続 | |
def d=(v) | |
@mux.d0 = [v[0][0], v[0][1], v[0][2], v[0][3], v[0][4], v[0][5], v[0][6], v[0][7]] | |
@mux.d1 = [v[1][0], v[1][1], v[1][2], v[1][3], v[1][4], v[1][5], v[1][6], v[1][7]] | |
@mux.d2 = [v[2][0], v[2][1], v[2][2], v[2][3], v[2][4], v[2][5], v[2][6], v[2][7]] | |
@mux.d3 = [v[3][0], v[3][1], v[3][2], v[3][3], v[3][4], v[3][5], v[3][6], v[3][7]] | |
end | |
# 出力(スリーステートバッファ) | |
def o | |
[ | |
@tsb7, | |
@tsb6, | |
@tsb5, | |
@tsb4, | |
@tsb3, | |
@tsb2, | |
@tsb1, | |
@tsb0 | |
] | |
end | |
def inspect | |
"#{HLHASH[@tsb7.o.get]}"+ | |
"#{HLHASH[@tsb6.o.get]}"+ | |
"#{HLHASH[@tsb5.o.get]}"+ | |
"#{HLHASH[@tsb4.o.get]}"+ | |
"#{HLHASH[@tsb3.o.get]}"+ | |
"#{HLHASH[@tsb2.o.get]}"+ | |
"#{HLHASH[@tsb1.o.get]}"+ | |
"#{HLHASH[@tsb0.o.get]}" | |
end | |
end | |
# 2bitの入力から4bitのどれかを選択してHにするセレクタ | |
class Selector2 | |
def initialize | |
@and3 = AND.new | |
@and2 = AND.new | |
@and1 = AND.new | |
@and0 = AND.new | |
@not0 = NOT.new | |
@not1 = NOT.new | |
@and2.a = @not0.o | |
@and1.b = @not1.o | |
@and0.a = @not0.o | |
@and0.b = @not1.o | |
end | |
def s=(v) | |
@not0.a = v[1] | |
@not1.a = v[0] | |
@and3.a = v[1] | |
@and3.b = v[0] | |
@and1.a = v[1] | |
@and2.b = v[0] | |
end | |
def o | |
[ | |
@and3.o, | |
@and2.o, | |
@and1.o, | |
@and0.o | |
] | |
end | |
def inspect | |
"#{HLHASH[@and3.o.get]}"+ | |
"#{HLHASH[@and2.o.get]}"+ | |
"#{HLHASH[@and1.o.get]}"+ | |
"#{HLHASH[@and0.o.get]}" | |
end | |
end | |
# 4bitレジスタ | |
class Register4 | |
def initialize | |
@dff3 = DFF.new | |
@dff2 = DFF.new | |
@dff1 = DFF.new | |
@dff0 = DFF.new | |
@mux = Mux1_4.new | |
@mux.d0 = self.o | |
@dff3.d = @mux.o[0] | |
@dff2.d = @mux.o[1] | |
@dff1.d = @mux.o[2] | |
@dff0.d = @mux.o[3] | |
end | |
def clk=(v) | |
@dff3.clk = v | |
@dff2.clk = v | |
@dff1.clk = v | |
@dff0.clk = v | |
end | |
def d=(v) | |
@mux.d1 = v | |
end | |
# writeが1 | |
def rw=(v) | |
@mux.s = 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 | |
vcc = OutputPin.new(H) | |
gnd = OutputPin.new(L) | |
# deadROM | |
dead_rom = ROM32bit.new | |
dead_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 | |
] | |
# beefROM | |
beef_rom = ROM32bit.new | |
beef_rom.d = [ | |
[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 | |
] | |
# データバス | |
bus7 = Bus.new | |
bus6 = Bus.new | |
bus5 = Bus.new | |
bus4 = Bus.new | |
bus3 = Bus.new | |
bus2 = Bus.new | |
bus1 = Bus.new | |
bus0 = Bus.new | |
# チップセレクト用 | |
_not = NOT.new | |
# クロックとクリアの入力線 | |
clk = Line.new | |
clrb = Line.new | |
# 4bitカウンタ | |
c4 = Counter4.new | |
c4.clk = clk.o | |
c4.clrb = clrb.o | |
# ROMにカウンタの値を接続 | |
dead_rom.a = [c4.o[2], c4.o[3]] | |
dead_rom.csb = c4.o[1] | |
beef_rom.a = [c4.o[2], c4.o[3]] | |
beef_rom.csb = _not.o | |
_not.a = c4.o[1] | |
# ROMの出力はThreeStateBufferなのでBusオブジェクトにaddする | |
bus7.add dead_rom.o[0] | |
bus7.add beef_rom.o[0] | |
bus6.add dead_rom.o[1] | |
bus6.add beef_rom.o[1] | |
bus5.add dead_rom.o[2] | |
bus5.add beef_rom.o[2] | |
bus4.add dead_rom.o[3] | |
bus4.add beef_rom.o[3] | |
bus3.add dead_rom.o[4] | |
bus3.add beef_rom.o[4] | |
bus2.add dead_rom.o[5] | |
bus2.add beef_rom.o[5] | |
bus1.add dead_rom.o[6] | |
bus1.add beef_rom.o[6] | |
bus0.add dead_rom.o[7] | |
bus0.add beef_rom.o[7] | |
# 4bitレジスタabcd作成 | |
rega = Register4.new | |
regb = Register4.new | |
regc = Register4.new | |
regd = Register4.new | |
rega.clk = regb.clk = regc.clk = regd.clk = clk.o | |
rega.clrb = regb.clrb = regc.clrb = regd.clrb = clrb.o | |
# レジスタに書き込みする値はROM内の命令のbit5~bit2 | |
rega.d = regb.d = regc.d = regd.d = [bus5.o, bus4.o, bus3.o, bus2.o] | |
# 2bitセレクタ | |
sel = Selector2.new | |
# セレクタの入力はROM内の命令のbit1~bit0 | |
sel.s = [bus1.o, bus0.o] | |
# セレクタの出力はレジスタのrwに繋ぐ | |
rega.rw = sel.o[3] | |
regb.rw = sel.o[2] | |
regc.rw = sel.o[1] | |
regd.rw = sel.o[0] | |
# 簡易ロジックアナライザ | |
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", bus0.o) | |
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b1", bus1.o) | |
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b2", bus2.o) | |
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b3", bus3.o) | |
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b4", bus4.o) | |
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b5", bus5.o) | |
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