aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-03-23 06:48:46 +0100
committerTristan Gingold <tgingold@free.fr>2020-03-23 06:48:46 +0100
commite1e293701bb457af7bffc2e18a890cf552599144 (patch)
tree7a0776b854dcac395b522da787441a95fe554534
parent0cd37c83c170b5292b5ec9800013da6b4f63c1c1 (diff)
downloadghdl-e1e293701bb457af7bffc2e18a890cf552599144.tar.gz
ghdl-e1e293701bb457af7bffc2e18a890cf552599144.tar.bz2
ghdl-e1e293701bb457af7bffc2e18a890cf552599144.zip
synth: add id_inout gate to handle inout behaviour. Fir #1166
-rw-r--r--src/synth/netlists-builders.adb21
-rw-r--r--src/synth/netlists-builders.ads2
-rw-r--r--src/synth/netlists-disp_vhdl.adb13
-rw-r--r--src/synth/netlists-gates.ads12
-rw-r--r--src/synth/synth-insts.adb44
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;