diff options
-rw-r--r-- | testsuite/synth/issue1122/mult.vhd | 174 | ||||
-rw-r--r-- | testsuite/synth/issue1122/mult_pkg.vhd | 115 | ||||
-rw-r--r-- | testsuite/synth/issue1122/repro.vhdl | 62 | ||||
-rw-r--r-- | testsuite/synth/issue1122/repro2.vhdl | 22 | ||||
-rwxr-xr-x | testsuite/synth/issue1122/testsuite.sh | 15 |
5 files changed, 388 insertions, 0 deletions
diff --git a/testsuite/synth/issue1122/mult.vhd b/testsuite/synth/issue1122/mult.vhd new file mode 100644 index 000000000..da115faab --- /dev/null +++ b/testsuite/synth/issue1122/mult.vhd @@ -0,0 +1,174 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.mult_pkg.all; + +entity mult is port ( + clk : in std_logic; + rst : in std_logic; + slot : in std_logic; + a : in mult_i_t; + y : out mult_o_t); +end mult; + +architecture stru of mult is + signal this_c : mult_reg_t; + signal this_r : mult_reg_t := MULT_RESET; + + begin + mult : process(this_r, slot, a) + variable this : mult_reg_t; + variable aa : std_logic_vector(31 downto 0); + variable ah : std_logic_vector(30 downto 0); + variable bh : std_logic_vector(15 downto 0); + variable abh2 : std_logic_vector(32 downto 0); + variable p2 : std_logic_vector(31 downto 0); + variable p3 : std_logic_vector(31 downto 0); + variable sgn : std_logic_vector(31 downto 0); + variable pm : std_logic_vector(47 downto 0); + variable c : std_logic_vector(63 downto 0); + variable acc : std_logic_vector(63 downto 0); + variable region: std_logic_vector(2 downto 0); + variable sat : std_logic; + variable code : mult_codeline_t; + begin + this := this_r; + + code := MULT_CODE(this.state); + y.busy <= code.busy; -- FIXME: warning : combinatorial output + + -- operand intermediates, multiplier and input mux, lower 31bits of A and upper/lower 16bits of B + aa := this.m1; + if code.sela = MB then aa := this.mb; end if; + + ah := aa(30 downto 0); + if code.size = B16 then ah(30 downto 15) := (others => '0'); end if; + + bh := this.m2(15 downto 0); + if code.size = B16 then bh(15) := '0'; + elsif code.shift = '1' then bh := '0' & this.m2(30 downto 16); end if; + + -- partial product adder input mux + if code.size = B16 then abh2 := '0' & x"0000" & (aa(15) and this.m2(15)) & this.abh(29 downto 15); + elsif this.shift = '0' then abh2 := '0' & this.abh(46 downto 15); + else abh2 := '0' & (aa(31) and this.m2(31)) & this.abh(45 downto 15); end if; + + -- partial products adders + p2 := (others => '0'); + if aa(31) = '1' and code.shift = '1' then p2 := '0' & this.m2(30 downto 0); end if; + if aa(15) = '1' and code.size = B16 then p2 := x"0000" & '0' & this.m2(14 downto 0); end if; + + p3 := (others => '0'); + if this.m2(31) = '1' and code.shift = '1' then p3 := '0' & aa(30 downto 0); end if; + if this.m2(15) = '1' and code.size = B16 then p3 := x"0000" & '0' & aa(14 downto 0); end if; + + if code.sign = 1 then sgn := (others => '1'); else sgn := (others => '0'); end if; + pm := std_logic_vector(unsigned(abh2) + unsigned(sgn(0) & (this.p23 xor sgn)) + code.sign) & this.abh(14 downto 0); + + this.p23 := std_logic_vector(unsigned(p2) + unsigned(p3)); + + if this.shift = '0' then + if pm(47) = '1' and code.size = B16 then c := x"ffff" & pm; + else c := x"0000" & pm; end if; + else c := pm & x"0000"; + end if; + + -- accumulator + acc := std_logic_vector(unsigned(c) + unsigned((this.mach and to_slv(code.use_h, 32)) & this.macl)); + + -- saturate + sat := '1'; region := (others => '0'); + case this.result_op is + when IDENTITY => sat := '0'; + + when SATURATE64 => + if acc(63) = '0' and acc(62 downto 47) /= x"0000" then region(0) := '1'; + elsif acc(63) = '1' and acc(62 downto 47) /= x"ffff" then region(0) := '1'; end if; + + region(2 downto 1) := this.mach(31) & acc(63); + + if c(63) = '0' then + case region is + when "001" | "010" | "011" | "101" => acc := P48MAX; + when "111" => acc := N48MAX; + when others => sat := '0'; + end case; + else + case region is + when "001" => acc := P48MAX; + when "011" | "100" | "101" | "111" => acc := N48MAX; + when others => sat := '0'; + end case; + end if; + + when SATURATE32 => + region := this.macl(31) & acc(31) & '0'; + if c(31) = '0' then + case (region) is + when "010" => acc := P32MAX; + when others => sat := '0'; + end case; + else + case (region) is + when "100" => acc := N32MAX; + when others => sat := '0'; + end case; + end if; + end case; + + -- multiplier + this.abh := std_logic_vector(unsigned(ah) * unsigned(bh)); + + -- load the internal registers from the CPU + if slot = '1' then + if a.command /= NOP then + this.m2 := a.in2; + if a.command = MACL or a.command = MACW then this.mb := this.m1; end if; + end if; + + if a.wr_m1 = '1' then this.m1 := a.in1; end if; + end if; + + if slot = '1' and a.wr_mach = '1' then this.mach := a.in1; + elsif slot = '1' and (a.command = DMULSL or a.command = DMULUL) then this.mach := x"00000000"; + elsif this.state = MACWS1 and sat = '1' then this.mach := this.mach or x"00000001"; + elsif code.mach_en = '1' then this.mach := acc(63 downto 32); + end if; + + if slot = '1' and a.wr_macl = '1' then this.macl := a.in2; + elsif slot = '1' and a.command /= NOP and a.command /= MACL and a.command /= MACW then this.macl := x"00000000"; + elsif code.macl_en = '1' then this.macl := acc(31 downto 0); + end if; + + -- delayed versions of the control signals to delay for p23 pipeline register + this.state := code.state; + this.shift := code.shift; + + -- load the command from the CPU + if code.busy = '0' and slot = '1' then + this.result_op := IDENTITY; + this.state := a.command; + + if a.command = MACL then + if a.s = '1' then this.result_op := SATURATE64; end if; + elsif a.command = MACW then -- override start state, MACWS and MACW set different busy and mach_en values + if a.s = '1' then this.result_op := SATURATE32; this.state := MACWS; end if; + end if; + end if; + + this_c <= this; + end process; + + mult_r0 : process(clk, rst) + begin + if rst='1' then + this_r <= MULT_RESET; + elsif clk='1' and clk'event then + this_r <= this_c; + end if; + end process; + + -- drive the outputs + y.mach <= this_r.mach; + y.macl <= this_r.macl; +end stru; diff --git a/testsuite/synth/issue1122/mult_pkg.vhd b/testsuite/synth/issue1122/mult_pkg.vhd new file mode 100644 index 000000000..88dac9c7b --- /dev/null +++ b/testsuite/synth/issue1122/mult_pkg.vhd @@ -0,0 +1,115 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package mult_pkg is + type mult_state_t is (NOP, DMULSL, DMULSL1, DMULSL2, DMULUL, DMULUL1, DMULUL2, MACL, MACL1, MACL2, MACW, MACW1, MACWS, MACWS1, MULL, MULL1, MULL2, MULSW, MULSW1, MULUW, MULUW1); + type mult_result_op_t is (IDENTITY, SATURATE32, SATURATE64); + type mult_sela_t is ( M1, MB ); + + type mult_size_t is ( B16, B32 ); + constant P48MAX : std_logic_vector(63 downto 0) := x"00007fffffffffff"; + constant N48MAX : std_logic_vector(63 downto 0) := x"ffff800000000000"; + constant P32MAX : std_logic_vector(63 downto 0) := x"000000007fffffff"; + constant N32MAX : std_logic_vector(63 downto 0) := x"ffffffff80000000"; + + type mult_codeline_t is record + state : mult_state_t; + busy : std_logic; + sela : mult_sela_t; + shift : std_logic; + sign : integer range 0 to 1; + size : mult_size_t; + mach_en : std_logic; + macl_en : std_logic; + use_h : std_logic; + end record; + + type mult_microcode_t is array (mult_state_t) of mult_codeline_t; + + constant MULT_CODE : mult_microcode_t := ( +-- state busy sela shft sign size h_en l_en use_h + ( NOP, '0', M1, '0', 0, B16, '0', '0', '1' ), -- NOP + ( DMULSL1, '1', M1, '0', 1, B32, '0', '0', '1' ), -- DMULSL + ( DMULSL2, '1', M1, '1', 1, B32, '1', '1', '1' ), -- DMULSL1 + ( NOP, '0', M1, '1', 1, B32, '1', '1', '1' ), -- DMULSL2 + ( DMULUL1, '1', M1, '0', 0, B32, '0', '0', '1' ), -- DMULUL + ( DMULUL2, '1', M1, '1', 0, B32, '1', '1', '1' ), -- DMULUL1 + ( NOP, '0', M1, '1', 0, B32, '1', '1', '1' ), -- DMULUL2 + ( MACL1, '1', MB, '0', 1, B32, '0', '0', '1' ), -- MACL + ( MACL2, '1', MB, '1', 1, B32, '1', '1', '1' ), -- MACL1 + ( NOP, '0', MB, '1', 1, B32, '1', '1', '1' ), -- MACL2 + ( MACW1, '1', M1, '0', 1, B16, '0', '0', '1' ), -- MACW + ( NOP, '0', M1, '0', 1, B16, '1', '1', '1' ), -- MACW1 + ( MACWS1, '1', M1, '0', 1, B16, '0', '0', '0' ), -- MACWS + ( NOP, '0', M1, '0', 1, B16, '0', '1', '0' ), -- MACWS1 + ( MULL1, '1', M1, '0', 1, B32, '0', '0', '0' ), -- MULL + ( MULL2, '1', M1, '1', 1, B32, '0', '1', '0' ), -- MULL1 + ( NOP, '0', M1, '1', 1, B32, '0', '1', '0' ), -- MULL2 + ( MULSW1, '1', M1, '0', 1, B16, '0', '0', '0' ), -- MULSW + ( NOP, '0', M1, '0', 1, B16, '0', '1', '0' ), -- MULSW1 + ( MULUW1, '1', M1, '0', 0, B16, '0', '0', '0' ), -- MULUW + ( NOP, '0', M1, '0', 0, B16, '0', '1', '0' ) -- MULUW1 + ); + + type mult_i_t is record + wr_m1 : std_logic; + command : mult_state_t; + s : std_logic; + wr_mach : std_logic; + wr_macl : std_logic; + in1 : std_logic_vector(31 downto 0); + in2 : std_logic_vector(31 downto 0); + end record; + + type mult_o_t is record + mach : std_logic_vector(31 downto 0); + macl : std_logic_vector(31 downto 0); + busy : std_logic; + end record; + + type mult_reg_t is record + state : mult_state_t; + result_op : mult_result_op_t; + m1, m2, mb : std_logic_vector(31 downto 0); + p23 : std_logic_vector(31 downto 0); + mach, macl : std_logic_vector(31 downto 0); + shift : std_logic; + abh : std_logic_vector(46 downto 0); + end record; + + constant MULT_RESET : mult_reg_t := (state => NOP, + result_op => IDENTITY, + m1 => (others => '0'), + m2 => (others => '0'), + mb => (others => '0'), + p23 => (others => '0'), + mach => (others => '0'), + macl => (others => '0'), + shift => '0', + abh => (others => '0') + ); + + component mult is + + port ( + clk : in std_logic; + rst : in std_logic; + slot : in std_logic; + a : in mult_i_t; + y : out mult_o_t); + end component mult; + + function to_slv(b : std_logic; s : integer) return std_logic_vector; +end package; + +package body mult_pkg is + + function to_slv(b : std_logic; s : integer) return std_logic_vector is + variable r : std_logic_vector(s-1 downto 0); + begin + r := (others => b); + return r; + end function to_slv; + +end package body; diff --git a/testsuite/synth/issue1122/repro.vhdl b/testsuite/synth/issue1122/repro.vhdl new file mode 100644 index 000000000..a0dfd78ea --- /dev/null +++ b/testsuite/synth/issue1122/repro.vhdl @@ -0,0 +1,62 @@ +entity repro is + port (clk : bit; + rst : bit; + d : bit_vector (7 downto 0); + q : out bit_vector (7 downto 0)); +end repro; + +architecture behav of repro is + constant c : bit_vector (7 downto 0) := x"7e"; + signal s : bit_vector (7 downto 0) := c; +begin + process (clk) + begin + if rst = '1' then + s <= c; + elsif clk = '1' and clk'event then + s <= d; + end if; + end process; + + q <= s; +end behav; + +-- For this design: +-- %3:$o[8]{n7w8} := 8'uh7e +-- \s:$o[8]{n8w8} := $isignal{i7} ( +-- .$i: %8:$o[8]{n12w8} := $mux2{i11} ( +-- .$s: \rst{n2w1}, +-- .$i0: %7:$o[8]{n11w8} := $mux2{i10} ( +-- .$s: %6:$o{n10w1} := $edge{i9} ( +-- .$i: \clk{n1w1}), +-- .$i0: \s:$o{n8w8}, +-- .$i1: \d{n3w8}), +-- .$i1: %3:$o{n7w8}), +-- .$init: %3:$o{n7w8}) +-- \q := \s:$o{n8w8} + +-- For repro2: +-- \s:$o{n8w1} := $isignal{i7} ( +-- .$i: %9:$o{n13w1} := $mux2{i12} ( +-- .$s: \rst{n2w1}, +-- .$i0: %8:$o{n12w1} := $mux2{i11} ( +-- .$s: %7:$o{n11w1} := $edge{i10} ( +-- .$i: \clk{n1w1}), +-- .$i0: \s:$o{n8w1}, +-- .$i1: \d{n3w1}), +-- .$i1: %6:$o{n10w1} := 1'uh1), +-- .$init: %3:$o{n7w1} := 1'uh1) +-- \q := \s:$o{n8w1} + +--> + +-- %3:$o{n7w1} := 1'uh1 +-- \s:$o{n8w1} := $isignal{i7} ( +-- .$i: %10:$q{n14w1} := $iadff{i13} ( +-- .$clk: \clk{n1w1}, +-- .$d: \d{n3w1}, +-- .$rst: \rst{n2w1}, +-- .$rst_val: %6:$o{n10w1} := 1'uh1, +-- .$init: %3:$o{n7w1}), +-- .$init: %3:$o{n7w1}) +-- \q := \s:$o{n8w1} diff --git a/testsuite/synth/issue1122/repro2.vhdl b/testsuite/synth/issue1122/repro2.vhdl new file mode 100644 index 000000000..7492e36c9 --- /dev/null +++ b/testsuite/synth/issue1122/repro2.vhdl @@ -0,0 +1,22 @@ +entity repro2 is + port (clk : bit; + rst : bit; + d : bit; + q : out bit); +end repro2; + +architecture behav of repro2 is + constant c : bit := '1'; + signal s : bit := c; +begin + process (clk) + begin + if rst = '1' then + s <= c; + elsif clk = '1' and clk'event then + s <= d; + end if; + end process; + + q <= s; +end behav; diff --git a/testsuite/synth/issue1122/testsuite.sh b/testsuite/synth/issue1122/testsuite.sh new file mode 100755 index 000000000..ad74b19cc --- /dev/null +++ b/testsuite/synth/issue1122/testsuite.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +. ../../testenv.sh + +synth mult.vhd mult_pkg.vhd -e > syn_mult.vhdl +analyze mult_pkg.vhd syn_mult.vhdl +clean + +for t in repro repro2; do + synth $t.vhdl -e $t > syn_$t.vhdl + analyze syn_$t.vhdl + clean +done + +echo "Test successful" |