概要
paiza.ioでelixirやってみた。
FPGAの高位合成書いてみた。
俺言語書いてみた。
高位合成て何
FPGAを記述する、HDL言語を生成するコンパイラ
下のコードから下の下のコードを生成する。
10 a=1
20 b=1
30 ?=a*b
60 a=a+1
70 #=a<10*30
90 b=b+1
100 a=1
110 #=b<10*30
120 #=120
module ore(input clk, input rst, output reg [7:0] out);
reg [7:0] a;
reg [7:0] b;
reg [7:0] pc;
always @(posedge clk)
begin
if (!rst)
begin
a <= 0;
b <= 0;
pc <= 10;
end
else
begin
case(pc)
10:
begin
a <= 1;
pc <= 20;
end
20:
begin
b <= 1;
pc <= 30;
end
30:
begin
out <= a*b;
pc <= 60;
end
60:
begin
a <= a+1;
pc <= 70;
end
70:
begin
if (a<10)
pc <= 30;
else
pc <= 90;
end
90:
begin
b <= b+1;
pc <= 100;
end
100:
begin
a <= 1;
pc <= 110;
end
110:
begin
if (b<10)
pc <= 30;
else
pc <= 120;
end
120:
begin
pc <= 120;
end
endcase
end
end
endmodule
module test;
reg clk,
rst;
wire [7:0] out;
ore u(.clk(clk), .rst(rst), .out(out));
initial
begin
clk = 0;
rst = 1;
$monitor("%d", out);
#2
rst = 0;
#2
rst = 1;
#2500
$finish;
end
always
#1
clk = ~clk;
endmodule
シミュレーション結果
>iverilog kuku.v
>vvp a.out
x
1
2
3
4
5
6
7
8
9
2
4
6
8
10
12
14
16
18
3
6
9
12
15
18
21
24
27
4
8
12
16
20
24
28
32
36
5
10
15
20
25
30
35
40
45
6
12
18
24
30
36
42
48
54
7
14
21
28
35
42
49
56
63
8
16
24
32
40
48
56
64
72
9
18
27
36
45
54
63
72
81
サンプルコード
defmodule Asm do
def start_link do
Agent.start_link(fn ->
%{u: ""}
end, name: __MODULE__)
end
def print(a, b) do
Agent.update(__MODULE__, fn v ->
str = " pc <= " <> a <>";\n end\n " <> a <> ":\n begin\n out <= " <> b <> ";\n"
%{v | u: v.u <> str}
end)
end
def jmp(a, b) do
Agent.update(__MODULE__, fn v ->
if String.match?(b, ~r/\*/) do
s = String.split(b, "*")
str = " pc <= " <> a <>";\n end\n " <> a <> ":\n begin\n if (" <> Enum.at(s, 0) <> ")\n pc <= " <> Enum.at(s, 1) <> ";\n else\n"
%{v | u: v.u <> str}
else
str = " pc <= " <> a <>";\n end\n " <> a <> ":\n begin\n pc <= " <> b <> ";\n end\n"
%{v | u: v.u <> str}
end
end)
end
def a(a, b) do
Agent.update(__MODULE__, fn v ->
if a == "10" do
str = " " <> a <> ":\n begin\n a <= " <> b <> ";\n"
%{v | u: v.u <> str}
else
str = " pc <= " <> a <>";\n end\n " <> a <> ":\n begin\n a <= " <> b <> ";\n"
%{v | u: v.u <> str}
end
end)
end
def b(a, b) do
Agent.update(__MODULE__, fn v ->
if a == "10" do
str = " " <> a <> ":\n begin\n b <= " <> b <> ";\n"
%{v | u: v.u <> str}
else
str = " pc <= " <> a <>";\n end\n " <> a <> ":\n begin\n b <= " <> b <> ";\n"
%{v | u: v.u <> str}
end
end)
end
def echo() do
Agent.get(__MODULE__, fn v ->
IO.puts "module ore(input clk, input rst, output reg [7:0] out);\n" <>
" reg [7:0] a;\n" <>
" reg [7:0] b;\n" <>
" reg [7:0] pc;\n" <>
" always @(posedge clk)\n" <>
" begin\n" <>
" if (!rst)\n" <>
" begin\n" <>
" a <= 0;\n" <>
" b <= 0;\n" <>
" pc <= 10;\n" <>
" end\n" <>
" else\n" <>
" begin\n" <>
" case(pc)\n" <>
v.u <>
" endcase\n" <>
" end\n" <>
" end\n" <>
"endmodule\n\n" <>
"module test;\n" <>
" reg clk,\n" <>
" rst;\n" <>
" wire [7:0] out;\n" <>
" ore u(.clk(clk), .rst(rst), .out(out));\n" <>
" initial\n" <>
" begin\n" <>
" clk = 0;\n" <>
" rst = 1;\n" <>
" $monitor(\"%d\", out);\n" <>
" #2\n" <>
" rst = 0;\n" <>
" #2\n" <>
" rst = 1;\n" <>
" #2500\n" <>
" $finish;\n" <>
" end\n" <>
" always\n" <>
" #1\n" <>
" clk = ~clk;\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.jmp(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) == "b" ->
Asm.b(Enum.at(s, 0), Enum.at(s, 2))
true ->
IO.puts ""
end
end)
Asm.echo
end
end
Asm.start_link
Main.run("""
10 a=1
20 b=1
30 ?=a*b
60 a=a+1
70 #=a<10*30
90 b=b+1
100 a=1
110 #=b<10*30
120 #=120
""")
成果物
以上。