概要
paiza.ioでelixirやってみた。
高位合成、やってみた。
練習問題やってみた。
実装編。
練習問題
俺言語で8bitシフトレジスタを実現せよ。
サンプルコード
defmodule Asm do
def start_link do
Agent.start_link(fn ->
%{u: ""}
end, name: __MODULE__)
end
def a(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" a <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def o(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" o <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def p(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" p <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def x(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" x <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def b(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" b <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def c(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" c <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def d(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" d <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def e(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" e <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def f(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" f <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def g(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" g <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def h(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
str = " " <> a <> ":\n" <>
" begin\n" <>
" h <= " <> b <> ";\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
end)
end
def print(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a)
if String.match?(b, ~r/\"/) do
b = String.replace(b, "\"", "")
s = String.split(b, "", trim: true)
l = String.length(b)
str = Enum.reduce(s, ["", c], fn x, y ->
pc = Enum.at(y, 1)
str = Enum.at(y, 0) <>
" #{pc}:\n" <>
" begin\n" <>
" out <= \"#{x}\";\n" <>
" pc <= #{pc + 1};\n" <>
" end\n"
pc = pc + 1
[str, pc]
end)
str = Enum.at(str, 0) <>
" #{c + l}:\n" <>
" begin\n" <>
" out <= \" \";\n" <>
" pc <= #{c + 10};\n" <>
" end\n"
%{v | u: v.u <> str}
else
str = " #{c}:\n" <>
" begin\n" <>
" out <= a / 10 + 48;\n" <>
" pc <= #{c + 1};\n" <>
" end\n" <>
" #{c + 1}:\n" <>
" begin\n" <>
" out <= a % 10 + 48;\n" <>
" pc <= #{c + 2};\n" <>
" end\n" <>
" #{c + 2}:\n" <>
" begin\n" <>
" out <= 32;\n" <>
" pc <= #{c + 10};\n" <>
" end\n"
%{v | u: v.u <> str}
end
end)
end
def loop(a, b) do
Agent.update(__MODULE__, fn v ->
c = String.to_integer(a) + 10
if String.match?(b, ~r/\*/) do
b = String.replace(b, "@", "==")
s = String.split(b, "*")
str = " " <> a <> ":\n" <>
" begin\n" <>
" if (" <> Enum.at(s, 0) <> ")\n" <>
" pc <= " <> Enum.at(s, 1) <> ";\n" <>
" else\n" <>
" pc <= #{c};\n" <>
" end\n"
%{v | u: v.u <> str}
else
str = " " <> a <> ":\n" <>
" begin\n" <>
" pc <= " <> b <> ";\n" <>
" end\n"
%{v | u: v.u <> str}
end
end)
end
def make() do
Agent.get(__MODULE__, fn v ->
IO.puts "module ore(input clk, input rst, input o, input p, input q, output x, output y, output z);\n" <>
" reg [7:0] a;\n" <>
" reg [7:0] b;\n" <>
" reg [7:0] c;\n" <>
" reg [7:0] d;\n" <>
" reg [7:0] e;\n" <>
" reg [7:0] f;\n" <>
" reg [7:0] g;\n" <>
" reg [7:0] h;\n" <>
" reg [7:0] pc;\n" <>
" reg x;\n" <>
" reg y;\n" <>
" reg z;\n" <>
" wire o;\n" <>
" wire p;\n" <>
" wire q;\n" <>
" always @(posedge clk)\n" <>
" begin\n" <>
" if (!rst)\n" <>
" begin\n" <>
" a <= 0;\n" <>
" b <= 0;\n" <>
" c <= 0;\n" <>
" d <= 0;\n" <>
" e <= 0;\n" <>
" f <= 0;\n" <>
" g <= 0;\n" <>
" h <= 0;\n" <>
" pc <= 10;\n" <>
" end\n" <>
" else\n" <>
" begin\n" <>
" case(pc)\n" <>
v.u <>
" endcase\n" <>
" end\n" <>
" end\n" <>
" initial\n" <>
" begin\n" <>
" //$monitor(\" %d %d\", pc, x);\n" <>
" end\n" <>
"endmodule\n\n" <>
"module test;\n" <>
" reg clk,\n" <>
" rst;\n" <>
" wire [7:0] out;\n" <>
" reg o;\n" <>
" reg p;\n" <>
" reg q;\n" <>
" wire x;\n" <>
" wire y;\n" <>
" wire z;\n" <>
" ore u(.clk(clk), .rst(rst), .o(o), .p(p), .q(q), .x(x), .y(y), .z(z));\n" <>
" initial\n" <>
" begin\n" <>
" clk = 0;\n" <>
" rst = 1;\n" <>
" #2\n" <>
" rst = 0;\n" <>
" #2\n" <>
" rst = 1;\n" <>
" #40\n" <>
" o = 0;\n" <>
" p = 0;\n" <>
" #40\n" <>
" o = 1;\n" <>
" p = 1;\n" <>
" #40\n" <>
" o = 0;\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" p = 1;\n" <>
" #40\n" <>
" p = 0;\n" <>
" #40\n" <>
" $finish;\n" <>
" end\n" <>
" always\n" <>
" #1\n" <>
" clk = ~clk;\n" <>
" initial\n" <>
" begin\n" <>
" $display(\" o p x \");\n" <>
" $monitor(\" %d %d %d \", o, p, x);\n" <>
" end\n" <>
"endmodule\n"
end)
end
end
defmodule Main do
def run(str) do
str = String.replace(str, "=", " ")
Enum.map(String.split(str, "\n"), fn l ->
s = String.split(l, " ")
cond do
Enum.at(s, 1) == "?" ->
Asm.print(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "#" ->
Asm.loop(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "a" ->
Asm.a(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "o" ->
Asm.o(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "p" ->
Asm.p(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "x" ->
Asm.x(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "b" ->
Asm.b(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "c" ->
Asm.c(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "d" ->
Asm.d(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "e" ->
Asm.e(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "f" ->
Asm.f(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "g" ->
Asm.g(Enum.at(s, 0), Enum.at(s, 2))
Enum.at(s, 1) == "h" ->
Asm.h(Enum.at(s, 0), Enum.at(s, 2))
true ->
IO.puts l
end
end)
Asm.make
end
end
Asm.start_link
Main.run("""
10 x=0
20 a=o
30 #=p@1*50
40 #=20
50 x=h
60 h=g
70 g=f
80 f=e
90 e=d
100 d=c
110 c=b
120 b=a
130 #=p@0*20
140 #=130
""")
シュミレーション結果
>vvp a.out
o p x
x x x
x x 0
0 0 0
1 1 0
0 0 0
0 1 0
0 0 0
0 1 0
0 0 0
0 1 0
0 0 0
0 1 0
0 0 0
0 1 0
0 0 0
0 1 0
0 0 0
0 1 0
0 1 1
0 0 1
0 1 1
0 1 0
0 0 0
0 1 0
0 0 0
ore1.v:181: $finish called at 884 (1s)
成果物
以上。