概要
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
写真
成果物
以上。