From 2c70ace5754bc18a151e7b4d4bde7018dd64c2af Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Sun, 29 Dec 2013 12:26:10 +0100 Subject: Add bug18810 testcase. --- testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd | 241 +++++++++++++++++++ testsuite/gna/bug18810/DMEM.vhd | 243 +++++++++++++++++++ testsuite/gna/bug18810/OISC_SUBLEQ.vhd | 339 +++++++++++++++++++++++++++ testsuite/gna/bug18810/testsuite.sh | 10 + 4 files changed, 833 insertions(+) create mode 100644 testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd create mode 100644 testsuite/gna/bug18810/DMEM.vhd create mode 100644 testsuite/gna/bug18810/OISC_SUBLEQ.vhd create mode 100755 testsuite/gna/bug18810/testsuite.sh (limited to 'testsuite/gna') diff --git a/testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd b/testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd new file mode 100644 index 000000000..25b113fe6 --- /dev/null +++ b/testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd @@ -0,0 +1,241 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.OISC_SUBLEQ_PKG.all; + +entity BENCH_OISC_SUBLEQ is +begin +end entity BENCH_OISC_SUBLEQ; + +architecture BENCH of BENCH_OISC_SUBLEQ is + + signal sPCLK : std_logic := '0'; + signal sDCLK : std_logic := '0'; + signal sCLK : std_logic := '0'; + signal sCLR : std_logic := '1'; + + constant cPCLK_CYCLE : time := 1000.0 ns / 250.0; -- NOTE: 250[MHz] + constant cDCLK_CYCLE : time := 1000.0 ns / 200.0; -- NOTE: 200[MHz] + constant cCLK_CYCLE : time := 1000.0 ns / 150.0; -- NOTE: 150[MHz] + constant cCLR_TIME : time := 10*cCLK_CYCLE; + + constant clog2PADDR : integer range 0 to integer'high := 8; + constant clog2DADDR : integer range 0 to integer'high := 4; + constant cDW : integer range 1 to integer'high := 8; + + type tPIF is record + OISC_SUBLEQ_oPINST : std_logic_vector(clog2DADDR+clog2DADDR+clog2PADDR-1 downto 0); + end record tPIF; + signal sP : tPIF; + + type tP is record + OISC_SUBLEQ_iPWE : std_logic; + OISC_SUBLEQ_iPADDR : integer range 0 to 2**clog2PADDR-1; + OISC_SUBLEQ_iPINST : std_logic_vector(clog2DADDR+clog2DADDR+clog2PADDR-1 downto 0); + DONE : std_logic; + end record tP; + constant cP : tP := ( + OISC_SUBLEQ_iPWE => '0', + OISC_SUBLEQ_iPADDR => 0, + OISC_SUBLEQ_iPINST => (clog2DADDR+clog2DADDR+clog2PADDR-1 downto 0 => '0'), + DONE => '0' + ); + signal rP : tP := cP; + + type tDIF is record + OISC_SUBLEQ_oDDATA : std_logic_vector(cDW-1 downto 0); + end record tDIF; + signal sD : tDIF; + + type tD is record + OISC_SUBLEQ_iDWE : std_logic; + OISC_SUBLEQ_iDADDR : integer range 0 to 2**clog2DADDR-1; + OISC_SUBLEQ_iDDATA : std_logic_vector(cDW-1 downto 0); + DONE : std_logic; + end record tD; + constant cD : tD := ( + OISC_SUBLEQ_iDWE => '0', + OISC_SUBLEQ_iDADDR => 0, + OISC_SUBLEQ_iDDATA => (cDW-1 downto 0 => '0'), + DONE => '0' + ); + signal rD : tD := cD; + + type tIF is record + OISC_SUBLEQ_oACT : std_logic; + OISC_SUBLEQ_oPC : integer range 0 to 2**clog2PADDR-1; + OISC_SUBLEQ_oLEQ : std_logic; + end record tIF; + signal s : tIF; + + type t is record + ACT : std_logic; + DONE : std_logic; + end record t; + constant c : t := ( + ACT => '0', + DONE => '0' + ); + signal r : t := c; + +begin + + P_sPCLK : process + begin + sPCLK <= '0'; wait for cPCLK_CYCLE/2; + sPCLK <= '1'; wait for cPCLK_CYCLE/2; + end process P_sPCLK; + + P_sDCLK : process + begin + sDCLK <= '0'; wait for cDCLK_CYCLE/2; + sDCLK <= '1'; wait for cDCLK_CYCLE/2; + end process P_sDCLK; + + P_sCLK : process + begin + sCLK <= '0'; wait for cCLK_CYCLE/2; + sCLK <= '1'; wait for cCLK_CYCLE/2; + end process P_sCLK; + + P_sCLR : process + begin + sCLR <= '1'; wait for cCLR_TIME; + sCLR <= '0'; wait; + end process P_sCLR; + + B_STIM : block is + pure function fINST ( + iA : integer range 0 to 2**clog2DADDR-1; + iB : integer range 0 to 2**clog2DADDR-1; + iC : integer range 0 to 2**clog2PADDR-1 + ) return std_logic_vector is + variable vA : std_logic_vector(clog2DADDR-1 downto 0); + variable vB : std_logic_vector(clog2DADDR-1 downto 0); + variable vC : std_logic_vector(clog2PADDR-1 downto 0); + begin + vA := std_logic_vector(to_unsigned(iA, clog2DADDR)); + vB := std_logic_vector(to_unsigned(iB, clog2DADDR)); + vC := std_logic_vector(to_unsigned(iC, clog2PADDR)); + return vA & vB & vC; + end function fINST; + + constant cD_Z : integer range 0 to 2**clog2DADDR-1 := 0; + constant cD_X : integer range 0 to 2**clog2DADDR-1 := 1; + constant cD_Y : integer range 0 to 2**clog2DADDR-1 := 2; + constant cV_Z : std_logic_vector(cDW-1 downto 0) := std_logic_vector(to_signed( 0, cDW)); + constant cV_X : std_logic_vector(cDW-1 downto 0) := std_logic_vector(to_signed(12, cDW)); + constant cV_Y : std_logic_vector(cDW-1 downto 0) := std_logic_vector(to_signed(34, cDW)); + constant cP_ORG : integer range 0 to 2**clog2PADDR-1 := 0; + constant cP_START : integer range 0 to 2**clog2PADDR-1 := cP_ORG+8; + constant cP_STOP : integer range 0 to 2**clog2PADDR-1 := 2**clog2PADDR-1; + begin + P_STIM_P : process + begin + -- ORG: JMP START = ORG: subleq Z, Z, START + rP.OISC_SUBLEQ_iPADDR <= cP_ORG; + rP.OISC_SUBLEQ_iPINST <= fINST(cD_Z, cD_Z, cP_START); + rP.OISC_SUBLEQ_iPWE <= '1'; + wait until (rising_edge(sPCLK)); + + -- START: ADD X, Y = START: subleq X, Z, START+1 + -- subleq Z, Y, START+2 + -- subleq Z, Z, START+3 + rP.OISC_SUBLEQ_iPADDR <= cP_START; + rP.OISC_SUBLEQ_iPINST <= fINST(cD_X, cD_Z, cP_START+1); + rP.OISC_SUBLEQ_iPWE <= '1'; + wait until (rising_edge(sPCLK)); + rP.OISC_SUBLEQ_iPADDR <= cP_START+1; + rP.OISC_SUBLEQ_iPINST <= fINST(cD_Z, cD_Y, cP_START+2); + rP.OISC_SUBLEQ_iPWE <= '1'; + wait until (rising_edge(sPCLK)); + rP.OISC_SUBLEQ_iPADDR <= cP_START+2; + rP.OISC_SUBLEQ_iPINST <= fINST(cD_Z, cD_Z, cP_START+3); + rP.OISC_SUBLEQ_iPWE <= '1'; + wait until (rising_edge(sPCLK)); + + -- START+3: JUMP STOP = START+3: subleq Z, Z, STOP + rP.OISC_SUBLEQ_iPADDR <= cP_START+3; + rP.OISC_SUBLEQ_iPINST <= fINST(cD_Z, cD_Z, cP_STOP); + rP.OISC_SUBLEQ_iPWE <= '1'; + wait until (rising_edge(sPCLK)); + + -- STOP: JUMP STOP = STOP: subleq Z, Z, STOP + rP.OISC_SUBLEQ_iPADDR <= cP_STOP; + rP.OISC_SUBLEQ_iPINST <= fINST(cD_Z, cD_Z, cP_STOP); + rP.OISC_SUBLEQ_iPWE <= '1'; + wait until (rising_edge(sPCLK)); + + rP <= cP; + rP.DONE <= '1'; + wait; + end process P_STIM_P; + + P_STIM_D : process + begin + rD.OISC_SUBLEQ_iDADDR <= cD_Z; + rD.OISC_SUBLEQ_iDDATA <= cV_Z; + rD.OISC_SUBLEQ_iDWE <= '1'; + wait until (rising_edge(sDCLK)); + + rD.OISC_SUBLEQ_iDADDR <= cD_X; + rD.OISC_SUBLEQ_iDDATA <= cV_X; + rD.OISC_SUBLEQ_iDWE <= '1'; + wait until (rising_edge(sDCLK)); + + rD.OISC_SUBLEQ_iDADDR <= cD_Y; + rD.OISC_SUBLEQ_iDDATA <= cV_Y; + rD.OISC_SUBLEQ_iDWE <= '1'; + wait until (rising_edge(sDCLK)); + + rD <= cD; + rD.DONE <= '1'; + wait; + end process P_STIM_D; + + P_STIM : process + begin + wait until (rP.DONE = '1' and rD.DONE = '1' and sCLR /= '1'); + wait until (rising_edge(sCLK)); + + r.ACT <= '1'; + wait until (rising_edge(sCLK)); + + wait until (s.OISC_SUBLEQ_oPC = cP_STOP); + + r.ACT <= '0'; + r.DONE <= '1'; + wait; + end process P_STIM; + end block B_STIM; + + U_OISC_SUBLEQ : OISC_SUBLEQ + generic map ( + log2PADDR => clog2PADDR, + log2DADDR => clog2DADDR, + DW => cDW, + ZERO => false, + ASYNC => false + ) + port map ( + iPCLK => sPCLK, + iPWE => rP.OISC_SUBLEQ_iPWE, + iPADDR => rP.OISC_SUBLEQ_iPADDR, + iPINST => rP.OISC_SUBLEQ_iPINST, + oPINST => sP.OISC_SUBLEQ_oPINST, + + iDCLK => sDCLK, + iDWE => rD.OISC_SUBLEQ_iDWE, + iDADDR => rD.OISC_SUBLEQ_iDADDR, + iDDATA => rD.OISC_SUBLEQ_iDDATA, + oDDATA => sD.OISC_SUBLEQ_oDDATA, + + iCLR => sCLR, + iCLK => sCLK, + iACT => r.ACT, + oACT => s.OISC_SUBLEQ_oACT, + oPC => s.OISC_SUBLEQ_oPC, + oLEQ => s.OISC_SUBLEQ_oLEQ + ); + +end architecture BENCH; diff --git a/testsuite/gna/bug18810/DMEM.vhd b/testsuite/gna/bug18810/DMEM.vhd new file mode 100644 index 000000000..4eb5fe2fc --- /dev/null +++ b/testsuite/gna/bug18810/DMEM.vhd @@ -0,0 +1,243 @@ +-- NOTE: http://www.eecg.toronto.edu/~steffan/papers/laforest_fpga10.pdf + +library ieee; +use ieee.std_logic_1164.all; + +package DMEM_PRIM_PKG is + + component DMEM_PRIM is + generic ( + log2A : integer range 0 to integer'high := 4; + DW : integer range 1 to integer'high := 8; + ZERO : boolean := false + ); + port ( + iWCLK : in std_logic; + iWE : in std_logic; + iWA : in integer range 0 to 2**log2A-1; + iWD : in std_logic_vector(DW-1 downto 0); + + iRA0 : in integer range 0 to 2**log2A-1; + iRA1 : in integer range 0 to 2**log2A-1; + iRA2 : in integer range 0 to 2**log2A-1; + oRD0 : out std_logic_vector(DW-1 downto 0); + oRD1 : out std_logic_vector(DW-1 downto 0); + oRD2 : out std_logic_vector(DW-1 downto 0) + ); + end component DMEM_PRIM; + + constant cDMEM_PRIM_W_LATENCY : integer := 1; + constant cDMEM_PRIM_R0_LATENCY : integer := 0; + constant cDMEM_PRIM_R1_LATENCY : integer := 0; + constant cDMEM_PRIM_R2_LATENCY : integer := 0; + +end package DMEM_PRIM_PKG; + +package body DMEM_PRIM_PKG is + + -- NOTE: This body should keep to be empty to stub. + +end package body DMEM_PRIM_PKG; + +library ieee; +use ieee.std_logic_1164.all; + +entity DMEM_PRIM is + generic ( + log2A : integer range 0 to integer'high := 4; + DW : integer range 1 to integer'high := 8; + ZERO : boolean := false + ); + port ( + iWCLK : in std_logic; + iWE : in std_logic; + iWA : in integer range 0 to 2**log2A-1; + iWD : in std_logic_vector(DW-1 downto 0); + + iRA0 : in integer range 0 to 2**log2A-1; + iRA1 : in integer range 0 to 2**log2A-1; + iRA2 : in integer range 0 to 2**log2A-1; + oRD0 : out std_logic_vector(DW-1 downto 0); + oRD1 : out std_logic_vector(DW-1 downto 0); + oRD2 : out std_logic_vector(DW-1 downto 0) + ); +begin +end entity DMEM_PRIM; + +architecture RTL of DMEM_PRIM is + + type tDMEM_PRIM is array (0 to 2**log2A-1) of std_logic_vector(DW-1 downto 0); + signal aDMEM_PRIM0 : tDMEM_PRIM := (0 to 2**log2A-1 => (DW-1 downto 0 => '0')); + signal aDMEM_PRIM1 : tDMEM_PRIM := (0 to 2**log2A-1 => (DW-1 downto 0 => '0')); + signal aDMEM_PRIM2 : tDMEM_PRIM := (0 to 2**log2A-1 => (DW-1 downto 0 => '0')); + +begin + + P_DMEM_PRIM : process (iWCLK) + begin + if (rising_edge(iWCLK)) then + if (iWE = '1') then + aDMEM_PRIM0(iWA) <= iWD; + aDMEM_PRIM1(iWA) <= iWD; + aDMEM_PRIM2(iWA) <= iWD; + end if; + end if; + end process P_DMEM_PRIM; + + oRD0 <= (DW-1 downto 0 => '0') when (ZERO = true and iRA0 = 0) else aDMEM_PRIM0(iRA0); + oRD1 <= (DW-1 downto 0 => '0') when (ZERO = true and iRA1 = 0) else aDMEM_PRIM1(iRA1); + oRD2 <= (DW-1 downto 0 => '0') when (ZERO = true and iRA2 = 0) else aDMEM_PRIM2(iRA2); + +end architecture RTL; + +library ieee; +use ieee.std_logic_1164.all; +use work.DMEM_PRIM_PKG.all; + +package DMEM_PKG is + + component DMEM is + generic ( + log2DADDR : integer range 0 to integer'high := 4; + DW : integer range 1 to integer'high := 8; + ZERO : boolean := false + ); + port ( + iDCLK : in std_logic; + iDWE : in std_logic; + iDADDR : in integer range 0 to 2**log2DADDR-1; + iDDATA : in std_logic_vector(DW-1 downto 0); + oDDATA : out std_logic_vector(DW-1 downto 0); + + iCLK : in std_logic; + iAADDR : in integer range 0 to 2**log2DADDR-1; + oADATA : out std_logic_vector(DW-1 downto 0); + iBWE : in std_logic; + iBADDR : in integer range 0 to 2**log2DADDR-1; + iBDATA : in std_logic_vector(DW-1 downto 0); + oBDATA : out std_logic_vector(DW-1 downto 0) + ); + end component DMEM; + + constant cDMEM_DW_LATENCY : integer := cDMEM_PRIM_W_LATENCY; + constant cDMEM_DR_LATENCY : integer := cDMEM_PRIM_R0_LATENCY; + constant cDMEM_AR_LATENCY : integer := cDMEM_PRIM_R1_LATENCY; + constant cDMEM_BW_LATENCY : integer := cDMEM_PRIM_W_LATENCY; + constant cDMEM_BR_LATENCY : integer := cDMEM_PRIM_R2_LATENCY; + +end package DMEM_PKG; + +package body DMEM_PKG is + + -- NOTE: This body should keep to be empty to stub. + +end package body DMEM_PKG; + +library ieee; +use ieee.std_logic_1164.all; +use work.DMEM_PRIM_PKG.all; + +entity DMEM is + generic ( + log2DADDR : integer range 0 to integer'high := 4; + DW : integer range 1 to integer'high := 8; + ZERO : boolean := false + ); + port ( + iDCLK : in std_logic; + iDWE : in std_logic; + iDADDR : in integer range 0 to 2**log2DADDR-1; + iDDATA : in std_logic_vector(DW-1 downto 0); + oDDATA : out std_logic_vector(DW-1 downto 0); + + iCLK : in std_logic; + iAADDR : in integer range 0 to 2**log2DADDR-1; + oADATA : out std_logic_vector(DW-1 downto 0); + iBWE : in std_logic; + iBADDR : in integer range 0 to 2**log2DADDR-1; + iBDATA : in std_logic_vector(DW-1 downto 0); + oBDATA : out std_logic_vector(DW-1 downto 0) + ); +begin +end entity DMEM; + +architecture RTL of DMEM is + + -- FIXME: ISE 13.2 does not support "protected"... :( + type tBANK is (BANK_D, BANK_B); + type tLVT is array (0 to 2**log2DADDR-1) of tBANK; + shared variable aLVT : tLVT := (0 to 2**log2DADDR-1 => BANK_D); + + signal sDMEM_PRIM_D_oDDATA : std_logic_vector(DW-1 downto 0); + signal sDMEM_PRIM_D_oADATA : std_logic_vector(DW-1 downto 0); + signal sDMEM_PRIM_D_oBDATA : std_logic_vector(DW-1 downto 0); + + signal sDMEM_PRIM_B_oDDATA : std_logic_vector(DW-1 downto 0); + signal sDMEM_PRIM_B_oADATA : std_logic_vector(DW-1 downto 0); + signal sDMEM_PRIM_B_oBDATA : std_logic_vector(DW-1 downto 0); + +begin + + P_LVT_D : process (iDCLK) + begin + if (rising_edge(iDCLK)) then + if (iDWE = '1') then + aLVT(iDADDR) := BANK_D; + end if; + end if; + end process P_LVT_D; + + P_LVT_B : process (iCLK) + begin + if (rising_edge(iCLK)) then + if (iBWE = '1') then + aLVT(iBADDR) := BANK_B; + end if; + end if; + end process P_LVT_B; + + U_DMEM_PRIM_D : DMEM_PRIM + generic map ( + log2A => log2DADDR, + DW => DW, + ZERO => ZERO + ) + port map ( + iWCLK => iDCLK, + iWE => iDWE, + iWA => iDADDR, + iWD => iDDATA, + + iRA0 => iDADDR, + iRA1 => iAADDR, + iRA2 => iBADDR, + oRD0 => sDMEM_PRIM_D_oDDATA, + oRD1 => sDMEM_PRIM_D_oADATA, + oRD2 => sDMEM_PRIM_D_oBDATA + ); + + U_DMEM_PRIM_B : DMEM_PRIM + generic map ( + log2A => log2DADDR, + DW => DW, + ZERO => ZERO + ) + port map ( + iWCLK => iCLK, + iWE => iBWE, + iWA => iBADDR, + iWD => iBDATA, + + iRA0 => iDADDR, + iRA1 => iAADDR, + iRA2 => iBADDR, + oRD0 => sDMEM_PRIM_B_oDDATA, + oRD1 => sDMEM_PRIM_B_oADATA, + oRD2 => sDMEM_PRIM_B_oBDATA + ); + + oDDATA <= sDMEM_PRIM_D_oDDATA when (aLVT(iDADDR) = BANK_D) else sDMEM_PRIM_B_oDDATA; + oADATA <= sDMEM_PRIM_D_oADATA when (aLVT(iAADDR) = BANK_D) else sDMEM_PRIM_B_oADATA; + oBDATA <= sDMEM_PRIM_D_oBDATA when (aLVT(iBADDR) = BANK_D) else sDMEM_PRIM_B_oBDATA; + +end architecture RTL; diff --git a/testsuite/gna/bug18810/OISC_SUBLEQ.vhd b/testsuite/gna/bug18810/OISC_SUBLEQ.vhd new file mode 100644 index 000000000..5141fbd22 --- /dev/null +++ b/testsuite/gna/bug18810/OISC_SUBLEQ.vhd @@ -0,0 +1,339 @@ +library ieee; +use ieee.std_logic_1164.all; +use work.DMEM_PKG.all; + +package OISC_SUBLEQ_PKG is + + component OISC_SUBLEQ is + generic ( + log2PADDR : integer range 0 to integer'high := 8; + log2DADDR : integer range 0 to integer'high := 4; + DW : integer range 1 to integer'high := 8; + ZERO : boolean := false; + LVT_DMEM : boolean := true; + ASYNC : boolean := false + ); + port ( + iPCLK : in std_logic; + iPWE : in std_logic; + iPADDR : in integer range 0 to 2**log2PADDR-1; + iPINST : in std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); + oPINST : out std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); + + iDCLK : in std_logic; + iDWE : in std_logic; + iDADDR : in integer range 0 to 2**log2DADDR-1; + iDDATA : in std_logic_vector(DW-1 downto 0); + oDDATA : out std_logic_vector(DW-1 downto 0); + + iCLR : in std_logic; + iCLK : in std_logic; + iACT : in std_logic; + oACT : out std_logic; + oPC : out integer range 0 to 2**log2PADDR-1; + oLEQ : out std_logic + ); + end component OISC_SUBLEQ; + + constant cOISC_SUBLEQ_PW_LATENCY : integer := 1; + constant cOISC_SUBLEQ_PR_LATENCY : integer := 0; + constant cOISC_SUBLEQ_LATENCY : integer := 1; + + pure function fOISC_SUBLEQ_DW_LATENCY ( + iLVT_DMEM : boolean + ) return integer; + pure function fOISC_SUBLEQ_DR_LATENCY ( + iLVT_DMEM : boolean + ) return integer; + +end package OISC_SUBLEQ_PKG; + +package body OISC_SUBLEQ_PKG is + + pure function fOISC_SUBLEQ_DW_LATENCY ( + iLVT_DMEM : boolean + ) return integer is + begin + if (iLVT_DMEM = true) then + return cDMEM_DW_LATENCY; + else + return 1; + end if; + end function fOISC_SUBLEQ_DW_LATENCY; + + pure function fOISC_SUBLEQ_DR_LATENCY ( + iLVT_DMEM : boolean + ) return integer is + begin + if (iLVT_DMEM = true) then + return cDMEM_DR_LATENCY; + else + return 0; + end if; + end function fOISC_SUBLEQ_DR_LATENCY; + +end package body OISC_SUBLEQ_PKG; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.DMEM_PKG.all; + +entity OISC_SUBLEQ is + generic ( + log2PADDR : integer range 0 to integer'high := 8; + log2DADDR : integer range 0 to integer'high := 4; + DW : integer range 1 to integer'high := 8; + ZERO : boolean := true; + LVT_DMEM : boolean := true; + ASYNC : boolean := false + ); + port ( + iPCLK : in std_logic; + iPWE : in std_logic; + iPADDR : in integer range 0 to 2**log2PADDR-1; + iPINST : in std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); + oPINST : out std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); + + iDCLK : in std_logic; + iDWE : in std_logic; + iDADDR : in integer range 0 to 2**log2DADDR-1; + iDDATA : in std_logic_vector(DW-1 downto 0); + oDDATA : out std_logic_vector(DW-1 downto 0); + + iCLR : in std_logic; + iCLK : in std_logic; + iACT : in std_logic; + oACT : out std_logic; + oPC : out integer range 0 to 2**log2PADDR-1; + oLEQ : out std_logic + ); +begin + -- RTL_SYNTHESIS OFF + A_DMEM_AR_LATENCY : assert (not (LVT_DMEM = true and cDMEM_AR_LATENCY /= 0)) + report OISC_SUBLEQ'instance_name & + "cDMEM_AR_LATENCY =" & integer'image(cDMEM_AR_LATENCY) + severity warning; + A_DMEM_BW_LATENCY : assert (not (LVT_DMEM = true and cDMEM_BW_LATENCY /= 1)) + report OISC_SUBLEQ'instance_name & + "cDMEM_BW_LATENCY =" & integer'image(cDMEM_BW_LATENCY) + severity warning; + A_DMEM_BR_LATENCY : assert (not (LVT_DMEM = true and cDMEM_BR_LATENCY /= 0)) + report OISC_SUBLEQ'instance_name & + "cDMEM_BR_LATENCY =" & integer'image(cDMEM_BR_LATENCY) + severity warning; + -- RTL_SYNTHESIS ON +end entity OISC_SUBLEQ; + +architecture TP of OISC_SUBLEQ is + + type tIF is record + PMEM_oA : integer range 0 to 2**log2DADDR-1; + PMEM_oB : integer range 0 to 2**log2DADDR-1; + PMEM_oC : integer range 0 to 2**log2PADDR-1; + DMEM_oA : std_logic_vector(DW-1 downto 0); + DMEM_oB : std_logic_vector(DW-1 downto 0); + end record tIF; + signal s : tIF; + + type t is record + ACT : std_logic; + SUB : std_logic_vector(DW-1 downto 0); + PC : integer range 0 to 2**log2PADDR-1; + LEQ : std_logic; + end record t; + constant c : t := ( + ACT => '0', + SUB => (DW-1 downto 0 => '0'), + PC => 0, + LEQ => '0' + ); + signal g : t; + signal r : t := c; + +begin + + B_BLOB : block is + type tPMEM is array (0 to 2**log2PADDR-1) of std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); + signal aPMEM : tPMEM := (0 to 2**log2PADDR-1 => (log2DADDR+log2DADDR+log2PADDR-1 downto 0 => '0')); + + signal gPMEM_oINST : std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); + signal gPMEM_oA : std_logic_vector(log2DADDR-1 downto 0); + signal gPMEM_oB : std_logic_vector(log2DADDR-1 downto 0); + signal gPMEM_oC : std_logic_vector(log2PADDR-1 downto 0); + begin + P_PMEM_P : process (iPCLK) + begin + if (rising_edge(iPCLK)) then + if (iPWE = '1') then + aPMEM(iPADDR) <= iPINST; + end if; + end if; + end process P_PMEM_P; + + oPINST <= aPMEM(iPADDR); + gPMEM_oINST <= aPMEM(r.PC); + gPMEM_oA <= gPMEM_oINST(log2DADDR+log2DADDR+log2PADDR-1 downto log2DADDR+log2PADDR); + gPMEM_oB <= gPMEM_oINST( log2DADDR+log2PADDR-1 downto log2PADDR); + gPMEM_oC <= gPMEM_oINST( log2PADDR-1 downto 0); + s.PMEM_oA <= to_integer(unsigned(gPMEM_oA)); + s.PMEM_oB <= to_integer(unsigned(gPMEM_oB)); + s.PMEM_oC <= to_integer(unsigned(gPMEM_oC)); + + G_LVT_DMEM : if (LVT_DMEM = true) generate + begin + U_DMEM : DMEM + generic map ( + log2DADDR => log2DADDR, + DW => DW, + ZERO => ZERO + ) + port map ( + iDCLK => iDCLK, + iDWE => iDWE, + iDADDR => iDADDR, + iDDATA => iDDATA, + oDDATA => oDDATA, + + iCLK => iCLK, + iAADDR => s.PMEM_oA, + oADATA => s.DMEM_oA, + iBWE => iACT, + iBADDR => s.PMEM_oB, + iBDATA => g.SUB, + oBDATA => s.DMEM_oB + ); + end generate G_LVT_DMEM; + + G_2W3R_DMEM : if (LVT_DMEM = false) generate + -- FIXME: ISE 13.2 does not support "protected"... :( + --type tDMEM is protected + -- procedure pWRITE( + -- iADDR : in integer range 0 to 2**log2DADDR-1; + -- iDATA : in std_logic_vector(DW-1 downto 0) + -- ); + -- impure function fREAD( + -- iADDR : integer range 0 to 2**log2DADDR-1 + -- ) return std_logic_vector; + --end protected tDMEM; + --type tDMEM is protected body + -- type tDMEM_PRIM is array (0 to 2**log2DADDR-1) of std_logic_vector(DW-1 downto 0); + -- variable aDMEM_PRIM : tDMEM_PRIM := (0 to 2**log2DADDR-1 => (DW-1 downto 0 => '0')); + -- procedure pWRITE( + -- iADDR : in integer range 0 to 2**log2DADDR-1; + -- iDATA : in std_logic_vector(DW-1 downto 0) + -- ) is + -- begin + -- aDMEM_PRIM(iADDR) := iDATA; + -- end procedure pWRITE; + -- impure function fREAD( + -- iADDR : integer range 0 to 2**log2DADDR-1 + -- ) return std_logic_vector is + -- begin + -- return aDMEM_PRIM(iADDR); + -- end function fREAD; + --end protected body tDMEM; + --shared variable aDMEM : tDMEM; + + -- FIXME: VHDL-93 shared variable does not provide mutex... :( + type tDMEM is array (0 to 2**log2DADDR-1) of std_logic_vector(DW-1 downto 0); + shared variable aDMEM : tDMEM := (0 to 2**log2DADDR-1 => (DW-1 downto 0 => '0')); + begin + P_DMEM_D : process (iDCLK) + begin + if (rising_edge(iDCLK)) then + if (iDWE = '1') then + --aDMEM.pWRITE(iDADDR, iDDATA); + aDMEM(iDADDR) := iDDATA; + end if; + end if; + end process P_DMEM_D; + + --oDDATA <= (DW-1 downto 0 => '0') when (ZERO = true and iDADDR = 0) else aDMEM.fREAD(iDADDR); + --s.DMEM_oA <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oA = 0) else aDMEM.fREAD(s.PMEM_oA); + --s.DMEM_oB <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oB = 0) else aDMEM.fREAD(s.PMEM_oB); + oDDATA <= (DW-1 downto 0 => '0') when (ZERO = true and iDADDR = 0) else aDMEM(iDADDR); + s.DMEM_oA <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oA = 0) else aDMEM(s.PMEM_oA); + s.DMEM_oB <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oB = 0) else aDMEM(s.PMEM_oB); + + -- FIXME: This DMEM write back is kludge... :( + P_DMEM_WRITE_BACK : process (iCLK) + begin + if (rising_edge(iCLK)) then + if (iACT = '1') then + --aDMEM.pWRITE(s.PMEM_oB, g.SUB); + aDMEM(s.PMEM_oB) := g.SUB; + end if; + end if; + end process P_DMEM_WRITE_BACK; + end generate G_2W3R_DMEM; + end block B_BLOB; + + P_COMB : process (iACT, r, s) + variable v : t := c; + pure function fSUB ( + iA : std_logic_vector(DW-1 downto 0); + iB : std_logic_vector(DW-1 downto 0) + ) return std_logic_vector is + variable vSUB : signed(DW-1 downto 0); + begin + -- FIXME: Consider th3 borrow? + vSUB := signed(iB) - signed(iA); + return std_logic_vector(vSUB); + end function fSUB; + begin + if (iACT = '1') then + v.ACT := '1'; + v.SUB := fSUB(s.DMEM_oA, s.DMEM_oB); + if (signed(v.SUB) <= 0) then + v.PC := s.PMEM_oC; + v.LEQ := '1'; + else + if (r.PC >= 2**log2PADDR-1) then + v.PC := 0; + else + v.PC := r.PC + 1; + end if; + v.LEQ := '0'; + end if; + else + v.ACT := '0'; + v.SUB := r.SUB; + v.PC := r.PC; + v.LEQ := r.LEQ; + end if; + + g <= v; + + oACT <= r.ACT; + oPC <= r.PC; + oLEQ <= r.LEQ; + end process P_COMB; + + G_ASYNC : if (ASYNC = true) generate + begin + P_SEQ : process (iCLR, iCLK) + begin + if (iCLR = '1') then + r <= c; + elsif (rising_edge(iCLK)) then + r <= g; + end if; + end process P_SEQ; + end generate G_ASYNC; + + G_SYNC : if (ASYNC = false) generate + begin + P_SEQ : process (iCLK) + begin + if (rising_edge(iCLK)) then + if (iCLR = '1') then + r <= c; + else + r <= g; + end if; + end if; + end process P_SEQ; + end generate G_SYNC; + +end architecture TP; diff --git a/testsuite/gna/bug18810/testsuite.sh b/testsuite/gna/bug18810/testsuite.sh new file mode 100755 index 000000000..c617e5d28 --- /dev/null +++ b/testsuite/gna/bug18810/testsuite.sh @@ -0,0 +1,10 @@ +#! /bin/sh + +. ../../testenv.sh + +analyze DMEM.vhd OISC_SUBLEQ.vhd BENCH_OISC_SUBLEQ.vhd +elab_simulate BENCH_OISC_SUBLEQ --stop-time=2us + +clean + +echo "Test successful" -- cgit v1.2.3