概要
windowsでiverilogやってみた。
自作cpu、見つけたので、調査してみた。
練習問題やってみた。
練習問題
elixirでzktcのアセンブラが動くインタープリタを書け。
1から9まで数えよ。
サンプルコード
defmodule Va do
use Agent
def start_link() do
Agent.start_link(fn ->
0
end, name: __MODULE__)
end
def get() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def set(x) do
Agent.update(__MODULE__, fn v ->
x
end)
end
end
defmodule Src do
use Agent
def start_link() do
Agent.start_link(fn ->
""
end, name: __MODULE__)
end
def set(x) do
Agent.update(__MODULE__, fn v ->
x
end)
end
def get() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def getn(n) do
Agent.get(__MODULE__, fn v ->
Enum.at(String.split(v, "\n", trim: true), n - 1)
end)
end
def getl("end") do
0
end
def getl(a) do
Agent.get(__MODULE__, fn v ->
Enum.reduce(String.split(v, "\n", trim: true), 1, fn l, n ->
if String.starts_with?(l, a) do
Va.set(n)
end
n = n + 1
end)
Va.get
end)
end
end
defmodule Sim do
def start_link do
Agent.start_link(fn ->
[x1: 0, x2: 0, x3: 0, x7: 0, pc: 1, stack: [], g: ""]
end, name: __MODULE__)
end
def lil(xd, d) do
Agent.update(__MODULE__, fn v ->
cond do
xd == "x1" ->
v = List.keyreplace(v, :x1, 0, {:x1, String.to_integer(d)})
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
xd == "x2" ->
v = List.keyreplace(v, :x2, 0, {:x2, String.to_integer(d)})
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
xd == "x3" ->
v = List.keyreplace(v, :x3, 0, {:x3, String.to_integer(d)})
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
xd == "x7" ->
IO.write(<<String.to_integer(d)>>)
v = List.keyreplace(v, :x7, 0, {:x7, String.to_integer(d)})
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
end
end)
end
def add(xd, xs) do
Agent.update(__MODULE__, fn v ->
cond do
xd == "x3" && xs == "x1" ->
vd = v[:x3] + v[:x1]
v = List.keyreplace(v, :x3, 0, {:x3, vd})
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
end
end)
end
def mov(xd, xs) do
Agent.update(__MODULE__, fn v ->
cond do
xd == "x7" && xs == "x3" ->
vd = v[:x7]
vs = v[:x3]
vd = vs
v = List.keyreplace(v, :x7, 0, {:x7, vd})
IO.write(<<vd>>)
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
end
end)
end
def jal(xd, l) do
Agent.update(__MODULE__, fn v ->
pc = Src.getl(l)
List.keyreplace(v, :pc, 0, {:pc, pc})
end)
end
def addi(xd, xs, i) do
Agent.update(__MODULE__, fn v ->
cond do
xd == "x1" && xs == "x1" ->
vs = v[:x1]
vd = vs + String.to_integer(i)
v = List.keyreplace(v, :x1, 0, {:x1, vd})
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
end
end)
end
def blt(xd, xs, l) do
Agent.update(__MODULE__, fn v ->
cond do
xd == "x1" && xs == "x2" ->
vd = v[:x1]
vs = v[:x2]
if (vd > vs) do
pc = Src.getl(l)
List.keyreplace(v, :pc, 0, {:pc, pc})
else
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
end
end
end)
end
def pc() do
Agent.get(__MODULE__, fn v ->
v[:pc]
end)
end
def test() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def up() do
Agent.update(__MODULE__, fn v ->
pc = v[:pc] + 1
List.keyreplace(v, :pc, 0, {:pc, pc})
end)
end
def ret() do
Agent.update(__MODULE__, fn v ->
pc = 0
List.keyreplace(v, :pc, 0, {:pc, pc})
end)
end
end
defmodule Main do
def run(0) do
IO.puts("ok")
end
def run(pc) do
m = Src.getn(pc)
#IO.puts(m)
s = String.split(m, " ")
#IO.inspect(s)
cond do
Enum.at(s, 1) == "lil" ->
Sim.lil(Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 1) == "addi" ->
Sim.addi(Enum.at(s, 2), Enum.at(s, 3), Enum.at(s, 4))
Enum.at(s, 1) == "add" ->
Sim.add(Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 1) == "mov" ->
Sim.mov(Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 1) == "blt" ->
Sim.blt(Enum.at(s, 2), Enum.at(s, 3), Enum.at(s, 4))
Enum.at(s, 1) == "jal" ->
Sim.jal(Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 1) == "ret" ->
Sim.ret()
true ->
Sim.up
#IO.puts(Enum.at(s, 1))
end
#IO.inspect Sim.test
run(Sim.pc)
end
def start(str) do
Src.set(str)
run(1)
end
end
Va.start_link
Sim.start_link
Src.start_link
str = """
lil x1 0
lil x2 8
loop:
addi x1 x1 1
lil x3 48
add x3 x1
mov x7 x3
lil x7 10
blt x1 x2 bye
jal x0 loop
bye:
ret
"""
Main.start(str)
投入したソース
lil x1 0
lil x2 8
loop:
addi x1 x1 1
lil x3 48
add x3 x1
mov x7 x3
lil x7 10
blt x1 x2 bye
jal x0 loop
bye:
ret
実行結果
1
2
3
4
5
6
7
8
9
ok
成果物
以上。