Commit 4092f2f4 authored by Marc's avatar Marc
Browse files

version 1.2 and 1.2.1

parent 16d5a3b0
......@@ -495,13 +495,14 @@ architecture rtl of iu3 is
sa => swizzling_init,
sb => swizzling_init,
ol => (others => '0'),
od => (others => '0')
od => (others => '0'),
hp => '0'
--ac => vector_reg_res
);
function to_word(reg : simd_ctrl_reg_type) return word is
begin
return "00000" & reg.od & reg.ol & swizzling_get(reg.sa) & swizzling_get(reg.sb) & reg.ms & reg.mk;
return "0000" & reg.hp & reg.od & reg.ol & swizzling_get(reg.sa) & swizzling_get(reg.sb) & reg.ms & reg.mk;
end to_word;
function to_scr(data : word) return simd_ctrl_reg_type is
......@@ -513,6 +514,7 @@ architecture rtl of iu3 is
reg.sb := swizzling_set(data(20 downto 13));
reg.ol := data(22 downto 21);
reg.od := data(26 downto 23);
reg.hp := data(27);
return reg;
end to_scr;
......
......@@ -149,6 +149,8 @@ constant dummy_ft_consistency_check:
signal holdn : std_logic;
signal rfi : iregfile_in_type;
signal rfo : iregfile_out_type;
--signal rfo1 : iregfile_out_type;
--signal rfo2 : iregfile_out_type;
signal crami : cram_in_type;
signal cramo : cram_out_type;
signal tbi : tracebuf_in_type;
......@@ -197,6 +199,11 @@ begin
tbi, tbo, tbi_2p, tbo_2p, fpi, fpo, cpi, cpo, irqi, irqo, dbgi, dbgo, clk, clk2, clken
);
-- rfo.data1 <= rfo1.data1 when rfo1.data1 = rfo2.data1 else
-- rfo2.data1;
-- rfo.data2 <= rfo1.data2 when rfo1.data2 = rfo2.data2 else
-- rfo2.data2;
-- IU register file
rf0 : regfile_3p_l3 generic map (MEMTECH_MOD*(1-IURF_INFER), IRFBITS, 32, IRFWT, IREGNUM,
scantest, RFREADHOLD)
......@@ -206,6 +213,14 @@ begin
ahbi.testin
);
-- rf1 : regfile_3p_l3 generic map (MEMTECH_MOD*(1-IURF_INFER), IRFBITS, 32, IRFWT, IREGNUM,
-- scantest, RFREADHOLD)
-- port map (gclk2, rfi.waddr(IRFBITS-1 downto 0), rfi.wdata, rfi.wren,
-- gclk2, rfi.raddr1(IRFBITS-1 downto 0), rfi.ren1, rfo2.data1,
-- rfi.raddr2(IRFBITS-1 downto 0), rfi.ren2, rfo2.data2,
-- ahbi.testin
-- );
-- cache memory
cmem0 : cachemem
generic map (MEMTECH_MOD, icen, irepl, isets, ilinesize, isetsize, isetlock, dcen,
......
......@@ -16,9 +16,9 @@ entity lpmul is
end;
architecture rtl of lpmul is
constant SMAX : std_logic_vector(VLEN-1 downto 0) := "0" & (VLEN-2 downto 0 => '1');
constant SMIN : std_logic_vector(VLEN-1 downto 0) := "1" & (VLEN-2 downto 0 => '0');
constant UMAX : std_logic_vector(VLEN-1 downto 0) := (others => '1');
constant SMAX : vector_component := "0" & (VLEN-2 downto 0 => '1');
constant SMIN : vector_component := "1" & (VLEN-2 downto 0 => '0');
constant UMAX : vector_component := (others => '1');
function sign_invert(a : std_logic_vector) return std_logic_vector is
begin
......@@ -61,20 +61,25 @@ architecture rtl of lpmul is
sel := "111"; -- result is ff unsigned max
end if;
end if;
elsif sign = '1' then -- if no saturation but signed
if asign /= bsign then -- and result should be negative
sel := "001"; -- result is ca2 negative
end if;
end if;
return sel;
end sat_mux;
procedure sat_sel (sel : in std_logic_vector(2 downto 0);
r, nr : in std_logic_vector(VLEN-1 downto 0);
mulres : out std_logic_vector(VLEN-1 downto 0)) is
r, nr : in high_prec_component;
mulres : out high_prec_component) is
begin
case sel is
when "000" => mulres := r;
when "001" => mulres := nr;
when "011" => mulres := SMAX;
when "100" => mulres := SMIN;
when "111" => mulres := UMAX;
when "011" => mulres := (vector_component'range => '0') & SMAX;
when "100" => mulres := (vector_component'range => '1') & SMIN;
when "111" => mulres := (vector_component'range => '0') & UMAX;
when others => mulres := (others => '0');
end case;
end sat_sel;
......@@ -82,9 +87,9 @@ architecture rtl of lpmul is
begin
comb : process( muli)
variable z : std_logic_vector(VLEN*2-1 downto 0);
variable r : std_logic_vector(VLEN-1 downto 0);
variable a, b : std_logic_vector(VLEN-1 downto 0);
variable z : high_prec_component;
variable r : high_prec_component;
variable a, b : vector_component;
variable signA, signB : std_logic;
variable mux : std_logic_vector(2 downto 0);
begin
......@@ -93,17 +98,19 @@ begin
signB := muli.opB(muli.opB'left);
-- have both operands as positive if signed and saturation
if (muli.sign and signA and muli.sat) = '1' then
--if (muli.sign and signA and muli.sat) = '1' then
if (muli.sign and signA) = '1' then
a := sign_invert(muli.opA);
end if;
if (muli.sign and signB and muli.sat) = '1' then
--if (muli.sign and signB and muli.sat) = '1' then
if (muli.sign and signB) = '1' then
b := sign_invert(muli.opB);
end if;
-- low precision product
z := product(a, b);
-- select result with sign and saturation
mux := sat_mux(signA, signB, z(r'left), muli.sign, muli.sat, z(z'left downto r'length));
sat_sel(mux, z(r'range), sign_invert(z(r'range)), r);
mux := sat_mux(signA, signB, z(vector_component'left), muli.sign, muli.sat, z(z'left downto vector_component'length));
sat_sel(mux, z, sign_invert(z), r);
mulo.mul_res <= r;
end process;
end;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library grlib;
use grlib.stdlib.all;
library marcmod;
use marcmod.simdmod.all;
entity simd_module is
port(
clk : in std_ulogic;
rstn : in std_ulogic;
holdn : in std_ulogic;
sdi : in simd_in_type;
sdo : out simd_out_type
);
end;
architecture rtl of simd_module is
---------------------------------------------------------------
-- REGISTER TYPES DEFINITION --
--------------------------------------------------------------
type lpmul_in_array is array (0 to VSIZE-1) of lpmul_in_type;
type lpmul_out_array is array (0 to VSIZE-1) of lpmul_out_type;
type l1_sum_array is array (0 to VSIZE/2) of std_logic_vector(VLEN downto 0);
type l2_sum_array is array (0 to VSIZE/4) of std_logic_vector(VLEN+1 downto 0);
-- Stage1 entry register
type s1_reg_type is record
ra : vector_reg_type;
rb : vector_reg_type;
op1: std_logic_vector(4 downto 0);
op2: std_logic_vector(2 downto 0);
en : std_logic;
end record;
-- Stage2 entry register
type s2_reg_type is record
ra : inter_reg_type;
op2: std_logic_vector(2 downto 0);
sat: std_logic;
en : std_logic;
end record;
-- Stage3 entry register
type s3_reg_type is record
rc : word;
end record;
-- Group of pipeline registers
type registers is record
s1 : s1_reg_type;
s2 : s2_reg_type;
s3 : s3_reg_type;
end record;
---------------------------------------------------------------
-- CONSTANTS FOR PIPELINE REGISTERS RESET --
--------------------------------------------------------------
constant vector_reg_res : vector_reg_type := (others => (others => '0'));
constant inter_reg_res : inter_reg_type := (others => (others => '0'));
-- set the 1st stage registers reset
constant s1_reg_res : s1_reg_type := (
ra => vector_reg_res,
rb => vector_reg_res,
op1 => (others => '0'),
op2 => (others => '0'),
en => '0'
);
-- set the 2nd stage registers reset
constant s2_reg_res : s2_reg_type := (
ra => inter_reg_res,
op2 => (others => '0'),
sat => '0',
en => '0'
);
-- set the 3rd stage registers reset
constant s3_reg_res : s3_reg_type := (
rc => (others => '0')
);
-- reset all registers
constant RRES : registers := (
s1 => s1_reg_res,
s2 => s2_reg_res,
s3 => s3_reg_res
);
---------------------------------------------------------------
-- FUNCTIONS
--------------------------------------------------------------
function to_vector(data : word) return vector_reg_type is
variable vec : vector_reg_type;
begin
for i in vec'range loop
vec(i) := data(VLEN*i+VLEN-1 downto VLEN*i);
end loop;
return vec;
end;
function to_word(vec : vector_reg_type) return word is
variable data : word;
begin
for i in vec'range loop
data(VLEN*i+VLEN-1 downto VLEN*i) := vec(i);
end loop;
return data;
end;
function to_word(vec : inter_reg_type) return word is
variable data : word;
begin
for i in vec'range loop
data(VLEN*i+VLEN-1 downto VLEN*i) := vec(i)(vector_component'range);
end loop;
return data;
end;
function swizzling(data : vector_reg_type; sz : swizzling_reg_type) return vector_reg_type is
variable result : vector_reg_type;
begin
for i in result'range loop
result(i) := data(sz(i));
end loop;
return result;
end function swizzling;
---------------------------------------------------------------
-- SATURATION FUNCTIONS
--------------------------------------------------------------
function clipping (value, max_val, min_val : integer) return integer is
begin
if value > max_val then return max_val;
elsif value < min_val then return min_val;
else return value;
end if;
end clipping;
function extend(value : std_logic_vector; sign : std_logic; size : integer) return std_logic_vector is
begin
if sign = '1' then
return std_logic_vector(resize(signed(value), size));
else
return std_logic_vector(resize(unsigned(value), size));
end if;
end extend;
function signed_sat(a, leng : integer; sat : std_logic) return std_logic_vector is
begin
if sat = '1' then
return std_logic_vector(to_signed(clipping(a, 127, -128), leng));
else return std_logic_vector(to_signed(a, leng));
end if;
end signed_sat;
function unsigned_sat(a, leng : integer; sat : std_logic) return std_logic_vector is
begin
if sat = '1' then
return std_logic_vector(to_unsigned(clipping(a, 255, 0), leng));
else return std_logic_vector(to_signed(a, leng));
end if;
end unsigned_sat;
---------------------------------------------------------------
-- SIGNALS DEFINITIONS
--------------------------------------------------------------
--signals for the registers r -> current, rin -> next
signal r, rin: registers;
signal lpmuli : lpmul_in_array;
signal lpmulo : lpmul_out_array;
---------------------------------------------------------------
-- TWO OPERANDS OPERATIONS (S1) --
--------------------------------------------------------------
-- s1 result multiplexor
procedure s1_mux(op : in std_logic_vector(4 downto 0);
sel: out std_logic_vector(3 downto 0)) is
begin
sel := '0' & op(2 downto 0);
case op is
when S1_SADD | S1_USADD => sel := "0001";
when S1_SSUB | S1_USSUB => sel := "0010";
when S1_SMUL | S1_USMUL => sel := "0011";
when S1_AND | S1_OR | S1_XOR | S1_NAND | S1_NOR | S1_XNOR =>
sel := "0111";
when S1_MOVB => sel := "0100";
when S1_SHFT | S1_SSHFT => sel := "1000";
when others =>
end case;
end s1_mux;
procedure s1_select(sel: in std_logic_vector(3 downto 0);
ra, rs2, add_res, sub_res, max_res, min_res, logic_res, shift_res, mul_res : in inter_reg_type;
s1_res : out inter_reg_type) is
begin
case sel is
when "0000" => s1_res := ra;
when "0001" => s1_res := add_res;
when "0010" => s1_res := sub_res;
when "0011" => s1_res := mul_res;
when "0100" => s1_res := rs2;
when "0101" => s1_res := max_res;
when "0110" => s1_res := min_res;
when "0111" => s1_res := logic_res;
when "1000" => s1_res := shift_res;
when others => s1_res := (others => (others => '0'));
end case;
end s1_select;
function add(a, b : vector_component;
sign, sat : std_logic) return std_logic_vector is
variable z : integer;
begin
if sign = '1' then
z := to_integer(signed(a)) + to_integer(signed(b));
return signed_sat(z, high_prec_component'length, sat);
else
z := to_integer(unsigned(a)) + to_integer(unsigned(b));
return unsigned_sat(z, high_prec_component'length, sat);
end if;
end add;
function sub(a, b : vector_component;
sign, sat : std_logic) return std_logic_vector is
variable z : integer range -512 to 512;
begin
if sign = '1' then
z := to_integer(signed(a)) - to_integer(signed(b));
return signed_sat(z, high_prec_component'length, sat);
else
z := to_integer(signed(a)) - to_integer(signed(b));
return unsigned_sat(z, high_prec_component'length, sat);
end if;
end sub;
-- max function
function max(a, b : vector_component;
sign : std_logic) return high_prec_component is
variable z : vector_component;
begin
if sign = '1' then
if signed(a) > signed(b) then z := a;
else z := b;
end if;
else
if a > b then z := a;
else z := b;
end if;
end if;
return (z(z'left) and sign)&z;
end max;
-- min function
function min(a, b : vector_component;
sign : std_logic) return high_prec_component is
variable z : vector_component;
begin
if sign = '1' then
if signed(a) > signed(b) then z := b;
else z := a;
end if;
else
if a > b then z := b;
else z := a;
end if;
end if;
return (z(z'left) and sign)&z;
end min;
--logic operations
function logic_op(a, b : vector_component;
op : std_logic_vector(2 downto 0)) return vector_component is
variable z : vector_component;
begin
case op is
when "111" => z := a and b;
when "000" => z := a or b;
when "001" => z := a xor b;
when "010" => z := a nand b;
when "011" => z := a nor b;
when "100" => z := a xnor b;
when others => z := (others => '0');
end case;
return z;
end logic_op;
function shift(a, b : vector_component; sat : std_logic) return high_prec_component is
variable z : high_prec_component;
variable i : integer;
begin
i := to_integer(signed(b(b'left downto 1)));
if b(b'left) = '1' then -- shift right
if b(0) = '1' then -- arithmetic
z := std_logic_vector(shift_right(signed(a(a'left)&a), -i));
else
z := std_logic_vector(shift_right(unsigned('0'&a), -i));
end if;
else
z := std_logic_vector(shift_left(unsigned('0'&a), i));
end if;
return z;
end shift;
--apply mask to vector
procedure mask(vector, original : in inter_reg_type;
msk : in std_logic_vector(VSIZE-1 downto 0);
msk_res : out inter_reg_type) is
begin
msk_res := original;
for i in msk'range loop
if msk(i) = '1' then
msk_res(i) := vector(i);
end if;
end loop;
end mask;
--apply shift and accumulate
--procedure shift_and_acc(be : in s2byteen_reg_type;
-- acc : in vector_reg_type;
-- data: in vector_reg_type;
-- res : out vector_reg_type;
-- nxt_be : out s2byteen_reg_type) is
-- variable new_acc : vector_reg_type;
--begin
-- new_acc := acc;
-- for i in be'range loop
-- if be(i) = '1' then
-- new_acc(i) := data(0);
-- end if;
-- end loop;
-- res := new_acc; nxt_be := be(be'left-1 downto 0) & '0';
--end shift_and_acc;
---------------------------------------------------------------
-- REDUCTION OPERATIONS (S2) --
--------------------------------------------------------------
procedure s2_select(sel : in std_logic_vector(2 downto 0);
ra, sum_res, max_res, min_res, xor_res : in word;
rc : out word) is
begin
case sel is
when "000" => rc := ra;
when "001" | "101" => rc := sum_res;
when "010" | "110" => rc := max_res;
when "011" | "111" => rc := min_res;
when "100" => rc := xor_res;
when others =>rc := ra;
end case;
end s2_select;
function sum(a : inter_reg_type; sign, sat : std_logic) return word is
variable acc : integer := 0;
begin
if sign = '1' then
for i in 0 to VSIZE-1 loop
acc := acc + to_integer(signed(a(i)));
end loop;
return signed_sat(acc, word'length, sat);
else
for i in 0 to VSIZE-1 loop
acc := acc + to_integer(unsigned(a(i)));
end loop;
return unsigned_sat(acc, word'length, sat);
end if;
end sum;
--max recursive function
function max_red(a : inter_reg_type; sign : std_logic) return word is
variable acc : integer;
begin
if sign = '1' then
acc := to_integer(signed(a(0)));
for i in 1 to VSIZE-1 loop
if to_integer(signed(a(i))) > acc then
acc := to_integer(signed(a(i)));
end if;
end loop;
else
acc := to_integer(unsigned(a(0)));
for i in 1 to VSIZE-1 loop
if to_integer(unsigned(a(i))) > acc then
acc := to_integer(unsigned(a(i)));
end if;
end loop;
end if;
return unsigned_sat(acc, word'length, '0');
end max_red;
--min recursive function
function min_red(a : inter_reg_type; sign : std_logic) return word is
variable acc : integer;
begin
if sign = '1' then
acc := to_integer(signed(a(0)));
for i in 1 to VSIZE-1 loop
if to_integer(signed(a(i))) < acc then
acc := to_integer(signed(a(i)));
end if;
end loop;
else
acc := to_integer(unsigned(a(0)));
for i in 1 to VSIZE-1 loop
if to_integer(unsigned(a(i))) < acc then
acc := to_integer(unsigned(a(i)));
end if;
end loop;
end if;
return unsigned_sat(acc, word'length, '0');
end min_red;
function xor_red(a : inter_reg_type) return word is
variable acc : vector_component;
begin
acc := a(0)(vector_component'range);
for i in 1 to VSIZE-1 loop
acc := a(i)(vector_component'range) xor acc;
end loop;
return std_logic_vector(resize(unsigned(acc), word'length));
end xor_red;
begin
---------------------------------------------------------------
-- MAIN BODY --
--------------------------------------------------------------
genmul : for i in 0 to XLEN/VLEN-1 generate
mul : lpmul
port map(lpmuli(i), lpmulo(i));
end generate genmul;