aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synth-stmts.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-01-08 07:27:14 +0100
committerTristan Gingold <tgingold@free.fr>2020-01-08 07:28:29 +0100
commite4384df2d52f319b2a8e45b3a1a26277d88760b5 (patch)
treedb40677456c84e8f159d4d94190589237e173344 /src/synth/synth-stmts.adb
parent513ea00c0d355c1534b8ed6f28a78ca15c91d612 (diff)
downloadghdl-e4384df2d52f319b2a8e45b3a1a26277d88760b5.tar.gz
ghdl-e4384df2d52f319b2a8e45b3a1a26277d88760b5.tar.bz2
ghdl-e4384df2d52f319b2a8e45b3a1a26277d88760b5.zip
synth: improve support of out/inout variable parameters.
Diffstat (limited to 'src/synth/synth-stmts.adb')
-rw-r--r--src/synth/synth-stmts.adb74
1 files changed, 66 insertions, 8 deletions
diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb
index 4717cd488..4986ea1b1 100644
--- a/src/synth/synth-stmts.adb
+++ b/src/synth/synth-stmts.adb
@@ -51,6 +51,7 @@ with Synth.Flags;
with Synth.Debugger;
with Netlists.Builders; use Netlists.Builders;
+with Netlists.Folds; use Netlists.Folds;
with Netlists.Gates;
with Netlists.Utils; use Netlists.Utils;
with Netlists.Locations; use Netlists.Locations;
@@ -538,6 +539,22 @@ package body Synth.Stmts is
return Create_Value_Net (N, Typ);
end Synth_Read_Memory;
+ function Synth_Read (Syn_Inst : Synth_Instance_Acc;
+ Targ : Target_Info;
+ Loc : Node) return Value_Acc
+ is
+ N : Net;
+ begin
+ if Targ.Kind = Target_Simple then
+ N := Build2_Extract (Get_Build (Syn_Inst),
+ Get_Net (Targ.Obj), Targ.Off, Targ.Targ_Type.W);
+ return Create_Value_Net (N, Targ.Targ_Type);
+ else
+ return Synth_Read_Memory (Syn_Inst, Targ.Obj, Targ.Off, No_Net,
+ Targ.Targ_Type, Loc);
+ end if;
+ end Synth_Read;
+
-- Concurrent or sequential simple signal assignment
procedure Synth_Simple_Signal_Assignment
(Syn_Inst : Synth_Instance_Acc; Stmt : Node)
@@ -1432,12 +1449,8 @@ package body Synth.Stmts is
raise Internal_Error;
end if;
Val := Info.Obj;
- elsif Info.Kind = Target_Simple then
- Val := Info.Obj;
else
- Val := Synth_Read_Memory
- (Caller_Inst, Info.Obj, Info.Off, No_Net,
- Info.Targ_Type, Assoc);
+ Val := Synth_Read (Caller_Inst, Info, Assoc);
end if;
when Iir_Kind_Interface_Signal_Declaration =>
-- Always pass by reference (use an alias).
@@ -1463,7 +1476,13 @@ package body Synth.Stmts is
Create_Object (Subprg_Inst, Inter, Val);
when Iir_Kind_Interface_Variable_Declaration =>
-- Arguments are passed by copy.
- Create_Object (Subprg_Inst, Inter, Unshare (Val, Current_Pool));
+ if Is_Static (Val) or else Get_Mode (Inter) = Iir_In_Mode then
+ Val := Unshare (Val, Current_Pool);
+ else
+ -- Will be changed to a wire.
+ null;
+ end if;
+ Create_Object (Subprg_Inst, Inter, Val);
when Iir_Kind_Interface_Signal_Declaration =>
Create_Object (Subprg_Inst, Inter, Val);
when Iir_Kind_Interface_File_Declaration =>
@@ -1486,6 +1505,37 @@ package body Synth.Stmts is
Inter_Chain, Assoc_Chain, Infos);
end Synth_Subprogram_Association;
+ -- Create wires for out and inout interface variables.
+ procedure Synth_Subprogram_Association_Wires
+ (Subprg_Inst : Synth_Instance_Acc; Inter_Chain : Node; Assoc_Chain : Node)
+ is
+ Inter : Node;
+ Assoc : Node;
+ Val : Value_Acc;
+ Iterator : Association_Iterator;
+ Wire : Wire_Id;
+ begin
+ -- Process in INTER order.
+ Association_Iterate_Init (Iterator, Inter_Chain, Assoc_Chain);
+ loop
+ Association_Iterate_Next (Iterator, Inter, Assoc);
+ exit when Inter = Null_Node;
+
+ if Get_Mode (Inter) in Iir_Out_Modes
+ and then Get_Kind (Inter) = Iir_Kind_Interface_Variable_Declaration
+ then
+ Val := Get_Value (Subprg_Inst, Inter);
+ -- Arguments are passed by copy.
+ Wire := Alloc_Wire (Wire_Variable, Inter);
+ Set_Wire_Gate (Wire, Get_Net (Val));
+
+ Val := Create_Value_Wire (Wire, Val.Typ);
+ Create_Object_Force (Subprg_Inst, Inter, null);
+ Create_Object_Force (Subprg_Inst, Inter, Val);
+ end if;
+ end loop;
+ end Synth_Subprogram_Association_Wires;
+
procedure Synth_Subprogram_Back_Association
(Subprg_Inst : Synth_Instance_Acc;
Caller_Inst : Synth_Instance_Acc;
@@ -1513,6 +1563,12 @@ package body Synth.Stmts is
Nbr_Inout := Nbr_Inout + 1;
Val := Get_Value (Subprg_Inst, Inter);
Synth_Assignment (Caller_Inst, Infos (Nbr_Inout), Val, Assoc);
+
+ -- Free wire used for out/inout interface variables.
+ if Val.Kind = Value_Wire then
+ Phi_Discard_Wires (Val.W, No_Wire_Id);
+ Free_Wire (Val.W);
+ end if;
end if;
Next_Association_Interface (Assoc, Assoc_Inter);
@@ -1557,6 +1613,8 @@ package body Synth.Stmts is
Push_Phi;
+ Synth_Subprogram_Association_Wires (Sub_Inst, Inter_Chain, Assoc_Chain);
+
if Is_Func then
-- Set a default value for the return.
C.Ret_Typ := Get_Value_Type (Syn_Inst, Get_Return_Type (Imp));
@@ -1685,8 +1743,8 @@ package body Synth.Stmts is
Sub_Inst : Synth_Instance_Acc;
begin
Areapools.Mark (Area_Mark, Instance_Pool.all);
- Sub_Inst := Make_Instance (Syn_Inst, Bod,
- New_Internal_Name (Build_Context));
+ Sub_Inst := Make_Instance (Syn_Inst, Bod,
+ New_Internal_Name (Build_Context));
Synth_Subprogram_Association
(Sub_Inst, Syn_Inst, Inter_Chain, Assoc_Chain, Infos);