eRubyによるメタプログラミングの実例
説明
まとめ:行数の比較
行数 | コメント | |
class定義 | 32行 | FPop classはVHDLMODULE classを継承しているので実質的にはもっと多い |
erbソース | 181行 | 内部で使う信号の宣言が無駄に行数を使っている |
VHDL | 337行 | 本当は利用しているcomponentの定義も必要なのでもっと多い |
FP加算器のclass定義
class FPadd < FPop def initialize(nf = 32, nm = 23) super(nf, nm, 4) @narg = 3 @name = gen_name(:add) @nadder = nm + 1 + 3 + 1 @swap = addcomponent Swap.new(nf) @rshift = addcomponent Rshift.new(nm+1,@nexp+1) @sbit = addcomponent Extractsbit.new(nm+1, @nexp+1) @sadd = addcomponent INTsadder.new(@nadder+1) ## 2 @test = addcomponent FPaddtest.new(nf, nm, @nadder) ## 1 @uflow = addcomponent Underflow.new(@nman+1,@nexp) @delay1 = addcomponent(Delay.new(1,2)) @delay2 = addcomponent(Delay.new(@nexp,2)) @delay3 = addcomponent(Delay.new(1,3)) @delay4 = addcomponent(Delay.new(@nexp,3)) @delay5 = addcomponent(Delay.new(@nexp+1,3)) if @nexp == @nman then @delay6 = @delay5 else @delay6 = addcomponent(Delay.new(@nman+1,3)) end end def run super('float_add.vhd.erb') end end
FP加算器のソース(float_add.vhd.erb)
------------------------------------------------------------------------------- % defineIO :in, :x, @nfloat % defineIO :in, :y, @nfloat % defineIO :out, :z, @nfloat % defineIO :in, :clk, 1 ------------------------------------------------------------------------------- % nfloat = @nfloat % nman = @nman % nexp = @nexp % % width_nf = "#{nfloat-1} downto 0" % width_nm = "#{nman-1} downto 0" % width_ne = "#{nexp-1} downto 0" ------------------------------------------------------------------------------- <%= generate_header %> <%= generate_entity %> architecture source of <%= @name %> is <%= generate_components %> signal signz,sz : std_logic; signal manz,mz : std_logic_vector(<%= nman %> downto 0); signal expz,ez : std_logic_vector(<%= width_ne %>); signal ex0, ey0 : std_logic_vector(<%= nexp %> downto 0); signal xx, yy : std_logic_vector(<%= width_nf %>); signal sx, sy : std_logic; signal mx, my : std_logic_vector(<%= nman %> downto 0); signal ex, ey : std_logic_vector(<%= width_ne %>); signal dx : std_logic_vector(<%= nexp %> downto 0); signal dy : std_logic_vector(<%= nexp %> downto 0); signal diff : std_logic_vector(<%= nexp %> downto 0); -- signal res0 : std_logic_vector(<%= nman %> downto 0); signal expz0 : std_logic_vector(<%= width_ne %>); signal signz0 : std_logic; signal ulp0, rbit0, sbit0 : std_logic; signal res1 : std_logic_vector(<%= nman %> downto 0); signal expz1 : std_logic_vector(<%= width_ne %>); signal signz1 : std_logic; signal ulp1, rbit1, sbit1 : std_logic; -- signal o1 : std_logic_vector(<%= @nadder - 1 %> downto 0); signal o2 : std_logic_vector(<%= @nadder - 1 %> downto 0); signal r1, r2, r3 : std_logic; signal a0, a1 : std_logic_vector(<%= @nadder %> downto 0); signal b0, b1 : std_logic_vector(<%= @nadder %> downto 0); signal res : std_logic_vector(<%= @nadder %> downto 0); signal resn : std_logic_vector(<%= @nadder %> downto 0); signal zf : std_logic; -- signal dd : std_logic_vector(<%= nexp + 1 %> downto 0); signal d0 : std_logic_vector(<%= nexp + 1 %> downto 0); signal manzz : std_logic_vector(<%= nman %> downto 0); signal expzz : std_logic_vector(<%= width_ne %>); signal ulp, rbit, sbit : std_logic; signal zz : std_logic_vector(<%= width_nf %>); signal expz0_reg : std_logic_vector(<%= width_ne %>); signal expz0_regg : std_logic_vector(<%= width_ne %>); signal r1_reg, r2_reg, r3_reg : std_logic; signal diff_reg : std_logic_vector(<%= nexp %> downto 0); signal res0_reg : std_logic_vector(<%= nman %> downto 0); signal signz0_reg : std_logic; signal signz1_reg : std_logic; signal ulp0_reg, rbit0_reg, sbit0_reg : std_logic; signal zf_reg : std_logic; begin ex0 <= '0'&x(<%= nfloat - 2 %> downto <%= nman %>); ey0 <= '0'&y(<%= nfloat - 2 %> downto <%= nman %>); dx <= ex0 - ey0; dy <= ey0 - ex0; -- swap s0 : <%= @swap %> port map ( f => dx(<%= nexp %>), x => x, y => y, xs => xx, ys => yy); with dx(<%= nexp %>) select diff <= dy when '1', dx when others; e0 : <%= @fextract %> port map ( x => xx, s => sx, m => mx, e => ex); e1 : <%= @fextract %> port map ( x => yy, s => sy, m => my, e => ey); -------------------------------------------------------------------- -- if diff > <%= nman + 1 %> res0 <= mx; expz0 <= ex; signz0 <= sx; ulp0 <= res0(0); rbit0 <= '0'; sbit0 <= '1'; -- else -- o1 o1 <= "00"&mx&"00"; -- o2 shift0 : <%= @rshift %> port map (c => diff, i => my, o => o2); r1 <= o2(1); r2 <= o2(0); -- r3 sb0 : <%= @sbit %> port map (c => diff, i => my, s => r3); ---- a0 <= o1(<%= @nadder - 1 %> downto 0)&'0'; b0 <= o2(<%= @nadder - 1 %> downto 0)&r3; -- add: <%= @sadd %> port map (x => a0, sx => sx, y => b0, sy => sy, z => resn, sz => signz1, clk => clk); d1 : <%= @delay1 %> port map (i => r1, o => r1_reg, clk => clk); d2 : <%= @delay1 %> port map (i => r2, o => r2_reg, clk => clk); d3 : <%= @delay1 %> port map (i => r3, o => r3_reg, clk => clk); d4 : <%= @delay2 %> port map (i => expz0, o => expz0_reg, clk => clk); -- flag zf if res == 0 with resn select zf <= '1' when "<%= 0.to_b(@nadder+1) %>", '0' when others; ---- f0 : <%= @test %> port map ( tmp => resn(<%= @nadder - 1 %> downto 0), exp => expz0_reg, r1 => r1_reg, r2 => r2_reg, r3 => r3_reg, res => res1, expz => expz1, ulp => ulp1, rbit => rbit1, sbit => sbit1, clk => clk); process(clk) begin if(clk'event and clk='1') then signz1_reg <= signz1; zf_reg <= zf; end if; end process; --sadd 2 signz1, resn --test 3 res1, expz1, ulp1, rbit1, sbit1 d5 : <%= @delay3 %> port map (i => signz0, o => signz0_reg, clk => clk); d6 : <%= @delay3 %> port map (i => ulp0, o => ulp0_reg, clk => clk); d7 : <%= @delay3 %> port map (i => rbit0, o => rbit0_reg, clk => clk); d8 : <%= @delay3 %> port map (i => sbit0, o => sbit0_reg, clk => clk); d9 : <%= @delay4 %> port map (i => expz0, o => expz0_regg, clk => clk); d10 : <%= @delay5 %> port map (i => diff, o => diff_reg, clk => clk); d11 : <%= @delay6 %> port map (i => res0, o => res0_reg, clk => clk); -------------------------------------------------------------------- d0 <= '0'&diff_reg; dd <= "<%= (nman + 1).to_b(nexp+1) %>" - d0; uf : <%= @uflow %> port map (f => dd(<%= nexp %>), m1 => res0_reg, e1 => expz0_regg, u1 => ulp0_reg, r1 => rbit0_reg, s1 => sbit0_reg, m2 => res1, e2 => expz1, u2 => ulp1, r2 => rbit1, s2 => sbit1, m => manzz, e => expzz, u => ulp, r => rbit, s => sbit ); with dd(<%= nexp %>) select signz <= signz0_reg when '1', signz1_reg when others; r0 : <%= @frounding %> port map ( m => manzz, e => expzz, u => ulp, r => rbit, s => sbit, mout => manz, eout=> expz); with zf_reg select sz <= signz when '0', '0' when others; with zf_reg select mz <= manz when '0', "<%= 0.to_b(@nman+1) %>" when others; with zf_reg select ez <= expz when '0', "<%= 0.to_b(@nexp) %>" when others; c0 : <%= @fcompose %> port map (s => sz, m => mz, e => ez, z => z, clk => clk); end source; ------------------------------------------------------------------------------- <%= generate_components_body %> -------------------------------------------------------------------------------
生成結果(単精度相当)
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity fp_add_32_23_8_4 is port ( x : in std_logic_vector(31 downto 0); y : in std_logic_vector(31 downto 0); z : out std_logic_vector(31 downto 0); clk : in std_logic ); end fp_add_32_23_8_4; architecture source of fp_add_32_23_8_4 is component extract_32_23_8 port ( x : in std_logic_vector(31 downto 0); s : out std_logic; m : out std_logic_vector(23 downto 0); e : out std_logic_vector(7 downto 0) ); end component; component rounding_32_23_8 port ( m : in std_logic_vector(23 downto 0); e : in std_logic_vector(7 downto 0); u : in std_logic; r : in std_logic; s : in std_logic; mout : out std_logic_vector(23 downto 0); eout : out std_logic_vector(7 downto 0) ); end component; component compose_32_23_8 port ( s : in std_logic; m : in std_logic_vector(23 downto 0); e : in std_logic_vector(7 downto 0); z : out std_logic_vector(31 downto 0); clk : in std_logic ); end component; component swap_32 port ( f : in std_logic; x : in std_logic_vector(31 downto 0); y : in std_logic_vector(31 downto 0); xs : out std_logic_vector(31 downto 0); ys : out std_logic_vector(31 downto 0) ); end component; component int_rshift_24_9_0 port ( c : in std_logic_vector(8 downto 0); i : in std_logic_vector(23 downto 0); o : out std_logic_vector(27 downto 0) ); end component; component int_extractsbit_24_9_0 port ( c : in std_logic_vector(8 downto 0); i : in std_logic_vector(23 downto 0); s : out std_logic ); end component; component int_sadder_29_2 port ( x : in std_logic_vector(28 downto 0); sx : in std_logic; y : in std_logic_vector(28 downto 0); sy : in std_logic; z : out std_logic_vector(28 downto 0); sz : out std_logic; clk : in std_logic ); end component; component fp_addtest_32_23_8_0 port ( tmp : in std_logic_vector(27 downto 0); exp : in std_logic_vector(7 downto 0); r1 : in std_logic; r2 : in std_logic; r3 : in std_logic; res : out std_logic_vector(23 downto 0); expz : out std_logic_vector(7 downto 0); ulp : out std_logic; rbit : out std_logic; sbit : out std_logic; clk : in std_logic ); end component; component underflow_24_8 port ( f : in std_logic; m1 : in std_logic_vector(23 downto 0); e1 : in std_logic_vector(7 downto 0); u1 : in std_logic; r1 : in std_logic; s1 : in std_logic; m2 : in std_logic_vector(23 downto 0); e2 : in std_logic_vector(7 downto 0); u2 : in std_logic; r2 : in std_logic; s2 : in std_logic; m : out std_logic_vector(23 downto 0); e : out std_logic_vector(7 downto 0); u : out std_logic; r : out std_logic; s : out std_logic ); end component; component delay_1_2 port ( i : in std_logic; o : out std_logic; clk : in std_logic ); end component; component delay_8_2 port ( i : in std_logic_vector(7 downto 0); o : out std_logic_vector(7 downto 0); clk : in std_logic ); end component; component delay_1_3 port ( i : in std_logic; o : out std_logic; clk : in std_logic ); end component; component delay_8_3 port ( i : in std_logic_vector(7 downto 0); o : out std_logic_vector(7 downto 0); clk : in std_logic ); end component; component delay_9_3 port ( i : in std_logic_vector(8 downto 0); o : out std_logic_vector(8 downto 0); clk : in std_logic ); end component; component delay_24_3 port ( i : in std_logic_vector(23 downto 0); o : out std_logic_vector(23 downto 0); clk : in std_logic ); end component; signal signz,sz : std_logic; signal manz,mz : std_logic_vector(23 downto 0); signal expz,ez : std_logic_vector(7 downto 0); signal ex0, ey0 : std_logic_vector(8 downto 0); signal xx, yy : std_logic_vector(31 downto 0); signal sx, sy : std_logic; signal mx, my : std_logic_vector(23 downto 0); signal ex, ey : std_logic_vector(7 downto 0); signal dx : std_logic_vector(8 downto 0); signal dy : std_logic_vector(8 downto 0); signal diff : std_logic_vector(8 downto 0); -- signal res0 : std_logic_vector(23 downto 0); signal expz0 : std_logic_vector(7 downto 0); signal signz0 : std_logic; signal ulp0, rbit0, sbit0 : std_logic; signal res1 : std_logic_vector(23 downto 0); signal expz1 : std_logic_vector(7 downto 0); signal signz1 : std_logic; signal ulp1, rbit1, sbit1 : std_logic; -- signal o1 : std_logic_vector(27 downto 0); signal o2 : std_logic_vector(27 downto 0); signal r1, r2, r3 : std_logic; signal a0, a1 : std_logic_vector(28 downto 0); signal b0, b1 : std_logic_vector(28 downto 0); signal res : std_logic_vector(28 downto 0); signal resn : std_logic_vector(28 downto 0); signal zf : std_logic; -- signal dd : std_logic_vector(9 downto 0); signal d0 : std_logic_vector(9 downto 0); signal manzz : std_logic_vector(23 downto 0); signal expzz : std_logic_vector(7 downto 0); signal ulp, rbit, sbit : std_logic; signal zz : std_logic_vector(31 downto 0); signal expz0_reg : std_logic_vector(7 downto 0); signal expz0_regg : std_logic_vector(7 downto 0); signal r1_reg, r2_reg, r3_reg : std_logic; signal diff_reg : std_logic_vector(8 downto 0); signal res0_reg : std_logic_vector(23 downto 0); signal signz0_reg : std_logic; signal signz1_reg : std_logic; signal ulp0_reg, rbit0_reg, sbit0_reg : std_logic; signal zf_reg : std_logic; begin ex0 <= '0'&x(30 downto 23); ey0 <= '0'&y(30 downto 23); dx <= ex0 - ey0; dy <= ey0 - ex0; -- swap s0 : swap_32 port map ( f => dx(8), x => x, y => y, xs => xx, ys => yy); with dx(8) select diff <= dy when '1', dx when others; e0 : extract_32_23_8 port map ( x => xx, s => sx, m => mx, e => ex); e1 : extract_32_23_8 port map ( x => yy, s => sy, m => my, e => ey); -------------------------------------------------------------------- -- if diff > 24 res0 <= mx; expz0 <= ex; signz0 <= sx; ulp0 <= res0(0); rbit0 <= '0'; sbit0 <= '1'; -- else -- o1 o1 <= "00"&mx&"00"; -- o2 shift0 : int_rshift_24_9_0 port map (c => diff, i => my, o => o2); r1 <= o2(1); r2 <= o2(0); -- r3 sb0 : int_extractsbit_24_9_0 port map (c => diff, i => my, s => r3); ---- a0 <= o1(27 downto 0)&'0'; b0 <= o2(27 downto 0)&r3; -- add: int_sadder_29_2 port map (x => a0, sx => sx, y => b0, sy => sy, z => resn, sz => signz1, clk => clk); d1 : delay_1_2 port map (i => r1, o => r1_reg, clk => clk); d2 : delay_1_2 port map (i => r2, o => r2_reg, clk => clk); d3 : delay_1_2 port map (i => r3, o => r3_reg, clk => clk); d4 : delay_8_2 port map (i => expz0, o => expz0_reg, clk => clk); -- flag zf if res == 0 with resn select zf <= '1' when "00000000000000000000000000000", '0' when others; ---- f0 : fp_addtest_32_23_8_0 port map ( tmp => resn(27 downto 0), exp => expz0_reg, r1 => r1_reg, r2 => r2_reg, r3 => r3_reg, res => res1, expz => expz1, ulp => ulp1, rbit => rbit1, sbit => sbit1, clk => clk); process(clk) begin if(clk'event and clk='1') then signz1_reg <= signz1; zf_reg <= zf; end if; end process; --sadd 2 signz1, resn --test 3 res1, expz1, ulp1, rbit1, sbit1 d5 : delay_1_3 port map (i => signz0, o => signz0_reg, clk => clk); d6 : delay_1_3 port map (i => ulp0, o => ulp0_reg, clk => clk); d7 : delay_1_3 port map (i => rbit0, o => rbit0_reg, clk => clk); d8 : delay_1_3 port map (i => sbit0, o => sbit0_reg, clk => clk); d9 : delay_8_3 port map (i => expz0, o => expz0_regg, clk => clk); d10 : delay_9_3 port map (i => diff, o => diff_reg, clk => clk); d11 : delay_24_3 port map (i => res0, o => res0_reg, clk => clk); -------------------------------------------------------------------- d0 <= '0'&diff_reg; dd <= "000011000" - d0; uf : underflow_24_8 port map (f => dd(8), m1 => res0_reg, e1 => expz0_regg, u1 => ulp0_reg, r1 => rbit0_reg, s1 => sbit0_reg, m2 => res1, e2 => expz1, u2 => ulp1, r2 => rbit1, s2 => sbit1, m => manzz, e => expzz, u => ulp, r => rbit, s => sbit ); with dd(8) select signz <= signz0_reg when '1', signz1_reg when others; r0 : rounding_32_23_8 port map ( m => manzz, e => expzz, u => ulp, r => rbit, s => sbit, mout => manz, eout=> expz); with zf_reg select sz <= signz when '0', '0' when others; with zf_reg select mz <= manz when '0', "000000000000000000000000" when others; with zf_reg select ez <= expz when '0', "00000000" when others; c0 : compose_32_23_8 port map (s => sz, m => mz, e => ez, z => z, clk => clk); end source;
エミュレーションコードの生成
そのうち載せる。
Last modified 14 years ago
Last modified on Sep 22, 2010 7:28:43 AM