use ieee.numeric_std.all;
library work;
+use work.utils.all;
use work.decode_types.all;
package common is
constant MSR_FE1 : integer := (63 - 55); -- Floating Exception mode
constant MSR_IR : integer := (63 - 58); -- Instruction Relocation
constant MSR_DR : integer := (63 - 59); -- Data Relocation
+ constant MSR_PMM : integer := (63 - 61); -- Performance Monitor Mark
constant MSR_RI : integer := (63 - 62); -- Recoverable Interrupt
constant MSR_LE : integer := (63 - 63); -- Little Endian
constant SPR_HSPRG0 : spr_num_t := 304;
constant SPR_HSPRG1 : spr_num_t := 305;
constant SPR_PID : spr_num_t := 48;
- constant SPR_PRTBL : spr_num_t := 720;
+ constant SPR_PTCR : spr_num_t := 464;
constant SPR_PVR : spr_num_t := 287;
+ -- PMU registers
+ constant SPR_UPMC1 : spr_num_t := 771;
+ constant SPR_UPMC2 : spr_num_t := 772;
+ constant SPR_UPMC3 : spr_num_t := 773;
+ constant SPR_UPMC4 : spr_num_t := 774;
+ constant SPR_UPMC5 : spr_num_t := 775;
+ constant SPR_UPMC6 : spr_num_t := 776;
+ constant SPR_UMMCR0 : spr_num_t := 779;
+ constant SPR_UMMCR1 : spr_num_t := 782;
+ constant SPR_UMMCR2 : spr_num_t := 769;
+ constant SPR_UMMCRA : spr_num_t := 770;
+ constant SPR_USIER : spr_num_t := 768;
+ constant SPR_USIAR : spr_num_t := 780;
+ constant SPR_USDAR : spr_num_t := 781;
+ constant SPR_PMC1 : spr_num_t := 787;
+ constant SPR_PMC2 : spr_num_t := 788;
+ constant SPR_PMC3 : spr_num_t := 789;
+ constant SPR_PMC4 : spr_num_t := 790;
+ constant SPR_PMC5 : spr_num_t := 791;
+ constant SPR_PMC6 : spr_num_t := 792;
+ constant SPR_MMCR0 : spr_num_t := 795;
+ constant SPR_MMCR1 : spr_num_t := 798;
+ constant SPR_MMCR2 : spr_num_t := 785;
+ constant SPR_MMCRA : spr_num_t := 786;
+ constant SPR_SIER : spr_num_t := 784;
+ constant SPR_SIAR : spr_num_t := 796;
+ constant SPR_SDAR : spr_num_t := 797;
+
-- GPR indices in the register file (GPR only)
subtype gpr_index_t is std_ulogic_vector(4 downto 0);
constant FPSCR_NI : integer := 63 - 61;
constant FPSCR_RN : integer := 63 - 63;
- type irq_state_t is (WRITE_SRR0, WRITE_SRR1);
+ -- Real addresses
+ -- REAL_ADDR_BITS is the number of real address bits that we store
+ constant REAL_ADDR_BITS : positive := 56;
+ subtype real_addr_t is std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
+ function addr_to_real(addr: std_ulogic_vector(63 downto 0)) return real_addr_t;
+
+ -- Used for tracking instruction completion and pending register writes
+ constant TAG_COUNT : positive := 4;
+ constant TAG_NUMBER_BITS : natural := log2(TAG_COUNT);
+ subtype tag_number_t is integer range 0 to TAG_COUNT - 1;
+ subtype tag_index_t is unsigned(TAG_NUMBER_BITS - 1 downto 0);
+ type instr_tag_t is record
+ tag : tag_number_t;
+ valid : std_ulogic;
+ end record;
+ constant instr_tag_init : instr_tag_t := (tag => 0, valid => '0');
+ function tag_match(tag1 : instr_tag_t; tag2 : instr_tag_t) return boolean;
+
+ subtype intr_vector_t is integer range 0 to 16#fff#;
-- For now, fixed 16 sources, make this either a parametric
-- package of some sort or an unconstrainted array.
dec: std_ulogic_vector(63 downto 0);
msr: std_ulogic_vector(63 downto 0);
cfar: std_ulogic_vector(63 downto 0);
- irq_state : irq_state_t;
- srr1: std_ulogic_vector(63 downto 0);
end record;
type Fetch1ToIcacheType is record
big_endian : std_ulogic;
stop_mark: std_ulogic;
sequential: std_ulogic;
+ predicted : std_ulogic;
+ pred_ntaken : std_ulogic;
nia: std_ulogic_vector(63 downto 0);
end record;
fetch_failed: std_ulogic;
nia: std_ulogic_vector(63 downto 0);
insn: std_ulogic_vector(31 downto 0);
+ big_endian: std_ulogic;
+ next_predicted: std_ulogic;
+ next_pred_ntaken: std_ulogic;
+ end record;
+
+ type IcacheEventType is record
+ icache_miss : std_ulogic;
+ itlb_miss_resolved : std_ulogic;
end record;
type Decode1ToDecode2Type is record
insn: std_ulogic_vector(31 downto 0);
ispr1: gspr_index_t; -- (G)SPR used for branch condition (CTR) or mfspr
ispr2: gspr_index_t; -- (G)SPR used for branch target (CTR, LR, TAR)
+ ispro: gspr_index_t; -- (G)SPR written with LR or CTR
decode: decode_rom_t;
br_pred: std_ulogic; -- Branch was predicted to be taken
+ big_endian: std_ulogic;
end record;
constant Decode1ToDecode2Init : Decode1ToDecode2Type :=
(valid => '0', stop_mark => '0', nia => (others => '0'), insn => (others => '0'),
- ispr1 => (others => '0'), ispr2 => (others => '0'), decode => decode_rom_init, br_pred => '0');
+ ispr1 => (others => '0'), ispr2 => (others => '0'), ispro => (others => '0'),
+ decode => decode_rom_init, br_pred => '0', big_endian => '0');
type Decode1ToFetch1Type is record
redirect : std_ulogic;
redirect_nia : std_ulogic_vector(63 downto 0);
end record;
+ type bypass_data_t is record
+ tag : instr_tag_t;
+ data : std_ulogic_vector(63 downto 0);
+ end record;
+ constant bypass_data_init : bypass_data_t := (tag => instr_tag_init, data => (others => '0'));
+
+ type cr_bypass_data_t is record
+ tag : instr_tag_t;
+ data : std_ulogic_vector(31 downto 0);
+ end record;
+ constant cr_bypass_data_init : cr_bypass_data_t := (tag => instr_tag_init, data => (others => '0'));
+
type Decode2ToExecute1Type is record
valid: std_ulogic;
unit : unit_t;
+ fac : facility_t;
insn_type: insn_type_t;
nia: std_ulogic_vector(63 downto 0);
+ instr_tag : instr_tag_t;
write_reg: gspr_index_t;
+ write_reg_enable: std_ulogic;
read_reg1: gspr_index_t;
read_reg2: gspr_index_t;
read_data1: std_ulogic_vector(63 downto 0);
read_data2: std_ulogic_vector(63 downto 0);
read_data3: std_ulogic_vector(63 downto 0);
- bypass_data1: std_ulogic;
- bypass_data2: std_ulogic;
- bypass_data3: std_ulogic;
cr: std_ulogic_vector(31 downto 0);
- bypass_cr : std_ulogic;
xerc: xer_common_t;
lr: std_ulogic;
+ br_abs: std_ulogic;
rc: std_ulogic;
oe: std_ulogic;
invert_a: std_ulogic;
+ addm1 : std_ulogic;
invert_out: std_ulogic;
input_carry: carry_in_t;
output_carry: std_ulogic;
input_cr: std_ulogic;
output_cr: std_ulogic;
+ output_xer: std_ulogic;
is_32bit: std_ulogic;
is_signed: std_ulogic;
insn: std_ulogic_vector(31 downto 0);
update : std_ulogic; -- is this an update instruction?
reserve : std_ulogic; -- set for larx/stcx
br_pred : std_ulogic;
+ result_sel : std_ulogic_vector(2 downto 0); -- select source of result
+ sub_select : std_ulogic_vector(2 downto 0); -- sub-result selection
+ repeat : std_ulogic; -- set if instruction is cracked into two ops
+ second : std_ulogic; -- set if this is the second op
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
- (valid => '0', unit => NONE, insn_type => OP_ILLEGAL, bypass_data1 => '0', bypass_data2 => '0', bypass_data3 => '0',
- bypass_cr => '0', lr => '0', rc => '0', oe => '0', invert_a => '0',
- invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0',
+ (valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
+ write_reg_enable => '0',
+ lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0', addm1 => '0',
+ invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0',
+ output_cr => '0', output_xer => '0',
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'));
+ 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'),
+ result_sel => "000", sub_select => "000",
+ repeat => '0', second => '0', others => (others => '0'));
type MultiplyInputType is record
valid: std_ulogic;
is_extended => '0', is_modulus => '0',
neg_result => '0', others => (others => '0'));
+ type PMUEventType is record
+ no_instr_avail : std_ulogic;
+ dispatch : std_ulogic;
+ ext_interrupt : std_ulogic;
+ instr_complete : std_ulogic;
+ fp_complete : std_ulogic;
+ ld_complete : std_ulogic;
+ st_complete : std_ulogic;
+ br_taken_complete : std_ulogic;
+ br_mispredict : std_ulogic;
+ ipref_discard : std_ulogic;
+ itlb_miss : std_ulogic;
+ itlb_miss_resolved : std_ulogic;
+ icache_miss : std_ulogic;
+ dc_miss_resolved : std_ulogic;
+ dc_load_miss : std_ulogic;
+ dc_ld_miss_resolved : std_ulogic;
+ dc_store_miss : std_ulogic;
+ dtlb_miss : std_ulogic;
+ dtlb_miss_resolved : std_ulogic;
+ ld_miss_nocache : std_ulogic;
+ ld_fill_nocache : std_ulogic;
+ end record;
+ constant PMUEventInit : PMUEventType := (others => '0');
+
+ type Execute1ToPMUType is record
+ mfspr : std_ulogic;
+ mtspr : std_ulogic;
+ spr_num : std_ulogic_vector(4 downto 0);
+ spr_val : std_ulogic_vector(63 downto 0);
+ tbbits : std_ulogic_vector(3 downto 0); -- event bits from timebase
+ pmm_msr : std_ulogic; -- PMM bit from MSR
+ pr_msr : std_ulogic; -- PR bit from MSR
+ run : std_ulogic;
+ nia : std_ulogic_vector(63 downto 0);
+ addr : std_ulogic_vector(63 downto 0);
+ addr_v : std_ulogic;
+ occur : PMUEventType;
+ end record;
+
+ type PMUToExecute1Type is record
+ spr_val : std_ulogic_vector(63 downto 0);
+ intr : std_ulogic;
+ end record;
+
type Decode2ToRegisterFileType is record
read1_enable : std_ulogic;
read1_reg : gspr_index_t;
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);
+ 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_xerc_data : xer_common_t;
end record;
- type Execute1ToFetch1Type is record
- redirect: std_ulogic;
- virt_mode: std_ulogic;
- priv_mode: std_ulogic;
- big_endian: std_ulogic;
- mode_32bit: std_ulogic;
- redirect_nia: std_ulogic_vector(63 downto 0);
- end record;
- constant Execute1ToFetch1Init : Execute1ToFetch1Type := (redirect => '0', virt_mode => '0',
- priv_mode => '0', big_endian => '0',
- mode_32bit => '0', others => (others => '0'));
-
type Execute1ToLoadstore1Type is record
valid : std_ulogic;
op : insn_type_t; -- what ld/st or m[tf]spr or TLB op to do
nia : std_ulogic_vector(63 downto 0);
insn : std_ulogic_vector(31 downto 0);
+ instr_tag : instr_tag_t;
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
byte_reverse : std_ulogic;
sign_extend : std_ulogic; -- do we need to sign extend?
update : std_ulogic; -- is this an update instruction?
- update_reg : gpr_index_t; -- if so, the register to update
xerc : xer_common_t;
reserve : std_ulogic; -- set for larx/stcx.
rc : std_ulogic; -- set for stcx.
priv_mode : std_ulogic; -- privileged mode (MSR[PR] = 0)
mode_32bit : std_ulogic; -- trim addresses to 32 bits
is_32bit : std_ulogic;
- end record;
- constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type := (valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0',
- sign_extend => '0', update => '0', xerc => xerc_init,
- reserve => '0', rc => '0', virt_mode => '0', priv_mode => '0',
- nia => (others => '0'), insn => (others => '0'),
- addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'),
- write_reg => (others => '0'), length => (others => '0'),
- mode_32bit => '0', is_32bit => '0', others => (others => '0'));
+ repeat : std_ulogic;
+ second : std_ulogic;
+ msr : std_ulogic_vector(63 downto 0);
+ end record;
+ constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type :=
+ (valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0',
+ sign_extend => '0', update => '0', xerc => xerc_init,
+ reserve => '0', rc => '0', virt_mode => '0', priv_mode => '0',
+ nia => (others => '0'), insn => (others => '0'),
+ instr_tag => instr_tag_init,
+ addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'),
+ write_reg => (others => '0'),
+ length => (others => '0'),
+ mode_32bit => '0', is_32bit => '0',
+ repeat => '0', second => '0',
+ msr => (others => '0'));
type Loadstore1ToExecute1Type is record
busy : std_ulogic;
- exception : std_ulogic;
- alignment : std_ulogic;
- invalid : std_ulogic;
- perm_error : std_ulogic;
- rc_error : std_ulogic;
- badtree : std_ulogic;
- segment_fault : std_ulogic;
- instr_fault : std_ulogic;
+ in_progress : std_ulogic;
+ interrupt : std_ulogic;
end record;
type Loadstore1ToDcacheType is record
valid : std_ulogic;
+ hold : std_ulogic;
load : std_ulogic; -- is this a load
dcbz : std_ulogic;
nc : std_ulogic;
reserve : std_ulogic;
+ atomic : std_ulogic; -- part of a multi-transfer atomic op
+ atomic_last : std_ulogic;
virt_mode : std_ulogic;
priv_mode : std_ulogic;
addr : std_ulogic_vector(63 downto 0);
- data : std_ulogic_vector(63 downto 0);
+ data : std_ulogic_vector(63 downto 0); -- valid the cycle after .valid = 1
byte_sel : std_ulogic_vector(7 downto 0);
end record;
cache_paradox : std_ulogic;
end record;
+ type DcacheEventType is record
+ load_miss : std_ulogic;
+ store_miss : std_ulogic;
+ dcache_refill : std_ulogic;
+ dtlb_miss : std_ulogic;
+ dtlb_miss_resolved : std_ulogic;
+ end record;
+
type Loadstore1ToMmuType is record
valid : std_ulogic;
tlbie : std_ulogic;
type Loadstore1ToWritebackType is record
valid : std_ulogic;
+ instr_tag : instr_tag_t;
write_enable: std_ulogic;
write_reg : gspr_index_t;
write_data : std_ulogic_vector(63 downto 0);
xerc : xer_common_t;
rc : std_ulogic;
store_done : std_ulogic;
+ interrupt : std_ulogic;
+ intr_vec : intr_vector_t;
+ srr0: std_ulogic_vector(63 downto 0);
+ srr1: std_ulogic_vector(15 downto 0);
+ end record;
+ constant Loadstore1ToWritebackInit : Loadstore1ToWritebackType :=
+ (valid => '0', instr_tag => instr_tag_init, write_enable => '0',
+ write_reg => (others => '0'), write_data => (others => '0'),
+ xerc => xerc_init, rc => '0', store_done => '0',
+ interrupt => '0', intr_vec => 0,
+ srr0 => (others => '0'), srr1 => (others => '0'));
+
+ type Loadstore1EventType is record
+ load_complete : std_ulogic;
+ store_complete : std_ulogic;
+ itlb_miss : std_ulogic;
end record;
- constant Loadstore1ToWritebackInit : Loadstore1ToWritebackType := (valid => '0', write_enable => '0', xerc => xerc_init,
- rc => '0', store_done => '0', write_data => (others => '0'), others => (others => '0'));
type Execute1ToWritebackType is record
valid: std_ulogic;
+ instr_tag : instr_tag_t;
rc : std_ulogic;
mode_32bit : std_ulogic;
write_enable : std_ulogic;
write_cr_data : std_ulogic_vector(31 downto 0);
write_xerc_enable : std_ulogic;
xerc : xer_common_t;
- exc_write_enable : std_ulogic;
- exc_write_reg : gspr_index_t;
- exc_write_data : std_ulogic_vector(63 downto 0);
- end record;
- constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', rc => '0', mode_32bit => '0', write_enable => '0',
- write_cr_enable => '0', exc_write_enable => '0',
- write_xerc_enable => '0', xerc => xerc_init,
- write_data => (others => '0'), write_cr_mask => (others => '0'),
- write_cr_data => (others => '0'), write_reg => (others => '0'),
- exc_write_reg => (others => '0'), exc_write_data => (others => '0'));
+ interrupt : std_ulogic;
+ intr_vec : intr_vector_t;
+ redirect: std_ulogic;
+ redir_mode: std_ulogic_vector(3 downto 0);
+ last_nia: std_ulogic_vector(63 downto 0);
+ br_offset: std_ulogic_vector(63 downto 0);
+ br_last: std_ulogic;
+ br_taken: std_ulogic;
+ abs_br: std_ulogic;
+ srr1: std_ulogic_vector(15 downto 0);
+ msr: std_ulogic_vector(63 downto 0);
+ end record;
+ constant Execute1ToWritebackInit : Execute1ToWritebackType :=
+ (valid => '0', instr_tag => instr_tag_init, rc => '0', mode_32bit => '0',
+ write_enable => '0', write_cr_enable => '0',
+ write_xerc_enable => '0', xerc => xerc_init,
+ write_data => (others => '0'), write_cr_mask => (others => '0'),
+ write_cr_data => (others => '0'), write_reg => (others => '0'),
+ interrupt => '0', intr_vec => 0, redirect => '0', redir_mode => "0000",
+ last_nia => (others => '0'), br_offset => (others => '0'),
+ br_last => '0', br_taken => '0', abs_br => '0',
+ srr1 => (others => '0'), msr => (others => '0'));
type Execute1ToFPUType is record
valid : std_ulogic;
op : insn_type_t;
nia : std_ulogic_vector(63 downto 0);
+ itag : instr_tag_t;
insn : std_ulogic_vector(31 downto 0);
single : std_ulogic;
fe_mode : std_ulogic_vector(1 downto 0);
out_cr : std_ulogic;
end record;
constant Execute1ToFPUInit : Execute1ToFPUType := (valid => '0', op => OP_ILLEGAL, nia => (others => '0'),
+ itag => instr_tag_init,
insn => (others => '0'), fe_mode => "00", rc => '0',
fra => (others => '0'), frb => (others => '0'),
frc => (others => '0'), frt => (others => '0'),
type FPUToExecute1Type is record
busy : std_ulogic;
exception : std_ulogic;
- interrupt : std_ulogic;
- illegal : std_ulogic;
end record;
+ constant FPUToExecute1Init : FPUToExecute1Type := (others => '0');
type FPUToWritebackType is record
valid : std_ulogic;
+ interrupt : std_ulogic;
+ instr_tag : instr_tag_t;
write_enable : std_ulogic;
write_reg : gspr_index_t;
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;
+ intr_vec : intr_vector_t;
+ srr0 : std_ulogic_vector(63 downto 0);
+ srr1 : std_ulogic_vector(15 downto 0);
+ end record;
+ constant FPUToWritebackInit : FPUToWritebackType :=
+ (valid => '0', interrupt => '0', instr_tag => instr_tag_init,
+ write_enable => '0', write_reg => (others => '0'),
+ write_cr_enable => '0', write_cr_mask => (others => '0'),
+ write_cr_data => (others => '0'),
+ intr_vec => 0, srr1 => (others => '0'),
+ others => (others => '0'));
type DividerToExecute1Type is record
valid: std_ulogic;
constant DividerToExecute1Init : DividerToExecute1Type := (valid => '0', overflow => '0',
others => (others => '0'));
+ type WritebackToFetch1Type is record
+ redirect: std_ulogic;
+ virt_mode: std_ulogic;
+ priv_mode: std_ulogic;
+ big_endian: std_ulogic;
+ mode_32bit: std_ulogic;
+ redirect_nia: std_ulogic_vector(63 downto 0);
+ br_nia : std_ulogic_vector(63 downto 0);
+ br_last : std_ulogic;
+ br_taken : std_ulogic;
+ end record;
+ constant WritebackToFetch1Init : WritebackToFetch1Type :=
+ (redirect => '0', virt_mode => '0', priv_mode => '0', big_endian => '0',
+ mode_32bit => '0', redirect_nia => (others => '0'),
+ br_last => '0', br_taken => '0', br_nia => (others => '0'));
+
type WritebackToRegisterFileType is record
write_reg : gspr_index_t;
write_data : std_ulogic_vector(63 downto 0);
write_enable : std_ulogic;
end record;
- constant WritebackToRegisterFileInit : WritebackToRegisterFileType := (write_enable => '0', write_data => (others => '0'), others => (others => '0'));
+ constant WritebackToRegisterFileInit : WritebackToRegisterFileType :=
+ (write_enable => '0', write_data => (others => '0'), others => (others => '0'));
type WritebackToCrFileType is record
write_cr_enable : std_ulogic;
write_cr_mask => (others => '0'),
write_cr_data => (others => '0'));
+ type WritebackEventType is record
+ instr_complete : std_ulogic;
+ fp_complete : std_ulogic;
+ end record;
+
end common;
package body common is
begin
case spr is
when SPR_LR =>
- n := 0;
+ n := 0; -- N.B. decode2 relies on this specific value
when SPR_CTR =>
- n:= 1;
+ n := 1; -- N.B. decode2 relies on this specific value
when SPR_SRR0 =>
n := 2;
when SPR_SRR1 =>
begin
return "10" & f;
end;
+
+ function tag_match(tag1 : instr_tag_t; tag2 : instr_tag_t) return boolean is
+ begin
+ return tag1.valid = '1' and tag2.valid = '1' and tag1.tag = tag2.tag;
+ end;
+
+ function addr_to_real(addr: std_ulogic_vector(63 downto 0)) return real_addr_t is
+ begin
+ return addr(real_addr_t'range);
+ end;
end common;