paiza.ioでelixir その117

# 概要
paiza.ioでelixirやってみた。
FPGAの高位合成書いてみた。
練習問題やってみた。

# 練習問題
zundokoを書け。

# サンプルコード

```
10 a=0
20 b=234
30 b=b*5
40 b=b+1
50 #=b<120*100
60 ?="zun"
70 a=a+1
80 #=a>3*130
90 #=30
100 ?="doko"
110 a=0
120 #=30
130 ?="doko" 
140 ?="kiyosi!!"
150 #=150
```

# 実行結果

```
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
                b <= 234;
                pc <= 30;
            end
            30:
            begin
                b <= b*5;
                pc <= 40;
            end
            40:
            begin
                b <= b+1;
                pc <= 50;
            end
            50:
            begin
                if (b<120)
                    pc <= 100;
                else
                    pc <= 60;
            end
            60:
            begin
                out <= "z";
                pc <= 61;
            end
            61:
            begin
                out <= "u";
                pc <= 62;
            end
            62:
            begin
                out <= "n";
                pc <= 63;
            end
            63:
            begin
                out <= " ";
                pc <= 70;
            end
            70:
            begin
                a <= a+1;
                pc <= 80;
            end
            80:
            begin
                if (a>3)
                    pc <= 130;
                else
                    pc <= 90;
            end
            90:
            begin
                pc <= 30;
            end
            100:
            begin
                out <= "d";
                pc <= 101;
            end
            101:
            begin
                out <= "o";
                pc <= 102;
            end
            102:
            begin
                out <= "k";
                pc <= 103;
            end
            103:
            begin
                out <= "o";
                pc <= 104;
            end
            104:
            begin
                out <= " ";
                pc <= 110;
            end
            110:
            begin
                a <= 0;
                pc <= 120;
            end
            120:
            begin
                pc <= 30;
            end
            130:
            begin
                out <= "d";
                pc <= 131;
            end
            131:
            begin
                out <= "o";
                pc <= 132;
            end
            132:
            begin
                out <= "k";
                pc <= 133;
            end
            133:
            begin
                out <= "o";
                pc <= 134;
            end
            134:
            begin
                out <= " ";
                pc <= 140;
            end
            140:
            begin
                out <= "k";
                pc <= 141;
            end
            141:
            begin
                out <= "i";
                pc <= 142;
            end
            142:
            begin
                out <= "y";
                pc <= 143;
            end
            143:
            begin
                out <= "o";
                pc <= 144;
            end
            144:
            begin
                out <= "s";
                pc <= 145;
            end
            145:
            begin
                out <= "i";
                pc <= 146;
            end
            146:
            begin
                out <= "!";
                pc <= 147;
            end
            147:
            begin
                out <= "!";
                pc <= 148;
            end
            148:
            begin
                out <= " ";
                pc <= 150;
            end
            150:
            begin
                pc <= 150;
            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
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
 100
 101  d
 102  o
 103  k
 104  o
 110
 120
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
  90
  30
  40
  50
  60
  61  z
  62  u
  63  n
  70
  80
 130
 131  d
 132  o
 133  k
 134  o
 140
 141  k
 142  i
 143  y
 144  o
 145  s
 146  i
 147  !
 148  !
 150
```

# サンプルコード

```

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 b=234
30 b=b*5
40 b=b+1
50 #=b<120*100
60 ?="zun"
70 a=a+1
80 #=a>3*130
90 #=30
100 ?="doko"
110 a=0
120 #=30
130 ?="doko" 
140 ?="kiyosi!!"
150 #=150
""")




```


# 成果物

https://paiza.io/projects/xIMkzDE7C_iPE-zRsIE3bA?language=elixir


以上。