diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-04-20 04:43:52 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-04-20 07:34:00 +0200 |
commit | 1c081e799d51ce644d33910ff801dc0479ab4a06 (patch) | |
tree | 4a1a6d9970e0ade12a345a6ac67129e0b4ee0ccb | |
parent | 70cf91a7ccc9e8cce2277897efa10d9c6f59f1f1 (diff) | |
download | ghdl-1c081e799d51ce644d33910ff801dc0479ab4a06.tar.gz ghdl-1c081e799d51ce644d33910ff801dc0479ab4a06.tar.bz2 ghdl-1c081e799d51ce644d33910ff801dc0479ab4a06.zip |
synth: improve handling of nested memories. Fix #1250
-rw-r--r-- | src/synth/netlists-disp_vhdl.adb | 6 | ||||
-rw-r--r-- | src/synth/synth-decls.adb | 7 | ||||
-rw-r--r-- | src/synth/synth-expr.adb | 10 | ||||
-rw-r--r-- | src/synth/synth-objtypes.ads | 2 | ||||
-rw-r--r-- | src/synth/synth-stmts.adb | 143 | ||||
-rw-r--r-- | src/synth/synth-stmts.ads | 27 |
6 files changed, 107 insertions, 88 deletions
diff --git a/src/synth/netlists-disp_vhdl.adb b/src/synth/netlists-disp_vhdl.adb index 8fdffbdc5..c772be71b 100644 --- a/src/synth/netlists-disp_vhdl.adb +++ b/src/synth/netlists-disp_vhdl.adb @@ -856,7 +856,11 @@ package body Netlists.Disp_Vhdl is when Id_Signal => Disp_Template (" \o0 <= \i0; -- (signal)" & NL, Inst); when Id_Isignal => - Disp_Template (" \o0 <= \i0; -- (isignal)" & NL, Inst); + if Get_Driver (Get_Input (Inst, 0)) /= No_Net then + -- It is possible (and meaningful) to have unassigned + -- isignal. + Disp_Template (" \o0 <= \i0; -- (isignal)" & NL, Inst); + end if; when Id_Port => Disp_Template (" \o0 <= \i0; -- (port)" & NL, Inst); when Id_Nop => diff --git a/src/synth/synth-decls.adb b/src/synth/synth-decls.adb index d615af910..003505bc6 100644 --- a/src/synth/synth-decls.adb +++ b/src/synth/synth-decls.adb @@ -776,8 +776,7 @@ package body Synth.Decls is is Atype : constant Node := Get_Declaration_Type (Decl); Off : Value_Offsets; - Voff : Net; - Rdwd : Width; + Dyn : Stmts.Dyn_Name; Res : Valtyp; Obj_Typ : Type_Acc; Base : Valtyp; @@ -792,8 +791,8 @@ package body Synth.Decls is end if; Stmts.Synth_Assignment_Prefix (Syn_Inst, Get_Name (Decl), - Base, Typ, Off, Voff, Rdwd); - pragma Assert (Voff = No_Net); + Base, Typ, Off, Dyn); + pragma Assert (Dyn.Voff = No_Net); if Base.Val.Kind = Value_Net then -- Object is a net if it is not writable. Extract the -- bits for the alias. diff --git a/src/synth/synth-expr.adb b/src/synth/synth-expr.adb index 963532044..54f8d9916 100644 --- a/src/synth/synth-expr.adb +++ b/src/synth/synth-expr.adb @@ -1858,19 +1858,17 @@ package body Synth.Expr is Off : Value_Offsets; Res : Valtyp; - Voff : Net; - Rdwd : Width; + Dyn : Dyn_Name; begin - Synth_Assignment_Prefix - (Syn_Inst, Expr, Base, Typ, Off, Voff, Rdwd); - if Voff = No_Net and then Is_Static (Base.Val) then + Synth_Assignment_Prefix (Syn_Inst, Expr, Base, Typ, Off, Dyn); + if Dyn.Voff = No_Net and then Is_Static (Base.Val) then Res := Create_Value_Memory (Typ); Copy_Memory (Res.Val.Mem, Base.Val.Mem + Off.Mem_Off, Typ.Sz); return Res; end if; return Synth_Read_Memory - (Syn_Inst, Base, Typ, Off.Net_Off, Voff, Expr); + (Syn_Inst, Base, Typ, Off.Net_Off, Dyn, Expr); end; when Iir_Kind_Selected_Element => declare diff --git a/src/synth/synth-objtypes.ads b/src/synth/synth-objtypes.ads index 41d23ba8a..a332536d1 100644 --- a/src/synth/synth-objtypes.ads +++ b/src/synth/synth-objtypes.ads @@ -175,6 +175,8 @@ package Synth.Objtypes is Mem_Off : Size_Type; end record; + No_Value_Offsets : constant Value_Offsets := (0, 0); + function "+" (L, R : Value_Offsets) return Value_Offsets; Global_Pool : aliased Areapool; diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb index 234dbf922..aaaa2ab25 100644 --- a/src/synth/synth-stmts.adb +++ b/src/synth/synth-stmts.adb @@ -94,14 +94,12 @@ package body Synth.Stmts is Dest_Base : out Valtyp; Dest_Typ : out Type_Acc; Dest_Off : out Value_Offsets; - Dest_Voff : out Net; - Dest_Rdwd : out Width) is + Dest_Dyn : out Dyn_Name) is begin case Get_Kind (Pfx) is when Iir_Kind_Simple_Name => Synth_Assignment_Prefix (Syn_Inst, Get_Named_Entity (Pfx), - Dest_Base, Dest_Typ, - Dest_Off, Dest_Voff, Dest_Rdwd); + Dest_Base, Dest_Typ, Dest_Off, Dest_Dyn); when Iir_Kind_Interface_Signal_Declaration | Iir_Kind_Variable_Declaration | Iir_Kind_Interface_Variable_Declaration @@ -115,8 +113,7 @@ package body Synth.Stmts is declare Targ : constant Valtyp := Get_Value (Syn_Inst, Pfx); begin - Dest_Voff := No_Net; - Dest_Rdwd := 0; + Dest_Dyn := No_Dyn_Name; Dest_Typ := Targ.Typ; if Targ.Val.Kind = Value_Alias then @@ -133,36 +130,44 @@ package body Synth.Stmts is Dest_Base := Synth_Expression (Syn_Inst, Pfx); Dest_Typ := Dest_Base.Typ; Dest_Off := (0, 0); - Dest_Voff := No_Net; - Dest_Rdwd := 0; + Dest_Dyn := No_Dyn_Name; when Iir_Kind_Indexed_Name => declare Voff : Net; Off : Value_Offsets; - Pfx_W : Width; begin Synth_Assignment_Prefix (Syn_Inst, Get_Prefix (Pfx), - Dest_Base, Dest_Typ, Dest_Off, Dest_Voff, Dest_Rdwd); + Dest_Base, Dest_Typ, Dest_Off, Dest_Dyn); Strip_Const (Dest_Base); - Pfx_W := Dest_Typ.W; Synth_Indexed_Name (Syn_Inst, Pfx, Dest_Typ, Voff, Off); - Dest_Typ := Get_Array_Element (Dest_Typ); - - Dest_Off.Net_Off := Dest_Off.Net_Off + Off.Net_Off; - Dest_Off.Mem_Off := Dest_Off.Mem_Off + Off.Mem_Off; - - if Voff /= No_Net then - if Dest_Voff = No_Net then - Dest_Voff := Voff; - Dest_Rdwd := Pfx_W; + if Voff = No_Net then + -- Static index. + Dest_Off := Dest_Off + Off; + else + -- Dynamic index. + if Dest_Dyn.Voff = No_Net then + -- The first one. + Dest_Dyn := (Pfx_Off => Dest_Off, + Pfx_Typ => Dest_Typ, + Voff => Voff); + Dest_Off := Off; else - Dest_Voff := Build_Addidx - (Get_Build (Syn_Inst), Dest_Voff, Voff); + -- Nested one. + -- FIXME + Dest_Off := Dest_Off + Off; + -- if Dest_Off /= (0, 0) then + -- Error_Msg_Synth (+Pfx, "nested memory not supported"); + -- end if; + + Dest_Dyn.Voff := Build_Addidx + (Get_Build (Syn_Inst), Dest_Dyn.Voff, Voff); end if; end if; + + Dest_Typ := Get_Array_Element (Dest_Typ); end; when Iir_Kind_Selected_Element => @@ -172,7 +177,7 @@ package body Synth.Stmts is begin Synth_Assignment_Prefix (Syn_Inst, Get_Prefix (Pfx), - Dest_Base, Dest_Typ, Dest_Off, Dest_Voff, Dest_Rdwd); + Dest_Base, Dest_Typ, Dest_Off, Dest_Dyn); Dest_Off.Net_Off := Dest_Off.Net_Off + Dest_Typ.Rec.E (Idx + 1).Boff; Dest_Off.Mem_Off := @@ -188,35 +193,41 @@ package body Synth.Stmts is Res_Bnd : Bound_Type; Sl_Voff : Net; Sl_Off : Value_Offsets; - Pfx_W : Width; begin Synth_Assignment_Prefix (Syn_Inst, Get_Prefix (Pfx), - Dest_Base, Dest_Typ, Dest_Off, Dest_Voff, Dest_Rdwd); + Dest_Base, Dest_Typ, Dest_Off, Dest_Dyn); Strip_Const (Dest_Base); - Pfx_W := Dest_Typ.W; Get_Onedimensional_Array_Bounds (Dest_Typ, Pfx_Bnd, El_Typ); Synth_Slice_Suffix (Syn_Inst, Pfx, Pfx_Bnd, El_Typ, Res_Bnd, Sl_Voff, Sl_Off); - Dest_Off.Net_Off := Dest_Off.Net_Off + Sl_Off.Net_Off; - Dest_Off.Mem_Off := Dest_Off.Mem_Off + Sl_Off.Mem_Off; - if Sl_Voff /= No_Net then + if Sl_Voff = No_Net then + -- Fixed slice. + Dest_Typ := Create_Onedimensional_Array_Subtype + (Dest_Typ, Res_Bnd); + Dest_Off.Net_Off := Dest_Off.Net_Off + Sl_Off.Net_Off; + Dest_Off.Mem_Off := Dest_Off.Mem_Off + Sl_Off.Mem_Off; + else -- Variable slice. - if Dest_Voff /= No_Net then - Dest_Voff := Build_Addidx - (Get_Build (Syn_Inst), Dest_Voff, Sl_Voff); + if Dest_Dyn.Voff = No_Net then + -- First one. + Dest_Dyn := (Pfx_Off => Dest_Off, + Pfx_Typ => Dest_Typ, + Voff => Sl_Voff); + Dest_Off := Sl_Off; else - Dest_Rdwd := Pfx_W; - Dest_Voff := Sl_Voff; + -- Nested. + if Dest_Off /= (0, 0) then + Error_Msg_Synth (+Pfx, "nested memory not supported"); + end if; + + Dest_Dyn.Voff := Build_Addidx + (Get_Build (Syn_Inst), Dest_Dyn.Voff, Sl_Voff); end if; Dest_Typ := Create_Slice_Type (Res_Bnd.Len, El_Typ); - else - -- Fixed slice. - Dest_Typ := Create_Onedimensional_Array_Subtype - (Dest_Typ, Res_Bnd); end if; end; @@ -224,8 +235,8 @@ package body Synth.Stmts is | Iir_Kind_Dereference => Synth_Assignment_Prefix (Syn_Inst, Get_Prefix (Pfx), - Dest_Base, Dest_Typ, Dest_Off, Dest_Voff, Dest_Rdwd); - if Dest_Off /= (0, 0) and then Dest_Voff /= No_Net then + Dest_Base, Dest_Typ, Dest_Off, Dest_Dyn); + if Dest_Off /= (0, 0) and then Dest_Dyn.Voff /= No_Net then raise Internal_Error; end if; Dest_Base := Heap.Synth_Dereference (Read_Access (Dest_Base)); @@ -265,11 +276,7 @@ package body Synth.Stmts is -- For a memory: the destination is known. Mem_Obj : Valtyp; -- The dynamic offset. - Mem_Voff : Net; - -- Offset of the memory in the wire (usually 0). - Mem_Moff : Uns32; - -- Width of the whole memory - Mem_Mwidth : Width; + Mem_Dyn : Dyn_Name; -- Offset of the data to be accessed from the memory. Mem_Doff : Uns32; end case; @@ -314,12 +321,10 @@ package body Synth.Stmts is Typ : Type_Acc; Off : Value_Offsets; - Voff : Net; - Rdwd : Width; + Dyn : Dyn_Name; begin - Synth_Assignment_Prefix - (Syn_Inst, Target, Base, Typ, Off, Voff, Rdwd); - if Voff = No_Net then + Synth_Assignment_Prefix (Syn_Inst, Target, Base, Typ, Off, Dyn); + if Dyn.Voff = No_Net then -- FIXME: check index. return Target_Info'(Kind => Target_Simple, Targ_Type => Typ, @@ -329,9 +334,7 @@ package body Synth.Stmts is return Target_Info'(Kind => Target_Memory, Targ_Type => Typ, Mem_Obj => Base, - Mem_Mwidth => Rdwd, - Mem_Moff => 0, -- Uns32 (Off.Mem_Off), - Mem_Voff => Voff, + Mem_Dyn => Dyn, Mem_Doff => Off.Net_Off); end if; end; @@ -464,16 +467,17 @@ package body Synth.Stmts is end if; when Target_Memory => declare + Ctxt : constant Context_Acc := Get_Build (Syn_Inst); N : Net; begin N := Get_Current_Assign_Value - (Get_Build (Syn_Inst), Target.Mem_Obj.Val.W, - Target.Mem_Moff, Target.Mem_Mwidth); - N := Build_Dyn_Insert (Get_Build (Syn_Inst), N, Get_Net (V), - Target.Mem_Voff, Target.Mem_Doff); + (Ctxt, Target.Mem_Obj.Val.W, + Target.Mem_Dyn.Pfx_Off.Net_Off, Target.Mem_Dyn.Pfx_Typ.W); + N := Build_Dyn_Insert + (Ctxt, N, Get_Net (V), Target.Mem_Dyn.Voff, Target.Mem_Doff); Set_Location (N, Loc); - Phi_Assign_Net (Get_Build (Syn_Inst), Target.Mem_Obj.Val.W, - N, Target.Mem_Moff); + Phi_Assign_Net (Ctxt, Target.Mem_Obj.Val.W, N, + Target.Mem_Dyn.Pfx_Off.Net_Off); end; end case; end Synth_Assignment; @@ -493,20 +497,20 @@ package body Synth.Stmts is Obj : Valtyp; Res_Typ : Type_Acc; Off : Uns32; - Voff : Net; + Dyn : Dyn_Name; Loc : Node) return Valtyp is N : Net; begin N := Get_Net (Obj); - if Voff /= No_Net then + if Dyn.Voff /= No_Net then Synth.Source.Set_Location_Maybe (N, Loc); - N := Build_Dyn_Extract - (Get_Build (Syn_Inst), N, Voff, Off, Res_Typ.W); + pragma Assert (Off = 0 or Dyn.Pfx_Off.Net_Off = 0); + N := Build_Dyn_Extract (Get_Build (Syn_Inst), N, Dyn.Voff, + Dyn.Pfx_Off.Net_Off + Off, Res_Typ.W); else pragma Assert (not Is_Static (Obj.Val)); - N := Build2_Extract - (Get_Build (Syn_Inst), N, Off, Res_Typ.W); + N := Build2_Extract (Get_Build (Syn_Inst), N, Off, Res_Typ.W); end if; Set_Location (N, Loc); return Create_Value_Net (N, Res_Typ); @@ -527,7 +531,7 @@ package body Synth.Stmts is raise Internal_Error; when Target_Memory => return Synth_Read_Memory (Syn_Inst, Targ.Mem_Obj, Targ.Targ_Type, - Targ.Mem_Moff, Targ.Mem_Voff, Loc); + 0, Targ.Mem_Dyn, Loc); end case; end Synth_Read; @@ -3334,15 +3338,14 @@ package body Synth.Stmts is declare Off : Value_Offsets; - Voff : Net; - Wd : Width; + Dyn : Dyn_Name; N : Net; Base : Valtyp; Typ : Type_Acc; begin - Synth_Assignment_Prefix (Syn_Inst, Sig, Base, Typ, Off, Voff, Wd); + Synth_Assignment_Prefix (Syn_Inst, Sig, Base, Typ, Off, Dyn); pragma Assert (Off = (0, 0)); - pragma Assert (Voff = No_Net); + pragma Assert (Dyn.Voff = No_Net); pragma Assert (Base.Val.Kind = Value_Wire); pragma Assert (Base.Typ = Typ); diff --git a/src/synth/synth-stmts.ads b/src/synth/synth-stmts.ads index dce23cf8e..7f449e90c 100644 --- a/src/synth/synth-stmts.ads +++ b/src/synth/synth-stmts.ads @@ -34,21 +34,34 @@ package Synth.Stmts is Inter_Chain : Node; Assoc_Chain : Node); + -- Dynamic index for Synth_Assignment_Prefix. + -- As dynamic is about dynamic (!) index, the index is a net. + type Dyn_Name is record + -- Start and type of the indexed part, which can be a part of the + -- base name. + Pfx_Off : Value_Offsets; + Pfx_Typ : Type_Acc; + + -- Variable offset. + Voff : Net; + end record; + + No_Dyn_Name : constant Dyn_Name := (Pfx_Off => No_Value_Offsets, + Pfx_Typ => null, + Voff => No_Net); + -- Transform PFX into DEST_*. -- DEST_BASE is the base object (with its own typ). Can be the result, -- a net or an object larger than the result. -- DEST_TYP is the type of the result. - -- DEST_NET_OFF/DEST_MEM_OFF/DEST_VOFF are the offsets in the base. - -- DEST_NET_OFF is used when - -- the base is a net, while DEST_VOFF is set when the offset is dynamic. - -- DEST_RDWD is the width of what is extracted from the base. + -- DEST_OFF is the offset, within DEST_DYN. + -- DEST_DYN is set (Voff field set) when there is a non-static index. procedure Synth_Assignment_Prefix (Syn_Inst : Synth_Instance_Acc; Pfx : Node; Dest_Base : out Valtyp; Dest_Typ : out Type_Acc; Dest_Off : out Value_Offsets; - Dest_Voff : out Net; - Dest_Rdwd : out Width); + Dest_Dyn : out Dyn_Name); procedure Synth_Assignment (Syn_Inst : Synth_Instance_Acc; Target : Node; @@ -59,7 +72,7 @@ package Synth.Stmts is Obj : Valtyp; Res_Typ : Type_Acc; Off : Uns32; - Voff : Net; + Dyn : Dyn_Name; Loc : Node) return Valtyp; function Synth_User_Function_Call |