From f7b855dfc36cd1d916e019ab31edbcc679077255 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 28 Sep 2020 14:04:08 +1000 Subject: [PATCH] execute1: Improve timing on comparisons Using the main adder for comparisons has the disadvantage of creating a long path from the CA/OV bit forwarding to v.busy via the carry input of the adder, the comparison result, and determining whether a trap instruction would trap. Instead we now have dedicated comparators for the high and low words of a_in vs. b_in, and combine their results to get the signed and unsigned comparison results. Signed-off-by: Paul Mackerras --- execute1.vhdl | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/execute1.vhdl b/execute1.vhdl index 6a27ee8..3385455 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -356,6 +356,8 @@ begin variable zerohi, zerolo : std_ulogic; variable msb_a, msb_b : std_ulogic; variable a_lt : std_ulogic; + variable a_lt_lo : std_ulogic; + variable a_lt_hi : std_ulogic; variable lv : Execute1ToLoadstore1Type; variable irq_valid : std_ulogic; variable exception : std_ulogic; @@ -612,24 +614,32 @@ begin -- values are equal trapval := "00100"; else + a_lt_lo := '0'; + a_lt_hi := '0'; + if unsigned(a_in(30 downto 0)) < unsigned(b_in(30 downto 0)) then + a_lt_lo := '1'; + end if; + if unsigned(a_in(62 downto 31)) < unsigned(b_in(62 downto 31)) then + a_lt_hi := '1'; + end if; if l = '1' then -- 64-bit comparison msb_a := a_in(63); msb_b := b_in(63); + a_lt := a_lt_hi or (zerohi and (a_in(31) xnor b_in(31)) and a_lt_lo); else -- 32-bit comparison msb_a := a_in(31); msb_b := b_in(31); + a_lt := a_lt_lo; end if; if msb_a /= msb_b then - -- Subtraction might overflow, but - -- comparison is clear from MSB difference. + -- Comparison is clear from MSB difference. -- for signed, 0 is greater; for unsigned, 1 is greater trapval := msb_a & msb_b & '0' & msb_b & msb_a; else - -- Subtraction cannot overflow since MSBs are equal. - -- carry = 1 indicates RA is smaller (signed or unsigned) - a_lt := (not l and carry_32) or (l and carry_64); + -- MSBs are equal, so signed and unsigned comparisons give the + -- same answer. trapval := a_lt & not a_lt & '0' & a_lt & not a_lt; end if; end if;