1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-02-14 11:54:28 +00:00
Files
antonblanchard.microwatt/common.vhdl
Paul Mackerras 25b9450475 divider: Do absolute-value ops in divider instead of decode
This moves the negation of negative operands for signed divide and
modulus operations out of the decode2 stage and into the divider.
If either of the operands for a signed divide or modulus operation
is negative, the divider now takes an extra cycle to negate the
operands that are negative.

The interface to the divider now has an 'is_signed' signal rather
than a 'neg_result' signal, and the dividend and divisor can be
negative, so divider_tb had to be updated for the new interface.

The reason for doing this is that one of the worst timing violations
on the Arty A7-100 at 100MHz involved the carry chain in the adders
that did the negation of the dividend and divisor in the decode stage.
Moving the negations to a separate cycle fixes that and also seems to
reduce the total number of slice LUTs used.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-09-28 08:55:08 +10:00

225 lines
8.1 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
library work;
use work.decode_types.all;
package common is
type ctrl_t is record
lr: std_ulogic_vector(63 downto 0);
ctr: std_ulogic_vector(63 downto 0);
tb: std_ulogic_vector(63 downto 0);
carry: std_ulogic;
end record;
type Fetch1ToFetch2Type is record
nia: std_ulogic_vector(63 downto 0);
pipe_stop : std_ulogic;
end record;
type Fetch2ToDecode1Type is record
valid: std_ulogic;
stop_mark : std_ulogic;
nia: std_ulogic_vector(63 downto 0);
insn: std_ulogic_vector(31 downto 0);
end record;
constant Fetch2ToDecode1Init : Fetch2ToDecode1Type := (valid => '0', stop_mark => '0', others => (others => '0'));
type Decode1ToDecode2Type is record
valid: std_ulogic;
stop_mark : std_ulogic;
nia: std_ulogic_vector(63 downto 0);
insn: std_ulogic_vector(31 downto 0);
decode: decode_rom_t;
end record;
constant Decode1ToDecode2Init : Decode1ToDecode2Type := (valid => '0', stop_mark => '0', decode => decode_rom_init, others => (others => '0'));
type Fetch2ToIcacheType is record
req: std_ulogic;
addr: std_ulogic_vector(63 downto 0);
end record;
type IcacheToFetch2Type is record
ack: std_ulogic;
insn: std_ulogic_vector(31 downto 0);
end record;
type Decode2ToExecute1Type is record
valid: std_ulogic;
insn_type: insn_type_t;
nia: std_ulogic_vector(63 downto 0);
write_reg: std_ulogic_vector(4 downto 0);
read_reg1: std_ulogic_vector(4 downto 0);
read_reg2: std_ulogic_vector(4 downto 0);
read_data1: std_ulogic_vector(63 downto 0);
read_data2: std_ulogic_vector(63 downto 0);
const1: std_ulogic_vector(7 downto 0);
const2: std_ulogic_vector(5 downto 0);
const3: std_ulogic_vector(4 downto 0);
cr: std_ulogic_vector(31 downto 0);
lr: std_ulogic;
rc: std_ulogic;
input_carry: std_ulogic;
output_carry: std_ulogic;
input_cr: std_ulogic;
output_cr: std_ulogic;
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type := (valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', input_carry => '0', output_carry => '0', input_cr => '0', output_cr => '0', others => (others => '0'));
type Decode2ToMultiplyType is record
valid: std_ulogic;
insn_type: insn_type_t;
write_reg: std_ulogic_vector(4 downto 0);
data1: std_ulogic_vector(64 downto 0);
data2: std_ulogic_vector(64 downto 0);
rc: std_ulogic;
end record;
constant Decode2ToMultiplyInit : Decode2ToMultiplyType := (valid => '0', insn_type => OP_ILLEGAL, rc => '0', others => (others => '0'));
type Decode2ToDividerType is record
valid: std_ulogic;
write_reg: std_ulogic_vector(4 downto 0);
dividend: std_ulogic_vector(63 downto 0);
divisor: std_ulogic_vector(63 downto 0);
is_signed: std_ulogic;
is_32bit: std_ulogic;
is_extended: std_ulogic;
is_modulus: std_ulogic;
rc: std_ulogic;
end record;
constant Decode2ToDividerInit: Decode2ToDividerType := (valid => '0', is_signed => '0', is_32bit => '0', is_extended => '0', is_modulus => '0', rc => '0', others => (others => '0'));
type Decode2ToRegisterFileType is record
read1_enable : std_ulogic;
read1_reg : std_ulogic_vector(4 downto 0);
read2_enable : std_ulogic;
read2_reg : std_ulogic_vector(4 downto 0);
read3_enable : std_ulogic;
read3_reg : std_ulogic_vector(4 downto 0);
end record;
type RegisterFileToDecode2Type is record
read1_data : std_ulogic_vector(63 downto 0);
read2_data : std_ulogic_vector(63 downto 0);
read3_data : std_ulogic_vector(63 downto 0);
end record;
type Decode2ToCrFileType is record
read : std_ulogic;
end record;
type CrFileToDecode2Type is record
read_cr_data : std_ulogic_vector(31 downto 0);
end record;
type Execute1ToFetch1Type is record
redirect: std_ulogic;
redirect_nia: std_ulogic_vector(63 downto 0);
end record;
constant Execute1ToFetch1TypeInit : Execute1ToFetch1Type := (redirect => '0', others => (others => '0'));
type Decode2ToLoadstore1Type is record
valid : std_ulogic;
load : std_ulogic; -- is this a load or store
addr1 : std_ulogic_vector(63 downto 0);
addr2 : std_ulogic_vector(63 downto 0);
data : std_ulogic_vector(63 downto 0); -- data to write, unused for read
write_reg : std_ulogic_vector(4 downto 0); -- read data goes to this register
length : std_ulogic_vector(3 downto 0);
byte_reverse : std_ulogic;
sign_extend : std_ulogic; -- do we need to sign extend?
update : std_ulogic; -- is this an update instruction?
update_reg : std_ulogic_vector(4 downto 0); -- if so, the register to update
end record;
constant Decode2ToLoadstore1Init : Decode2ToLoadstore1Type := (valid => '0', load => '0', byte_reverse => '0', sign_extend => '0', update => '0', others => (others => '0'));
type Loadstore1ToLoadstore2Type is record
valid : std_ulogic;
load : std_ulogic;
addr : std_ulogic_vector(63 downto 0);
data : std_ulogic_vector(63 downto 0);
write_reg : std_ulogic_vector(4 downto 0);
length : std_ulogic_vector(3 downto 0);
byte_reverse : std_ulogic;
sign_extend : std_ulogic;
update : std_ulogic;
update_reg : std_ulogic_vector(4 downto 0);
end record;
type Loadstore2ToWritebackType is record
valid : std_ulogic;
write_enable: std_ulogic;
write_reg : std_ulogic_vector(4 downto 0);
write_data : std_ulogic_vector(63 downto 0);
end record;
constant Loadstore2ToWritebackInit : Loadstore2ToWritebackType := (valid => '0', write_enable => '0', others => (others => '0'));
type Execute1ToExecute2Type is record
valid: std_ulogic;
write_enable : std_ulogic;
write_reg: std_ulogic_vector(4 downto 0);
write_data: std_ulogic_vector(63 downto 0);
write_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
rc : std_ulogic;
end record;
constant Execute1ToExecute2Init : Execute1ToExecute2Type := (valid => '0', write_enable => '0', write_cr_enable => '0', rc => '0', others => (others => '0'));
type Execute2ToWritebackType is record
valid: std_ulogic;
write_enable : std_ulogic;
write_reg: std_ulogic_vector(4 downto 0);
write_data: std_ulogic_vector(63 downto 0);
write_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
end record;
constant Execute2ToWritebackInit : Execute2ToWritebackType := (valid => '0', write_enable => '0', write_cr_enable => '0', others => (others => '0'));
type MultiplyToWritebackType is record
valid: std_ulogic;
write_reg_enable : std_ulogic;
write_reg_nr: std_ulogic_vector(4 downto 0);
write_reg_data: std_ulogic_vector(63 downto 0);
write_cr_enable: std_ulogic;
write_cr_mask: std_ulogic_vector(7 downto 0);
write_cr_data: std_ulogic_vector(31 downto 0);
end record;
constant MultiplyToWritebackInit : MultiplyToWritebackType := (valid => '0', write_reg_enable => '0', write_cr_enable => '0', others => (others => '0'));
type DividerToWritebackType is record
valid: std_ulogic;
write_reg_enable : std_ulogic;
write_reg_nr: std_ulogic_vector(4 downto 0);
write_reg_data: std_ulogic_vector(63 downto 0);
write_cr_enable: std_ulogic;
write_cr_mask: std_ulogic_vector(7 downto 0);
write_cr_data: std_ulogic_vector(31 downto 0);
end record;
constant DividerToWritebackInit : DividerToWritebackType := (valid => '0', write_reg_enable => '0', write_cr_enable => '0', others => (others => '0'));
type WritebackToRegisterFileType is record
write_reg : std_ulogic_vector(4 downto 0);
write_data : std_ulogic_vector(63 downto 0);
write_enable : std_ulogic;
end record;
constant WritebackToRegisterFileInit : WritebackToRegisterFileType := (write_enable => '0', others => (others => '0'));
type WritebackToCrFileType is record
write_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
end record;
constant WritebackToCrFileInit : WritebackToCrFileType := (write_cr_enable => '0', others => (others => '0'));
-- Would prefer not to expose this outside the register file, but ghdl
-- doesn't support external names
type regfile is array(0 to 32) of std_ulogic_vector(63 downto 0);
end common;
package body common is
end common;