X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=common.vhdl;h=fb60ce3142edb2a1dac024183bc0af562bcab8f0;hb=5e90133b61c8a07fd0ccf7dac864daa8500c0f3a;hp=3ee19d771acbecf2d5a3e591493d0759de3b9285;hpb=8160f4f8214e982284b2ce2678c8298073b4267c;p=microwatt.git diff --git a/common.vhdl b/common.vhdl index 3ee19d7..fb60ce3 100644 --- a/common.vhdl +++ b/common.vhdl @@ -3,16 +3,25 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; +use work.utils.all; use work.decode_types.all; package common is + -- Processor Version Number + constant PVR_MICROWATT : std_ulogic_vector(31 downto 0) := x"00630000"; -- MSR bit numbers constant MSR_SF : integer := (63 - 0); -- Sixty-Four bit mode constant MSR_EE : integer := (63 - 48); -- External interrupt Enable constant MSR_PR : integer := (63 - 49); -- PRoblem state + constant MSR_FP : integer := (63 - 50); -- Floating Point available + constant MSR_FE0 : integer := (63 - 52); -- Floating Exception mode + constant MSR_SE : integer := (63 - 53); -- Single-step bit of TE field + constant MSR_BE : integer := (63 - 54); -- Branch trace bit of TE field + 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 @@ -24,12 +33,15 @@ package common is constant SPR_XER : spr_num_t := 1; constant SPR_LR : spr_num_t := 8; constant SPR_CTR : spr_num_t := 9; + constant SPR_TAR : spr_num_t := 815; constant SPR_DSISR : spr_num_t := 18; constant SPR_DAR : spr_num_t := 19; constant SPR_TB : spr_num_t := 268; + constant SPR_TBU : spr_num_t := 269; constant SPR_DEC : spr_num_t := 22; constant SPR_SRR0 : spr_num_t := 26; constant SPR_SRR1 : spr_num_t := 27; + constant SPR_CFAR : spr_num_t := 28; constant SPR_HSRR0 : spr_num_t := 314; constant SPR_HSRR1 : spr_num_t := 315; constant SPR_SPRG0 : spr_num_t := 272; @@ -39,12 +51,46 @@ package common is constant SPR_SPRG3U : spr_num_t := 259; constant SPR_HSPRG0 : spr_num_t := 304; constant SPR_HSPRG1 : spr_num_t := 305; + constant SPR_PID : spr_num_t := 48; + 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); - -- Extended GPR indice (can hold an SPR) - subtype gspr_index_t is std_ulogic_vector(5 downto 0); + -- Extended GPR index (can hold an SPR or a FPR) + subtype gspr_index_t is std_ulogic_vector(6 downto 0); + + -- FPR indices + subtype fpr_index_t is std_ulogic_vector(4 downto 0); -- Some SPRs are stored in the register file, they use the magic -- GPR numbers above 31. @@ -54,6 +100,9 @@ package common is -- indicates if this is indeed a fast SPR. If clear, then -- the SPR is not stored in the GPR file. -- + -- FPRs are also stored in the register file, using GSPR + -- numbers from 64 to 95. + -- function fast_spr_num(spr: spr_num_t) return gspr_index_t; -- Indices conversion functions @@ -61,6 +110,7 @@ package common is function gpr_to_gspr(i: gpr_index_t) return gspr_index_t; function gpr_or_spr_to_gspr(g: gpr_index_t; s: gspr_index_t) return gspr_index_t; function is_fast_spr(s: gspr_index_t) return std_ulogic; + function fpr_to_gspr(f: fpr_index_t) return gspr_index_t; -- The XER is split: the common bits (CA, OV, SO, OV32 and CA32) are -- in the CR file as a kind of CR extension (with a separate write @@ -74,38 +124,103 @@ package common is end record; constant xerc_init : xer_common_t := (others => '0'); - type irq_state_t is (WRITE_SRR0, WRITE_SRR1); + -- FPSCR bit numbers + constant FPSCR_FX : integer := 63 - 32; + constant FPSCR_FEX : integer := 63 - 33; + constant FPSCR_VX : integer := 63 - 34; + constant FPSCR_OX : integer := 63 - 35; + constant FPSCR_UX : integer := 63 - 36; + constant FPSCR_ZX : integer := 63 - 37; + constant FPSCR_XX : integer := 63 - 38; + constant FPSCR_VXSNAN : integer := 63 - 39; + constant FPSCR_VXISI : integer := 63 - 40; + constant FPSCR_VXIDI : integer := 63 - 41; + constant FPSCR_VXZDZ : integer := 63 - 42; + constant FPSCR_VXIMZ : integer := 63 - 43; + constant FPSCR_VXVC : integer := 63 - 44; + constant FPSCR_FR : integer := 63 - 45; + constant FPSCR_FI : integer := 63 - 46; + constant FPSCR_C : integer := 63 - 47; + constant FPSCR_FL : integer := 63 - 48; + constant FPSCR_FG : integer := 63 - 49; + constant FPSCR_FE : integer := 63 - 50; + constant FPSCR_FU : integer := 63 - 51; + constant FPSCR_VXSOFT : integer := 63 - 53; + constant FPSCR_VXSQRT : integer := 63 - 54; + constant FPSCR_VXCVI : integer := 63 - 55; + constant FPSCR_VE : integer := 63 - 56; + constant FPSCR_OE : integer := 63 - 57; + constant FPSCR_UE : integer := 63 - 58; + constant FPSCR_ZE : integer := 63 - 59; + constant FPSCR_XE : integer := 63 - 60; + constant FPSCR_NI : integer := 63 - 61; + constant FPSCR_RN : integer := 63 - 63; + + -- 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. + type ics_to_icp_t is record + -- Level interrupts only, ICS just keeps prsenting the + -- highest priority interrupt. Once handling edge, something + -- smarter involving handshake & reject support will be needed + src : std_ulogic_vector(3 downto 0); + pri : std_ulogic_vector(7 downto 0); + end record; -- This needs to die... type ctrl_t is record tb: std_ulogic_vector(63 downto 0); dec: std_ulogic_vector(63 downto 0); msr: std_ulogic_vector(63 downto 0); - irq_state : irq_state_t; - irq_nia: std_ulogic_vector(63 downto 0); - srr1: std_ulogic_vector(63 downto 0); + cfar: std_ulogic_vector(63 downto 0); end record; type Fetch1ToIcacheType is record req: std_ulogic; + virt_mode : std_ulogic; + priv_mode : std_ulogic; + 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; - type IcacheToFetch2Type is record + type IcacheToDecode1Type is record valid: std_ulogic; stop_mark: std_ulogic; + 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 Fetch2ToDecode1Type is record - valid: std_ulogic; - stop_mark : std_ulogic; - nia: std_ulogic_vector(63 downto 0); - insn: std_ulogic_vector(31 downto 0); + type IcacheEventType is record + icache_miss : std_ulogic; + itlb_miss_resolved : std_ulogic; end record; - constant Fetch2ToDecode1Init : Fetch2ToDecode1Type := (valid => '0', stop_mark => '0', others => (others => '0')); type Decode1ToDecode2Type is record valid: std_ulogic; @@ -114,35 +229,61 @@ package common is 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'), 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 Decode1ToDecode2Init : Decode1ToDecode2Type := (valid => '0', stop_mark => '0', decode => decode_rom_init, others => (others => '0')); + 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); 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); @@ -151,24 +292,44 @@ package common is sign_extend : std_ulogic; -- do we need to sign extend? 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', - lr => '0', rc => '0', oe => '0', invert_a => '0', - invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0', - is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', - byte_reverse => '0', sign_extend => '0', update => '0', others => (others => '0')); - - type Execute1ToMultiplyType is record + (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'), + result_sel => "000", sub_select => "000", + repeat => '0', second => '0', others => (others => '0')); + + type MultiplyInputType is record valid: std_ulogic; - insn_type: insn_type_t; - data1: std_ulogic_vector(64 downto 0); - data2: std_ulogic_vector(64 downto 0); + data1: std_ulogic_vector(63 downto 0); + data2: std_ulogic_vector(63 downto 0); + addend: std_ulogic_vector(127 downto 0); is_32bit: std_ulogic; + not_result: std_ulogic; end record; - constant Execute1ToMultiplyInit : Execute1ToMultiplyType := (valid => '0', insn_type => OP_ILLEGAL, - is_32bit => '0', - others => (others => '0')); + constant MultiplyInputInit : MultiplyInputType := (valid => '0', + is_32bit => '0', not_result => '0', + others => (others => '0')); + + type MultiplyOutputType is record + valid: std_ulogic; + result: std_ulogic_vector(127 downto 0); + overflow : std_ulogic; + end record; + constant MultiplyOutputInit : MultiplyOutputType := (valid => '0', overflow => '0', + others => (others => '0')); type Execute1ToDividerType is record valid: std_ulogic; @@ -184,19 +345,64 @@ package common is 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; read2_enable : std_ulogic; read2_reg : gspr_index_t; read3_enable : std_ulogic; - read3_reg : gpr_index_t; + read3_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 @@ -208,51 +414,64 @@ package common is read_xerc_data : xer_common_t; 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 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 - write_reg : gpr_index_t; + write_reg : gspr_index_t; length : std_ulogic_vector(3 downto 0); ci : std_ulogic; -- cache-inhibited load/store 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. virt_mode : std_ulogic; -- do translation through TLB priv_mode : std_ulogic; -- privileged mode (MSR[PR] = 0) - spr_num : spr_num_t; -- SPR number for mfspr/mtspr + mode_32bit : std_ulogic; -- trim addresses to 32 bits + is_32bit : std_ulogic; + 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', - spr_num => 0, others => (others => '0')); + 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 - exception : std_ulogic; + busy : 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; @@ -261,26 +480,46 @@ package common is data : std_ulogic_vector(63 downto 0); store_done : std_ulogic; error : std_ulogic; - tlb_miss : std_ulogic; - perm_error : std_ulogic; - rc_error : std_ulogic; + 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; + slbia : std_ulogic; + mtspr : std_ulogic; + iside : std_ulogic; + load : std_ulogic; + priv : std_ulogic; + sprn : std_ulogic_vector(9 downto 0); addr : std_ulogic_vector(63 downto 0); rs : std_ulogic_vector(63 downto 0); end record; type MmuToLoadstore1Type is record - done : std_ulogic; - error : std_ulogic; + done : std_ulogic; + err : std_ulogic; + invalid : std_ulogic; + badtree : std_ulogic; + segerr : std_ulogic; + perm_error : std_ulogic; + rc_error : std_ulogic; + sprval : std_ulogic_vector(63 downto 0); end record; type MmuToDcacheType is record valid : std_ulogic; tlbie : std_ulogic; + doall : std_ulogic; + tlbld : std_ulogic; addr : std_ulogic_vector(63 downto 0); pte : std_ulogic_vector(63 downto 0); end record; @@ -288,23 +527,50 @@ package common is type DcacheToMmuType is record stall : std_ulogic; done : std_ulogic; + err : std_ulogic; + data : std_ulogic_vector(63 downto 0); + end record; + + type MmuToIcacheType is record + tlbld : std_ulogic; + tlbie : std_ulogic; + doall : std_ulogic; + addr : std_ulogic_vector(63 downto 0); + pte : std_ulogic_vector(63 downto 0); end record; type Loadstore1ToWritebackType is record valid : std_ulogic; + instr_tag : instr_tag_t; write_enable: std_ulogic; - write_reg : gpr_index_t; + 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', 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_reg: gspr_index_t; write_data: std_ulogic_vector(63 downto 0); @@ -313,22 +579,78 @@ package common is 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); + 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', rc => '0', write_enable => '0', - write_cr_enable => '0', exc_write_enable => '0', - write_xerc_enable => '0', xerc => xerc_init, - others => (others => '0')); - - type MultiplyToExecute1Type is record - valid: std_ulogic; - write_reg_data: std_ulogic_vector(63 downto 0); - overflow : std_ulogic; + 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); + fra : std_ulogic_vector(63 downto 0); + frb : std_ulogic_vector(63 downto 0); + frc : std_ulogic_vector(63 downto 0); + frt : gspr_index_t; + rc : std_ulogic; + out_cr : std_ulogic; end record; - constant MultiplyToExecute1Init : MultiplyToExecute1Type := (valid => '0', overflow => '0', - others => (others => '0')); + 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'), + single => '0', out_cr => '0'); + + type FPUToExecute1Type is record + busy : std_ulogic; + exception : 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); + 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; @@ -338,12 +660,29 @@ package common is 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', 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; @@ -354,10 +693,12 @@ package common is end record; constant WritebackToCrFileInit : WritebackToCrFileType := (write_cr_enable => '0', write_xerc_enable => '0', write_xerc_data => xerc_init, - others => (others => '0')); + write_cr_mask => (others => '0'), + write_cr_data => (others => '0')); - type XicsToExecute1Type is record - irq : std_ulogic; + type WritebackEventType is record + instr_complete : std_ulogic; + fp_complete : std_ulogic; end record; end common; @@ -369,12 +710,16 @@ package body common is end; function fast_spr_num(spr: spr_num_t) return gspr_index_t is variable n : integer range 0 to 31; + -- tmp variable introduced as workaround for VCS compilation + -- simulation was failing with subtype constraint mismatch error + -- see GitHub PR #173 + variable tmp : std_ulogic_vector(4 downto 0); 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 => @@ -397,11 +742,14 @@ package body common is n := 11; when SPR_XER => n := 12; + when SPR_TAR => + n := 13; when others => n := 0; - return "000000"; + return "0000000"; end case; - return "1" & std_ulogic_vector(to_unsigned(n, 5)); + tmp := std_ulogic_vector(to_unsigned(n, 5)); + return "01" & tmp; end; function gspr_to_gpr(i: gspr_index_t) return gpr_index_t is @@ -411,7 +759,7 @@ package body common is function gpr_to_gspr(i: gpr_index_t) return gspr_index_t is begin - return "0" & i; + return "00" & i; end; function gpr_or_spr_to_gspr(g: gpr_index_t; s: gspr_index_t) return gspr_index_t is @@ -427,4 +775,19 @@ package body common is begin return s(5); end; + + function fpr_to_gspr(f: fpr_index_t) return gspr_index_t is + 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;