aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2017-11-27 21:10:49 +0100
committerTristan Gingold <tgingold@free.fr>2017-11-27 21:10:49 +0100
commit9e4ec135ab7bfec367acbfd6e7c742b7f1d9b1ea (patch)
tree9d171046f7c457e949b9e082af9bbbf94925b11a
parent93e1e6fa9bd08d36307bd4767e94203ca123fbd5 (diff)
downloadghdl-9e4ec135ab7bfec367acbfd6e7c742b7f1d9b1ea.tar.gz
ghdl-9e4ec135ab7bfec367acbfd6e7c742b7f1d9b1ea.tar.bz2
ghdl-9e4ec135ab7bfec367acbfd6e7c742b7f1d9b1ea.zip
Add reproducer for #467
-rw-r--r--testsuite/gna/issue467/AbstractMmPkg.vhd651
-rw-r--r--testsuite/gna/issue467/axi_master.vhd170
-rw-r--r--testsuite/gna/issue467/eu_tb.vhdl30
-rw-r--r--testsuite/gna/issue467/testbench.vhdl21
-rw-r--r--testsuite/gna/issue467/testbench2.vhdl78
-rwxr-xr-xtestsuite/gna/issue467/testsuite.sh11
6 files changed, 961 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;
diff --git a/testsuite/gna/issue467/axi_master.vhd b/testsuite/gna/issue467/axi_master.vhd
new file mode 100644
index 000000000..d72f7ea55
--- /dev/null
+++ b/testsuite/gna/issue467/axi_master.vhd
@@ -0,0 +1,170 @@
+-------------------------------------------------------------------------------
+-- Title : AXI-Lite Master BFM
+-- Project : P500
+-------------------------------------------------------------------------------
+-- File : axi_master.vhd
+-- Author : Rob Gaddi <rgaddi@highlandtechnology.com>
+-- Company : Highland Technology, Inc.
+-- Created : 21-Nov-2017
+-- Last update: 21-Nov-2017
+-- Platform : Simulation
+-- Standard : VHDL-2008
+-------------------------------------------------------------------------------
+-- Description: Simulation model of an AXI4-Lite bus master.
+-------------------------------------------------------------------------------
+-- Revision History:
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library osvvm;
+use osvvm.TbUtilPkg.all;
+use osvvm.AlertLogPkg.all;
+
+use work.AbstractMmPkg.all;
+
+entity axi_master is
+ generic (
+ LOG_NAME : string := "axi_master";
+ DATAWIDTH : positive := 32;
+ ADDRWIDTH : positive := 12
+ );
+ port (
+ -- AXI interface
+ AWADDR : out std_logic_vector(ADDRWIDTH-1 downto 0);
+ AWPROT : out std_logic_vector(2 downto 0);
+ AWVALID : out std_logic;
+ AWREADY : in std_logic;
+
+ WDATA : out std_logic_vector(DATAWIDTH-1 downto 0);
+ WSTRB : out std_logic_vector((DATAWIDTH/8)-1 downto 0);
+ WVALID : out std_logic;
+ WREADY : in std_logic;
+
+ BRESP : in std_logic_vector(1 downto 0);
+ BVALID : in std_logic;
+ BREADY : out std_logic;
+
+ ARADDR : out std_logic_vector(ADDRWIDTH-1 downto 0);
+ ARPROT : out std_logic_vector(2 downto 0);
+ ARVALID : out std_logic;
+ ARREADY : in std_logic;
+
+ RDATA : in std_logic_vector(DATAWIDTH-1 downto 0);
+ RRESP : in std_logic_vector(1 downto 0);
+ RVALID : in std_logic;
+ RREADY : out std_logic;
+
+ ACLK : in std_logic;
+ ARESETn : in std_logic;
+
+ -- AMR interface
+ amr : inout AbstractMmRecType
+ );
+end entity axi_master;
+
+architecture Behavioral of axi_master is
+
+ constant ALRT : AlertLogIDType := GetAlertLogID(LOG_NAME);
+
+ signal prot: std_logic_vector(2 downto 0);
+ constant BADREADDATA : std_logic_vector(RDATA'range) := (others => 'X');
+
+begin
+
+ INITIALIZE: process
+ begin
+ prot <= (others => '0');
+ wait;
+ end process INITIALIZE;
+
+ AXI: process
+
+ procedure SingleRead is
+ variable request_ack : boolean := false;
+ begin
+ ARADDR <= STD_LOGIC_VECTOR(GetByteAddress(amr));
+ ARPROT <= prot;
+ ARVALID <= '1';
+
+ while not request_ack loop
+ wait until rising_edge(ACLK);
+ if RVALID = '1' then
+ RREADY <= '0';
+ request_ack := true;
+ end if;
+ end loop;
+
+ RREADY <= '1';
+ wait until rising_edge(ACLK) and RVALID='1';
+ if RRESP = "00" then
+ amr.readdata <= RDATA;
+ else
+ amr.readdata <= BADREADDATA;
+ end if;
+ RREADY <= '0';
+ end procedure SingleRead;
+
+ procedure SingleWrite is
+ variable addr_ack : boolean := false;
+ variable data_ack : boolean := false;
+ variable resp_ack : boolean := false;
+ begin
+ AWADDR <= STD_LOGIC_VECTOR(GetByteAddress(amr));
+ AWPROT <= prot;
+ AWVALID <= '1';
+ WDATA <= amr.writedata;
+ WSTRB <= amr.byteen;
+ WVALID <= '1';
+
+ while not (addr_ack and data_ack) loop
+ wait until rising_edge(ACLK);
+ if AWREADY = '1' then
+ AWVALID <= '0';
+ addr_ack := true;
+ end if;
+ if WREADY = '1' then
+ WVALID <= '0';
+ data_ack := true;
+ end if;
+ end loop;
+
+ BREADY <= '1';
+ wait until rising_edge(ACLK) and BVALID='1';
+ BREADY <= '0';
+ end procedure SingleWrite;
+
+ begin
+ InitializeAmr(amr);
+ amr.alert <= ALRT;
+
+ loop
+ AWVALID <= '0';
+ WVALID <= '0';
+ BREADY <= '0';
+ ARVALID <= '0';
+ RREADY <= '0';
+
+ WaitForTransaction(ACLK, amr.rdy, amr.ack);
+ if ARESETn = '0' then
+ wait until ARESETn = '1';
+ end if;
+ case amr.trans is
+ when SINGLE =>
+ if amr.write = AMR_READ then
+ SingleRead;
+ else
+ SingleWrite;
+ end if;
+
+ when others =>
+ Alert(ALRT, "Transaction type " & TransactionType'image(amr.trans) &
+ " not supported by model.", FAILURE);
+
+ end case;
+ end loop;
+ end process AXI;
+
+end architecture Behavioral;
diff --git a/testsuite/gna/issue467/eu_tb.vhdl b/testsuite/gna/issue467/eu_tb.vhdl
new file mode 100644
index 000000000..ce989056e
--- /dev/null
+++ b/testsuite/gna/issue467/eu_tb.vhdl
@@ -0,0 +1,30 @@
+package unbound_rec is
+ type UnbRecType is record
+ writedata: bit_vector;
+ end record;
+end package;
+
+use work.unbound_rec.all;
+entity eut is
+ port (
+ form_sig: out UnbRecType
+ );
+end entity;
+
+architecture foo of eut is
+begin
+end architecture;
+
+use work.unbound_rec.all;
+entity eu_tb is
+end entity;
+
+architecture fum of eu_tb is
+ signal act_sig: UnbRecType (writedata (7 downto 0));
+begin
+UUT:
+ entity work.eut
+ port map (
+ form_sig => act_sig
+ );
+end architecture;
diff --git a/testsuite/gna/issue467/testbench.vhdl b/testsuite/gna/issue467/testbench.vhdl
new file mode 100644
index 000000000..957b733dc
--- /dev/null
+++ b/testsuite/gna/issue467/testbench.vhdl
@@ -0,0 +1,21 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.AbstractMmPkg.all;
+
+entity testbench is
+end entity testbench;
+
+architecture TB of testbench is
+
+ signal rec : AbstractMmRecType(
+ writedata(31 downto 0),
+ readdata(31 downto 0),
+ address(4 downto 0),
+ byteen(3 downto 0)
+ );
+
+begin
+
+end architecture TB;
diff --git a/testsuite/gna/issue467/testbench2.vhdl b/testsuite/gna/issue467/testbench2.vhdl
new file mode 100644
index 000000000..9d611cb71
--- /dev/null
+++ b/testsuite/gna/issue467/testbench2.vhdl
@@ -0,0 +1,78 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.AbstractMmPkg.all;
+
+entity testbench is
+end entity testbench;
+
+architecture TB of testbench is
+
+ signal AWADDR : std_logic_vector(6 downto 0);
+ signal AWPROT : std_logic_vector(2 downto 0);
+ signal AWVALID : std_logic;
+ signal AWREADY : std_logic;
+ signal WDATA : std_logic_vector(31 downto 0);
+ signal WSTRB : std_logic_vector(3 downto 0);
+ signal WVALID : std_logic;
+ signal WREADY : std_logic;
+ signal BRESP : std_logic_vector(1 downto 0);
+ signal BVALID : std_logic;
+ signal BREADY : std_logic;
+ signal ARADDR : std_logic_vector(6 downto 0);
+ signal ARPROT : std_logic_vector(2 downto 0);
+ signal ARVALID : std_logic;
+ signal ARREADY : std_logic;
+ signal RDATA : std_logic_vector(31 downto 0);
+ signal RRESP : std_logic_vector(1 downto 0);
+ signal RVALID : std_logic;
+ signal RREADY : std_logic;
+ signal ACLK : std_logic;
+ signal ARESETn : std_logic;
+
+ signal rec : AbstractMmRecType(
+ writedata(31 downto 0),
+ readdata(31 downto 0),
+ address(4 downto 0),
+ byteen(3 downto 0)
+ );
+
+begin
+
+ BFM: entity work.axi_master
+ generic map (
+ DATAWIDTH => 32,
+ ADDRWIDTH => AWADDR'length
+ ) port map(
+ -- AXI interface,
+ AWADDR => AWADDR,
+ AWPROT => AWPROT,
+ AWVALID => AWVALID,
+ AWREADY => AWREADY,
+
+ WDATA => WDATA,
+ WSTRB => WSTRB,
+ WVALID => WVALID,
+ WREADY => WREADY,
+
+ BRESP => BRESP,
+ BVALID => BVALID,
+ BREADY => BREADY,
+ ARADDR => ARADDR,
+ ARPROT => ARPROT,
+ ARVALID => ARVALID,
+ ARREADY => ARREADY,
+
+ RDATA => RDATA,
+ RRESP => RRESP,
+ RVALID => RVALID,
+ RREADY => RREADY,
+
+ ACLK => ACLK,
+ ARESETn => ARESETn,
+
+ -- AMR interface
+ amr => rec
+ );
+end architecture TB;
diff --git a/testsuite/gna/issue467/testsuite.sh b/testsuite/gna/issue467/testsuite.sh
new file mode 100755
index 000000000..45609d665
--- /dev/null
+++ b/testsuite/gna/issue467/testsuite.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+. ../../testenv.sh
+
+export GHDL_STD_FLAGS=--std=08
+analyze eu_tb.vhdl
+elab_simulate eu_tb
+
+clean
+
+echo "Test successful"