概要
paiza.ioでelixirやってみた。
FPGAの高位合成書いてみた。
高位合成て何
FPGAを記述する、HDL言語を生成するコンパイラ
下のコードから下の下のコードを生成する。
make 4
in 0 1
out 2 3
xor 0 1 2
or 0 1 3
module x(input a0, input a1, output a2, output a3);
assign a2 = a0 ^ a1;
assign a3 = a0 | a1;
endmodule
module testbench;
reg a0, a1;
x u(.a0(a0), .a1(a1), .a2(a2), .a3(a3));
initial
begin
$display("a0 a1 a2 a3");
$monitor("%b %b %b %b", a0, a1, a2, a3);
a0 = 0; a1 = 0; #10;
a0 = 0; a1 = 1; #10;
a0 = 1; a1 = 0; #10;
a0 = 1; a1 = 1; #10;
$finish;
end
endmodule
シミュレーション結果
>iverilog x.v
>vvp a.out
a0 a1 a2 a3
0 0 0 0
0 1 1 1
1 0 1 1
1 1 0 1
サンプルコード
defmodule Asm do
def start_link do
Agent.start_link(fn ->
%{in0: "", in1: "", out0: "", u: ""}
end, name: __MODULE__)
end
def make0(a) do
Agent.update(__MODULE__, fn v ->
v
end)
end
def in0(a, b) do
Agent.update(__MODULE__, fn v ->
str = "input a" <> a <> ", input a" <> b
%{v | in0: str}
end)
end
def out0(a, b) do
Agent.update(__MODULE__, fn v ->
str = ", output a" <> a <> ", output a" <> b
%{v | out0: str}
end)
end
def and0(a, b, c) do
Agent.update(__MODULE__, fn v ->
str = " assign a" <> c <> " = a" <> a <> " & a" <> b <> ";\n"
%{v | u: v.u <> str}
end)
end
def nand0(a, b, c) do
Agent.update(__MODULE__, fn v ->
str = " assign a" <> c <> " = ~(a" <> a <> " & a" <> b <> ");\n"
%{v | u: v.u <> str}
end)
end
def nor0(a, b, c) do
Agent.update(__MODULE__, fn v ->
str = " assign a" <> c <> " = ~(a" <> a <> " | a" <> b <> ");\n"
%{v | u: v.u <> str}
end)
end
def xor0(a, b, c) do
Agent.update(__MODULE__, fn v ->
str = " assign a" <> c <> " = a" <> a <> " ^ a" <> b <> ";\n"
%{v | u: v.u <> str}
end)
end
def or0(a, b, c) do
Agent.update(__MODULE__, fn v ->
str = " assign a" <> c <> " = a" <> a <> " | a" <> b <> ";\n"
%{v | u: v.u <> str}
end)
end
def print() do
Agent.get(__MODULE__, fn v ->
IO.puts "module x(" <> v.in0 <> v.out0 <> ");\n" <>
v.u <>
"endmodule\n\n" <>
"module testbench;\n" <>
" reg a0, a1;\n" <>
" x u(.a0(a0), .a1(a1), .a2(a2), .a3(a3));\n" <>
" initial\n" <>
" begin\n" <>
" $display(\"a0 a1 a2 a3\");\n" <>
" $monitor(\"%b %b %b %b\", a0, a1, a2, a3);\n"<>
" a0 = 0; a1 = 0; #10;\n" <>
" a0 = 0; a1 = 1; #10;\n" <>
" a0 = 1; a1 = 0; #10;\n" <>
" a0 = 1; a1 = 1; #10;\n" <>
" $finish;\n" <>
" end\n" <>
"endmodule"
end)
end
end
defmodule Main do
def run(str) do
Enum.map(String.split(str, "\n"), fn l ->
s = String.split(l, " ")
cond do
Enum.at(s, 0) == "make" ->
Asm.make0(Enum.at(s, 1))
Enum.at(s, 0) == "in" ->
Asm.in0(Enum.at(s, 1), Enum.at(s, 2))
Enum.at(s, 0) == "out" ->
Asm.out0(Enum.at(s, 1), Enum.at(s, 2))
Enum.at(s, 0) == "and" ->
Asm.and0(Enum.at(s, 1), Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 0) == "nand" ->
Asm.nand0(Enum.at(s, 1), Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 0) == "nor" ->
Asm.nor0(Enum.at(s, 1), Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 0) == "xor" ->
Asm.xor0(Enum.at(s, 1), Enum.at(s, 2), Enum.at(s, 3))
Enum.at(s, 0) == "or" ->
Asm.or0(Enum.at(s, 1), Enum.at(s, 2), Enum.at(s, 3))
true ->
IO.puts ""
end
end)
Asm.print
end
end
Asm.start_link
Main.run("""
make 4
in 0 1
out 2 3
xor 0 1 2
or 0 1 3
""")
成果物
以上。