aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth')
-rw-r--r--src/synth/netlists-cleanup.adb27
-rw-r--r--src/synth/netlists-cleanup.ads6
-rw-r--r--src/synth/netlists-disp_verilog.adb67
-rw-r--r--src/synth/netlists-expands.adb62
-rw-r--r--src/synth/netlists-memories.adb5
-rw-r--r--src/synth/synth-flags.ads4
-rw-r--r--src/synth/synth-vhdl_insts.adb7
-rw-r--r--src/synth/synthesis.adb4
8 files changed, 137 insertions, 45 deletions
diff --git a/src/synth/netlists-cleanup.adb b/src/synth/netlists-cleanup.adb
index c2fc603b4..52b3c87e0 100644
--- a/src/synth/netlists-cleanup.adb
+++ b/src/synth/netlists-cleanup.adb
@@ -385,4 +385,31 @@ package body Netlists.Cleanup is
end;
end Mark_And_Sweep;
+ procedure Replace_Null_Inputs (Ctxt : Context_Acc; M : Module)
+ is
+ Inst : Instance;
+ Drv : Net;
+ Inp : Input;
+ Null_X : Net;
+ begin
+ Null_X := No_Net;
+
+ Inst := Get_First_Instance (M);
+ while Inst /= No_Instance loop
+ for I in 1 .. Get_Nbr_Inputs (Inst) loop
+ Inp := Get_Input (Inst, I - 1);
+ Drv := Get_Driver (Inp);
+ if Drv /= No_Net and then Get_Width (Drv) = 0 then
+ if Null_X = No_Net then
+ Null_X := Build_Const_X (Ctxt, 0);
+ end if;
+ Disconnect (Inp);
+ Connect (Inp, Null_X);
+ end if;
+ end loop;
+
+ Inst := Get_Next_Instance (Inst);
+ end loop;
+ end Replace_Null_Inputs;
+
end Netlists.Cleanup;
diff --git a/src/synth/netlists-cleanup.ads b/src/synth/netlists-cleanup.ads
index be4f0e0fb..a13e66c47 100644
--- a/src/synth/netlists-cleanup.ads
+++ b/src/synth/netlists-cleanup.ads
@@ -16,6 +16,8 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <gnu.org/licenses>.
+with Netlists.Builders; use Netlists.Builders;
+
package Netlists.Cleanup is
-- Remove instances of module M whose outputs are not connected.
-- Their inputs will be deconnected, which can result in new instances
@@ -26,6 +28,10 @@ package Netlists.Cleanup is
-- sweep algorithm.
procedure Mark_And_Sweep (M : Module);
+ -- Reconnection inputs of width 0 (the null inputs) to an Const_X gate.
+ -- This will make all the null logic unconnected and ready to be cleaned.
+ procedure Replace_Null_Inputs (Ctxt : Context_Acc; M : Module);
+
-- Remove Id_Output gates.
procedure Remove_Output_Gates (M : Module);
end Netlists.Cleanup;
diff --git a/src/synth/netlists-disp_verilog.adb b/src/synth/netlists-disp_verilog.adb
index 848adc05b..cd13a6d77 100644
--- a/src/synth/netlists-disp_verilog.adb
+++ b/src/synth/netlists-disp_verilog.adb
@@ -31,6 +31,10 @@ package body Netlists.Disp_Verilog is
Flag_Merge_Lit : constant Boolean := True;
Flag_Merge_Edge : constant Boolean := True;
+ -- Wires/regs/parameters of size 0 are not possible in verilog.
+ -- Do not display them.
+ Flag_Null_Wires : constant Boolean := False;
+
procedure Put_Type (W : Width) is
begin
if W > 1 then
@@ -158,10 +162,12 @@ package body Netlists.Disp_Verilog is
is
Imod : constant Module := Get_Module (Inst);
Idx : Port_Idx;
+ Drv : Net;
Max_Idx : Port_Idx;
Name : Sname;
First : Boolean;
Param : Param_Desc;
+ Desc : Port_Desc;
begin
Put (" ");
@@ -217,33 +223,37 @@ package body Netlists.Disp_Verilog is
Idx := 0;
Max_Idx := Get_Nbr_Inputs (Imod);
for I of Inputs (Inst) loop
- if First then
- First := False;
- else
- Put_Line (",");
- end if;
- Put (" ");
- if Idx < Max_Idx then
- Put (".");
- Put_Interface_Name (Get_Input_Desc (Imod, Idx).Name);
- Put ("(");
- end if;
- Disp_Net_Name (Get_Driver (I));
- if Idx < Max_Idx then
- Put (")");
- Idx := Idx + 1;
+ Drv := Get_Driver (I);
+ if Flag_Null_Wires or else Get_Width (Drv) /= 0 then
+ if First then
+ First := False;
+ else
+ Put_Line (",");
+ end if;
+ Put (" ");
+ if Idx < Max_Idx then
+ Put (".");
+ Put_Interface_Name (Get_Input_Desc (Imod, Idx).Name);
+ Put ("(");
+ end if;
+ Disp_Net_Name (Get_Driver (I));
+ if Idx < Max_Idx then
+ Put (")");
+ end if;
end if;
+ Idx := Idx + 1;
end loop;
-- Outputs
Idx := 0;
for O of Outputs (Inst) loop
+ Desc := Get_Output_Desc (Imod, Idx);
if First then
First := False;
else
Put_Line (",");
end if;
Put (" .");
- Put_Interface_Name (Get_Output_Desc (Imod, Idx).Name);
+ Put_Interface_Name (Desc.Name);
Idx := Idx + 1;
Put ("(");
declare
@@ -434,9 +444,14 @@ package body Netlists.Disp_Verilog is
-- a name. In that case, a signal will be created and driven.
function Need_Signal (Inst : Instance) return Boolean
is
+ O : constant Net := Get_Output (Inst, 0);
I : Input;
begin
- I := Get_First_Sink (Get_Output (Inst, 0));
+ if not Flag_Null_Wires and then Get_Width (O) = 0 then
+ return False;
+ end if;
+
+ I := Get_First_Sink (O);
while I /= No_Input loop
if Need_Name (Get_Input_Parent (I)) then
return True;
@@ -1212,14 +1227,18 @@ package body Netlists.Disp_Verilog is
-- Output assignments.
declare
Idx : Port_Idx;
+ Desc : Port_Desc;
begin
Idx := 0;
for I of Inputs (Self_Inst) loop
- Put (" assign ");
- Put_Name (Get_Output_Desc (M, Idx).Name);
- Put (" = ");
- Disp_Net_Name (Get_Driver (I));
- Put_Line (";");
+ Desc := Get_Output_Desc (M, Idx);
+ if Desc.W /= 0 or Flag_Null_Wires then
+ Put (" assign ");
+ Put_Name (Desc.Name);
+ Put (" = ");
+ Disp_Net_Name (Get_Driver (I));
+ Put_Line (";");
+ end if;
Idx := Idx + 1;
end loop;
end;
@@ -1246,6 +1265,10 @@ package body Netlists.Disp_Verilog is
is
Attr : Attribute;
begin
+ if not (Desc.W /= 0 or Flag_Null_Wires) then
+ return;
+ end if;
+
if First then
Put (" (");
First := False;
diff --git a/src/synth/netlists-expands.adb b/src/synth/netlists-expands.adb
index efb9fc93f..0f69dd93d 100644
--- a/src/synth/netlists-expands.adb
+++ b/src/synth/netlists-expands.adb
@@ -46,6 +46,9 @@ package body Netlists.Expands is
N := Addr_Net;
Nbr_Els := 1;
P := Memidx_Arr'Last;
+ if P = 0 then
+ return;
+ end if;
loop
Ninst := Get_Net_Parent (N);
case Get_Id (Ninst) is
@@ -213,34 +216,47 @@ package body Netlists.Expands is
-- 2. compute number of cells.
Gather_Memidx (Addr_Net, Memidx_Arr, Nbr_Els);
- -- 2. build extract gates
- Els := new Case_Element_Array (1 .. Nbr_Els);
- declare
- Idx : Positive;
- Off : Uns32;
- Sel : Uns64;
- begin
- Idx := 1;
- Off := Get_Param_Uns32 (Inst, 0);
- Sel := 0;
- Fill_Els (Ctxt, Memidx_Arr, 1, Val, Els, Idx, Addr_Net, Off, W, Sel);
- end;
+ if Nbr_Els = 1 then
+ -- There is only one element, so it's not really dynamic.
+ -- Just return the value.
+ Res := Get_Input_Net (Inst, 0);
+ -- Disconnect the address
+ Addr := Disconnect_And_Get (Inst, 1);
+ if not Is_Connected (Addr) then
+ -- Should be a Const_X.
+ Remove_Instance (Get_Net_Parent (Addr));
+ end if;
+ else
+ -- 2. build extract gates
+ Els := new Case_Element_Array (1 .. Nbr_Els);
+ declare
+ Idx : Positive;
+ Off : Uns32;
+ Sel : Uns64;
+ begin
+ Idx := 1;
+ Off := Get_Param_Uns32 (Inst, 0);
+ Sel := 0;
+ Fill_Els (Ctxt, Memidx_Arr,
+ 1, Val, Els, Idx, Addr_Net, Off, W, Sel);
+ end;
- -- 3. build mux tree
- Disconnect (Get_Input (Inst, 1));
- Extract_Address (Ctxt, Addr_Net, Ndims, Addr);
- Truncate_Address (Ctxt, Addr, Nbr_Els);
- Def := No_Net;
- Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc);
+ -- 3. build mux tree
+ Disconnect (Get_Input (Inst, 1));
+ Extract_Address (Ctxt, Addr_Net, Ndims, Addr);
+ Truncate_Address (Ctxt, Addr, Nbr_Els);
+ Def := No_Net;
+ Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc);
+
+ -- 4. remove old dyn_extract.
+ Remove_Memidx (Memidx_Arr);
+
+ Free_Case_Element_Array (Els);
+ end if;
- -- 4. remove old dyn_extract.
Disconnect (Get_Input (Inst, 0));
Redirect_Inputs (Get_Output (Inst, 0), Res);
Remove_Instance (Inst);
-
- Remove_Memidx (Memidx_Arr);
-
- Free_Case_Element_Array (Els);
end Expand_Dyn_Extract;
procedure Generate_Decoder (Ctxt : Context_Acc;
diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb
index 2764ec380..ffc3316ba 100644
--- a/src/synth/netlists-memories.adb
+++ b/src/synth/netlists-memories.adb
@@ -243,6 +243,11 @@ package body Netlists.Memories is
end if;
Res := Res + 1;
N := Get_Input_Net (Inst, 0);
+ when Id_Const_X =>
+ -- For a null wire.
+ pragma Assert (Res = 0);
+ pragma Assert (Get_Width (N) = 0);
+ return 0;
when others =>
raise Internal_Error;
end case;
diff --git a/src/synth/synth-flags.ads b/src/synth/synth-flags.ads
index fed17efc1..211c01c1d 100644
--- a/src/synth/synth-flags.ads
+++ b/src/synth/synth-flags.ads
@@ -51,8 +51,12 @@ package Synth.Flags is
Flag_Debug_Nomemory2 : Boolean := False;
+ -- Do not expand dynamic gates.
Flag_Debug_Noexpand : Boolean := False;
+ -- Do not transform null net to null X.
+ Flag_Debug_Nonull : Boolean := False;
+
Flag_Trace_Statements : Boolean := False;
-- Display source of elaborated design.
diff --git a/src/synth/synth-vhdl_insts.adb b/src/synth/synth-vhdl_insts.adb
index 8d77b06b5..2d3f3360f 100644
--- a/src/synth/synth-vhdl_insts.adb
+++ b/src/synth/synth-vhdl_insts.adb
@@ -198,6 +198,13 @@ package body Synth.Vhdl_Insts is
T := T.Arr_El;
end loop;
end;
+ when Type_Record =>
+ for I in Typ.Rec.E'Range loop
+ Hash_Bounds (C, Typ.Rec.E (I).Typ);
+ end loop;
+ when Type_Bit
+ | Type_Logic =>
+ null;
when others =>
raise Internal_Error;
end case;
diff --git a/src/synth/synthesis.adb b/src/synth/synthesis.adb
index 310a30a59..911b2d5f6 100644
--- a/src/synth/synthesis.adb
+++ b/src/synth/synthesis.adb
@@ -79,6 +79,10 @@ package body Synthesis is
procedure Instance_Passes (Ctxt : Context_Acc; M : Module) is
begin
+ if not Synth.Flags.Flag_Debug_Nonull then
+ Netlists.Cleanup.Replace_Null_Inputs (Ctxt, M);
+ end if;
+
-- Remove unused gates. This is not only an optimization but also
-- a correctness point: there might be some unsynthesizable gates, like
-- the one created for 'rising_egde (clk) and not rst'.