verilisp

去年発見した verilisp。使うのは簡単。

(module test (
        (output a)
        (inout (2 b c))
        (input d e)
    )
    (display b c d e)
)
(module test2 ()
    (wire a b0 b1 d_ c0 c1 e)
    (test
        a
        (cat b0 b1)
        (name d d_)
        (name c (cat c0 c1))
        e
    )
    (display 2)
)
(module clock (
        (output clk)
    )
    (always ()
        (= clk (! clk))
    )
)

これを verilisp にかけるとあらふしぎ

module test(a, b, c, d, e);
    output a;
    inout [1 : 0] b;
    inout [1 : 0] c;
    input d;
    input e;
    $display(b, c, d, e);
endmodule

module test2();
    wire a;
    wire b0;
    wire b1;
    wire d_;
    wire c0;
    wire c1;
    wire e;
    test anon_0 (a, {b0, b1}, .d(d_), .c({c0, c1}), e);
    $display(2);
endmodule

module clock(clk);
    output clk;
    always
    begin
        clk = (!clk);
    end
endmodule

これだけなら単なるコンバータだ。lisp なので defmacro が使える。

(defmacro make-test-macro (WORDSIZE)
    `(progn
        (module test_macro ()
            (wire (,WORDSIZE sum_out) c_out)
            (reg (,(l_- WORDSIZE 1) sum_in) (,WORDSIZE b) a0 a1 c_in)
            )))

(make-test-macro 4)

これが

module test_macro();
    wire [3 : 0] sum_out;
    wire c_out;
    reg [2 : 0] sum_in;
    reg [3 : 0] b;
    reg a0;
    reg a1;
    reg c_in;
endmodule

こうなる。まぁ、これでもまだ。コンバータだ。もうちょいましな macro を作らないとなぁ。