You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

434 lines
15 KiB
VHDL

-- © IBM Corp. 2020
-- Licensed under the Apache License, Version 2.0 (the "License"), as modified by
-- the terms below; you may not use the files in this repository except in
-- compliance with the License as modified.
-- You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
--
-- Modified Terms:
--
-- 1) For the purpose of the patent license granted to you in Section 3 of the
-- License, the "Work" hereby includes implementations of the work of authorship
-- in physical form.
--
-- 2) Notwithstanding any terms to the contrary in the License, any licenses
-- necessary for implementation of the Work that are available from OpenPOWER
-- via the Power ISA End User License Agreement (EULA) are explicitly excluded
-- hereunder, and may be obtained from OpenPOWER under the terms and conditions
-- of the EULA.
--
-- Unless required by applicable law or agreed to in writing, the reference design
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
-- for the specific language governing permissions and limitations under the License.
--
-- Additional rights, including the ability to physically implement a softcore that
-- is compliant with the required sections of the Power ISA Specification, are
-- available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
-- obtained (along with the Power ISA) here: https://openpowerfoundation.org.
library ieee;
use ieee.std_logic_1164.all;
package iuq_pkg is
subtype EFF_IFAR is std_ulogic_vector( 0 to 61);
subtype REAL_IFAR is std_ulogic_vector(22 to 61);
subtype EFF_DATA_ADD is std_ulogic_vector( 0 to 61);
subtype REAL_DATA_ADD is std_ulogic_vector(18 to 61);
function ib(x : std_ulogic) return boolean;
-- all functions assume to logic vector strand direction
function barrel_left(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector;
function barrel_right(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector;
function pri_enc(a : std_ulogic_vector) return std_ulogic_vector;
function shift_left(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector;
function shift_right(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector;
function mask_left(a : std_ulogic_vector ) return std_ulogic_vector;
function mask_right(a : std_ulogic_vector ) return std_ulogic_vector;
function shift_leftx1B(a : std_ulogic_vector; s: std_ulogic_vector) return std_ulogic_vector;
function shift_rightx1B(a : std_ulogic_vector; s: std_ulogic_vector) return std_ulogic_vector;
procedure zeros(signal x : out std_ulogic);
procedure zeros(signal x : out std_ulogic_vector);
function encode_4to2( a : std_ulogic_vector(0 to 3) ) return std_ulogic_vector;
function encode_8to3( a : std_ulogic_vector(0 to 7) ) return std_ulogic_vector;
function encode_16to4(a : std_ulogic_vector(0 to 15)) return std_ulogic_vector;
-- Instruction type definition
type PPC_INSTR is record
vld : std_ulogic;
instr : std_ulogic_vector(0 to 31);
ta : std_ulogic_vector(0 to 6);
ta_vld : std_ulogic;
ta_typ : std_ulogic_vector(0 to 1);
s1 : std_ulogic_vector(0 to 6);
s1_vld : std_ulogic;
s1_typ : std_ulogic_vector(0 to 1);
s2 : std_ulogic_vector(0 to 6);
s2_vld : std_ulogic;
s2_typ : std_ulogic_vector(0 to 1);
s3 : std_ulogic_vector(0 to 6);
s3_vld : std_ulogic;
s3_typ : std_ulogic_vector(0 to 1);
isFxuIssue : std_ulogic;
isVsuIssue : std_ulogic;
--EX2_exit : std_ulogic;
EX4_exit : std_ulogic;
EX7_exit : std_ulogic;
isLWARX : std_ulogic;
isSTWCX : std_ulogic;
is_vcrs : std_ulogic;
pred_update : std_ulogic;
pred_taken_cnt : std_ulogic_vector(0 to 1);
isINVALID_OP : std_ulogic;
isATTN : std_ulogic;
UpdatesLR : std_ulogic;
UpdatesCR : std_ulogic;
UpdatesCTR : std_ulogic;
UsesLR : std_ulogic;
UsesCR : std_ulogic;
UsesCTR : std_ulogic;
is_st : std_ulogic;
is_ld : std_ulogic;
ibat_err : std_ulogic;
tid : std_ulogic_vector(0 to 3);
ifar : EFF_IFAR;
bta : EFF_IFAR;
end record;
function TO_STLV ( x : PPC_INSTR ) return std_ulogic_vector;
function TO_PPCI ( x : std_ulogic_vector(0 to 97+2*EFF_IFAR'length) ) return PPC_INSTR;
end iuq_pkg;
package body iuq_pkg is
function ib(x : std_ulogic) return boolean
is
begin
return(x = '1');
end ib;
-- These functions all assume TO direction logic
function barrel_left(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector
is
variable result : std_ulogic_vector(a'left to a'right);
variable i : integer := 0;
begin
result := a;
for i in s'left to s'right loop
if s(i) = '1' then
exit;
end if;
result := result(result'left+1 to result'right)&result(result'left);
end loop;
return( result );
end barrel_left;
function barrel_right(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector
is
variable result : std_ulogic_vector(a'left to a'right);
begin
result := a;
for i in a'left to a'right loop
if s(i) = '1' then
exit;
end if;
result := result(result'right) & result(result'left to result'right-1);
end loop;
return( result );
end barrel_right;
function pri_enc(a : std_ulogic_vector) return std_ulogic_vector
is
variable result : std_ulogic_vector(a'left to a'right);
begin
result := (others => '0');
for i in a'left to a'right loop
if a(i) = '1' then
result(i) := '1';
exit;
end if;
end loop;
return( result );
end pri_enc;
function shift_left(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector is
variable result : std_ulogic_vector(a'left to a'right);
begin
result := a;
for i in s'left to s'right loop
if s(i) = '1' then
exit;
end if;
result := result( result'left+1 to result'right)&'0';
end loop;
return(result);
end shift_left;
function shift_right(a : std_ulogic_vector; s : std_ulogic_vector) return std_ulogic_vector is
variable result : std_ulogic_vector(a'left to a'right);
begin
result := a;
for i in s'left to s'right loop
if s(i) = '1' then
exit;
end if;
result := '0'&result(result'left to result'right-1);
end loop;
return(result);
end shift_right;
function mask_left(a : std_ulogic_vector ) return std_ulogic_vector is
variable result : std_ulogic_vector(a'left to a'right);
variable flag : integer := 0;
begin
for i in a'right downto a'left loop
if ((a(i) = '1') or (flag = 1)) then
result(i) := '1';
flag := 1;
else
result(i) := a(i);
end if;
end loop;
return( result );
end mask_left;
function mask_right(a : std_ulogic_vector ) return std_ulogic_vector is
variable result : std_ulogic_vector(a'left to a'right);
variable flag : integer := 0;
begin
for i in a'left to a'right loop
if ((a(i) = '1') or (flag = 1)) then
result(i) := '1';
flag := 1;
else
result(i) := a(i);
end if;
end loop;
return( result );
end mask_right;
function encode_4to2( a : std_ulogic_vector(0 to 3) ) return std_ulogic_vector is
variable result : std_ulogic_vector(0 to 1);
begin
case a is
when "1000" => result := "00";
when "0100" => result := "01";
when "0010" => result := "10";
when "0001" => result := "11";
when others => result := "00";
end case;
return(result);
end encode_4to2;
function encode_8to3( a : std_ulogic_vector(0 to 7) ) return std_ulogic_vector is
variable result : std_ulogic_vector(0 to 2);
begin
case a is
when "10000000" => result := "000";
when "01000000" => result := "001";
when "00100000" => result := "010";
when "00010000" => result := "011";
when "00001000" => result := "100";
when "00000100" => result := "101";
when "00000010" => result := "110";
when "00000001" => result := "111";
when others => result := "000";
end case;
return(result);
end encode_8to3;
function encode_16to4(a : std_ulogic_vector(0 to 15)) return std_ulogic_vector is
variable result : std_ulogic_vector(0 to 3);
begin
case a is
when "1000000000000000" => result := "0000";
when "0100000000000000" => result := "0001";
when "0010000000000000" => result := "0010";
when "0001000000000000" => result := "0011";
when "0000100000000000" => result := "0100";
when "0000010000000000" => result := "0101";
when "0000001000000000" => result := "0110";
when "0000000100000000" => result := "0111";
when "0000000010000000" => result := "1000";
when "0000000001000000" => result := "1001";
when "0000000000100000" => result := "1010";
when "0000000000010000" => result := "1011";
when "0000000000001000" => result := "1100";
when "0000000000000100" => result := "1101";
when "0000000000000010" => result := "1110";
when "0000000000000001" => result := "1111";
when others => result := "0000";
end case;
return(result);
end encode_16to4;
-- you better make sure that a and result are multiples of 1B with s being a strand representing the number of bytes to shift
function shift_leftx1B(a : std_ulogic_vector; s: std_ulogic_vector) return std_ulogic_vector is
variable result : std_ulogic_vector(a'left to a'right);
begin
result := a;
for i in s'left to s'right loop
if s(i) = '1' then
exit;
end if;
result := result( result'left+8 to result'right)&"00000000";
end loop;
return(result);
end shift_leftx1B;
function shift_rightx1B(a : std_ulogic_vector; s: std_ulogic_vector) return std_ulogic_vector is
variable result : std_ulogic_vector(a'left to a'right);
begin
result := a;
for i in s'left to s'right loop
if s(i) = '1' then
exit;
end if;
result := "00000000"&result(result'left to result'right-8);
end loop;
return(result);
end shift_rightx1B;
--------------------------------------------------------------------
--- PPC_INSTR manipulation
--------------------------------------------------------------------
-- x bit TID
function TO_STLV ( x : PPC_INSTR ) return std_ulogic_vector
is
variable result : std_ulogic_vector(0 to 97+2*EFF_IFAR'length);
begin
result := x.vld &
x.instr &
x.ta &
x.ta_vld &
x.ta_typ &
x.s1 &
x.s1_vld &
x.s1_typ &
x.s2 &
x.s2_vld &
x.s2_typ &
x.s3 &
x.s3_vld &
x.s3_typ &
x.isFxuIssue &
x.isVsuIssue &
x.EX4_exit &
x.EX7_exit &
x.isLWARX &
x.isSTWCX &
x.is_vcrs &
x.pred_update &
x.pred_taken_cnt &
x.isINVALID_OP &
x.isATTN &
x.UpdatesLR &
x.UpdatesCR &
x.UpdatesCTR &
x.UsesLR &
x.UsesCR &
x.UsesCTR &
x.is_st &
x.is_ld &
x.ibat_err &
x.tid &
x.ifar &
x.bta
;
return result;
end TO_STLV;
-- x bit TID
function TO_PPCI ( x : std_ulogic_vector(0 to 97+2*EFF_IFAR'length) ) return PPC_INSTR is
variable result : PPC_INSTR;
begin
result.vld := x(0);
result.instr := x(1 to 32);
result.ta := x(33 to 39);
result.ta_vld := x(40);
result.ta_typ := x(41 to 42);
result.s1 := x(43 to 49);
result.s1_vld := x(50);
result.s1_typ := x(51 to 52);
result.s2 := x(53 to 59);
result.s2_vld := x(60);
result.s2_typ := x(61 to 62);
result.s3 := x(63 to 69);
result.s3_vld := x(70);
result.s3_typ := x(71 to 72);
result.isFxuIssue := x(73);
result.isVsuIssue := x(74);
result.EX4_exit := x(75);
result.EX7_exit := x(76);
result.isLWARX := x(77);
result.isSTWCX := x(78);
result.is_vcrs := x(79);
result.pred_update := x(80);
result.pred_taken_cnt := x(81 to 82);
result.isINVALID_OP := x(83);
result.isATTN := x(84);
result.UpdatesLR := x(85);
result.UpdatesCR := x(86);
result.UpdatesCTR := x(87);
result.UsesLR := x(88);
result.UsesCR := x(89);
result.UsesCTR := x(90);
result.is_st := x(91);
result.is_ld := x(92);
result.ibat_err := x(93);
result.tid := x(94 to 97);
result.ifar := x(98 to 97+EFF_IFAR'length);
result.bta := x(98+EFF_IFAR'length to 97+2*EFF_IFAR'length);
return result;
end TO_PPCI;
procedure zeros(signal x : out std_ulogic)
is
begin
x <= '0';
end zeros;
procedure zeros(signal x : out std_ulogic_vector)
is
begin
for i in x'range loop
x(i) <= '0';
end loop;
end zeros;
end iuq_pkg;