paiza.ioでelixir その313

# 概要
paiza.ioでelixirやってみた。
練習問題、やってみた。

# 練習問題
真理値表を表示する、インタープリターのコマンドで高位合成せよ。
コマンド
lut 3 -- 表、全体を定義、この場合　３
lin 2 -- 入力を定義、この場合　２
lout 1 -- 出力を定義、この場合　１
code 02 01 -- 入力と出力を定義、この場合　１と０なら、１

# 方針
組み合わせ回路は、これで全て解決。

# サンプルコード

```

defmodule Asm do
	def start_link do
		Agent.start_link(fn ->
			%{l: 0, i: 0, o: 0, u: ""}
		end, name: __MODULE__)
	end
    def lut(d) do
		Agent.update(__MODULE__, fn v ->
	        {a, _} = Integer.parse(d)
            %{v | l: a}
		end)
    end
    def lin(d) do
		Agent.update(__MODULE__, fn v ->
	        {a, _} = Integer.parse(d)
            %{v | i: a}
		end)
    end
    def lout(d) do
		Agent.update(__MODULE__, fn v ->
	        {a, _} = Integer.parse(d)
            %{v | o: a}
		end)
    end
    def code(a, b) do
		Agent.update(__MODULE__, fn v ->
            str = "        " <> tt(v.i) <> "'h" <> a <> ": code = " <> tt(v.o) <> "'h" <> b <> ";\n"
            %{v | u: v.u <> str}
		end)
    end
    def tb(d) do
        cond do
        d == 1 ->
            ""
        d == 2 ->
            "[1:0]"
        d == 3 ->
            "[2:0]"
        d == 4 ->
            "[3:0]"
        d == 5 ->
            "[4:0]"
        d == 6 ->
            "[5:0]"
        d == 7 ->
            "[6:0]"
        d == 8 ->
            "[7:0]"
        true ->
            "not match"
        end
    end
    def tt(d) do
        cond do
        d == 1 ->
            "1"
        d == 2 ->
            "2"
        d == 3 ->
            "3"
        d == 4 ->
            "4"
        d == 5 ->
            "5"
        d == 6 ->
            "6"
        d == 7 ->
            "7"
        d == 8 ->
            "8"
        true ->
            "not match"
        end
    end
    def td(d) do
        cond do
        d == 2 ->
            "        data = 2'h0; #10;\n" <>
		    "        data = 2'h1; #10;\n" <>
            "        data = 2'h2; #10;\n" <>
		    "        data = 2'h3; #10;\n" 
        d == 3 ->
            "        data = 3'h0; #10;\n" <>
		    "        data = 3'h1; #10;\n" <>
		    "        data = 3'h2; #10;\n" <>
		    "        data = 3'h3; #10;\n" <>
		    "        data = 3'h4; #10;\n" <>
		    "        data = 3'h5; #10;\n" <>
		    "        data = 3'h6; #10;\n" <>
		    "        data = 3'h7; #10;\n" <>
		    "        data = 3'h8; #10;\n" 
        d == 4 ->
            "        data = 4'h0; #10;\n" <>
		    "        data = 4'h1; #10;\n" <>
		    "        data = 4'h2; #10;\n" <>
		    "        data = 4'h3; #10;\n" <>
		    "        data = 4'h4; #10;\n" <>
		    "        data = 4'h5; #10;\n" <>
		    "        data = 4'h6; #10;\n" <>
		    "        data = 4'h7; #10;\n" <>
		    "        data = 4'h8; #10;\n" <>
		    "        data = 4'h9; #10;\n" <>
            "        data = 4'hA; #10;\n" <>
		    "        data = 4'hB; #10;\n" <>
		    "        data = 4'hC; #10;\n" <>
		    "        data = 4'hD; #10;\n" <>
		    "        data = 4'hE; #10;\n" <>
		    "        data = 4'hF; #10;\n" 
        true ->
            "not match"
        end
    end
    def print() do
		Agent.get(__MODULE__, fn v ->
            IO.puts "module lut(input wire " <>
            tb(v.i) <>
            " data, output reg " <>
            tb(v.o) <>
            " code);\n" <>
	        "    always @(data)\n" <>
	        "    begin\n" <>
		    "        case(data)\n" <>
		    v.u <>
		    "        endcase\n" <>
	        "    end\n" <>
		    "endmodule\n\n" <>
		    "module testbench;\n" <>
            "    reg " <>
            tb(v.i) <>
            " data;\n" <>
	        "    wire " <>
	        tb(v.o) <>
	        " code;\n" <>
	        "    lut u(.data(data), .code(code));\n" <>
	        "    initial\n" <>
	        "    begin\n" <>
		    "        $display(\"data code\");\n" <>
		    "        $monitor(\"%h  %h\", data, code);\n" <>
            td(v.i) <>
		    "        $finish;\n" <>
	        "    end\n" <>
            "endmodule\n"

		end)
	end
end

defmodule Main do
	def run(str) do
    	Enum.map(String.split(str, "\n"), fn l ->
		    s = String.split(l, " ")
		    cond do
				Enum.at(s, 0) == "lut" ->
					Asm.lut(Enum.at(s, 1))
				Enum.at(s, 0) == "lin" ->
					Asm.lin(Enum.at(s, 1))
				Enum.at(s, 0) == "lout" ->
					Asm.lout(Enum.at(s, 1))
				Enum.at(s, 0) == "code" ->
					Asm.code(Enum.at(s, 1), Enum.at(s, 2))
				true ->
					IO.puts ""
			end
	    end)
	    Asm.print
	end
end

Asm.start_link

Main.run("""
lut 3
lin 2
lout 1
code 00 00
code 01 01
code 02 01
code 03 00
""")




```

# 投入したソース
xor
```
lut 3
lin 2
lout 1
code 00 00
code 01 01
code 02 01
code 03 00
```

# 実行結果
生成したverilog
```

module lut(input wire [1:0] data, output reg  code);
    always @(data)
    begin
        case(data)
        2'h00: code = 1'h00;
        2'h01: code = 1'h01;
        2'h02: code = 1'h01;
        2'h03: code = 1'h00;
        endcase
    end
endmodule

module testbench;
    reg [1:0] data;
    wire  code;
    lut u(.data(data), .code(code));
    initial
    begin
        $display("data code");
        $monitor("%h  %h", data, code);
        data = 2'h0; #10;
        data = 2'h1; #10;
        data = 2'h2; #10;
        data = 2'h3; #10;
        $finish;
    end
endmodule

```

# 成果物

https://paiza.io/projects/IG1L5LvZw4peKnrLArJSRA


# 実行結果をiverilogで実行した結果

```
>iverilog lut0.v
lut0.v:6: warning: extra digits given for sized hex constant.
lut0.v:6: warning: extra digits given for sized hex constant.
lut0.v:7: warning: extra digits given for sized hex constant.
lut0.v:7: warning: extra digits given for sized hex constant.
lut0.v:8: warning: extra digits given for sized hex constant.
lut0.v:8: warning: extra digits given for sized hex constant.
lut0.v:9: warning: extra digits given for sized hex constant.
lut0.v:9: warning: extra digits given for sized hex constant.

>vvp a.out
data code
0  0
1  1
2  1
3  0
lut0.v:26: $finish called at 40 (1s)


```

以上。