まずはYosysに簡単なPassを作ってみる。接続関係を示すために、Yosysの内部構造RTLILのProcessについて勉強しよう。
struct RTLIL::Process : public RTLIL::AttrObject { unsigned int hashidx_; unsigned int hash() const { return hashidx_; } protected: // use module->addProcess() and module->remove() to create or destroy processes friend struct RTLIL::Module; Process(); ~Process(); public: RTLIL::IdString name; RTLIL::Module *module; RTLIL::CaseRule root_case; std::vector<RTLIL::SyncRule*> syncs; template<typename T> void rewrite_sigspecs(T &functor); template<typename T> void rewrite_sigspecs2(T &functor); RTLIL::Process *clone() const; };
Process
クラスは大きく分けてroot_case
とSyncRule
の2つに分けられており、SyncRule
はベクトル形式になっている。
CaseRule
の方は複数のassign
文が格納されており、主に組み合わせ回路の記述に使われるものと思われる。
struct RTLIL::CaseRule : public RTLIL::AttrObject { std::vector<RTLIL::SigSpec> compare; std::vector<RTLIL::SigSig> actions; std::vector<RTLIL::SwitchRule*> switches; ~CaseRule(); bool empty() const; template<typename T> void rewrite_sigspecs(T &functor); template<typename T> void rewrite_sigspecs2(T &functor); RTLIL::CaseRule *clone() const; };
SyncRule
は一方で順序回路の記述に使われる。
struct RTLIL::SyncRule { RTLIL::SyncType type; RTLIL::SigSpec signal; std::vector<RTLIL::SigSig> actions; std::vector<RTLIL::MemWriteAction> mem_write_actions; template<typename T> void rewrite_sigspecs(T &functor); template<typename T> void rewrite_sigspecs2(T &functor); RTLIL::SyncRule *clone() const; };
例えば以下のSystemVerilogコードをコンパイルしてRTLILに変換してみる。
module adder3 ( input logic clk, input logic reset, input logic [31:0] in0, input logic [31:0] in1, input logic [31:0] in2, output logic [63:32] out ); logic [31: 0] temp; always_ff @ (posedge clk, posedge reset) begin if (reset) begin temp <= 'h0; end else begin temp <= in0 * in1; end end assign out = temp + in2; endmodule // adder3
変換後は以下のようになる。
process $proc$adder.sv:40$1 assign $0\temp[31:0] \temp switch \reset case 1'1 assign $0\temp[31:0] 0 case assign $0\temp[31:0] $mul$adder.sv:44$2_Y end sync posedge \clk update \temp $0\temp[31:0] sync posedge \reset update \temp $0\temp[31:0] end
assign $0\temp[31:0] \temp
: まあtemp0 = temp
みたいなassign文だと思えばよかろう。switch \reset
:reset
信号に基づいて$0\temp[31:0] \temp
に格納する値を決める。reset
ならばゼロを、そうでなければ$mul$adder.sv:44$2_Y
を格納する。sync posedge \clk
: clkに基づいて\temp
に$0\temp[31:0]
を格納する。これが順序回路の代入になる。sync posedge \reset
: resetに基づいて\temp
に$0\temp[31:0]
を格納する。これが順序回路の非同期リセットになる。
そして、加算と乗算は別のコンポーネントとして作られている。
cell $add $add$adder.sv:48$3 parameter \A_SIGNED 0 parameter \A_WIDTH 32 parameter \B_SIGNED 0 parameter \B_WIDTH 32 parameter \Y_WIDTH 32 connect \A \temp connect \B \in2 connect \Y $add$adder.sv:48$3_Y end attribute \src "adder.sv:44.13-44.22" cell $mul $mul$adder.sv:44$2 parameter \A_SIGNED 0 parameter \A_WIDTH 32 parameter \B_SIGNED 0 parameter \B_WIDTH 32 parameter \Y_WIDTH 32 connect \A \in0 connect \B \in1 connect \Y $mul$adder.sv:44$2_Y end