diff options
Diffstat (limited to 'testsuite/gna/issue467/AbstractMmPkg.vhd')
-rw-r--r-- | testsuite/gna/issue467/AbstractMmPkg.vhd | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/testsuite/gna/issue467/AbstractMmPkg.vhd b/testsuite/gna/issue467/AbstractMmPkg.vhd new file mode 100644 index 000000000..2752a07c2 --- /dev/null +++ b/testsuite/gna/issue467/AbstractMmPkg.vhd @@ -0,0 +1,651 @@ +------------------------------------------------------------------------------- +-- Title : Abstract Memory-Mapped Interface +-- Project : +------------------------------------------------------------------------------- +-- File : AbstractMmPkg.vhd +-- Author : Rob Gaddi <rgaddi@highlandtechnology.com> +-- Company : Highland Technology, Inc. +-- Created : 20-Nov-2017 +-- Last update: 2017-11-25 +-- Platform : Simulation +-- Standard : VHDL-2008 +------------------------------------------------------------------------------- +-- Description: Support package for abstract memory-mapped interface BFMs. +------------------------------------------------------------------------------- +-- Revision History: +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; +use osvvm.AlertLogPkg.all; +use osvvm.TbUtilPkg.all; +use osvvm.ResolutionPkg.all; + +package AbstractMmPkg is + + ----------------------------------------------------------------------- + -- Constants and Types + ----------------------------------------------------------------------- + + type AlertLogIDArrayType is array(integer range <>) of AlertLogIDType; + function alert_resolver(ta: AlertLogIDArrayType) return AlertLogIDType; + subtype ResolvedAlert is alert_resolver AlertLogIDType; + + -- Transaction types + type TransactionType_unresolved is ( + NONE, + SINGLE, + + LINEAR_BURST, + CONSTANT_BURST, + CYCLE_BURST, + + BURST_DATA, + + PARAM + ); + type TransactionArrayType is array(integer range <>) of TransactionType_unresolved; + function resolved(ta: TransactionArrayType) return TransactionType_unresolved; + subtype TransactionType is resolved TransactionType_unresolved; + + type AbstractMmRecType is record + writedata : std_logic_vector; + readdata : std_logic_vector; + address : unsigned; + byteen : std_logic_vector; + write : std_logic; + burstlen : integer_max; + trans : TransactionType; + + addressiswords : std_logic; + alert : ResolvedAlert; + + rdy : std_logic; + ack : std_logic; + end record AbstractMmRecType; + + constant AMR_READ: std_logic := '0'; + constant AMR_WRITE: std_logic := '1'; + + constant AMR_ADDRESS_BYTES : std_logic := '0'; + constant AMR_ADDRESS_WORDS : std_logic := '1'; + + constant ALRT : AlertLogIDType := GetAlertLogID("AbstractMmPkg"); + + ----------------------------------------------------------------------- + -- Driver Functions + ----------------------------------------------------------------------- + + -- AmrRead (single read) + procedure AmrRead( + data: out std_logic_vector; + addr: in unsigned; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrRead( + data: out std_logic_vector; + addr: in std_logic_vector; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrRead( + data: out std_logic_vector; + addr: in natural; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrRead( + data: out std_logic_vector; + addr: in unsigned; + signal rec: inout AbstractMmRecType + ); + procedure AmrRead( + data: out std_logic_vector; + addr: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrRead( + data: out std_logic_vector; + addr: in natural; + signal rec: inout AbstractMmRecType + ); + + -- AmrWrite (single write) + procedure AmrWrite( + data: in std_logic_vector; + addr: in unsigned; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrWrite( + data: in std_logic_vector; + addr: in std_logic_vector; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrWrite( + data: in std_logic_vector; + addr: in natural; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrWrite( + data: in std_logic_vector; + addr: in unsigned; + signal rec: inout AbstractMmRecType + ); + procedure AmrWrite( + data: in std_logic_vector; + addr: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrWrite( + data: in std_logic_vector; + addr: in natural; + signal rec: inout AbstractMmRecType + ); + + -- AmrAssert (single assert) + procedure AmrAssert( + data: in std_logic_vector; + addr: in unsigned; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrAssert( + data: in std_logic_vector; + addr: in std_logic_vector; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrAssert( + data: in std_logic_vector; + addr: in natural; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrAssert( + data: in std_logic_vector; + addr: in unsigned; + signal rec: inout AbstractMmRecType + ); + procedure AmrAssert( + data: in std_logic_vector; + addr: in std_logic_vector; + signal rec: inout AbstractMmRecType + ); + procedure AmrAssert( + data: in std_logic_vector; + addr: in natural; + signal rec: inout AbstractMmRecType + ); + + ----------------------------------------------------------------------- + -- Model Support Functions + ----------------------------------------------------------------------- + + procedure InterpretByteEnable( + rec : in AbstractMmRecType; + width : out natural; + align : out natural + ); + + function GetByteAddress(rec: in AbstractMmRecType; unalign: boolean := false) return unsigned; + function GetWordAddress(rec: in AbstractMmRecType) return unsigned; + + ----------------------------------------------------------------------- + -- Utility Functions + ----------------------------------------------------------------------- + + -- Initialization + procedure InitializeAmr(signal rec: out AbstractMmRecType); +-- function INIT_AMR(datalen, addrlen : positive) return AbstractMmRecType; +-- function INIT_AMR(datalen, addrlen, belen : positive) return AbstractMmRecType; + + -- Selecting word/byte addressing + procedure SetAddressWords(signal rec: inout AbstractMmRecType); + procedure SetAddressBytes(signal rec: inout AbstractMmRecType); + + -- Overriding the default alert + procedure OverrideAlert(signal rec: inout AbstractMmRecType; alert: AlertLogIDType); + +end package AbstractMmPkg; + +package body AbstractMmPkg is + + procedure InitializeAmr(signal rec: out AbstractMmRecType) is + variable local : AbstractMmRecType( + writedata(rec.writedata'range), + readdata(rec.readdata'range), + address(rec.address'range), + byteen(rec.byteen'range) + ); + constant WD : std_logic_vector(rec.writedata'range) := (others => 'Z'); + constant RD : std_logic_vector(rec.readdata'range) := (others => 'Z'); + constant AD : unsigned(rec.address'range) := (others => 'Z'); + constant BE : std_logic_vector(rec.byteen'range) := (others => 'Z'); + begin + local := ( + writedata => WD, + readdata => RD, + address => AD, + byteen => BE, + write => 'Z', + burstlen => integer'left, + trans => NONE, + addressiswords => 'Z', + alert => ALRT, + rdy => 'Z', + ack => 'Z' + ); + rec <= local; + end procedure InitializeAmr; + + --function INIT_AMR( + -- datalen, addrlen : positive + --) return AbstractMmRecType is + -- constant belen : positive := datalen / 8; + --begin + -- return INIT_AMR(datalen, addrlen, belen); + --end function INIT_AMR; + + --function INIT_AMR( + -- datalen, addrlen, belen: positive + --) return AbstractMmRecType is + --begin + -- return ( + -- writedata => (datalen downto 1 => 'Z'), + -- readdata => (datalen downto 1 => 'Z'), + -- address => (addrlen downto 1 => 'Z'), + -- byteen => (belen downto 1 => 'Z'), + -- write => 'Z', + -- burstlen => integer'left, + -- trans => NONE, + + -- addressiswords => 'Z', + -- alert => ALRT, + + -- rdy => 'Z', + -- ack => 'Z' + -- ); + --end function INIT_AMR; + + procedure SetAddressWords(signal rec: inout AbstractMmRecType) is + begin + rec.addressiswords <= AMR_ADDRESS_WORDS; + end procedure SetAddressWords; + + procedure SetAddressBytes(signal rec: inout AbstractMmRecType) is + begin + rec.addressiswords <= AMR_ADDRESS_BYTES; + end procedure SetAddressBytes; + + ----------------------------------------------------------------------- + -- AmrRead + ----------------------------------------------------------------------- + + procedure AmrRead( + data: out std_logic_vector; + addr: in unsigned; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + constant WD : std_logic_vector(rec.writedata'range) := (others => 'X'); + begin + rec.writedata <= WD; + rec.address <= RESIZE(addr, rec.address'length); + rec.byteen <= byteen; + rec.write <= AMR_READ; + rec.burstlen <= 1; + rec.trans <= SINGLE; + RequestTransaction(rec.rdy, rec.ack); + data := rec.readdata; + end procedure AmrRead; + + procedure AmrRead( + data: out std_logic_vector; + addr: in std_logic_vector; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + begin + AmrRead(data, UNSIGNED(addr), byteen, rec); + end procedure AmrRead; + + procedure AmrRead( + data: out std_logic_vector; + addr: in natural; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + begin + AmrRead(data, TO_UNSIGNED(addr, rec.address'length), byteen, rec); + end procedure AmrRead; + + procedure AmrRead( + data: out std_logic_vector; + addr: in unsigned; + signal rec: inout AbstractMmRecType + ) is + variable byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrRead(data, addr, byteen, rec); + end procedure AmrRead; + + procedure AmrRead( + data: out std_logic_vector; + addr: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + variable byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrRead(data, UNSIGNED(addr), byteen, rec); + end procedure AmrRead; + + procedure AmrRead( + data: out std_logic_vector; + addr: in natural; + signal rec: inout AbstractMmRecType + ) is + variable byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrRead(data, TO_UNSIGNED(addr, rec.address'length), byteen, rec); + end procedure AmrRead; + + ----------------------------------------------------------------------- + -- AmrWrite (single write) + ----------------------------------------------------------------------- + + procedure AmrWrite( + data: in std_logic_vector; + addr: in unsigned; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + begin + rec.writedata <= data; + rec.address <= RESIZE(addr, rec.address'length); + rec.byteen <= byteen; + rec.write <= AMR_WRITE; + rec.burstlen <= 1; + rec.trans <= SINGLE; + RequestTransaction(rec.rdy, rec.ack); + end procedure AmrWrite; + + procedure AmrWrite( + data: in std_logic_vector; + addr: in std_logic_vector; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is begin + AmrWrite(data, UNSIGNED(addr), byteen, rec); + end procedure AmrWrite; + + procedure AmrWrite( + data: in std_logic_vector; + addr: in natural; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is begin + AmrWrite(data, TO_UNSIGNED(addr, rec.address'length), byteen, rec); + end procedure AmrWrite; + + procedure AmrWrite( + data: in std_logic_vector; + addr: in unsigned; + signal rec: inout AbstractMmRecType + ) is + constant byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrWrite(data, addr, byteen, rec); + end procedure AmrWrite; + + procedure AmrWrite( + data: in std_logic_vector; + addr: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + constant byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrWrite(data, UNSIGNED(addr), byteen, rec); + end procedure AmrWrite; + + procedure AmrWrite( + data: in std_logic_vector; + addr: in natural; + signal rec: inout AbstractMmRecType + ) is + constant byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrWrite(data, TO_UNSIGNED(addr, rec.address'length), byteen, rec); + end procedure AmrWrite; + + ----------------------------------------------------------------------- + -- AmrAssert (single assert) + ----------------------------------------------------------------------- + + procedure AmrAssert( + data: in std_logic_vector; + addr: in unsigned; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + variable readdata : std_logic_vector(data'range); + begin + AmrRead(readdata, addr, byteen, rec); + --AffirmIfEqual(rec.alert, readdata, data, "Assert @ 0x" & TO_HSTRING(addr)); + end procedure AmrAssert; + + procedure AmrAssert( + data: in std_logic_vector; + addr: in std_logic_vector; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is begin + AmrAssert(data, UNSIGNED(addr), byteen, rec); + end procedure AmrAssert; + + procedure AmrAssert( + data: in std_logic_vector; + addr: in natural; + byteen: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is begin + AmrAssert(data, TO_UNSIGNED(addr, rec.address'length), byteen, rec); + end procedure AmrAssert; + + procedure AmrAssert( + data: in std_logic_vector; + addr: in unsigned; + signal rec: inout AbstractMmRecType + ) is + constant byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrAssert(data, addr, byteen, rec); + end procedure AmrAssert; + + procedure AmrAssert( + data: in std_logic_vector; + addr: in std_logic_vector; + signal rec: inout AbstractMmRecType + ) is + constant byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrAssert(data, UNSIGNED(addr), byteen, rec); + end procedure AmrAssert; + + procedure AmrAssert( + data: in std_logic_vector; + addr: in natural; + signal rec: inout AbstractMmRecType + ) is + constant byteen : std_logic_vector(rec.byteen'range) := (others => '1'); + begin + AmrAssert(data, TO_UNSIGNED(addr, rec.address'length), byteen, rec); + end procedure AmrAssert; + + ----------------------------------------------------------------------- + -- Utility Functions + ----------------------------------------------------------------------- + + -- Turn a number into the number of bits needed to represent it. + function clog2(x : positive) return natural is + variable y : natural := 1; + begin + for log in 0 to 255 loop + if y >= x then + return log; + end if; + y := y * 2; + end loop; + return natural'right; + end function clog2; + + -- Allow only 1 entry to be other than NONE. + function resolved(ta: TransactionArrayType) return TransactionType_unresolved is + variable r : TransactionType_unresolved := NONE; + variable t : TransactionType_unresolved; + begin + for idx in ta'range loop + t := ta(idx); + if t /= NONE then + assert r = NONE + report "Multiple non-NONE transaction types." + severity failure; + r := t; + end if; + end loop; + return r; + end function resolved; + + -- Allow up to 1 entry to be other than our local ALRT, in which + -- case it wins. + function alert_resolver(ta: AlertLogIDArrayType) return AlertLogIDType is + variable r : AlertLogIDType := ALRT; + variable t : AlertLogIDType; + begin + for idx in ta'range loop + t := ta(idx); + if (t /= ALRT) and (t >= ALERTLOG_BASE_ID) then + assert r = ALRT + report "Multiple alerts provided." + severity failure; + r := t; + end if; + end loop; + return r; + end function alert_resolver; + + procedure InterpretByteEnable( + rec : in AbstractMmRecType; + width : out natural; + align : out natural + ) is + alias byteen : std_logic_vector(rec.byteen'range) is rec.byteen; + alias LA : AlertLogIDType is rec.alert; + variable first, last: integer; + variable found : boolean := false; + begin + if (and byteen) = '1' then + -- Try to provide fast resolution for the most common case. + width := byteen'length; + align := 0; + else + -- Alright, do it the hard way. Scan for contiguous enables. + for i in byteen'low to byteen'high loop + if byteen(i) = '1' then + found := true; + first := i; + exit; + end if; + end loop; + + if not found then + -- No byte enables are set + Alert(LA, "No byte enables set.", WARNING); + width := 0; + align := 0; + else + last := first; + for i in first+1 to byteen'high loop + if byteen(i) = '1' then + last := i; + else + exit; + end if; + end loop; + + if last /= byteen'high then + for i in last+1 to byteen'high loop + if byteen(i) = '1' then + Alert(LA, "Non-contiguous byte enables " & TO_STRING(byteen), WARNING); + exit; + end if; + end loop; + end if; + + width := last-first+1; + align := first; + end if; + end if; + end procedure InterpretByteEnable; + + function GetByteAddress(rec: in AbstractMmRecType; unalign: boolean := false) return unsigned is + variable padding : unsigned(clog2(rec.byteen'length)-1 downto 0); + variable alignment : integer := integer'left; + begin + case rec.addressiswords is + when AMR_ADDRESS_BYTES => + return rec.address; + + when AMR_ADDRESS_WORDS => + if unalign then + for i in rec.byteen'low to rec.byteen'high loop + if rec.byteen(i) = '1' then + alignment := i; + exit; + end if; + end loop; + if alignment /= integer'left then + report "All bytes disabled." severity warning; + alignment := 0; + end if; + padding := TO_UNSIGNED(alignment, padding'length); + else + padding := (others => '0'); + end if; + return rec.address & PADDING; + + when others => + report "Byte/word addressing not defined." severity failure; + return (rec.address'range => 'X'); + end case; + end function GetByteAddress; + + function GetWordAddress(rec: in AbstractMmRecType) return unsigned is + variable padding : unsigned(clog2(rec.byteen'length)-1 downto 0); + variable alignment, width : integer; + begin + case rec.addressiswords is + when AMR_ADDRESS_BYTES => + return rec.address(rec.address'high downto padding'length); + + when AMR_ADDRESS_WORDS => + return rec.address; + + when others => + report "Byte/word addressing not defined." severity failure; + return (rec.address'range => 'X'); + end case; + end function GetWordAddress; + + procedure OverrideAlert(signal rec: inout AbstractMmRecType; alert: AlertLogIDType) is + begin + rec.alert <= alert; + end procedure OverrideAlert; + +end package body AbstractMmPkg; |