summaryrefslogtreecommitdiff
path: root/testsuite/gna/bug18810/OISC_SUBLEQ.vhd
diff options
context:
space:
mode:
authorTristan Gingold2013-12-29 12:26:10 +0100
committerTristan Gingold2013-12-29 12:26:10 +0100
commit2c70ace5754bc18a151e7b4d4bde7018dd64c2af (patch)
tree59d15332b7b55320b45aa7b11647e9bf2c52bf37 /testsuite/gna/bug18810/OISC_SUBLEQ.vhd
parentcb9f13404bcc6d8d26838bc0fb2f236952deaaed (diff)
downloadghdl-2c70ace5754bc18a151e7b4d4bde7018dd64c2af.tar.gz
ghdl-2c70ace5754bc18a151e7b4d4bde7018dd64c2af.tar.bz2
ghdl-2c70ace5754bc18a151e7b4d4bde7018dd64c2af.zip
Add bug18810 testcase.
Diffstat (limited to 'testsuite/gna/bug18810/OISC_SUBLEQ.vhd')
-rw-r--r--testsuite/gna/bug18810/OISC_SUBLEQ.vhd339
1 files changed, 339 insertions, 0 deletions
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;