aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth')
-rw-r--r--src/synth/elab-vhdl_insts.adb2
-rw-r--r--src/synth/elab-vhdl_insts.ads3
-rw-r--r--src/synth/elab-vhdl_values.adb7
-rw-r--r--src/synth/elab-vhdl_values.ads3
-rw-r--r--src/synth/netlists-gates.ads4
-rw-r--r--src/synth/netlists-memories.adb151
-rw-r--r--src/synth/synth-environment.adb13
-rw-r--r--src/synth/synth-flags.ads5
-rw-r--r--src/synth/synth-vhdl_context.adb10
-rw-r--r--src/synth/synth-vhdl_context.ads1
-rw-r--r--src/synth/synth-vhdl_decls.adb22
-rw-r--r--src/synth/synth-vhdl_eval.adb4
-rw-r--r--src/synth/synth-vhdl_expr.adb115
-rw-r--r--src/synth/synth-vhdl_insts.adb277
-rw-r--r--src/synth/synth-vhdl_oper.adb7
-rw-r--r--src/synth/synth-vhdl_stmts.adb18
16 files changed, 454 insertions, 188 deletions
diff --git a/src/synth/elab-vhdl_insts.adb b/src/synth/elab-vhdl_insts.adb
index 25984a8fa..ac60a49f9 100644
--- a/src/synth/elab-vhdl_insts.adb
+++ b/src/synth/elab-vhdl_insts.adb
@@ -1042,6 +1042,8 @@ package body Elab.Vhdl_Insts is
pragma Assert (Is_Expr_Pool_Empty);
+ Top_Instance := Top_Inst;
+
Elab_Instance_Body (Top_Inst);
pragma Assert (Areapools.Is_Empty (Expr_Pool));
diff --git a/src/synth/elab-vhdl_insts.ads b/src/synth/elab-vhdl_insts.ads
index 1e78c3329..ca79f762a 100644
--- a/src/synth/elab-vhdl_insts.ads
+++ b/src/synth/elab-vhdl_insts.ads
@@ -21,6 +21,9 @@ with Vhdl.Nodes; use Vhdl.Nodes;
with Elab.Vhdl_Context; use Elab.Vhdl_Context;
package Elab.Vhdl_Insts is
+ -- The result of Elab_Top_Unit, to handle external names.
+ Top_Instance : Synth_Instance_Acc;
+
function Elab_Top_Unit (Config : Node) return Synth_Instance_Acc;
procedure Elab_Generics_Association (Sub_Inst : Synth_Instance_Acc;
diff --git a/src/synth/elab-vhdl_values.adb b/src/synth/elab-vhdl_values.adb
index 0a1a4b982..724e961b5 100644
--- a/src/synth/elab-vhdl_values.adb
+++ b/src/synth/elab-vhdl_values.adb
@@ -105,13 +105,14 @@ package body Elab.Vhdl_Values is
return To_Value_Acc (Alloc (Pool, (Kind => Value_Wire, N => S)));
end Create_Value_Wire;
- function Create_Value_Net (S : Uns32) return Value_Acc
+ function Create_Value_Net (S : Uns32; Pool : Areapool_Acc)
+ return Value_Acc
is
subtype Value_Type_Net is Value_Type (Value_Net);
function Alloc is new Areapools.Alloc_On_Pool_Addr (Value_Type_Net);
begin
return To_Value_Acc
- (Alloc (Current_Pool, Value_Type_Net'(Kind => Value_Net, N => S)));
+ (Alloc (Pool, Value_Type_Net'(Kind => Value_Net, N => S)));
end Create_Value_Net;
function Create_Value_Signal (S : Signal_Index_Type; Init : Value_Acc)
@@ -306,7 +307,7 @@ package body Elab.Vhdl_Values is
Res := Create_Value_Memory (Src.Typ, Current_Pool);
Copy_Memory (Res.Val.Mem, Src.Val.Mem, Src.Typ.Sz);
when Value_Net =>
- Res := (Src.Typ, Create_Value_Net (Src.Val.N));
+ Res := (Src.Typ, Create_Value_Net (Src.Val.N, Current_Pool));
when Value_Wire =>
Res := (Src.Typ, Create_Value_Wire (Src.Val.N, Current_Pool));
when Value_File =>
diff --git a/src/synth/elab-vhdl_values.ads b/src/synth/elab-vhdl_values.ads
index 21ea4a35b..c4482c71c 100644
--- a/src/synth/elab-vhdl_values.ads
+++ b/src/synth/elab-vhdl_values.ads
@@ -140,7 +140,8 @@ package Elab.Vhdl_Values is
function Is_Equal (L, R : Valtyp) return Boolean;
-- Create a Value_Net.
- function Create_Value_Net (S : Uns32) return Value_Acc;
+ function Create_Value_Net (S : Uns32; Pool : Areapool_Acc)
+ return Value_Acc;
-- Create a Value_Wire.
function Create_Value_Wire (S : Uns32; Pool : Areapool_Acc)
diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads
index b496111ae..e5ad1a052 100644
--- a/src/synth/netlists-gates.ads
+++ b/src/synth/netlists-gates.ads
@@ -119,6 +119,10 @@ package Netlists.Gates is
-- by a gate (and thus the value of the output could be read), but that
-- driving value may not be available early enough.
-- Id_Ioutput is an output with an initial value.
+ --
+ -- Inputs: 0: driver
+ -- 1: initial value (if any)
+ -- Output: 0: value
Id_Signal : constant Module_Id := 52;
Id_Isignal : constant Module_Id := 53;
Id_Output : constant Module_Id := 54;
diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb
index 84267ea44..8e62137e6 100644
--- a/src/synth/netlists-memories.adb
+++ b/src/synth/netlists-memories.adb
@@ -438,7 +438,8 @@ package body Netlists.Memories is
-- Return True iff MUX_INP is a mux2 input whose output is connected to a
-- dff to create a DFF with enable (the other mux2 input is connected to
-- the dff output).
- function Is_Enable_Dff (Mux_Inp : Input) return Boolean
+ procedure Is_Enable_Dff
+ (Mux_Inp : Input; Res : out Boolean; Inv : out Boolean)
is
Mux_Inst : constant Instance := Get_Input_Parent (Mux_Inp);
pragma Assert (Get_Id (Mux_Inst) = Id_Mux2);
@@ -446,42 +447,56 @@ package body Netlists.Memories is
Inp : Input;
Dff_Inst : Instance;
Dff_Out : Net;
+ Prt : Port_Idx;
begin
+ Inv := False;
+ Res := False;
+
Inp := Get_First_Sink (Mux_Out);
if Inp = No_Input or else Get_Next_Sink (Inp) /= No_Input then
-- The output of the mux must be connected to one input.
- return False;
+ return;
end if;
+
+ -- Check if the mux is before a dff.
Dff_Inst := Get_Input_Parent (Inp);
if Get_Id (Dff_Inst) /= Id_Dff then
- return False;
+ return;
end if;
+
Dff_Out := Get_Output (Dff_Inst, 0);
if Mux_Inp = Get_Input (Mux_Inst, 1) then
- return Skip_Signal (Get_Input_Net (Mux_Inst, 2)) = Dff_Out;
+ -- Loop on sel = 1 (so enable is inverted).
+ Inv := True;
+ Prt := 2;
else
- return Skip_Signal (Get_Input_Net (Mux_Inst, 1)) = Dff_Out;
+ -- Loop on sel = 0.
+ Prt := 1;
end if;
+ Res := Skip_Signal (Get_Input_Net (Mux_Inst, Prt)) = Dff_Out;
end Is_Enable_Dff;
- -- INST is a Dyn_Extract.
- -- If INST is followed by a dff or a dff+enable (with mux2), return the
- -- dff in LAST_INST, the clock in CLK and the enable in EN.
+ -- EXTR_INST is a Dyn_Extract.
+ -- If EXTR_INST is followed by a dff or a dff+enable (with mux2),
+ -- return the dff in LAST_INST, the clock in CLK and the enable in EN.
procedure Extract_Extract_Dff (Ctxt : Context_Acc;
- Inst : Instance;
+ Extr_Inst : Instance;
Last_Inst : out Instance;
Clk : out Net;
En : out Net)
is
- Val : constant Net := Get_Output (Inst, 0);
+ Val : constant Net := Get_Output (Extr_Inst, 0);
Inp : Input;
Iinst : Instance;
+ Is_Dff : Boolean;
+ Is_Inv : Boolean;
begin
Inp := Get_First_Sink (Val);
if Get_Next_Sink (Inp) = No_Input then
- -- There is a single input.
+ -- The output of INST (a Dyn_Extract) goes to only one gate.
Iinst := Get_Input_Parent (Inp);
+
if Get_Id (Iinst) = Id_Dff then
-- The output of the dyn_extract is directly connected to a dff.
-- So this is a synchronous read without enable.
@@ -496,7 +511,13 @@ package body Netlists.Memories is
Last_Inst := Iinst;
return;
end;
- elsif Get_Id (Iinst) = Id_Mux2 and then Is_Enable_Dff (Inp) then
+ end if;
+ if Get_Id (Iinst) = Id_Mux2 then
+ Is_Enable_Dff (Inp, Is_Dff, Is_Inv);
+ else
+ Is_Dff := False;
+ end if;
+ if Is_Dff then
declare
Mux_Out : constant Net := Get_Output (Iinst, 0);
Mux_En_Inp : constant Input := Get_Input (Iinst, 0);
@@ -504,12 +525,11 @@ package body Netlists.Memories is
Mux_I1_Inp : constant Input := Get_Input (Iinst, 2);
Dff_Din : constant Input := Get_First_Sink (Mux_Out);
Dff_Inst : constant Instance := Get_Input_Parent (Dff_Din);
- Dff_Out : constant Net := Get_Output (Dff_Inst, 0);
Clk_Inp : constant Input := Get_Input (Dff_Inst, 0);
begin
Clk := Get_Driver (Clk_Inp);
En := Get_Driver (Mux_En_Inp);
- if Dff_Out = Get_Driver (Mux_I1_Inp) then
+ if Is_Inv then
En := Build_Monadic (Ctxt, Id_Not, En);
Copy_Location (En, Iinst);
end if;
@@ -525,7 +545,7 @@ package body Netlists.Memories is
end if;
end if;
- Last_Inst := Inst;
+ Last_Inst := Extr_Inst;
Clk := No_Net;
En := No_Net;
end Extract_Extract_Dff;
@@ -1019,89 +1039,43 @@ package body Netlists.Memories is
-- VAL is the output of the dyn_extract.
--
-- Infere a synchronous read if the dyn_extract is connected to a dff.
- function Create_ROM_Read_Port
- (Ctxt : Context_Acc; Last : Net; Addr : Net; Val : Net; Step : Width)
- return Instance
+ function Create_ROM_Read_Port (Ctxt : Context_Acc;
+ Last : Net;
+ Addr : Net;
+ Extr_Inst : Instance;
+ Step : Width) return Instance
is
+ Val : constant Net := Get_Output (Extr_Inst, 0);
W : constant Width := Get_Width (Val);
Res : Instance;
- Inp : Input;
- Iinst : Instance;
+ Dff_Inst : Instance;
N : Net;
+ Clk : Net;
+ En : Net;
begin
- Inp := Get_First_Sink (Val);
- if Get_Next_Sink (Inp) = No_Input then
- -- There is a single input.
- Iinst := Get_Input_Parent (Inp);
- if Get_Id (Iinst) = Id_Dff then
- -- The output of the dyn_extract is directly connected to a dff.
- -- So this is a synchronous read without enable.
- declare
- Clk_Inp : Input;
- Clk : Net;
- En : Net;
- begin
- Clk_Inp := Get_Input (Iinst, 0);
- Clk := Get_Driver (Clk_Inp);
- Disconnect (Clk_Inp);
- En := Build_Const_UB32 (Ctxt, 1, 1);
- Disconnect (Inp);
- Res := Build_Mem_Rd_Sync (Ctxt, Last, Addr, Clk, En, Step);
-
- -- Slice the output.
- N := Get_Output (Res, 1);
- N := Build2_Extract (Ctxt, N, 0, W);
-
- Redirect_Inputs (Get_Output (Iinst, 0), N);
- Remove_Instance (Iinst);
- return Res;
- end;
- elsif Get_Id (Iinst) = Id_Mux2 and then Is_Enable_Dff (Inp) then
- declare
- Mux_Out : constant Net := Get_Output (Iinst, 0);
- Mux_En_Inp : constant Input := Get_Input (Iinst, 0);
- Mux_I0_Inp : constant Input := Get_Input (Iinst, 1);
- Mux_I1_Inp : constant Input := Get_Input (Iinst, 2);
- Dff_Din : constant Input := Get_First_Sink (Mux_Out);
- Dff_Inst : constant Instance := Get_Input_Parent (Dff_Din);
- Dff_Out : constant Net := Get_Output (Dff_Inst, 0);
- Clk_Inp : constant Input := Get_Input (Dff_Inst, 0);
- Clk : constant Net := Get_Driver (Clk_Inp);
- En : Net;
- begin
- En := Get_Driver (Mux_En_Inp);
- if Dff_Out = Get_Driver (Mux_I1_Inp) then
- En := Build_Monadic (Ctxt, Id_Not, En);
- Copy_Location (En, Dff_Inst);
- end if;
- Disconnect (Mux_En_Inp);
- Disconnect (Mux_I0_Inp);
- Disconnect (Mux_I1_Inp);
- Disconnect (Dff_Din);
- Disconnect (Clk_Inp);
- Remove_Instance (Iinst);
- Res := Build_Mem_Rd_Sync (Ctxt, Last, Addr, Clk, En, Step);
- Set_Location (Res, Get_Location (Dff_Inst));
-
- -- Slice the output.
- N := Get_Output (Res, 1);
- N := Build2_Extract (Ctxt, N, 0, W);
-
- Redirect_Inputs (Dff_Out, N);
- Remove_Instance (Dff_Inst);
- return Res;
- end;
+ Extract_Extract_Dff (Ctxt, Extr_Inst, Dff_Inst, Clk, En);
+ if Dff_Inst /= Extr_Inst then
+ -- There was a dff, so the read port is synchronous.
+ if En = No_Net then
+ En := Build_Const_UB32 (Ctxt, 1, 1);
end if;
- end if;
- -- Replace Dyn_Extract with mem_rd.
- Res := Build_Mem_Rd (Ctxt, Last, Addr, Step);
+ Res := Build_Mem_Rd_Sync (Ctxt, Last, Addr, Clk, En, Step);
+ else
+ -- Replace Dyn_Extract with mem_rd (asynchronous read port).
+ Res := Build_Mem_Rd (Ctxt, Last, Addr, Step);
+ end if;
-- Slice the output.
N := Get_Output (Res, 1);
N := Build2_Extract (Ctxt, N, 0, W);
- Redirect_Inputs (Val, N);
+ if Dff_Inst /= Extr_Inst then
+ Redirect_Inputs (Get_Output (Dff_Inst, 0), N);
+ Remove_Instance (Dff_Inst);
+ else
+ Redirect_Inputs (Get_Output (Extr_Inst, 0), N);
+ end if;
return Res;
end Create_ROM_Read_Port;
@@ -1117,7 +1091,6 @@ package body Netlists.Memories is
Extr_Inst : Instance;
Addr_Inp : Input;
Addr : Net;
- Val : Net;
Port_Inst : Instance;
begin
Last := Get_Output (Mem_Inst, 0);
@@ -1142,11 +1115,11 @@ package body Netlists.Memories is
Addr_Inp := Get_Input (Extr_Inst, 1);
Addr := Get_Driver (Addr_Inp);
Disconnect (Addr_Inp);
- Val := Get_Output (Extr_Inst, 0);
Convert_Memidx (Ctxt, Orig, Addr, Step);
-- Replace Dyn_Extract with mem_rd.
- Port_Inst := Create_ROM_Read_Port (Ctxt, Last, Addr, Val, Step);
+ Port_Inst := Create_ROM_Read_Port
+ (Ctxt, Last, Addr, Extr_Inst, Step);
Remove_Instance (Extr_Inst);
diff --git a/src/synth/synth-environment.adb b/src/synth/synth-environment.adb
index d6b48ec88..bd68aa39f 100644
--- a/src/synth/synth-environment.adb
+++ b/src/synth/synth-environment.adb
@@ -770,12 +770,19 @@ package body Synth.Environment is
function Is_Tribuf_Net (N : Net) return Boolean
is
use Netlists.Gates;
+ Inst : constant Instance := Get_Net_Parent (N);
begin
- case Get_Id (Get_Net_Parent (N)) is
+ case Get_Id (Inst) is
when Id_Tri
- | Id_Resolver
- | Id_Port =>
+ | Id_Resolver
+ | Id_Const_Z =>
+ return True;
+ when Id_Port =>
+ -- We don't know, so assume yes.
return True;
+ when Id_Signal
+ | Id_Isignal =>
+ return Is_Tribuf_Net (Get_Input_Net (Inst, 0));
when others =>
return False;
end case;
diff --git a/src/synth/synth-flags.ads b/src/synth/synth-flags.ads
index aa3a0b8aa..541663543 100644
--- a/src/synth/synth-flags.ads
+++ b/src/synth/synth-flags.ads
@@ -74,6 +74,11 @@ package Synth.Flags is
-- Synthesize PSL and assertions.
Flag_Formal : Boolean := True;
+ -- True to keep hierarchy: an module/entity instantiation is synthesized
+ -- as an instantiation.
+ -- If false, the netlist is flat.
+ Flag_Keep_Hierarchy : Boolean := True;
+
-- If true, automatically add a cover on PSL asserts to know if the
-- asserted has been started.
Flag_Assert_Cover : Boolean := True;
diff --git a/src/synth/synth-vhdl_context.adb b/src/synth/synth-vhdl_context.adb
index 55f9f795d..81898157f 100644
--- a/src/synth/synth-vhdl_context.adb
+++ b/src/synth/synth-vhdl_context.adb
@@ -384,18 +384,16 @@ package body Synth.Vhdl_Context is
return (Wtype, Create_Value_Wire (W, Pool));
end Create_Value_Wire;
- function Create_Value_Net (N : Net) return Value_Acc
+ function Create_Value_Net (N : Net; Pool : Areapool_Acc) return Value_Acc
is
function To_Uns32 is new Ada.Unchecked_Conversion (Net, Uns32);
begin
- return Create_Value_Net (To_Uns32 (N));
+ return Create_Value_Net (To_Uns32 (N), Pool);
end Create_Value_Net;
- function Create_Value_Net (N : Net; Ntype : Type_Acc) return Valtyp
- is
- pragma Assert (Ntype /= null);
+ function Create_Value_Net (N : Net; Ntype : Type_Acc) return Valtyp is
begin
- return (Ntype, Create_Value_Net (N));
+ return (Ntype, Create_Value_Net (N, Current_Pool));
end Create_Value_Net;
function Create_Value_Dyn_Alias (Obj : Value_Acc;
diff --git a/src/synth/synth-vhdl_context.ads b/src/synth/synth-vhdl_context.ads
index 396f0718d..94dc401d4 100644
--- a/src/synth/synth-vhdl_context.ads
+++ b/src/synth/synth-vhdl_context.ads
@@ -104,6 +104,7 @@ package Synth.Vhdl_Context is
pragma Inline (Set_Value_Wire);
-- Create a Value_Net.
+ function Create_Value_Net (N : Net; Pool : Areapool_Acc) return Value_Acc;
function Create_Value_Net (N : Net; Ntype : Type_Acc) return Valtyp;
-- Create a Value_Wire. For a bit wire, RNG must be null.
diff --git a/src/synth/synth-vhdl_decls.adb b/src/synth/synth-vhdl_decls.adb
index 19473775f..f1e42c97b 100644
--- a/src/synth/synth-vhdl_decls.adb
+++ b/src/synth/synth-vhdl_decls.adb
@@ -659,12 +659,12 @@ package body Synth.Vhdl_Decls is
if Aval.Val.Kind = Value_Net then
-- Object is a net if it is not writable. Extract the
-- bits for the alias.
- Current_Pool := Instance_Pool;
- Aval := Create_Value_Net
- (Build2_Extract (Get_Build (Syn_Inst), Get_Value_Net (Aval.Val),
- Off, Val.Typ.W),
- Val.Typ);
- Current_Pool := Expr_Pool'Access;
+ Aval := (Val.Typ,
+ Create_Value_Net (Build2_Extract
+ (Get_Build (Syn_Inst),
+ Get_Value_Net (Aval.Val),
+ Off, Val.Typ.W),
+ Instance_Pool));
Val.Val.A_Off := (0, 0);
else
Aval := Unshare (Aval, Instance_Pool);
@@ -844,6 +844,14 @@ package body Synth.Vhdl_Decls is
Finalize_Assignment (Get_Build (Syn_Inst), W);
Gate_Net := Get_Wire_Gate (W);
+
+ Free_Wire (W);
+
+ -- Replace the wire with a net so that external names can refer to it.
+ Mutate_Object
+ (Syn_Inst, Decl,
+ (Vt.Typ, Create_Value_Net (Gate_Net, Process_Pool'Access)));
+
Gate := Get_Net_Parent (Gate_Net);
case Get_Id (Gate) is
when Id_Signal
@@ -883,8 +891,6 @@ package body Synth.Vhdl_Decls is
-- The value of an undriven signal is its initial value.
Connect (Get_Input (Gate, 0), Def_Val);
end if;
-
- Free_Wire (W);
end Finalize_Signal;
procedure Finalize_Declaration
diff --git a/src/synth/synth-vhdl_eval.adb b/src/synth/synth-vhdl_eval.adb
index 020c67896..1913f349a 100644
--- a/src/synth/synth-vhdl_eval.adb
+++ b/src/synth/synth-vhdl_eval.adb
@@ -609,6 +609,7 @@ package body Synth.Vhdl_Eval is
end case;
end Eval_Vector_Minimum;
+ -- ARG to log-vector, sign extended.
function Eval_To_Log_Vector (Arg : Uns64; Sz : Int64; Res_Type : Type_Acc)
return Memtyp
is
@@ -2634,7 +2635,8 @@ package body Synth.Vhdl_Eval is
(Uns64 (Read_Discrete (Param1)), Int64 (Param2.Typ.Abound.Len),
Res_Typ);
when Iir_Predefined_Ieee_Numeric_Std_Tosgn_Int_Nat_Sgn
- | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Vector_Int =>
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Vector_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Signed_Int =>
return Eval_To_Log_Vector
(To_Uns64 (Read_Discrete (Param1)), Read_Discrete (Param2),
Res_Typ);
diff --git a/src/synth/synth-vhdl_expr.adb b/src/synth/synth-vhdl_expr.adb
index b5093cb02..c73b2133e 100644
--- a/src/synth/synth-vhdl_expr.adb
+++ b/src/synth/synth-vhdl_expr.adb
@@ -41,6 +41,7 @@ with Elab.Vhdl_Annotations;
with Elab.Vhdl_Heap; use Elab.Vhdl_Heap;
with Elab.Vhdl_Types; use Elab.Vhdl_Types;
with Elab.Vhdl_Expr;
+with Elab.Vhdl_Insts;
with Synth.Errors; use Synth.Errors;
with Synth.Vhdl_Environment;
@@ -830,6 +831,114 @@ package body Synth.Vhdl_Expr is
end case;
end Synth_Subtype_Conversion;
+ function Synth_Pathname (Loc_Inst : Synth_Instance_Acc;
+ Name : Node;
+ Cur_Inst : Synth_Instance_Acc;
+ Path : Node) return Valtyp
+ is
+ Suffix : constant Node := Get_Pathname_Suffix (Path);
+ Id : constant Name_Id := Get_Identifier (Path);
+ Scope : constant Node := Get_Source_Scope (Cur_Inst);
+ Res : Node;
+ begin
+ if Suffix = Null_Node then
+ -- Object simple name.
+ case Get_Kind (Scope) is
+ when Iir_Kind_Architecture_Body =>
+ Res := Find_Name_In_Chain (Get_Declaration_Chain (Scope), Id);
+ when others =>
+ Error_Kind ("synth_pathname(obj)", Scope);
+ end case;
+ if Res = Null_Node then
+ Error_Msg_Synth
+ (Loc_Inst, Path, "cannot find object %i in %i", (+Id, +Scope));
+ return No_Valtyp;
+ end if;
+ case Get_Kind (Res) is
+ when Iir_Kind_Signal_Declaration =>
+ case Iir_Kinds_External_Name (Get_Kind (Name)) is
+ when Iir_Kind_External_Signal_Name =>
+ return Get_Value (Cur_Inst, Res);
+ when Iir_Kind_External_Constant_Name
+ | Iir_Kind_External_Variable_Name =>
+ Error_Msg_Synth
+ (Loc_Inst, Path, "object name %i is a signal", +Res);
+ return No_Valtyp;
+ end case;
+ when others =>
+ Error_Kind ("synth_pathname(1)", Res);
+ end case;
+ else
+ -- Find name in concurrent statements.
+ case Get_Kind (Scope) is
+ when Iir_Kind_Architecture_Body =>
+ Res := Find_Name_In_Chain
+ (Get_Concurrent_Statement_Chain (Scope), Id);
+ when others =>
+ Error_Kind ("synth_pathname(scope)", Scope);
+ end case;
+ if Res = Null_Node then
+ Error_Msg_Synth
+ (Loc_Inst, Path,
+ "cannot find path element %i in %i", (+Id, +Scope));
+ return No_Valtyp;
+ end if;
+ case Get_Kind (Res) is
+ when Iir_Kind_Component_Instantiation_Statement =>
+ if Is_Entity_Instantiation (Res) then
+ return Synth_Pathname
+ (Loc_Inst, Name, Get_Sub_Instance (Cur_Inst, Res), Suffix);
+ else
+ -- TODO: skip component.
+ raise Internal_Error;
+ end if;
+ when others =>
+ Error_Kind ("synth_pathname(2)", Res);
+ end case;
+ end if;
+ end Synth_Pathname;
+
+ function Synth_Absolute_Pathname
+ (Syn_Inst : Synth_Instance_Acc; Name : Node; Path : Node) return Valtyp
+ is
+ Path_Inst : constant Synth_Instance_Acc := Elab.Vhdl_Insts.Top_Instance;
+ Top_Arch : constant Node := Get_Source_Scope (Path_Inst);
+ Top_Ent : constant Node := Get_Entity (Top_Arch);
+ Suffix : constant Node := Get_Pathname_Suffix (Path);
+ begin
+ if Get_Identifier (Top_Ent) /= Get_Identifier (Suffix) then
+ Error_Msg_Synth
+ (Syn_Inst, Path,
+ "root %i of absolute pathname is not the top entity %i",
+ (+Top_Ent, +Suffix));
+ return No_Valtyp;
+ end if;
+
+ return Synth_Pathname
+ (Syn_Inst, Name, Path_Inst, Get_Pathname_Suffix (Suffix));
+ end Synth_Absolute_Pathname;
+
+ function Synth_External_Name (Syn_Inst : Synth_Instance_Acc; Name : Node)
+ return Valtyp
+ is
+ Path : Node;
+ Res : Valtyp;
+ begin
+ Path := Get_External_Pathname (Name);
+ case Get_Kind (Path) is
+ when Iir_Kind_Absolute_Pathname =>
+ Res := Synth_Absolute_Pathname (Syn_Inst, Name, Path);
+ when others =>
+ Error_Kind ("synth_external_name", Path);
+ end case;
+ if Res = No_Valtyp then
+ return No_Valtyp;
+ end if;
+
+ -- TODO: type.
+ return Res;
+ end Synth_External_Name;
+
function Synth_Name (Syn_Inst : Synth_Instance_Acc; Name : Node)
return Valtyp is
begin
@@ -854,6 +963,8 @@ package body Synth.Vhdl_Expr is
| Iir_Kind_File_Declaration
| Iir_Kind_Interface_File_Declaration =>
return Get_Value (Syn_Inst, Name);
+ when Iir_Kind_External_Signal_Name =>
+ return Synth_External_Name (Syn_Inst, Name);
when Iir_Kind_Attribute_Value =>
-- It's a little bit complex for attribute of an entity or
-- of an architecture as there might be no instances for them.
@@ -2041,7 +2152,6 @@ package body Synth.Vhdl_Expr is
Set_Location (Res, Call);
return Create_Value_Net (Res, Boolean_Type);
-
end Synth_Psl_Stable;
function Synth_Psl_Rose (Syn_Inst : Synth_Instance_Acc; Call : Node)
@@ -2072,7 +2182,6 @@ package body Synth.Vhdl_Expr is
Set_Location (Res, Call);
return Create_Value_Net (Res, Boolean_Type);
-
end Synth_Psl_Rose;
function Synth_Psl_Fell (Syn_Inst : Synth_Instance_Acc; Call : Node)
@@ -2102,7 +2211,6 @@ package body Synth.Vhdl_Expr is
Set_Location (Res, Call);
return Create_Value_Net (Res, Boolean_Type);
-
end Synth_Psl_Fell;
function Synth_Onehot0 (Ctxt : Context_Acc; DffCurr : Net; Call : Node;
@@ -2358,6 +2466,7 @@ package body Synth.Vhdl_Expr is
| Iir_Kind_Guard_Signal_Declaration
| Iir_Kind_Object_Alias_Declaration -- For PSL
| Iir_Kind_Non_Object_Alias_Declaration -- For PSL
+ | Iir_Kind_External_Signal_Name
| Iir_Kind_Implicit_Dereference
| Iir_Kind_Dereference =>
declare
diff --git a/src/synth/synth-vhdl_insts.adb b/src/synth/synth-vhdl_insts.adb
index 2a20d06a9..35c8ac392 100644
--- a/src/synth/synth-vhdl_insts.adb
+++ b/src/synth/synth-vhdl_insts.adb
@@ -60,6 +60,10 @@ with Synth.Vhdl_Context; use Synth.Vhdl_Context;
package body Synth.Vhdl_Insts is
Global_Base_Instance : Base_Instance_Acc;
+ procedure Synth_Instance_Design (Syn_Inst : Synth_Instance_Acc;
+ Entity : Node;
+ Arch : Node);
+
function Mode_To_Port_Kind (Mode : Iir_Mode) return Port_Kind is
begin
case Mode is
@@ -479,7 +483,9 @@ package body Synth.Vhdl_Insts is
Inter := Get_Chain (Inter);
end loop;
- -- Allocate values and count inputs and outputs
+ -- There are already valtyp for ports (created during elab), but they
+ -- are signals. Convert ports valtyp to nets/wires.
+ -- Count inputs and outputs.
Inter := Get_Port_Chain (Decl);
Nbr_Inputs := 0;
Nbr_Outputs := 0;
@@ -818,7 +824,8 @@ package body Synth.Vhdl_Insts is
procedure Synth_Individual_Output_Assoc (Outp : Net;
Syn_Inst : Synth_Instance_Acc;
Inter_Typ : Type_Acc;
- Assoc : Node)
+ Assoc : Node;
+ Add_Port : Boolean)
is
Marker : Mark_Type;
Iassoc : Node;
@@ -830,8 +837,12 @@ package body Synth.Vhdl_Insts is
begin
Mark_Expr_Pool (Marker);
- Port := Builders.Build_Port (Get_Build (Syn_Inst), Outp);
- Set_Location (Port, Assoc);
+ if Add_Port then
+ Port := Builders.Build_Port (Get_Build (Syn_Inst), Outp);
+ Set_Location (Port, Assoc);
+ else
+ Port := Outp;
+ end if;
Iassoc := Get_Chain (Assoc);
while Iassoc /= Null_Node
@@ -855,14 +866,16 @@ package body Synth.Vhdl_Insts is
end loop;
end Synth_Individual_Output_Assoc;
+ -- Associate output according to ASSOC.
+ -- If ADD_PORT is true, a port gate is added.
procedure Synth_Output_Assoc (Outp : Net;
Syn_Inst : Synth_Instance_Acc;
Assoc : Node;
Inter_Inst : Synth_Instance_Acc;
- Inter : Node)
+ Inter : Node;
+ Add_Port : Boolean)
is
Marker : Mark_Type;
- Actual : Node;
Formal_Typ : Type_Acc;
Port : Net;
O : Valtyp;
@@ -872,23 +885,24 @@ package body Synth.Vhdl_Insts is
case Get_Kind (Assoc) is
when Iir_Kind_Association_Element_Open =>
-- Not connected.
- return;
+ null;
when Iir_Kinds_Association_Element_By_Actual =>
- Actual := Get_Actual (Assoc);
+ Mark_Expr_Pool (Marker);
+ -- Create a port gate (so that is has a name).
+ if Add_Port then
+ Port := Builders.Build_Port (Get_Build (Syn_Inst), Outp);
+ Set_Location (Port, Assoc);
+ else
+ Port := Outp;
+ end if;
+ O := Create_Value_Net (Port, Formal_Typ);
+ -- Assign the port output to the actual (a net).
+ Synth_Assignment (Syn_Inst, Get_Actual (Assoc), O, Assoc);
+ Release_Expr_Pool (Marker);
when others =>
Synth_Individual_Output_Assoc
- (Outp, Syn_Inst, Formal_Typ, Assoc);
- return;
+ (Outp, Syn_Inst, Formal_Typ, Assoc, Add_Port);
end case;
-
- Mark_Expr_Pool (Marker);
- -- Create a port gate (so that is has a name).
- Port := Builders.Build_Port (Get_Build (Syn_Inst), Outp);
- Set_Location (Port, Assoc);
- O := Create_Value_Net (Port, Formal_Typ);
- -- Assign the port output to the actual (a net).
- Synth_Assignment (Syn_Inst, Actual, O, Assoc);
- Release_Expr_Pool (Marker);
end Synth_Output_Assoc;
procedure Inst_Input_Connect (Syn_Inst : Synth_Instance_Acc;
@@ -1013,7 +1027,7 @@ package body Synth.Vhdl_Insts is
(Syn_Inst, Inst, Nbr_Outputs, Inter_Typ, N);
Synth_Output_Assoc
- (N, Syn_Inst, Assoc, Ent_Inst, Inter);
+ (N, Syn_Inst, Assoc, Ent_Inst, Inter, True);
end case;
pragma Assert (Areapools.Is_At_Mark (Expr_Pool, Marker));
@@ -1113,6 +1127,106 @@ package body Synth.Vhdl_Insts is
pragma Assert (Is_Expr_Pool_Empty);
end Synth_Direct_Instantiation_Statement;
+ procedure Synth_Flat_Instantiation_Statement
+ (Syn_Inst : Synth_Instance_Acc;
+ Stmt : Node;
+ Sub_Inst : Synth_Instance_Acc;
+ Entity : Node;
+ Arch : Node)
+ is
+ Ctxt : constant Context_Acc := Get_Build (Syn_Inst);
+ Inter : Node;
+ Inter_Typ : Type_Acc;
+ Val : Valtyp;
+ N : Net;
+ Name : Sname;
+ Wid : Wire_Id;
+ begin
+ pragma Assert (Is_Expr_Pool_Empty);
+
+ Name := New_Sname_User (Get_Identifier (Stmt), Get_Sname (Syn_Inst));
+ Set_Extra (Sub_Inst, Syn_Inst, Name);
+
+ -- There are already valtyp for ports (created during elab), but they
+ -- are signals. Convert ports valtyp to nets/wires.
+ Inter := Get_Port_Chain (Entity);
+ Current_Pool := Process_Pool'Access;
+ while Is_Valid (Inter) loop
+ Inter_Typ := Get_Value (Sub_Inst, Inter).Typ;
+
+ Name := New_Sname_User (Get_Identifier (Inter), Get_Sname (Sub_Inst));
+ N := Build_Signal
+ (Ctxt, New_Internal_Name (Ctxt, Name), Get_Type_Width (Inter_Typ));
+ Set_Location (N, Inter);
+
+ case Mode_To_Port_Kind (Get_Mode (Inter)) is
+ when Port_In =>
+ -- TODO: default value (isignal).
+ Val := Create_Value_Net (N, Inter_Typ);
+ when Port_Out
+ | Port_Inout =>
+ Wid := Alloc_Wire (Wire_Output, (Inter, Inter_Typ));
+ Set_Wire_Gate (Wid, N);
+ Val := Create_Value_Wire (Wid, Inter_Typ, Current_Pool);
+ end case;
+ Replace_Signal (Sub_Inst, Inter, Val);
+ Inter := Get_Chain (Inter);
+ end loop;
+ Current_Pool := Expr_Pool'Access;
+
+ -- Connections.
+ Push_Phi;
+
+ declare
+ Marker : Mark_Type;
+
+ Assoc : Node;
+ Assoc_Inter : Node;
+ Inter : Node;
+ Inter_Typ : Type_Acc;
+ N : Net;
+ Vt : Valtyp;
+ Inst : Instance;
+ begin
+ Mark_Expr_Pool (Marker);
+
+ Assoc := Get_Port_Map_Aspect_Chain (Stmt);
+ Assoc_Inter := Get_Port_Chain (Entity);
+ while Is_Valid (Assoc) loop
+ if Get_Whole_Association_Flag (Assoc) then
+ Inter := Get_Association_Interface (Assoc, Assoc_Inter);
+ Inter_Typ := Get_Subtype_Object (Sub_Inst, Get_Type (Inter));
+ Vt := Get_Value (Sub_Inst, Inter);
+
+ case Mode_To_Port_Kind (Get_Mode (Inter)) is
+ when Port_In =>
+ -- Connect the net to the input.
+ N := Synth_Input_Assoc
+ (Syn_Inst, Assoc, Sub_Inst, Inter, Inter_Typ);
+ if N /= No_Net then
+ -- Ignore errors.
+ Inst := Get_Net_Parent (Get_Value_Net (Vt.Val));
+ Connect (Get_Input (Inst, 0), N);
+ end if;
+
+ when Port_Out
+ | Port_Inout =>
+ N := Get_Wire_Gate (Get_Value_Wire (Vt.Val));
+ Synth_Output_Assoc
+ (N, Syn_Inst, Assoc, Sub_Inst, Inter, False);
+ end case;
+
+ Release_Expr_Pool (Marker);
+ end if;
+ Next_Association_Interface (Assoc, Assoc_Inter);
+ end loop;
+ end;
+
+ Pop_And_Merge_Phi (Ctxt, Get_Location (Stmt));
+
+ Synth_Instance_Design (Sub_Inst, Entity, Arch);
+ end Synth_Flat_Instantiation_Statement;
+
procedure Synth_Design_Instantiation_Statement
(Syn_Inst : Synth_Instance_Acc; Stmt : Node)
is
@@ -1122,8 +1236,20 @@ package body Synth.Vhdl_Insts is
Ent : constant Node := Get_Entity (Arch);
Config : constant Node := Get_Instance_Config (Sub_Inst);
begin
- Synth_Direct_Instantiation_Statement
- (Syn_Inst, Stmt, Sub_Inst, Ent, Arch, Config);
+ if Flag_Keep_Hierarchy then
+ Synth_Direct_Instantiation_Statement
+ (Syn_Inst, Stmt, Sub_Inst, Ent, Arch, Config);
+ else
+ -- Dependencies
+ -- Set files root dir
+ -- Create name prefix
+ -- Build ports
+ -- For in: net
+ -- For out/inout: wires
+ -- Connect
+ Synth_Flat_Instantiation_Statement
+ (Syn_Inst, Stmt, Sub_Inst, Ent, Arch);
+ end if;
end Synth_Design_Instantiation_Statement;
procedure Synth_Blackbox_Instantiation_Statement
@@ -1301,7 +1427,8 @@ package body Synth.Vhdl_Insts is
if Mode_To_Port_Kind (Get_Mode (Inter)) = Port_Out then
O := Get_Value (Comp_Inst, Inter);
Port := Get_Net (Ctxt, O);
- Synth_Output_Assoc (Port, Syn_Inst, Assoc, Comp_Inst, Inter);
+ Synth_Output_Assoc
+ (Port, Syn_Inst, Assoc, Comp_Inst, Inter, True);
Nbr_Outputs := Nbr_Outputs + 1;
end if;
end if;
@@ -1444,7 +1571,7 @@ package body Synth.Vhdl_Insts is
N : Net;
begin
pragma Assert (Val.Val.Kind = Value_Net);
- N := Get_Value_Net (Val.Val);
+ -- Get the net from the port(s).
Inst_Output_Connect (Syn_Inst, Self_Inst, Idx, Val.Typ, N);
Set_Value_Net (Val.Val, N);
end Create_Input_Wire;
@@ -1526,6 +1653,60 @@ package body Synth.Vhdl_Insts is
end loop;
end Synth_Verification_Units;
+ procedure Synth_Instance_Design (Syn_Inst : Synth_Instance_Acc;
+ Entity : Node;
+ Arch : Node)
+ is
+ begin
+ -- Entity
+ Synth_Concurrent_Declarations (Syn_Inst, Get_Declaration_Chain (Entity));
+ if not Is_Error (Syn_Inst) then
+ Synth_Concurrent_Statements
+ (Syn_Inst, Get_Concurrent_Statement_Chain (Entity));
+ end if;
+
+ pragma Assert (Is_Expr_Pool_Empty);
+
+ if not Is_Error (Syn_Inst) then
+ Synth_Attribute_Values (Syn_Inst, Entity);
+ end if;
+
+ pragma Assert (Is_Expr_Pool_Empty);
+
+ -- Architecture
+ if not Is_Error (Syn_Inst) then
+ Synth_Concurrent_Declarations
+ (Syn_Inst, Get_Declaration_Chain (Arch));
+ end if;
+
+ pragma Assert (Is_Expr_Pool_Empty);
+
+ if not Is_Error (Syn_Inst) then
+ Synth_Concurrent_Statements
+ (Syn_Inst, Get_Concurrent_Statement_Chain (Arch));
+ end if;
+
+ pragma Assert (Is_Expr_Pool_Empty);
+
+ if not Is_Error (Syn_Inst) then
+ Synth_Attribute_Values (Syn_Inst, Arch);
+ end if;
+
+ pragma Assert (Is_Expr_Pool_Empty);
+
+ -- Vunits
+ if not Is_Error (Syn_Inst) then
+ Synth_Verification_Units (Syn_Inst);
+ end if;
+
+ pragma Assert (Is_Expr_Pool_Empty);
+
+ -- Finalize
+ Finalize_Declarations (Syn_Inst, Get_Declaration_Chain (Arch));
+ Finalize_Declarations (Syn_Inst, Get_Declaration_Chain (Entity));
+ Finalize_Declarations (Syn_Inst, Get_Port_Chain (Entity));
+ end Synth_Instance_Design;
+
procedure Synth_Instance (Inst : Inst_Object)
is
Entity : constant Node := Inst.Decl;
@@ -1586,53 +1767,7 @@ package body Synth.Vhdl_Insts is
-- FIXME: what about inner block configuration ?
pragma Assert (Get_Kind (Inst.Config) = Iir_Kind_Block_Configuration);
- -- Entity
- Synth_Concurrent_Declarations (Syn_Inst, Get_Declaration_Chain (Entity));
- if not Is_Error (Syn_Inst) then
- Synth_Concurrent_Statements
- (Syn_Inst, Get_Concurrent_Statement_Chain (Entity));
- end if;
-
- pragma Assert (Is_Expr_Pool_Empty);
-
- if not Is_Error (Syn_Inst) then
- Synth_Attribute_Values (Syn_Inst, Entity);
- end if;
-
- pragma Assert (Is_Expr_Pool_Empty);
-
- -- Architecture
- if not Is_Error (Syn_Inst) then
- Synth_Concurrent_Declarations
- (Syn_Inst, Get_Declaration_Chain (Arch));
- end if;
-
- pragma Assert (Is_Expr_Pool_Empty);
-
- if not Is_Error (Syn_Inst) then
- Synth_Concurrent_Statements
- (Syn_Inst, Get_Concurrent_Statement_Chain (Arch));
- end if;
-
- pragma Assert (Is_Expr_Pool_Empty);
-
- if not Is_Error (Syn_Inst) then
- Synth_Attribute_Values (Syn_Inst, Arch);
- end if;
-
- pragma Assert (Is_Expr_Pool_Empty);
-
- -- Vunits
- if not Is_Error (Syn_Inst) then
- Synth_Verification_Units (Syn_Inst);
- end if;
-
- pragma Assert (Is_Expr_Pool_Empty);
-
- -- Finalize
- Finalize_Declarations (Syn_Inst, Get_Declaration_Chain (Arch));
- Finalize_Declarations (Syn_Inst, Get_Declaration_Chain (Entity));
- Finalize_Declarations (Syn_Inst, Get_Port_Chain (Entity));
+ Synth_Instance_Design (Syn_Inst, Entity, Arch);
Finalize_Wires;
diff --git a/src/synth/synth-vhdl_oper.adb b/src/synth/synth-vhdl_oper.adb
index d9f1c694e..64d2deae3 100644
--- a/src/synth/synth-vhdl_oper.adb
+++ b/src/synth/synth-vhdl_oper.adb
@@ -2039,7 +2039,8 @@ package body Synth.Vhdl_Oper is
return Synth_Resize (Ctxt, L, B.Len, False, Expr);
end;
when Iir_Predefined_Ieee_Numeric_Std_Tosgn_Int_Nat_Sgn
- | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Vector_Int =>
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Vector_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Signed_Int =>
return Synth_Conv_Vector (True);
when Iir_Predefined_Ieee_Numeric_Std_Toint_Uns_Nat
| Iir_Predefined_Ieee_Numeric_Std_Unsigned_To_Integer_Slv_Nat
@@ -2060,7 +2061,10 @@ package body Synth.Vhdl_Oper is
| Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Vector_Uns
| Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Unsigned_Uns
| Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Unsigned_Log
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Signed_Log
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Signed_Uns
| Iir_Predefined_Ieee_Std_Logic_Arith_Ext =>
+ -- Unsigned to unsigned (resize)
declare
W : Width;
begin
@@ -2090,6 +2094,7 @@ package body Synth.Vhdl_Oper is
when Iir_Predefined_Ieee_Numeric_Std_Resize_Sgn_Nat
| Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Vector_Sgn
| Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Unsigned_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Signed_Sgn
| Iir_Predefined_Ieee_Std_Logic_Arith_Sxt =>
if not Is_Static (R.Val) then
Error_Msg_Synth
diff --git a/src/synth/synth-vhdl_stmts.adb b/src/synth/synth-vhdl_stmts.adb
index 6a6285a96..6fb438356 100644
--- a/src/synth/synth-vhdl_stmts.adb
+++ b/src/synth/synth-vhdl_stmts.adb
@@ -990,10 +990,11 @@ package body Synth.Vhdl_Stmts is
Mark_Expr_Pool (Marker);
Targ := Synth_Target (Inst, Get_Target (Stmt));
Targ_Type := Targ.Targ_Type;
+
First := No_Valtyp;
Last := No_Net;
Ce := Get_Conditional_Expression_Chain (Stmt);
- while Ce /= Null_Node loop
+ loop
-- First, evaluate the condition.
Cond := Get_Condition (Ce);
if Cond /= Null_Node then
@@ -1050,8 +1051,21 @@ package body Synth.Vhdl_Stmts is
exit when Cond_Tri = True;
Ce := Get_Chain (Ce);
+ exit when Ce = Null_Node;
end loop;
- Synth_Assignment (Inst, Targ, First, Stmt);
+
+ if Last /= No_Net then
+ if Cond_Tri /= True then
+ -- There is at least one Mux2, and its input-1 is not connected.
+ -- Implement missing assignment as a self-assignment.
+ Val := Synth_Read (Inst, Targ, Stmt);
+ Connect (Get_Input (Get_Net_Parent (Last), 1),
+ Get_Net (Ctxt, Val));
+ end if;
+
+ Synth_Assignment (Inst, Targ, First, Stmt);
+ end if;
+
Release_Expr_Pool (Marker);
end Synth_Conditional_Variable_Assignment;