paiza.ioでelixir その75

# 概要
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
""")

```

# 成果物

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


以上。