mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-29 13:32:48 +00:00
The goal is to have the icache fit in BRAM by latching the output into a register. In order to avoid timing issues , we need to give the BRAM a full cycle on reads, and thus we souce the BRAM address directly from fetch1 latched NIA. (Note: This will be problematic if/when we want to hash the address, we'll probably be better off having fetch1 latch a fully hashed address along with the normal one, so the icache can use the former to address the BRAM and pass the latter along) One difficulty is that we cannot really stall the icache without adding more combo logic that would break the "one full cycle" BRAM model. This means that on stalls from decode, by the time we stall fetch1, it has already gone to the next address, which the icache is already latching. We work around this by having a "stash" buffer in fetch2 that will stash away the icache output on a stall, and override the output of the icache with the content of the stash buffer when unstalling. This requires a rewrite of the stop/step debug logic as well. We now do most of the hard work in fetch1 which makes more sense. Note: Vivado is still not inferring an built-in output register for the BRAMs. I don't want to add another cycle... I don't fully understand why it wouldn't be able to treat current_row as such but clearly it won't. At least the timing seems good enough now for 100Mhz, possibly more. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
224 lines
8.1 KiB
VHDL
224 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 Fetch1ToIcacheType is record
|
|
req: std_ulogic;
|
|
stop_mark: std_ulogic;
|
|
nia: std_ulogic_vector(63 downto 0);
|
|
end record;
|
|
|
|
type IcacheToFetch2Type 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;
|
|
|
|
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 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);
|
|
read_data3: std_ulogic_vector(63 downto 0);
|
|
cr: std_ulogic_vector(31 downto 0);
|
|
lr: std_ulogic;
|
|
rc: std_ulogic;
|
|
invert_a: std_ulogic;
|
|
input_carry: carry_in_t;
|
|
output_carry: std_ulogic;
|
|
input_cr: std_ulogic;
|
|
output_cr: std_ulogic;
|
|
is_32bit: std_ulogic;
|
|
is_signed: std_ulogic;
|
|
insn: std_ulogic_vector(31 downto 0);
|
|
end record;
|
|
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
|
|
(valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', invert_a => '0',
|
|
input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0',
|
|
is_32bit => '0', is_signed => '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'));
|
|
end common;
|
|
|
|
package body common is
|
|
end common;
|