paiza.ioでelixir その116

# 概要
paiza.ioでelixirやってみた。
FPGAの高位合成書いてみた。
俺言語で書いたfizzbuzzをコンパイルしてみた。

# 高位合成て何
FPGAを記述する、HDL言語を生成するコンパイラ
下のコードから下の下のコードを生成する。

```
10 a=0
20 a=a+1
30 #=a>100*180
40 b=a%15
50 #=b@0*120
60 b=a%5
70 #=b@0*140
80 b=a%3
90 #=b@0*160
100 ?=a
110 #=20
120 ?="fizzbuzz"
130 #=20
140 ?="buzz"
150 #=20
160 ?="fizz"
170 #=20
180 #=180
```

```
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 <= 0;
                pc <= 20;
            end
            20:
            begin
                a <= a+1;
                pc <= 30;
            end
            30:
            begin
                if (a>100)
                    pc <= 180;
                else
                    pc <= 40;
            end
            40:
            begin
                b <= a%15;
                pc <= 50;
            end
            50:
            begin
                if (b==0)
                    pc <= 120;
                else
                    pc <= 60;
            end
            60:
            begin
                b <= a%5;
                pc <= 70;
            end
            70:
            begin
                if (b==0)
                    pc <= 140;
                else
                    pc <= 80;
            end
            80:
            begin
                b <= a%3;
                pc <= 90;
            end
            90:
            begin
                if (b==0)
                    pc <= 160;
                else
                    pc <= 100;
            end
            100:
            begin
                out <= a / 10 + 48;
                pc <= 101;
            end
            101:
            begin
                out <= a % 10 + 48;
                pc <= 102;
            end
            102:
            begin
                out <= 32;
                pc <= 110;
            end
            110:
            begin
                pc <= 20;
            end
            120:
            begin
                out <= "f";
                pc <= 121;
            end
            121:
            begin
                out <= "i";
                pc <= 122;
            end
            122:
            begin
                out <= "z";
                pc <= 123;
            end
            123:
            begin
                out <= "z";
                pc <= 124;
            end
            124:
            begin
                out <= "b";
                pc <= 125;
            end
            125:
            begin
                out <= "u";
                pc <= 126;
            end
            126:
            begin
                out <= "z";
                pc <= 127;
            end
            127:
            begin
                out <= "z";
                pc <= 128;
            end
            128:
            begin
                out <= " ";
                pc <= 130;
            end
            130:
            begin
                pc <= 20;
            end
            140:
            begin
                out <= "b";
                pc <= 141;
            end
            141:
            begin
                out <= "u";
                pc <= 142;
            end
            142:
            begin
                out <= "z";
                pc <= 143;
            end
            143:
            begin
                out <= "z";
                pc <= 144;
            end
            144:
            begin
                out <= " ";
                pc <= 150;
            end
            150:
            begin
                pc <= 20;
            end
            160:
            begin
                out <= "f";
                pc <= 161;
            end
            161:
            begin
                out <= "i";
                pc <= 162;
            end
            162:
            begin
                out <= "z";
                pc <= 163;
            end
            163:
            begin
                out <= "z";
                pc <= 164;
            end
            164:
            begin
                out <= " ";
                pc <= 170;
            end
            170:
            begin
                pc <= 20;
            end
            180:
            begin
                pc <= 180;
            end
            endcase
        end
    end
    initial
    begin
        $monitor(" %d  %s", pc, out);
    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;
    #2
        rst = 0;
    #2
        rst = 1;
    #2700
        $finish;
    end
    always
    #1
        clk = ~clk;
endmodule



```

# シミュレーション結果

```
>vvp a.out
   x
  10
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  0
 102  1
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  0
 102  2
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  0
 102  4
 110
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  0
 102  7
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  0
 102  8
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  1
 102  1
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  1
 102  3
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  1
 102  4
 110
  20
  30
  40
  50
 120
 121  f
 122  i
 123  z
 124  z
 125  b
 126  u
 127  z
 128  z
 130
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  1
 102  6
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  1
 102  7
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  1
 102  9
 110
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  2
 102  2
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  2
 102  3
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  2
 102  6
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  2
 102  8
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  2
 102  9
 110
  20
  30
  40
  50
 120
 121  f
 122  i
 123  z
 124  z
 125  b
 126  u
 127  z
 128  z
 130
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  3
 102  1
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  3
 102  2
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  3
 102  4
 110
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  3
 102  7
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  3
 102  8
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  4
 102  1
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  4
 102  3
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  4
 102  4
 110
  20
  30
  40
  50
 120
 121  f
 122  i
 123  z
 124  z
 125  b
 126  u
 127  z
 128  z
 130
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  4
 102  6
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  4
 102  7
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  4
 102  9
 110
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  5
 102  2
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  5
 102  3
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  5
 102  6
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  5
 102  8
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  5
 102  9
 110
  20
  30
  40
  50
 120
 121  f
 122  i
 123  z
 124  z
 125  b
 126  u
 127  z
 128  z
 130
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  6
 102  1
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  6
 102  2
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  6
 102  4
 110
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  6
 102  7
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  6
 102  8
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  7
 102  1
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  7
 102  3
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  7
 102  4
 110
  20
  30
  40
  50
 120
 121  f
 122  i
 123  z
 124  z
 125  b
 126  u
 127  z
 128  z
 130
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  7
 102  6
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  7
 102  7
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  7
 102  9
 110
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  8
 102  2
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  8
 102  3
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  8
 102  6
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  8
 102  8
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  8
 102  9
 110
  20
  30
  40
  50
 120
 121  f
 122  i
 123  z
 124  z
 125  b
 126  u
 127  z
 128  z
 130
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  9
 102  1
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  9
 102  2
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  9
 102  4
 110
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  9
 102  7
 110
  20
  30
  40
  50
  60
  70
  80
  90
 100
 101  9
 102  8
 110
  20
  30
  40
  50
  60
  70
  80
  90
 160
 161  f
 162  i
 163  z
 164  z
 170
  20
  30
  40
  50
  60
  70
 140
 141  b
 142  u
 143  z
 144  z
 150
  20
  30
 180


```

# サンプルコード

```

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 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 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, 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" <>
	        "    initial\n" <>
	        "    begin\n" <>
		    "        $monitor(\" %d  %s\", pc, out);\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" <>	
		    "    #2\n" <>
			"        rst = 0;\n" <>
		    "    #2\n" <>
		    "        rst = 1;\n" <>
		    "    #2700\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.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) == "b" ->
				Asm.b(Enum.at(s, 0), Enum.at(s, 2))
			true ->
				IO.puts ""
			end
	    end)
	    Asm.make
	end
end

Asm.start_link

Main.run("""
10 a=0
20 a=a+1
30 #=a>100*180
40 b=a%15
50 #=b@0*120
60 b=a%5
70 #=b@0*140
80 b=a%3
90 #=b@0*160
100 ?=a
110 #=20
120 ?="fizzbuzz"
130 #=20
140 ?="buzz"
150 #=20
160 ?="fizz"
170 #=20
180 #=180
""")




```

# 成果物

https://paiza.io/projects/cL7ueolsFCIZlsrQBz36Zg?language=elixir


以上。