diff options
author | Tristan Gingold <tgingold@free.fr> | 2013-12-29 12:26:10 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2013-12-29 12:26:10 +0100 |
commit | 2c70ace5754bc18a151e7b4d4bde7018dd64c2af (patch) | |
tree | 59d15332b7b55320b45aa7b11647e9bf2c52bf37 /testsuite/gna/bug18810/OISC_SUBLEQ.vhd | |
parent | cb9f13404bcc6d8d26838bc0fb2f236952deaaed (diff) | |
download | ghdl-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.vhd | 339 |
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 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; |