eRubyによるメタプログラミングの実例
説明
まとめ:行数の比較
行数 | コメント
|
class定義 | 32行 |
|
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加算器のソース
-------------------------------------------------------------------------------
% 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;
エミュレーションコードの生成
そのうち載せる。