mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-03 03:59:22 +00:00
multiplier: Generalize interface to the multiplier
This makes the interface to the multiplier more general so an instance of it can be used in the FPU. It now has a 128-bit addend that is added on to the product. Instead of an input to negate the output, it now has a "not_result" input to complement the output. Execute1 uses not_result=1 and addend=-1 to get the effect of negating the output. The interface is defined this way because this is what can be done easily with the Xilinx DSP slices in xilinx-mult.vhdl. This also adds clock enable signals to the DSP slices, mostly for the sake of reducing power consumption. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
27
common.vhdl
27
common.vhdl
@@ -182,16 +182,25 @@ package common is
|
||||
is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0',
|
||||
byte_reverse => '0', sign_extend => '0', update => '0', nia => (others => '0'), read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'), cr => (others => '0'), insn => (others => '0'), data_len => (others => '0'), others => (others => '0'));
|
||||
|
||||
type Execute1ToMultiplyType is record
|
||||
type MultiplyInputType is record
|
||||
valid: std_ulogic;
|
||||
data1: std_ulogic_vector(63 downto 0);
|
||||
data2: std_ulogic_vector(63 downto 0);
|
||||
addend: std_ulogic_vector(127 downto 0);
|
||||
is_32bit: std_ulogic;
|
||||
neg_result: std_ulogic;
|
||||
not_result: std_ulogic;
|
||||
end record;
|
||||
constant Execute1ToMultiplyInit : Execute1ToMultiplyType := (valid => '0',
|
||||
is_32bit => '0', neg_result => '0',
|
||||
others => (others => '0'));
|
||||
constant MultiplyInputInit : MultiplyInputType := (valid => '0',
|
||||
is_32bit => '0', not_result => '0',
|
||||
others => (others => '0'));
|
||||
|
||||
type MultiplyOutputType is record
|
||||
valid: std_ulogic;
|
||||
result: std_ulogic_vector(127 downto 0);
|
||||
overflow : std_ulogic;
|
||||
end record;
|
||||
constant MultiplyOutputInit : MultiplyOutputType := (valid => '0', overflow => '0',
|
||||
others => (others => '0'));
|
||||
|
||||
type Execute1ToDividerType is record
|
||||
valid: std_ulogic;
|
||||
@@ -382,14 +391,6 @@ package common is
|
||||
write_cr_data => (others => '0'), write_reg => (others => '0'),
|
||||
exc_write_reg => (others => '0'), exc_write_data => (others => '0'));
|
||||
|
||||
type MultiplyToExecute1Type is record
|
||||
valid: std_ulogic;
|
||||
result: std_ulogic_vector(127 downto 0);
|
||||
overflow : std_ulogic;
|
||||
end record;
|
||||
constant MultiplyToExecute1Init : MultiplyToExecute1Type := (valid => '0', overflow => '0',
|
||||
others => (others => '0'));
|
||||
|
||||
type DividerToExecute1Type is record
|
||||
valid: std_ulogic;
|
||||
write_reg_data: std_ulogic_vector(63 downto 0);
|
||||
|
||||
@@ -89,8 +89,8 @@ architecture behaviour of execute1 is
|
||||
signal countzero_result: std_ulogic_vector(63 downto 0);
|
||||
|
||||
-- multiply signals
|
||||
signal x_to_multiply: Execute1ToMultiplyType;
|
||||
signal multiply_to_x: MultiplyToExecute1Type;
|
||||
signal x_to_multiply: MultiplyInputType;
|
||||
signal multiply_to_x: MultiplyOutputType;
|
||||
|
||||
-- divider signals
|
||||
signal x_to_divider: Execute1ToDividerType;
|
||||
@@ -396,7 +396,7 @@ begin
|
||||
abs2 := - signed(b_in);
|
||||
end if;
|
||||
|
||||
x_to_multiply <= Execute1ToMultiplyInit;
|
||||
x_to_multiply <= MultiplyInputInit;
|
||||
x_to_multiply.is_32bit <= e_in.is_32bit;
|
||||
|
||||
x_to_divider <= Execute1ToDividerInit;
|
||||
@@ -406,7 +406,8 @@ begin
|
||||
x_to_divider.is_modulus <= '1';
|
||||
end if;
|
||||
|
||||
x_to_multiply.neg_result <= sign1 xor sign2;
|
||||
x_to_multiply.not_result <= sign1 xor sign2;
|
||||
x_to_multiply.addend <= (others => sign1 xor sign2);
|
||||
x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus);
|
||||
if e_in.is_32bit = '0' then
|
||||
-- 64-bit forms
|
||||
|
||||
@@ -12,22 +12,22 @@ entity multiply is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
|
||||
m_in : in Execute1ToMultiplyType;
|
||||
m_out : out MultiplyToExecute1Type
|
||||
m_in : in MultiplyInputType;
|
||||
m_out : out MultiplyOutputType
|
||||
);
|
||||
end entity multiply;
|
||||
|
||||
architecture behaviour of multiply is
|
||||
signal m: Execute1ToMultiplyType := Execute1ToMultiplyInit;
|
||||
signal m: MultiplyInputType := MultiplyInputInit;
|
||||
|
||||
type multiply_pipeline_stage is record
|
||||
valid : std_ulogic;
|
||||
data : unsigned(127 downto 0);
|
||||
is_32bit : std_ulogic;
|
||||
neg_res : std_ulogic;
|
||||
not_res : std_ulogic;
|
||||
end record;
|
||||
constant MultiplyPipelineStageInit : multiply_pipeline_stage := (valid => '0',
|
||||
is_32bit => '0', neg_res => '0',
|
||||
is_32bit => '0', not_res => '0',
|
||||
data => (others => '0'));
|
||||
|
||||
type multiply_pipeline_type is array(0 to PIPELINE_DEPTH-1) of multiply_pipeline_stage;
|
||||
@@ -53,19 +53,19 @@ begin
|
||||
variable d2 : std_ulogic_vector(63 downto 0);
|
||||
variable ov : std_ulogic;
|
||||
begin
|
||||
v := r;
|
||||
v.multiply_pipeline(0).valid := m.valid;
|
||||
v.multiply_pipeline(0).data := unsigned(m.data1) * unsigned(m.data2);
|
||||
v.multiply_pipeline(0).data := (unsigned(m.data1) * unsigned(m.data2)) + unsigned(m.addend);
|
||||
v.multiply_pipeline(0).is_32bit := m.is_32bit;
|
||||
v.multiply_pipeline(0).neg_res := m.neg_result;
|
||||
v.multiply_pipeline(0).not_res := m.not_result;
|
||||
|
||||
loop_0: for i in 1 to PIPELINE_DEPTH-1 loop
|
||||
v.multiply_pipeline(i) := r.multiply_pipeline(i-1);
|
||||
end loop;
|
||||
|
||||
if v.multiply_pipeline(PIPELINE_DEPTH-1).neg_res = '0' then
|
||||
d := std_ulogic_vector(v.multiply_pipeline(PIPELINE_DEPTH-1).data);
|
||||
else
|
||||
d := std_ulogic_vector(- signed(v.multiply_pipeline(PIPELINE_DEPTH-1).data));
|
||||
d := std_ulogic_vector(v.multiply_pipeline(PIPELINE_DEPTH-1).data);
|
||||
if v.multiply_pipeline(PIPELINE_DEPTH-1).not_res = '1' then
|
||||
d := not d;
|
||||
end if;
|
||||
|
||||
ov := '0';
|
||||
|
||||
@@ -17,8 +17,8 @@ architecture behave of multiply_tb is
|
||||
|
||||
constant pipeline_depth : integer := 4;
|
||||
|
||||
signal m1 : Execute1ToMultiplyType := Execute1ToMultiplyInit;
|
||||
signal m2 : MultiplyToExecute1Type;
|
||||
signal m1 : MultiplyInputType := MultiplyInputInit;
|
||||
signal m2 : MultiplyOutputType;
|
||||
|
||||
function absval(x: std_ulogic_vector) return std_ulogic_vector is
|
||||
begin
|
||||
@@ -45,6 +45,7 @@ begin
|
||||
stim_process: process
|
||||
variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0);
|
||||
variable si: std_ulogic_vector(15 downto 0);
|
||||
variable sign: std_ulogic;
|
||||
begin
|
||||
wait for clk_period;
|
||||
|
||||
@@ -90,7 +91,9 @@ begin
|
||||
|
||||
m1.data1 <= absval(ra);
|
||||
m1.data2 <= absval(rb);
|
||||
m1.neg_result <= ra(63) xor rb(63);
|
||||
sign := ra(63) xor rb(63);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@@ -114,7 +117,8 @@ begin
|
||||
|
||||
m1.data1 <= ra;
|
||||
m1.data2 <= rb;
|
||||
m1.neg_result <= '0';
|
||||
m1.not_result <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@@ -138,7 +142,9 @@ begin
|
||||
|
||||
m1.data1 <= absval(ra);
|
||||
m1.data2 <= absval(rb);
|
||||
m1.neg_result <= ra(63) xor rb(63);
|
||||
sign := ra(63) xor rb(63);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@@ -164,7 +170,9 @@ begin
|
||||
m1.data1(31 downto 0) <= absval(ra(31 downto 0));
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(31 downto 0) <= absval(rb(31 downto 0));
|
||||
m1.neg_result <= ra(31) xor rb(31);
|
||||
sign := ra(31) xor rb(31);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@@ -190,7 +198,9 @@ begin
|
||||
m1.data1(31 downto 0) <= absval(ra(31 downto 0));
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(31 downto 0) <= absval(rb(31 downto 0));
|
||||
m1.neg_result <= ra(31) xor rb(31);
|
||||
sign := ra(31) xor rb(31);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@@ -217,7 +227,8 @@ begin
|
||||
m1.data1(31 downto 0) <= ra(31 downto 0);
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(31 downto 0) <= rb(31 downto 0);
|
||||
m1.neg_result <= '0';
|
||||
m1.not_result <= '0';
|
||||
m1.addend <= (others => '0');
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
@@ -243,7 +254,9 @@ begin
|
||||
m1.data1 <= absval(ra);
|
||||
m1.data2 <= (others => '0');
|
||||
m1.data2(15 downto 0) <= absval(si);
|
||||
m1.neg_result <= ra(63) xor si(15);
|
||||
sign := ra(63) xor si(15);
|
||||
m1.not_result <= sign;
|
||||
m1.addend <= (others => sign);
|
||||
m1.valid <= '1';
|
||||
|
||||
wait for clk_period;
|
||||
|
||||
@@ -12,8 +12,8 @@ entity multiply is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
|
||||
m_in : in Execute1ToMultiplyType;
|
||||
m_out : out MultiplyToExecute1Type
|
||||
m_in : in MultiplyInputType;
|
||||
m_out : out MultiplyOutputType
|
||||
);
|
||||
end entity multiply;
|
||||
|
||||
@@ -33,11 +33,11 @@ architecture behaviour of multiply is
|
||||
signal p1_pat, p1_patb : std_ulogic;
|
||||
|
||||
signal req_32bit, r32_1 : std_ulogic;
|
||||
signal req_neg, rneg_1 : std_ulogic;
|
||||
signal req_not, rnot_1 : std_ulogic;
|
||||
signal valid_1 : std_ulogic;
|
||||
|
||||
begin
|
||||
addend <= (others => m_in.neg_result);
|
||||
addend <= m_in.addend;
|
||||
|
||||
m00: DSP48E1
|
||||
generic map (
|
||||
@@ -73,7 +73,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -129,7 +129,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -184,7 +184,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -239,7 +239,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -295,7 +295,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -351,7 +351,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -408,7 +408,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -464,7 +464,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -520,7 +520,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -575,7 +575,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -630,7 +630,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -685,7 +685,7 @@ begin
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
CEINMODE => '0',
|
||||
CEM => '1',
|
||||
CEM => m_in.valid,
|
||||
CEP => '0',
|
||||
CLK => clk,
|
||||
D => (others => '0'),
|
||||
@@ -734,12 +734,12 @@ begin
|
||||
CARRYINSEL => "000",
|
||||
CARRYOUT => s0_carry,
|
||||
CEA1 => '0',
|
||||
CEA2 => '1',
|
||||
CEA2 => valid_1,
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '1',
|
||||
CEC => '1',
|
||||
CEB2 => valid_1,
|
||||
CEC => valid_1,
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@@ -792,12 +792,12 @@ begin
|
||||
CARRYIN => s0_carry(3),
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '1',
|
||||
CEA2 => valid_1,
|
||||
CEAD => '0',
|
||||
CEALUMODE => '0',
|
||||
CEB1 => '0',
|
||||
CEB2 => '1',
|
||||
CEC => '1',
|
||||
CEB2 => valid_1,
|
||||
CEC => valid_1,
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@@ -848,7 +848,7 @@ begin
|
||||
port map (
|
||||
A => m21_p(22 downto 0) & m03_p(5 downto 0) & '0',
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "00" & rneg_1 & '0',
|
||||
ALUMODE => "00" & rnot_1 & '0',
|
||||
B => (others => '0'),
|
||||
BCIN => (others => '0'),
|
||||
C => p0_mask,
|
||||
@@ -857,12 +857,12 @@ begin
|
||||
CARRYINSEL => "000",
|
||||
CARRYOUT => p0_carry,
|
||||
CEA1 => '0',
|
||||
CEA2 => '1',
|
||||
CEA2 => valid_1,
|
||||
CEAD => '0',
|
||||
CEALUMODE => '1',
|
||||
CEALUMODE => valid_1,
|
||||
CEB1 => '0',
|
||||
CEB2 => '1',
|
||||
CEC => '1',
|
||||
CEB2 => valid_1,
|
||||
CEC => valid_1,
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
CED => '0',
|
||||
@@ -911,7 +911,7 @@ begin
|
||||
port map (
|
||||
A => x"0000000" & '0' & m21_p(41),
|
||||
ACIN => (others => '0'),
|
||||
ALUMODE => "00" & rneg_1 & '0',
|
||||
ALUMODE => "00" & rnot_1 & '0',
|
||||
B => m21_p(40 downto 23),
|
||||
BCIN => (others => '0'),
|
||||
C => (others => '0'),
|
||||
@@ -919,11 +919,11 @@ begin
|
||||
CARRYIN => p0_carry(3),
|
||||
CARRYINSEL => "000",
|
||||
CEA1 => '0',
|
||||
CEA2 => '1',
|
||||
CEA2 => valid_1,
|
||||
CEAD => '0',
|
||||
CEALUMODE => '1',
|
||||
CEALUMODE => valid_1,
|
||||
CEB1 => '0',
|
||||
CEB2 => '1',
|
||||
CEB2 => valid_1,
|
||||
CEC => '0',
|
||||
CECARRYIN => '0',
|
||||
CECTRL => '0',
|
||||
@@ -952,7 +952,7 @@ begin
|
||||
RSTP => '0'
|
||||
);
|
||||
|
||||
product(31 downto 0) <= product_lo xor (31 downto 0 => req_neg);
|
||||
product(31 downto 0) <= product_lo xor (31 downto 0 => req_not);
|
||||
|
||||
mult_out: process(all)
|
||||
variable ov : std_ulogic;
|
||||
@@ -977,8 +977,8 @@ begin
|
||||
valid_1 <= m_in.valid;
|
||||
req_32bit <= r32_1;
|
||||
r32_1 <= m_in.is_32bit;
|
||||
req_neg <= rneg_1;
|
||||
rneg_1 <= m_in.neg_result;
|
||||
req_not <= rnot_1;
|
||||
rnot_1 <= m_in.not_result;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user