From e1e293701bb457af7bffc2e18a890cf552599144 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Mon, 23 Mar 2020 06:48:46 +0100 Subject: synth: add id_inout gate to handle inout behaviour. Fir #1166 --- src/synth/netlists-builders.adb | 21 +++++++++++++++++++ src/synth/netlists-builders.ads | 2 ++ src/synth/netlists-disp_vhdl.adb | 13 ++++++++++++ src/synth/netlists-gates.ads | 12 +++++++++++ src/synth/synth-insts.adb | 44 ++++++++++++++++++++++++++++------------ 5 files changed, 79 insertions(+), 13 deletions(-) diff --git a/src/synth/netlists-builders.adb b/src/synth/netlists-builders.adb index 9280d619c..98647c193 100644 --- a/src/synth/netlists-builders.adb +++ b/src/synth/netlists-builders.adb @@ -420,6 +420,7 @@ package body Netlists.Builders is is Outputs : Port_Desc_Array (0 .. 0); Inputs2 : Port_Desc_Array (0 .. 1); + Outputs2 : Port_Desc_Array (0 .. 1); begin Inputs2 := (0 => Create_Input ("i"), 1 => Create_Input ("init")); @@ -456,6 +457,13 @@ package body Netlists.Builders is (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("nop"), No_Sname), Id_Nop, 1, 1, 0); Set_Ports_Desc (Ctxt.M_Nop, Inputs2 (0 .. 0), Outputs); + + Ctxt.M_Inout := New_User_Module + (Ctxt.Design, New_Sname_Artificial (Name_Inout, No_Sname), + Id_Inout, 1, 2, 0); + Outputs2 := (0 => Outputs (0), + 1 => Create_Output ("oport")); + Set_Ports_Desc (Ctxt.M_Inout, Inputs2 (0 .. 0), Outputs2); end Create_Objects_Module; procedure Create_Dff_Modules (Ctxt : Context_Acc) @@ -1254,6 +1262,19 @@ package body Netlists.Builders is return Build_Object (Ctxt, Ctxt.M_Output, W); end Build_Output; + function Build_Inout (Ctxt : Context_Acc; W : Width) return Instance + is + Inst : Instance; + O : Net; + begin + Inst := New_Internal_Instance (Ctxt, Ctxt.M_Inout); + O := Get_Output (Inst, 0); + Set_Width (O, W); + O := Get_Output (Inst, 1); + Set_Width (O, W); + return Inst; + end Build_Inout; + function Build_Ioutput (Ctxt : Context_Acc; Init : Net) return Net is Wd : constant Width := Get_Width (Init); diff --git a/src/synth/netlists-builders.ads b/src/synth/netlists-builders.ads index f686c6390..62c31502b 100644 --- a/src/synth/netlists-builders.ads +++ b/src/synth/netlists-builders.ads @@ -152,6 +152,7 @@ package Netlists.Builders is function Build_Output (Ctxt : Context_Acc; W : Width) return Net; function Build_Ioutput (Ctxt : Context_Acc; Init : Net) return Net; + function Build_Inout (Ctxt : Context_Acc; W : Width) return Instance; function Build_Signal (Ctxt : Context_Acc; Name : Sname; W : Width) return Net; function Build_Isignal (Ctxt : Context_Acc; Name : Sname; Init : Net) @@ -228,6 +229,7 @@ private M_Signal : Module; M_Isignal : Module; M_Port : Module; + M_Inout : Module; M_Dff : Module; M_Idff : Module; M_Adff : Module; diff --git a/src/synth/netlists-disp_vhdl.adb b/src/synth/netlists-disp_vhdl.adb index 99a87d2f4..a9086785c 100644 --- a/src/synth/netlists-disp_vhdl.adb +++ b/src/synth/netlists-disp_vhdl.adb @@ -757,6 +757,19 @@ package body Netlists.Disp_Vhdl is null; when Id_Output => Disp_Template (" \o0 <= \i0; -- (output)" & NL, Inst); + when Id_Inout => + -- Gates inout are special: output 1 must be connected to an + -- output (with the is_inout flag set) of the module. + Disp_Template (" \o1 <= \i0; -- (inout - port)" & NL, Inst); + Disp_Template (" \o0 <= ", Inst); + declare + Inp : constant Input := Get_First_Sink (Get_Output (Inst, 1)); + Iinst : constant Instance := Get_Input_Parent (Inp); + begin + Put_Name (Get_Output_Name (Get_Module (Iinst), + Get_Port_Idx (Inp))); + end; + Put ("; -- (inout - read)" & NL); when Id_Signal => Disp_Template (" \o0 <= \i0; -- (signal)" & NL, Inst); when Id_Isignal => diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads index 042091e3c..7ea18d4a0 100644 --- a/src/synth/netlists-gates.ads +++ b/src/synth/netlists-gates.ads @@ -119,6 +119,18 @@ package Netlists.Gates is Id_Output : constant Module_Id := 50; Id_Ioutput : constant Module_Id := 51; Id_Port : constant Module_Id := 52; + + -- Id_Inout is a virtual gate used to fit inout direction into the netlist + -- model which has only inputs and outputs. + -- It is virtual because it doesn't perform any computation. + -- Its output 1 must always be connected to an inout port of the module. + -- (more precisely: to an input port marked as inout of the self instance). + -- If input 0 is connected, it is a driver to the inout port. + -- The current value of the inout port can be read from output 0. + -- + -- Inputs: 0: value to be assigned to the port + -- Outputs: 0: value of the port + -- 1: direct and only connection to the port Id_Inout : constant Module_Id := 53; -- Note: initial values must be constant nets. diff --git a/src/synth/synth-insts.adb b/src/synth/synth-insts.adb index b33df7097..fae1a5a65 100644 --- a/src/synth/synth-insts.adb +++ b/src/synth/synth-insts.adb @@ -1309,31 +1309,49 @@ package body Synth.Insts is Val : Value_Acc) is Default : constant Node := Get_Default_Value (Inter); + Desc : constant Port_Desc := + Get_Output_Desc (Get_Module (Self_Inst), Idx); Inter_Typ : Type_Acc; Value : Net; Init : Value_Acc; Inp : Input; - W : Width; begin pragma Assert (Val.Kind = Value_Wire); -- Create a gate for the output, so that it could be read. Val.W := Alloc_Wire (Wire_Output, Inter); - W := Get_Output_Desc (Get_Module (Self_Inst), Idx).W; - pragma Assert (W = Get_Type_Width (Val.Typ)); - if Default /= Null_Node then - Inter_Typ := Get_Value_Type (Syn_Inst, Get_Type (Inter)); - Init := Synth_Expression_With_Type - (Syn_Inst, Default, Inter_Typ); - Init := Synth_Subtype_Conversion - (Init, Inter_Typ, False, Inter); - Value := Builders.Build_Ioutput (Build_Context, Get_Net (Init)); + pragma Assert (Desc.W = Get_Type_Width (Val.Typ)); + + Inp := Get_Input (Self_Inst, Idx); + + if Desc.Is_Inout then + if Default /= Null_Node then + -- TODO: initialized inout. + raise Internal_Error; + end if; + declare + Io_Inst : Instance; + begin + Io_Inst := Builders.Build_Inout (Build_Context, Desc.W); + -- Connect port1 of gate inout to the pin. + Connect (Inp, Get_Output (Io_Inst, 1)); + -- And port0 of the gate will be use to read from the pin. + Value := Get_Output (Io_Inst, 0); + end; else - Value := Builders.Build_Output (Build_Context, W); + if Default /= Null_Node then + Inter_Typ := Get_Value_Type (Syn_Inst, Get_Type (Inter)); + Init := Synth_Expression_With_Type + (Syn_Inst, Default, Inter_Typ); + Init := Synth_Subtype_Conversion + (Init, Inter_Typ, False, Inter); + Value := Builders.Build_Ioutput (Build_Context, Get_Net (Init)); + else + Value := Builders.Build_Output (Build_Context, Desc.W); + end if; + Connect (Inp, Value); end if; Set_Location (Value, Inter); - Inp := Get_Input (Self_Inst, Idx); - Connect (Inp, Value); Set_Wire_Gate (Val.W, Value); end Create_Output_Wire; -- cgit v1.2.3