summaryrefslogtreecommitdiff
path: root/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd241
-rw-r--r--testsuite/gna/bug18810/DMEM.vhd243
-rw-r--r--testsuite/gna/bug18810/OISC_SUBLEQ.vhd339
-rwxr-xr-xtestsuite/gna/bug18810/testsuite.sh10
4 files changed, 833 insertions, 0 deletions
diff --git a/testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd b/testsuite/gna/bug18810/BENCH_OISC_SUBLEQ.vhd
new file mode 100644
index 0000000..25b113f
--- /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 0000000..4eb5fe2
--- /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 0000000..5141fbd
--- /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 0000000..c617e5d
--- /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"