aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Lehmann <Paebbels@gmail.com>2021-12-15 22:10:09 +0100
committerGitHub <noreply@github.com>2021-12-15 22:10:09 +0100
commit918e15bb6fab7da8719624ac9d37a47db4751375 (patch)
treee343b717af2139c142b660a1c918bce06ecd946a
parent75bd31ff74ba3965bec27bf34a93b9c451e0d749 (diff)
parentf32d77707a2639fed94978965b3a9690c2bf7904 (diff)
downloadghdl-918e15bb6fab7da8719624ac9d37a47db4751375.tar.gz
ghdl-918e15bb6fab7da8719624ac9d37a47db4751375.tar.bz2
ghdl-918e15bb6fab7da8719624ac9d37a47db4751375.zip
Merge branch 'ghdl:master' into paebbels/pyGHDL-updates
-rw-r--r--src/ghdldrv/ghdllocal.adb17
-rw-r--r--src/ghdldrv/ghdlsynth.adb33
-rw-r--r--src/ortho/mcode/binary_file.ads2
-rw-r--r--src/ortho/mcode/ortho_code-dwarf.adb6
-rw-r--r--src/ortho/mcode/ortho_code-dwarf.ads6
-rw-r--r--src/ortho/mcode/ortho_code-x86-abi.adb62
-rw-r--r--src/ortho/mcode/ortho_code-x86-abi.ads4
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb82
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.ads6
-rw-r--r--src/ortho/mcode/ortho_code-x86-flags_linux.ads3
-rw-r--r--src/ortho/mcode/ortho_code-x86-flags_linux64.ads5
-rw-r--r--src/ortho/mcode/ortho_code-x86-flags_macosx.ads3
-rw-r--r--src/ortho/mcode/ortho_code-x86-flags_macosx64.ads3
-rw-r--r--src/ortho/mcode/ortho_code-x86-flags_windows.ads3
-rw-r--r--src/ortho/mcode/ortho_code-x86-flags_windows64.ads3
-rw-r--r--src/ortho/mcode/ortho_jit.adb2
-rw-r--r--src/synth/elab-vhdl_insts.adb12
-rw-r--r--src/synth/elab-vhdl_types.adb4
-rw-r--r--src/synth/synth-vhdl_insts.adb50
-rw-r--r--src/vhdl/vhdl-annotations.adb11
-rw-r--r--src/vhdl/vhdl-configuration.adb69
-rw-r--r--src/vhdl/vhdl-configuration.ads6
-rw-r--r--src/vhdl/vhdl-sem_expr.adb3
-rw-r--r--testsuite/gna/bug0100/name4.vhdl14
-rwxr-xr-xtestsuite/gna/bug0100/testsuite.sh1
-rw-r--r--testsuite/synth/issue412/generic_pkg.vhdl42
-rw-r--r--testsuite/synth/issue412/generic_sfifo-orig.vhdl88
-rw-r--r--testsuite/synth/issue412/generic_sfifo.vhdl88
-rw-r--r--testsuite/synth/issue412/my_fifo.vhdl31
-rw-r--r--testsuite/synth/issue412/tb_my_fifo.vhdl66
-rwxr-xr-xtestsuite/synth/issue412/testsuite.sh13
31 files changed, 648 insertions, 90 deletions
diff --git a/src/ghdldrv/ghdllocal.adb b/src/ghdldrv/ghdllocal.adb
index 4e0b0b05b..722c1a26f 100644
--- a/src/ghdldrv/ghdllocal.adb
+++ b/src/ghdldrv/ghdllocal.adb
@@ -86,7 +86,6 @@ package body Ghdllocal is
pragma Assert (Opt'First = 1);
pragma Assert (Opt'Last >= 5);
Eq_Pos : Natural;
- Id : Name_Id;
begin
Eq_Pos := 0;
for I in 3 .. Opt'Last loop
@@ -106,21 +105,9 @@ package body Ghdllocal is
return Option_Err;
end if;
- declare
- Res : String (1 .. Eq_Pos - 3) := Opt (3 .. Eq_Pos - 1);
- Err : Boolean;
- begin
- Vhdl.Scanner.Convert_Identifier (Res, Err);
- if Err then
- Error_Msg_Option
- ("incorrect generic name in generic override option");
- return Option_Err;
- end if;
- Id := Name_Table.Get_Identifier (Res);
- end;
-
Vhdl.Configuration.Add_Generic_Override
- (Id, Opt (Eq_Pos + 1 .. Opt'Last));
+ (Opt (3 .. Eq_Pos - 1), Opt (Eq_Pos + 1 .. Opt'Last));
+
return Option_Ok;
end Decode_Generic_Override_Option;
diff --git a/src/ghdldrv/ghdlsynth.adb b/src/ghdldrv/ghdlsynth.adb
index cfc5f281b..ced5b71c9 100644
--- a/src/ghdldrv/ghdlsynth.adb
+++ b/src/ghdldrv/ghdlsynth.adb
@@ -378,20 +378,25 @@ package body Ghdlsynth is
Foreign_Resolve_Instances.all;
end if;
- if Get_Kind (Get_Library_Unit (Config)) /= Iir_Kind_Foreign_Module then
- -- Check (and possibly abandon) if entity can be at the top of the
- -- hierarchy.
- declare
- Entity : constant Iir :=
- Vhdl.Utils.Get_Entity_From_Configuration (Config);
- begin
- Vhdl.Configuration.Apply_Generic_Override (Entity);
- Vhdl.Configuration.Check_Entity_Declaration_Top (Entity, False);
- if Nbr_Errors > 0 then
- return Null_Iir;
- end if;
- end;
- end if;
+ -- Check (and possibly abandon) if entity can be at the top of the
+ -- hierarchy.
+ declare
+ Config_Unit : constant Iir := Get_Library_Unit (Config);
+ Top : Iir;
+ begin
+ if Get_Kind (Config_Unit) = Iir_Kind_Foreign_Module then
+ Top := Config_Unit;
+ Vhdl.Configuration.Apply_Generic_Override (Top);
+ -- No Check_Entity_Declaration (yet).
+ else
+ Top := Vhdl.Utils.Get_Entity_From_Configuration (Config);
+ Vhdl.Configuration.Apply_Generic_Override (Top);
+ Vhdl.Configuration.Check_Entity_Declaration_Top (Top, False);
+ end if;
+ if Nbr_Errors > 0 then
+ return Null_Iir;
+ end if;
+ end;
return Config;
end Ghdl_Synth_Configure;
diff --git a/src/ortho/mcode/binary_file.ads b/src/ortho/mcode/binary_file.ads
index 08770ae3b..423f6b153 100644
--- a/src/ortho/mcode/binary_file.ads
+++ b/src/ortho/mcode/binary_file.ads
@@ -128,6 +128,7 @@ package Binary_File is
procedure Prealloc (L : Pc_Type);
-- Add bits in the current section.
+ -- Space must be pre-allocated.
procedure Gen_8 (B : Byte);
procedure Gen_8 (B0, B1 : Byte);
@@ -136,6 +137,7 @@ package Binary_File is
procedure Gen_64 (B : Unsigned_64);
-- Add bits in the current section, but as stand-alone data.
+ -- Displayed if Dump_Asm.
procedure Gen_Data_8 (B : Unsigned_8);
procedure Gen_Data_16 (B : Unsigned_32);
procedure Gen_Data_32 (Sym : Symbol; Offset : Integer_32);
diff --git a/src/ortho/mcode/ortho_code-dwarf.adb b/src/ortho/mcode/ortho_code-dwarf.adb
index cb0676891..66e527a16 100644
--- a/src/ortho/mcode/ortho_code-dwarf.adb
+++ b/src/ortho/mcode/ortho_code-dwarf.adb
@@ -13,11 +13,13 @@
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <gnu.org/licenses>.
+
+with Ada.Text_IO;
with GNAT.Directory_Operations;
+
with Tables;
-with Interfaces; use Interfaces;
+
with Dwarf; use Dwarf;
-with Ada.Text_IO;
with Ortho_Code.Flags; use Ortho_Code.Flags;
with Ortho_Code.Decls;
with Ortho_Code.Types;
diff --git a/src/ortho/mcode/ortho_code-dwarf.ads b/src/ortho/mcode/ortho_code-dwarf.ads
index 41803be84..86d5689c4 100644
--- a/src/ortho/mcode/ortho_code-dwarf.ads
+++ b/src/ortho/mcode/ortho_code-dwarf.ads
@@ -13,6 +13,8 @@
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <gnu.org/licenses>.
+with Interfaces; use Interfaces;
+
with Binary_File; use Binary_File;
package Ortho_Code.Dwarf is
@@ -29,6 +31,10 @@ package Ortho_Code.Dwarf is
procedure Set_Line_Stmt (Line : Int32);
procedure Set_Filename (Dir : String; File : String);
+ -- Low-level procedure (also used to generate .eh_frame)
+ procedure Gen_Uleb128 (V : Unsigned_32);
+ procedure Gen_Sleb128 (V : Int32);
+
type Mark_Type is limited private;
procedure Mark (M : out Mark_Type);
procedure Release (M : Mark_Type);
diff --git a/src/ortho/mcode/ortho_code-x86-abi.adb b/src/ortho/mcode/ortho_code-x86-abi.adb
index ea9be4471..306335124 100644
--- a/src/ortho/mcode/ortho_code-x86-abi.adb
+++ b/src/ortho/mcode/ortho_code-x86-abi.adb
@@ -13,6 +13,9 @@
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <gnu.org/licenses>.
+with System;
+
+with Ada.Text_IO;
with Ortho_Code.Decls; use Ortho_Code.Decls;
with Ortho_Code.Exprs; use Ortho_Code.Exprs;
with Ortho_Code.Consts;
@@ -25,7 +28,6 @@ with Ortho_Code.X86.Insns;
with Ortho_Code.X86.Emits;
with Binary_File;
with Binary_File.Memory;
-with Ada.Text_IO;
package body Ortho_Code.X86.Abi is
-- First argument is at %ebp + 8 / %rbp + 16
@@ -861,4 +863,62 @@ package body Ortho_Code.X86.Abi is
(Ortho_Code.X86.Emits.Chkstk_Symbol, Chkstk'Address);
end if;
end Link_Intrinsics;
+
+ type Void is null record;
+ type Void_Ptr is access Void;
+
+ -- From GCC unwind-dw2-fde.h
+ type Frame_Info_Object is record
+ pc_begin : Void_Ptr;
+ tbase : Void_Ptr;
+ dbase : Void_Ptr;
+ U : Void_Ptr;
+ S : Void_Ptr;
+ fde_end : Void_Ptr; -- Maybe optional
+ next : Void_Ptr;
+ end record;
+ pragma Convention (C, Frame_Info_Object);
+
+ -- Object for the generated code.
+ This_Object : Frame_Info_Object;
+
+ procedure Register_Unwind
+ is
+ use Binary_File.Memory;
+ use System;
+
+ -- From GCC unwind-dw2-fde.h
+ procedure Register_Frame_Info_Bases
+ (Eh_Frame : Address;
+ Object : Address;
+ Tbase : Address;
+ Dbase : Address);
+ pragma Import (C, Register_Frame_Info_Bases,
+ "__register_frame_info_bases");
+ begin
+ if X86.Flags.Eh_Frame then
+ Register_Frame_Info_Bases
+ (Get_Section_Addr (X86.Emits.Sect_Eh_Frame),
+ This_Object'Address,
+ Get_Section_Addr (X86.Emits.Sect_Text),
+ Get_Section_Addr (X86.Emits.Sect_Bss));
+ end if;
+ end Register_Unwind;
+
+ procedure Unregister_Unwind
+ is
+ use Binary_File.Memory;
+ use System;
+
+ -- From GCC unwind-dw2-fde.h
+ procedure Deregister_Frame_Info_Bases (Eh_Frame : Address);
+ pragma Import (C, Deregister_Frame_Info_Bases,
+ "__deregister_frame_info_bases");
+ begin
+ if X86.Flags.Eh_Frame then
+ Deregister_Frame_Info_Bases
+ (Get_Section_Addr (X86.Emits.Sect_Eh_Frame));
+ end if;
+ end Unregister_Unwind;
+
end Ortho_Code.X86.Abi;
diff --git a/src/ortho/mcode/ortho_code-x86-abi.ads b/src/ortho/mcode/ortho_code-x86-abi.ads
index cc6cf560b..6e720e1e1 100644
--- a/src/ortho/mcode/ortho_code-x86-abi.ads
+++ b/src/ortho/mcode/ortho_code-x86-abi.ads
@@ -79,6 +79,10 @@ package Ortho_Code.X86.Abi is
-- Link in memory intrinsics symbols.
procedure Link_Intrinsics;
+ -- Register unwinding info for JIT.
+ procedure Register_Unwind;
+ procedure Unregister_Unwind;
+
-- Target specific data for subprograms.
type Target_Subprg is record
Fp_Slot : Uns32 := 0;
diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb
index 132f7287b..84336818c 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.adb
+++ b/src/ortho/mcode/ortho_code-x86-emits.adb
@@ -46,11 +46,6 @@ package body Ortho_Code.X86.Emits is
Mode_U32 | Mode_I32 => Sz_32,
Mode_U64 | Mode_I64 => Sz_64);
- -- Well known sections.
- Sect_Text : Binary_File.Section_Acc;
- Sect_Rodata : Binary_File.Section_Acc;
- Sect_Bss : Binary_File.Section_Acc;
-
-- For 64 bit to 32 bit conversion, we need an extra register. Just before
-- the conversion, there is an OE_Reg instruction containing the extra
-- register. Its value is saved here.
@@ -2936,7 +2931,7 @@ package body Ortho_Code.X86.Emits is
-- Emit prolog.
-- push %ebp / push %rbp
Push_Reg (R_Bp);
- -- movl %esp, %ebp / movl %rsp, %rbp
+ -- movl %esp, %ebp / movq %rsp, %rbp
Start_Insn;
Gen_Rex (16#48#);
Gen_8 (Opc_Mov_Rm_Reg + 1);
@@ -2971,7 +2966,7 @@ package body Ortho_Code.X86.Emits is
end;
end if;
- -- subl XXX, %esp / subl XXX, %rsp
+ -- subl XXX, %esp / subq XXX, %rsp
if Frame_Size /= 0 then
if not X86.Flags.Flag_Alloca_Call
or else Frame_Size <= 4096
@@ -3090,6 +3085,24 @@ package body Ortho_Code.X86.Emits is
end if;
end Emit_Epilogue;
+ procedure Gen_FDE
+ is
+ Subprg_Size : Unsigned_32;
+ begin
+ Subprg_Size := Unsigned_32 (Get_Current_Pc - Subprg_Pc);
+
+ Set_Current_Section (Sect_Eh_Frame);
+ Prealloc (20);
+ Gen_32 (16); -- Length
+ Gen_32 (Unsigned_32 (Get_Current_Pc)); -- CIE pointer
+ Gen_32 (Unsigned_32 (Subprg_Pc)); -- Initial location (.text rel)
+ Gen_32 (Subprg_Size); -- Function size
+ Gen_8 (0); -- Length
+ Gen_8 (0);
+ Gen_8 (0);
+ Gen_8 (0);
+ end Gen_FDE;
+
procedure Emit_Subprg (Subprg : Subprogram_Data_Acc)
is
pragma Assert (Subprg = Cur_Subprg);
@@ -3114,6 +3127,10 @@ package body Ortho_Code.X86.Emits is
end loop;
Emit_Epilogue (Subprg);
+
+ if Flags.Eh_Frame then
+ Gen_FDE;
+ end if;
end Emit_Subprg;
procedure Emit_Var_Decl (Decl : O_Dnode)
@@ -3295,6 +3312,51 @@ package body Ortho_Code.X86.Emits is
Debug_Hex := True;
end if;
+ if Flags.Eh_Frame then
+ Create_Section (Sect_Eh_Frame, ".eh_frame", 0);
+ Set_Current_Section (Sect_Eh_Frame);
+ Prealloc (32);
+
+ -- Generate CIE
+ Gen_32 (28); -- Length
+ Gen_32 (0); -- CIE id = 0
+ Gen_8 (1); -- Version = 1
+ Gen_8 (Character'Pos ('z')); -- Augmentation
+ Gen_8 (Character'Pos ('R')); -- Augmentation
+ Gen_8 (0); -- End of Augmentation
+ Gen_8 (1); -- Code align factor
+ if Flags.M64 then
+ Dwarf.Gen_Sleb128 (-8); -- Data align factor
+ Dwarf.Gen_Uleb128 (16); -- Return address (16 = rip)
+ else
+ Dwarf.Gen_Sleb128 (-4);
+ Dwarf.Gen_Uleb128 (0); -- TODO
+ end if;
+ Dwarf.Gen_Uleb128 (1); -- z: length of the remainder of augmentation
+ Gen_8 (16#23#); -- R: pointer encoding: .text relative, udata4
+
+ -- CFIs (call frame instructions)
+ -- Initial state: cfa = rsp + 8, rip = -8@cfa
+ Gen_8 (16#0c#); -- DW_CFA_def_cfa
+ Gen_8 (16#07#); -- reg 7 (rsp)
+ Gen_8 (16#08#); -- offset 8
+ Gen_8 (16#80# or 16#10#); -- DW_CFA_def_offset reg 16 (rip)
+ Gen_8 (16#01#); -- offset 1 * (-8) = -8
+ -- push %rbp, cfa = rsp + 16
+ Gen_8 (16#40# or 16#01#); -- DW_CFA_advance_loc +1
+ Gen_8 (16#0e#); -- DW_CFA_def_cfa_offset
+ Gen_8 (16#10#); -- offset 16
+ Gen_8 (16#80# or 16#06#); -- DW_CFA_def_offset reg 6 (rbp)
+ Gen_8 (16#02#); -- offset 2 * (-8) = -16
+ -- movq %rsp, %rbp, cfa = rbp + 16
+ Gen_8 (16#40# or 16#03#); -- DW_CFA_advance_loc +3
+ Gen_8 (16#0d#); -- DW_CFA_def_cfa_register
+ Gen_8 (16#06#); -- reg 6 (rbp)
+ Gen_8 (0); -- nop
+ Gen_8 (0); -- nop
+ Set_Current_Section (Sect_Text);
+ end if;
+
if Flag_Debug /= Debug_None then
Dwarf.Init;
Set_Current_Section (Sect_Text);
@@ -3309,6 +3371,12 @@ package body Ortho_Code.X86.Emits is
Set_Current_Section (Sect_Text);
Dwarf.Finish;
end if;
+
+ if Flags.Eh_Frame then
+ Set_Current_Section (Sect_Eh_Frame);
+ Prealloc (4);
+ Gen_32 (0); -- Size = 0 -> end.
+ end if;
end Finish;
end Ortho_Code.X86.Emits;
diff --git a/src/ortho/mcode/ortho_code-x86-emits.ads b/src/ortho/mcode/ortho_code-x86-emits.ads
index 97802cd19..edd327884 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.ads
+++ b/src/ortho/mcode/ortho_code-x86-emits.ads
@@ -31,6 +31,12 @@ package Ortho_Code.X86.Emits is
type Intrinsic_Symbols_Map is array (Intrinsics_X86) of Symbol;
Intrinsics_Symbol : Intrinsic_Symbols_Map;
+ -- Well known sections.
+ Sect_Text : Section_Acc;
+ Sect_Rodata : Section_Acc;
+ Sect_Bss : Section_Acc;
+ Sect_Eh_Frame : Section_Acc;
+
Mcount_Symbol : Symbol;
Chkstk_Symbol : Symbol;
end Ortho_Code.X86.Emits;
diff --git a/src/ortho/mcode/ortho_code-x86-flags_linux.ads b/src/ortho/mcode/ortho_code-x86-flags_linux.ads
index a6ef992b8..119158ee8 100644
--- a/src/ortho/mcode/ortho_code-x86-flags_linux.ads
+++ b/src/ortho/mcode/ortho_code-x86-flags_linux.ads
@@ -30,6 +30,9 @@ package Ortho_Code.X86.Flags_Linux is
-- 32 bits.
M64 : constant Boolean := False;
+ -- Generate eh_frame for unwinding.
+ Eh_Frame : constant Boolean := False;
+
-- Not Windows x64 calling convention.
Win64 : constant Boolean := False;
end Ortho_Code.X86.Flags_Linux;
diff --git a/src/ortho/mcode/ortho_code-x86-flags_linux64.ads b/src/ortho/mcode/ortho_code-x86-flags_linux64.ads
index 6a34106fc..bb46a732d 100644
--- a/src/ortho/mcode/ortho_code-x86-flags_linux64.ads
+++ b/src/ortho/mcode/ortho_code-x86-flags_linux64.ads
@@ -27,9 +27,12 @@ package Ortho_Code.X86.Flags_Linux64 is
-- Alignment for double (64 bit float).
Mode_F64_Align : constant Natural := 3;
- -- 32 bits.
+ -- 64 bits.
M64 : constant Boolean := True;
+ -- Generate eh_frame for unwinding.
+ Eh_Frame : constant Boolean := True;
+
-- Not Windows x64 calling convention.
Win64 : constant Boolean := False;
end Ortho_Code.X86.Flags_Linux64;
diff --git a/src/ortho/mcode/ortho_code-x86-flags_macosx.ads b/src/ortho/mcode/ortho_code-x86-flags_macosx.ads
index 552cf00a9..a14b310a6 100644
--- a/src/ortho/mcode/ortho_code-x86-flags_macosx.ads
+++ b/src/ortho/mcode/ortho_code-x86-flags_macosx.ads
@@ -30,6 +30,9 @@ package Ortho_Code.X86.Flags_Macosx is
-- 32 bits.
M64 : constant Boolean := False;
+ -- Generate eh_frame for unwinding.
+ Eh_Frame : constant Boolean := False;
+
-- Not Windows x64 calling convention.
Win64 : constant Boolean := False;
end Ortho_Code.X86.Flags_Macosx;
diff --git a/src/ortho/mcode/ortho_code-x86-flags_macosx64.ads b/src/ortho/mcode/ortho_code-x86-flags_macosx64.ads
index a32291766..6f133afa9 100644
--- a/src/ortho/mcode/ortho_code-x86-flags_macosx64.ads
+++ b/src/ortho/mcode/ortho_code-x86-flags_macosx64.ads
@@ -30,6 +30,9 @@ package Ortho_Code.X86.Flags_Macosx64 is
-- 64 bits.
M64 : constant Boolean := True;
+ -- Generate eh_frame for unwinding.
+ Eh_Frame : constant Boolean := False;
+
-- Not Windows x64 calling convention.
Win64 : constant Boolean := False;
end Ortho_Code.X86.Flags_Macosx64;
diff --git a/src/ortho/mcode/ortho_code-x86-flags_windows.ads b/src/ortho/mcode/ortho_code-x86-flags_windows.ads
index fa74bca58..921868410 100644
--- a/src/ortho/mcode/ortho_code-x86-flags_windows.ads
+++ b/src/ortho/mcode/ortho_code-x86-flags_windows.ads
@@ -30,6 +30,9 @@ package Ortho_Code.X86.Flags_Windows is
-- 32 bits.
M64 : constant Boolean := False;
+ -- Generate eh_frame for unwinding.
+ Eh_Frame : constant Boolean := False;
+
-- Not Windows x64 calling convention.
Win64 : constant Boolean := False;
end Ortho_Code.X86.Flags_Windows;
diff --git a/src/ortho/mcode/ortho_code-x86-flags_windows64.ads b/src/ortho/mcode/ortho_code-x86-flags_windows64.ads
index 8fd76f2ae..cf7320188 100644
--- a/src/ortho/mcode/ortho_code-x86-flags_windows64.ads
+++ b/src/ortho/mcode/ortho_code-x86-flags_windows64.ads
@@ -30,6 +30,9 @@ package Ortho_Code.X86.Flags_Windows64 is
-- 64 bits.
M64 : constant Boolean := True;
+ -- Generate eh_frame for unwinding.
+ Eh_Frame : constant Boolean := False;
+
-- Windows x64 calling convention.
Win64 : constant Boolean := True;
end Ortho_Code.X86.Flags_Windows64;
diff --git a/src/ortho/mcode/ortho_jit.adb b/src/ortho/mcode/ortho_jit.adb
index 9be0f054a..84145f747 100644
--- a/src/ortho/mcode/ortho_jit.adb
+++ b/src/ortho/mcode/ortho_jit.adb
@@ -66,6 +66,8 @@ package body Ortho_Jit is
return;
end if;
+ Ortho_Code.Abi.Register_Unwind;
+
if Snap_Filename /= null then
declare
use Ada.Text_IO;
diff --git a/src/synth/elab-vhdl_insts.adb b/src/synth/elab-vhdl_insts.adb
index 71adc953d..b8b53517d 100644
--- a/src/synth/elab-vhdl_insts.adb
+++ b/src/synth/elab-vhdl_insts.adb
@@ -106,6 +106,15 @@ package body Elab.Vhdl_Insts is
Create_Package_Interface (Sub_Inst, Inter, Pkg_Inst);
end;
+ when Iir_Kind_Interface_Type_Declaration =>
+ declare
+ Act_Typ : Type_Acc;
+ begin
+ Act_Typ := Synth_Subtype_Indication
+ (Syn_Inst, Get_Actual (Assoc));
+ Create_Subtype_Object (Sub_Inst, Get_Type (Inter), Act_Typ);
+ end;
+
when Iir_Kind_Interface_Variable_Declaration
| Iir_Kind_Interface_File_Declaration
| Iir_Kind_Interface_Signal_Declaration
@@ -113,8 +122,7 @@ package body Elab.Vhdl_Insts is
| Iir_Kind_Interface_Terminal_Declaration =>
raise Internal_Error;
- when Iir_Kinds_Interface_Subprogram_Declaration
- | Iir_Kind_Interface_Type_Declaration =>
+ when Iir_Kinds_Interface_Subprogram_Declaration =>
raise Internal_Error;
end case;
diff --git a/src/synth/elab-vhdl_types.adb b/src/synth/elab-vhdl_types.adb
index 300f57427..7d726d154 100644
--- a/src/synth/elab-vhdl_types.adb
+++ b/src/synth/elab-vhdl_types.adb
@@ -530,7 +530,9 @@ package body Elab.Vhdl_Types is
when Iir_Kinds_Denoting_Name =>
Atype := Get_Named_Entity (Atype);
when Iir_Kind_Subtype_Declaration
- | Iir_Kind_Type_Declaration =>
+ | Iir_Kind_Type_Declaration
+ | Iir_Kind_Subtype_Attribute
+ | Iir_Kind_Interface_Type_Declaration =>
-- Type already declared, so already handled.
return Null_Node;
when Iir_Kind_Array_Subtype_Definition
diff --git a/src/synth/synth-vhdl_insts.adb b/src/synth/synth-vhdl_insts.adb
index dfb42b532..235d9ed8e 100644
--- a/src/synth/synth-vhdl_insts.adb
+++ b/src/synth/synth-vhdl_insts.adb
@@ -254,28 +254,34 @@ package body Synth.Vhdl_Insts is
Gen_Decl := Generics;
while Gen_Decl /= Null_Node loop
- Gen := Get_Value (Params.Syn_Inst, Gen_Decl);
- Strip_Const (Gen);
- case Gen.Typ.Kind is
- when Type_Discrete =>
- declare
- S : constant String :=
- Uns64'Image (To_Uns64 (Read_Discrete (Gen)));
- begin
- if Len + S'Length > Str_Len then
- Has_Hash := True;
- Hash_Const (Ctxt, Gen.Val, Gen.Typ);
- else
- Str (Len + 1 .. Len + S'Length) := S;
- pragma Assert (Str (Len + 1) = ' ');
- Str (Len + 1) := '_'; -- Overwrite the space.
- Len := Len + S'Length;
- end if;
- end;
- when others =>
- Has_Hash := True;
- Hash_Const (Ctxt, Gen.Val, Gen.Typ);
- end case;
+ if Get_Kind (Gen_Decl) = Iir_Kind_Interface_Constant_Declaration
+ then
+ Gen := Get_Value (Params.Syn_Inst, Gen_Decl);
+ Strip_Const (Gen);
+ case Gen.Typ.Kind is
+ when Type_Discrete =>
+ declare
+ S : constant String :=
+ Uns64'Image (To_Uns64 (Read_Discrete (Gen)));
+ begin
+ if Len + S'Length > Str_Len then
+ Has_Hash := True;
+ Hash_Const (Ctxt, Gen.Val, Gen.Typ);
+ else
+ Str (Len + 1 .. Len + S'Length) := S;
+ pragma Assert (Str (Len + 1) = ' ');
+ Str (Len + 1) := '_'; -- Overwrite the space.
+ Len := Len + S'Length;
+ end if;
+ end;
+ when others =>
+ Has_Hash := True;
+ Hash_Const (Ctxt, Gen.Val, Gen.Typ);
+ end case;
+ else
+ -- TODO: add a unique number (index)
+ null;
+ end if;
Gen_Decl := Get_Chain (Gen_Decl);
end loop;
diff --git a/src/vhdl/vhdl-annotations.adb b/src/vhdl/vhdl-annotations.adb
index b1a36646e..13aa8bf3b 100644
--- a/src/vhdl/vhdl-annotations.adb
+++ b/src/vhdl/vhdl-annotations.adb
@@ -431,7 +431,8 @@ package body Vhdl.Annotations is
when Iir_Kind_Protected_Type_Declaration =>
Annotate_Protected_Type_Declaration (Block_Info, Def);
- when Iir_Kind_Incomplete_Type_Definition =>
+ when Iir_Kind_Incomplete_Type_Definition
+ | Iir_Kind_Subtype_Attribute =>
null;
when Iir_Kind_Foreign_Vector_Type_Definition =>
@@ -509,8 +510,12 @@ package body Vhdl.Annotations is
Create_Object_Info (Block_Info, Decl);
when Iir_Kind_Interface_Package_Declaration =>
Annotate_Interface_Package_Declaration (Block_Info, Decl);
- when Iir_Kinds_Interface_Subprogram_Declaration
- | Iir_Kind_Interface_Type_Declaration =>
+ when Iir_Kind_Interface_Type_Declaration =>
+ if Flag_Synthesis then
+ -- Create an info on the interface_type_definition
+ Create_Object_Info (Block_Info, Get_Type (Decl));
+ end if;
+ when Iir_Kinds_Interface_Subprogram_Declaration =>
-- Macro-expanded
null;
when others =>
diff --git a/src/vhdl/vhdl-configuration.adb b/src/vhdl/vhdl-configuration.adb
index aeb737028..64a615bfb 100644
--- a/src/vhdl/vhdl-configuration.adb
+++ b/src/vhdl/vhdl-configuration.adb
@@ -27,6 +27,7 @@ with Vhdl.Sem_Scopes;
with Vhdl.Sem_Lib; use Vhdl.Sem_Lib;
with Vhdl.Canon;
with Vhdl.Evaluation;
+with Vhdl.Scanner;
package body Vhdl.Configuration is
procedure Add_Design_Concurrent_Stmts (Parent : Iir);
@@ -1167,7 +1168,7 @@ package body Vhdl.Configuration is
end Find_Top_Entity;
type Override_Entry is record
- Gen : Name_Id;
+ Gen : String_Acc;
Value : String_Acc;
end record;
@@ -1177,9 +1178,9 @@ package body Vhdl.Configuration is
Table_Low_Bound => 1,
Table_Initial => 16);
- procedure Add_Generic_Override (Id : Name_Id; Value : String) is
+ procedure Add_Generic_Override (Name : String; Value : String) is
begin
- Override_Table.Append (Override_Entry'(Gen => Id,
+ Override_Table.Append (Override_Entry'(Gen => new String'(Name),
Value => new String'(Value)));
end Add_Generic_Override;
@@ -1325,29 +1326,57 @@ package body Vhdl.Configuration is
procedure Apply_Generic_Override (Ent : Iir)
is
- Inter_Chain : constant Iir := Get_Generic_Chain (Ent);
- Inter : Iir;
begin
for I in Override_Table.First .. Override_Table.Last loop
declare
Over : constant Override_Entry := Override_Table.Table (I);
begin
- Inter := Inter_Chain;
- while Inter /= Null_Iir loop
- exit when Get_Identifier (Inter) = Over.Gen;
- Inter := Get_Chain (Inter);
- end loop;
+ case Get_Kind (Ent) is
+ when Iir_Kind_Entity_Declaration =>
+ declare
+ Inter_Chain : constant Iir := Get_Generic_Chain (Ent);
+ Gen_Name : String := Over.Gen.all;
+ Gen_Id : Name_Id;
+ Inter : Iir;
+ Err : Boolean;
+ begin
+ Vhdl.Scanner.Convert_Identifier (Gen_Name, Err);
+ if Err then
+ Error_Msg_Option
+ ("incorrect name in generic override option");
+ Gen_Id := Null_Identifier;
+ else
+ Gen_Id := Name_Table.Get_Identifier (Gen_Name);
- if Inter = Null_Iir then
- Error_Msg_Elab ("no generic %i for -g", +Over.Gen);
- elsif Get_Kind (Inter) /= Iir_Kind_Interface_Constant_Declaration
- then
- Error_Msg_Elab
- ("generic %n cannot be overriden (not a constant)",
- +Over.Gen);
- else
- Override_Generic (Inter, Over.Value);
- end if;
+ Inter := Inter_Chain;
+ while Inter /= Null_Iir loop
+ exit when Get_Identifier (Inter) = Gen_Id;
+ Inter := Get_Chain (Inter);
+ end loop;
+ end if;
+
+ if Gen_Id = Null_Identifier then
+ -- Skip it
+ null;
+ elsif Inter = Null_Iir then
+ Error_Msg_Elab ("no generic %i for -g", +Gen_Id);
+ elsif (Get_Kind (Inter)
+ /= Iir_Kind_Interface_Constant_Declaration)
+ then
+ -- Could be a generic package, a generic type...
+ Error_Msg_Elab
+ ("generic %n cannot be overriden (not a constant)",
+ +Gen_Id);
+ else
+ Override_Generic (Inter, Over.Value);
+ end if;
+ end;
+ when Iir_Kind_Foreign_Module =>
+ Apply_Foreign_Override
+ (Get_Foreign_Node (Ent), Over.Gen.all, Over.Value.all);
+ when others =>
+ raise Internal_Error;
+ end case;
end;
end loop;
end Apply_Generic_Override;
diff --git a/src/vhdl/vhdl-configuration.ads b/src/vhdl/vhdl-configuration.ads
index d272d23e9..dfd59c516 100644
--- a/src/vhdl/vhdl-configuration.ads
+++ b/src/vhdl/vhdl-configuration.ads
@@ -69,8 +69,12 @@ package Vhdl.Configuration is
type Mark_Instantiated_Units_Access is access procedure (N : Int32);
Mark_Foreign_Module : Mark_Instantiated_Units_Access;
+ type Apply_Foreign_Override_Access is access procedure
+ (Top : Int32; Gen : String; Value : String);
+ Apply_Foreign_Override : Apply_Foreign_Override_Access;
+
-- Add an override for generic ID.
- procedure Add_Generic_Override (Id : Name_Id; Value : String);
+ procedure Add_Generic_Override (Name : String; Value : String);
-- Apply generic overrides to entity ENT.
procedure Apply_Generic_Override (Ent : Iir);
diff --git a/src/vhdl/vhdl-sem_expr.adb b/src/vhdl/vhdl-sem_expr.adb
index 21e7b2237..04a73071c 100644
--- a/src/vhdl/vhdl-sem_expr.adb
+++ b/src/vhdl/vhdl-sem_expr.adb
@@ -4767,7 +4767,8 @@ package body Vhdl.Sem_Expr is
Obj := Get_Named_Entity (Obj);
when Iir_Kinds_Psl_Builtin =>
return;
- when Iir_Kind_Error =>
+ when Iir_Kind_Parenthesis_Name
+ | Iir_Kind_Error =>
return;
when others =>
Error_Kind ("check_read", Obj);
diff --git a/testsuite/gna/bug0100/name4.vhdl b/testsuite/gna/bug0100/name4.vhdl
new file mode 100644
index 000000000..5c88203ad
--- /dev/null
+++ b/testsuite/gna/bug0100/name4.vhdl
@@ -0,0 +1,14 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity name4 is
+ port (leds_o : std_logic_vector(3 downto 0);
+ leds_init : std_logic_vector(3 downto 0);
+ led_init_en : std_logic);
+end;
+
+architecture behav of name4 is
+begin
+ leds_o <= (led_init());
+end behav;
+
diff --git a/testsuite/gna/bug0100/testsuite.sh b/testsuite/gna/bug0100/testsuite.sh
index 2e9d2203e..3733548f3 100755
--- a/testsuite/gna/bug0100/testsuite.sh
+++ b/testsuite/gna/bug0100/testsuite.sh
@@ -29,6 +29,7 @@ analyze_failure compon.vhdl
analyze_failure --force-analysis varcomp.vhdl
#analyze_failure --force-analysis name1.vhdl
#analyze_failure --force-analysis name2.vhdl
+analyze_failure --force-analysis name4.vhdl
analyze_failure --force-analysis inst2.vhdl
if analyze_failure --force-analysis notype1.vhdl 2>&1 | grep -q "indexed name"; then
diff --git a/testsuite/synth/issue412/generic_pkg.vhdl b/testsuite/synth/issue412/generic_pkg.vhdl
new file mode 100644
index 000000000..3a97c2961
--- /dev/null
+++ b/testsuite/synth/issue412/generic_pkg.vhdl
@@ -0,0 +1,42 @@
+-- package containing a type-generic D Flip Flop
+-- may not be 100% valid VHDL code, contact ktbarrett on gitter
+-- non-generic version does synthesize correctly
+package generic_pkg is
+
+ procedure generic_FF
+ generic (
+ constant T: type)
+ paramater (
+ signal q : out T;
+ signal d : in T;
+ signal clk : in std_logic;
+ signal rst : in std_logic;
+ constant INIT : in T;
+ signal en : in std_logic := '1');
+
+end package generic_pkg;
+
+package body generic_pkg is
+
+ procedure generic_FF
+ generic (
+ constant T: type)
+ paramater (
+ signal q : out T;
+ signal d : in T;
+ signal clk : in std_logic;
+ signal rst : in std_logic;
+ constant INIT : in T;
+ signal en : in std_logic := '1')
+ is
+ begin
+ if (rising_edge(clk)) then
+ if (rst /= '0') then
+ q <= INIT;
+ elsif (en = '1') then
+ q <= d;
+ end if;
+ end if;
+ end procedure generic_FF;
+
+end package body generic_pkg;
diff --git a/testsuite/synth/issue412/generic_sfifo-orig.vhdl b/testsuite/synth/issue412/generic_sfifo-orig.vhdl
new file mode 100644
index 000000000..d1ea90685
--- /dev/null
+++ b/testsuite/synth/issue412/generic_sfifo-orig.vhdl
@@ -0,0 +1,88 @@
+-- A simple type-generic stream-style synchronous FIFO
+-- may not be 100% valid VHDL code, contact ktbarrett on gitter
+-- non-generic version does synthesize correctly
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+
+entity generic_SFIFO is
+ generic (
+ T : type;
+ MIN_DEPTH : natural);
+ port (
+ clk : in std_ulogic;
+ rst : in std_ulogic;
+ data_in : in T;
+ valid_in : in std_ulogic;
+ ready_out : out std_ulogic;
+ data_out : out T;
+ valid_out : out std_ulogic;
+ ready_in : in std_ulogic);
+end entity generic_SFIFO;
+
+architecture rtl of generic_SFIFO is
+
+ function clog2 (n: natural) return natural is
+ variable i : natural;
+ variable test : natural;
+ begin
+ test := 1;
+ i := 0;
+ while (test < n) loop
+ i := i + 1;
+ test := test * 2;
+ end loop;
+ return i;
+ end function clog2;
+
+ constant ptr_size : natural := clog2(MIN_DEPTH);
+ constant depth : natural := 2 ** ptr_size;
+ signal rd_ptr : unsigned(ptr_size downto 0);
+ signal wr_ptr : unsigned(ptr_size downto 0);
+
+ type ram_type is array(0 to depth - 1) of T;
+
+ signal ram : ram_type;
+
+begin
+
+ fifo_proc : process (clk) is
+
+ variable next_wr_ptr : wr_ptr'subtype;
+ variable next_rd_ptr : rd_ptr'subtype;
+
+ begin
+
+ if (rising_edge(clk)) then
+ if (rst /= '0') then
+ rd_ptr <= (others => '0');
+ wr_ptr <= (others => '0');
+ ready_out <= '0';
+ valid_out <= '0';
+ else
+ next_wr_ptr := wr_ptr;
+ next_rd_ptr := rd_ptr;
+ if ((valid_in='1') and (ready_out='1')) then
+ ram(to_integer(wr_ptr(wr_ptr'left - 1 downto 0))) <= data_in;
+ next_wr_ptr := wr_ptr + 1;
+ end if;
+ if ((valid_out='1') and (ready_in='1')) then
+ next_rd_ptr := rd_ptr + 1;
+ end if;
+ ready_out <= '0' when
+ (next_wr_ptr(next_wr_ptr'left) /= next_rd_ptr(next_rd_ptr'left)) and
+ (next_wr_ptr(next_wr_ptr'left - 1 downto 0) = next_rd_ptr(next_rd_ptr'left - 1 downto 0)) else
+ '1';
+ valid_out <= '0' when
+ (wr_ptr(wr_ptr'left) = next_rd_ptr(next_rd_ptr'left)) and
+ (wr_ptr(wr_ptr'left - 1 downto 0) = next_rd_ptr(next_rd_ptr'left - 1 downto 0)) else
+ '1';
+ wr_ptr <= next_wr_ptr;
+ rd_ptr <= next_rd_ptr;
+ data_out <= ram(to_integer(next_rd_ptr(next_rd_ptr'left - 1 downto 0)));
+ end if;
+ end if;
+
+ end process fifo_proc;
+
+end architecture rtl;
diff --git a/testsuite/synth/issue412/generic_sfifo.vhdl b/testsuite/synth/issue412/generic_sfifo.vhdl
new file mode 100644
index 000000000..92e72a970
--- /dev/null
+++ b/testsuite/synth/issue412/generic_sfifo.vhdl
@@ -0,0 +1,88 @@
+-- A simple type-generic stream-style synchronous FIFO
+-- may not be 100% valid VHDL code, contact ktbarrett on gitter
+-- non-generic version does synthesize correctly
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+
+entity generic_SFIFO is
+ generic (
+ type T;
+ MIN_DEPTH : natural);
+ port (
+ clk : in std_ulogic;
+ rst : in std_ulogic;
+ data_in : in T;
+ valid_in : in std_ulogic;
+ ready_out : out std_ulogic; -- If true, can accept data
+ data_out : out T;
+ valid_out : out std_ulogic;
+ ready_in : in std_ulogic); -- To consume data
+end entity generic_SFIFO;
+
+architecture rtl of generic_SFIFO is
+
+ function clog2 (n: natural) return natural is
+ variable i : natural;
+ variable test : natural;
+ begin
+ test := 1;
+ i := 0;
+ while (test < n) loop
+ i := i + 1;
+ test := test * 2;
+ end loop;
+ return i;
+ end function clog2;
+
+ constant ptr_size : natural := clog2(MIN_DEPTH);
+ constant depth : natural := 2 ** ptr_size;
+ signal rd_ptr : unsigned(ptr_size downto 0);
+ signal wr_ptr : unsigned(ptr_size downto 0);
+
+ type ram_type is array(0 to depth - 1) of T;
+
+ signal ram : ram_type;
+
+begin
+
+ fifo_proc : process (clk) is
+
+ variable next_wr_ptr : wr_ptr'subtype;
+ variable next_rd_ptr : rd_ptr'subtype;
+
+ begin
+
+ if (rising_edge(clk)) then
+ if (rst /= '0') then
+ rd_ptr <= (others => '0');
+ wr_ptr <= (others => '0');
+ ready_out <= '0';
+ valid_out <= '0';
+ else
+ next_wr_ptr := wr_ptr;
+ next_rd_ptr := rd_ptr;
+ if ((valid_in='1') and (ready_out='1')) then
+ ram(to_integer(wr_ptr(wr_ptr'left - 1 downto 0))) <= data_in;
+ next_wr_ptr := wr_ptr + 1;
+ end if;
+ if ((valid_out='1') and (ready_in='1')) then
+ next_rd_ptr := rd_ptr + 1;
+ end if;
+ ready_out <= '0' when
+ (next_wr_ptr(next_wr_ptr'left) /= next_rd_ptr(next_rd_ptr'left)) and
+ (next_wr_ptr(next_wr_ptr'left - 1 downto 0) = next_rd_ptr(next_rd_ptr'left - 1 downto 0)) else
+ '1';
+ valid_out <= '0' when
+ (wr_ptr(wr_ptr'left) = next_rd_ptr(next_rd_ptr'left)) and
+ (wr_ptr(wr_ptr'left - 1 downto 0) = next_rd_ptr(next_rd_ptr'left - 1 downto 0)) else
+ '1';
+ wr_ptr <= next_wr_ptr;
+ rd_ptr <= next_rd_ptr;
+ data_out <= ram(to_integer(next_rd_ptr(next_rd_ptr'left - 1 downto 0)));
+ end if;
+ end if;
+
+ end process fifo_proc;
+
+end architecture rtl;
diff --git a/testsuite/synth/issue412/my_fifo.vhdl b/testsuite/synth/issue412/my_fifo.vhdl
new file mode 100644
index 000000000..c06f1a776
--- /dev/null
+++ b/testsuite/synth/issue412/my_fifo.vhdl
@@ -0,0 +1,31 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity my_FIFO is
+ port (
+ clk : in std_ulogic;
+ rst : in std_ulogic;
+ data_in : in std_logic_vector(7 downto 0);
+ valid_in : in std_ulogic;
+ ready_out : out std_ulogic;
+ data_out : out std_logic_vector(7 downto 0);
+ valid_out : out std_ulogic;
+ ready_in : in std_ulogic);
+end entity my_FIFO;
+
+architecture behav of my_fifo is
+begin
+ inst: entity work.generic_sfifo
+ generic map (
+ t => std_logic_vector (7 downto 0),
+ min_depth => 8)
+ port map (
+ clk => clk,
+ rst => rst,
+ data_in => data_in,
+ valid_in => valid_in,
+ ready_out => ready_out,
+ data_out => data_out,
+ valid_out => valid_out,
+ ready_in => ready_in);
+end behav;
diff --git a/testsuite/synth/issue412/tb_my_fifo.vhdl b/testsuite/synth/issue412/tb_my_fifo.vhdl
new file mode 100644
index 000000000..8f3def0de
--- /dev/null
+++ b/testsuite/synth/issue412/tb_my_fifo.vhdl
@@ -0,0 +1,66 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity tb_my_FIFO is
+end;
+
+architecture behav of tb_my_fifo is
+ signal clk : std_ulogic;
+ signal rst : std_ulogic;
+ signal data_in : std_logic_vector(7 downto 0);
+ signal valid_in : std_ulogic;
+ signal ready_out : std_ulogic;
+ signal data_out : std_logic_vector(7 downto 0);
+ signal valid_out : std_ulogic;
+ signal ready_in : std_ulogic;
+begin
+ inst_my_FIFO: entity work.my_FIFO
+ port map (
+ clk => clk,
+ rst => rst,
+ data_in => data_in,
+ valid_in => valid_in,
+ ready_out => ready_out,
+ data_out => data_out,
+ valid_out => valid_out,
+ ready_in => ready_in);
+
+ process
+ procedure pulse is
+ begin
+ clk <= '0';
+ wait for 5 ns;
+ clk <= '1';
+ wait for 5 ns;
+ end pulse;
+ begin
+ rst <= '1';
+ valid_in <= '0';
+ ready_in <= '0';
+ pulse;
+
+ rst <= '0';
+ pulse;
+
+ assert valid_out = '0' severity failure;
+ assert ready_out = '1' severity failure;
+
+ data_in <= x"d5";
+ valid_in <= '1';
+ pulse;
+
+ valid_in <= '0';
+
+ -- Need a second cycle to see the data on the outputs.
+ pulse;
+ assert valid_out = '1' severity failure;
+ assert data_out = x"d5" severity failure;
+
+ ready_in <= '1';
+ pulse;
+ assert valid_out = '0' severity failure;
+
+ ready_in <= '0';
+ wait;
+ end process;
+end behav;
diff --git a/testsuite/synth/issue412/testsuite.sh b/testsuite/synth/issue412/testsuite.sh
new file mode 100755
index 000000000..0fe7c9ba9
--- /dev/null
+++ b/testsuite/synth/issue412/testsuite.sh
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+. ../../testenv.sh
+
+GHDL_STD_FLAGS=--std=08
+
+synth generic_sfifo.vhdl my_fifo.vhdl -e > syn_my_fifo.vhdl
+
+analyze syn_my_fifo.vhdl tb_my_fifo.vhdl
+elab_simulate tb_my_fifo
+clean
+
+echo "Test successful"