paiza.ioでelixir その302

# 概要
paiza.ioでelixirやってみた。
高位合成、やってみた。
練習問題やってみた。
実装編。

# 練習問題
俺言語で、serial送信を実現せよ。

# サンプルコード

```


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 <= j[9 - 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 i(a, b) do
		Agent.update(__MODULE__, fn v ->
		
		    vv = String.trim(b, "\"")
		        |> String.codepoints()
                |> Enum.with_index(fn (k, i) ->
	                "\t\tmem[#{i}] <= {1'b1, \"#{k}\", 1'b0};"
                end)
                |> Enum.join("\n")


		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    vv <>
			    "\n                mem[5] <= 0;\n" <>			    
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def j(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
				"                j <= mem[m];\n" <>
				"                m <= m + 1;\n" <>
				"                if (m > 5) m <= 0;\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 "`timescale 1ns/1ps\n" <>
            "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 [9:0] mem[31:0];\n" <>
	        "    reg [9:0] i;\n" <>
	        "    reg [7:0] j;\n" <>
	        "    reg [7:0] n;\n" <>
	        "    reg [7:0] m;\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" <>
			"            i <= 0;\n" <>
			"            j <= 0;\n" <>
			"            n <= 0;\n" <>
			"            m <= 0;\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" <>	
		    "        o = 0;\n" <>
		    "    #2\n" <>
			"        rst = 0;\n" <>
		    "    #2\n" <>
		    "        rst = 1;\n" <>
		    "    #90000\n" <>
			"        $finish;\n" <>
	        "    end\n" <>
	        "    always\n" <>
		    "    #1\n" <>
			"        clk = ~clk;\n" <>
	        "    always\n" <>
		    "    #868\n" <>
			"        o = ~o;\n" <>
	        "    initial\n" <>
	        "    begin\n" <>
	        "		 $dumpfile(\"test.vcd\");\n" <>
		    "        $dumpvars(0, u);\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))
			Enum.at(s, 1) == "i" ->
				Asm.i(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "j" ->
				Asm.j(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=1
20 i="hello"
30 j=i
40 #=j@0*200
50 #=b@9*150
60 #=o@1*80
70 #=60
80 a=j
90 #=a@1*120
100 x=1
110 #=130
120 x=0
130 #=o@0*170
140 #=130
150 b=0
160 #=30
170 b=b+1
180 #=50
200 #=200
""")




```

# 実行結果

```

`timescale 1ns/1ps
module ore(input clk, input rst, input o, input p, input q, output x, output y, output z);
    reg [7:0] a;
    reg [7:0] b;
    reg [7:0] c;
    reg [7:0] d;
    reg [7:0] e;
    reg [7:0] f;
    reg [7:0] g;
    reg [7:0] h;
    reg [7:0] pc;
    reg [9:0] mem[31:0];
    reg [9:0] i;
    reg [7:0] j;
    reg [7:0] n;
    reg [7:0] m;
    reg x;
    reg y;
    reg z;
    wire o;
    wire p;
    wire q;
    always @(posedge clk)
    begin
        if (!rst)
        begin
            a <= 0;
            b <= 0;
            c <= 0;
            d <= 0;
            e <= 0;
            f <= 0;
            g <= 0;
            h <= 0;
            pc <= 10;
            i <= 0;
            j <= 0;
            n <= 0;
            m <= 0;
        end
        else
        begin
            case(pc)
            10:
            begin
                x <= 1;
                pc <= 20;
            end
            20:
            begin
		mem[0] <= {1'b1, "h", 1'b0};
		mem[1] <= {1'b1, "e", 1'b0};
		mem[2] <= {1'b1, "l", 1'b0};
		mem[3] <= {1'b1, "l", 1'b0};
		mem[4] <= {1'b1, "o", 1'b0};
                mem[5] <= 0;
                pc <= 30;
            end
            30:
            begin
                j <= mem[m];
                m <= m + 1;
                if (m > 5) m <= 0;
                pc <= 40;
            end
            40:
            begin
                if (j==0)
                    pc <= 200;
                else
                    pc <= 50;
            end
            50:
            begin
                if (b==9)
                    pc <= 150;
                else
                    pc <= 60;
            end
            60:
            begin
                if (o==1)
                    pc <= 80;
                else
                    pc <= 70;
            end
            70:
            begin
                pc <= 60;
            end
            80:
            begin
                a <= j[9 - b];
                pc <= 90;
            end
            90:
            begin
                if (a==1)
                    pc <= 120;
                else
                    pc <= 100;
            end
            100:
            begin
                x <= 1;
                pc <= 110;
            end
            110:
            begin
                pc <= 130;
            end
            120:
            begin
                x <= 0;
                pc <= 130;
            end
            130:
            begin
                if (o==0)
                    pc <= 170;
                else
                    pc <= 140;
            end
            140:
            begin
                pc <= 130;
            end
            150:
            begin
                b <= 0;
                pc <= 160;
            end
            160:
            begin
                pc <= 30;
            end
            170:
            begin
                b <= b+1;
                pc <= 180;
            end
            180:
            begin
                pc <= 50;
            end
            200:
            begin
                pc <= 200;
            end
            endcase
        end
    end
    initial
    begin
        //$monitor(" %d  %d", pc, x);
    end
endmodule

module test;
    reg clk,
        rst;
    wire [7:0] out;
    reg o;
    reg p;
    reg q;
    wire x;
    wire y;
    wire z;
    ore u(.clk(clk), .rst(rst), .o(o), .p(p), .q(q), .x(x), .y(y), .z(z));
    initial
    begin
        clk = 0;
        rst = 1;
        o = 0;
    #2
        rst = 0;
    #2
        rst = 1;
    #90000
        $finish;
    end
    always
    #1
        clk = ~clk;
    always
    #868
        o = ~o;
    initial
    begin
		 $dumpfile("test.vcd");
        $dumpvars(0, u);
        $display(" o  p  x ");
        $monitor(" %d %d  %d ", o, p, x);
    end
endmodule
```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/1f4afd18-4bfd-1ac3-160b-766814ca34c7.png)


# 成果物

https://paiza.io/projects/2ftOu3BWbFPkRt6_eQk5Eg


以上。